Skip to content

Commit

Permalink
table done
Browse files Browse the repository at this point in the history
  • Loading branch information
kayra1 committed Jul 29, 2024
1 parent abc9e56 commit de4ca33
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 16 deletions.
4 changes: 2 additions & 2 deletions ui/src/app/certificate_requests/row.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, Dispatch, SetStateAction, useEffect, useRef } from "react"
import { UseMutationResult, useMutation, useQueryClient } from "react-query"
import { extractCSR, extractCert } from "../utils"
import { RequiredParams, deleteCSR, rejectCSR, revokeCertificate } from "../queries"
import { RequiredCSRParams, deleteCSR, rejectCSR, revokeCertificate } from "../queries"
import { ConfirmationModal, SubmitCertificateModal, SuccessNotification } from "./components"
import "./../globals.scss"
import { useCookies } from "react-cookie"
Expand Down Expand Up @@ -43,7 +43,7 @@ export default function Row({ id, csr, certificate, ActionMenuExpanded, setActio
const revokeMutation = useMutation(revokeCertificate, {
onSuccess: () => queryClient.invalidateQueries('csrs')
})
const mutationFunc = (mutation: UseMutationResult<any, unknown, RequiredParams, unknown>, params: RequiredParams) => {
const mutationFunc = (mutation: UseMutationResult<any, unknown, RequiredCSRParams, unknown>, params: RequiredCSRParams) => {
mutation.mutate(params)
}

Expand Down
23 changes: 18 additions & 5 deletions ui/src/app/queries.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CSREntry, UserEntry } from "./types"
import { HTTPStatus } from "./utils"

export type RequiredParams = {
export type RequiredCSRParams = {
id: string
authToken: string
csr?: string
Expand Down Expand Up @@ -36,7 +36,7 @@ export async function postCSR(params: { authToken: string, csr: string }) {
return response.json()
}

export async function postCertToID(params: RequiredParams) {
export async function postCertToID(params: RequiredCSRParams) {
if (!params.cert) {
throw new Error('Certificate not provided')
}
Expand All @@ -54,7 +54,7 @@ export async function postCertToID(params: RequiredParams) {
return response.json()
}

export async function deleteCSR(params: RequiredParams) {
export async function deleteCSR(params: RequiredCSRParams) {
const response = await fetch("/api/v1/certificate_requests/" + params.id, {
method: 'delete',
headers: {
Expand All @@ -67,7 +67,7 @@ export async function deleteCSR(params: RequiredParams) {
return response.json()
}

export async function rejectCSR(params: RequiredParams) {
export async function rejectCSR(params: RequiredCSRParams) {
const response = await fetch("/api/v1/certificate_requests/" + params.id + "/certificate/reject", {
method: 'post',
headers: {
Expand All @@ -80,7 +80,7 @@ export async function rejectCSR(params: RequiredParams) {
return response.json()
}

export async function revokeCertificate(params: RequiredParams) {
export async function revokeCertificate(params: RequiredCSRParams) {
const response = await fetch("/api/v1/certificate_requests/" + params.id + "/certificate/reject", {
method: 'post',
headers: {
Expand Down Expand Up @@ -129,4 +129,17 @@ export async function getUsers(params: { authToken: string }): Promise<UserEntry
throw new Error(`${response.status}: ${HTTPStatus(response.status)}`)
}
return response.json()
}

export async function deleteUser(params: { authToken: string, id: string }) {
const response = await fetch("/api/v1/accounts/" + params.id, {
method: 'delete',
headers: {
'Authorization': "Bearer " + params.authToken
}
})
if (!response.ok) {
throw new Error(`${response.status}: ${HTTPStatus(response.status)}`)
}
return response.json()
}
32 changes: 32 additions & 0 deletions ui/src/app/users/components.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Dispatch, SetStateAction } from "react"

export type ConfirmationModalData = {
onMouseDownFunc: () => void
warningText: string
} | null

interface ConfirmationModalProps {
modalData: ConfirmationModalData
setModalData: Dispatch<SetStateAction<ConfirmationModalData>>
}

export function ConfirmationModal({ modalData, setModalData }: ConfirmationModalProps) {
const confirmQuery = () => {
modalData?.onMouseDownFunc()
setModalData(null)
}
return (
<div className="p-modal" id="modal">
<section className="p-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="modal-title" aria-describedby="modal-description">
<header className="p-modal__header">
<h2 className="p-modal__title" id="modal-title">Confirm Action</h2>
</header>
<p>{modalData?.warningText}</p>
<footer className="p-modal__footer">
<button className="u-no-margin--bottom" aria-controls="modal" onMouseDown={() => setModalData(null)}>Cancel</button>
<button className="p-button--negative u-no-margin--bottom" onMouseDown={confirmQuery}>Confirm</button>
</footer>
</section>
</div>
)
}
11 changes: 2 additions & 9 deletions ui/src/app/users/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { getUsers } from "../queries"
import { UserEntry } from "../types"
import { useCookies } from "react-cookie"
import { useRouter } from "next/navigation"
import { UsersTable } from "./table"

function Error({ msg }: { msg: string }) {
return (
Expand Down Expand Up @@ -59,13 +60,5 @@ export default function CertificateRequests() {
return <Error msg={query.error.message} />
}
const users = Array.from(query.data ? query.data : [])
return (
<>
{
users.map((user) => {
return <div key={user.id}>{user.username}</div>
})
}
</>
)
return <UsersTable users={users} />
}
47 changes: 47 additions & 0 deletions ui/src/app/users/row.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useState, Dispatch, SetStateAction, useEffect, useRef } from "react"
import { UseMutationResult, useMutation, useQueryClient } from "react-query"
import { RequiredCSRParams, deleteUser } from "../queries"
import { ConfirmationModalData, ConfirmationModal } from "./components"
import "./../globals.scss"
import { useAuth } from "../auth/authContext"

type rowProps = {
id: number,
username: string,
}

export default function Row({ id, username }: rowProps) {
const auth = useAuth()
const [confirmationModalData, setConfirmationModalData] = useState<ConfirmationModalData>(null)
const queryClient = useQueryClient()
const deleteMutation = useMutation(deleteUser, {
onSuccess: () => queryClient.invalidateQueries('users')
})
const mutationFunc = (mutation: UseMutationResult<any, unknown, RequiredCSRParams, unknown>, params: RequiredCSRParams) => {
mutation.mutate(params)
}

const handleDelete = () => {
setConfirmationModalData({
onMouseDownFunc: () => mutationFunc(deleteMutation, { id: id.toString(), authToken: auth.user ? auth.user.authToken : "" }),
warningText: "Deleting a user cannot be undone."
})
}

return (
<>
<tr>
<td className="" width={5} aria-label="id">{id}</td>
<td className="" aria-label="username">{username}</td>
<td className="" aria-label="delete-button">
{id == 1 ?
<button className="p-button--negative has-icon" onClick={handleDelete} disabled={true}><i className="p-icon--error"></i></button>
:
<button className="p-button--negative has-icon" onClick={handleDelete}><i className="p-icon--error"></i></button>
}
</td>
{confirmationModalData != null && <ConfirmationModal modalData={confirmationModalData} setModalData={setConfirmationModalData} />}
</tr>
</>
)
}
42 changes: 42 additions & 0 deletions ui/src/app/users/table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useContext, useState, Dispatch, SetStateAction } from "react"
import { AsideContext } from "../aside"
import { UserEntry } from "../types"
import Row from "./row"

type TableProps = {
users: UserEntry[]
}

export function UsersTable({ users: rows }: TableProps) {
const { isOpen: isAsideOpen, setIsOpen: setAsideIsOpen } = useContext(AsideContext)
return (
<div className="p-panel">
<div className="p-panel__header is-sticky">
<h4 className="p-panel__title">Users</h4>
<div className="p-panel__controls">
{rows.length > 0 && <button className="u-no-margin--bottom p-button--positive" aria-label="add-csr-button" onClick={() => setAsideIsOpen(true)}>Create New User</button>}
</div>
</div>
<div className="p-panel__content">
<div className="u-fixed-width">
<table id="csr-table" aria-label="Certificate Requests Table" className="p-table--expanding">
<thead>
<tr>
<th>ID</th>
<th>Username</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{
rows.map((row) => (
<Row key={row.id} id={row.id} username={row.username} />
)
)}
</tbody>
</table>
</div>
</div>
</div>
)
}

0 comments on commit de4ca33

Please sign in to comment.