From bd1a28e6c3f3fc5d50c3d5d67e83c9d436799c04 Mon Sep 17 00:00:00 2001 From: Chad Elliott Date: Mon, 27 Jan 2025 11:11:52 -0600 Subject: [PATCH] Moved all certification related resolve() calls into the api script and added the description field for new certifications. --- web-ui/src/api/certification.js | 45 +++++++++- .../certifications/Certifications.jsx | 84 ++++++++----------- .../EarnedCertificationsTable.jsx | 32 +++---- 3 files changed, 89 insertions(+), 72 deletions(-) diff --git a/web-ui/src/api/certification.js b/web-ui/src/api/certification.js index a8c9dafb5e..e62905f10d 100644 --- a/web-ui/src/api/certification.js +++ b/web-ui/src/api/certification.js @@ -5,7 +5,11 @@ const certificationUrl = '/services/certification'; export const getCertifications = async cookie => { return resolve({ url: certificationUrl, - headers: { 'X-CSRF-Header': cookie, Accept: 'application/json' } + headers: { + 'X-CSRF-Header': cookie, + Accept: 'application/json', + 'Content-Type': 'application/json;charset=UTF-8', + } }); }; @@ -15,3 +19,42 @@ export const getCertification = async (id, cookie) => { headers: { 'X-CSRF-Header': cookie, Accept: 'application/json' } }); }; + +export const createCertification = async (data, cookie) => { + return resolve({ + method: 'POST', + url: certificationUrl, + headers: { + 'X-CSRF-Header': cookie, + Accept: 'application/json', + 'Content-Type': 'application/json;charset=UTF-8' + }, + data: data, + }); +} + +export const updateCertification = async (id, data, cookie) => { + return resolve({ + method: 'PUT', + url: `${certificationUrl}/${id}`, + headers: { + 'X-CSRF-Header': cookie, + Accept: 'application/json', + 'Content-Type': 'application/json;charset=UTF-8' + }, + data: data, + }); +} + +export const mergeCertification = async (sourceId, targetId, cookie) => { + return resolve({ + method: 'POST', + url: `${certificationUrl}/merge`, + headers: { + 'X-CSRF-Header': cookie, + Accept: 'application/json', + 'Content-Type': 'application/json;charset=UTF-8' + }, + data: { sourceId, targetId }, + }); +} diff --git a/web-ui/src/components/certifications/Certifications.jsx b/web-ui/src/components/certifications/Certifications.jsx index eaebe1fc28..2cf5758a02 100644 --- a/web-ui/src/components/certifications/Certifications.jsx +++ b/web-ui/src/components/certifications/Certifications.jsx @@ -10,7 +10,12 @@ import { } from '@mui/material'; import Autocomplete from '@mui/material/Autocomplete'; -import { resolve } from '../../api/api.js'; +import { + getCertifications, + createCertification, + updateCertification, + mergeCertification, +} from '../../api/certification'; import { AppContext } from '../../context/AppContext'; import { selectCsrfToken } from '../../context/selectors'; import ConfirmationDialog from '../dialogs/ConfirmationDialog'; @@ -33,6 +38,7 @@ const Certifications = ({ forceUpdate = () => {}, open, onClose }) => { const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false); const [mergeDialogOpen, setMergeDialogOpen] = useState(false); const [name, setName] = useState(''); + const [description, setDescription] = useState(''); const [selectedCertification, setSelectedCertification] = useState(null); const [selectedTarget, setSelectedTarget] = useState(null); @@ -48,20 +54,13 @@ const Certifications = ({ forceUpdate = () => {}, open, onClose }) => { setAdding(true); setBadgeUrl(''); setName(''); + setDescription(''); setSelectedCertification(null); setSelectedTarget(null); }; const loadCertifications = useCallback(async () => { - const res = await resolve({ - method: 'GET', - url: certificationBaseUrl, - headers: { - 'X-CSRF-Header': csrf, - Accept: 'application/json', - 'Content-Type': 'application/json;charset=UTF-8' - } - }); + const res = await getCertifications(csrf); if (res.error) return; const certs = await res.payload.data; @@ -78,8 +77,11 @@ const Certifications = ({ forceUpdate = () => {}, open, onClose }) => { if (csrf) loadCertifications(); }, [csrf]); + // `exclude` is optional. If supplied, the certification name that matches + // will be removed from the list of options. This is useful when merging + // certifications. const certificationSelect = useCallback( - (label, setSelected) => ( + (label, setSelected, exclude) => ( {}, open, onClose }) => { } setAdding(!Boolean(foundCert)); setName(foundCert.name); + setDescription(foundCert.description); setBadgeUrl(foundCert.badgeUrl); setSelected(foundCert); }} - options={certifications.map(cert => cert.name)} + options={certifications.map(cert => cert.name).filter(name => name !== exclude)} renderInput={params => { return ( {}, open, onClose }) => { const deleteCertification = useCallback(async () => { selectedCertification.active = false; const { id } = selectedCertification; - const res = await resolve({ - method: 'PUT', - url: certificationBaseUrl + '/' + id, - headers: { - 'X-CSRF-Header': csrf, - Accept: 'application/json', - 'Content-Type': 'application/json;charset=UTF-8' - }, - data: selectedCertification - }); + const res = await updateCertification(id, selectedCertification, csrf); if (res.error) return; setCertificationMap(map => { @@ -141,19 +135,10 @@ const Certifications = ({ forceUpdate = () => {}, open, onClose }) => { close(); }, [certificationMap, certifications, selectedCertification]); - const mergeCertification = useCallback(async () => { + const mergeSelectedCertification = useCallback(async () => { const sourceId = selectedCertification.id; const targetId = selectedTarget.id; - const res = await resolve({ - method: 'POST', - url: certificationBaseUrl + '/merge', - headers: { - 'X-CSRF-Header': csrf, - Accept: 'application/json', - 'Content-Type': 'application/json;charset=UTF-8' - }, - data: { sourceId, targetId } - }); + const res = await mergeCertification(sourceId, targetId, csrf); if (res.error) return; setCertifications(certs => certs.filter(cert => cert.id !== sourceId)); @@ -166,19 +151,13 @@ const Certifications = ({ forceUpdate = () => {}, open, onClose }) => { }, [selectedCertification, selectedTarget]); const saveCertification = useCallback(async () => { - const url = adding - ? certificationBaseUrl - : certificationBaseUrl + '/' + selectedCertification.id; - const res = await resolve({ - method: adding ? 'POST' : 'PUT', - url, - headers: { - 'X-CSRF-Header': csrf, - Accept: 'application/json', - 'Content-Type': 'application/json;charset=UTF-8' - }, - data: { name, badgeUrl } - }); + let res; + const data = { name, description, badgeUrl }; + if (adding) { + res = await createCertification(data, csrf); + } else { + res = await updateCertification(selectedCertification.id, data, csrf); + } if (res.error) return; const newCert = res.payload.data; @@ -191,7 +170,7 @@ const Certifications = ({ forceUpdate = () => {}, open, onClose }) => { ); close(); forceUpdate(); - }, [badgeUrl, certificationMap, name, selectedCertification]); + }, [badgeUrl, certificationMap, name, description, selectedCertification]); return ( <> @@ -209,6 +188,12 @@ const Certifications = ({ forceUpdate = () => {}, open, onClose }) => { onChange={e => setName(e.target.value)} value={name} /> + setDescription(e.target.value)} + value={description} + /> {}, open, onClose }) => { Merge {selectedCertification?.name} Certification Into - {certificationSelect('Target Certification', setSelectedTarget)} + {certificationSelect('Target Certification', + setSelectedTarget, selectedCertification?.name)}
-