Skip to content

Commit

Permalink
Create last published component
Browse files Browse the repository at this point in the history
  • Loading branch information
synnestokkevaag committed Jan 9, 2025
1 parent 973a6a7 commit fda5cb0
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 78 deletions.
45 changes: 38 additions & 7 deletions plugins/ros/src/components/riScInfo/RiScInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { RiScWithMetadata } from '../../utils/types';
import React, { useState } from 'react';
import { DifferenceFetchState, RiScWithMetadata } from '../../utils/types';
import { Box, Grid, Typography } from '@material-ui/core';
import { RiScStatusComponent } from './riScStatus/RiScStatusComponent';
import { InfoCard } from '@backstage/core-components';
Expand All @@ -8,25 +8,42 @@ import { pluginRiScTranslationRef } from '../../utils/translations';
import { useFontStyles } from '../../utils/style';
import EditButton from '../common/EditButton';
import { useRiScs } from '../../contexts/RiScContext';
import { LastPublishedComponent } from './riScStatus/LastPublishedComponent';

interface RiScInfoProps {
riSc: RiScWithMetadata;
edit: () => void;
}

const emptyDifferenceFetchState: DifferenceFetchState = {
differenceState: {
entriesOnLeft: [],
entriesOnRight: [],
difference: [],
},
status: null,
isLoading: false,
errorMessage: '',
currentDifferenceId: '',
defaultLastModifiedDateString: '',
};

