diff --git a/.github/workflows/gradle-build-feature.yml b/.github/workflows/gradle-build-feature.yml index 127ca38dc9..bdcb909e9b 100644 --- a/.github/workflows/gradle-build-feature.yml +++ b/.github/workflows/gradle-build-feature.yml @@ -8,6 +8,8 @@ on: - 'doc-**/*' - 'hotfix-**/*' - 'dependabot/**/*' +env: + HUSKY: 0 jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/gradle-build-native-feature.yml b/.github/workflows/gradle-build-native-feature.yml index 8f074129cb..464acf6882 100644 --- a/.github/workflows/gradle-build-native-feature.yml +++ b/.github/workflows/gradle-build-native-feature.yml @@ -8,6 +8,8 @@ on: - 'doc-**/*' - 'hotfix-**/*' - 'dependabot/**/*' +env: + HUSKY: 0 jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/gradle-build-production.yml b/.github/workflows/gradle-build-production.yml index e69a0babcb..096478d4bc 100644 --- a/.github/workflows/gradle-build-production.yml +++ b/.github/workflows/gradle-build-production.yml @@ -4,6 +4,7 @@ on: branches: - "master" env: + HUSKY: 0 PROJECT_ID: ${{ secrets.RUN_PROJECT }} RUN_REGION: us-central1 SERVICE_NAME: checkins-master diff --git a/.github/workflows/gradle-build-publish.yml b/.github/workflows/gradle-build-publish.yml index 9e8fed23d5..0f7cec56ef 100644 --- a/.github/workflows/gradle-build-publish.yml +++ b/.github/workflows/gradle-build-publish.yml @@ -2,6 +2,8 @@ name: Gradle Publish to GitHub Packages on: release: types: [created] +env: + HUSKY: 0 jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/gradle-dependency-submission.yml b/.github/workflows/gradle-dependency-submission.yml index 3aa1f9b734..959013aeaf 100644 --- a/.github/workflows/gradle-dependency-submission.yml +++ b/.github/workflows/gradle-dependency-submission.yml @@ -3,7 +3,8 @@ name: Gradle Dependency Submission on: push: branches: [ 'develop', 'master', 'feature-2532/graal' ] - +env: + HUSKY: 0 permissions: contents: write diff --git a/.github/workflows/gradle-deploy-develop.yml b/.github/workflows/gradle-deploy-develop.yml index a30f87d573..2d8679e81b 100644 --- a/.github/workflows/gradle-deploy-develop.yml +++ b/.github/workflows/gradle-deploy-develop.yml @@ -4,6 +4,7 @@ on: branches: - 'develop' env: + HUSKY: 0 PROJECT_ID: ${{ secrets.RUN_PROJECT }} RUN_REGION: us-central1 SERVICE_NAME: checkins-develop diff --git a/.github/workflows/gradle-deploy-native-develop.yml b/.github/workflows/gradle-deploy-native-develop.yml index 98105aaa74..5ef9eee305 100644 --- a/.github/workflows/gradle-deploy-native-develop.yml +++ b/.github/workflows/gradle-deploy-native-develop.yml @@ -4,6 +4,7 @@ on: branches: - 'develop' env: + HUSKY: 0 PROJECT_ID: ${{ secrets.RUN_PROJECT }} RUN_REGION: us-central1 SERVICE_NAME: checkins-develop-native diff --git a/.github/workflows/jekyll.yml b/.github/workflows/jekyll.yml index 300f52c479..a78e80609b 100644 --- a/.github/workflows/jekyll.yml +++ b/.github/workflows/jekyll.yml @@ -10,6 +10,8 @@ on: # Runs on pushes targeting the default branch push: branches: [develop] +env: + HUSKY: 0 # Allows you to run this workflow manually from the Actions tab workflow_dispatch: diff --git a/web-ui/.husky/pre-push b/web-ui/.husky/pre-push new file mode 100755 index 0000000000..a64ea70f31 --- /dev/null +++ b/web-ui/.husky/pre-push @@ -0,0 +1 @@ +./gradlew check diff --git a/web-ui/package.json b/web-ui/package.json index 559f2f6bab..f0d1fca48b 100644 --- a/web-ui/package.json +++ b/web-ui/package.json @@ -43,7 +43,6 @@ "react-jss": "^10.4.0", "react-modal": "^3.14.3", "react-router-dom": "^5.3.0", - "react-swipeable-views": "^0.14.0", "recharts": "^2.12.4", "reselect": "^4.0.0", "styled-components": "^6.1.8" @@ -58,7 +57,8 @@ "serve": "vite preview", "start": "vite", "test": "vitest", - "update-test": "vitest -u" + "update-test": "vitest -u", + "prepare": "cd .. && husky web-ui/.husky" }, "eslintConfig": { "extends": "react-app" @@ -76,31 +76,30 @@ ] }, "devDependencies": { - "@ladle/react": "^4.1.2", + "@ladle/react": "^5.0.1", + "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.2.0", "@testing-library/user-event": "^14.6.1", - "@testing-library/dom": "^10.4.0", - "@types/react-router-dom": "^5.3.0", - "@vitejs/plugin-react-swc": "^3.6.0", - "@vitest/coverage-v8": "^1.4.0", - "eslint": "^9.1.1", - "eslint-plugin-react": "^7.34.1", - "eslint-plugin-react-hooks": "^4.6.0", + "@types/react-router-dom": "^5.3.3", + "@vitejs/plugin-react-swc": "^3.8.0", + "@vitest/coverage-v8": "^3.0.8", + "eslint": "^9.22.0", + "eslint-plugin-react": "^7.37.4", + "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-vitest": "^0.5.4", - "globals": "^15.0.0", - "happy-dom": "^15.10.2", - "jest-fetch-mock": "^3.0.3", - "jsdom": "^24.0.0", - "msw": "^2.6.4", - "prettier": "3.2.5", + "globals": "^16.0.0", + "husky": "^9.1.7", + "jsdom": "^26.0.0", + "msw": "^2.7.3", + "prettier": "3.5.3", "prop-types": "^15.8.1", "react-test-renderer": "^18.3.1", - "typescript": "^5.4.5", - "typescript-eslint": "^7.7.1", - "vite": "^5.4.12", - "vite-tsconfig-paths": "^4.3.2", - "vitest": "^1.6.1", - "vitest-fetch-mock": "^0.2.2" + "typescript": "^5.8.2", + "typescript-eslint": "^8.26.1", + "vite": "^6.2.1", + "vite-tsconfig-paths": "^5.1.4", + "vitest": "^3.0.8", + "vitest-fetch-mock": "^0.4.5" } } diff --git a/web-ui/src/App.jsx b/web-ui/src/App.jsx index 870391c129..a22d3ed0cc 100644 --- a/web-ui/src/App.jsx +++ b/web-ui/src/App.jsx @@ -65,8 +65,9 @@ const theme = extendTheme({ components: { MuiButtonBase: { defaultProps: { - disableRipple: typeof process !== 'undefined' && !!process.env.VITEST_WORKER_ID, // No more ripple...only when testing. - }, + disableRipple: + typeof process !== 'undefined' && !!process.env.VITEST_WORKER_ID // No more ripple...only when testing. + } }, MuiCssBaseline: { styleOverrides: { diff --git a/web-ui/src/api/api.js b/web-ui/src/api/api.js index 8f5aabff06..63f9839f2e 100644 --- a/web-ui/src/api/api.js +++ b/web-ui/src/api/api.js @@ -61,7 +61,7 @@ export const getMyFetch = async () => { function windowLogin() { return new Promise((resolve, reject) => { const authUrl = `${BASE_API_URL}/login?close=true`; - const loginWindow = window.open(authUrl, "Login", "width=500,height=600"); + const loginWindow = window.open(authUrl, 'Login', 'width=500,height=600'); const interval = setInterval(() => { try { diff --git a/web-ui/src/api/certification.js b/web-ui/src/api/certification.js index e62905f10d..29376b726d 100644 --- a/web-ui/src/api/certification.js +++ b/web-ui/src/api/certification.js @@ -8,7 +8,7 @@ export const getCertifications = async cookie => { headers: { 'X-CSRF-Header': cookie, Accept: 'application/json', - 'Content-Type': 'application/json;charset=UTF-8', + 'Content-Type': 'application/json;charset=UTF-8' } }); }; @@ -29,9 +29,9 @@ export const createCertification = async (data, cookie) => { Accept: 'application/json', 'Content-Type': 'application/json;charset=UTF-8' }, - data: data, + data: data }); -} +}; export const updateCertification = async (id, data, cookie) => { return resolve({ @@ -42,9 +42,9 @@ export const updateCertification = async (id, data, cookie) => { Accept: 'application/json', 'Content-Type': 'application/json;charset=UTF-8' }, - data: data, + data: data }); -} +}; export const mergeCertification = async (sourceId, targetId, cookie) => { return resolve({ @@ -55,6 +55,6 @@ export const mergeCertification = async (sourceId, targetId, cookie) => { Accept: 'application/json', 'Content-Type': 'application/json;charset=UTF-8' }, - data: { sourceId, targetId }, + data: { sourceId, targetId } }); -} +}; diff --git a/web-ui/src/api/feedback.js b/web-ui/src/api/feedback.js index 856618502d..8815235557 100644 --- a/web-ui/src/api/feedback.js +++ b/web-ui/src/api/feedback.js @@ -22,14 +22,11 @@ export const findReviewRequestsByPeriodAndTeamMembers = async ( }); }; -export const findReviewRequestsByPeriod = async ( - period, - cookie -) => { +export const findReviewRequestsByPeriod = async (period, cookie) => { return resolve({ url: feedbackRequestURL, params: { - reviewPeriodId: period?.id, + reviewPeriodId: period?.id }, headers: { 'X-CSRF-Header': cookie, Accept: 'application/json' } }); diff --git a/web-ui/src/api/generic.js b/web-ui/src/api/generic.js index 23998c6403..4357d38312 100644 --- a/web-ui/src/api/generic.js +++ b/web-ui/src/api/generic.js @@ -18,7 +18,7 @@ export const downloadData = (url, cookie, params) => { params: params, headers: { 'X-CSRF-Header': cookie, - Accept: 'application/json', + Accept: 'application/json' }, url: url }); @@ -33,6 +33,6 @@ export const initiate = (url, cookie, params) => { 'Content-Type': 'application/json;charset=UTF-8' }, url: url, - data: params, + data: params }); }; diff --git a/web-ui/src/api/kudos.js b/web-ui/src/api/kudos.js index a9a9601232..5144450538 100644 --- a/web-ui/src/api/kudos.js +++ b/web-ui/src/api/kudos.js @@ -1,15 +1,15 @@ -import { resolve } from "./api.js"; +import { resolve } from './api.js'; -const kudosUrl = "/services/kudos"; +const kudosUrl = '/services/kudos'; export const createKudos = async (kudos, cookie) => { return resolve({ - method: "post", + method: 'post', url: kudosUrl, data: kudos, - responseType: "json", + responseType: 'json', headers: { - "X-CSRF-Header": cookie, + 'X-CSRF-Header': cookie, Accept: 'application/json', 'Content-Type': 'application/json;charset=UTF-8' } @@ -22,8 +22,8 @@ export const getReceivedKudos = async (memberId, cookie) => { params: { recipientId: memberId }, - responseType: "json", - headers: { "X-CSRF-Header": cookie, Accept: 'application/json' } + responseType: 'json', + headers: { 'X-CSRF-Header': cookie, Accept: 'application/json' } }); }; @@ -33,15 +33,15 @@ export const getSentKudos = async (memberId, cookie) => { params: { senderId: memberId }, - responseType: "json", - headers: { "X-CSRF-Header": cookie, Accept: 'application/json' } + responseType: 'json', + headers: { 'X-CSRF-Header': cookie, Accept: 'application/json' } }); }; -export const getRecentKudos = async (cookie) => { +export const getRecentKudos = async cookie => { return resolve({ url: `${kudosUrl}/recent`, - responseType: "json", + responseType: 'json', headers: { 'X-CSRF-Header': cookie, Accept: 'application/json' } }); }; @@ -52,42 +52,44 @@ export const getAllKudos = async (cookie, isPending) => { params: { isPending: isPending }, - responseType: "json", + responseType: 'json', headers: { 'X-CSRF-Header': cookie, Accept: 'application/json' } }); }; export const updateKudos = async (kudos, cookie) => { return resolve({ - method: "put", + method: 'put', url: kudosUrl, data: kudos, - responseType: "json", + responseType: 'json', headers: { - "X-CSRF-Header": cookie, + 'X-CSRF-Header': cookie, Accept: 'application/json', - 'Content-Type': 'application/json;charset=UTF-8'} + 'Content-Type': 'application/json;charset=UTF-8' + } }); }; export const approveKudos = async (kudos, cookie) => { return resolve({ - method: "put", + method: 'put', url: `${kudosUrl}/approve`, data: kudos, - responseType: "json", + responseType: 'json', headers: { - "X-CSRF-Header": cookie, + 'X-CSRF-Header': cookie, Accept: 'application/json', - 'Content-Type': 'application/json;charset=UTF-8'} + 'Content-Type': 'application/json;charset=UTF-8' + } }); }; export const deleteKudos = async (kudosId, cookie) => { return resolve({ - method: "delete", + method: 'delete', url: `${kudosUrl}/${kudosId}`, - responseType: "json", - headers: { "X-CSRF-Header": cookie, Accept: 'application/json' } + responseType: 'json', + headers: { 'X-CSRF-Header': cookie, Accept: 'application/json' } }); }; diff --git a/web-ui/src/api/settings.js b/web-ui/src/api/settings.js index ba46645b62..038a234130 100644 --- a/web-ui/src/api/settings.js +++ b/web-ui/src/api/settings.js @@ -23,7 +23,7 @@ export const putOption = async (option, cookie) => { Accept: 'application/json', 'Content-Type': 'application/json;charset=UTF-8' }, - data: option, + data: option }); }; @@ -36,6 +36,6 @@ export const postOption = async (option, cookie) => { Accept: 'application/json', 'Content-Type': 'application/json;charset=UTF-8' }, - data: option, + data: option }); }; diff --git a/web-ui/src/api/volunteer.js b/web-ui/src/api/volunteer.js index aedc924058..7b751fa225 100644 --- a/web-ui/src/api/volunteer.js +++ b/web-ui/src/api/volunteer.js @@ -4,18 +4,18 @@ const organizationBaseUrl = '/services/volunteer/organization'; // Create New Organization export const createNewOrganization = async (csrf, newOrganization) => { - const res = await resolve({ - method: 'POST', - url: organizationBaseUrl, - headers: { - 'X-CSRF-Header': csrf, - 'Content-Type': 'application/json', - }, - data: newOrganization, - }); - - return res; - }; + const res = await resolve({ + method: 'POST', + url: organizationBaseUrl, + headers: { + 'X-CSRF-Header': csrf, + 'Content-Type': 'application/json' + }, + data: newOrganization + }); + + return res; +}; // Save New Organization export const saveNewOrganization = async (csrf, newOrganization) => { @@ -46,4 +46,3 @@ export const saveNewEvent = async (csrf, newEvent) => { return res; }; - diff --git a/web-ui/src/components/admin/permissions/Permissions.jsx b/web-ui/src/components/admin/permissions/Permissions.jsx index f3af9e81a6..5f1f94a0b5 100644 --- a/web-ui/src/components/admin/permissions/Permissions.jsx +++ b/web-ui/src/components/admin/permissions/Permissions.jsx @@ -5,14 +5,16 @@ import MobileTable from './MobileTable'; import { AppContext } from '../../../context/AppContext'; import { selectHasPermissionAssignmentPermission, - noPermission, + noPermission } from '../../../context/selectors'; export default function Permissions() { const { state } = useContext(AppContext); const showDesktop = useMediaQuery('(min-width:650px)', { noSsr: true }); - return selectHasPermissionAssignmentPermission(state) ? - (
{showDesktop ? : }
) : - (

{noPermission}

); + return selectHasPermissionAssignmentPermission(state) ? ( +
{showDesktop ? : }
+ ) : ( +

{noPermission}

+ ); } diff --git a/web-ui/src/components/admin/roles/Roles.jsx b/web-ui/src/components/admin/roles/Roles.jsx index 1f3865581f..b9f6445b33 100644 --- a/web-ui/src/components/admin/roles/Roles.jsx +++ b/web-ui/src/components/admin/roles/Roles.jsx @@ -14,7 +14,11 @@ import { } from '../../../api/roles'; import { selectCanEditMemberRolesPermission, - noPermission, selectMemberRoles, selectCsrfToken, selectRoles, selectMemberProfiles, + noPermission, + selectMemberRoles, + selectCsrfToken, + selectRoles, + selectMemberProfiles } from '../../../context/selectors'; import RoleUserCards from './RoleUserCards'; diff --git a/web-ui/src/components/admin/roles/Roles.test.jsx b/web-ui/src/components/admin/roles/Roles.test.jsx index d36cab40e4..6a0db5627d 100644 --- a/web-ui/src/components/admin/roles/Roles.test.jsx +++ b/web-ui/src/components/admin/roles/Roles.test.jsx @@ -11,7 +11,7 @@ const initialState = { ], memberRoles: [ { memberRoleId: { roleId: 1, memberId: 1 } }, - { memberRoleId: { roleId: 2, memberId: 2 } }, + { memberRoleId: { roleId: 2, memberId: 2 } } ], roles: [ { id: 1, role: 'ADMIN', description: 'Administrator' }, @@ -22,8 +22,8 @@ const initialState = { name: 'Current User', role: ['MEMBER'], id: 1, - permissions: [{ permission: 'CAN_EDIT_MEMBER_ROLES' }], - }, + permissions: [{ permission: 'CAN_EDIT_MEMBER_ROLES' }] + } } }; @@ -36,7 +36,7 @@ const noPermState = { ], memberRoles: [ { memberRoleId: { roleId: 1, memberId: 1 } }, - { memberRoleId: { roleId: 2, memberId: 2 } }, + { memberRoleId: { roleId: 2, memberId: 2 } } ], roles: [ { id: 1, role: 'ADMIN', description: 'Administrator' }, @@ -47,8 +47,8 @@ const noPermState = { name: 'Current User', role: ['MEMBER'], id: 1, - permissions: [], - }, + permissions: [] + } } }; diff --git a/web-ui/src/components/admin/users/Users.jsx b/web-ui/src/components/admin/users/Users.jsx index f09251288d..614c775acc 100644 --- a/web-ui/src/components/admin/users/Users.jsx +++ b/web-ui/src/components/admin/users/Users.jsx @@ -8,10 +8,7 @@ import { styled } from '@mui/material/styles'; import AdminMemberCard from '../../member-directory/AdminMemberCard'; import MemberModal from '../../member-directory/MemberModal'; -import { - createMember, - reportSelectedMembersCsv -} from '../../../api/member'; +import { createMember, reportSelectedMembersCsv } from '../../../api/member'; import { AppContext } from '../../../context/AppContext'; import { UPDATE_MEMBER_PROFILES, UPDATE_TOAST } from '../../../context/actions'; import { @@ -19,7 +16,7 @@ import { selectNormalizedMembers, selectNormalizedMembersAdmin, selectHasCreateMembersPermission, - selectCanEditAllOrganizationMembers, + selectCanEditAllOrganizationMembers } from '../../../context/selectors'; import { useQueryParameters } from '../../../helpers/query-parameters'; @@ -109,7 +106,9 @@ const Users = () => { const downloadMembers = async () => { const res = await reportSelectedMembersCsv( - normalizedMembers.map((m) => m.id), csrf); + normalizedMembers.map(m => m.id), + csrf + ); if (res?.error) { dispatch({ type: UPDATE_TOAST, diff --git a/web-ui/src/components/certifications/Certifications.jsx b/web-ui/src/components/certifications/Certifications.jsx index 2cf5758a02..887a84a456 100644 --- a/web-ui/src/components/certifications/Certifications.jsx +++ b/web-ui/src/components/certifications/Certifications.jsx @@ -14,7 +14,7 @@ import { getCertifications, createCertification, updateCertification, - mergeCertification, + mergeCertification } from '../../api/certification'; import { AppContext } from '../../context/AppContext'; import { selectCsrfToken } from '../../context/selectors'; @@ -103,7 +103,9 @@ const Certifications = ({ forceUpdate = () => {}, open, onClose }) => { setBadgeUrl(foundCert.badgeUrl); setSelected(foundCert); }} - options={certifications.map(cert => cert.name).filter(name => name !== exclude)} + options={certifications + .map(cert => cert.name) + .filter(name => name !== exclude)} renderInput={params => { return ( {}, open, onClose }) => { Merge {selectedCertification?.name} Certification Into - {certificationSelect('Target Certification', - setSelectedTarget, selectedCertification?.name)} + {certificationSelect( + 'Target Certification', + setSelectedTarget, + selectedCertification?.name + )}
-
@@ -98,15 +94,11 @@ exports[`has no billable hours 1`] = ` 1850 - PTO Hours: - 0 - Billable Utilization: - (none) - - Overtime Worked: - - + - Overtime Worked: (none)

diff --git a/web-ui/src/components/dialogs/OrganizationDialog.jsx b/web-ui/src/components/dialogs/OrganizationDialog.jsx index b227144f28..f5e2403641 100644 --- a/web-ui/src/components/dialogs/OrganizationDialog.jsx +++ b/web-ui/src/components/dialogs/OrganizationDialog.jsx @@ -1,5 +1,12 @@ import React from 'react'; -import { Dialog, DialogTitle, DialogContent, DialogActions, Button, TextField } from '@mui/material'; +import { + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Button, + TextField +} from '@mui/material'; import PropTypes from 'prop-types'; const OrganizationDialog = ({ @@ -19,7 +26,9 @@ const OrganizationDialog = ({ fullWidth margin="dense" value={organization.name} - onChange={e => setOrganization({ ...organization, name: e.target.value })} + onChange={e => + setOrganization({ ...organization, name: e.target.value }) + } required /> setOrganization({ ...organization, description: e.target.value })} + onChange={e => + setOrganization({ ...organization, description: e.target.value }) + } required /> setOrganization({ ...organization, website: e.target.value })} + onChange={e => + setOrganization({ ...organization, website: e.target.value }) + } />
- + ); @@ -58,4 +76,4 @@ OrganizationDialog.propTypes = { setOrganization: PropTypes.func.isRequired }; -export default OrganizationDialog; \ No newline at end of file +export default OrganizationDialog; diff --git a/web-ui/src/components/earned-certifications/EarnedCertificationBadges.jsx b/web-ui/src/components/earned-certifications/EarnedCertificationBadges.jsx index 6c012ef9c0..aca5f2d796 100644 --- a/web-ui/src/components/earned-certifications/EarnedCertificationBadges.jsx +++ b/web-ui/src/components/earned-certifications/EarnedCertificationBadges.jsx @@ -1,19 +1,20 @@ import PropTypes from 'prop-types'; import React, { useCallback, useContext, useEffect, useState } from 'react'; -import {Card, CardContent, CardHeader, Chip, Tooltip} from '@mui/material'; +import { Card, CardContent, CardHeader, Chip, Tooltip } from '@mui/material'; import { resolve } from '../../api/api.js'; import { AppContext } from '../../context/AppContext'; import { selectCsrfToken } from '../../context/selectors'; import './EarnedCertificationBadges.css'; -import certifications from "../certifications/Certifications.jsx"; +import certifications from '../certifications/Certifications.jsx'; const earnedCertificationBaseUrl = '/services/earned-certification'; const propTypes = { - memberId: PropTypes.string, certifications: PropTypes.array, + memberId: PropTypes.string, + certifications: PropTypes.array }; const EarnedCertificationBadges = ({ memberId, certifications }) => { const [earnedCertifications, setEarnedCertifications] = useState([]); @@ -43,98 +44,110 @@ const EarnedCertificationBadges = ({ memberId, certifications }) => { if (earnedCertifications.length === 0 || !certifications) return null; return ( - - - - {earnedCertifications.map(earnedCert => { - // Find the corresponding certification using earnedCert.certificationId - const cert = certifications.find(c => c.id === earnedCert.certificationId); - // If no matching cert is found, skip rendering for that earnedCert - if (!cert) return null; - if (cert.badgeUrl && cert.badgeUrl.trim().length > 0) { - return ( - + + + {earnedCertifications.map(earnedCert => { + // Find the corresponding certification using earnedCert.certificationId + const cert = certifications.find( + c => c.id === earnedCert.certificationId + ); + // If no matching cert is found, skip rendering for that earnedCert + if (!cert) return null; + if (cert.badgeUrl && cert.badgeUrl.trim().length > 0) { + return ( + + {cert.name}
+ Issued on: {earnedCert.earnedDate}
+ Expires on: {earnedCert.expirationDate} + + } + > + {earnedCert.validationUrl ? ( + + {`${cert.name}, + + ) : ( + {`${cert.name}, + )} +
+ ); + } else { + return ( + <> + {earnedCert.validationUrl ? ( + + {cert.name}
- Issued on: {earnedCert.earnedDate}
+ Issued on: {earnedCert.earnedDate} +
Expires on: {earnedCert.expirationDate} } - > - {earnedCert.validationUrl ? ( -
- {`${cert.name}, - - ) : ( - {`${cert.name}, - )} -
- ); - } else { - return ( - <> - {earnedCert.validationUrl ? ( - - - {cert.name}
- Issued on: {earnedCert.earnedDate}
- Expires on: {earnedCert.expirationDate} - - } - /> -
- ) : ( - - {cert.name}
- Issued on: {earnedCert.earnedDate}
- Expires on: {earnedCert.expirationDate} - - } - /> - )} - - ); - } - })} -
-
+ /> + + ) : ( + + {cert.name}
+ Issued on: {earnedCert.earnedDate} +
+ Expires on: {earnedCert.expirationDate} + + } + /> + )} + + ); + } + })} + + ); - }; EarnedCertificationBadges.propTypes = propTypes; diff --git a/web-ui/src/components/feedback_recipient_card/FeedbackRecipientCard.jsx b/web-ui/src/components/feedback_recipient_card/FeedbackRecipientCard.jsx index a9d82acc25..37d5fa11f8 100644 --- a/web-ui/src/components/feedback_recipient_card/FeedbackRecipientCard.jsx +++ b/web-ui/src/components/feedback_recipient_card/FeedbackRecipientCard.jsx @@ -3,7 +3,14 @@ import { styled } from '@mui/material/styles'; import { AppContext } from '../../context/AppContext'; import { selectProfileMap } from '../../context/selectors'; import { getAvatarURL } from '../../api/api.js'; -import { Box, Card, CardHeader, CardContent, Container, Typography } from '@mui/material'; +import { + Box, + Card, + CardHeader, + CardContent, + Container, + Typography +} from '@mui/material'; import Avatar from '@mui/material/Avatar'; import PriorityHighIcon from '@mui/icons-material/PriorityHigh'; import { green } from '@mui/material/colors'; diff --git a/web-ui/src/components/feedback_request_card/feedback_request_subcard/FeedbackRequestSubcard.test.jsx b/web-ui/src/components/feedback_request_card/feedback_request_subcard/FeedbackRequestSubcard.test.jsx index 30a69dbdd7..30b409d72f 100644 --- a/web-ui/src/components/feedback_request_card/feedback_request_subcard/FeedbackRequestSubcard.test.jsx +++ b/web-ui/src/components/feedback_request_card/feedback_request_subcard/FeedbackRequestSubcard.test.jsx @@ -4,7 +4,7 @@ import { BrowserRouter } from 'react-router-dom'; import { AppContextProvider } from '../../../context/AppContext'; import FeedbackRequestSubcard from './FeedbackRequestSubcard'; -const defaultTheme = {} +const defaultTheme = {}; it('renders correctly', () => { snapshot( diff --git a/web-ui/src/components/feedback_request_confirmation/FeedbackRequestConfirmation.jsx b/web-ui/src/components/feedback_request_confirmation/FeedbackRequestConfirmation.jsx index 8d01337fc8..1ce337f9bc 100644 --- a/web-ui/src/components/feedback_request_confirmation/FeedbackRequestConfirmation.jsx +++ b/web-ui/src/components/feedback_request_confirmation/FeedbackRequestConfirmation.jsx @@ -5,7 +5,7 @@ import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import { selectProfile, selectHasCreateFeedbackPermission, - noPermission, + noPermission } from '../../context/selectors'; import { AppContext } from '../../context/AppContext'; import { Link, useLocation } from 'react-router-dom'; diff --git a/web-ui/src/components/feedback_request_confirmation/FeedbackRequestConfirmation.test.jsx b/web-ui/src/components/feedback_request_confirmation/FeedbackRequestConfirmation.test.jsx index cf598a2827..d1d4da49ac 100644 --- a/web-ui/src/components/feedback_request_confirmation/FeedbackRequestConfirmation.test.jsx +++ b/web-ui/src/components/feedback_request_confirmation/FeedbackRequestConfirmation.test.jsx @@ -8,7 +8,7 @@ const userStateWithPermission = { userProfile: { name: 'sherlock holmes', role: ['MEMBER'], - permissions: [{ permission: 'CAN_CREATE_FEEDBACK_REQUEST' }], + permissions: [{ permission: 'CAN_CREATE_FEEDBACK_REQUEST' }] } } }; @@ -18,7 +18,7 @@ const userStateWithoutPermission = { userProfile: { name: 'john watson', role: ['MEMBER'], - permissions: [{ permission: 'CAN_VIEW_SKILLS_REPORT' }], + permissions: [{ permission: 'CAN_VIEW_SKILLS_REPORT' }] } } }; diff --git a/web-ui/src/components/feedback_submission_tips/FeedbackSubmissionTips.jsx b/web-ui/src/components/feedback_submission_tips/FeedbackSubmissionTips.jsx index 7ea53d6edd..a3c2b8d067 100644 --- a/web-ui/src/components/feedback_submission_tips/FeedbackSubmissionTips.jsx +++ b/web-ui/src/components/feedback_submission_tips/FeedbackSubmissionTips.jsx @@ -86,7 +86,8 @@ const FeedbackSubmissionTips = props => { - SBI is a common approach to providing constructive and fair feedback{' '} + SBI is a common approach to providing constructive and fair + feedback{' '}
diff --git a/web-ui/src/components/feedback_submit_confirmation/FeedbackSubmitConfirmation.jsx b/web-ui/src/components/feedback_submit_confirmation/FeedbackSubmitConfirmation.jsx index 1d707f1371..8534094b6b 100644 --- a/web-ui/src/components/feedback_submit_confirmation/FeedbackSubmitConfirmation.jsx +++ b/web-ui/src/components/feedback_submit_confirmation/FeedbackSubmitConfirmation.jsx @@ -7,7 +7,7 @@ import { selectCurrentUser, selectProfile, selectHasCreateFeedbackPermission, - noPermission, + noPermission } from '../../context/selectors'; import { AppContext } from '../../context/AppContext'; import { useLocation } from 'react-router-dom'; diff --git a/web-ui/src/components/feedback_submit_confirmation/FeedbackSubmitConfirmation.test.jsx b/web-ui/src/components/feedback_submit_confirmation/FeedbackSubmitConfirmation.test.jsx index 83e35af751..39b9fb77e1 100644 --- a/web-ui/src/components/feedback_submit_confirmation/FeedbackSubmitConfirmation.test.jsx +++ b/web-ui/src/components/feedback_submit_confirmation/FeedbackSubmitConfirmation.test.jsx @@ -8,7 +8,7 @@ const userStateWithPermission = { userProfile: { name: 'john watson', role: ['MEMBER'], - permissions: [{ permission: 'CAN_CREATE_FEEDBACK_REQUEST' }], + permissions: [{ permission: 'CAN_CREATE_FEEDBACK_REQUEST' }] } } }; diff --git a/web-ui/src/components/feedback_submit_form/FeedbackSubmitForm.jsx b/web-ui/src/components/feedback_submit_form/FeedbackSubmitForm.jsx index 9ae46e2cc2..50e26e8b60 100644 --- a/web-ui/src/components/feedback_submit_form/FeedbackSubmitForm.jsx +++ b/web-ui/src/components/feedback_submit_form/FeedbackSubmitForm.jsx @@ -188,7 +188,11 @@ const FeedbackSubmitForm = ({ ) : ( - + {isReviewing ? 'Reviewing' : 'Submitting'} Feedback on{' '} {requesteeName} diff --git a/web-ui/src/components/feedback_template_selector/FeedbackTemplateSelector.jsx b/web-ui/src/components/feedback_template_selector/FeedbackTemplateSelector.jsx index 5a58e48c95..f3fc6b0bde 100644 --- a/web-ui/src/components/feedback_template_selector/FeedbackTemplateSelector.jsx +++ b/web-ui/src/components/feedback_template_selector/FeedbackTemplateSelector.jsx @@ -97,7 +97,7 @@ const FeedbackTemplateSelector = ({ query, changeQuery }) => { active: true, isAdHoc: true, isPublic: false, - isReview: false, + isReview: false }; const newTemplateQuestion = { diff --git a/web-ui/src/components/guides/GuideLink.test.jsx b/web-ui/src/components/guides/GuideLink.test.jsx index 12093b4d7e..8e247e70b8 100644 --- a/web-ui/src/components/guides/GuideLink.test.jsx +++ b/web-ui/src/components/guides/GuideLink.test.jsx @@ -13,7 +13,12 @@ it('renders correctly', () => { it('renders descriptions', () => { snapshot( - + ); -}); \ No newline at end of file +}); diff --git a/web-ui/src/components/guides/GuidesPanel.jsx b/web-ui/src/components/guides/GuidesPanel.jsx index 1951f55716..c196b687b8 100644 --- a/web-ui/src/components/guides/GuidesPanel.jsx +++ b/web-ui/src/components/guides/GuidesPanel.jsx @@ -3,7 +3,11 @@ import PdfIcon from '@mui/icons-material/PictureAsPdf'; import { Card, CardHeader, List } from '@mui/material'; import { AppContext } from '../../context/AppContext.jsx'; -import {selectCsrfToken, selectCurrentUserRoles, selectRoles} from '../../context/selectors.js'; +import { + selectCsrfToken, + selectCurrentUserRoles, + selectRoles +} from '../../context/selectors.js'; import { getDocumentsForRoleId } from '../../api/document.js'; import GuideLink from './GuideLink'; @@ -48,13 +52,14 @@ const GuidesPanel = () => { useEffect(() => { const getDocuments = async () => { const docs = []; - if(userRoles) { + if (userRoles) { for (const roleName of userRoles) { - const memberRoleId = allRoles.find(role => role.role === roleName)?.id; + const memberRoleId = allRoles.find( + role => role.role === roleName + )?.id; const res = await getDocumentsForRoleId(memberRoleId, csrf); - const responseBody = res.payload?.data && !res.error - ? res.payload.data - : undefined; + const responseBody = + res.payload?.data && !res.error ? res.payload.data : undefined; if (responseBody?.length > 0) { docs.push(...responseBody); } @@ -69,15 +74,21 @@ const GuidesPanel = () => { }, [allRoles, userRoles, csrf, setDocuments, getDocumentsForRoleId]); return ( - - } title={"Check-In Resources"} /> - - {documents.map(doc => ( - - ))} - - - );; + + } title={'Check-In Resources'} /> + + {documents.map(doc => ( + + ))} + + + ); }; export default GuidesPanel; diff --git a/web-ui/src/components/guides/GuidesPanel.test.jsx b/web-ui/src/components/guides/GuidesPanel.test.jsx index 5c4760b87d..35a3c243af 100644 --- a/web-ui/src/components/guides/GuidesPanel.test.jsx +++ b/web-ui/src/components/guides/GuidesPanel.test.jsx @@ -2,8 +2,8 @@ import React from 'react'; import { MemoryRouter } from 'react-router-dom'; import GuidesPanel from './GuidesPanel'; import { AppContextProvider } from '../../context/AppContext.jsx'; -import {setupServer} from "msw/node"; -import {http, HttpResponse} from "msw"; +import { setupServer } from 'msw/node'; +import { http, HttpResponse } from 'msw'; const initialState = { state: { @@ -47,12 +47,12 @@ const pdlMockuments = [ ]; const server = setupServer( - http.get('http://localhost:8080/services/document/1', () => { - return HttpResponse.json(mockuments); - }), - http.get('http://localhost:8080/services/document/2', () => { - return HttpResponse.json(pdlMockuments); - }) + http.get('http://localhost:8080/services/document/1', () => { + return HttpResponse.json(mockuments); + }), + http.get('http://localhost:8080/services/document/2', () => { + return HttpResponse.json(pdlMockuments); + }) ); beforeAll(() => server.listen({ onUnhandledRequest(request, print) {} })); @@ -60,7 +60,8 @@ afterEach(() => server.resetHandlers()); afterAll(() => server.close()); it('renders correctly', async () => { - await waitForSnapshot('mockument-3', + await waitForSnapshot( + 'mockument-3', diff --git a/web-ui/src/components/guild-results/EditGuildModal.jsx b/web-ui/src/components/guild-results/EditGuildModal.jsx index 953c5ccfb1..019cdfabbc 100644 --- a/web-ui/src/components/guild-results/EditGuildModal.jsx +++ b/web-ui/src/components/guild-results/EditGuildModal.jsx @@ -12,7 +12,7 @@ import { Modal, Switch, TextField, - Checkbox, + Checkbox } from '@mui/material'; import Autocomplete from '@mui/material/Autocomplete'; import './EditGuildModal.css'; @@ -167,19 +167,22 @@ const EditGuildModal = ({ guild = {}, open, onSave, onClose, headerText }) => { value={editedGuild.name ? editedGuild.name : ''} onChange={e => setGuild({ ...editedGuild, name: e.target.value })} /> - {guild.id && (<> - { - const { checked } = event.target; - setGuild({ ...editedGuild, active: checked }); - }} - /> Active - )} + {guild.id && ( + <> + { + const { checked } = event.target; + setGuild({ ...editedGuild, active: checked }); + }} + />{' '} + Active + + )}
({ })); const inactiveStyle = { - 'color': 'var(--action-disabled)', - 'fontSize': '0.75em', + color: 'var(--action-disabled)', + fontSize: '0.75em' }; const propTypes = { @@ -147,9 +147,8 @@ const GuildSummaryCard = ({ guild, index, isOpen, onGuildSelect }) => { /> {!guild.active && ( - Inactive diff --git a/web-ui/src/components/guild-results/GuildSummaryCard.test.jsx b/web-ui/src/components/guild-results/GuildSummaryCard.test.jsx index c6f534b6d5..dba9b29921 100644 --- a/web-ui/src/components/guild-results/GuildSummaryCard.test.jsx +++ b/web-ui/src/components/guild-results/GuildSummaryCard.test.jsx @@ -20,7 +20,7 @@ const guilds = [ lead: true } ], - active: true, + active: true } ]; @@ -34,12 +34,14 @@ const initialState = { 'https://upload.wikimedia.org/wikipedia/commons/7/74/SNL_MrBill_Doll.jpg' }, guilds, - memberProfiles: [{ - id: '3fa4-5717-4562-b3fc-2c963f66afa9', - pdlId: '', - title: 'Tester', - workEmail: 'test@tester.com' - }] + memberProfiles: [ + { + id: '3fa4-5717-4562-b3fc-2c963f66afa9', + pdlId: '', + title: 'Tester', + workEmail: 'test@tester.com' + } + ] } }; @@ -72,7 +74,7 @@ it('renders correctly for guild lead', () => { snapshot( - + ); diff --git a/web-ui/src/components/kudos/PublicKudos.css b/web-ui/src/components/kudos/PublicKudos.css index 2959c0fda8..96dad62128 100644 --- a/web-ui/src/components/kudos/PublicKudos.css +++ b/web-ui/src/components/kudos/PublicKudos.css @@ -4,6 +4,3 @@ align-items: center; gap: 1rem; } - - - diff --git a/web-ui/src/components/kudos/PublicKudos.jsx b/web-ui/src/components/kudos/PublicKudos.jsx index dbc3fa5cd2..324d4e6129 100644 --- a/web-ui/src/components/kudos/PublicKudos.jsx +++ b/web-ui/src/components/kudos/PublicKudos.jsx @@ -4,7 +4,7 @@ import { UPDATE_TOAST } from '../../context/actions'; import { AppContext } from '../../context/AppContext'; import { selectCsrfToken, - selectHasCreateKudosPermission, + selectHasCreateKudosPermission } from '../../context/selectors'; import { sortKudos } from '../../context/util'; @@ -48,13 +48,15 @@ const PublicKudos = () => {

Kudos

- {selectHasCreateKudosPermission(state) && } + {selectHasCreateKudosPermission(state) && ( + + )}
{
) : !kudosLoading && kudos?.length > 0 ? (
- {kudos.map(k => ())} + {kudos.map(k => ( + + ))}
) : ( diff --git a/web-ui/src/components/kudos/PublicKudosCard.css b/web-ui/src/components/kudos/PublicKudosCard.css index 2851ea69b5..9fb9727c61 100644 --- a/web-ui/src/components/kudos/PublicKudosCard.css +++ b/web-ui/src/components/kudos/PublicKudosCard.css @@ -1,3 +1,3 @@ .kudos-card { min-width: 450px; -} \ No newline at end of file +} diff --git a/web-ui/src/components/kudos/PublicKudosCard.jsx b/web-ui/src/components/kudos/PublicKudosCard.jsx index 8a27875432..f7949e8115 100644 --- a/web-ui/src/components/kudos/PublicKudosCard.jsx +++ b/web-ui/src/components/kudos/PublicKudosCard.jsx @@ -1,5 +1,5 @@ -import React, { useCallback, useContext, useState } from "react"; -import PropTypes from "prop-types"; +import React, { useCallback, useContext, useState } from 'react'; +import PropTypes from 'prop-types'; import { Card, CardHeader, @@ -17,23 +17,23 @@ import { DialogContentText, DialogActions, TextField, - Link, -} from "@mui/material"; + Link +} from '@mui/material'; import { selectCsrfToken, - selectActiveOrInactiveProfile, -} from "../../context/selectors"; -import { AppContext } from "../../context/AppContext"; -import { getAvatarURL } from "../../api/api"; -import DateFnsUtils from "@date-io/date-fns"; -import CheckIcon from "@mui/icons-material/Check"; -import CloseIcon from "@mui/icons-material/Close"; -import TeamIcon from "@mui/icons-material/Groups"; + selectActiveOrInactiveProfile +} from '../../context/selectors'; +import { AppContext } from '../../context/AppContext'; +import { getAvatarURL } from '../../api/api'; +import DateFnsUtils from '@date-io/date-fns'; +import CheckIcon from '@mui/icons-material/Check'; +import CloseIcon from '@mui/icons-material/Close'; +import TeamIcon from '@mui/icons-material/Groups'; -import { approveKudos, deleteKudos } from "../../api/kudos"; -import { UPDATE_TOAST } from "../../context/actions"; +import { approveKudos, deleteKudos } from '../../api/kudos'; +import { UPDATE_TOAST } from '../../context/actions'; -import "./PublicKudosCard.css"; +import './PublicKudosCard.css'; const dateUtils = new DateFnsUtils(); @@ -45,8 +45,8 @@ const propTypes = { recipientTeam: PropTypes.object, dateCreated: PropTypes.array.isRequired, dateApproved: PropTypes.array, - recipientMembers: PropTypes.array, - }).isRequired, + recipientMembers: PropTypes.array + }).isRequired }; const KudosCard = ({ kudos }) => { @@ -64,20 +64,24 @@ const KudosCard = ({ kudos }) => { const components = []; let index = 0; do { - index = regexIndexOf(message, - new RegExp('\\b' + name + '\\b', 'i'), index); + index = regexIndexOf( + message, + new RegExp('\\b' + name + '\\b', 'i'), + index + ); if (index != -1) { - const link = - {name} - ; + const link = ( + + {name} + + ); if (index > 0) { components.push(message.slice(0, index)); } components.push(link); message = message.slice(index + name.length); } - } while(index != -1); + } while (index != -1); components.push(message); return components; }; @@ -88,20 +92,31 @@ const KudosCard = ({ kudos }) => { names.push(`${member.firstName} ${member.middleName} ${member.lastName}`); } const firstAndLast = `${member.firstName} ${member.lastName}`; - if (!members.some((k) => k.id != member.id && - firstAndLast == `${k.firstName} ${k.lastName}`)) { + if ( + !members.some( + k => k.id != member.id && firstAndLast == `${k.firstName} ${k.lastName}` + ) + ) { names.push(firstAndLast); } - if (!members.some((k) => k.id != member.id && - (member.lastName == k.lastName || - member.lastName == k.firstName))) { + if ( + !members.some( + k => + k.id != member.id && + (member.lastName == k.lastName || member.lastName == k.firstName) + ) + ) { // If there are no other recipients with a name that contains this // member's last name, we can replace based on that. names.push(member.lastName); } - if (!members.some((k) => k.id != member.id && - (member.firstName == k.lastName || - member.firstName == k.firstName))) { + if ( + !members.some( + k => + k.id != member.id && + (member.firstName == k.lastName || member.firstName == k.firstName) + ) + ) { // If there are no other recipients with a name that contains this // member's first name, we can replace based on that. names.push(member.firstName); @@ -109,17 +124,17 @@ const KudosCard = ({ kudos }) => { return names; }; - const linkNames = (kudos) => { + const linkNames = kudos => { const lines = []; let index = 0; for (let line of kudos.message.split('\n')) { - const components = [ line ]; + const components = [line]; for (let member of kudos.recipientMembers) { const names = searchNames(member, kudos.recipientMembers); for (let name of names) { for (let i = 0; i < components.length; i++) { const component = components[i]; - if (typeof(component) === "string") { + if (typeof component === 'string') { const built = linkMember(member, name, component); if (built.length > 1) { components.splice(i, 1, ...built); @@ -129,8 +144,8 @@ const KudosCard = ({ kudos }) => { } } lines.push( - - {components} + + {components} ); index++; @@ -139,15 +154,17 @@ const KudosCard = ({ kudos }) => { }; const multiTooltip = (num, list) => { - let tooltip = ""; - let prefix = ""; + let tooltip = ''; + let prefix = ''; for (let member of list.slice(-num)) { tooltip += prefix + `${member.firstName} ${member.lastName}`; - prefix = ", "; + prefix = ', '; } - return - {`+${num}`} - ; + return ( + + {`+${num}`} + + ); }; const getRecipientComponent = useCallback(() => { @@ -166,10 +183,11 @@ const KudosCard = ({ kudos }) => { } return ( - multiTooltip( - extra, kudos.recipientMembers)}> - {kudos.recipientMembers.map((member) => ( + multiTooltip(extra, kudos.recipientMembers)} + > + {kudos.recipientMembers.map(member => ( { ); }, [kudos]); - let titleText = kudos?.recipientTeam?.name ? "Kudos, " + kudos?.recipientTeam?.name + "!" : "Kudos!"; - if(kudos?.recipientMembers?.length === 1 && kudos?.recipientMembers[0]?.firstName) titleText = "Kudos, " + kudos?.recipientMembers[0]?.firstName + "!"; + let titleText = kudos?.recipientTeam?.name + ? 'Kudos, ' + kudos?.recipientTeam?.name + '!' + : 'Kudos!'; + if ( + kudos?.recipientMembers?.length === 1 && + kudos?.recipientMembers[0]?.firstName + ) + titleText = 'Kudos, ' + kudos?.recipientMembers[0]?.firstName + '!'; return ( - - from } - label={sender?.name} - />)} - subheaderTypographyProps={{variant:"subtitle1"}} - /> - + + - {linkNames(kudos)} + from{' '} + } + label={sender?.name} + /> - {kudos.recipientTeam && ( - multiTooltip( - extra, kudos.recipientMembers)}> - {kudos.recipientMembers.map((member) => ( - + + <>{linkNames(kudos)} + {kudos.recipientTeam && ( + multiTooltip(extra, kudos.recipientMembers)} > - - - ))} - - )} - - + {kudos.recipientMembers.map(member => ( + + + + ))} + + )} +
+ ); }; diff --git a/web-ui/src/components/kudos/PublicKudosCard.test.jsx b/web-ui/src/components/kudos/PublicKudosCard.test.jsx index 24215cf0c1..ffff1379ce 100644 --- a/web-ui/src/components/kudos/PublicKudosCard.test.jsx +++ b/web-ui/src/components/kudos/PublicKudosCard.test.jsx @@ -7,111 +7,110 @@ const initialState = { csrf: 'O_3eLX2-e05qpS_yOeg1ZVAs9nDhspEi', teams: [], userProfile: { - id: "1", + id: '1', firstName: 'Jimmy', lastName: 'Johnson', - role: ['MEMBER'], + role: ['MEMBER'] }, memberProfiles: [ { - id: "1", + id: '1', firstName: 'Jimmy', lastName: 'Johnson', - role: ['MEMBER'], + role: ['MEMBER'] }, { - id: "2", + id: '2', firstName: 'Jimmy', lastName: 'Olsen', - role: ['MEMBER'], + role: ['MEMBER'] }, { - id: "3", + id: '3', firstName: 'Clark', lastName: 'Kent', - role: ['MEMBER'], + role: ['MEMBER'] }, { - id: "4", + id: '4', firstName: 'Kent', lastName: 'Brockman', - role: ['MEMBER'], + role: ['MEMBER'] }, { - id: "5", + id: '5', firstName: 'Jerry', lastName: 'Garcia', - role: ['MEMBER'], + role: ['MEMBER'] }, { - id: "6", + id: '6', firstName: 'Brock', lastName: 'Smith', - role: ['MEMBER'], + role: ['MEMBER'] }, { - id: "7", + id: '7', firstName: 'Jimmy', middleName: 'T.', lastName: 'Olsen', - role: ['MEMBER'], - }, - ], + role: ['MEMBER'] + } + ] } }; const kudos = { id: 'test-kudos', - message: "Brock and Brockman did a great job helping Clark, Jimmy Olsen, Jimmy T. Olsen, and Johnson", - senderId: "5", - dateCreated: [ 2025, 2, 14 ], + message: + 'Brock and Brockman did a great job helping Clark, Jimmy Olsen, Jimmy T. Olsen, and Johnson', + senderId: '5', + dateCreated: [2025, 2, 14], recipientMembers: [ - { - id: "1", - firstName: 'Jimmy', - lastName: 'Johnson', - role: ['MEMBER'], - }, - { - id: "2", - firstName: 'Jimmy', - lastName: 'Olsen', - role: ['MEMBER'], - }, - { - id: "3", - firstName: 'Clark', - lastName: 'Kent', - role: ['MEMBER'], - }, - { - id: "6", - firstName: 'Brock', - lastName: 'Smith', - role: ['MEMBER'], - }, - { - id: "4", - firstName: 'Kent', - lastName: 'Brockman', - role: ['MEMBER'], - }, - { - id: "7", - firstName: 'Jimmy', - middleName: 'T.', - lastName: 'Olsen', - role: ['MEMBER'], - }, - ], + { + id: '1', + firstName: 'Jimmy', + lastName: 'Johnson', + role: ['MEMBER'] + }, + { + id: '2', + firstName: 'Jimmy', + lastName: 'Olsen', + role: ['MEMBER'] + }, + { + id: '3', + firstName: 'Clark', + lastName: 'Kent', + role: ['MEMBER'] + }, + { + id: '6', + firstName: 'Brock', + lastName: 'Smith', + role: ['MEMBER'] + }, + { + id: '4', + firstName: 'Kent', + lastName: 'Brockman', + role: ['MEMBER'] + }, + { + id: '7', + firstName: 'Jimmy', + middleName: 'T.', + lastName: 'Olsen', + role: ['MEMBER'] + } + ] }; it('renders correctly', () => { snapshot( - + ); }); diff --git a/web-ui/src/components/kudos/__snapshots__/PublicKudosCard.test.jsx.snap b/web-ui/src/components/kudos/__snapshots__/PublicKudosCard.test.jsx.snap index 853d4b6faf..d9293b5a6a 100644 --- a/web-ui/src/components/kudos/__snapshots__/PublicKudosCard.test.jsx.snap +++ b/web-ui/src/components/kudos/__snapshots__/PublicKudosCard.test.jsx.snap @@ -70,7 +70,8 @@ exports[`renders correctly 1`] = ` - from + from +
diff --git a/web-ui/src/components/kudos_card/KudosCard.jsx b/web-ui/src/components/kudos_card/KudosCard.jsx index b94fe452cc..ece4b332a1 100644 --- a/web-ui/src/components/kudos_card/KudosCard.jsx +++ b/web-ui/src/components/kudos_card/KudosCard.jsx @@ -1,5 +1,5 @@ -import React, { useCallback, useContext, useState } from "react"; -import PropTypes from "prop-types"; +import React, { useCallback, useContext, useState } from 'react'; +import PropTypes from 'prop-types'; import { Paper, Collapse, @@ -18,24 +18,24 @@ import { TextField, FormGroup, FormControlLabel, - Checkbox, -} from "@mui/material"; + Checkbox +} from '@mui/material'; import { selectCsrfToken, - selectActiveOrInactiveProfile, -} from "../../context/selectors"; + selectActiveOrInactiveProfile +} from '../../context/selectors'; import MemberSelector from '../member_selector/MemberSelector'; -import { AppContext } from "../../context/AppContext"; -import { getAvatarURL } from "../../api/api"; -import DateFnsUtils from "@date-io/date-fns"; -import CheckIcon from "@mui/icons-material/Check"; -import CloseIcon from "@mui/icons-material/Close"; -import EditIcon from "@mui/icons-material/Edit"; -import TeamIcon from "@mui/icons-material/Groups"; +import { AppContext } from '../../context/AppContext'; +import { getAvatarURL } from '../../api/api'; +import DateFnsUtils from '@date-io/date-fns'; +import CheckIcon from '@mui/icons-material/Check'; +import CloseIcon from '@mui/icons-material/Close'; +import EditIcon from '@mui/icons-material/Edit'; +import TeamIcon from '@mui/icons-material/Groups'; -import "./KudosCard.css"; -import { approveKudos, deleteKudos, updateKudos } from "../../api/kudos"; -import { UPDATE_TOAST } from "../../context/actions"; +import './KudosCard.css'; +import { approveKudos, deleteKudos, updateKudos } from '../../api/kudos'; +import { UPDATE_TOAST } from '../../context/actions'; const dateUtils = new DateFnsUtils(); @@ -47,11 +47,11 @@ const propTypes = { recipientTeam: PropTypes.object, dateCreated: PropTypes.array.isRequired, dateApproved: PropTypes.array, - recipientMembers: PropTypes.array, + recipientMembers: PropTypes.array }).isRequired, includeActions: PropTypes.bool, includeEdit: PropTypes.bool, - onKudosAction: PropTypes.func, + onKudosAction: PropTypes.func }; const KudosCard = ({ kudos, includeActions, includeEdit, onKudosAction }) => { @@ -64,7 +64,9 @@ const KudosCard = ({ kudos, includeActions, includeEdit, onKudosAction }) => { const [kudosPublic, setKudosPublic] = useState(kudos.publiclyVisible); const [kudosMessage, setKudosMessage] = useState(kudos.message); const [memberSelectorOpen, setMemberSelectorOpen] = useState(false); - const [kudosRecipientMembers, setKudosRecipientMembers] = useState(kudos.recipientMembers); + const [kudosRecipientMembers, setKudosRecipientMembers] = useState( + kudos.recipientMembers + ); const sender = selectActiveOrInactiveProfile(state, kudos.senderId); @@ -92,7 +94,7 @@ const KudosCard = ({ kudos, includeActions, includeEdit, onKudosAction }) => { return ( - {kudos.recipientMembers.map((member) => ( + {kudos.recipientMembers.map(member => ( { }, [kudos]); const approveKudosCallback = useCallback( - async (event) => { + async event => { event.stopPropagation(); const res = await approveKudos(kudos, csrf); if (res?.payload?.data && !res.error) { dispatch({ type: UPDATE_TOAST, payload: { - severity: "success", - toast: "Kudos approved", - }, + severity: 'success', + toast: 'Kudos approved' + } }); onKudosAction && onKudosAction(); } else { dispatch({ type: UPDATE_TOAST, payload: { - severity: "error", - toast: "Failed to approve kudos", - }, + severity: 'error', + toast: 'Failed to approve kudos' + } }); } }, @@ -138,18 +140,18 @@ const KudosCard = ({ kudos, includeActions, includeEdit, onKudosAction }) => { dispatch({ type: UPDATE_TOAST, payload: { - severity: "success", - toast: "Kudos deleted", - }, + severity: 'success', + toast: 'Kudos deleted' + } }); onKudosAction && onKudosAction(); } else { dispatch({ type: UPDATE_TOAST, payload: { - severity: "error", - toast: "Failed to delete kudos", - }, + severity: 'error', + toast: 'Failed to delete kudos' + } }); } }, [kudos, csrf, dispatch, onKudosAction]); @@ -163,7 +165,7 @@ const KudosCard = ({ kudos, includeActions, includeEdit, onKudosAction }) => { id: kudos.id, message: kudosMessage, publiclyVisible: kudosPublic, - recipientMembers: kudosRecipientMembers, + recipientMembers: kudosRecipientMembers }; // Update on the server. @@ -172,25 +174,33 @@ const KudosCard = ({ kudos, includeActions, includeEdit, onKudosAction }) => { dispatch({ type: UPDATE_TOAST, payload: { - severity: "error", - toast: "Failed to update kudos", - }, + severity: 'error', + toast: 'Failed to update kudos' + } }); } else { dispatch({ type: UPDATE_TOAST, payload: { - severity: "success", - toast: "Kudos Updated", - }, + severity: 'success', + toast: 'Kudos Updated' + } }); onKudosAction && onKudosAction(); } - }, [kudos, kudosMessage, kudosPublic, kudosRecipientMembers, csrf, dispatch, onKudosAction]); + }, [ + kudos, + kudosMessage, + kudosPublic, + kudosRecipientMembers, + csrf, + dispatch, + onKudosAction + ]); const getStatusComponent = useCallback(() => { const dateApproved = kudos.dateApproved - ? new Date(kudos.dateApproved.join("/")) + ? new Date(kudos.dateApproved.join('/')) : null; const info = []; @@ -211,12 +221,12 @@ const KudosCard = ({ kudos, includeActions, includeEdit, onKudosAction }) => { } else if (dateApproved) { info.push( - Received{" "} - {dateApproved ? dateUtils.format(dateApproved, "MM/dd/yyyy") : ""} + Received{' '} + {dateApproved ? dateUtils.format(dateApproved, 'MM/dd/yyyy') : ''} ); } else { - const dateCreated = new Date(kudos.dateCreated.join("/")); + const dateCreated = new Date(kudos.dateCreated.join('/')); if (kudos.publiclyVisible) { info.push( @@ -226,7 +236,7 @@ const KudosCard = ({ kudos, includeActions, includeEdit, onKudosAction }) => { } info.push( - Created {dateUtils.format(dateCreated, "MM/dd/yyyy")} + Created {dateUtils.format(dateCreated, 'MM/dd/yyyy')} ); } @@ -236,7 +246,7 @@ const KudosCard = ({ kudos, includeActions, includeEdit, onKudosAction }) => { @@ -306,7 +316,7 @@ const KudosCard = ({ kudos, includeActions, includeEdit, onKudosAction }) => { - + Edit Kudos { fullWidth multiline defaultValue={kudosMessage} - onChange={(event) => { + onChange={event => { setKudosMessage(event.target.value); }} rows={5} - style={{ marginTop: "2rem" }} + style={{ marginTop: '2rem' }} variant="outlined" /> - - + @@ -369,9 +381,9 @@ const KudosCard = ({ kudos, includeActions, includeEdit, onKudosAction }) => { {kudos.recipientMembers?.length > 1 && (
- {kudos.recipientTeam ? "Team Members:" : "Members:"} + {kudos.recipientTeam ? 'Team Members:' : 'Members:'} - {kudos.recipientMembers.map((recipient) => ( + {kudos.recipientMembers.map(recipient => ( } diff --git a/web-ui/src/components/kudos_card/KudosCard.test.jsx b/web-ui/src/components/kudos_card/KudosCard.test.jsx index f411e0441e..e32c54468b 100644 --- a/web-ui/src/components/kudos_card/KudosCard.test.jsx +++ b/web-ui/src/components/kudos_card/KudosCard.test.jsx @@ -7,127 +7,128 @@ const initialState = { csrf: 'O_3eLX2-e05qpS_yOeg1ZVAs9nDhspEi', teams: [], userProfile: { - id: "1", + id: '1', firstName: 'Jimmy', lastName: 'Johnson', - role: ['MEMBER'], + role: ['MEMBER'] }, terminatedMembers: [ { - id: "5", + id: '5', firstName: 'Jerry', lastName: 'Garcia', name: 'Jerry Garcia', - role: ['MEMBER'], - }, + role: ['MEMBER'] + } ], memberProfiles: [ { - id: "1", + id: '1', firstName: 'Jimmy', lastName: 'Johnson', name: 'Jimmy Johnson', - role: ['MEMBER'], + role: ['MEMBER'] }, { - id: "2", + id: '2', firstName: 'Jimmy', lastName: 'Olsen', name: 'Jimmy Olsen', - role: ['MEMBER'], + role: ['MEMBER'] }, { - id: "3", + id: '3', firstName: 'Clark', lastName: 'Kent', name: 'Clark Kent', - role: ['MEMBER'], + role: ['MEMBER'] }, { - id: "4", + id: '4', firstName: 'Kent', lastName: 'Brockman', name: 'Kent Brockman', - role: ['MEMBER'], + role: ['MEMBER'] }, { - id: "6", + id: '6', firstName: 'Brock', lastName: 'Smith', name: 'Brock Smith', - role: ['MEMBER'], + role: ['MEMBER'] }, { - id: "7", + id: '7', firstName: 'Jimmy', middleName: 'T.', lastName: 'Olsen', name: 'Jimmy T. Olsen', - role: ['MEMBER'], - }, - ], + role: ['MEMBER'] + } + ] } }; const terminated = { id: 'test-terminated-kudos', - message: "Brock and Brockman did a great job helping Clark, Jimmy Olsen, Jimmy T. Olsen, and Johnson", - senderId: "5", - dateCreated: [ 2025, 2, 14 ], + message: + 'Brock and Brockman did a great job helping Clark, Jimmy Olsen, Jimmy T. Olsen, and Johnson', + senderId: '5', + dateCreated: [2025, 2, 14], recipientMembers: [ - { - id: "1", - firstName: 'Jimmy', - lastName: 'Johnson', - role: ['MEMBER'], - }, - { - id: "2", - firstName: 'Jimmy', - lastName: 'Olsen', - role: ['MEMBER'], - }, - { - id: "3", - firstName: 'Clark', - lastName: 'Kent', - role: ['MEMBER'], - }, - { - id: "6", - firstName: 'Brock', - lastName: 'Smith', - role: ['MEMBER'], - }, - { - id: "4", - firstName: 'Kent', - lastName: 'Brockman', - role: ['MEMBER'], - }, - { - id: "7", - firstName: 'Jimmy', - middleName: 'T.', - lastName: 'Olsen', - role: ['MEMBER'], - }, - ], + { + id: '1', + firstName: 'Jimmy', + lastName: 'Johnson', + role: ['MEMBER'] + }, + { + id: '2', + firstName: 'Jimmy', + lastName: 'Olsen', + role: ['MEMBER'] + }, + { + id: '3', + firstName: 'Clark', + lastName: 'Kent', + role: ['MEMBER'] + }, + { + id: '6', + firstName: 'Brock', + lastName: 'Smith', + role: ['MEMBER'] + }, + { + id: '4', + firstName: 'Kent', + lastName: 'Brockman', + role: ['MEMBER'] + }, + { + id: '7', + firstName: 'Jimmy', + middleName: 'T.', + lastName: 'Olsen', + role: ['MEMBER'] + } + ] }; const kudos = { id: 'test-kudos', - message: "Jimmy is awesome!", - senderId: "1", - dateCreated: [ 2025, 2, 17 ], + message: 'Jimmy is awesome!', + senderId: '1', + dateCreated: [2025, 2, 17], recipientMembers: [ - { - id: "2", - firstName: 'Jimmy', - lastName: 'Olsen', - role: ['MEMBER'], - }, - ], + { + id: '2', + firstName: 'Jimmy', + lastName: 'Olsen', + role: ['MEMBER'] + } + ] }; it('inactive renders correctly', () => { @@ -137,7 +138,7 @@ it('inactive renders correctly', () => { kudos={terminated} includeActions includeEdit - onKudosAction={() =>{}} + onKudosAction={() => {}} /> ); @@ -150,7 +151,7 @@ it('active renders correctly', () => { kudos={kudos} includeActions includeEdit - onKudosAction={() =>{}} + onKudosAction={() => {}} /> ); diff --git a/web-ui/src/components/kudos_dialog/KudosDialog.css b/web-ui/src/components/kudos_dialog/KudosDialog.css index c06923cc21..010d7fedd6 100644 --- a/web-ui/src/components/kudos_dialog/KudosDialog.css +++ b/web-ui/src/components/kudos_dialog/KudosDialog.css @@ -1,10 +1,10 @@ .kudos-dialog .kudos-dialog-content { - margin: 8rem 6rem 1rem 6rem; - height: 100%; + margin: 8rem 6rem 1rem 6rem; + height: 100%; } .kudos-dialog .kudos-dialog-content .kudos-recipient-container { - display: flex; - flex-direction: row; - gap: 1rem; -} \ No newline at end of file + display: flex; + flex-direction: row; + gap: 1rem; +} diff --git a/web-ui/src/components/kudos_dialog/KudosDialog.jsx b/web-ui/src/components/kudos_dialog/KudosDialog.jsx index 28ed890c83..ff85d0da78 100644 --- a/web-ui/src/components/kudos_dialog/KudosDialog.jsx +++ b/web-ui/src/components/kudos_dialog/KudosDialog.jsx @@ -317,13 +317,17 @@ const KudosDialog = ({ open, recipient, teamId, onClose }) => { value={message} onChange={handleMessageChange} /> - {publicKudos ? - Kudos will be visible to admins for approval, then sent to the - recipient. - :
} + {publicKudos ? ( + + Kudos will be visible to admins for approval, then sent to the + recipient. + + ) : ( +
+ )}