Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use DialogContent #1841

Merged
merged 1 commit into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"i18n:sort": "tsx ./src/i18n/check.ts --sort"
},
"dependencies": {
"@altinn/altinn-components": "^0.18.6",
"@altinn/altinn-components": "^0.18.8",
"@digdir/designsystemet-css": "1.0.0-next.50",
"@digdir/designsystemet-react": "1.0.0-next.50",
"@digdir/designsystemet-theme": "1.0.0-next.50",
Expand Down
53 changes: 14 additions & 39 deletions packages/frontend/src/api/useDialogById.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import type {
TransmissionFieldsFragment,
} from 'bff-types-generated';
import { AttachmentUrlConsumer } from 'bff-types-generated';
import type { GuiActionButtonProps, InboxItemMetaField } from '../components';
import { t } from 'i18next';
import type { GuiActionButtonProps } from '../components';
import { QUERY_KEYS } from '../constants/queryKeys.ts';
import { i18n } from '../i18n/config.ts';
import { type ValueType, getPreferredPropertyByLocale } from '../i18n/property.ts';
import { useOrganizations } from '../pages/Inbox/useOrganizations.ts';
import { getOrganization } from './organizations.ts';
import { graphQLSDK } from './queries.ts';
import { getSeenByLabel } from './useDialogs.tsx';

export interface Participant {
name: string;
Expand Down Expand Up @@ -60,7 +61,6 @@ export interface DialogByIdDetails {
sender: Participant;
receiver: Participant;
title: string;
metaFields: InboxItemMetaField[];
guiActions: GuiActionButtonProps[];
additionalInfo: { value: string; mediaType: string } | undefined;
attachments: AttachmentFieldsFragment[];
Expand All @@ -73,10 +73,14 @@ export interface DialogByIdDetails {
transmissions: DialogTransmission[];
status: DialogStatus;
dueAt?: string;
isSeenByEndUser: boolean;
seenByOthersCount: number;
seenByLabel?: string;
}

interface UseDialogByIdOutput {
isSuccess: boolean;
isError: boolean;
isLoading: boolean;
dialog?: DialogByIdDetails;
}
Expand All @@ -85,38 +89,6 @@ export const getDialogsById = (id: string): Promise<GetDialogByIdQuery> =>
id,
});

export const getMetaFields = (item: DialogByIdFieldsFragment, isSeenByEndUser: boolean) => {
const nOtherSeen = item.seenSinceLastUpdate?.filter((seenLogEntry) => !seenLogEntry.isCurrentEndUser).length ?? 0;
const metaFields: InboxItemMetaField[] = [];

if (isSeenByEndUser && nOtherSeen) {
metaFields.push({
type: 'seenBy',
label: `${i18n.t('word.seenBy')} ${i18n.t('word.you')} ${i18n.t('word.and')} ${nOtherSeen} ${i18n.t('word.others')}`,
options: {
tooltip: item.seenSinceLastUpdate.map((seenLogEntry) => seenLogEntry.seenBy.actorName).join('\n'),
},
});
} else if (nOtherSeen) {
metaFields.push({
type: 'seenBy',
label: `${i18n.t('word.seenBy')} ${nOtherSeen} ${i18n.t('word.others')}`,
options: {
tooltip: item.seenSinceLastUpdate.map((seenLogEntry) => seenLogEntry.seenBy.actorName).join('\n'),
},
});
} else if (isSeenByEndUser) {
metaFields.push({
type: 'seenBy',
label: `${i18n.t('word.seenBy')} ${i18n.t('word.you')}`,
options: {
tooltip: item.seenSinceLastUpdate.map((seenLogEntry) => seenLogEntry.seenBy.actorName).join('\n'),
},
});
}
return metaFields;
};

const getMainContentReference = (
args: { value: ValueType; mediaType: string } | undefined | null,
): EmbeddedContent | undefined => {
Expand Down Expand Up @@ -151,8 +123,8 @@ export function mapDialogToToInboxItem(
const dialogReceiverParty = parties?.find((party) => party.party === item.party);
const actualReceiverParty = dialogReceiverParty ?? endUserParty;
const serviceOwner = getOrganization(organizations || [], item.org, 'nb');
const isSeenByEndUser = item.seenSinceLastUpdate.find((seenLogEntry) => seenLogEntry.isCurrentEndUser) !== undefined;
const senderName = item.content.senderName?.value;
const { isSeenByEndUser, seenByOthersCount, seenByLabel } = getSeenByLabel(item.seenSinceLastUpdate, t);

return {
title: getPreferredPropertyByLocale(titleObj)?.value ?? '',
Expand All @@ -167,7 +139,6 @@ export function mapDialogToToInboxItem(
name: actualReceiverParty?.name ?? '',
isCompany: actualReceiverParty?.partyType === 'Organization',
},
metaFields: getMetaFields(item, isSeenByEndUser),
additionalInfo: {
value: getPreferredPropertyByLocale(additionalInfoObj)?.value ?? '',
mediaType: item.content?.additionalInfo?.mediaType ?? '',
Expand All @@ -188,6 +159,9 @@ export function mapDialogToToInboxItem(
),
mainContentReference: getMainContentReference(mainContentReference),
dialogToken: item.dialogToken!,
isSeenByEndUser,
seenByLabel,
seenByOthersCount,
activities: item.activities
.map((activity) => ({
id: activity.id,
Expand Down Expand Up @@ -222,7 +196,7 @@ export const useDialogById = (parties: PartyFieldsFragment[], id?: string): UseD
const queryClient = useQueryClient();
const { organizations, isLoading: isOrganizationsLoading } = useOrganizations();
const partyURIs = parties.map((party) => party.party);
const { data, isSuccess, isLoading } = useQuery<GetDialogByIdQuery>({
const { data, isSuccess, isLoading, isError } = useQuery<GetDialogByIdQuery>({
queryKey: [QUERY_KEYS.DIALOG_BY_ID, id, organizations],
staleTime: 1000 * 60 * 10,
retry: 3,
Expand All @@ -237,12 +211,13 @@ export const useDialogById = (parties: PartyFieldsFragment[], id?: string): UseD
});

if (isOrganizationsLoading) {
return { isLoading: true, isSuccess: false };
return { isLoading: true, isError: false, isSuccess: false };
}

return {
isLoading,
isSuccess,
dialog: mapDialogToToInboxItem(data?.dialogById.dialog, parties, organizations),
isError,
};
};
80 changes: 20 additions & 60 deletions packages/frontend/src/api/useDialogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import {
type SearchDialogFieldsFragment,
SystemLabel,
} from 'bff-types-generated';
import { t } from 'i18next';
import type { InboxItemInput, InboxItemMetaField, InboxItemMetaFieldType } from '../components';
import { type TFunction, t } from 'i18next';
import { QUERY_KEYS } from '../constants/queryKeys.ts';
import { i18n } from '../i18n/config.ts';
import { getPreferredPropertyByLocale } from '../i18n/property.ts';
import type { InboxItemInput } from '../pages/Inbox/InboxItemInput.ts';
import { useOrganizations } from '../pages/Inbox/useOrganizations.ts';
import { getOrganization } from './organizations.ts';
import { graphQLSDK } from './queries.ts';
Expand All @@ -28,6 +27,7 @@ interface UseDialogsOutput {
dialogsByView: DialogsByView;
isSuccess: boolean;
isLoading: boolean;
isError: boolean;
}

export function mapDialogToToInboxItem(
Expand All @@ -48,12 +48,7 @@ export function mapDialogToToInboxItem(

const actualReceiverParty = dialogReceiverParty ?? dialogReceiverSubParty ?? endUserParty;
const serviceOwner = getOrganization(organizations || [], item.org, 'nb');
const isSeenByEndUser =
item.seenSinceLastUpdate.find((seenLogEntry) => seenLogEntry.isCurrentEndUser) !== undefined;

const { isSeenByYou, seenByOthersCount } = getSeenByLabel(item.seenSinceLastUpdate);

const seenByLabel = `${t('word.seenBy')} ${isSeenByYou ? t('word.you') : ''} ${seenByOthersCount > 0 ? ' + ' + seenByOthersCount : ''}`;
const { isSeenByEndUser, seenByOthersCount, seenByLabel } = getSeenByLabel(item.seenSinceLastUpdate, t);
return {
id: item.id,
party: item.party,
Expand Down Expand Up @@ -110,11 +105,21 @@ interface SeenByItem {
isCurrentEndUser: boolean;
}

export const getSeenByLabel = (seenBy: SeenByItem[]): { isSeenByYou: boolean; seenByOthersCount: number } => {
const isSeenByYou = seenBy?.some((item) => item.isCurrentEndUser === true);
const seenByOthersCount = seenBy?.filter((item) => item.isCurrentEndUser === false).length;
export const getSeenByLabel = (
seenBy: SeenByItem[],
t: TFunction<'translation', undefined>,
): { isSeenByEndUser: boolean; seenByOthersCount: number; seenByLabel: string | undefined } => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

const isSeenByEndUser = seenBy?.some((item) => item.isCurrentEndUser);
const seenByOthersCount = seenBy?.filter((item) => !item.isCurrentEndUser).length;
let seenByLabel: string | undefined = undefined;
if (isSeenByEndUser) {
seenByLabel = `${t('word.seenBy')} ${t('word.you')}`;
}
if (seenByOthersCount > 0) {
seenByLabel = (seenByLabel ?? t('word.seenBy')) + (isSeenByEndUser ? ` + ` : ' ') + seenByOthersCount;
}

return { isSeenByYou, seenByOthersCount };
return { isSeenByEndUser, seenByOthersCount, seenByLabel };
};

export const searchDialogs = (
Expand Down Expand Up @@ -190,7 +195,7 @@ export const useDialogs = (parties: PartyFieldsFragment[]): UseDialogsOutput =>
const partiesToUse = parties ? parties : selectedParties;
const mergedPartiesWithSubParties = flattenParties(partiesToUse);

const { data, isSuccess, isLoading } = useQuery<GetAllDialogsForPartiesQuery>({
const { data, isSuccess, isLoading, isError } = useQuery<GetAllDialogsForPartiesQuery>({
queryKey: [QUERY_KEYS.DIALOGS, mergedPartiesWithSubParties, organizations],
staleTime: 1000 * 60 * 10,
retry: 3,
Expand All @@ -203,6 +208,7 @@ export const useDialogs = (parties: PartyFieldsFragment[]): UseDialogsOutput =>
return {
isLoading,
isSuccess,
isError,
dialogs,
dialogsByView: {
inbox: dialogs.filter((dialog) => dialog.viewType === 'inbox'),
Expand All @@ -214,49 +220,3 @@ export const useDialogs = (parties: PartyFieldsFragment[]): UseDialogsOutput =>
dialogCountInconclusive: data?.searchDialogs?.hasNextPage === true || data?.searchDialogs?.items === null,
};
};

export const getMetaFields = (item: SearchDialogFieldsFragment, isSeenByEndUser: boolean) => {
const nOtherSeen = item.seenSinceLastUpdate?.filter((seenLogEntry) => !seenLogEntry.isCurrentEndUser).length ?? 0;
const metaFields: InboxItemMetaField[] = [];
metaFields.push({
type: `status_${item.status}` as InboxItemMetaFieldType,
label: `${i18n.t('word.status')}: ${item.status}`,
});

metaFields.push({ type: 'timestamp', label: item.updatedAt });

if (typeof item.guiAttachmentCount === 'number' && item.guiAttachmentCount > 0) {
metaFields.push({
type: 'attachment',
label: item.guiAttachmentCount.toString(),
});
}

if (isSeenByEndUser && nOtherSeen) {
metaFields.push({
type: 'seenBy',
label: `${i18n.t('word.seenBy')} ${i18n.t('word.you')} ${i18n.t('word.and')} ${nOtherSeen} ${i18n.t('word.others')}`,
options: {
tooltip: item.seenSinceLastUpdate.map((seenLogEntry) => seenLogEntry.seenBy.actorName).join('\n'),
},
});
} else if (nOtherSeen) {
metaFields.push({
type: 'seenBy',
label: `${i18n.t('word.seenBy')} ${nOtherSeen} ${i18n.t('word.others')}`,
options: {
tooltip: item.seenSinceLastUpdate.map((seenLogEntry) => seenLogEntry.seenBy.actorName).join('\n'),
},
});
} else if (isSeenByEndUser) {
metaFields.push({
type: 'seenBy',
label: `${i18n.t('word.seenBy')} ${i18n.t('word.you')}`,
options: {
tooltip: item.seenSinceLastUpdate.map((seenLogEntry) => seenLogEntry.seenBy.actorName).join('\n'),
},
});
}

return metaFields;
};
3 changes: 1 addition & 2 deletions packages/frontend/src/components/Activity/Activity.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Avatar } from '@altinn/altinn-components';
import { ActorType } from 'bff-types-generated';
import { t } from 'i18next';
import type { DialogActivity, Participant } from '../../api/useDialogById.tsx';
import { useFormat } from '../../i18n/useDateFnsLocale.tsx';

import { t } from 'i18next';
import styles from './activity.module.css';

interface ActivityProps {
Expand Down
Loading