Skip to content

Commit

Permalink
Thomas/mar 410 tag info on case list (#300)
Browse files Browse the repository at this point in the history
* feat(api): add new endpoint for getting a list of cases

* feat(tags): add tags to case list
  • Loading branch information
balzdur authored Dec 12, 2023
1 parent 231faae commit de61672
Show file tree
Hide file tree
Showing 9 changed files with 355 additions and 130 deletions.
4 changes: 4 additions & 0 deletions packages/app-builder/public/locales/en/cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"case.name": "Name",
"case.date": "Date",
"case.status": "Status",
"case.tags": "Tags",
"case.contributors": "Contributors",
"case.decisions": "Decisions",
"case.inbox": "Inbox",
Expand All @@ -19,6 +20,9 @@
"case_detail.decisions_count_other": "{{count}} decisions",
"case_detail.history": "History",
"case_detail.unknown_user": "unknown user",
"case_detail.unknown_tag": "unknown tag",
"case_detail.other_tags_count_one": "+{{count}} other",
"case_detail.other_tags_count_other": "+{{count}} others",
"case_detail.history.event_title.case_created": "Case created",
"case_detail.history.event_title.comment_added": "Note",
"case_detail.history.event_title.decision_added_one": "{{count}} decision added",
Expand Down
11 changes: 7 additions & 4 deletions packages/app-builder/src/components/Cases/CaseInformation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { Collapsible } from 'ui-design-system';

import { CaseContributors } from './CaseContributors';
import { casesI18n } from './cases-i18n';
import { CaseTags } from './CaseTags';

export function CaseInformation({
caseDetail: { created_at, name, id, contributors },
caseDetail: { created_at, name, id, contributors, tags },
inbox: { name: inboxName },
}: {
caseDetail: Case;
Expand All @@ -25,17 +26,19 @@ export function CaseInformation({
{t('cases:case_detail.informations')}
</Collapsible.Title>
<Collapsible.Content>
<div className="grid grid-cols-[max-content_1fr] grid-rows-4 items-center gap-x-10 gap-y-2">
<div className="grid grid-cols-[max-content_1fr] grid-rows-5 items-center gap-x-10 gap-y-2">
<CaseLabel>{t('cases:case.name')}</CaseLabel>
<EditCaseName caseId={id} name={name} />
<CaseLabel>{t('cases:case.date')}</CaseLabel>
<div>
{formatDateTime(created_at, { language, timeStyle: undefined })}
</div>
<CaseLabel>{t('cases:case.contributors')}</CaseLabel>
<CaseContributors contributors={contributors} />
<CaseLabel>{t('cases:case.inbox')}</CaseLabel>
<div className="first-letter:capitalize">{inboxName}</div>
<CaseLabel>{t('cases:case.tags')}</CaseLabel>
<CaseTags caseTags={tags} />
<CaseLabel>{t('cases:case.contributors')}</CaseLabel>
<CaseContributors contributors={contributors} />
</div>
</Collapsible.Content>
</Collapsible.Container>
Expand Down
52 changes: 52 additions & 0 deletions packages/app-builder/src/components/Cases/CaseTags.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useOrganizationTags } from '@app-builder/services/organization/organization-tags';
import { type CaseTag } from 'marble-api';
import { useTranslation } from 'react-i18next';
import { Tooltip } from 'ui-design-system';

import { casesI18n } from './cases-i18n';

export function CaseTags({ caseTags }: { caseTags: CaseTag[] }) {
const { t } = useTranslation(casesI18n);
return (
<Tooltip.Default
content={
<div className="flex max-w-sm flex-wrap gap-1">
{caseTags.map((caseTag) => (
<CaseTag key={caseTag.id} caseTag={caseTag} />
))}
</div>
}
>
<div className="flex w-fit flex-wrap items-center gap-1">
{caseTags.slice(0, 3).map((caseTag) => (
<CaseTag key={caseTag.id} caseTag={caseTag} />
))}
{caseTags.length > 3 ? (
<div className="text-grey-100 bg-grey-05 flex h-6 items-center rounded-s px-2 text-xs font-normal">
{t('cases:case_detail.other_tags_count', {
count: caseTags.length - 3,
})}
</div>
) : null}
</div>
</Tooltip.Default>
);
}

function CaseTag({ caseTag }: { caseTag: CaseTag }) {
const { getTagById } = useOrganizationTags();
const { t } = useTranslation(casesI18n);

const tag = getTagById(caseTag.tag_id);

return (
<div
className="bg-grey-05 flex h-6 items-center rounded px-2"
style={{ backgroundColor: tag?.color }}
>
<span className="text-grey-100 line-clamp-1 text-xs font-normal">
{tag?.name || t('cases:case_detail.unknown_tag')}
</span>
</div>
);
}
61 changes: 34 additions & 27 deletions packages/app-builder/src/components/Cases/CasesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { formatDateTime } from '@app-builder/utils/format';
import { getRoute } from '@app-builder/utils/routes';
import { fromUUID } from '@app-builder/utils/short-uuid';
import { useNavigate } from '@remix-run/react';
import { type ColumnDef, getCoreRowModel } from '@tanstack/react-table';
import { createColumnHelper, getCoreRowModel } from '@tanstack/react-table';
import clsx from 'clsx';
import { type Case } from 'marble-api';
import { useMemo } from 'react';
Expand All @@ -12,6 +12,9 @@ import { Table, useVirtualTable } from 'ui-design-system';
import { CaseContributors } from './CaseContributors';
import { casesI18n } from './cases-i18n';
import { CaseStatus } from './CaseStatus';
import { CaseTags } from './CaseTags';

const columnHelper = createColumnHelper<Case>();

export function CasesList({ cases }: { cases: Case[] }) {
const {
Expand All @@ -20,45 +23,49 @@ export function CasesList({ cases }: { cases: Case[] }) {
} = useTranslation(casesI18n);
const navigate = useNavigate();

const columns = useMemo<ColumnDef<Case, string>[]>(
const columns = useMemo(
() => [
{
columnHelper.accessor(({ status }) => status, {
id: 'status',
accessorFn: (c) => c.status,
header: t('cases:case.status'),
size: 50,
cell: ({ getValue }) => (
<CaseStatus status={getValue<Case['status']>()} />
),
},
{
cell: ({ getValue }) => <CaseStatus status={getValue()} />,
}),
columnHelper.accessor(({ name }) => name, {
id: 'name',
accessorFn: (c) => c.name,
header: t('cases:case.name'),
size: 200,
},
{
id: 'created_at',
accessorFn: (row) =>
formatDateTime(row.created_at, { language, timeStyle: undefined }),
header: t('cases:case.date'),
size: 100,
},
{
}),
columnHelper.accessor(
({ created_at }) =>
formatDateTime(created_at, { language, timeStyle: undefined }),
{
id: 'created_at',
header: t('cases:case.date'),
size: 100,
},
),
columnHelper.accessor(({ decisions_count }) => decisions_count, {
id: 'decisions',
accessorFn: (c) => c.decisions_count,
header: t('cases:case.decisions'),
size: 100,
},
{
id: 'contributors',
accessorFn: (c) => c.contributors,
header: t('cases:case.contributors'),
}),
columnHelper.accessor(({ tags }) => tags, {
id: 'tags',
header: t('cases:case.tags'),
size: 100,
cell: ({ getValue }) => (
<CaseContributors contributors={getValue<Case['contributors']>()} />
<div className="p-2">
<CaseTags caseTags={getValue()} />
</div>
),
},
}),
columnHelper.accessor(({ contributors }) => contributors, {
id: 'contributors',
header: t('cases:case.contributors'),
size: 100,
cell: ({ getValue }) => <CaseContributors contributors={getValue()} />,
}),
],
[language, t],
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import {
adaptOrganizationDto,
type Organization,
} from '@app-builder/models/organization';
import { type Tag } from 'marble-api';

export interface OrganizationRepository {
getCurrentOrganization(): Promise<Organization>;
listUsers(): Promise<User[]>;
listTags(): Promise<Tag[]>;
}

export function getOrganizationRepository() {
Expand All @@ -26,5 +28,9 @@ export function getOrganizationRepository() {
await marbleApiClient.listOrganizationUsers(organizationId);
return users.map(adaptUser);
},
listTags: async () => {
const { tags } = await marbleApiClient.listTags();
return tags;
},
});
}
Loading

0 comments on commit de61672

Please sign in to comment.