-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
feat(novui,web): V2 flow list #5682
Merged
Merged
Changes from 11 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
2773eff
feat: Add react table
antonjoel82 a9ae614
feat: Port minimalist table from design-system
antonjoel82 1275c7b
feat: Add placeholder
antonjoel82 d40931e
feat: Novui work on table
antonjoel82 6c8a087
feat: Temporary workflows list page
antonjoel82 35055a4
feat: Semantic radius tokens
antonjoel82 b233bd6
feat: Dimension tokens
antonjoel82 0abcb85
fix: Fix tokens
antonjoel82 227f870
feat: Table on list page
antonjoel82 e80b93a
fix: Cspell & add comment
antonjoel82 a1f6459
Merge branch 'next' into v2-flow-list
antonjoel82 b625291
fix: Table styling
antonjoel82 89220e2
feat: Re-define layout primitives
antonjoel82 05b41ed
fix: Clean-up fixmes
antonjoel82 ac673aa
fix: Typo in footer
antonjoel82 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
apps/web/src/studio/components/workflows/WorkflowsListPage.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { SettingsPageContainer } from '../../../pages/settings/SettingsPageContainer'; | ||
import { WorkflowsTable } from './table'; | ||
|
||
export const WorkflowsListPage = () => { | ||
return ( | ||
<SettingsPageContainer title="Workflows"> | ||
<WorkflowsTable /> | ||
</SettingsPageContainer> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './WorkflowsListPage'; |
110 changes: 110 additions & 0 deletions
110
apps/web/src/studio/components/workflows/table/WorkflowsTable.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* cspell:disable */ | ||
|
||
import { createColumnHelper, Table } from '@novu/novui'; | ||
import { css } from '@novu/novui/css'; | ||
import format from 'date-fns/format'; | ||
import { FC } from 'react'; | ||
import { WorkflowTableRow } from './WorkflowsTable.types'; | ||
import { GroupCell, NameCell, StatusCell } from './WorkflowsTableCellRenderers'; | ||
|
||
// TODO: remove this test data | ||
const TEST_FLOW = { | ||
_id: 'adaewr', | ||
name: 'test naming', | ||
active: false, | ||
type: 'REGULAR', | ||
draft: true, | ||
critical: false, | ||
isBlueprint: false, | ||
_notificationGroupId: 'dsasdfasdf', | ||
tags: [], | ||
triggers: [ | ||
{ | ||
type: 'event', | ||
identifier: 'test-naming', | ||
variables: [], | ||
reservedVariables: [], | ||
subscriberVariables: [], | ||
_id: 'sdfsdf', | ||
}, | ||
], | ||
steps: [], | ||
preferenceSettings: { | ||
email: true, | ||
sms: true, | ||
in_app: true, | ||
chat: true, | ||
push: true, | ||
}, | ||
_environmentId: 'sdfsdf', | ||
_organizationId: 'sdf', | ||
_creatorId: 'sdfsdfsdf', | ||
deleted: false, | ||
createdAt: '2024-06-04T19:11:11.600Z', | ||
updatedAt: '2024-06-05T17:55:39.022Z', | ||
__v: 0, | ||
notificationGroup: { | ||
_id: 'sdfsdf', | ||
name: 'General', | ||
_organizationId: 'sdfsdf', | ||
_environmentId: 'sdfdfsdfsf', | ||
createdAt: '2024-05-17T22:26:08.177Z', | ||
updatedAt: '2024-05-17T22:26:08.177Z', | ||
__v: 0, | ||
}, | ||
workflowIntegrationStatus: { | ||
hasActiveIntegrations: true, | ||
channels: { | ||
in_app: { | ||
hasActiveIntegrations: false, | ||
}, | ||
email: { | ||
hasActiveIntegrations: true, | ||
hasPrimaryIntegrations: true, | ||
}, | ||
sms: { | ||
hasActiveIntegrations: true, | ||
hasPrimaryIntegrations: true, | ||
}, | ||
chat: { | ||
hasActiveIntegrations: false, | ||
}, | ||
push: { | ||
hasActiveIntegrations: false, | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
interface IWorkflowsTableProps { | ||
temp?: string; | ||
} | ||
|
||
const columnHelper = createColumnHelper<WorkflowTableRow>(); | ||
|
||
const WORKFLOW_COLUMNS = [ | ||
columnHelper.accessor('name', { | ||
header: 'Name & Trigger ID', | ||
cell: NameCell, | ||
}), | ||
columnHelper.accessor('notificationGroup.name', { | ||
header: 'Group', | ||
cell: GroupCell, | ||
}), | ||
columnHelper.accessor('createdAt', { | ||
header: 'Created at', | ||
cell: ({ getValue }) => format(new Date(getValue() ?? ''), 'dd/MM/yyyy HH:mm'), | ||
}), | ||
columnHelper.accessor('active', { | ||
header: 'Status', | ||
cell: StatusCell, | ||
}), | ||
]; | ||
|
||
export const WorkflowsTable: FC<IWorkflowsTableProps> = () => { | ||
return ( | ||
<div className={css({ display: 'flex', flex: '1' })}> | ||
<Table<typeof TEST_FLOW> columns={WORKFLOW_COLUMNS} data={[TEST_FLOW]} className={css({ w: '100%' })} /> | ||
</div> | ||
); | ||
}; |
3 changes: 3 additions & 0 deletions
3
apps/web/src/studio/components/workflows/table/WorkflowsTable.types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { INotificationTemplateExtended } from '../../../../hooks/useTemplates'; | ||
|
||
export type WorkflowTableRow = INotificationTemplateExtended; |
64 changes: 64 additions & 0 deletions
64
apps/web/src/studio/components/workflows/table/WorkflowsTableCellRenderers.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { CellRendererComponent } from '@novu/novui'; | ||
import { css } from '@novu/novui/css'; | ||
import { IconBolt, IconCable, IconFlashOff } from '@novu/novui/icons'; | ||
import { Center, Flex, HStack, styled } from '@novu/novui/jsx'; | ||
import { text } from '@novu/novui/recipes'; | ||
import { ColorToken } from '@novu/novui/tokens'; | ||
import { WorkflowTableRow } from './WorkflowsTable.types'; | ||
|
||
export const GroupCell: CellRendererComponent<WorkflowTableRow, string> = (props) => { | ||
return ( | ||
<Center | ||
className={css({ | ||
color: 'typography.text.main', | ||
rounded: '50', | ||
border: 'solid', | ||
py: '25', | ||
px: '75', | ||
borderColor: 'badge.border', | ||
width: '[fit-content]', | ||
bg: '[transparent]', | ||
})} | ||
> | ||
{props.getValue()} | ||
</Center> | ||
); | ||
}; | ||
|
||
const Text = styled('p', text); | ||
|
||
export const NameCell: CellRendererComponent<WorkflowTableRow, string> = ({ getValue, row: { original } }) => { | ||
return ( | ||
<HStack gap="50"> | ||
{ | ||
<IconCable | ||
className={css({ width: '200', height: '200', color: 'icon.secondary' })} | ||
title="workflow-row-label" | ||
/> | ||
} | ||
<Flex direction={'column'}> | ||
<Text variant={'main'}>{getValue()}</Text> | ||
<Text variant={'secondary'}>{original.triggers ? original.triggers[0].identifier : 'Unknown'}</Text> | ||
</Flex> | ||
</HStack> | ||
); | ||
}; | ||
|
||
export const StatusCell: CellRendererComponent<WorkflowTableRow, boolean> = ({ getValue }) => { | ||
const isActive = getValue(); | ||
getValue(); | ||
const color: ColorToken = isActive ? 'status.active' : 'status.inactive'; | ||
|
||
return ( | ||
<HStack gap="0"> | ||
{isActive ? ( | ||
<IconBolt size="16" className={css({ color })} title="workflow-status-indicator" /> | ||
) : ( | ||
<IconFlashOff size="16" className={css({ color })} title="workflow-status-indicator" /> | ||
)} | ||
<Text variant={'main'} color={color}> | ||
{isActive ? 'Active' : 'Inactive'} | ||
</Text> | ||
</HStack> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './WorkflowsTable'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,4 +40,6 @@ export default defineConfig({ | |
|
||
// Enables JSX util generation! | ||
jsxFramework: 'react', | ||
|
||
validation: 'error', | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from './Test'; | ||
export * from './NovuiProvider'; | ||
export * from './table'; | ||
export * from './Test'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import React, { useState } from 'react'; | ||
import { StoryFn, Meta } from '@storybook/react'; | ||
import { Badge, Switch } from '@mantine/core'; | ||
|
||
import { Table } from './Table'; | ||
import { ColumnDef } from '@tanstack/react-table'; | ||
|
||
export default { | ||
title: 'Components/Table', | ||
component: Table, | ||
argTypes: { | ||
data: { | ||
control: false, | ||
}, | ||
columns: { | ||
control: false, | ||
}, | ||
}, | ||
} as Meta<typeof Table>; | ||
|
||
const SwitchCell = (props) => { | ||
const [status, setStatus] = useState(props.status); | ||
const switchHandler = () => { | ||
setStatus((prev) => (prev === 'Enabled' ? 'Disabled' : 'Enabled')); | ||
}; | ||
|
||
return <Switch label={status} onChange={switchHandler} checked={status === 'Enabled'} />; | ||
}; | ||
|
||
const BadgeCell = (props) => { | ||
return ( | ||
<Badge variant="outline" size="md" radius="xs"> | ||
{props.getValue()} | ||
</Badge> | ||
); | ||
}; | ||
|
||
interface IExampleData { | ||
name: string; | ||
category: string; | ||
creationDate: string; | ||
status: string; | ||
} | ||
|
||
const columns: ColumnDef<IExampleData>[] = [ | ||
{ accessorKey: 'name', header: 'Name' }, | ||
{ accessorKey: 'category', header: 'Category', cell: BadgeCell }, | ||
{ accessorKey: 'creationDate', header: 'Date Created' }, | ||
{ accessorKey: 'status', header: 'Status', cell: SwitchCell }, | ||
]; | ||
|
||
const data: IExampleData[] = [ | ||
{ name: 'Great', category: 'Fun', status: 'Disabled', creationDate: '01/01/2021 16:36' }, | ||
{ name: 'Whats up?', category: 'Done', status: 'Enabled', creationDate: '01/01/2021 16:36' }, | ||
]; | ||
|
||
const Template: StoryFn<typeof Table> = ({ ...args }) => <Table columns={columns} data={data} {...args} />; | ||
|
||
export const PrimaryUse = Template.bind({}); | ||
PrimaryUse.args = {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { type TableStylesNames } from '@mantine/core'; | ||
import { css } from '../../../styled-system/css'; | ||
|
||
const tableStyles: Partial<Record<TableStylesNames, string>> = { | ||
tr: css({ | ||
'& td': { | ||
textOverflow: 'ellipsis', | ||
}, | ||
}), | ||
table: css({ | ||
borderCollapse: 'collapse', | ||
borderSpacingX: '125', | ||
textStyle: 'text.main', | ||
'& tr td:first-of-type': { | ||
pl: '200', | ||
pr: '200', | ||
}, | ||
'& tr th:first-of-type': { | ||
pl: '200', | ||
pr: '200', | ||
}, | ||
'& tr td:last-child': { | ||
pr: '200', | ||
}, | ||
'& tr th:last-child': { | ||
pr: '200', | ||
}, | ||
'& thead tr': { | ||
borderBottom: 'solid', | ||
borderColor: 'table.header.border', | ||
}, | ||
'& thead tr th': { | ||
fontWeight: 'regular', | ||
// height: '17px', | ||
textAlign: 'left', | ||
color: 'typography.text.tertiary', | ||
borderBottom: 'none', | ||
borderSpacing: '0', | ||
pb: '100', | ||
}, | ||
'& tbody tr td': { | ||
// TODO: replace with token value | ||
maxWidth: '[100px]', | ||
// TODO: replace with token value | ||
height: '[80px]', | ||
|
||
color: 'typography.text.main', | ||
borderBottom: 'solid', | ||
borderColor: 'table.row.border', | ||
}, | ||
'& tbody tr[data-disabled="true"]:hover': { | ||
cursor: 'default', | ||
}, | ||
'& tbody tr[data-disabled="false"]:hover': { | ||
cursor: 'pointer', | ||
}, | ||
'& tbody tr:last-of-type td': { | ||
borderBottom: 'solid', | ||
borderColor: 'table.bottom.border', | ||
}, | ||
_hover: { | ||
'& tbody tr:hover': { | ||
bg: 'table.row.surface.hover', | ||
}, | ||
}, | ||
}), | ||
}; | ||
|
||
export default tableStyles; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗒 note (non-blocking): This is a placeholder for other props