export const RiScInfo = ({ riSc, edit }: RiScInfoProps) => {
const { t } = useTranslationRef(pluginRiScTranslationRef);
const { label, body2 } = useFontStyles();

const { approveRiSc } = useRiScs();

const [differenceFetchState, setDifferenceFetchState] =
useState<DifferenceFetchState>(emptyDifferenceFetchState);

return (
<Grid container>
<Grid
item
xs={12}
sm={6}
md={6}
xs={8}
sm={4}
md={4}
style={{
display: 'flex',
flexDirection: 'column',
Expand All @@ -47,8 +64,22 @@ export const RiScInfo = ({ riSc, edit }: RiScInfoProps) => {
<Typography className={body2}>{riSc.content.scope}</Typography>
</InfoCard>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<RiScStatusComponent selectedRiSc={riSc} publishRiScFn={approveRiSc} />
<Grid item xs={8} sm={4} md={4}>
<LastPublishedComponent
selectedRiSc={riSc}
differenceFetchState={differenceFetchState}
setDifferenceFetchState={setDifferenceFetchState}
emptyDifferenceFetchState={emptyDifferenceFetchState}
/>
</Grid>
<Grid item xs={8} sm={4} md={4}>
<RiScStatusComponent
selectedRiSc={riSc}
publishRiScFn={approveRiSc}
differenceFetchState={differenceFetchState}
setDifferenceFetchState={setDifferenceFetchState}
emptyDifferenceFetchState={emptyDifferenceFetchState}
/>
</Grid>
</Grid>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { parseISO } from 'date-fns';
import {
getAgeStatus,
parseISODateFromEncryptedROS,
} from '../../../utils/utilityfunctions';
import SentimentSatisfiedAltIcon from '@mui/icons-material/SentimentSatisfiedAlt';
import SentimentNeutralIcon from '@mui/icons-material/SentimentNeutral';
import SentimentVeryDissatisfiedIcon from '@mui/icons-material/SentimentVeryDissatisfied';
import { useAuthenticatedFetch } from '../../../utils/hooks';
import { DifferenceFetchState, RiScWithMetadata } from '../../../utils/types';
import { Box, Typography } from '@mui/material';
import React from 'react';
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
import { pluginRiScTranslationRef } from '../../../utils/translations';
import { InfoCard } from '@backstage/core-components';
import HighlightOffIcon from '@mui/icons-material/HighlightOff';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';

interface LastPublishedComponentProps {
selectedRiSc: RiScWithMetadata;
differenceFetchState: DifferenceFetchState;
setDifferenceFetchState: React.Dispatch<
React.SetStateAction<DifferenceFetchState>
>;
emptyDifferenceFetchState: DifferenceFetchState;
}

export const LastPublishedComponent = ({
selectedRiSc,
differenceFetchState,
setDifferenceFetchState,
emptyDifferenceFetchState,
}: LastPublishedComponentProps) => {
const { t } = useTranslationRef(pluginRiScTranslationRef);

const { fetchDifference } = useAuthenticatedFetch();

const getDifferences = () => {
if (
!selectedRiSc ||
differenceFetchState.isLoading ||
differenceFetchState.currentDifferenceId === selectedRiSc.id
)
return;

setDifferenceFetchState({ ...differenceFetchState, isLoading: true });
fetchDifference(
selectedRiSc,
response => {
setDifferenceFetchState({
differenceState: response.differenceState,
isLoading: false,
currentDifferenceId: selectedRiSc.id,
status: response.status,
errorMessage: response.errorMessage,
defaultLastModifiedDateString: response.defaultLastModifiedDateString,
});
},
() => {
setDifferenceFetchState({
...emptyDifferenceFetchState,
errorMessage: t('rosStatus.difference.error'),
status: 'FrontendFallback', // Fallback when the backend does not deliver a response with status
});
},
);
};

const formatedDateString = parseISODateFromEncryptedROS(
differenceFetchState.defaultLastModifiedDateString,
);

const lastModifiedDate =
formatedDateString && parseISO(formatedDateString).toLocaleDateString();

getDifferences(); // TODO

const age = lastModifiedDate && getAgeStatus(lastModifiedDate);

return (
<InfoCard>
<Typography variant="h5">Publication status</Typography>
{!lastModifiedDate && (
<Typography display="flex" gap={1} mt={1}>
<HighlightOffIcon color="error" />
No risk scorecard published
</Typography>
)}
{lastModifiedDate && (
<Typography display="flex" flexDirection="column" gap={1} mt={1}>
<Box display="flex" gap={1}>
<CheckCircleOutlineIcon color="success" />
Risk scorecard published
</Box>
<Box display="flex" gap={1}>
{age === 'bad' && <SentimentVeryDissatisfiedIcon color="error" />}
{age === 'ok' && <SentimentNeutralIcon color="warning" />}
{age === 'good' && <SentimentSatisfiedAltIcon color="success" />}
{t('rosStatus.difference.publishDate')}
{lastModifiedDate}
</Box>
</Typography>
)}
</InfoCard>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import { ErrorOutline, Favorite } from '@mui/icons-material';
import { DifferenceText } from './DifferenceText';
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
import { pluginRiScTranslationRef } from '../../../utils/translations';
import { parseISODateFromEncryptedROS } from '../../../utils/utilityfunctions';
import { parseISO } from 'date-fns';

type RiScDifferenceDialogProps = {
differenceFetchState: DifferenceFetchState;
Expand All @@ -20,22 +18,9 @@ export const RiScDifferenceDialog = ({
}: RiScDifferenceDialogProps) => {
const { t } = useTranslationRef(pluginRiScTranslationRef);

const formatedDateString = parseISODateFromEncryptedROS(
differenceFetchState.defaultLastModifiedDateString,
);

const parsedDateString = formatedDateString
? parseISO(formatedDateString).toLocaleDateString()
: null;
return (
<Box>
<Typography>{t('rosStatus.difference.description')}</Typography>
<Typography fontWeight={700} fontSize={13} pb={2}>
{parsedDateString &&
t('rosStatus.difference.publishDate', {
date: parsedDateString,
})}
</Typography>
<Typography pb={2}>{t('rosStatus.difference.description')}</Typography>
<Box>
<Typography variant="h3" fontSize={18}>
{t('rosStatus.difference.differences.title')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,99 +14,57 @@ import { useRiScs } from '../../../contexts/RiScContext';
import { subtitle1 } from '../../common/typography';
import Box from '@mui/material/Box';
import { WarningAmberOutlined } from '@mui/icons-material';
import { useAuthenticatedFetch } from '../../../utils/hooks';
import Progress from './Progress';
import { RiScMigrationDialog } from '../MigrationDialog';
import { RiScPublishDialog } from '../PublishDialog';
import PendingActionsIcon from '@mui/icons-material/PendingActions';
import EditNoteIcon from '@mui/icons-material/EditNote';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';

const emptyDifferenceFetchState: DifferenceFetchState = {
differenceState: {
entriesOnLeft: [],
entriesOnRight: [],
difference: [],
},
status: null,
isLoading: false,
errorMessage: '',
currentDifferenceId: '',
defaultLastModifiedDateString: '',
};

interface RiScStatusProps {
selectedRiSc: RiScWithMetadata;
publishRiScFn: () => void;
differenceFetchState: DifferenceFetchState;
setDifferenceFetchState: React.Dispatch<
React.SetStateAction<DifferenceFetchState>
>;
emptyDifferenceFetchState: DifferenceFetchState;
}

export const RiScStatusComponent = ({
selectedRiSc,
publishRiScFn,
differenceFetchState,
setDifferenceFetchState,
emptyDifferenceFetchState,
}: RiScStatusProps) => {
const { t } = useTranslationRef(pluginRiScTranslationRef);
const { fetchDifference } = useAuthenticatedFetch();

const [publishRiScDialogIsOpen, setPublishRiScDialogIsOpen] =
useState<boolean>(false);

const [migrationDialogIsOpen, setMigrationDialogIsOpen] =
useState<boolean>(false);

const [differenceFetchState, setDifferenceFetchState] =
useState<DifferenceFetchState>(emptyDifferenceFetchState);

const { updateRiSc } = useRiScs();

const handleApproveAndPublish = () => {
publishRiScFn();
setPublishRiScDialogIsOpen(false);
};

const getDifferences = () => {
if (
!selectedRiSc ||
differenceFetchState.isLoading ||
differenceFetchState.currentDifferenceId === selectedRiSc.id
)
return;

setDifferenceFetchState({ ...differenceFetchState, isLoading: true });
fetchDifference(
selectedRiSc,
response => {
setDifferenceFetchState({
differenceState: response.differenceState,
isLoading: false,
currentDifferenceId: selectedRiSc.id,
status: response.status,
errorMessage: response.errorMessage,
defaultLastModifiedDateString: response.defaultLastModifiedDateString,
});
},
() => {
setDifferenceFetchState({
...emptyDifferenceFetchState,
errorMessage: t('rosStatus.difference.error'),
status: 'FrontendFallback', // Fallback when the backend does not deliver a response with status
});
},
);
};

const handleUpdate = () => {
updateRiSc(selectedRiSc.content);
setMigrationDialogIsOpen(false);
};

const handleOpenPublishRiScDialog = () => {
setPublishRiScDialogIsOpen(true);
getDifferences();
};

useEffect(() => {
setDifferenceFetchState(emptyDifferenceFetchState);
}, [selectedRiSc]);
}, [emptyDifferenceFetchState, selectedRiSc, setDifferenceFetchState]);

const [status, setStatus] = useState<0 | 1 | 2 | 3>(0);

Expand Down
7 changes: 3 additions & 4 deletions plugins/ros/src/utils/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const pluginRiScTranslationRef = createTranslationRef({
rosStatus: {
statusBadge: {
missing:
'Once the draft is complete, the risk owner can review and accept the changes.', // Mangler godkjenning av risikoeier
'Once the draft is complete, the risk owner can accept the changes.', // Mangler godkjenning av risikoeier
approved: 'Accepted by risk owner', // Godkjent av risikoeier
error: 'Failed to retrieve status', // Kunne ikke hente status
migration: {
Expand All @@ -84,7 +84,7 @@ export const pluginRiScTranslationRef = createTranslationRef({
},
difference: {
description: 'Summary of changes that will be approved by risk owner.',
publishDate: 'Last published changes {{date}}',
publishDate: 'Last published changes: ',
fetching: 'Fetching changes',
error: 'Error while fetching changes',
newROS: 'No published Risk scorecards to compare with',
Expand Down Expand Up @@ -514,8 +514,7 @@ export const pluginRiScNorwegianTranslation = createTranslationResource({
'rosStatus.moreInformationButton': 'Mer informasjon',
'rosStatus.difference.description':
'Oppsummering av endringer som må godkjennes av risikoeier.',
'rosStatus.difference.publishDate':
'Siste publiserte endringer {{date}}',
'rosStatus.difference.publishDate': 'Siste publiserte endringer: ',
'rosStatus.difference.fetching': 'Henter endringer',
'rosStatus.difference.error': 'Feil med uthenting av endringer',
'rosStatus.difference.newROS':
Expand Down
16 changes: 16 additions & 0 deletions plugins/ros/src/utils/utilityfunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,19 @@ export const deleteAction = (
remove(index);
onSubmit();
};

export const getAgeStatus = (date: string): 'good' | 'ok' | 'bad' => {
const [day, month, year] = date.split('/').map(Number);
const parsedDate: Date = new Date(year, month - 1, day);

const now: Date = new Date();
const diffInMilliseconds: number = now.getTime() - parsedDate.getTime();
const diffInMonths: number = diffInMilliseconds / (1000 * 60 * 60 * 24 * 30);

if (diffInMonths > 6) {
return 'bad';
} else if (diffInMonths > 3) {
return 'ok';
}
return 'good';
};

0 comments on commit fda5cb0

Please sign in to comment.