From dde5521cc43fd37a5ff53ebd00fd7000ec6ef27d Mon Sep 17 00:00:00 2001 From: Georgi Manev Date: Mon, 30 Oct 2023 15:26:50 +0100 Subject: [PATCH 01/13] Service ticket page with the new naming convention applied and pages moved to the wfo-surf-ui app --- apps/wfo-ui-surf/next.config.js | 5 +- apps/wfo-ui-surf/package.json | 1 + .../pages/service-tickets/active.tsx | 6 + .../pages/service-tickets/completed.tsx | 6 + apps/wfo-ui-surf/translations/en-US.json | 18 +- apps/wfo-ui-surf/translations/nl-NL.json | 18 +- mkdocs/docs/adrs/0005-component-naming.md | 2 +- .../src/components/WfoDateTime/index.ts | 1 + .../src/components/WfoInsyncIcon/index.ts | 1 + .../WfoPageTemplate/WfoSidebar/WfoSidebar.tsx | 29 +++ .../WfoTable/WfoBasicTable/WfoBasicTable.tsx | 13 +- .../WfoTable/WfoBasicTable/styles.ts | 21 ++ .../src/components/WfoTable/utils/columns.ts | 2 + .../src/components/index.ts | 1 + .../src/hooks/DataFetchHooks.ts | 17 ++ packages/surf/.storybook/main.js | 28 ++ packages/surf/.storybook/preview.js | 14 + packages/surf/CHANGELOG.md | 4 + packages/surf/eslintrc.js | 3 + packages/surf/jest.config.cjs | 7 + packages/surf/package.json | 71 ++++++ .../components/WfoServiceTicketList/index.ts | 2 + ...apghQlCimResultToServiceTicketListItems.ts | 48 ++++ .../subscriptionListTabs.ts | 71 ++++++ packages/surf/src/components/index.ts | 1 + packages/surf/src/constants.ts | 4 + packages/surf/src/index.ts | 2 + packages/surf/src/messages/en-US.json | 17 ++ .../messages/getTranslationMessages.spec.ts | 51 ++++ .../src/messages/getTranslationMessages.ts | 26 ++ packages/surf/src/messages/index.ts | 1 + packages/surf/src/messages/nl-NL.json | 17 ++ .../surf/src/pages/cim/WfoSentEmailsPage.tsx | 10 + .../src/pages/cim/WfoServiceTicketsActive.tsx | 240 ++++++++++++++++++ .../pages/cim/WfoServiceTicketsComplete.tsx | 11 + .../pages/cim/WfoServiceTicketsPageLayout.tsx | 60 +++++ packages/surf/src/pages/cim/index.ts | 4 + packages/surf/src/pages/index.ts | 1 + packages/surf/src/types/index.ts | 1 + packages/surf/src/types/types.ts | 187 ++++++++++++++ packages/surf/tsconfig.build.json | 14 + packages/surf/tsconfig.json | 16 ++ 42 files changed, 1046 insertions(+), 6 deletions(-) create mode 100644 apps/wfo-ui-surf/pages/service-tickets/active.tsx create mode 100644 apps/wfo-ui-surf/pages/service-tickets/completed.tsx create mode 100644 packages/orchestrator-ui-components/src/components/WfoDateTime/index.ts create mode 100644 packages/orchestrator-ui-components/src/components/WfoInsyncIcon/index.ts create mode 100644 packages/surf/.storybook/main.js create mode 100644 packages/surf/.storybook/preview.js create mode 100644 packages/surf/CHANGELOG.md create mode 100644 packages/surf/eslintrc.js create mode 100644 packages/surf/jest.config.cjs create mode 100644 packages/surf/package.json create mode 100644 packages/surf/src/components/WfoServiceTicketList/index.ts create mode 100644 packages/surf/src/components/WfoServiceTicketList/mapGrapghQlCimResultToServiceTicketListItems.ts create mode 100644 packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts create mode 100644 packages/surf/src/components/index.ts create mode 100644 packages/surf/src/constants.ts create mode 100644 packages/surf/src/index.ts create mode 100644 packages/surf/src/messages/en-US.json create mode 100644 packages/surf/src/messages/getTranslationMessages.spec.ts create mode 100644 packages/surf/src/messages/getTranslationMessages.ts create mode 100644 packages/surf/src/messages/index.ts create mode 100644 packages/surf/src/messages/nl-NL.json create mode 100644 packages/surf/src/pages/cim/WfoSentEmailsPage.tsx create mode 100644 packages/surf/src/pages/cim/WfoServiceTicketsActive.tsx create mode 100644 packages/surf/src/pages/cim/WfoServiceTicketsComplete.tsx create mode 100644 packages/surf/src/pages/cim/WfoServiceTicketsPageLayout.tsx create mode 100644 packages/surf/src/pages/cim/index.ts create mode 100644 packages/surf/src/pages/index.ts create mode 100644 packages/surf/src/types/index.ts create mode 100644 packages/surf/src/types/types.ts create mode 100644 packages/surf/tsconfig.build.json create mode 100644 packages/surf/tsconfig.json diff --git a/apps/wfo-ui-surf/next.config.js b/apps/wfo-ui-surf/next.config.js index 110593f5f..115627f05 100644 --- a/apps/wfo-ui-surf/next.config.js +++ b/apps/wfo-ui-surf/next.config.js @@ -6,5 +6,8 @@ module.exports = { locales: ['en-US', 'nl-NL'], defaultLocale: 'en-US', }, - transpilePackages: ['@orchestrator-ui/orchestrator-ui-components'], + transpilePackages: [ + '@orchestrator-ui/orchestrator-ui-components', + '@orchestrator-ui/surf', + ], }; diff --git a/apps/wfo-ui-surf/package.json b/apps/wfo-ui-surf/package.json index 46c3b21c2..111a88312 100644 --- a/apps/wfo-ui-surf/package.json +++ b/apps/wfo-ui-surf/package.json @@ -18,6 +18,7 @@ "@emotion/react": "^11.11.1", "@graphql-typed-document-node/core": "3.2.0", "@orchestrator-ui/orchestrator-ui-components": "*", + "@orchestrator-ui/surf": "*", "graphql": "16.7.1", "graphql-request": "5.2.0", "moment": "^2.29.4", diff --git a/apps/wfo-ui-surf/pages/service-tickets/active.tsx b/apps/wfo-ui-surf/pages/service-tickets/active.tsx new file mode 100644 index 000000000..37c87eefa --- /dev/null +++ b/apps/wfo-ui-surf/pages/service-tickets/active.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import { WfoServiceTicketsActive } from '@orchestrator-ui/surf'; + +export const ActiveServiceTicketsPage = () => ; + +export default ActiveServiceTicketsPage; diff --git a/apps/wfo-ui-surf/pages/service-tickets/completed.tsx b/apps/wfo-ui-surf/pages/service-tickets/completed.tsx new file mode 100644 index 000000000..f36910c30 --- /dev/null +++ b/apps/wfo-ui-surf/pages/service-tickets/completed.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import { WfoServiceTicketsComplete } from '@orchestrator-ui/surf'; + +export const ServiceTicketsCompletePage = () => ; + +export default ServiceTicketsCompletePage; diff --git a/apps/wfo-ui-surf/translations/en-US.json b/apps/wfo-ui-surf/translations/en-US.json index 0967ef424..d75644afc 100644 --- a/apps/wfo-ui-surf/translations/en-US.json +++ b/apps/wfo-ui-surf/translations/en-US.json @@ -1 +1,17 @@ -{} +{ + "cim": { + "serviceTickets": { + "jiraTicketId": "Jira ticket", + "titleNl": "Title", + "processState": "State", + "startDate": "Start time", + "openedBy": "Opened by", + "createDate": "Created on", + "lastUpdateTime": "Updated on", + "tabs": { + "active": "Active", + "completed": "Completed" + } + } + } +} diff --git a/apps/wfo-ui-surf/translations/nl-NL.json b/apps/wfo-ui-surf/translations/nl-NL.json index 0967ef424..d75644afc 100644 --- a/apps/wfo-ui-surf/translations/nl-NL.json +++ b/apps/wfo-ui-surf/translations/nl-NL.json @@ -1 +1,17 @@ -{} +{ + "cim": { + "serviceTickets": { + "jiraTicketId": "Jira ticket", + "titleNl": "Title", + "processState": "State", + "startDate": "Start time", + "openedBy": "Opened by", + "createDate": "Created on", + "lastUpdateTime": "Updated on", + "tabs": { + "active": "Active", + "completed": "Completed" + } + } + } +} diff --git a/mkdocs/docs/adrs/0005-component-naming.md b/mkdocs/docs/adrs/0005-component-naming.md index 2f4bd4a3d..f895d9be0 100644 --- a/mkdocs/docs/adrs/0005-component-naming.md +++ b/mkdocs/docs/adrs/0005-component-naming.md @@ -7,7 +7,7 @@ Date: 2023-08-08 *Accepted* ## Decisions -To (practically) ensure components have unique names even when they are used in combination with components from other sources we have decided that all components that the @orchesrator-ui package exposes are prefixed with WFO. All complete pages that are exposed are prefixed with WFO and post fixed with Page +To (practically) ensure components have unique names even when they are used in combination with components from other sources we have decided that all components that the @orchesrator-ui package exposes are prefixed with Wfo. All complete pages that are exposed are prefixed with WFO and post fixed with Page ## Action items - Rename all exposed component in @orcestrator-ui packages diff --git a/packages/orchestrator-ui-components/src/components/WfoDateTime/index.ts b/packages/orchestrator-ui-components/src/components/WfoDateTime/index.ts new file mode 100644 index 000000000..665a63796 --- /dev/null +++ b/packages/orchestrator-ui-components/src/components/WfoDateTime/index.ts @@ -0,0 +1 @@ +export * from './WfoDateTime'; diff --git a/packages/orchestrator-ui-components/src/components/WfoInsyncIcon/index.ts b/packages/orchestrator-ui-components/src/components/WfoInsyncIcon/index.ts new file mode 100644 index 000000000..faf0b8a88 --- /dev/null +++ b/packages/orchestrator-ui-components/src/components/WfoInsyncIcon/index.ts @@ -0,0 +1 @@ +export * from './WfoInsyncIcon'; diff --git a/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx b/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx index 8b6bdde48..d38caeadf 100644 --- a/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx @@ -130,6 +130,35 @@ export const WfoSidebar: FC = ({ overrideMenuItems }) => { }, href: PATH_SETTINGS, }, + { + name: 'Service tickets', + id: '8', + onClick: () => { + // Note: Using a string literal instead of const, otherwise I'll need to add the surf package to orchestrator-ui-components. Maybe here we use an ENV var ? + router.push('/service-tickets/active'); + }, + items: [ + { + name: 'Active', + id: '8.1', + isSelected: router.pathname === '/service-tickets/active', + onClick: (e) => { + e.preventDefault(); + router.push('/service-tickets/active'); + }, + }, + { + name: 'Completed', + id: '8.2', + isSelected: + router.pathname === '/service-tickets/completed', + onClick: (e) => { + e.preventDefault(); + router.push('/service-tickets/completed'); + }, + }, + ], + }, ]; const defaultMenu: EuiSideNavItemType[] = [ diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx index de332c48d..748018acf 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx @@ -9,12 +9,14 @@ import type { WfoDataSearch, } from '../utils/columns'; import { + WFO_TABLE_COLOR_FIELD, WfoTableControlColumnConfig, WfoTableDataColumnConfig, } from '../utils/columns'; import { useOrchestratorTheme } from '../../../hooks'; import { getStyles } from './styles'; import { SortOrder } from '../../../types'; +import { EuiTableSortingType } from '@elastic/eui/src/components/basic_table/table_types'; export type WfoBasicTableColumns = { [Property in keyof T]: WfoTableDataColumnConfig & { @@ -37,6 +39,8 @@ export type WfoBasicTableProps = { onCriteriaChange?: (criteria: Criteria) => void; onUpdateDataSorting?: (updatedDataSorting: WfoDataSorting) => void; onDataSearch?: (updatedDataSearch: WfoDataSearch) => void; + sorting?: EuiTableSortingType; + color?: boolean; }; export const WfoBasicTable = ({ @@ -49,13 +53,17 @@ export const WfoBasicTable = ({ onCriteriaChange, onUpdateDataSorting, onDataSearch, + sorting, }: WfoBasicTableProps) => { const { theme } = useOrchestratorTheme(); - const { basicTableStyle } = getStyles(theme); + const { basicTableStyle, basicTableWithColorColumn } = getStyles(theme); + const styles = columns.hasOwnProperty(WFO_TABLE_COLOR_FIELD) + ? basicTableWithColorColumn + : basicTableStyle; return ( ({ onUpdateDataSorting, onDataSearch, )} + sorting={sorting} pagination={pagination} onChange={onCriteriaChange} loading={isLoading} diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/styles.ts b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/styles.ts index 54ec26523..b7e6d68ff 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/styles.ts +++ b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/styles.ts @@ -48,8 +48,29 @@ export const getStyles = (theme: EuiThemeComputed) => { cursor: isSortable ? 'pointer' : 'not-allowed', }); + const basicTableWithColorColumn = css( + { + '.euiTableHeaderCell': { + paddingBlock: 8, + paddingLeft: 8, + }, + '.euiTableCellContent:first-child': { + padding: 0, + border: 0, + }, + '.euiTableRowCell:first-child': { + padding: 0, + }, + '.euiTableSortIcon': { + display: 'none', + }, + }, + basicTableStyle, + ); + return { basicTableStyle, + basicTableWithColorColumn, headerCellContentStyle, headerCellPopoverHeaderStyle, headerCellPopoverHeaderTitleStyle, diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts b/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts index 0ad27dbc6..304d090e8 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts +++ b/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts @@ -66,3 +66,5 @@ export const getSortDirectionFromString = ( return undefined; } }; + +export const WFO_TABLE_COLOR_FIELD = 'color'; diff --git a/packages/orchestrator-ui-components/src/components/index.ts b/packages/orchestrator-ui-components/src/components/index.ts index 760320bda..4b83abbf4 100644 --- a/packages/orchestrator-ui-components/src/components/index.ts +++ b/packages/orchestrator-ui-components/src/components/index.ts @@ -14,3 +14,4 @@ export * from './WfoLoading'; export * from './WfoToastsList'; export * from './WfoForms'; export * from './WfoStartTaskButtonComboBox'; +export * from './WfoDateTime'; diff --git a/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts b/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts index b4647e19c..7b2985d15 100644 --- a/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts +++ b/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts @@ -88,3 +88,20 @@ export const useCacheNames = () => { getCacheNames(orchestratorApiBaseUrl), ); }; + +export const useQueryWithRest = ( + endpoint: string, + queryKey: string, + refetchInterval?: number, +) => { + const { orchestratorApiBaseUrl } = useContext(OrchestratorConfigContext); + + const fetchFromApi = async () => { + const response = await fetch(orchestratorApiBaseUrl + endpoint); + return await response.json(); + }; + + return useQuery([queryKey], fetchFromApi, { + refetchInterval, + }); +}; diff --git a/packages/surf/.storybook/main.js b/packages/surf/.storybook/main.js new file mode 100644 index 000000000..adc97d539 --- /dev/null +++ b/packages/surf/.storybook/main.js @@ -0,0 +1,28 @@ +import { join, dirname } from 'path'; + +/** + * This function is used to resolve the absolute path of a package. + * It is needed in projects that use Yarn PnP or are set up within a monorepo. + */ +function getAbsolutePath(value) { + return dirname(require.resolve(join(value, 'package.json'))); +} + +/** @type { import('@storybook/nextjs').StorybookConfig } */ +const config = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + addons: [ + getAbsolutePath('@storybook/addon-links'), + getAbsolutePath('@storybook/addon-essentials'), + getAbsolutePath('@storybook/addon-onboarding'), + getAbsolutePath('@storybook/addon-interactions'), + ], + framework: { + name: getAbsolutePath('@storybook/nextjs'), + options: {}, + }, + docs: { + autodocs: 'tag', + }, +}; +export default config; diff --git a/packages/surf/.storybook/preview.js b/packages/surf/.storybook/preview.js new file mode 100644 index 000000000..074832a12 --- /dev/null +++ b/packages/surf/.storybook/preview.js @@ -0,0 +1,14 @@ +/** @type { import('@storybook/react').Preview } */ +const preview = { + parameters: { + actions: { argTypesRegex: '^on[A-Z].*' }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + }, +}; + +export default preview; diff --git a/packages/surf/CHANGELOG.md b/packages/surf/CHANGELOG.md new file mode 100644 index 000000000..f4150f31f --- /dev/null +++ b/packages/surf/CHANGELOG.md @@ -0,0 +1,4 @@ +# @orchestrator-ui/surf + +## 0.1.0 + diff --git a/packages/surf/eslintrc.js b/packages/surf/eslintrc.js new file mode 100644 index 000000000..afa84f0b8 --- /dev/null +++ b/packages/surf/eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ['@orchestrator-ui/eslint-config-custom'], +}; diff --git a/packages/surf/jest.config.cjs b/packages/surf/jest.config.cjs new file mode 100644 index 000000000..ad618d123 --- /dev/null +++ b/packages/surf/jest.config.cjs @@ -0,0 +1,7 @@ +const base = require('@orchestrator-ui/jest-config/jest-base.config.js'); + +module.exports = { + ...base, + name: 'surf', + displayName: 'Surf Components Tests', +}; diff --git a/packages/surf/package.json b/packages/surf/package.json new file mode 100644 index 000000000..562d2a2ee --- /dev/null +++ b/packages/surf/package.json @@ -0,0 +1,71 @@ +{ + "name": "@orchestrator-ui/surf", + "private": true, + "version": "0.1.0", + "license": "MIT", + "scripts": { + "test": "jest --passWithNoTests", + "build": "tsup src/index.ts --format esm --dts --tsconfig tsconfig.build.json", + "tsc": "tsc --noEmit", + "lint": "eslint \"src/**/*.ts*\"", + "dev": "yarn build -- --watch", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build", + "reset": "rm -rf node_modules" + }, + "dependencies": { + "@orchestrator-ui/orchestrator-ui-components": "*", + "@graphql-typed-document-node/core": "3.2.0", + "axios": "^0.24.0", + "invariant": "^2.2.4", + "moment": "2.29.4", + "object-hash": "^2.1.1", + "use-query-params": "2.2.1", + "uniforms": "^3.8.1", + "uniforms-bridge-json-schema": "^3.8.1", + "uniforms-unstyled": "^3.8.1" + }, + "peerDependencies": { + "@elastic/eui": "^88.1.0", + "@emotion/css": "^11.11.2", + "@emotion/react": "^11.11.1", + "graphql-request": "5.2.0", + "next": "^13.4.1", + "next-intl": "2.19.0", + "next-query-params": "4.2.2", + "react": "^18.2.0", + "react-query": "3.39.3" + }, + "devDependencies": { + "@orchestrator-ui/eslint-config-custom": "*", + "@orchestrator-ui/jest-config": "*", + "@storybook/addon-essentials": "^7.2.1", + "@storybook/addon-interactions": "^7.2.1", + "@storybook/addon-links": "^7.2.1", + "@storybook/addon-onboarding": "^1.0.8", + "@storybook/blocks": "^7.2.1", + "@storybook/nextjs": "^7.2.1", + "@storybook/react": "^7.2.1", + "@storybook/testing-library": "^0.2.0", + "@testing-library/jest-dom": "^5.16.1", + "@testing-library/react": "^14.0.0", + "@testing-library/react-hooks": "^8.0.1", + "@testing-library/user-event": "^14.4.3", + "@types/invariant": "^2.2.33", + "@types/jest": "^27.4.0", + "@types/object-hash": "^2.1.0", + "esbuild": "^0.14.10", + "esbuild-jest": "^0.5.0", + "jest": "^27.4.7", + "jest-watch-typeahead": "^1.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "storybook": "^7.2.1", + "tsup": "^7.2.0", + "uniforms-bridge-simple-schema-2": "^3.8.1" + }, + "type": "module", + "main": "./dist/index.js", + "browser": "./dist/index.js", + "types": "./dist/index.d.ts" +} diff --git a/packages/surf/src/components/WfoServiceTicketList/index.ts b/packages/surf/src/components/WfoServiceTicketList/index.ts new file mode 100644 index 000000000..f617fc49e --- /dev/null +++ b/packages/surf/src/components/WfoServiceTicketList/index.ts @@ -0,0 +1,2 @@ +export * from './mapGrapghQlCimResultToServiceTicketListItems'; +export * from './subscriptionListTabs'; diff --git a/packages/surf/src/components/WfoServiceTicketList/mapGrapghQlCimResultToServiceTicketListItems.ts b/packages/surf/src/components/WfoServiceTicketList/mapGrapghQlCimResultToServiceTicketListItems.ts new file mode 100644 index 000000000..e2ae4ea72 --- /dev/null +++ b/packages/surf/src/components/WfoServiceTicketList/mapGrapghQlCimResultToServiceTicketListItems.ts @@ -0,0 +1,48 @@ +import { + parseDate, + Subscription, + SubscriptionsResult, +} from '@orchestrator-ui/orchestrator-ui-components'; + +export type SubscriptionListItem = Pick< + Subscription, + 'subscriptionId' | 'description' | 'status' | 'insync' | 'note' +> & { + startDate: Date | null; + endDate: Date | null; + productName: string; + tag: string | null; +}; + +export function mapGrapghQlCimResultToServiceTicketListItems( + graphqlResponse: SubscriptionsResult, +): SubscriptionListItem[] { + return graphqlResponse.subscriptions.page.map( + (subscription: Subscription) => { + const { + description, + insync, + product, + startDate, + endDate, + status, + subscriptionId, + note, + } = subscription; + + const { name: productName, tag } = product; + + return { + subscriptionId, + description, + status, + insync, + startDate: parseDate(startDate), + endDate: parseDate(endDate), + note, + productName, + tag, + }; + }, + ); +} diff --git a/packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts b/packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts new file mode 100644 index 000000000..fe99d21ef --- /dev/null +++ b/packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts @@ -0,0 +1,71 @@ +import { WfoFilterTab } from '@orchestrator-ui/orchestrator-ui-components'; +import { SubscriptionListItem } from './mapGrapghQlCimResultToServiceTicketListItems'; + +export enum WfoSubscriptionsTabType { + ACTIVE = 'ACTIVE', + TERMINATED = 'TERMINATED', + TRANSIENT = 'TRANSIENT', + ALL = 'ALL', +} + +export const defaultSubscriptionsTabs: WfoFilterTab< + WfoSubscriptionsTabType, + SubscriptionListItem +>[] = [ + { + id: WfoSubscriptionsTabType.ACTIVE, + translationKey: 'active', + alwaysOnFilters: [ + { + field: 'status', + value: 'active', + }, + ], + }, + { + id: WfoSubscriptionsTabType.TERMINATED, + translationKey: 'terminated', + alwaysOnFilters: [ + { + field: 'status', + value: 'terminated', + }, + ], + }, + { + id: WfoSubscriptionsTabType.TRANSIENT, + translationKey: 'transient', + alwaysOnFilters: [ + { + field: 'status', + value: 'initial-provisioning-migrating', + }, + ], + }, + { + id: WfoSubscriptionsTabType.ALL, + translationKey: 'all', + }, +]; + +export const getSubscriptionsTabTypeFromString = ( + tabId?: string, +): WfoSubscriptionsTabType | undefined => { + if (!tabId) { + return undefined; + } + + switch (tabId.toUpperCase()) { + case WfoSubscriptionsTabType.ACTIVE.toString(): + return WfoSubscriptionsTabType.ACTIVE; + case WfoSubscriptionsTabType.TERMINATED.toString(): + return WfoSubscriptionsTabType.TERMINATED; + case WfoSubscriptionsTabType.TRANSIENT.toString(): + return WfoSubscriptionsTabType.TRANSIENT; + case WfoSubscriptionsTabType.ALL.toString(): + return WfoSubscriptionsTabType.ALL; + + default: + return undefined; + } +}; diff --git a/packages/surf/src/components/index.ts b/packages/surf/src/components/index.ts new file mode 100644 index 000000000..ccd4c86e0 --- /dev/null +++ b/packages/surf/src/components/index.ts @@ -0,0 +1 @@ +export * from './WfoServiceTicketList'; diff --git a/packages/surf/src/constants.ts b/packages/surf/src/constants.ts new file mode 100644 index 000000000..45d1a12b4 --- /dev/null +++ b/packages/surf/src/constants.ts @@ -0,0 +1,4 @@ +export const PATH_SERVICE_TICKETS = '/service-tickets'; +export const CIM_TICKETS_ENDPOINT = '/surf/cim/tickets'; +export const METADATA_SERVICE_TICKETS_ACTIVE_TABLE_LOCAL_STORAGE_KEY = + 'serviceTicketsActiveTable'; diff --git a/packages/surf/src/index.ts b/packages/surf/src/index.ts new file mode 100644 index 000000000..9d412aac4 --- /dev/null +++ b/packages/surf/src/index.ts @@ -0,0 +1,2 @@ +export * from './components'; +export * from './pages'; diff --git a/packages/surf/src/messages/en-US.json b/packages/surf/src/messages/en-US.json new file mode 100644 index 000000000..d75644afc --- /dev/null +++ b/packages/surf/src/messages/en-US.json @@ -0,0 +1,17 @@ +{ + "cim": { + "serviceTickets": { + "jiraTicketId": "Jira ticket", + "titleNl": "Title", + "processState": "State", + "startDate": "Start time", + "openedBy": "Opened by", + "createDate": "Created on", + "lastUpdateTime": "Updated on", + "tabs": { + "active": "Active", + "completed": "Completed" + } + } + } +} diff --git a/packages/surf/src/messages/getTranslationMessages.spec.ts b/packages/surf/src/messages/getTranslationMessages.spec.ts new file mode 100644 index 000000000..706ff1629 --- /dev/null +++ b/packages/surf/src/messages/getTranslationMessages.spec.ts @@ -0,0 +1,51 @@ +import { getTranslationMessages } from './getTranslationMessages'; +import { Locale } from '../types'; +import enUS from './en-US.json'; +import nlNL from './nl-NL.json'; + +describe('getTransalationMessages', () => { + it('Returns nl-NL translation when nl-NL locale is requested', () => { + const translation = getTranslationMessages(Locale.nlNL); + expect(translation).toEqual(nlNL); + }); + + it('Returns en-US translation when en-US locale is requested', () => { + const translation = getTranslationMessages(Locale.enUS); + expect(translation).toEqual(enUS); + }); + + it('Returns en-US translation when no locale is requested', () => { + const translation = getTranslationMessages(undefined); + expect(translation).toEqual(enUS); + }); + it('Returns en-US translation unknown locale is requested', () => { + const translation = getTranslationMessages('UNKNOWN-LOCALE'); + expect(translation).toEqual(enUS); + }); + it('Returns custom translation when custom translations map array is provided', () => { + const customEN = { + metadata: { + product: { + name: 'CUSTOM-EN-NAME', + }, + }, + }; + + const customMap = new Map([[Locale.enUS, customEN]]); + const translation = getTranslationMessages(Locale.enUS, customMap); + expect(translation).toEqual(customEN); + }); + it('Returns en-Us translation if unknown locale is requested together with custom translations map', () => { + const customEN = { + metadata: { + product: { + name: 'CUSTOM-EN-NAME', + }, + }, + }; + + const customMap = new Map([[Locale.enUS, customEN]]); + const translation = getTranslationMessages('UNKNOWN-LOCALE', customMap); + expect(translation).toEqual(customEN); + }); +}); diff --git a/packages/surf/src/messages/getTranslationMessages.ts b/packages/surf/src/messages/getTranslationMessages.ts new file mode 100644 index 000000000..ab9c3142c --- /dev/null +++ b/packages/surf/src/messages/getTranslationMessages.ts @@ -0,0 +1,26 @@ +import { AbstractIntlMessages } from 'next-intl'; + +import { Locale } from '../types'; +import nlNL from './nl-NL.json'; +import enUS from './en-US.json'; + +export type TranslationMessagesMap = Map; + +const standardMessageMap: TranslationMessagesMap = new Map([ + [Locale.enUS, enUS], + [Locale.nlNL, nlNL], +]); + +export const getTranslationMessages = ( + locale: string | undefined, + messages: TranslationMessagesMap = standardMessageMap, +) => { + switch (locale) { + case Locale.enUS: + return messages.get(Locale.enUS); + case Locale.nlNL: + return messages.get(Locale.nlNL); + default: + return messages.get(Locale.enUS); + } +}; diff --git a/packages/surf/src/messages/index.ts b/packages/surf/src/messages/index.ts new file mode 100644 index 000000000..2ad41be5a --- /dev/null +++ b/packages/surf/src/messages/index.ts @@ -0,0 +1 @@ +export * from './getTranslationMessages'; diff --git a/packages/surf/src/messages/nl-NL.json b/packages/surf/src/messages/nl-NL.json new file mode 100644 index 000000000..d75644afc --- /dev/null +++ b/packages/surf/src/messages/nl-NL.json @@ -0,0 +1,17 @@ +{ + "cim": { + "serviceTickets": { + "jiraTicketId": "Jira ticket", + "titleNl": "Title", + "processState": "State", + "startDate": "Start time", + "openedBy": "Opened by", + "createDate": "Created on", + "lastUpdateTime": "Updated on", + "tabs": { + "active": "Active", + "completed": "Completed" + } + } + } +} diff --git a/packages/surf/src/pages/cim/WfoSentEmailsPage.tsx b/packages/surf/src/pages/cim/WfoSentEmailsPage.tsx new file mode 100644 index 000000000..d1dcb9e66 --- /dev/null +++ b/packages/surf/src/pages/cim/WfoSentEmailsPage.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { WfoServiceTicketsPageLayout } from './WfoServiceTicketsPageLayout'; + +export const WfoSentEmailsPage = () => { + return ( + +

SENT EMAILS PAGE

+
+ ); +}; diff --git a/packages/surf/src/pages/cim/WfoServiceTicketsActive.tsx b/packages/surf/src/pages/cim/WfoServiceTicketsActive.tsx new file mode 100644 index 000000000..9c03510a2 --- /dev/null +++ b/packages/surf/src/pages/cim/WfoServiceTicketsActive.tsx @@ -0,0 +1,240 @@ +import React, { useState } from 'react'; +import { + Comparators, + Criteria, + EuiFlexGroup, + EuiFlexItem, + EuiTableSortingType, +} from '@elastic/eui'; +import { + ServiceTicketDefinition, + ServiceTicketProcessState, +} from '../../types'; +import { useTranslations } from 'next-intl'; +import { + getSortDirectionFromString, + parseDateToLocaleDateTimeString, + parseIsoString, + SortOrder, + useOrchestratorTheme, + useQueryWithRest, + WFO_TABLE_COLOR_FIELD, + WfoBasicTable, + WfoDataSorting, + WfoDateTime, + WfoTableColumns, +} from '@orchestrator-ui/orchestrator-ui-components'; +import { CIM_TICKETS_ENDPOINT } from '../../constants'; +import { WfoServiceTicketsPageLayout } from './WfoServiceTicketsPageLayout'; + +const SERVICE_TICKET_FIELD_JIRA_ID: keyof ServiceTicketDefinition = + 'jira_ticket_id'; +const SERVICE_TICKET_FIELD_TITLE: keyof ServiceTicketDefinition = 'title_nl'; +const SERVICE_TICKET_FIELD_PROCESS_STATE: keyof ServiceTicketDefinition = + 'process_state'; +const SERVICE_TICKET_FIELD_OPENED_BY: keyof ServiceTicketDefinition = + 'opened_by'; +const SERVICE_TICKET_FIELD_START_DATE: keyof ServiceTicketDefinition = + 'start_date'; +const SERVICE_TICKET_FIELD_CREATE_DATE: keyof ServiceTicketDefinition = + 'create_date'; +const SERVICE_TICKET_FIELD_LAST_UPDATE: keyof ServiceTicketDefinition = + 'last_update_time'; + +const { NEW, OPEN, OPEN_RELATED, OPEN_ACCEPTED, UPDATED, ABORTED, CLOSED } = + ServiceTicketProcessState; + +export const WfoServiceTicketsActive = () => { + const [pageIndex, setPageIndex] = useState(0); + const [pageSize, setPageSize] = useState(5); + const [dataSorting, setDataSorting] = useState< + WfoDataSorting + >({ + field: SERVICE_TICKET_FIELD_LAST_UPDATE, + sortOrder: SortOrder.DESC, + }); + const t = useTranslations('cim.serviceTickets'); + const { data, isFetching } = useQueryWithRest( + CIM_TICKETS_ENDPOINT, + 'serviceTickets', + ); + const { theme } = useOrchestratorTheme(); + + const mapStateToColor = (state: ServiceTicketProcessState) => { + switch (state) { + case OPEN || NEW: + return theme.colors.success; + case OPEN_ACCEPTED || OPEN_RELATED: + return theme.colors.warning; + case UPDATED: + return theme.colors.primary; + case CLOSED || ABORTED: + return theme.colors.lightShade; + default: + return theme.colors.emptyShade; + } + }; + + const tableColumns: WfoTableColumns = { + color: { + field: WFO_TABLE_COLOR_FIELD, + name: '', + width: '1', + render: (value, object) => ( + + ), + sortable: true, + }, + jira_ticket_id: { + field: SERVICE_TICKET_FIELD_JIRA_ID, + name: t('jiraTicketId'), + width: '100', + //Todo: Fix styling and add color according to State + render: (value) => ( + + {value} + + ), + sortable: true, + }, + title_nl: { + field: SERVICE_TICKET_FIELD_TITLE, + name: t('titleNl'), + width: '300', + }, + process_state: { + field: SERVICE_TICKET_FIELD_PROCESS_STATE, + name: t('processState'), + width: '120', + }, + opened_by: { + field: SERVICE_TICKET_FIELD_OPENED_BY, + name: t('openedBy'), + width: '180', + }, + start_date: { + field: SERVICE_TICKET_FIELD_START_DATE, + name: t('startDate'), + width: '150', + render: (date) => , + renderDetails: parseIsoString(parseDateToLocaleDateTimeString), + clipboardText: parseIsoString(parseDateToLocaleDateTimeString), + }, + create_date: { + field: SERVICE_TICKET_FIELD_CREATE_DATE, + name: t('createDate'), + width: '150', + render: (date: string) => ( + {new Date(date).toLocaleDateString()} + ), + }, + last_update_time: { + field: SERVICE_TICKET_FIELD_LAST_UPDATE, + name: t('lastUpdateTime'), + width: '150', + render: (date: string) => ( + {new Date(date).toLocaleString()} + ), + }, + }; + + const onCriteriaChange = ({ + page, + sort, + }: Criteria) => { + if (page) { + const { index: pageIndex, size: pageSize } = page; + setPageIndex(pageIndex); + setPageSize(pageSize); + } + if (sort) { + const { field: sortField, direction: sortDirection } = sort; + const sortOrder = getSortDirectionFromString( + sortDirection, + ) as SortOrder; + setDataSorting({ + field: sortField, + sortOrder: sortOrder, + }); + } + }; + + // Manually handle sorting and pagination of data + const findServiceTickets = ( + serviceTickets: ServiceTicketDefinition[], + pageIndex: number, + pageSize: number, + sortField: keyof ServiceTicketDefinition, + sortDirection: 'asc' | 'desc', + ) => { + let items; + if (sortField) { + items = serviceTickets + .slice(0) + .sort( + Comparators.property( + sortField, + Comparators.default(sortDirection), + ), + ); + } else { + items = serviceTickets; + } + let pageOfItems; + if (!pageIndex && !pageSize) { + pageOfItems = items; + } else { + const startIndex = pageIndex * pageSize; + pageOfItems = items.slice( + startIndex, + Math.min(startIndex + pageSize, serviceTickets.length), + ); + } + return { + pageOfItems, + totalItemCount: serviceTickets.length, + }; + }; + + const { pageOfItems, totalItemCount } = findServiceTickets( + data ? data : [], + pageIndex, + pageSize, + dataSorting.field, + dataSorting.sortOrder.toLowerCase() as 'asc' | 'desc', + ); + const pagination = { + pageIndex: pageIndex, + pageSize: pageSize, + totalItemCount: totalItemCount, + pageSizeOptions: [5, 10, 20], + }; + const sorting: EuiTableSortingType = { + sort: { + field: dataSorting.field, + direction: dataSorting.sortOrder.toLowerCase() as 'asc' | 'desc', + }, + enableAllColumns: true, + readOnly: false, + }; + + return ( + + + + ); +}; diff --git a/packages/surf/src/pages/cim/WfoServiceTicketsComplete.tsx b/packages/surf/src/pages/cim/WfoServiceTicketsComplete.tsx new file mode 100644 index 000000000..73cbcd112 --- /dev/null +++ b/packages/surf/src/pages/cim/WfoServiceTicketsComplete.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +import { WfoServiceTicketsPageLayout } from './WfoServiceTicketsPageLayout'; + +export const WfoServiceTicketsComplete = () => { + return ( + +

Complete

+
+ ); +}; diff --git a/packages/surf/src/pages/cim/WfoServiceTicketsPageLayout.tsx b/packages/surf/src/pages/cim/WfoServiceTicketsPageLayout.tsx new file mode 100644 index 000000000..b0150653e --- /dev/null +++ b/packages/surf/src/pages/cim/WfoServiceTicketsPageLayout.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import type { ReactNode } from 'react'; +import { EuiSpacer, EuiPageHeader, EuiTab, EuiTabs } from '@elastic/eui'; +import { useRouter } from 'next/router'; +import { useTranslations } from 'next-intl'; + +interface MetadataLayoutProps { + children: ReactNode; + tabs?: MetaDataTab[]; +} + +export interface MetaDataTab { + id: number; + translationKey: string; + path: string; +} + +const metaDataTabs: MetaDataTab[] = [ + { + id: 1, + translationKey: 'active', + path: '/service-tickets/active', + }, + { + id: 2, + translationKey: 'completed', + path: '/service-tickets/completed', + }, +]; + +export const WfoServiceTicketsPageLayout = ({ + children, + tabs = metaDataTabs, +}: MetadataLayoutProps) => { + const router = useRouter(); + const t = useTranslations('cim.serviceTickets.tabs'); + const currentPath = router.pathname; + + return ( + <> + + + + + + {tabs.map(({ id, translationKey: name, path }) => ( + router.push(path)} + > + {t(name)} + + ))} + + + {children} + + ); +}; diff --git a/packages/surf/src/pages/cim/index.ts b/packages/surf/src/pages/cim/index.ts new file mode 100644 index 000000000..141ac3c45 --- /dev/null +++ b/packages/surf/src/pages/cim/index.ts @@ -0,0 +1,4 @@ +export * from './WfoServiceTicketsActive'; +export * from './WfoServiceTicketsComplete'; +export * from './WfoSentEmailsPage'; +export * from './WfoServiceTicketsPageLayout'; diff --git a/packages/surf/src/pages/index.ts b/packages/surf/src/pages/index.ts new file mode 100644 index 000000000..7c7325db3 --- /dev/null +++ b/packages/surf/src/pages/index.ts @@ -0,0 +1 @@ +export * from './cim'; diff --git a/packages/surf/src/types/index.ts b/packages/surf/src/types/index.ts new file mode 100644 index 000000000..fcb073fef --- /dev/null +++ b/packages/surf/src/types/index.ts @@ -0,0 +1 @@ +export * from './types'; diff --git a/packages/surf/src/types/types.ts b/packages/surf/src/types/types.ts new file mode 100644 index 000000000..77f749d77 --- /dev/null +++ b/packages/surf/src/types/types.ts @@ -0,0 +1,187 @@ +/** CIM */ + +export interface CreateServiceTicketPayload { + ims_pw_id: string; + jira_ticket_id: string; + title_nl: string; + type: ServiceTicketType; +} + +export interface OpenServiceTicketPayload { + cim_ticket_id: string; + title_nl: string; + description_nl: string; + title_en: string; + description_en: string; + mail_subject: string; +} + +export interface UpdateServiceTicketPayload extends OpenServiceTicketPayload { + start_date?: string; + end_date?: string; +} + +export interface CloseServiceTicketPayload extends OpenServiceTicketPayload { + end_date?: string; +} + +export enum ServiceTicketProcessState { + NEW = 'new', + OPEN = 'open', + OPEN_RELATED = 'open_related', + OPEN_ACCEPTED = 'open_accepted', + UPDATED = 'updated', + ABORTED = 'aborted', + CLOSED = 'closed', +} + +export enum ServiceTicketTransition { + RELATING = 'relating', + ACCEPTING = 'accepting', + ABORTING = 'aborting', + OPENING = 'opening', + OPEN_AND_CLOSE = 'open_and_close', + UPDATING = 'updating', + CLOSING = 'closing', + CLEANING = 'cleaning', +} + +export type ServiceTicketDefinition = { + color?: string; + jira_ticket_id: string; + opened_by: string; + process_state: ServiceTicketProcessState; + start_date: string; + create_date: string; + last_update_time: string; + title_nl: string; +}; + +export enum ServiceTicketLogType { + OPEN = 'open', + UPDATE = 'update', + CLOSE = 'close', +} + +export interface ServiceTicketLog { + entry_time: string; + update_nl: string; + update_en: string; + log_type: ServiceTicketLogType; + logged_by: string; + transition: ServiceTicketTransition; + completed: boolean; +} + +export enum ServiceTicketImpactedObjectImpact { + DOWN = 'down', + NO_IMPACT = 'no_impact', + REDUCED_REDUNDANCY = 'reduced_redundancy', + RESILIENCE_LOSS = 'resilience_loss', +} + +export interface ServiceTicketImpactedIMSCircuit { + ims_circuit_id: number; + ims_circuit_name: string; + impact: ServiceTicketImpactedObjectImpact; + extra_information?: string; +} + +export interface ServiceTicketCustomer { + customer_id: string; + customer_name: string; + customer_abbrev: string; +} +export interface ServiceTicketBackgroundJobCount { + number_of_active_jobs: number; +} + +export interface ServiceTicketContact { + name: string; + email: string; + // Todo: add phone? +} + +export interface ServiceTicketRelatedCustomer { + customer: ServiceTicketCustomer; + customer_subscription_description?: string; + contacts: ServiceTicketContact[]; +} + +export interface ServiceTicketImpactedObject { + impact_override: ServiceTicketImpactedObjectImpact; + subscription_id: string | null; + product_type: string; + logged_by: string; + ims_circuits: ServiceTicketImpactedIMSCircuit[]; + owner_customer: ServiceTicketCustomer; + subscription_description: string; + owner_customer_description?: string; + owner_customer_contacts: ServiceTicketContact[]; + related_customers: ServiceTicketRelatedCustomer[]; +} + +export enum ServiceTicketType { + PLANNED_WORK = 'planned work', + INCIDENT = 'incident', +} + +export interface BackgroundJobLog { + message: string; + customer_id?: string; + subscription_id?: string; + entry_time: string; + process_state: string; + context: object; +} + +export interface Email { + customer: ServiceTicketCustomer; + message: string; + to: ServiceTicketContact[]; + cc: ServiceTicketContact[]; + bcc: ServiceTicketContact[]; + language: string; +} + +export interface EmailLog { + entry_time: string; + log_type: string; + // emails: any; +} + +export interface ServiceTicketWithDetails extends ServiceTicketDefinition { + // transitioning_state: any; + end_date: string; + last_update_time: string; + type: ServiceTicketType; + logs: ServiceTicketLog[]; + impacted_objects: ServiceTicketImpactedObject[]; + background_logs: BackgroundJobLog[]; + email_logs: EmailLog[]; +} + +export interface ImsInfo { + impact: ServiceTicketImpactedObjectImpact; + ims_circuit_id: number; + ims_circuit_name: string; + extra_information?: string; +} + +export interface ImpactedObject { + id: string; + customer: string; + impact: ServiceTicketImpactedObjectImpact; + type: string; + subscription: string; + impact_override?: ServiceTicketImpactedObjectImpact; + subscription_id: string | null; + ims_info: ImsInfo[]; + owner_customer_contacts: ServiceTicketContact[]; + related_customers: ServiceTicketRelatedCustomer[]; +} + +export enum Locale { + enUS = 'en-Us', + nlNL = 'nl-NL', +} diff --git a/packages/surf/tsconfig.build.json b/packages/surf/tsconfig.build.json new file mode 100644 index 000000000..9b43deee6 --- /dev/null +++ b/packages/surf/tsconfig.build.json @@ -0,0 +1,14 @@ +{ + "extends": "@orchestrator-ui/tsconfig/base.json", + "compilerOptions": { + "strictNullChecks": true + }, + "include": ["**/*.ts", "**/*.tsx"], + "exclude": [ + "node_modules", + "**/*.stories.ts", + "**/*.stories.js", + "**/*.stories.jsx", + "**/*.stories.tsx" + ] +} diff --git a/packages/surf/tsconfig.json b/packages/surf/tsconfig.json new file mode 100644 index 000000000..44bca3a11 --- /dev/null +++ b/packages/surf/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "@orchestrator-ui/tsconfig/base.json", + "compilerOptions": { + "strictNullChecks": true, + "rootDir": "./src", + "outDir": "./dist" + }, + "include": ["./src/**/*.ts", "./src/**/*.tsx"], + "exclude": [ + "node_modules", + "**/*.stories.ts", + "**/*.stories.js", + "**/*.stories.jsx", + "**/*.stories.tsx" + ] +} From 578278d341091a1e4d98c7288b869767e862244f Mon Sep 17 00:00:00 2001 From: Georgi Manev Date: Mon, 30 Oct 2023 17:08:00 +0100 Subject: [PATCH 02/13] Changed tab structure for service tickets page wip --- .../{completed.tsx => [serviceTicketId].tsx} | 4 +- .../service-tickets/{active.tsx => index.tsx} | 4 +- .../components/WfoServiceTicketList/index.ts | 1 - ...apghQlCimResultToServiceTicketListItems.ts | 48 -------- .../subscriptionListTabs.ts | 10 +- packages/surf/src/constants.ts | 3 + .../surf/src/pages/cim/WfoSentEmailsPage.tsx | 10 -- .../pages/cim/WfoServiceTicketListPage.tsx | 106 ++++++++++++++++++ ...icketsActive.tsx => WfoServiceTickets.tsx} | 23 ++-- .../pages/cim/WfoServiceTicketsComplete.tsx | 11 -- .../pages/cim/WfoServiceTicketsPageLayout.tsx | 60 ---------- .../getServiceTicketListTabTypeFromString.ts | 19 ++++ packages/surf/src/pages/cim/index.ts | 6 +- packages/surf/src/pages/cim/tabConfig.ts | 48 ++++++++ packages/surf/src/types/types.ts | 20 ++++ 15 files changed, 217 insertions(+), 156 deletions(-) rename apps/wfo-ui-surf/pages/service-tickets/{completed.tsx => [serviceTicketId].tsx} (62%) rename apps/wfo-ui-surf/pages/service-tickets/{active.tsx => index.tsx} (63%) delete mode 100644 packages/surf/src/components/WfoServiceTicketList/mapGrapghQlCimResultToServiceTicketListItems.ts delete mode 100644 packages/surf/src/pages/cim/WfoSentEmailsPage.tsx create mode 100644 packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx rename packages/surf/src/pages/cim/{WfoServiceTicketsActive.tsx => WfoServiceTickets.tsx} (93%) delete mode 100644 packages/surf/src/pages/cim/WfoServiceTicketsComplete.tsx delete mode 100644 packages/surf/src/pages/cim/WfoServiceTicketsPageLayout.tsx create mode 100644 packages/surf/src/pages/cim/getServiceTicketListTabTypeFromString.ts create mode 100644 packages/surf/src/pages/cim/tabConfig.ts diff --git a/apps/wfo-ui-surf/pages/service-tickets/completed.tsx b/apps/wfo-ui-surf/pages/service-tickets/[serviceTicketId].tsx similarity index 62% rename from apps/wfo-ui-surf/pages/service-tickets/completed.tsx rename to apps/wfo-ui-surf/pages/service-tickets/[serviceTicketId].tsx index f36910c30..486685885 100644 --- a/apps/wfo-ui-surf/pages/service-tickets/completed.tsx +++ b/apps/wfo-ui-surf/pages/service-tickets/[serviceTicketId].tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { WfoServiceTicketsComplete } from '@orchestrator-ui/surf'; +import { WfoServiceTickets } from '@orchestrator-ui/surf'; -export const ServiceTicketsCompletePage = () => ; +export const ServiceTicketsCompletePage = () => ; export default ServiceTicketsCompletePage; diff --git a/apps/wfo-ui-surf/pages/service-tickets/active.tsx b/apps/wfo-ui-surf/pages/service-tickets/index.tsx similarity index 63% rename from apps/wfo-ui-surf/pages/service-tickets/active.tsx rename to apps/wfo-ui-surf/pages/service-tickets/index.tsx index 37c87eefa..19d4b78d7 100644 --- a/apps/wfo-ui-surf/pages/service-tickets/active.tsx +++ b/apps/wfo-ui-surf/pages/service-tickets/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { WfoServiceTicketsActive } from '@orchestrator-ui/surf'; +import { WfoServiceTickets } from '@orchestrator-ui/surf'; -export const ActiveServiceTicketsPage = () => ; +export const ActiveServiceTicketsPage = () => ; export default ActiveServiceTicketsPage; diff --git a/packages/surf/src/components/WfoServiceTicketList/index.ts b/packages/surf/src/components/WfoServiceTicketList/index.ts index f617fc49e..b91069276 100644 --- a/packages/surf/src/components/WfoServiceTicketList/index.ts +++ b/packages/surf/src/components/WfoServiceTicketList/index.ts @@ -1,2 +1 @@ -export * from './mapGrapghQlCimResultToServiceTicketListItems'; export * from './subscriptionListTabs'; diff --git a/packages/surf/src/components/WfoServiceTicketList/mapGrapghQlCimResultToServiceTicketListItems.ts b/packages/surf/src/components/WfoServiceTicketList/mapGrapghQlCimResultToServiceTicketListItems.ts deleted file mode 100644 index e2ae4ea72..000000000 --- a/packages/surf/src/components/WfoServiceTicketList/mapGrapghQlCimResultToServiceTicketListItems.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { - parseDate, - Subscription, - SubscriptionsResult, -} from '@orchestrator-ui/orchestrator-ui-components'; - -export type SubscriptionListItem = Pick< - Subscription, - 'subscriptionId' | 'description' | 'status' | 'insync' | 'note' -> & { - startDate: Date | null; - endDate: Date | null; - productName: string; - tag: string | null; -}; - -export function mapGrapghQlCimResultToServiceTicketListItems( - graphqlResponse: SubscriptionsResult, -): SubscriptionListItem[] { - return graphqlResponse.subscriptions.page.map( - (subscription: Subscription) => { - const { - description, - insync, - product, - startDate, - endDate, - status, - subscriptionId, - note, - } = subscription; - - const { name: productName, tag } = product; - - return { - subscriptionId, - description, - status, - insync, - startDate: parseDate(startDate), - endDate: parseDate(endDate), - note, - productName, - tag, - }; - }, - ); -} diff --git a/packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts b/packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts index fe99d21ef..794bd0a69 100644 --- a/packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts +++ b/packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts @@ -1,5 +1,5 @@ import { WfoFilterTab } from '@orchestrator-ui/orchestrator-ui-components'; -import { SubscriptionListItem } from './mapGrapghQlCimResultToServiceTicketListItems'; +import { ServiceTicketDefinition } from '../../types'; export enum WfoSubscriptionsTabType { ACTIVE = 'ACTIVE', @@ -10,14 +10,14 @@ export enum WfoSubscriptionsTabType { export const defaultSubscriptionsTabs: WfoFilterTab< WfoSubscriptionsTabType, - SubscriptionListItem + ServiceTicketDefinition >[] = [ { id: WfoSubscriptionsTabType.ACTIVE, translationKey: 'active', alwaysOnFilters: [ { - field: 'status', + field: 'process_state', value: 'active', }, ], @@ -27,7 +27,7 @@ export const defaultSubscriptionsTabs: WfoFilterTab< translationKey: 'terminated', alwaysOnFilters: [ { - field: 'status', + field: 'process_state', value: 'terminated', }, ], @@ -37,7 +37,7 @@ export const defaultSubscriptionsTabs: WfoFilterTab< translationKey: 'transient', alwaysOnFilters: [ { - field: 'status', + field: 'process_state', value: 'initial-provisioning-migrating', }, ], diff --git a/packages/surf/src/constants.ts b/packages/surf/src/constants.ts index 45d1a12b4..1e47dfe95 100644 --- a/packages/surf/src/constants.ts +++ b/packages/surf/src/constants.ts @@ -2,3 +2,6 @@ export const PATH_SERVICE_TICKETS = '/service-tickets'; export const CIM_TICKETS_ENDPOINT = '/surf/cim/tickets'; export const METADATA_SERVICE_TICKETS_ACTIVE_TABLE_LOCAL_STORAGE_KEY = 'serviceTicketsActiveTable'; +export const ACTIVE_TICKETS_TABLE_LOCAL_STORAGE_KEY = 'activeTicketsTable'; +export const COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY = + 'completedTicketsTable'; diff --git a/packages/surf/src/pages/cim/WfoSentEmailsPage.tsx b/packages/surf/src/pages/cim/WfoSentEmailsPage.tsx deleted file mode 100644 index d1dcb9e66..000000000 --- a/packages/surf/src/pages/cim/WfoSentEmailsPage.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import { WfoServiceTicketsPageLayout } from './WfoServiceTicketsPageLayout'; - -export const WfoSentEmailsPage = () => { - return ( - -

SENT EMAILS PAGE

-
- ); -}; diff --git a/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx b/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx new file mode 100644 index 000000000..d75b5196f --- /dev/null +++ b/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx @@ -0,0 +1,106 @@ +import React, { useState, useEffect } from 'react'; +import { StringParam, useQueryParam, withDefault } from 'use-query-params'; +import { + DEFAULT_PAGE_SIZE, + SortOrder, + StoredTableConfig, + useDataDisplayParams, + useStoredTableConfig, + WfoFilterTabs, + WfoProcessListTabType, +} from '@orchestrator-ui/orchestrator-ui-components'; +import { ServiceTicketDefinition } from '../../types'; +import { + ACTIVE_TICKETS_TABLE_LOCAL_STORAGE_KEY, + COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY, +} from '../../constants'; +import { useRouter } from 'next/router'; +import { getServiceTicketListTabTypeFromString } from './getServiceTicketListTabTypeFromString'; +import { defaultServiceTicketsListTabs } from './tabConfig'; +import { EuiSpacer, EuiPageHeader } from '@elastic/eui'; +import { WfoServiceTickets } from './WfoServiceTickets'; + +export const WfoServiceTicketListPage = () => { + const router = useRouter(); + + const [activeTab, setActiveTab] = useQueryParam( + 'activeTab', + withDefault(StringParam, WfoProcessListTabType.ACTIVE), + ); + + const [tableDefaults, setTableDefaults] = + useState>(); + + const selectedServiceTicketListTab = + getServiceTicketListTabTypeFromString(activeTab); + + const localStorageKey = + selectedServiceTicketListTab === WfoProcessListTabType.ACTIVE + ? ACTIVE_TICKETS_TABLE_LOCAL_STORAGE_KEY + : COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY; + + const getStoredTableConfig = + useStoredTableConfig(localStorageKey); + + useEffect(() => { + const storedConfig = getStoredTableConfig(); + + if (storedConfig) { + setTableDefaults(storedConfig); + } + }, [getStoredTableConfig]); + + const { dataDisplayParams, setDataDisplayParam } = + useDataDisplayParams({ + // TODO: Improvement: A default pageSize value is set to avoid a graphql error when the query is executed + // the fist time before the useEffect has populated the tableDefaults. Better is to create a way for + // the query to wait for the values to be available + // https://github.com/workfloworchestrator/orchestrator-ui/issues/261 + pageSize: tableDefaults?.selectedPageSize || DEFAULT_PAGE_SIZE, + sortBy: { + field: 'last_update_time', + order: SortOrder.DESC, + }, + }); + + const handleChangeServiceTicketListTab = ( + updatedServiceTicketListTab: WfoProcessListTabType, + ) => { + setActiveTab(updatedServiceTicketListTab); + setDataDisplayParam('pageIndex', 0); + }; + + const alwaysOnFilters = defaultServiceTicketsListTabs.find( + ({ id }) => id === selectedServiceTicketListTab, + )?.alwaysOnFilters; + + if (!selectedServiceTicketListTab) { + router.replace('/processes'); + return null; + } + + return ( + <> + + + + + + + + + + + ); +}; diff --git a/packages/surf/src/pages/cim/WfoServiceTicketsActive.tsx b/packages/surf/src/pages/cim/WfoServiceTickets.tsx similarity index 93% rename from packages/surf/src/pages/cim/WfoServiceTicketsActive.tsx rename to packages/surf/src/pages/cim/WfoServiceTickets.tsx index 9c03510a2..cc835799a 100644 --- a/packages/surf/src/pages/cim/WfoServiceTicketsActive.tsx +++ b/packages/surf/src/pages/cim/WfoServiceTickets.tsx @@ -25,7 +25,6 @@ import { WfoTableColumns, } from '@orchestrator-ui/orchestrator-ui-components'; import { CIM_TICKETS_ENDPOINT } from '../../constants'; -import { WfoServiceTicketsPageLayout } from './WfoServiceTicketsPageLayout'; const SERVICE_TICKET_FIELD_JIRA_ID: keyof ServiceTicketDefinition = 'jira_ticket_id'; @@ -44,7 +43,7 @@ const SERVICE_TICKET_FIELD_LAST_UPDATE: keyof ServiceTicketDefinition = const { NEW, OPEN, OPEN_RELATED, OPEN_ACCEPTED, UPDATED, ABORTED, CLOSED } = ServiceTicketProcessState; -export const WfoServiceTicketsActive = () => { +export const WfoServiceTickets = () => { const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(5); const [dataSorting, setDataSorting] = useState< @@ -225,16 +224,14 @@ export const WfoServiceTicketsActive = () => { }; return ( - - - + ); }; diff --git a/packages/surf/src/pages/cim/WfoServiceTicketsComplete.tsx b/packages/surf/src/pages/cim/WfoServiceTicketsComplete.tsx deleted file mode 100644 index 73cbcd112..000000000 --- a/packages/surf/src/pages/cim/WfoServiceTicketsComplete.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; - -import { WfoServiceTicketsPageLayout } from './WfoServiceTicketsPageLayout'; - -export const WfoServiceTicketsComplete = () => { - return ( - -

Complete

-
- ); -}; diff --git a/packages/surf/src/pages/cim/WfoServiceTicketsPageLayout.tsx b/packages/surf/src/pages/cim/WfoServiceTicketsPageLayout.tsx deleted file mode 100644 index b0150653e..000000000 --- a/packages/surf/src/pages/cim/WfoServiceTicketsPageLayout.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react'; -import type { ReactNode } from 'react'; -import { EuiSpacer, EuiPageHeader, EuiTab, EuiTabs } from '@elastic/eui'; -import { useRouter } from 'next/router'; -import { useTranslations } from 'next-intl'; - -interface MetadataLayoutProps { - children: ReactNode; - tabs?: MetaDataTab[]; -} - -export interface MetaDataTab { - id: number; - translationKey: string; - path: string; -} - -const metaDataTabs: MetaDataTab[] = [ - { - id: 1, - translationKey: 'active', - path: '/service-tickets/active', - }, - { - id: 2, - translationKey: 'completed', - path: '/service-tickets/completed', - }, -]; - -export const WfoServiceTicketsPageLayout = ({ - children, - tabs = metaDataTabs, -}: MetadataLayoutProps) => { - const router = useRouter(); - const t = useTranslations('cim.serviceTickets.tabs'); - const currentPath = router.pathname; - - return ( - <> - - - - - - {tabs.map(({ id, translationKey: name, path }) => ( - router.push(path)} - > - {t(name)} - - ))} - - - {children} - - ); -}; diff --git a/packages/surf/src/pages/cim/getServiceTicketListTabTypeFromString.ts b/packages/surf/src/pages/cim/getServiceTicketListTabTypeFromString.ts new file mode 100644 index 000000000..fa0078564 --- /dev/null +++ b/packages/surf/src/pages/cim/getServiceTicketListTabTypeFromString.ts @@ -0,0 +1,19 @@ +import { WfoProcessListTabType } from '@orchestrator-ui/orchestrator-ui-components'; + +export const getServiceTicketListTabTypeFromString = ( + tabId?: string, +): WfoProcessListTabType | undefined => { + if (!tabId) { + return undefined; + } + + switch (tabId.toUpperCase()) { + case WfoProcessListTabType.ACTIVE.toString(): + return WfoProcessListTabType.ACTIVE; + case WfoProcessListTabType.COMPLETED.toString(): + return WfoProcessListTabType.COMPLETED; + + default: + return undefined; + } +}; diff --git a/packages/surf/src/pages/cim/index.ts b/packages/surf/src/pages/cim/index.ts index 141ac3c45..20fff549b 100644 --- a/packages/surf/src/pages/cim/index.ts +++ b/packages/surf/src/pages/cim/index.ts @@ -1,4 +1,2 @@ -export * from './WfoServiceTicketsActive'; -export * from './WfoServiceTicketsComplete'; -export * from './WfoSentEmailsPage'; -export * from './WfoServiceTicketsPageLayout'; +export * from './WfoServiceTickets'; +export * from './WfoServiceTicketListPage'; diff --git a/packages/surf/src/pages/cim/tabConfig.ts b/packages/surf/src/pages/cim/tabConfig.ts new file mode 100644 index 000000000..7f39d19a6 --- /dev/null +++ b/packages/surf/src/pages/cim/tabConfig.ts @@ -0,0 +1,48 @@ +import { + WfoFilterTab, + WfoProcessListTabType, +} from '@orchestrator-ui/orchestrator-ui-components'; +import { ServiceTicketDefinition } from '../../types'; +export const defaultServiceTicketsListTabs: WfoFilterTab< + WfoProcessListTabType, + ServiceTicketDefinition +>[] = [ + { + id: WfoProcessListTabType.ACTIVE, + translationKey: 'active', + alwaysOnFilters: [ + { + // Todo: isTask is not a key of Process + // However, backend still supports it. Field should not be a keyof ProcessListItem (or process) + // https://github.com/workfloworchestrator/orchestrator-ui/issues/290 + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore waiting for fix in backend + field: 'isTask', + value: 'false', + }, + { + field: 'process_state', + value: 'created-running-suspended-waiting-failed-resumed', + }, + ], + }, + { + id: WfoProcessListTabType.COMPLETED, + translationKey: 'completed', + alwaysOnFilters: [ + { + // Todo: isTask is not a key of Process + // However, backend still supports it. Field should not be a keyof ProcessListItem (or process) + // https://github.com/workfloworchestrator/orchestrator-ui/issues/290 + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore waiting for fix in backend + field: 'isTask', + value: 'false', + }, + { + field: 'process_state', + value: 'completed', + }, + ], + }, +]; diff --git a/packages/surf/src/types/types.ts b/packages/surf/src/types/types.ts index 77f749d77..3b188c9c9 100644 --- a/packages/surf/src/types/types.ts +++ b/packages/surf/src/types/types.ts @@ -1,4 +1,5 @@ /** CIM */ +import { Process } from '@orchestrator-ui/orchestrator-ui-components'; export interface CreateServiceTicketPayload { ims_pw_id: string; @@ -57,6 +58,25 @@ export type ServiceTicketDefinition = { title_nl: string; }; +export type ServiceTicketListItem = Pick< + Process, + | 'workflowName' + | 'lastStep' + | 'lastStatus' + | 'workflowTarget' + | 'createdBy' + | 'assignee' + | 'processId' + | 'subscriptions' +> & { + startedAt: Date; + lastModifiedAt: Date; + productName?: string; + productTag?: string; + customer: string; + customerAbbreviation: string; +}; + export enum ServiceTicketLogType { OPEN = 'open', UPDATE = 'update', From 2d0283e407b80ccce2058d79605651c455c01baf Mon Sep 17 00:00:00 2001 From: Georgi Manev Date: Tue, 31 Oct 2023 19:14:47 +0100 Subject: [PATCH 03/13] Added filtering for Active and Completed service tickets. --- .../service-tickets/[serviceTicketId].tsx | 4 +- .../pages/service-tickets/index.tsx | 4 +- .../WfoPageTemplate/WfoSidebar/WfoSidebar.tsx | 32 ++++----------- .../src/components/WfoPageTemplate/paths.ts | 1 + .../WfoProcessesList/WfoProcessList.tsx | 4 ++ .../src/hooks/DataFetchHooks.ts | 29 +++++++++++--- .../pages/cim/WfoServiceTicketListPage.tsx | 22 +++++------ ...eTickets.tsx => WfoServiceTicketsList.tsx} | 31 ++++++++++++++- packages/surf/src/pages/cim/index.ts | 2 +- packages/surf/src/pages/cim/tabConfig.ts | 39 +++++++++++-------- 10 files changed, 103 insertions(+), 65 deletions(-) rename packages/surf/src/pages/cim/{WfoServiceTickets.tsx => WfoServiceTicketsList.tsx} (88%) diff --git a/apps/wfo-ui-surf/pages/service-tickets/[serviceTicketId].tsx b/apps/wfo-ui-surf/pages/service-tickets/[serviceTicketId].tsx index 486685885..4f67f42f7 100644 --- a/apps/wfo-ui-surf/pages/service-tickets/[serviceTicketId].tsx +++ b/apps/wfo-ui-surf/pages/service-tickets/[serviceTicketId].tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { WfoServiceTickets } from '@orchestrator-ui/surf'; +import { WfoServiceTicketListPage } from '@orchestrator-ui/surf'; -export const ServiceTicketsCompletePage = () => ; +export const ServiceTicketsCompletePage = () => ; export default ServiceTicketsCompletePage; diff --git a/apps/wfo-ui-surf/pages/service-tickets/index.tsx b/apps/wfo-ui-surf/pages/service-tickets/index.tsx index 19d4b78d7..981b5ccd9 100644 --- a/apps/wfo-ui-surf/pages/service-tickets/index.tsx +++ b/apps/wfo-ui-surf/pages/service-tickets/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { WfoServiceTickets } from '@orchestrator-ui/surf'; +import { WfoServiceTicketListPage } from '@orchestrator-ui/surf'; -export const ActiveServiceTicketsPage = () => ; +export const ActiveServiceTicketsPage = () => ; export default ActiveServiceTicketsPage; diff --git a/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx b/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx index d38caeadf..685baf6cf 100644 --- a/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx @@ -10,6 +10,7 @@ import { PATH_METADATA_RESOURCE_TYPES, PATH_METADATA_WORKFLOWS, PATH_PROCESSES, + PATH_SERVICE_TICKETS, PATH_SETTINGS, PATH_START, PATH_SUBSCRIPTIONS, @@ -131,33 +132,14 @@ export const WfoSidebar: FC = ({ overrideMenuItems }) => { href: PATH_SETTINGS, }, { - name: 'Service tickets', + name: 'Service Tickets', id: '8', - onClick: () => { - // Note: Using a string literal instead of const, otherwise I'll need to add the surf package to orchestrator-ui-components. Maybe here we use an ENV var ? - router.push('/service-tickets/active'); + isSelected: router.pathname === PATH_SERVICE_TICKETS, + href: PATH_SERVICE_TICKETS, + onClick: (e) => { + e.preventDefault(); + router.push(PATH_SERVICE_TICKETS); }, - items: [ - { - name: 'Active', - id: '8.1', - isSelected: router.pathname === '/service-tickets/active', - onClick: (e) => { - e.preventDefault(); - router.push('/service-tickets/active'); - }, - }, - { - name: 'Completed', - id: '8.2', - isSelected: - router.pathname === '/service-tickets/completed', - onClick: (e) => { - e.preventDefault(); - router.push('/service-tickets/completed'); - }, - }, - ], }, ]; diff --git a/packages/orchestrator-ui-components/src/components/WfoPageTemplate/paths.ts b/packages/orchestrator-ui-components/src/components/WfoPageTemplate/paths.ts index fe8203b5e..db9596dd3 100644 --- a/packages/orchestrator-ui-components/src/components/WfoPageTemplate/paths.ts +++ b/packages/orchestrator-ui-components/src/components/WfoPageTemplate/paths.ts @@ -9,3 +9,4 @@ export const PATH_METADATA_RESOURCE_TYPES = '/metadata/resource-types'; export const PATH_METADATA_WORKFLOWS = '/metadata/workflows'; export const PATH_TASKS = '/tasks'; export const PATH_SETTINGS = '/settings'; +export const PATH_SERVICE_TICKETS = '/service-tickets'; diff --git a/packages/orchestrator-ui-components/src/components/WfoProcessesList/WfoProcessList.tsx b/packages/orchestrator-ui-components/src/components/WfoProcessesList/WfoProcessList.tsx index e9e506238..27e415c2b 100644 --- a/packages/orchestrator-ui-components/src/components/WfoProcessesList/WfoProcessList.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoProcessesList/WfoProcessList.tsx @@ -75,6 +75,10 @@ export const WfoProcessList: FC = ({ }) => { const t = useTranslations('processes.index'); + console.log('alwaysOnFilters', alwaysOnFilters); + console.log('defaultHiddenColumns', defaultHiddenColumns); + console.log('setDataDisplayParam', setDataDisplayParam); + const defaultTableColumns: WfoTableColumns = { workflowName: { field: 'workflowName', diff --git a/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts b/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts index 7b2985d15..a16d66670 100644 --- a/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts +++ b/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts @@ -1,7 +1,7 @@ import { useQuery } from 'react-query'; import { useContext } from 'react'; import { OrchestratorConfigContext } from '../contexts/OrchestratorConfigContext'; -import { ItemsList } from '../types'; +import { GraphqlFilter, ItemsList } from '../types'; async function getFavouriteSubscriptions(apiUrl: string) { const response = await fetch(apiUrl + '/subscriptions/?range=10%2C15'); @@ -89,19 +89,36 @@ export const useCacheNames = () => { ); }; -export const useQueryWithRest = ( +const filterDataByCriteria = ( + data: Type[], + filterCriteria: GraphqlFilter[], +): Type[] => { + return data.filter((item) => { + return filterCriteria.some((filter) => { + return item[filter.field] === filter.value; + }); + }); +}; + +export const useQueryWithRest = ( endpoint: string, queryKey: string, + filters?: GraphqlFilter[], refetchInterval?: number, ) => { const { orchestratorApiBaseUrl } = useContext(OrchestratorConfigContext); const fetchFromApi = async () => { const response = await fetch(orchestratorApiBaseUrl + endpoint); - return await response.json(); + let data = await response.json(); + return filters ? filterDataByCriteria(data, filters) : data; }; - return useQuery([queryKey], fetchFromApi, { - refetchInterval, - }); + return useQuery( + filters ? [queryKey, { filters }] : [queryKey], + fetchFromApi, + { + refetchInterval, + }, + ); }; diff --git a/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx b/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx index d75b5196f..887eb1495 100644 --- a/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx +++ b/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { StringParam, useQueryParam, withDefault } from 'use-query-params'; import { DEFAULT_PAGE_SIZE, @@ -17,8 +17,8 @@ import { import { useRouter } from 'next/router'; import { getServiceTicketListTabTypeFromString } from './getServiceTicketListTabTypeFromString'; import { defaultServiceTicketsListTabs } from './tabConfig'; -import { EuiSpacer, EuiPageHeader } from '@elastic/eui'; -import { WfoServiceTickets } from './WfoServiceTickets'; +import { EuiPageHeader, EuiSpacer } from '@elastic/eui'; +import { WfoServiceTicketsList } from './WfoServiceTicketsList'; export const WfoServiceTicketListPage = () => { const router = useRouter(); @@ -75,7 +75,7 @@ export const WfoServiceTicketListPage = () => { )?.alwaysOnFilters; if (!selectedServiceTicketListTab) { - router.replace('/processes'); + router.replace('/service-tickets'); return null; } @@ -83,7 +83,7 @@ export const WfoServiceTicketListPage = () => { <> - + { /> - ); diff --git a/packages/surf/src/pages/cim/WfoServiceTickets.tsx b/packages/surf/src/pages/cim/WfoServiceTicketsList.tsx similarity index 88% rename from packages/surf/src/pages/cim/WfoServiceTickets.tsx rename to packages/surf/src/pages/cim/WfoServiceTicketsList.tsx index cc835799a..41d541890 100644 --- a/packages/surf/src/pages/cim/WfoServiceTickets.tsx +++ b/packages/surf/src/pages/cim/WfoServiceTicketsList.tsx @@ -12,10 +12,13 @@ import { } from '../../types'; import { useTranslations } from 'next-intl'; import { + DataDisplayParams, + FilterQuery, getSortDirectionFromString, parseDateToLocaleDateTimeString, parseIsoString, SortOrder, + TableColumnKeys, useOrchestratorTheme, useQueryWithRest, WFO_TABLE_COLOR_FIELD, @@ -43,7 +46,31 @@ const SERVICE_TICKET_FIELD_LAST_UPDATE: keyof ServiceTicketDefinition = const { NEW, OPEN, OPEN_RELATED, OPEN_ACCEPTED, UPDATED, ABORTED, CLOSED } = ServiceTicketProcessState; -export const WfoServiceTickets = () => { +export type WfoServiceTicketsListProps = { + alwaysOnFilters?: FilterQuery[]; + defaultHiddenColumns: TableColumnKeys | undefined; + localStorageKey: string; + dataDisplayParams: DataDisplayParams; + setDataDisplayParam: < + DisplayParamKey extends + keyof DataDisplayParams, + >( + prop: DisplayParamKey, + value: DataDisplayParams[DisplayParamKey], + ) => void; + overrideDefaultTableColumns?: ( + defaultTableColumns: WfoTableColumns, + ) => WfoTableColumns; +}; + +export const WfoServiceTicketsList = ({ + alwaysOnFilters, + defaultHiddenColumns = [], + localStorageKey, + dataDisplayParams, + setDataDisplayParam, + overrideDefaultTableColumns, +}: WfoServiceTicketsListProps) => { const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(5); const [dataSorting, setDataSorting] = useState< @@ -52,10 +79,12 @@ export const WfoServiceTickets = () => { field: SERVICE_TICKET_FIELD_LAST_UPDATE, sortOrder: SortOrder.DESC, }); + const t = useTranslations('cim.serviceTickets'); const { data, isFetching } = useQueryWithRest( CIM_TICKETS_ENDPOINT, 'serviceTickets', + alwaysOnFilters, ); const { theme } = useOrchestratorTheme(); diff --git a/packages/surf/src/pages/cim/index.ts b/packages/surf/src/pages/cim/index.ts index 20fff549b..b4885bef4 100644 --- a/packages/surf/src/pages/cim/index.ts +++ b/packages/surf/src/pages/cim/index.ts @@ -1,2 +1,2 @@ -export * from './WfoServiceTickets'; +export * from './WfoServiceTicketsList'; export * from './WfoServiceTicketListPage'; diff --git a/packages/surf/src/pages/cim/tabConfig.ts b/packages/surf/src/pages/cim/tabConfig.ts index 7f39d19a6..65ae778a5 100644 --- a/packages/surf/src/pages/cim/tabConfig.ts +++ b/packages/surf/src/pages/cim/tabConfig.ts @@ -2,7 +2,10 @@ import { WfoFilterTab, WfoProcessListTabType, } from '@orchestrator-ui/orchestrator-ui-components'; -import { ServiceTicketDefinition } from '../../types'; +import { + ServiceTicketDefinition, + ServiceTicketProcessState, +} from '../../types'; export const defaultServiceTicketsListTabs: WfoFilterTab< WfoProcessListTabType, ServiceTicketDefinition @@ -12,17 +15,24 @@ export const defaultServiceTicketsListTabs: WfoFilterTab< translationKey: 'active', alwaysOnFilters: [ { - // Todo: isTask is not a key of Process - // However, backend still supports it. Field should not be a keyof ProcessListItem (or process) - // https://github.com/workfloworchestrator/orchestrator-ui/issues/290 - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore waiting for fix in backend - field: 'isTask', - value: 'false', + field: 'process_state', + value: ServiceTicketProcessState.OPEN, + }, + { + field: 'process_state', + value: ServiceTicketProcessState.OPEN_ACCEPTED, + }, + { + field: 'process_state', + value: ServiceTicketProcessState.UPDATED, + }, + { + field: 'process_state', + value: ServiceTicketProcessState.NEW, }, { field: 'process_state', - value: 'created-running-suspended-waiting-failed-resumed', + value: ServiceTicketProcessState.OPEN_RELATED, }, ], }, @@ -31,17 +41,12 @@ export const defaultServiceTicketsListTabs: WfoFilterTab< translationKey: 'completed', alwaysOnFilters: [ { - // Todo: isTask is not a key of Process - // However, backend still supports it. Field should not be a keyof ProcessListItem (or process) - // https://github.com/workfloworchestrator/orchestrator-ui/issues/290 - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore waiting for fix in backend - field: 'isTask', - value: 'false', + field: 'process_state', + value: ServiceTicketProcessState.CLOSED, }, { field: 'process_state', - value: 'completed', + value: ServiceTicketProcessState.ABORTED, }, ], }, From dffa053649b018421bd42873e409e06b5e955b5b Mon Sep 17 00:00:00 2001 From: Georgi Manev Date: Wed, 1 Nov 2023 09:28:03 +0100 Subject: [PATCH 04/13] linted --- .../orchestrator-ui-components/src/hooks/DataFetchHooks.ts | 2 +- packages/surf/src/pages/cim/WfoServiceTicketsList.tsx | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts b/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts index a16d66670..308aa9002 100644 --- a/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts +++ b/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts @@ -110,7 +110,7 @@ export const useQueryWithRest = ( const fetchFromApi = async () => { const response = await fetch(orchestratorApiBaseUrl + endpoint); - let data = await response.json(); + const data = await response.json(); return filters ? filterDataByCriteria(data, filters) : data; }; diff --git a/packages/surf/src/pages/cim/WfoServiceTicketsList.tsx b/packages/surf/src/pages/cim/WfoServiceTicketsList.tsx index 41d541890..0443fc04d 100644 --- a/packages/surf/src/pages/cim/WfoServiceTicketsList.tsx +++ b/packages/surf/src/pages/cim/WfoServiceTicketsList.tsx @@ -65,11 +65,6 @@ export type WfoServiceTicketsListProps = { export const WfoServiceTicketsList = ({ alwaysOnFilters, - defaultHiddenColumns = [], - localStorageKey, - dataDisplayParams, - setDataDisplayParam, - overrideDefaultTableColumns, }: WfoServiceTicketsListProps) => { const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(5); From 23965d73b859632f51f3d1ce6f7cbe499b761ed8 Mon Sep 17 00:00:00 2001 From: Georgi Manev Date: Thu, 2 Nov 2023 09:28:43 +0100 Subject: [PATCH 05/13] 411: Last commit before files are moved to wfo-ui-surf app --- .../components/WfoServiceTicketList/index.ts | 1 - .../subscriptionListTabs.ts | 71 ------------------- .../WfoServiceTicketsList.tsx | 41 +++++++++-- .../getServiceTicketListTabTypeFromString.ts | 0 .../components/WfoServiceTicketsList/index.ts | 1 + .../mapServiceTicketStateToColor.ts | 39 ++++++++++ packages/surf/src/components/index.ts | 2 +- .../pages/cim/WfoServiceTicketListPage.tsx | 4 +- packages/surf/src/pages/cim/index.ts | 2 +- 9 files changed, 78 insertions(+), 83 deletions(-) delete mode 100644 packages/surf/src/components/WfoServiceTicketList/index.ts delete mode 100644 packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts rename packages/surf/src/{pages/cim => components/WfoServiceTicketsList}/WfoServiceTicketsList.tsx (85%) rename packages/surf/src/{pages/cim => components/WfoServiceTicketsList}/getServiceTicketListTabTypeFromString.ts (100%) create mode 100644 packages/surf/src/components/WfoServiceTicketsList/index.ts create mode 100644 packages/surf/src/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts diff --git a/packages/surf/src/components/WfoServiceTicketList/index.ts b/packages/surf/src/components/WfoServiceTicketList/index.ts deleted file mode 100644 index b91069276..000000000 --- a/packages/surf/src/components/WfoServiceTicketList/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './subscriptionListTabs'; diff --git a/packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts b/packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts deleted file mode 100644 index 794bd0a69..000000000 --- a/packages/surf/src/components/WfoServiceTicketList/subscriptionListTabs.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { WfoFilterTab } from '@orchestrator-ui/orchestrator-ui-components'; -import { ServiceTicketDefinition } from '../../types'; - -export enum WfoSubscriptionsTabType { - ACTIVE = 'ACTIVE', - TERMINATED = 'TERMINATED', - TRANSIENT = 'TRANSIENT', - ALL = 'ALL', -} - -export const defaultSubscriptionsTabs: WfoFilterTab< - WfoSubscriptionsTabType, - ServiceTicketDefinition ->[] = [ - { - id: WfoSubscriptionsTabType.ACTIVE, - translationKey: 'active', - alwaysOnFilters: [ - { - field: 'process_state', - value: 'active', - }, - ], - }, - { - id: WfoSubscriptionsTabType.TERMINATED, - translationKey: 'terminated', - alwaysOnFilters: [ - { - field: 'process_state', - value: 'terminated', - }, - ], - }, - { - id: WfoSubscriptionsTabType.TRANSIENT, - translationKey: 'transient', - alwaysOnFilters: [ - { - field: 'process_state', - value: 'initial-provisioning-migrating', - }, - ], - }, - { - id: WfoSubscriptionsTabType.ALL, - translationKey: 'all', - }, -]; - -export const getSubscriptionsTabTypeFromString = ( - tabId?: string, -): WfoSubscriptionsTabType | undefined => { - if (!tabId) { - return undefined; - } - - switch (tabId.toUpperCase()) { - case WfoSubscriptionsTabType.ACTIVE.toString(): - return WfoSubscriptionsTabType.ACTIVE; - case WfoSubscriptionsTabType.TERMINATED.toString(): - return WfoSubscriptionsTabType.TERMINATED; - case WfoSubscriptionsTabType.TRANSIENT.toString(): - return WfoSubscriptionsTabType.TRANSIENT; - case WfoSubscriptionsTabType.ALL.toString(): - return WfoSubscriptionsTabType.ALL; - - default: - return undefined; - } -}; diff --git a/packages/surf/src/pages/cim/WfoServiceTicketsList.tsx b/packages/surf/src/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx similarity index 85% rename from packages/surf/src/pages/cim/WfoServiceTicketsList.tsx rename to packages/surf/src/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx index 0443fc04d..63cb60d1d 100644 --- a/packages/surf/src/pages/cim/WfoServiceTicketsList.tsx +++ b/packages/surf/src/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx @@ -22,6 +22,7 @@ import { useOrchestratorTheme, useQueryWithRest, WFO_TABLE_COLOR_FIELD, + WfoBadge, WfoBasicTable, WfoDataSorting, WfoDateTime, @@ -81,20 +82,35 @@ export const WfoServiceTicketsList = ({ 'serviceTickets', alwaysOnFilters, ); - const { theme } = useOrchestratorTheme(); + const { theme, toSecondaryColor } = useOrchestratorTheme(); const mapStateToColor = (state: ServiceTicketProcessState) => { switch (state) { case OPEN || NEW: - return theme.colors.success; + return { + backgroundColor: theme.colors.success, + textColor: theme.colors.successText, + }; case OPEN_ACCEPTED || OPEN_RELATED: - return theme.colors.warning; + return { + backgroundColor: theme.colors.warning, + textColor: theme.colors.warningText, + }; case UPDATED: - return theme.colors.primary; + return { + backgroundColor: theme.colors.primary, + textColor: theme.colors.primaryText, + }; case CLOSED || ABORTED: - return theme.colors.lightShade; + return { + backgroundColor: theme.colors.lightShade, + textColor: theme.colors.text, + }; default: - return theme.colors.emptyShade; + return { + backgroundColor: theme.colors.lightShade, + textColor: theme.colors.text, + }; } }; @@ -108,7 +124,8 @@ export const WfoServiceTicketsList = ({ style={{ paddingInline: 4, paddingBlock: 25, - backgroundColor: mapStateToColor(object.process_state), + backgroundColor: mapStateToColor(object.process_state) + .backgroundColor, }} /> ), @@ -135,6 +152,16 @@ export const WfoServiceTicketsList = ({ field: SERVICE_TICKET_FIELD_PROCESS_STATE, name: t('processState'), width: '120', + render: (value, object) => ( + + {value} + + ), }, opened_by: { field: SERVICE_TICKET_FIELD_OPENED_BY, diff --git a/packages/surf/src/pages/cim/getServiceTicketListTabTypeFromString.ts b/packages/surf/src/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts similarity index 100% rename from packages/surf/src/pages/cim/getServiceTicketListTabTypeFromString.ts rename to packages/surf/src/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts diff --git a/packages/surf/src/components/WfoServiceTicketsList/index.ts b/packages/surf/src/components/WfoServiceTicketsList/index.ts new file mode 100644 index 000000000..ce53af7b4 --- /dev/null +++ b/packages/surf/src/components/WfoServiceTicketsList/index.ts @@ -0,0 +1 @@ +export * from './WfoServiceTicketsList'; diff --git a/packages/surf/src/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts b/packages/surf/src/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts new file mode 100644 index 000000000..5b564c79f --- /dev/null +++ b/packages/surf/src/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts @@ -0,0 +1,39 @@ +import { ServiceTicketProcessState } from '../../types'; +import { EuiThemeComputed } from '@elastic/eui/src/services/theme/types'; + +const { NEW, OPEN, OPEN_RELATED, OPEN_ACCEPTED, UPDATED, ABORTED, CLOSED } = + ServiceTicketProcessState; + +// This probably will be subject to change +export const mapStateToColor = ( + state: ServiceTicketProcessState, + theme: EuiThemeComputed, +) => { + switch (state) { + case OPEN || NEW: + return { + backgroundColor: theme.colors.success, + textColor: theme.colors.successText, + }; + case OPEN_ACCEPTED || OPEN_RELATED: + return { + backgroundColor: theme.colors.warning, + textColor: theme.colors.warningText, + }; + case UPDATED: + return { + backgroundColor: theme.colors.primary, + textColor: theme.colors.primaryText, + }; + case CLOSED || ABORTED: + return { + backgroundColor: theme.colors.lightShade, + textColor: theme.colors.text, + }; + default: + return { + backgroundColor: theme.colors.lightShade, + textColor: theme.colors.text, + }; + } +}; diff --git a/packages/surf/src/components/index.ts b/packages/surf/src/components/index.ts index ccd4c86e0..ce53af7b4 100644 --- a/packages/surf/src/components/index.ts +++ b/packages/surf/src/components/index.ts @@ -1 +1 @@ -export * from './WfoServiceTicketList'; +export * from './WfoServiceTicketsList'; diff --git a/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx b/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx index 887eb1495..3c80f8bf4 100644 --- a/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx +++ b/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx @@ -15,10 +15,10 @@ import { COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY, } from '../../constants'; import { useRouter } from 'next/router'; -import { getServiceTicketListTabTypeFromString } from './getServiceTicketListTabTypeFromString'; +import { getServiceTicketListTabTypeFromString } from '../../components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString'; import { defaultServiceTicketsListTabs } from './tabConfig'; import { EuiPageHeader, EuiSpacer } from '@elastic/eui'; -import { WfoServiceTicketsList } from './WfoServiceTicketsList'; +import { WfoServiceTicketsList } from '../../components'; export const WfoServiceTicketListPage = () => { const router = useRouter(); diff --git a/packages/surf/src/pages/cim/index.ts b/packages/surf/src/pages/cim/index.ts index b4885bef4..84c0d666e 100644 --- a/packages/surf/src/pages/cim/index.ts +++ b/packages/surf/src/pages/cim/index.ts @@ -1,2 +1,2 @@ -export * from './WfoServiceTicketsList'; +export * from '../../components/WfoServiceTicketsList/WfoServiceTicketsList'; export * from './WfoServiceTicketListPage'; From 2bcb268161af806008e466d2af8aeb165e04a6b0 Mon Sep 17 00:00:00 2001 From: Georgi Manev Date: Thu, 2 Nov 2023 10:45:15 +0100 Subject: [PATCH 06/13] 411: Moved surf specific pages and components to the wfo-ui-surf --- .../WfoServiceTicketsList.tsx | 288 ++++++++++++++++++ .../getServiceTicketListTabTypeFromString.ts | 19 ++ .../components/WfoServiceTicketsList/index.ts | 1 + .../mapServiceTicketStateToColor.ts | 39 +++ .../WfoServiceTicketListPage.tsx | 106 +++++++ .../WfoServiceTicketsListPage/index.ts | 2 + .../WfoServiceTicketsListPage/tabConfig.ts | 53 ++++ apps/wfo-ui-surf/constants-surf.ts | 5 + apps/wfo-ui-surf/next.config.js | 5 +- apps/wfo-ui-surf/package.json | 1 - apps/wfo-ui-surf/pages/_app.tsx | 10 +- .../service-tickets/[serviceTicketId].tsx | 3 +- .../pages/service-tickets/index.tsx | 2 +- apps/wfo-ui-surf/pages/surf.tsx | 7 - apps/wfo-ui-surf/types/index.ts | 1 + apps/wfo-ui-surf/types/types.ts | 207 +++++++++++++ .../WfoPageTemplate/WfoSidebar/WfoSidebar.tsx | 11 - .../src/components/WfoPageTemplate/paths.ts | 1 - 18 files changed, 729 insertions(+), 32 deletions(-) create mode 100644 apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx create mode 100644 apps/wfo-ui-surf/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts create mode 100644 apps/wfo-ui-surf/components/WfoServiceTicketsList/index.ts create mode 100644 apps/wfo-ui-surf/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts create mode 100644 apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx create mode 100644 apps/wfo-ui-surf/components/WfoServiceTicketsListPage/index.ts create mode 100644 apps/wfo-ui-surf/components/WfoServiceTicketsListPage/tabConfig.ts create mode 100644 apps/wfo-ui-surf/constants-surf.ts delete mode 100644 apps/wfo-ui-surf/pages/surf.tsx create mode 100644 apps/wfo-ui-surf/types/index.ts create mode 100644 apps/wfo-ui-surf/types/types.ts diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx b/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx new file mode 100644 index 000000000..e48437d03 --- /dev/null +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx @@ -0,0 +1,288 @@ +import React, { useState } from 'react'; +import { + Comparators, + Criteria, + EuiFlexGroup, + EuiFlexItem, + EuiTableSortingType, +} from '@elastic/eui'; +import { + ServiceTicketDefinition, + ServiceTicketProcessState, +} from '../../types'; +import { useTranslations } from 'next-intl'; +import { + DataDisplayParams, + FilterQuery, + getSortDirectionFromString, + parseDateToLocaleDateTimeString, + parseIsoString, + SortOrder, + TableColumnKeys, + useOrchestratorTheme, + useQueryWithRest, + WFO_TABLE_COLOR_FIELD, + WfoBadge, + WfoBasicTable, + WfoDataSorting, + WfoDateTime, + WfoTableColumns, +} from '@orchestrator-ui/orchestrator-ui-components'; +import { CIM_TICKETS_ENDPOINT } from '../../constants-surf'; + +const SERVICE_TICKET_FIELD_JIRA_ID: keyof ServiceTicketDefinition = + 'jira_ticket_id'; +const SERVICE_TICKET_FIELD_TITLE: keyof ServiceTicketDefinition = 'title_nl'; +const SERVICE_TICKET_FIELD_PROCESS_STATE: keyof ServiceTicketDefinition = + 'process_state'; +const SERVICE_TICKET_FIELD_OPENED_BY: keyof ServiceTicketDefinition = + 'opened_by'; +const SERVICE_TICKET_FIELD_START_DATE: keyof ServiceTicketDefinition = + 'start_date'; +const SERVICE_TICKET_FIELD_CREATE_DATE: keyof ServiceTicketDefinition = + 'create_date'; +const SERVICE_TICKET_FIELD_LAST_UPDATE: keyof ServiceTicketDefinition = + 'last_update_time'; + +const { NEW, OPEN, OPEN_RELATED, OPEN_ACCEPTED, UPDATED, ABORTED, CLOSED } = + ServiceTicketProcessState; + +export type WfoServiceTicketsListProps = { + alwaysOnFilters?: FilterQuery[]; + defaultHiddenColumns: TableColumnKeys | undefined; + localStorageKey: string; + dataDisplayParams: DataDisplayParams; + setDataDisplayParam: < + DisplayParamKey extends + keyof DataDisplayParams, + >( + prop: DisplayParamKey, + value: DataDisplayParams[DisplayParamKey], + ) => void; + overrideDefaultTableColumns?: ( + defaultTableColumns: WfoTableColumns, + ) => WfoTableColumns; +}; + +export const WfoServiceTicketsList = ({ + alwaysOnFilters, +}: WfoServiceTicketsListProps) => { + const [pageIndex, setPageIndex] = useState(0); + const [pageSize, setPageSize] = useState(5); + const [dataSorting, setDataSorting] = useState< + WfoDataSorting + >({ + field: SERVICE_TICKET_FIELD_LAST_UPDATE, + sortOrder: SortOrder.DESC, + }); + + const t = useTranslations('cim.serviceTickets'); + const { data, isFetching } = useQueryWithRest( + CIM_TICKETS_ENDPOINT, + 'serviceTickets', + alwaysOnFilters, + ); + const { theme, toSecondaryColor } = useOrchestratorTheme(); + + const mapStateToColor = (state: ServiceTicketProcessState) => { + switch (state) { + case OPEN || NEW: + return { + backgroundColor: theme.colors.success, + textColor: theme.colors.successText, + }; + case OPEN_ACCEPTED || OPEN_RELATED: + return { + backgroundColor: theme.colors.warning, + textColor: theme.colors.warningText, + }; + case UPDATED: + return { + backgroundColor: theme.colors.primary, + textColor: theme.colors.primaryText, + }; + case CLOSED || ABORTED: + return { + backgroundColor: theme.colors.lightShade, + textColor: theme.colors.text, + }; + default: + return { + backgroundColor: theme.colors.lightShade, + textColor: theme.colors.text, + }; + } + }; + + const tableColumns: WfoTableColumns = { + color: { + field: WFO_TABLE_COLOR_FIELD, + name: '', + width: '1', + render: (value, object) => ( + + ), + sortable: true, + }, + jira_ticket_id: { + field: SERVICE_TICKET_FIELD_JIRA_ID, + name: t('jiraTicketId'), + width: '100', + //Todo: Fix styling and add color according to State + render: (value) => ( + + {value} + + ), + sortable: true, + }, + title_nl: { + field: SERVICE_TICKET_FIELD_TITLE, + name: t('titleNl'), + width: '300', + }, + process_state: { + field: SERVICE_TICKET_FIELD_PROCESS_STATE, + name: t('processState'), + width: '120', + render: (value, object) => ( + + {value} + + ), + }, + opened_by: { + field: SERVICE_TICKET_FIELD_OPENED_BY, + name: t('openedBy'), + width: '180', + }, + start_date: { + field: SERVICE_TICKET_FIELD_START_DATE, + name: t('startDate'), + width: '150', + render: (date) => , + renderDetails: parseIsoString(parseDateToLocaleDateTimeString), + clipboardText: parseIsoString(parseDateToLocaleDateTimeString), + }, + create_date: { + field: SERVICE_TICKET_FIELD_CREATE_DATE, + name: t('createDate'), + width: '150', + render: (date: string) => ( + {new Date(date).toLocaleDateString()} + ), + }, + last_update_time: { + field: SERVICE_TICKET_FIELD_LAST_UPDATE, + name: t('lastUpdateTime'), + width: '150', + render: (date: string) => ( + {new Date(date).toLocaleString()} + ), + }, + }; + + const onCriteriaChange = ({ + page, + sort, + }: Criteria) => { + if (page) { + const { index: pageIndex, size: pageSize } = page; + setPageIndex(pageIndex); + setPageSize(pageSize); + } + if (sort) { + const { field: sortField, direction: sortDirection } = sort; + const sortOrder = getSortDirectionFromString( + sortDirection, + ) as SortOrder; + setDataSorting({ + field: sortField, + sortOrder: sortOrder, + }); + } + }; + + // Manually handle sorting and pagination of data + const findServiceTickets = ( + serviceTickets: ServiceTicketDefinition[], + pageIndex: number, + pageSize: number, + sortField: keyof ServiceTicketDefinition, + sortDirection: 'asc' | 'desc', + ) => { + let items; + if (sortField) { + items = serviceTickets + .slice(0) + .sort( + Comparators.property( + sortField, + Comparators.default(sortDirection), + ), + ); + } else { + items = serviceTickets; + } + let pageOfItems; + if (!pageIndex && !pageSize) { + pageOfItems = items; + } else { + const startIndex = pageIndex * pageSize; + pageOfItems = items.slice( + startIndex, + Math.min(startIndex + pageSize, serviceTickets.length), + ); + } + return { + pageOfItems, + totalItemCount: serviceTickets.length, + }; + }; + + const { pageOfItems, totalItemCount } = findServiceTickets( + data ? data : [], + pageIndex, + pageSize, + dataSorting.field, + dataSorting.sortOrder.toLowerCase() as 'asc' | 'desc', + ); + const pagination = { + pageIndex: pageIndex, + pageSize: pageSize, + totalItemCount: totalItemCount, + pageSizeOptions: [5, 10, 20], + }; + const sorting: EuiTableSortingType = { + sort: { + field: dataSorting.field, + direction: dataSorting.sortOrder.toLowerCase() as 'asc' | 'desc', + }, + enableAllColumns: true, + readOnly: false, + }; + + return ( + + ); +}; diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts b/apps/wfo-ui-surf/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts new file mode 100644 index 000000000..fa0078564 --- /dev/null +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts @@ -0,0 +1,19 @@ +import { WfoProcessListTabType } from '@orchestrator-ui/orchestrator-ui-components'; + +export const getServiceTicketListTabTypeFromString = ( + tabId?: string, +): WfoProcessListTabType | undefined => { + if (!tabId) { + return undefined; + } + + switch (tabId.toUpperCase()) { + case WfoProcessListTabType.ACTIVE.toString(): + return WfoProcessListTabType.ACTIVE; + case WfoProcessListTabType.COMPLETED.toString(): + return WfoProcessListTabType.COMPLETED; + + default: + return undefined; + } +}; diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsList/index.ts b/apps/wfo-ui-surf/components/WfoServiceTicketsList/index.ts new file mode 100644 index 000000000..ce53af7b4 --- /dev/null +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsList/index.ts @@ -0,0 +1 @@ +export * from './WfoServiceTicketsList'; diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts b/apps/wfo-ui-surf/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts new file mode 100644 index 000000000..5b564c79f --- /dev/null +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts @@ -0,0 +1,39 @@ +import { ServiceTicketProcessState } from '../../types'; +import { EuiThemeComputed } from '@elastic/eui/src/services/theme/types'; + +const { NEW, OPEN, OPEN_RELATED, OPEN_ACCEPTED, UPDATED, ABORTED, CLOSED } = + ServiceTicketProcessState; + +// This probably will be subject to change +export const mapStateToColor = ( + state: ServiceTicketProcessState, + theme: EuiThemeComputed, +) => { + switch (state) { + case OPEN || NEW: + return { + backgroundColor: theme.colors.success, + textColor: theme.colors.successText, + }; + case OPEN_ACCEPTED || OPEN_RELATED: + return { + backgroundColor: theme.colors.warning, + textColor: theme.colors.warningText, + }; + case UPDATED: + return { + backgroundColor: theme.colors.primary, + textColor: theme.colors.primaryText, + }; + case CLOSED || ABORTED: + return { + backgroundColor: theme.colors.lightShade, + textColor: theme.colors.text, + }; + default: + return { + backgroundColor: theme.colors.lightShade, + textColor: theme.colors.text, + }; + } +}; diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx new file mode 100644 index 000000000..2a11ade0f --- /dev/null +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx @@ -0,0 +1,106 @@ +import React, { useEffect, useState } from 'react'; +import { StringParam, useQueryParam, withDefault } from 'use-query-params'; +import { + DEFAULT_PAGE_SIZE, + SortOrder, + StoredTableConfig, + useDataDisplayParams, + useStoredTableConfig, + WfoFilterTabs, + WfoProcessListTabType, +} from '@orchestrator-ui/orchestrator-ui-components'; +import { ServiceTicketDefinition } from '../../types'; +import { + ACTIVE_TICKETS_TABLE_LOCAL_STORAGE_KEY, + COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY, +} from '../../constants-surf'; +import { useRouter } from 'next/router'; +import { getServiceTicketListTabTypeFromString } from '../WfoServiceTicketsList/getServiceTicketListTabTypeFromString'; +import { defaultServiceTicketsListTabs } from './tabConfig'; +import { EuiPageHeader, EuiSpacer } from '@elastic/eui'; +import { WfoServiceTicketsList } from '../WfoServiceTicketsList'; + +export const WfoServiceTicketListPage = () => { + const router = useRouter(); + + const [activeTab, setActiveTab] = useQueryParam( + 'activeTab', + withDefault(StringParam, WfoProcessListTabType.ACTIVE), + ); + + const [tableDefaults, setTableDefaults] = + useState>(); + + const selectedServiceTicketListTab = + getServiceTicketListTabTypeFromString(activeTab); + + const localStorageKey = + selectedServiceTicketListTab === WfoProcessListTabType.ACTIVE + ? ACTIVE_TICKETS_TABLE_LOCAL_STORAGE_KEY + : COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY; + + const getStoredTableConfig = + useStoredTableConfig(localStorageKey); + + useEffect(() => { + const storedConfig = getStoredTableConfig(); + + if (storedConfig) { + setTableDefaults(storedConfig); + } + }, [getStoredTableConfig]); + + const { dataDisplayParams, setDataDisplayParam } = + useDataDisplayParams({ + // TODO: Improvement: A default pageSize value is set to avoid a graphql error when the query is executed + // the fist time before the useEffect has populated the tableDefaults. Better is to create a way for + // the query to wait for the values to be available + // https://github.com/workfloworchestrator/orchestrator-ui/issues/261 + pageSize: tableDefaults?.selectedPageSize || DEFAULT_PAGE_SIZE, + sortBy: { + field: 'last_update_time', + order: SortOrder.DESC, + }, + }); + + const handleChangeServiceTicketListTab = ( + updatedServiceTicketListTab: WfoProcessListTabType, + ) => { + setActiveTab(updatedServiceTicketListTab); + setDataDisplayParam('pageIndex', 0); + }; + + const alwaysOnFilters = defaultServiceTicketsListTabs.find( + ({ id }) => id === selectedServiceTicketListTab, + )?.alwaysOnFilters; + + if (!selectedServiceTicketListTab) { + router.replace('/service-tickets'); + return null; + } + + return ( + <> + + + + + + + + + + + ); +}; diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/index.ts b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/index.ts new file mode 100644 index 000000000..4743d6e04 --- /dev/null +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/index.ts @@ -0,0 +1,2 @@ +export * from '../WfoServiceTicketsList/WfoServiceTicketsList'; +export * from './WfoServiceTicketListPage'; diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/tabConfig.ts b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/tabConfig.ts new file mode 100644 index 000000000..65ae778a5 --- /dev/null +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/tabConfig.ts @@ -0,0 +1,53 @@ +import { + WfoFilterTab, + WfoProcessListTabType, +} from '@orchestrator-ui/orchestrator-ui-components'; +import { + ServiceTicketDefinition, + ServiceTicketProcessState, +} from '../../types'; +export const defaultServiceTicketsListTabs: WfoFilterTab< + WfoProcessListTabType, + ServiceTicketDefinition +>[] = [ + { + id: WfoProcessListTabType.ACTIVE, + translationKey: 'active', + alwaysOnFilters: [ + { + field: 'process_state', + value: ServiceTicketProcessState.OPEN, + }, + { + field: 'process_state', + value: ServiceTicketProcessState.OPEN_ACCEPTED, + }, + { + field: 'process_state', + value: ServiceTicketProcessState.UPDATED, + }, + { + field: 'process_state', + value: ServiceTicketProcessState.NEW, + }, + { + field: 'process_state', + value: ServiceTicketProcessState.OPEN_RELATED, + }, + ], + }, + { + id: WfoProcessListTabType.COMPLETED, + translationKey: 'completed', + alwaysOnFilters: [ + { + field: 'process_state', + value: ServiceTicketProcessState.CLOSED, + }, + { + field: 'process_state', + value: ServiceTicketProcessState.ABORTED, + }, + ], + }, +]; diff --git a/apps/wfo-ui-surf/constants-surf.ts b/apps/wfo-ui-surf/constants-surf.ts new file mode 100644 index 000000000..9c142a868 --- /dev/null +++ b/apps/wfo-ui-surf/constants-surf.ts @@ -0,0 +1,5 @@ +export const PATH_SERVICE_TICKETS = '/service-tickets'; +export const CIM_TICKETS_ENDPOINT = '/surf/cim/tickets'; +export const ACTIVE_TICKETS_TABLE_LOCAL_STORAGE_KEY = 'activeTicketsTable'; +export const COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY = + 'completedTicketsTable'; diff --git a/apps/wfo-ui-surf/next.config.js b/apps/wfo-ui-surf/next.config.js index 115627f05..110593f5f 100644 --- a/apps/wfo-ui-surf/next.config.js +++ b/apps/wfo-ui-surf/next.config.js @@ -6,8 +6,5 @@ module.exports = { locales: ['en-US', 'nl-NL'], defaultLocale: 'en-US', }, - transpilePackages: [ - '@orchestrator-ui/orchestrator-ui-components', - '@orchestrator-ui/surf', - ], + transpilePackages: ['@orchestrator-ui/orchestrator-ui-components'], }; diff --git a/apps/wfo-ui-surf/package.json b/apps/wfo-ui-surf/package.json index 111a88312..46c3b21c2 100644 --- a/apps/wfo-ui-surf/package.json +++ b/apps/wfo-ui-surf/package.json @@ -18,7 +18,6 @@ "@emotion/react": "^11.11.1", "@graphql-typed-document-node/core": "3.2.0", "@orchestrator-ui/orchestrator-ui-components": "*", - "@orchestrator-ui/surf": "*", "graphql": "16.7.1", "graphql-request": "5.2.0", "moment": "^2.29.4", diff --git a/apps/wfo-ui-surf/pages/_app.tsx b/apps/wfo-ui-surf/pages/_app.tsx index 2760f241a..5d77d5270 100644 --- a/apps/wfo-ui-surf/pages/_app.tsx +++ b/apps/wfo-ui-surf/pages/_app.tsx @@ -26,8 +26,7 @@ import NoSSR from 'react-no-ssr'; import { useRouter } from 'next/router'; type AppOwnProps = { orchestratorConfig: OrchestratorConfig }; - -const PATH_SURF = '/surf'; +import { PATH_SERVICE_TICKETS } from '../constants-surf'; const queryClientConfig: QueryClientConfig = { defaultOptions: { @@ -54,12 +53,13 @@ function CustomApp({ ): EuiSideNavItemType[] => [ ...defaultMenuItems, { - name: 'Surf', - isSelected: router.pathname === PATH_SURF, + name: 'Service Tickets', id: '8', + isSelected: router.pathname === PATH_SERVICE_TICKETS, + href: PATH_SERVICE_TICKETS, onClick: (e) => { e.preventDefault(); - router.push(PATH_SURF); + router.push(PATH_SERVICE_TICKETS); }, }, ]; diff --git a/apps/wfo-ui-surf/pages/service-tickets/[serviceTicketId].tsx b/apps/wfo-ui-surf/pages/service-tickets/[serviceTicketId].tsx index 4f67f42f7..4ee9f27ed 100644 --- a/apps/wfo-ui-surf/pages/service-tickets/[serviceTicketId].tsx +++ b/apps/wfo-ui-surf/pages/service-tickets/[serviceTicketId].tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { WfoServiceTicketListPage } from '@orchestrator-ui/surf'; - +import { WfoServiceTicketListPage } from '../../components/WfoServiceTicketsListPage'; export const ServiceTicketsCompletePage = () => ; export default ServiceTicketsCompletePage; diff --git a/apps/wfo-ui-surf/pages/service-tickets/index.tsx b/apps/wfo-ui-surf/pages/service-tickets/index.tsx index 981b5ccd9..1fc8324d5 100644 --- a/apps/wfo-ui-surf/pages/service-tickets/index.tsx +++ b/apps/wfo-ui-surf/pages/service-tickets/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { WfoServiceTicketListPage } from '@orchestrator-ui/surf'; +import { WfoServiceTicketListPage } from '../../components/WfoServiceTicketsListPage'; export const ActiveServiceTicketsPage = () => ; diff --git a/apps/wfo-ui-surf/pages/surf.tsx b/apps/wfo-ui-surf/pages/surf.tsx deleted file mode 100644 index c707c2a8c..000000000 --- a/apps/wfo-ui-surf/pages/surf.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; - -export function SurfPage() { - return

Hello SURF

; -} - -export default SurfPage; diff --git a/apps/wfo-ui-surf/types/index.ts b/apps/wfo-ui-surf/types/index.ts new file mode 100644 index 000000000..fcb073fef --- /dev/null +++ b/apps/wfo-ui-surf/types/index.ts @@ -0,0 +1 @@ +export * from './types'; diff --git a/apps/wfo-ui-surf/types/types.ts b/apps/wfo-ui-surf/types/types.ts new file mode 100644 index 000000000..3b188c9c9 --- /dev/null +++ b/apps/wfo-ui-surf/types/types.ts @@ -0,0 +1,207 @@ +/** CIM */ +import { Process } from '@orchestrator-ui/orchestrator-ui-components'; + +export interface CreateServiceTicketPayload { + ims_pw_id: string; + jira_ticket_id: string; + title_nl: string; + type: ServiceTicketType; +} + +export interface OpenServiceTicketPayload { + cim_ticket_id: string; + title_nl: string; + description_nl: string; + title_en: string; + description_en: string; + mail_subject: string; +} + +export interface UpdateServiceTicketPayload extends OpenServiceTicketPayload { + start_date?: string; + end_date?: string; +} + +export interface CloseServiceTicketPayload extends OpenServiceTicketPayload { + end_date?: string; +} + +export enum ServiceTicketProcessState { + NEW = 'new', + OPEN = 'open', + OPEN_RELATED = 'open_related', + OPEN_ACCEPTED = 'open_accepted', + UPDATED = 'updated', + ABORTED = 'aborted', + CLOSED = 'closed', +} + +export enum ServiceTicketTransition { + RELATING = 'relating', + ACCEPTING = 'accepting', + ABORTING = 'aborting', + OPENING = 'opening', + OPEN_AND_CLOSE = 'open_and_close', + UPDATING = 'updating', + CLOSING = 'closing', + CLEANING = 'cleaning', +} + +export type ServiceTicketDefinition = { + color?: string; + jira_ticket_id: string; + opened_by: string; + process_state: ServiceTicketProcessState; + start_date: string; + create_date: string; + last_update_time: string; + title_nl: string; +}; + +export type ServiceTicketListItem = Pick< + Process, + | 'workflowName' + | 'lastStep' + | 'lastStatus' + | 'workflowTarget' + | 'createdBy' + | 'assignee' + | 'processId' + | 'subscriptions' +> & { + startedAt: Date; + lastModifiedAt: Date; + productName?: string; + productTag?: string; + customer: string; + customerAbbreviation: string; +}; + +export enum ServiceTicketLogType { + OPEN = 'open', + UPDATE = 'update', + CLOSE = 'close', +} + +export interface ServiceTicketLog { + entry_time: string; + update_nl: string; + update_en: string; + log_type: ServiceTicketLogType; + logged_by: string; + transition: ServiceTicketTransition; + completed: boolean; +} + +export enum ServiceTicketImpactedObjectImpact { + DOWN = 'down', + NO_IMPACT = 'no_impact', + REDUCED_REDUNDANCY = 'reduced_redundancy', + RESILIENCE_LOSS = 'resilience_loss', +} + +export interface ServiceTicketImpactedIMSCircuit { + ims_circuit_id: number; + ims_circuit_name: string; + impact: ServiceTicketImpactedObjectImpact; + extra_information?: string; +} + +export interface ServiceTicketCustomer { + customer_id: string; + customer_name: string; + customer_abbrev: string; +} +export interface ServiceTicketBackgroundJobCount { + number_of_active_jobs: number; +} + +export interface ServiceTicketContact { + name: string; + email: string; + // Todo: add phone? +} + +export interface ServiceTicketRelatedCustomer { + customer: ServiceTicketCustomer; + customer_subscription_description?: string; + contacts: ServiceTicketContact[]; +} + +export interface ServiceTicketImpactedObject { + impact_override: ServiceTicketImpactedObjectImpact; + subscription_id: string | null; + product_type: string; + logged_by: string; + ims_circuits: ServiceTicketImpactedIMSCircuit[]; + owner_customer: ServiceTicketCustomer; + subscription_description: string; + owner_customer_description?: string; + owner_customer_contacts: ServiceTicketContact[]; + related_customers: ServiceTicketRelatedCustomer[]; +} + +export enum ServiceTicketType { + PLANNED_WORK = 'planned work', + INCIDENT = 'incident', +} + +export interface BackgroundJobLog { + message: string; + customer_id?: string; + subscription_id?: string; + entry_time: string; + process_state: string; + context: object; +} + +export interface Email { + customer: ServiceTicketCustomer; + message: string; + to: ServiceTicketContact[]; + cc: ServiceTicketContact[]; + bcc: ServiceTicketContact[]; + language: string; +} + +export interface EmailLog { + entry_time: string; + log_type: string; + // emails: any; +} + +export interface ServiceTicketWithDetails extends ServiceTicketDefinition { + // transitioning_state: any; + end_date: string; + last_update_time: string; + type: ServiceTicketType; + logs: ServiceTicketLog[]; + impacted_objects: ServiceTicketImpactedObject[]; + background_logs: BackgroundJobLog[]; + email_logs: EmailLog[]; +} + +export interface ImsInfo { + impact: ServiceTicketImpactedObjectImpact; + ims_circuit_id: number; + ims_circuit_name: string; + extra_information?: string; +} + +export interface ImpactedObject { + id: string; + customer: string; + impact: ServiceTicketImpactedObjectImpact; + type: string; + subscription: string; + impact_override?: ServiceTicketImpactedObjectImpact; + subscription_id: string | null; + ims_info: ImsInfo[]; + owner_customer_contacts: ServiceTicketContact[]; + related_customers: ServiceTicketRelatedCustomer[]; +} + +export enum Locale { + enUS = 'en-Us', + nlNL = 'nl-NL', +} diff --git a/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx b/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx index 685baf6cf..8b6bdde48 100644 --- a/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx @@ -10,7 +10,6 @@ import { PATH_METADATA_RESOURCE_TYPES, PATH_METADATA_WORKFLOWS, PATH_PROCESSES, - PATH_SERVICE_TICKETS, PATH_SETTINGS, PATH_START, PATH_SUBSCRIPTIONS, @@ -131,16 +130,6 @@ export const WfoSidebar: FC = ({ overrideMenuItems }) => { }, href: PATH_SETTINGS, }, - { - name: 'Service Tickets', - id: '8', - isSelected: router.pathname === PATH_SERVICE_TICKETS, - href: PATH_SERVICE_TICKETS, - onClick: (e) => { - e.preventDefault(); - router.push(PATH_SERVICE_TICKETS); - }, - }, ]; const defaultMenu: EuiSideNavItemType[] = [ diff --git a/packages/orchestrator-ui-components/src/components/WfoPageTemplate/paths.ts b/packages/orchestrator-ui-components/src/components/WfoPageTemplate/paths.ts index db9596dd3..fe8203b5e 100644 --- a/packages/orchestrator-ui-components/src/components/WfoPageTemplate/paths.ts +++ b/packages/orchestrator-ui-components/src/components/WfoPageTemplate/paths.ts @@ -9,4 +9,3 @@ export const PATH_METADATA_RESOURCE_TYPES = '/metadata/resource-types'; export const PATH_METADATA_WORKFLOWS = '/metadata/workflows'; export const PATH_TASKS = '/tasks'; export const PATH_SETTINGS = '/settings'; -export const PATH_SERVICE_TICKETS = '/service-tickets'; From 1b69d2dd8fbfba725c1d752acb136eef2369dc81 Mon Sep 17 00:00:00 2001 From: Georgi Manev Date: Thu, 2 Nov 2023 11:07:39 +0100 Subject: [PATCH 07/13] 411: Removed surf package --- packages/surf/.storybook/main.js | 28 -- packages/surf/.storybook/preview.js | 14 - packages/surf/CHANGELOG.md | 4 - packages/surf/eslintrc.js | 3 - packages/surf/jest.config.cjs | 7 - packages/surf/package.json | 71 ----- .../WfoServiceTicketsList.tsx | 288 ------------------ .../getServiceTicketListTabTypeFromString.ts | 19 -- .../components/WfoServiceTicketsList/index.ts | 1 - .../mapServiceTicketStateToColor.ts | 39 --- packages/surf/src/components/index.ts | 1 - packages/surf/src/constants.ts | 7 - packages/surf/src/index.ts | 2 - packages/surf/src/messages/en-US.json | 17 -- .../messages/getTranslationMessages.spec.ts | 51 ---- .../src/messages/getTranslationMessages.ts | 26 -- packages/surf/src/messages/index.ts | 1 - packages/surf/src/messages/nl-NL.json | 17 -- .../pages/cim/WfoServiceTicketListPage.tsx | 106 ------- packages/surf/src/pages/cim/index.ts | 2 - packages/surf/src/pages/cim/tabConfig.ts | 53 ---- packages/surf/src/pages/index.ts | 1 - packages/surf/src/types/index.ts | 1 - packages/surf/src/types/types.ts | 207 ------------- packages/surf/tsconfig.build.json | 14 - packages/surf/tsconfig.json | 16 - 26 files changed, 996 deletions(-) delete mode 100644 packages/surf/.storybook/main.js delete mode 100644 packages/surf/.storybook/preview.js delete mode 100644 packages/surf/CHANGELOG.md delete mode 100644 packages/surf/eslintrc.js delete mode 100644 packages/surf/jest.config.cjs delete mode 100644 packages/surf/package.json delete mode 100644 packages/surf/src/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx delete mode 100644 packages/surf/src/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts delete mode 100644 packages/surf/src/components/WfoServiceTicketsList/index.ts delete mode 100644 packages/surf/src/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts delete mode 100644 packages/surf/src/components/index.ts delete mode 100644 packages/surf/src/constants.ts delete mode 100644 packages/surf/src/index.ts delete mode 100644 packages/surf/src/messages/en-US.json delete mode 100644 packages/surf/src/messages/getTranslationMessages.spec.ts delete mode 100644 packages/surf/src/messages/getTranslationMessages.ts delete mode 100644 packages/surf/src/messages/index.ts delete mode 100644 packages/surf/src/messages/nl-NL.json delete mode 100644 packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx delete mode 100644 packages/surf/src/pages/cim/index.ts delete mode 100644 packages/surf/src/pages/cim/tabConfig.ts delete mode 100644 packages/surf/src/pages/index.ts delete mode 100644 packages/surf/src/types/index.ts delete mode 100644 packages/surf/src/types/types.ts delete mode 100644 packages/surf/tsconfig.build.json delete mode 100644 packages/surf/tsconfig.json diff --git a/packages/surf/.storybook/main.js b/packages/surf/.storybook/main.js deleted file mode 100644 index adc97d539..000000000 --- a/packages/surf/.storybook/main.js +++ /dev/null @@ -1,28 +0,0 @@ -import { join, dirname } from 'path'; - -/** - * This function is used to resolve the absolute path of a package. - * It is needed in projects that use Yarn PnP or are set up within a monorepo. - */ -function getAbsolutePath(value) { - return dirname(require.resolve(join(value, 'package.json'))); -} - -/** @type { import('@storybook/nextjs').StorybookConfig } */ -const config = { - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], - addons: [ - getAbsolutePath('@storybook/addon-links'), - getAbsolutePath('@storybook/addon-essentials'), - getAbsolutePath('@storybook/addon-onboarding'), - getAbsolutePath('@storybook/addon-interactions'), - ], - framework: { - name: getAbsolutePath('@storybook/nextjs'), - options: {}, - }, - docs: { - autodocs: 'tag', - }, -}; -export default config; diff --git a/packages/surf/.storybook/preview.js b/packages/surf/.storybook/preview.js deleted file mode 100644 index 074832a12..000000000 --- a/packages/surf/.storybook/preview.js +++ /dev/null @@ -1,14 +0,0 @@ -/** @type { import('@storybook/react').Preview } */ -const preview = { - parameters: { - actions: { argTypesRegex: '^on[A-Z].*' }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/, - }, - }, - }, -}; - -export default preview; diff --git a/packages/surf/CHANGELOG.md b/packages/surf/CHANGELOG.md deleted file mode 100644 index f4150f31f..000000000 --- a/packages/surf/CHANGELOG.md +++ /dev/null @@ -1,4 +0,0 @@ -# @orchestrator-ui/surf - -## 0.1.0 - diff --git a/packages/surf/eslintrc.js b/packages/surf/eslintrc.js deleted file mode 100644 index afa84f0b8..000000000 --- a/packages/surf/eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ['@orchestrator-ui/eslint-config-custom'], -}; diff --git a/packages/surf/jest.config.cjs b/packages/surf/jest.config.cjs deleted file mode 100644 index ad618d123..000000000 --- a/packages/surf/jest.config.cjs +++ /dev/null @@ -1,7 +0,0 @@ -const base = require('@orchestrator-ui/jest-config/jest-base.config.js'); - -module.exports = { - ...base, - name: 'surf', - displayName: 'Surf Components Tests', -}; diff --git a/packages/surf/package.json b/packages/surf/package.json deleted file mode 100644 index 562d2a2ee..000000000 --- a/packages/surf/package.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "name": "@orchestrator-ui/surf", - "private": true, - "version": "0.1.0", - "license": "MIT", - "scripts": { - "test": "jest --passWithNoTests", - "build": "tsup src/index.ts --format esm --dts --tsconfig tsconfig.build.json", - "tsc": "tsc --noEmit", - "lint": "eslint \"src/**/*.ts*\"", - "dev": "yarn build -- --watch", - "storybook": "storybook dev -p 6006", - "build-storybook": "storybook build", - "reset": "rm -rf node_modules" - }, - "dependencies": { - "@orchestrator-ui/orchestrator-ui-components": "*", - "@graphql-typed-document-node/core": "3.2.0", - "axios": "^0.24.0", - "invariant": "^2.2.4", - "moment": "2.29.4", - "object-hash": "^2.1.1", - "use-query-params": "2.2.1", - "uniforms": "^3.8.1", - "uniforms-bridge-json-schema": "^3.8.1", - "uniforms-unstyled": "^3.8.1" - }, - "peerDependencies": { - "@elastic/eui": "^88.1.0", - "@emotion/css": "^11.11.2", - "@emotion/react": "^11.11.1", - "graphql-request": "5.2.0", - "next": "^13.4.1", - "next-intl": "2.19.0", - "next-query-params": "4.2.2", - "react": "^18.2.0", - "react-query": "3.39.3" - }, - "devDependencies": { - "@orchestrator-ui/eslint-config-custom": "*", - "@orchestrator-ui/jest-config": "*", - "@storybook/addon-essentials": "^7.2.1", - "@storybook/addon-interactions": "^7.2.1", - "@storybook/addon-links": "^7.2.1", - "@storybook/addon-onboarding": "^1.0.8", - "@storybook/blocks": "^7.2.1", - "@storybook/nextjs": "^7.2.1", - "@storybook/react": "^7.2.1", - "@storybook/testing-library": "^0.2.0", - "@testing-library/jest-dom": "^5.16.1", - "@testing-library/react": "^14.0.0", - "@testing-library/react-hooks": "^8.0.1", - "@testing-library/user-event": "^14.4.3", - "@types/invariant": "^2.2.33", - "@types/jest": "^27.4.0", - "@types/object-hash": "^2.1.0", - "esbuild": "^0.14.10", - "esbuild-jest": "^0.5.0", - "jest": "^27.4.7", - "jest-watch-typeahead": "^1.0.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "storybook": "^7.2.1", - "tsup": "^7.2.0", - "uniforms-bridge-simple-schema-2": "^3.8.1" - }, - "type": "module", - "main": "./dist/index.js", - "browser": "./dist/index.js", - "types": "./dist/index.d.ts" -} diff --git a/packages/surf/src/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx b/packages/surf/src/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx deleted file mode 100644 index 63cb60d1d..000000000 --- a/packages/surf/src/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx +++ /dev/null @@ -1,288 +0,0 @@ -import React, { useState } from 'react'; -import { - Comparators, - Criteria, - EuiFlexGroup, - EuiFlexItem, - EuiTableSortingType, -} from '@elastic/eui'; -import { - ServiceTicketDefinition, - ServiceTicketProcessState, -} from '../../types'; -import { useTranslations } from 'next-intl'; -import { - DataDisplayParams, - FilterQuery, - getSortDirectionFromString, - parseDateToLocaleDateTimeString, - parseIsoString, - SortOrder, - TableColumnKeys, - useOrchestratorTheme, - useQueryWithRest, - WFO_TABLE_COLOR_FIELD, - WfoBadge, - WfoBasicTable, - WfoDataSorting, - WfoDateTime, - WfoTableColumns, -} from '@orchestrator-ui/orchestrator-ui-components'; -import { CIM_TICKETS_ENDPOINT } from '../../constants'; - -const SERVICE_TICKET_FIELD_JIRA_ID: keyof ServiceTicketDefinition = - 'jira_ticket_id'; -const SERVICE_TICKET_FIELD_TITLE: keyof ServiceTicketDefinition = 'title_nl'; -const SERVICE_TICKET_FIELD_PROCESS_STATE: keyof ServiceTicketDefinition = - 'process_state'; -const SERVICE_TICKET_FIELD_OPENED_BY: keyof ServiceTicketDefinition = - 'opened_by'; -const SERVICE_TICKET_FIELD_START_DATE: keyof ServiceTicketDefinition = - 'start_date'; -const SERVICE_TICKET_FIELD_CREATE_DATE: keyof ServiceTicketDefinition = - 'create_date'; -const SERVICE_TICKET_FIELD_LAST_UPDATE: keyof ServiceTicketDefinition = - 'last_update_time'; - -const { NEW, OPEN, OPEN_RELATED, OPEN_ACCEPTED, UPDATED, ABORTED, CLOSED } = - ServiceTicketProcessState; - -export type WfoServiceTicketsListProps = { - alwaysOnFilters?: FilterQuery[]; - defaultHiddenColumns: TableColumnKeys | undefined; - localStorageKey: string; - dataDisplayParams: DataDisplayParams; - setDataDisplayParam: < - DisplayParamKey extends - keyof DataDisplayParams, - >( - prop: DisplayParamKey, - value: DataDisplayParams[DisplayParamKey], - ) => void; - overrideDefaultTableColumns?: ( - defaultTableColumns: WfoTableColumns, - ) => WfoTableColumns; -}; - -export const WfoServiceTicketsList = ({ - alwaysOnFilters, -}: WfoServiceTicketsListProps) => { - const [pageIndex, setPageIndex] = useState(0); - const [pageSize, setPageSize] = useState(5); - const [dataSorting, setDataSorting] = useState< - WfoDataSorting - >({ - field: SERVICE_TICKET_FIELD_LAST_UPDATE, - sortOrder: SortOrder.DESC, - }); - - const t = useTranslations('cim.serviceTickets'); - const { data, isFetching } = useQueryWithRest( - CIM_TICKETS_ENDPOINT, - 'serviceTickets', - alwaysOnFilters, - ); - const { theme, toSecondaryColor } = useOrchestratorTheme(); - - const mapStateToColor = (state: ServiceTicketProcessState) => { - switch (state) { - case OPEN || NEW: - return { - backgroundColor: theme.colors.success, - textColor: theme.colors.successText, - }; - case OPEN_ACCEPTED || OPEN_RELATED: - return { - backgroundColor: theme.colors.warning, - textColor: theme.colors.warningText, - }; - case UPDATED: - return { - backgroundColor: theme.colors.primary, - textColor: theme.colors.primaryText, - }; - case CLOSED || ABORTED: - return { - backgroundColor: theme.colors.lightShade, - textColor: theme.colors.text, - }; - default: - return { - backgroundColor: theme.colors.lightShade, - textColor: theme.colors.text, - }; - } - }; - - const tableColumns: WfoTableColumns = { - color: { - field: WFO_TABLE_COLOR_FIELD, - name: '', - width: '1', - render: (value, object) => ( - - ), - sortable: true, - }, - jira_ticket_id: { - field: SERVICE_TICKET_FIELD_JIRA_ID, - name: t('jiraTicketId'), - width: '100', - //Todo: Fix styling and add color according to State - render: (value) => ( - - {value} - - ), - sortable: true, - }, - title_nl: { - field: SERVICE_TICKET_FIELD_TITLE, - name: t('titleNl'), - width: '300', - }, - process_state: { - field: SERVICE_TICKET_FIELD_PROCESS_STATE, - name: t('processState'), - width: '120', - render: (value, object) => ( - - {value} - - ), - }, - opened_by: { - field: SERVICE_TICKET_FIELD_OPENED_BY, - name: t('openedBy'), - width: '180', - }, - start_date: { - field: SERVICE_TICKET_FIELD_START_DATE, - name: t('startDate'), - width: '150', - render: (date) => , - renderDetails: parseIsoString(parseDateToLocaleDateTimeString), - clipboardText: parseIsoString(parseDateToLocaleDateTimeString), - }, - create_date: { - field: SERVICE_TICKET_FIELD_CREATE_DATE, - name: t('createDate'), - width: '150', - render: (date: string) => ( - {new Date(date).toLocaleDateString()} - ), - }, - last_update_time: { - field: SERVICE_TICKET_FIELD_LAST_UPDATE, - name: t('lastUpdateTime'), - width: '150', - render: (date: string) => ( - {new Date(date).toLocaleString()} - ), - }, - }; - - const onCriteriaChange = ({ - page, - sort, - }: Criteria) => { - if (page) { - const { index: pageIndex, size: pageSize } = page; - setPageIndex(pageIndex); - setPageSize(pageSize); - } - if (sort) { - const { field: sortField, direction: sortDirection } = sort; - const sortOrder = getSortDirectionFromString( - sortDirection, - ) as SortOrder; - setDataSorting({ - field: sortField, - sortOrder: sortOrder, - }); - } - }; - - // Manually handle sorting and pagination of data - const findServiceTickets = ( - serviceTickets: ServiceTicketDefinition[], - pageIndex: number, - pageSize: number, - sortField: keyof ServiceTicketDefinition, - sortDirection: 'asc' | 'desc', - ) => { - let items; - if (sortField) { - items = serviceTickets - .slice(0) - .sort( - Comparators.property( - sortField, - Comparators.default(sortDirection), - ), - ); - } else { - items = serviceTickets; - } - let pageOfItems; - if (!pageIndex && !pageSize) { - pageOfItems = items; - } else { - const startIndex = pageIndex * pageSize; - pageOfItems = items.slice( - startIndex, - Math.min(startIndex + pageSize, serviceTickets.length), - ); - } - return { - pageOfItems, - totalItemCount: serviceTickets.length, - }; - }; - - const { pageOfItems, totalItemCount } = findServiceTickets( - data ? data : [], - pageIndex, - pageSize, - dataSorting.field, - dataSorting.sortOrder.toLowerCase() as 'asc' | 'desc', - ); - const pagination = { - pageIndex: pageIndex, - pageSize: pageSize, - totalItemCount: totalItemCount, - pageSizeOptions: [5, 10, 20], - }; - const sorting: EuiTableSortingType = { - sort: { - field: dataSorting.field, - direction: dataSorting.sortOrder.toLowerCase() as 'asc' | 'desc', - }, - enableAllColumns: true, - readOnly: false, - }; - - return ( - - ); -}; diff --git a/packages/surf/src/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts b/packages/surf/src/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts deleted file mode 100644 index fa0078564..000000000 --- a/packages/surf/src/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { WfoProcessListTabType } from '@orchestrator-ui/orchestrator-ui-components'; - -export const getServiceTicketListTabTypeFromString = ( - tabId?: string, -): WfoProcessListTabType | undefined => { - if (!tabId) { - return undefined; - } - - switch (tabId.toUpperCase()) { - case WfoProcessListTabType.ACTIVE.toString(): - return WfoProcessListTabType.ACTIVE; - case WfoProcessListTabType.COMPLETED.toString(): - return WfoProcessListTabType.COMPLETED; - - default: - return undefined; - } -}; diff --git a/packages/surf/src/components/WfoServiceTicketsList/index.ts b/packages/surf/src/components/WfoServiceTicketsList/index.ts deleted file mode 100644 index ce53af7b4..000000000 --- a/packages/surf/src/components/WfoServiceTicketsList/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './WfoServiceTicketsList'; diff --git a/packages/surf/src/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts b/packages/surf/src/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts deleted file mode 100644 index 5b564c79f..000000000 --- a/packages/surf/src/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { ServiceTicketProcessState } from '../../types'; -import { EuiThemeComputed } from '@elastic/eui/src/services/theme/types'; - -const { NEW, OPEN, OPEN_RELATED, OPEN_ACCEPTED, UPDATED, ABORTED, CLOSED } = - ServiceTicketProcessState; - -// This probably will be subject to change -export const mapStateToColor = ( - state: ServiceTicketProcessState, - theme: EuiThemeComputed, -) => { - switch (state) { - case OPEN || NEW: - return { - backgroundColor: theme.colors.success, - textColor: theme.colors.successText, - }; - case OPEN_ACCEPTED || OPEN_RELATED: - return { - backgroundColor: theme.colors.warning, - textColor: theme.colors.warningText, - }; - case UPDATED: - return { - backgroundColor: theme.colors.primary, - textColor: theme.colors.primaryText, - }; - case CLOSED || ABORTED: - return { - backgroundColor: theme.colors.lightShade, - textColor: theme.colors.text, - }; - default: - return { - backgroundColor: theme.colors.lightShade, - textColor: theme.colors.text, - }; - } -}; diff --git a/packages/surf/src/components/index.ts b/packages/surf/src/components/index.ts deleted file mode 100644 index ce53af7b4..000000000 --- a/packages/surf/src/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './WfoServiceTicketsList'; diff --git a/packages/surf/src/constants.ts b/packages/surf/src/constants.ts deleted file mode 100644 index 1e47dfe95..000000000 --- a/packages/surf/src/constants.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const PATH_SERVICE_TICKETS = '/service-tickets'; -export const CIM_TICKETS_ENDPOINT = '/surf/cim/tickets'; -export const METADATA_SERVICE_TICKETS_ACTIVE_TABLE_LOCAL_STORAGE_KEY = - 'serviceTicketsActiveTable'; -export const ACTIVE_TICKETS_TABLE_LOCAL_STORAGE_KEY = 'activeTicketsTable'; -export const COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY = - 'completedTicketsTable'; diff --git a/packages/surf/src/index.ts b/packages/surf/src/index.ts deleted file mode 100644 index 9d412aac4..000000000 --- a/packages/surf/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './components'; -export * from './pages'; diff --git a/packages/surf/src/messages/en-US.json b/packages/surf/src/messages/en-US.json deleted file mode 100644 index d75644afc..000000000 --- a/packages/surf/src/messages/en-US.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "cim": { - "serviceTickets": { - "jiraTicketId": "Jira ticket", - "titleNl": "Title", - "processState": "State", - "startDate": "Start time", - "openedBy": "Opened by", - "createDate": "Created on", - "lastUpdateTime": "Updated on", - "tabs": { - "active": "Active", - "completed": "Completed" - } - } - } -} diff --git a/packages/surf/src/messages/getTranslationMessages.spec.ts b/packages/surf/src/messages/getTranslationMessages.spec.ts deleted file mode 100644 index 706ff1629..000000000 --- a/packages/surf/src/messages/getTranslationMessages.spec.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { getTranslationMessages } from './getTranslationMessages'; -import { Locale } from '../types'; -import enUS from './en-US.json'; -import nlNL from './nl-NL.json'; - -describe('getTransalationMessages', () => { - it('Returns nl-NL translation when nl-NL locale is requested', () => { - const translation = getTranslationMessages(Locale.nlNL); - expect(translation).toEqual(nlNL); - }); - - it('Returns en-US translation when en-US locale is requested', () => { - const translation = getTranslationMessages(Locale.enUS); - expect(translation).toEqual(enUS); - }); - - it('Returns en-US translation when no locale is requested', () => { - const translation = getTranslationMessages(undefined); - expect(translation).toEqual(enUS); - }); - it('Returns en-US translation unknown locale is requested', () => { - const translation = getTranslationMessages('UNKNOWN-LOCALE'); - expect(translation).toEqual(enUS); - }); - it('Returns custom translation when custom translations map array is provided', () => { - const customEN = { - metadata: { - product: { - name: 'CUSTOM-EN-NAME', - }, - }, - }; - - const customMap = new Map([[Locale.enUS, customEN]]); - const translation = getTranslationMessages(Locale.enUS, customMap); - expect(translation).toEqual(customEN); - }); - it('Returns en-Us translation if unknown locale is requested together with custom translations map', () => { - const customEN = { - metadata: { - product: { - name: 'CUSTOM-EN-NAME', - }, - }, - }; - - const customMap = new Map([[Locale.enUS, customEN]]); - const translation = getTranslationMessages('UNKNOWN-LOCALE', customMap); - expect(translation).toEqual(customEN); - }); -}); diff --git a/packages/surf/src/messages/getTranslationMessages.ts b/packages/surf/src/messages/getTranslationMessages.ts deleted file mode 100644 index ab9c3142c..000000000 --- a/packages/surf/src/messages/getTranslationMessages.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { AbstractIntlMessages } from 'next-intl'; - -import { Locale } from '../types'; -import nlNL from './nl-NL.json'; -import enUS from './en-US.json'; - -export type TranslationMessagesMap = Map; - -const standardMessageMap: TranslationMessagesMap = new Map([ - [Locale.enUS, enUS], - [Locale.nlNL, nlNL], -]); - -export const getTranslationMessages = ( - locale: string | undefined, - messages: TranslationMessagesMap = standardMessageMap, -) => { - switch (locale) { - case Locale.enUS: - return messages.get(Locale.enUS); - case Locale.nlNL: - return messages.get(Locale.nlNL); - default: - return messages.get(Locale.enUS); - } -}; diff --git a/packages/surf/src/messages/index.ts b/packages/surf/src/messages/index.ts deleted file mode 100644 index 2ad41be5a..000000000 --- a/packages/surf/src/messages/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './getTranslationMessages'; diff --git a/packages/surf/src/messages/nl-NL.json b/packages/surf/src/messages/nl-NL.json deleted file mode 100644 index d75644afc..000000000 --- a/packages/surf/src/messages/nl-NL.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "cim": { - "serviceTickets": { - "jiraTicketId": "Jira ticket", - "titleNl": "Title", - "processState": "State", - "startDate": "Start time", - "openedBy": "Opened by", - "createDate": "Created on", - "lastUpdateTime": "Updated on", - "tabs": { - "active": "Active", - "completed": "Completed" - } - } - } -} diff --git a/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx b/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx deleted file mode 100644 index 3c80f8bf4..000000000 --- a/packages/surf/src/pages/cim/WfoServiceTicketListPage.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { StringParam, useQueryParam, withDefault } from 'use-query-params'; -import { - DEFAULT_PAGE_SIZE, - SortOrder, - StoredTableConfig, - useDataDisplayParams, - useStoredTableConfig, - WfoFilterTabs, - WfoProcessListTabType, -} from '@orchestrator-ui/orchestrator-ui-components'; -import { ServiceTicketDefinition } from '../../types'; -import { - ACTIVE_TICKETS_TABLE_LOCAL_STORAGE_KEY, - COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY, -} from '../../constants'; -import { useRouter } from 'next/router'; -import { getServiceTicketListTabTypeFromString } from '../../components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString'; -import { defaultServiceTicketsListTabs } from './tabConfig'; -import { EuiPageHeader, EuiSpacer } from '@elastic/eui'; -import { WfoServiceTicketsList } from '../../components'; - -export const WfoServiceTicketListPage = () => { - const router = useRouter(); - - const [activeTab, setActiveTab] = useQueryParam( - 'activeTab', - withDefault(StringParam, WfoProcessListTabType.ACTIVE), - ); - - const [tableDefaults, setTableDefaults] = - useState>(); - - const selectedServiceTicketListTab = - getServiceTicketListTabTypeFromString(activeTab); - - const localStorageKey = - selectedServiceTicketListTab === WfoProcessListTabType.ACTIVE - ? ACTIVE_TICKETS_TABLE_LOCAL_STORAGE_KEY - : COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY; - - const getStoredTableConfig = - useStoredTableConfig(localStorageKey); - - useEffect(() => { - const storedConfig = getStoredTableConfig(); - - if (storedConfig) { - setTableDefaults(storedConfig); - } - }, [getStoredTableConfig]); - - const { dataDisplayParams, setDataDisplayParam } = - useDataDisplayParams({ - // TODO: Improvement: A default pageSize value is set to avoid a graphql error when the query is executed - // the fist time before the useEffect has populated the tableDefaults. Better is to create a way for - // the query to wait for the values to be available - // https://github.com/workfloworchestrator/orchestrator-ui/issues/261 - pageSize: tableDefaults?.selectedPageSize || DEFAULT_PAGE_SIZE, - sortBy: { - field: 'last_update_time', - order: SortOrder.DESC, - }, - }); - - const handleChangeServiceTicketListTab = ( - updatedServiceTicketListTab: WfoProcessListTabType, - ) => { - setActiveTab(updatedServiceTicketListTab); - setDataDisplayParam('pageIndex', 0); - }; - - const alwaysOnFilters = defaultServiceTicketsListTabs.find( - ({ id }) => id === selectedServiceTicketListTab, - )?.alwaysOnFilters; - - if (!selectedServiceTicketListTab) { - router.replace('/service-tickets'); - return null; - } - - return ( - <> - - - - - - - - - - - ); -}; diff --git a/packages/surf/src/pages/cim/index.ts b/packages/surf/src/pages/cim/index.ts deleted file mode 100644 index 84c0d666e..000000000 --- a/packages/surf/src/pages/cim/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from '../../components/WfoServiceTicketsList/WfoServiceTicketsList'; -export * from './WfoServiceTicketListPage'; diff --git a/packages/surf/src/pages/cim/tabConfig.ts b/packages/surf/src/pages/cim/tabConfig.ts deleted file mode 100644 index 65ae778a5..000000000 --- a/packages/surf/src/pages/cim/tabConfig.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { - WfoFilterTab, - WfoProcessListTabType, -} from '@orchestrator-ui/orchestrator-ui-components'; -import { - ServiceTicketDefinition, - ServiceTicketProcessState, -} from '../../types'; -export const defaultServiceTicketsListTabs: WfoFilterTab< - WfoProcessListTabType, - ServiceTicketDefinition ->[] = [ - { - id: WfoProcessListTabType.ACTIVE, - translationKey: 'active', - alwaysOnFilters: [ - { - field: 'process_state', - value: ServiceTicketProcessState.OPEN, - }, - { - field: 'process_state', - value: ServiceTicketProcessState.OPEN_ACCEPTED, - }, - { - field: 'process_state', - value: ServiceTicketProcessState.UPDATED, - }, - { - field: 'process_state', - value: ServiceTicketProcessState.NEW, - }, - { - field: 'process_state', - value: ServiceTicketProcessState.OPEN_RELATED, - }, - ], - }, - { - id: WfoProcessListTabType.COMPLETED, - translationKey: 'completed', - alwaysOnFilters: [ - { - field: 'process_state', - value: ServiceTicketProcessState.CLOSED, - }, - { - field: 'process_state', - value: ServiceTicketProcessState.ABORTED, - }, - ], - }, -]; diff --git a/packages/surf/src/pages/index.ts b/packages/surf/src/pages/index.ts deleted file mode 100644 index 7c7325db3..000000000 --- a/packages/surf/src/pages/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './cim'; diff --git a/packages/surf/src/types/index.ts b/packages/surf/src/types/index.ts deleted file mode 100644 index fcb073fef..000000000 --- a/packages/surf/src/types/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './types'; diff --git a/packages/surf/src/types/types.ts b/packages/surf/src/types/types.ts deleted file mode 100644 index 3b188c9c9..000000000 --- a/packages/surf/src/types/types.ts +++ /dev/null @@ -1,207 +0,0 @@ -/** CIM */ -import { Process } from '@orchestrator-ui/orchestrator-ui-components'; - -export interface CreateServiceTicketPayload { - ims_pw_id: string; - jira_ticket_id: string; - title_nl: string; - type: ServiceTicketType; -} - -export interface OpenServiceTicketPayload { - cim_ticket_id: string; - title_nl: string; - description_nl: string; - title_en: string; - description_en: string; - mail_subject: string; -} - -export interface UpdateServiceTicketPayload extends OpenServiceTicketPayload { - start_date?: string; - end_date?: string; -} - -export interface CloseServiceTicketPayload extends OpenServiceTicketPayload { - end_date?: string; -} - -export enum ServiceTicketProcessState { - NEW = 'new', - OPEN = 'open', - OPEN_RELATED = 'open_related', - OPEN_ACCEPTED = 'open_accepted', - UPDATED = 'updated', - ABORTED = 'aborted', - CLOSED = 'closed', -} - -export enum ServiceTicketTransition { - RELATING = 'relating', - ACCEPTING = 'accepting', - ABORTING = 'aborting', - OPENING = 'opening', - OPEN_AND_CLOSE = 'open_and_close', - UPDATING = 'updating', - CLOSING = 'closing', - CLEANING = 'cleaning', -} - -export type ServiceTicketDefinition = { - color?: string; - jira_ticket_id: string; - opened_by: string; - process_state: ServiceTicketProcessState; - start_date: string; - create_date: string; - last_update_time: string; - title_nl: string; -}; - -export type ServiceTicketListItem = Pick< - Process, - | 'workflowName' - | 'lastStep' - | 'lastStatus' - | 'workflowTarget' - | 'createdBy' - | 'assignee' - | 'processId' - | 'subscriptions' -> & { - startedAt: Date; - lastModifiedAt: Date; - productName?: string; - productTag?: string; - customer: string; - customerAbbreviation: string; -}; - -export enum ServiceTicketLogType { - OPEN = 'open', - UPDATE = 'update', - CLOSE = 'close', -} - -export interface ServiceTicketLog { - entry_time: string; - update_nl: string; - update_en: string; - log_type: ServiceTicketLogType; - logged_by: string; - transition: ServiceTicketTransition; - completed: boolean; -} - -export enum ServiceTicketImpactedObjectImpact { - DOWN = 'down', - NO_IMPACT = 'no_impact', - REDUCED_REDUNDANCY = 'reduced_redundancy', - RESILIENCE_LOSS = 'resilience_loss', -} - -export interface ServiceTicketImpactedIMSCircuit { - ims_circuit_id: number; - ims_circuit_name: string; - impact: ServiceTicketImpactedObjectImpact; - extra_information?: string; -} - -export interface ServiceTicketCustomer { - customer_id: string; - customer_name: string; - customer_abbrev: string; -} -export interface ServiceTicketBackgroundJobCount { - number_of_active_jobs: number; -} - -export interface ServiceTicketContact { - name: string; - email: string; - // Todo: add phone? -} - -export interface ServiceTicketRelatedCustomer { - customer: ServiceTicketCustomer; - customer_subscription_description?: string; - contacts: ServiceTicketContact[]; -} - -export interface ServiceTicketImpactedObject { - impact_override: ServiceTicketImpactedObjectImpact; - subscription_id: string | null; - product_type: string; - logged_by: string; - ims_circuits: ServiceTicketImpactedIMSCircuit[]; - owner_customer: ServiceTicketCustomer; - subscription_description: string; - owner_customer_description?: string; - owner_customer_contacts: ServiceTicketContact[]; - related_customers: ServiceTicketRelatedCustomer[]; -} - -export enum ServiceTicketType { - PLANNED_WORK = 'planned work', - INCIDENT = 'incident', -} - -export interface BackgroundJobLog { - message: string; - customer_id?: string; - subscription_id?: string; - entry_time: string; - process_state: string; - context: object; -} - -export interface Email { - customer: ServiceTicketCustomer; - message: string; - to: ServiceTicketContact[]; - cc: ServiceTicketContact[]; - bcc: ServiceTicketContact[]; - language: string; -} - -export interface EmailLog { - entry_time: string; - log_type: string; - // emails: any; -} - -export interface ServiceTicketWithDetails extends ServiceTicketDefinition { - // transitioning_state: any; - end_date: string; - last_update_time: string; - type: ServiceTicketType; - logs: ServiceTicketLog[]; - impacted_objects: ServiceTicketImpactedObject[]; - background_logs: BackgroundJobLog[]; - email_logs: EmailLog[]; -} - -export interface ImsInfo { - impact: ServiceTicketImpactedObjectImpact; - ims_circuit_id: number; - ims_circuit_name: string; - extra_information?: string; -} - -export interface ImpactedObject { - id: string; - customer: string; - impact: ServiceTicketImpactedObjectImpact; - type: string; - subscription: string; - impact_override?: ServiceTicketImpactedObjectImpact; - subscription_id: string | null; - ims_info: ImsInfo[]; - owner_customer_contacts: ServiceTicketContact[]; - related_customers: ServiceTicketRelatedCustomer[]; -} - -export enum Locale { - enUS = 'en-Us', - nlNL = 'nl-NL', -} diff --git a/packages/surf/tsconfig.build.json b/packages/surf/tsconfig.build.json deleted file mode 100644 index 9b43deee6..000000000 --- a/packages/surf/tsconfig.build.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "@orchestrator-ui/tsconfig/base.json", - "compilerOptions": { - "strictNullChecks": true - }, - "include": ["**/*.ts", "**/*.tsx"], - "exclude": [ - "node_modules", - "**/*.stories.ts", - "**/*.stories.js", - "**/*.stories.jsx", - "**/*.stories.tsx" - ] -} diff --git a/packages/surf/tsconfig.json b/packages/surf/tsconfig.json deleted file mode 100644 index 44bca3a11..000000000 --- a/packages/surf/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": "@orchestrator-ui/tsconfig/base.json", - "compilerOptions": { - "strictNullChecks": true, - "rootDir": "./src", - "outDir": "./dist" - }, - "include": ["./src/**/*.ts", "./src/**/*.tsx"], - "exclude": [ - "node_modules", - "**/*.stories.ts", - "**/*.stories.js", - "**/*.stories.jsx", - "**/*.stories.tsx" - ] -} From b2c8ddd2163202cbf741e3d30c73517f8d75960d Mon Sep 17 00:00:00 2001 From: Georgi Manev Date: Fri, 3 Nov 2023 13:37:21 +0100 Subject: [PATCH 08/13] Service ticket page in wfo-ui-surf app, + new badge and color components --- .../WfoBadges/WfoServiceTicketStatusBadge.tsx | 75 +++++++++++++++++++ .../WfoServiceTicketsList.tsx | 73 +++++------------- .../WfoServiceTicketListPage.tsx | 26 ++++++- apps/wfo-ui-surf/translations/en-US.json | 4 +- apps/wfo-ui-surf/translations/nl-NL.json | 4 +- apps/wfo-ui-surf/types/types.ts | 2 +- .../WfoTable/WfoBasicTable/WfoBasicTable.tsx | 50 +++++++------ .../WfoBasicTable/WfoStatusColorField.tsx | 44 +++++++++++ .../WfoTable/WfoBasicTable/index.ts | 1 + .../WfoTable/WfoBasicTable/styles.ts | 17 +++-- .../src/components/WfoTable/utils/columns.ts | 8 +- .../src/hooks/DataFetchHooks.ts | 2 +- .../src/hooks/useOrchestratorTheme.ts | 3 + .../src/icons/WfoArrowNarrowDown.tsx | 1 + .../src/icons/WfoArrowNarrowUp.tsx | 1 + 15 files changed, 221 insertions(+), 90 deletions(-) create mode 100644 apps/wfo-ui-surf/components/WfoBadges/WfoServiceTicketStatusBadge.tsx create mode 100644 packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx diff --git a/apps/wfo-ui-surf/components/WfoBadges/WfoServiceTicketStatusBadge.tsx b/apps/wfo-ui-surf/components/WfoBadges/WfoServiceTicketStatusBadge.tsx new file mode 100644 index 000000000..1ed7b508f --- /dev/null +++ b/apps/wfo-ui-surf/components/WfoBadges/WfoServiceTicketStatusBadge.tsx @@ -0,0 +1,75 @@ +import { ServiceTicketProcessState } from '../../types'; +import React, { FC } from 'react'; +import { + useOrchestratorTheme, + WfoBadge, +} from '@orchestrator-ui/orchestrator-ui-components'; + +export type WfoProcessStatusBadgeProps = { + serviceTicketState: ServiceTicketProcessState; +}; + +export const WfoServiceTicketStatusBadge: FC = ({ + serviceTicketState, +}) => { + const { theme, toSecondaryColor } = useOrchestratorTheme(); + + const getBadgeColorFromServiceTicketState = () => { + const { + primary, + lightShade, + primaryText, + success, + successText, + text, + warning, + warningText, + } = theme.colors; + + const { + NEW, + OPEN, + OPEN_RELATED, + OPEN_ACCEPTED, + UPDATED, + ABORTED, + CLOSED, + } = ServiceTicketProcessState; + + switch (serviceTicketState) { + case OPEN || NEW: + return { + badgeColor: toSecondaryColor(success), + textColor: successText, + }; + case OPEN_ACCEPTED || OPEN_RELATED: + return { + badgeColor: toSecondaryColor(warning), + textColor: warningText, + }; + case UPDATED: + return { + badgeColor: toSecondaryColor(primary), + textColor: primaryText, + }; + case CLOSED || ABORTED: + return { + badgeColor: toSecondaryColor(lightShade), + textColor: text, + }; + default: + return { + badgeColor: toSecondaryColor(lightShade), + textColor: text, + }; + } + }; + + const { badgeColor, textColor } = getBadgeColorFromServiceTicketState(); + + return ( + + {serviceTicketState.toLowerCase()} + + ); +}; diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx b/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx index e48437d03..6c7f46114 100644 --- a/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx @@ -19,16 +19,17 @@ import { parseIsoString, SortOrder, TableColumnKeys, - useOrchestratorTheme, - useQueryWithRest, - WFO_TABLE_COLOR_FIELD, - WfoBadge, + useFilterQueryWithRest, WfoBasicTable, WfoDataSorting, WfoDateTime, WfoTableColumns, + STATUS_COLOR_FIELD_COLUMN_PROPS, + WfoStatusColorField, + WfoTableColorColumnConfig, } from '@orchestrator-ui/orchestrator-ui-components'; import { CIM_TICKETS_ENDPOINT } from '../../constants-surf'; +import { WfoServiceTicketStatusBadge } from '../WfoBadges/WfoServiceTicketStatusBadge'; const SERVICE_TICKET_FIELD_JIRA_ID: keyof ServiceTicketDefinition = 'jira_ticket_id'; @@ -77,59 +78,28 @@ export const WfoServiceTicketsList = ({ }); const t = useTranslations('cim.serviceTickets'); - const { data, isFetching } = useQueryWithRest( + const { data, isFetching } = useFilterQueryWithRest( CIM_TICKETS_ENDPOINT, 'serviceTickets', alwaysOnFilters, ); - const { theme, toSecondaryColor } = useOrchestratorTheme(); - const mapStateToColor = (state: ServiceTicketProcessState) => { - switch (state) { - case OPEN || NEW: - return { - backgroundColor: theme.colors.success, - textColor: theme.colors.successText, - }; - case OPEN_ACCEPTED || OPEN_RELATED: - return { - backgroundColor: theme.colors.warning, - textColor: theme.colors.warningText, - }; - case UPDATED: - return { - backgroundColor: theme.colors.primary, - textColor: theme.colors.primaryText, - }; - case CLOSED || ABORTED: - return { - backgroundColor: theme.colors.lightShade, - textColor: theme.colors.text, - }; - default: - return { - backgroundColor: theme.colors.lightShade, - textColor: theme.colors.text, - }; - } + const serviceTicketColorMappings = { + success: [OPEN, NEW], + warning: [OPEN_ACCEPTED, OPEN_RELATED], + primary: [UPDATED], + lightShade: [CLOSED, ABORTED], }; const tableColumns: WfoTableColumns = { - color: { - field: WFO_TABLE_COLOR_FIELD, - name: '', - width: '1', + status_color_field: { + ...(STATUS_COLOR_FIELD_COLUMN_PROPS as WfoTableColorColumnConfig), render: (value, object) => ( - ), - sortable: true, }, jira_ticket_id: { field: SERVICE_TICKET_FIELD_JIRA_ID, @@ -153,14 +123,9 @@ export const WfoServiceTicketsList = ({ name: t('processState'), width: '120', render: (value, object) => ( - - {value} - + ), }, opened_by: { diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx index 2a11ade0f..d0e203c38 100644 --- a/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx @@ -17,11 +17,19 @@ import { import { useRouter } from 'next/router'; import { getServiceTicketListTabTypeFromString } from '../WfoServiceTicketsList/getServiceTicketListTabTypeFromString'; import { defaultServiceTicketsListTabs } from './tabConfig'; -import { EuiPageHeader, EuiSpacer } from '@elastic/eui'; +import { + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiPageHeader, + EuiSpacer, +} from '@elastic/eui'; import { WfoServiceTicketsList } from '../WfoServiceTicketsList'; +import { useTranslations } from 'next-intl'; export const WfoServiceTicketListPage = () => { const router = useRouter(); + const t = useTranslations('cim.serviceTickets'); const [activeTab, setActiveTab] = useQueryParam( 'activeTab', @@ -82,8 +90,20 @@ export const WfoServiceTicketListPage = () => { return ( <> - - + + + + + + + {t('newServiceTicket')} + + + = { onUpdateDataSorting?: (updatedDataSorting: WfoDataSorting) => void; onDataSearch?: (updatedDataSearch: WfoDataSearch) => void; sorting?: EuiTableSortingType; - color?: boolean; + hasStatusColorColumn?: boolean; }; export const WfoBasicTable = ({ @@ -56,27 +61,30 @@ export const WfoBasicTable = ({ sorting, }: WfoBasicTableProps) => { const { theme } = useOrchestratorTheme(); - const { basicTableStyle, basicTableWithColorColumn } = getStyles(theme); - const styles = columns.hasOwnProperty(WFO_TABLE_COLOR_FIELD) - ? basicTableWithColorColumn + const { basicTableStyle, basicTableWithStatusColorColumn } = + getStyles(theme); + const styles = columns.hasOwnProperty(WFO_STATUS_COLOR_FIELD) + ? basicTableWithStatusColorColumn : basicTableStyle; return ( - + + + ); }; diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx new file mode 100644 index 000000000..df1c37bed --- /dev/null +++ b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { EuiFlexItem } from '@elastic/eui'; +import { useOrchestratorTheme } from '../../../hooks'; +import { defaultOrchestratorTheme } from '../../../theme'; +import { WFO_STATUS_COLOR_FIELD } from '../utils/columns'; + +export type WfoStatusColorFieldProps = { + colorMappings: { [key: string]: string[] }; + state: string; +}; + +export const STATUS_COLOR_FIELD_COLUMN_PROPS = { + field: WFO_STATUS_COLOR_FIELD, + name: '', + width: '1', +}; + +type ThemeType = typeof defaultOrchestratorTheme; + +export const WfoStatusColorField = ({ + colorMappings, + state, +}: WfoStatusColorFieldProps) => { + const { theme, toStatusColorFieldColor } = useOrchestratorTheme(); + let color: keyof ThemeType['colors'] = + 'lightShade' as keyof ThemeType['colors']; + + for (const [colorName, states] of Object.entries(colorMappings)) { + if (states.includes(state)) { + color = colorName as keyof ThemeType['colors']; + break; + } + } + + return ( + + ); +}; diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/index.ts b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/index.ts index 3d6bb6881..64cd61bc2 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/index.ts +++ b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/index.ts @@ -1,3 +1,4 @@ export * from './WfoBasicTable'; export * from './WfoSortDirectionIcon'; export * from './WfoTableHeaderCell'; +export * from './WfoStatusColorField'; diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/styles.ts b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/styles.ts index b7e6d68ff..b07c51e5e 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/styles.ts +++ b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/styles.ts @@ -48,20 +48,25 @@ export const getStyles = (theme: EuiThemeComputed) => { cursor: isSortable ? 'pointer' : 'not-allowed', }); - const basicTableWithColorColumn = css( + const basicTableWithStatusColorColumn = css( { - '.euiTableHeaderCell': { + '.wfoBasicTable thead td': { paddingBlock: 8, paddingLeft: 8, }, - '.euiTableCellContent:first-child': { + '.wfoBasicTable thead th': { + paddingBlock: 8, + paddingLeft: 8, + }, + '.wfoBasicTable thead th button span:first-child': { padding: 0, border: 0, }, - '.euiTableRowCell:first-child': { + '.wfoBasicTable tbody tr td div:first-child': { padding: 0, + border: 0, }, - '.euiTableSortIcon': { + '.wfoBasicTable thead svg:not(.wfoArrowNarrowIcon)': { display: 'none', }, }, @@ -70,7 +75,7 @@ export const getStyles = (theme: EuiThemeComputed) => { return { basicTableStyle, - basicTableWithColorColumn, + basicTableWithStatusColorColumn, headerCellContentStyle, headerCellPopoverHeaderStyle, headerCellPopoverHeaderTitleStyle, diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts b/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts index 304d090e8..6875a0ff5 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts +++ b/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts @@ -14,6 +14,12 @@ export type WfoTableDataColumnConfig = filterable?: boolean; }; +export const WFO_STATUS_COLOR_FIELD = 'status_color_field'; +export type WfoTableColorColumnConfig = WfoTableDataColumnConfig< + T, + typeof WFO_STATUS_COLOR_FIELD +>; + // Todo need to Pick a few props from EuiBasicTableColumn to prevent none-functioning props (truncateText) export type WfoTableColumnsWithExtraNonDataFields = WfoTableColumns & { [key: string]: EuiBasicTableColumn & { @@ -66,5 +72,3 @@ export const getSortDirectionFromString = ( return undefined; } }; - -export const WFO_TABLE_COLOR_FIELD = 'color'; diff --git a/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts b/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts index 308aa9002..11f2fe68c 100644 --- a/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts +++ b/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts @@ -100,7 +100,7 @@ const filterDataByCriteria = ( }); }; -export const useQueryWithRest = ( +export const useFilterQueryWithRest = ( endpoint: string, queryKey: string, filters?: GraphqlFilter[], diff --git a/packages/orchestrator-ui-components/src/hooks/useOrchestratorTheme.ts b/packages/orchestrator-ui-components/src/hooks/useOrchestratorTheme.ts index d5a3d894f..97bd12ea2 100644 --- a/packages/orchestrator-ui-components/src/hooks/useOrchestratorTheme.ts +++ b/packages/orchestrator-ui-components/src/hooks/useOrchestratorTheme.ts @@ -8,9 +8,12 @@ export const useOrchestratorTheme = () => { const toSecondaryColor = (color: string) => tint(color, 0.8); + const toStatusColorFieldColor = (color: string) => tint(color, 0.3); + return { theme: euiTheme, multiplyByBaseUnit, toSecondaryColor, + toStatusColorFieldColor, }; }; diff --git a/packages/orchestrator-ui-components/src/icons/WfoArrowNarrowDown.tsx b/packages/orchestrator-ui-components/src/icons/WfoArrowNarrowDown.tsx index 89ba10ab9..8736f821a 100644 --- a/packages/orchestrator-ui-components/src/icons/WfoArrowNarrowDown.tsx +++ b/packages/orchestrator-ui-components/src/icons/WfoArrowNarrowDown.tsx @@ -12,6 +12,7 @@ export const WfoArrowNarrowDown: FC = ({ viewBox="0 0 16 20" version="1.1" xmlns="http://www.w3.org/2000/svg" + className="wfoArrowNarrowIcon" > icon/arrow-narrow-down = ({ viewBox="0 0 16 20" version="1.1" xmlns="http://www.w3.org/2000/svg" + className="wfoArrowNarrowIcon" > icon/arrow-narrow-up Date: Mon, 6 Nov 2023 14:14:48 +0100 Subject: [PATCH 09/13] 411: Some fixes and refactoring --- .../WfoBadges/WfoServiceTicketStatusBadge.tsx | 9 +++-- .../WfoServiceTicketsList.tsx | 4 +- .../getServiceTicketListTabTypeFromString.ts | 12 +++--- .../mapServiceTicketStateToColor.ts | 39 ------------------- .../WfoServiceTicketListPage.tsx | 14 ++++--- .../WfoServiceTicketsListPage/tabConfig.ts | 12 +++--- apps/wfo-ui-surf/types/types.ts | 5 +++ .../WfoBasicTable/WfoStatusColorField.tsx | 4 ++ 8 files changed, 36 insertions(+), 63 deletions(-) delete mode 100644 apps/wfo-ui-surf/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts diff --git a/apps/wfo-ui-surf/components/WfoBadges/WfoServiceTicketStatusBadge.tsx b/apps/wfo-ui-surf/components/WfoBadges/WfoServiceTicketStatusBadge.tsx index 1ed7b508f..2873a4fdf 100644 --- a/apps/wfo-ui-surf/components/WfoBadges/WfoServiceTicketStatusBadge.tsx +++ b/apps/wfo-ui-surf/components/WfoBadges/WfoServiceTicketStatusBadge.tsx @@ -37,12 +37,14 @@ export const WfoServiceTicketStatusBadge: FC = ({ } = ServiceTicketProcessState; switch (serviceTicketState) { - case OPEN || NEW: + case OPEN: + case NEW: return { badgeColor: toSecondaryColor(success), textColor: successText, }; - case OPEN_ACCEPTED || OPEN_RELATED: + case OPEN_ACCEPTED: + case OPEN_RELATED: return { badgeColor: toSecondaryColor(warning), textColor: warningText, @@ -52,7 +54,8 @@ export const WfoServiceTicketStatusBadge: FC = ({ badgeColor: toSecondaryColor(primary), textColor: primaryText, }; - case CLOSED || ABORTED: + case CLOSED: + case ABORTED: return { badgeColor: toSecondaryColor(lightShade), textColor: text, diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx b/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx index 6c7f46114..740252e57 100644 --- a/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx @@ -18,15 +18,15 @@ import { parseDateToLocaleDateTimeString, parseIsoString, SortOrder, + STATUS_COLOR_FIELD_COLUMN_PROPS, TableColumnKeys, useFilterQueryWithRest, WfoBasicTable, WfoDataSorting, WfoDateTime, - WfoTableColumns, - STATUS_COLOR_FIELD_COLUMN_PROPS, WfoStatusColorField, WfoTableColorColumnConfig, + WfoTableColumns, } from '@orchestrator-ui/orchestrator-ui-components'; import { CIM_TICKETS_ENDPOINT } from '../../constants-surf'; import { WfoServiceTicketStatusBadge } from '../WfoBadges/WfoServiceTicketStatusBadge'; diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts b/apps/wfo-ui-surf/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts index fa0078564..ec4262fca 100644 --- a/apps/wfo-ui-surf/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsList/getServiceTicketListTabTypeFromString.ts @@ -1,17 +1,17 @@ -import { WfoProcessListTabType } from '@orchestrator-ui/orchestrator-ui-components'; +import { WfoServiceTicketListTabType } from '../../types'; export const getServiceTicketListTabTypeFromString = ( tabId?: string, -): WfoProcessListTabType | undefined => { +): WfoServiceTicketListTabType | undefined => { if (!tabId) { return undefined; } switch (tabId.toUpperCase()) { - case WfoProcessListTabType.ACTIVE.toString(): - return WfoProcessListTabType.ACTIVE; - case WfoProcessListTabType.COMPLETED.toString(): - return WfoProcessListTabType.COMPLETED; + case WfoServiceTicketListTabType.ACTIVE.toString(): + return WfoServiceTicketListTabType.ACTIVE; + case WfoServiceTicketListTabType.COMPLETED.toString(): + return WfoServiceTicketListTabType.COMPLETED; default: return undefined; diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts b/apps/wfo-ui-surf/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts deleted file mode 100644 index 5b564c79f..000000000 --- a/apps/wfo-ui-surf/components/WfoServiceTicketsList/mapServiceTicketStateToColor.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { ServiceTicketProcessState } from '../../types'; -import { EuiThemeComputed } from '@elastic/eui/src/services/theme/types'; - -const { NEW, OPEN, OPEN_RELATED, OPEN_ACCEPTED, UPDATED, ABORTED, CLOSED } = - ServiceTicketProcessState; - -// This probably will be subject to change -export const mapStateToColor = ( - state: ServiceTicketProcessState, - theme: EuiThemeComputed, -) => { - switch (state) { - case OPEN || NEW: - return { - backgroundColor: theme.colors.success, - textColor: theme.colors.successText, - }; - case OPEN_ACCEPTED || OPEN_RELATED: - return { - backgroundColor: theme.colors.warning, - textColor: theme.colors.warningText, - }; - case UPDATED: - return { - backgroundColor: theme.colors.primary, - textColor: theme.colors.primaryText, - }; - case CLOSED || ABORTED: - return { - backgroundColor: theme.colors.lightShade, - textColor: theme.colors.text, - }; - default: - return { - backgroundColor: theme.colors.lightShade, - textColor: theme.colors.text, - }; - } -}; diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx index d0e203c38..48fa262fb 100644 --- a/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/WfoServiceTicketListPage.tsx @@ -7,9 +7,11 @@ import { useDataDisplayParams, useStoredTableConfig, WfoFilterTabs, - WfoProcessListTabType, } from '@orchestrator-ui/orchestrator-ui-components'; -import { ServiceTicketDefinition } from '../../types'; +import { + ServiceTicketDefinition, + WfoServiceTicketListTabType, +} from '../../types'; import { ACTIVE_TICKETS_TABLE_LOCAL_STORAGE_KEY, COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY, @@ -33,7 +35,7 @@ export const WfoServiceTicketListPage = () => { const [activeTab, setActiveTab] = useQueryParam( 'activeTab', - withDefault(StringParam, WfoProcessListTabType.ACTIVE), + withDefault(StringParam, WfoServiceTicketListTabType.ACTIVE), ); const [tableDefaults, setTableDefaults] = @@ -43,7 +45,7 @@ export const WfoServiceTicketListPage = () => { getServiceTicketListTabTypeFromString(activeTab); const localStorageKey = - selectedServiceTicketListTab === WfoProcessListTabType.ACTIVE + selectedServiceTicketListTab === WfoServiceTicketListTabType.ACTIVE ? ACTIVE_TICKETS_TABLE_LOCAL_STORAGE_KEY : COMPLETED_TICKETS_TABLE_LOCAL_STORAGE_KEY; @@ -72,7 +74,7 @@ export const WfoServiceTicketListPage = () => { }); const handleChangeServiceTicketListTab = ( - updatedServiceTicketListTab: WfoProcessListTabType, + updatedServiceTicketListTab: WfoServiceTicketListTabType, ) => { setActiveTab(updatedServiceTicketListTab); setDataDisplayParam('pageIndex', 0); @@ -108,7 +110,7 @@ export const WfoServiceTicketListPage = () => { diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/tabConfig.ts b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/tabConfig.ts index 65ae778a5..ccbcf3c9e 100644 --- a/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/tabConfig.ts +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsListPage/tabConfig.ts @@ -1,17 +1,15 @@ -import { - WfoFilterTab, - WfoProcessListTabType, -} from '@orchestrator-ui/orchestrator-ui-components'; +import { WfoFilterTab } from '@orchestrator-ui/orchestrator-ui-components'; import { ServiceTicketDefinition, ServiceTicketProcessState, + WfoServiceTicketListTabType, } from '../../types'; export const defaultServiceTicketsListTabs: WfoFilterTab< - WfoProcessListTabType, + WfoServiceTicketListTabType, ServiceTicketDefinition >[] = [ { - id: WfoProcessListTabType.ACTIVE, + id: WfoServiceTicketListTabType.ACTIVE, translationKey: 'active', alwaysOnFilters: [ { @@ -37,7 +35,7 @@ export const defaultServiceTicketsListTabs: WfoFilterTab< ], }, { - id: WfoProcessListTabType.COMPLETED, + id: WfoServiceTicketListTabType.COMPLETED, translationKey: 'completed', alwaysOnFilters: [ { diff --git a/apps/wfo-ui-surf/types/types.ts b/apps/wfo-ui-surf/types/types.ts index 77c3da5d1..9ea645819 100644 --- a/apps/wfo-ui-surf/types/types.ts +++ b/apps/wfo-ui-surf/types/types.ts @@ -1,6 +1,11 @@ /** CIM */ import { Process } from '@orchestrator-ui/orchestrator-ui-components'; +export enum WfoServiceTicketListTabType { + ACTIVE = 'ACTIVE', + COMPLETED = 'COMPLETED', +} + export interface CreateServiceTicketPayload { ims_pw_id: string; jira_ticket_id: string; diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx index df1c37bed..5fb9ebcbf 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx @@ -9,6 +9,10 @@ export type WfoStatusColorFieldProps = { state: string; }; +/* + Can we have all the definitions (ServiceTicketDefinition, ProductBlockDefinition ...) + extend from a base type? (ex. Definition) +*/ export const STATUS_COLOR_FIELD_COLUMN_PROPS = { field: WFO_STATUS_COLOR_FIELD, name: '', From 39cb5733217fca300755ca08555d261eb76ae3b2 Mon Sep 17 00:00:00 2001 From: Georgi Manev Date: Mon, 6 Nov 2023 14:34:09 +0100 Subject: [PATCH 10/13] 411: Resolved comments --- apps/wfo-ui-surf/types/types.ts | 2 -- .../src/components/WfoProcessesList/WfoProcessList.tsx | 4 ---- .../components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx | 4 ++-- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/apps/wfo-ui-surf/types/types.ts b/apps/wfo-ui-surf/types/types.ts index 9ea645819..1965a4fa3 100644 --- a/apps/wfo-ui-surf/types/types.ts +++ b/apps/wfo-ui-surf/types/types.ts @@ -172,11 +172,9 @@ export interface Email { export interface EmailLog { entry_time: string; log_type: string; - // emails: any; } export interface ServiceTicketWithDetails extends ServiceTicketDefinition { - // transitioning_state: any; end_date: string; last_update_time: string; type: ServiceTicketType; diff --git a/packages/orchestrator-ui-components/src/components/WfoProcessesList/WfoProcessList.tsx b/packages/orchestrator-ui-components/src/components/WfoProcessesList/WfoProcessList.tsx index 27e415c2b..e9e506238 100644 --- a/packages/orchestrator-ui-components/src/components/WfoProcessesList/WfoProcessList.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoProcessesList/WfoProcessList.tsx @@ -75,10 +75,6 @@ export const WfoProcessList: FC = ({ }) => { const t = useTranslations('processes.index'); - console.log('alwaysOnFilters', alwaysOnFilters); - console.log('defaultHiddenColumns', defaultHiddenColumns); - console.log('setDataDisplayParam', setDataDisplayParam); - const defaultTableColumns: WfoTableColumns = { workflowName: { field: 'workflowName', diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx index 5fb9ebcbf..e046fec9f 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx @@ -39,8 +39,8 @@ export const WfoStatusColorField = ({ return ( From 7b2c5465959b4f8da2bcdd68587ebab8f6aa9ce8 Mon Sep 17 00:00:00 2001 From: Georgi Manev Date: Tue, 7 Nov 2023 13:18:31 +0100 Subject: [PATCH 11/13] 411: resolved some comments --- apps/wfo-ui-surf/types/types.ts | 1 - .../WfoBasicTable/WfoStatusColorField.tsx | 16 +++++++--------- .../src/hooks/useOrchestratorTheme.ts | 3 --- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/apps/wfo-ui-surf/types/types.ts b/apps/wfo-ui-surf/types/types.ts index 1965a4fa3..f2d041b8e 100644 --- a/apps/wfo-ui-surf/types/types.ts +++ b/apps/wfo-ui-surf/types/types.ts @@ -124,7 +124,6 @@ export interface ServiceTicketBackgroundJobCount { export interface ServiceTicketContact { name: string; email: string; - // Todo: add phone? } export interface ServiceTicketRelatedCustomer { diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx index e046fec9f..ab1d85dce 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx @@ -1,31 +1,29 @@ import React from 'react'; -import { EuiFlexItem } from '@elastic/eui'; +import { EuiFlexItem, tint } from '@elastic/eui'; import { useOrchestratorTheme } from '../../../hooks'; import { defaultOrchestratorTheme } from '../../../theme'; import { WFO_STATUS_COLOR_FIELD } from '../utils/columns'; +type ThemeType = typeof defaultOrchestratorTheme; + +const toStatusColorFieldColor = (color: string) => tint(color, 0.3); + export type WfoStatusColorFieldProps = { colorMappings: { [key: string]: string[] }; state: string; }; -/* - Can we have all the definitions (ServiceTicketDefinition, ProductBlockDefinition ...) - extend from a base type? (ex. Definition) -*/ export const STATUS_COLOR_FIELD_COLUMN_PROPS = { field: WFO_STATUS_COLOR_FIELD, name: '', width: '1', }; -type ThemeType = typeof defaultOrchestratorTheme; - export const WfoStatusColorField = ({ colorMappings, state, }: WfoStatusColorFieldProps) => { - const { theme, toStatusColorFieldColor } = useOrchestratorTheme(); + const { theme } = useOrchestratorTheme(); let color: keyof ThemeType['colors'] = 'lightShade' as keyof ThemeType['colors']; @@ -40,7 +38,7 @@ export const WfoStatusColorField = ({ diff --git a/packages/orchestrator-ui-components/src/hooks/useOrchestratorTheme.ts b/packages/orchestrator-ui-components/src/hooks/useOrchestratorTheme.ts index 97bd12ea2..d5a3d894f 100644 --- a/packages/orchestrator-ui-components/src/hooks/useOrchestratorTheme.ts +++ b/packages/orchestrator-ui-components/src/hooks/useOrchestratorTheme.ts @@ -8,12 +8,9 @@ export const useOrchestratorTheme = () => { const toSecondaryColor = (color: string) => tint(color, 0.8); - const toStatusColorFieldColor = (color: string) => tint(color, 0.3); - return { theme: euiTheme, multiplyByBaseUnit, toSecondaryColor, - toStatusColorFieldColor, }; }; From 6ed199ad226d1b0c522ac51ab3a5fe1287f9250e Mon Sep 17 00:00:00 2001 From: Ricardo van der Heijden <20791917+ricardovdheijden@users.noreply.github.com> Date: Tue, 7 Nov 2023 16:38:23 +0100 Subject: [PATCH 12/13] 411 Moves the status color column into the basic table --- .../WfoServiceTicketsList.tsx | 28 +++---- apps/wfo-ui-surf/utils/getColorForState.ts | 19 +++++ .../WfoTable/WfoBasicTable/WfoBasicTable.tsx | 78 +++++++++++++------ .../WfoBasicTable/WfoStatusColorField.tsx | 2 +- .../WfoTable/WfoBasicTable/styles.ts | 40 ++++------ 5 files changed, 99 insertions(+), 68 deletions(-) create mode 100644 apps/wfo-ui-surf/utils/getColorForState.ts diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx b/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx index 740252e57..b393b6ae5 100644 --- a/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx @@ -18,18 +18,17 @@ import { parseDateToLocaleDateTimeString, parseIsoString, SortOrder, - STATUS_COLOR_FIELD_COLUMN_PROPS, TableColumnKeys, useFilterQueryWithRest, + useOrchestratorTheme, WfoBasicTable, WfoDataSorting, WfoDateTime, - WfoStatusColorField, - WfoTableColorColumnConfig, WfoTableColumns, } from '@orchestrator-ui/orchestrator-ui-components'; import { CIM_TICKETS_ENDPOINT } from '../../constants-surf'; import { WfoServiceTicketStatusBadge } from '../WfoBadges/WfoServiceTicketStatusBadge'; +import { ColorMappings, getColorForState } from '../../utils/getColorForState'; const SERVICE_TICKET_FIELD_JIRA_ID: keyof ServiceTicketDefinition = 'jira_ticket_id'; @@ -68,6 +67,7 @@ export type WfoServiceTicketsListProps = { export const WfoServiceTicketsList = ({ alwaysOnFilters, }: WfoServiceTicketsListProps) => { + const { theme } = useOrchestratorTheme(); const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(5); const [dataSorting, setDataSorting] = useState< @@ -84,23 +84,14 @@ export const WfoServiceTicketsList = ({ alwaysOnFilters, ); - const serviceTicketColorMappings = { - success: [OPEN, NEW], - warning: [OPEN_ACCEPTED, OPEN_RELATED], - primary: [UPDATED], - lightShade: [CLOSED, ABORTED], + const serviceTicketColorMappings: ColorMappings = { + [theme.colors.success]: [OPEN, NEW], + [theme.colors.warning]: [OPEN_ACCEPTED, OPEN_RELATED], + [theme.colors.primary]: [UPDATED], + [theme.colors.lightShade]: [CLOSED, ABORTED], }; const tableColumns: WfoTableColumns = { - status_color_field: { - ...(STATUS_COLOR_FIELD_COLUMN_PROPS as WfoTableColorColumnConfig), - render: (value, object) => ( - - ), - }, jira_ticket_id: { field: SERVICE_TICKET_FIELD_JIRA_ID, name: t('jiraTicketId'), @@ -248,6 +239,9 @@ export const WfoServiceTicketsList = ({ sorting={sorting} onCriteriaChange={onCriteriaChange} dataSorting={dataSorting} + getStatusColorForRow={(row) => + getColorForState(serviceTicketColorMappings, row.process_state) + } /> ); }; diff --git a/apps/wfo-ui-surf/utils/getColorForState.ts b/apps/wfo-ui-surf/utils/getColorForState.ts new file mode 100644 index 000000000..bd803c6d1 --- /dev/null +++ b/apps/wfo-ui-surf/utils/getColorForState.ts @@ -0,0 +1,19 @@ +import { ServiceTicketProcessState } from '../types'; + +const DEFAULT_COLOR = 'lightShade'; + +export type ColorMappings = { + [key: string]: string[]; +}; + +export const getColorForState = ( + colorMappings: ColorMappings, + state: ServiceTicketProcessState, +): string => { + for (const [colorName, states] of Object.entries(colorMappings)) { + if (states.includes(state)) { + return colorName; + } + } + return DEFAULT_COLOR; +}; diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx index 0636334b5..34dd1909c 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx @@ -2,8 +2,8 @@ import React, { ReactNode } from 'react'; import { EuiBasicTable, EuiBasicTableColumn, - EuiFlexItem, Pagination, + tint, } from '@elastic/eui'; import { Criteria } from '@elastic/eui/src/components/basic_table/basic_table'; import { WfoTableHeaderCell } from './WfoTableHeaderCell'; @@ -45,7 +45,7 @@ export type WfoBasicTableProps = { onUpdateDataSorting?: (updatedDataSorting: WfoDataSorting) => void; onDataSearch?: (updatedDataSearch: WfoDataSearch) => void; sorting?: EuiTableSortingType; - hasStatusColorColumn?: boolean; + getStatusColorForRow?: (row: T) => string; }; export const WfoBasicTable = ({ @@ -59,32 +59,62 @@ export const WfoBasicTable = ({ onUpdateDataSorting, onDataSearch, sorting, + getStatusColorForRow, }: WfoBasicTableProps) => { const { theme } = useOrchestratorTheme(); - const { basicTableStyle, basicTableWithStatusColorColumn } = - getStyles(theme); - const styles = columns.hasOwnProperty(WFO_STATUS_COLOR_FIELD) - ? basicTableWithStatusColorColumn - : basicTableStyle; + const { basicTableStyle, getStatusColumnStyle } = getStyles(theme); + + const toStatusColorFieldColor = (color: string) => tint(color, 0.3); + + const test: WfoTableControlColumnConfig = { + status_color_field: { + field: WFO_STATUS_COLOR_FIELD, + name: '', + width: '8', + render: (_, row) => { + const color = getStatusColorForRow?.(row); + return ( + <> + {color ? ( +
+ ) : null} + + // + ); + }, + }, + }; + + const newColumns: + | WfoBasicTableColumnsWithControlColumns + | WfoBasicTableColumns = { ...test, ...columns }; return ( - - - + ); }; diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx index ab1d85dce..a3dedbe38 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoStatusColorField.tsx @@ -36,7 +36,7 @@ export const WfoStatusColorField = ({ return ( { }, }); + const getStatusColumnStyle = (columnNumber: number) => + css({ + [`tbody tr td:nth-child(${columnNumber}) .euiTableCellContent`]: { + padding: 0, + '.euiTableCellContent__text': { + flex: 1, + '> *': { + paddingBlock: theme.base * 1.25, + }, + }, + }, + }); + const headerCellContentStyle = css({ fontWeight: theme.font.weight.semiBold, }); @@ -48,38 +61,13 @@ export const getStyles = (theme: EuiThemeComputed) => { cursor: isSortable ? 'pointer' : 'not-allowed', }); - const basicTableWithStatusColorColumn = css( - { - '.wfoBasicTable thead td': { - paddingBlock: 8, - paddingLeft: 8, - }, - '.wfoBasicTable thead th': { - paddingBlock: 8, - paddingLeft: 8, - }, - '.wfoBasicTable thead th button span:first-child': { - padding: 0, - border: 0, - }, - '.wfoBasicTable tbody tr td div:first-child': { - padding: 0, - border: 0, - }, - '.wfoBasicTable thead svg:not(.wfoArrowNarrowIcon)': { - display: 'none', - }, - }, - basicTableStyle, - ); - return { basicTableStyle, - basicTableWithStatusColorColumn, headerCellContentStyle, headerCellPopoverHeaderStyle, headerCellPopoverHeaderTitleStyle, headerCellPopoverContentStyle, getHeaderCellButtonStyle, + getStatusColumnStyle, }; }; From b4ab278f46546f14d700801a7982a4859be9bafe Mon Sep 17 00:00:00 2001 From: Georgi Manev Date: Wed, 8 Nov 2023 13:04:38 +0100 Subject: [PATCH 13/13] 411 Resolved all comments --- .../WfoServiceTicketsList.tsx | 88 +++++++++---------- apps/wfo-ui-surf/types/types.ts | 2 +- .../WfoTable/WfoBasicTable/WfoBasicTable.tsx | 61 +++++-------- .../WfoBasicTable/WfoStatusColorField.tsx | 40 ++------- .../src/components/WfoTable/utils/columns.ts | 6 +- .../src/hooks/DataFetchHooks.ts | 4 +- 6 files changed, 73 insertions(+), 128 deletions(-) diff --git a/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx b/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx index b393b6ae5..54dcd1007 100644 --- a/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx +++ b/apps/wfo-ui-surf/components/WfoServiceTicketsList/WfoServiceTicketsList.tsx @@ -1,11 +1,5 @@ import React, { useState } from 'react'; -import { - Comparators, - Criteria, - EuiFlexGroup, - EuiFlexItem, - EuiTableSortingType, -} from '@elastic/eui'; +import { Criteria, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { ServiceTicketDefinition, ServiceTicketProcessState, @@ -13,6 +7,7 @@ import { import { useTranslations } from 'next-intl'; import { DataDisplayParams, + DEFAULT_PAGE_SIZES, FilterQuery, getSortDirectionFromString, parseDateToLocaleDateTimeString, @@ -78,11 +73,13 @@ export const WfoServiceTicketsList = ({ }); const t = useTranslations('cim.serviceTickets'); - const { data, isFetching } = useFilterQueryWithRest( - CIM_TICKETS_ENDPOINT, - 'serviceTickets', - alwaysOnFilters, - ); + + const { data, isFetching } = + useFilterQueryWithRest( + CIM_TICKETS_ENDPOINT, + 'serviceTickets', + alwaysOnFilters, + ); const serviceTicketColorMappings: ColorMappings = { [theme.colors.success]: [OPEN, NEW], @@ -96,7 +93,6 @@ export const WfoServiceTicketsList = ({ field: SERVICE_TICKET_FIELD_JIRA_ID, name: t('jiraTicketId'), width: '100', - //Todo: Fix styling and add color according to State render: (value) => ( {value} @@ -171,33 +167,17 @@ export const WfoServiceTicketsList = ({ } }; - // Manually handle sorting and pagination of data - const findServiceTickets = ( + const paginateServiceTickets = ( serviceTickets: ServiceTicketDefinition[], pageIndex: number, pageSize: number, - sortField: keyof ServiceTicketDefinition, - sortDirection: 'asc' | 'desc', ) => { - let items; - if (sortField) { - items = serviceTickets - .slice(0) - .sort( - Comparators.property( - sortField, - Comparators.default(sortDirection), - ), - ); - } else { - items = serviceTickets; - } let pageOfItems; if (!pageIndex && !pageSize) { - pageOfItems = items; + pageOfItems = serviceTickets; } else { const startIndex = pageIndex * pageSize; - pageOfItems = items.slice( + pageOfItems = serviceTickets.slice( startIndex, Math.min(startIndex + pageSize, serviceTickets.length), ); @@ -208,40 +188,54 @@ export const WfoServiceTicketsList = ({ }; }; - const { pageOfItems, totalItemCount } = findServiceTickets( - data ? data : [], + const sortedData = data?.sort((a, b) => { + const aValue = a[dataSorting.field]; + const bValue = b[dataSorting.field]; + if (aValue === bValue) { + return 0; + } + if (aValue === null || aValue === undefined) { + return 1; + } + if (bValue === null || bValue === undefined) { + return -1; + } + return aValue > bValue + ? dataSorting.sortOrder === SortOrder.ASC + ? 1 + : -1 + : dataSorting.sortOrder === SortOrder.ASC + ? -1 + : 1; + }); + + const { pageOfItems, totalItemCount } = paginateServiceTickets( + sortedData ? sortedData : [], pageIndex, pageSize, - dataSorting.field, - dataSorting.sortOrder.toLowerCase() as 'asc' | 'desc', ); + const pagination = { pageIndex: pageIndex, pageSize: pageSize, totalItemCount: totalItemCount, - pageSizeOptions: [5, 10, 20], - }; - const sorting: EuiTableSortingType = { - sort: { - field: dataSorting.field, - direction: dataSorting.sortOrder.toLowerCase() as 'asc' | 'desc', - }, - enableAllColumns: true, - readOnly: false, + pageSizeOptions: DEFAULT_PAGE_SIZES, }; return ( getColorForState(serviceTicketColorMappings, row.process_state) } + onUpdateDataSorting={(currentSort) => { + setDataSorting(currentSort); + }} /> ); }; diff --git a/apps/wfo-ui-surf/types/types.ts b/apps/wfo-ui-surf/types/types.ts index f2d041b8e..60513f970 100644 --- a/apps/wfo-ui-surf/types/types.ts +++ b/apps/wfo-ui-surf/types/types.ts @@ -53,7 +53,7 @@ export enum ServiceTicketTransition { } export type ServiceTicketDefinition = { - status_color_field?: string; + statusColorField?: string; jira_ticket_id: string; opened_by: string; process_state: ServiceTicketProcessState; diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx index 34dd1909c..be7022eb8 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoTable/WfoBasicTable/WfoBasicTable.tsx @@ -1,10 +1,5 @@ import React, { ReactNode } from 'react'; -import { - EuiBasicTable, - EuiBasicTableColumn, - Pagination, - tint, -} from '@elastic/eui'; +import { EuiBasicTable, EuiBasicTableColumn, Pagination } from '@elastic/eui'; import { Criteria } from '@elastic/eui/src/components/basic_table/basic_table'; import { WfoTableHeaderCell } from './WfoTableHeaderCell'; @@ -21,7 +16,7 @@ import { import { useOrchestratorTheme } from '../../../hooks'; import { getStyles } from './styles'; import { SortOrder } from '../../../types'; -import { EuiTableSortingType } from '@elastic/eui/src/components/basic_table/table_types'; +import { WfoStatusColorField } from './WfoStatusColorField'; export type WfoBasicTableColumns = { [Property in keyof T]: WfoTableDataColumnConfig & { @@ -44,7 +39,6 @@ export type WfoBasicTableProps = { onCriteriaChange?: (criteria: Criteria) => void; onUpdateDataSorting?: (updatedDataSorting: WfoDataSorting) => void; onDataSearch?: (updatedDataSearch: WfoDataSearch) => void; - sorting?: EuiTableSortingType; getStatusColorForRow?: (row: T) => string; }; @@ -58,59 +52,46 @@ export const WfoBasicTable = ({ onCriteriaChange, onUpdateDataSorting, onDataSearch, - sorting, getStatusColorForRow, }: WfoBasicTableProps) => { const { theme } = useOrchestratorTheme(); const { basicTableStyle, getStatusColumnStyle } = getStyles(theme); - const toStatusColorFieldColor = (color: string) => tint(color, 0.3); - - const test: WfoTableControlColumnConfig = { - status_color_field: { + const statusColorColumn: WfoTableControlColumnConfig = { + statusColorField: { field: WFO_STATUS_COLOR_FIELD, name: '', - width: '8', - render: (_, row) => { - const color = getStatusColorForRow?.(row); - return ( - <> - {color ? ( -
- ) : null} - - // - ); - }, + width: theme.size.xs, + render: (_, row) => + getStatusColorForRow ? ( + + ) : ( + <> + ), }, }; - const newColumns: + const allTableColumns: | WfoBasicTableColumnsWithControlColumns - | WfoBasicTableColumns = { ...test, ...columns }; + | WfoBasicTableColumns = getStatusColorForRow + ? { ...statusColorColumn, ...columns } + : { ...columns }; + + const tableStyling = getStatusColorForRow + ? [basicTableStyle, getStatusColumnStyle(1)] + : basicTableStyle; return ( tint(color, 0.3); export type WfoStatusColorFieldProps = { - colorMappings: { [key: string]: string[] }; - state: string; + color: string; }; -export const STATUS_COLOR_FIELD_COLUMN_PROPS = { - field: WFO_STATUS_COLOR_FIELD, - name: '', - width: '1', -}; - -export const WfoStatusColorField = ({ - colorMappings, - state, -}: WfoStatusColorFieldProps) => { - const { theme } = useOrchestratorTheme(); - let color: keyof ThemeType['colors'] = - 'lightShade' as keyof ThemeType['colors']; - - for (const [colorName, states] of Object.entries(colorMappings)) { - if (states.includes(state)) { - color = colorName as keyof ThemeType['colors']; - break; - } - } +const toStatusColorFieldColor = (color: string) => tint(color, 0.3); +export const WfoStatusColorField = ({ color }: WfoStatusColorFieldProps) => { return ( + > ); }; diff --git a/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts b/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts index 6875a0ff5..2f6fb4ac6 100644 --- a/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts +++ b/packages/orchestrator-ui-components/src/components/WfoTable/utils/columns.ts @@ -14,11 +14,7 @@ export type WfoTableDataColumnConfig = filterable?: boolean; }; -export const WFO_STATUS_COLOR_FIELD = 'status_color_field'; -export type WfoTableColorColumnConfig = WfoTableDataColumnConfig< - T, - typeof WFO_STATUS_COLOR_FIELD ->; +export const WFO_STATUS_COLOR_FIELD = 'statusColorField'; // Todo need to Pick a few props from EuiBasicTableColumn to prevent none-functioning props (truncateText) export type WfoTableColumnsWithExtraNonDataFields = WfoTableColumns & { diff --git a/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts b/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts index 11f2fe68c..bfb610363 100644 --- a/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts +++ b/packages/orchestrator-ui-components/src/hooks/DataFetchHooks.ts @@ -110,11 +110,11 @@ export const useFilterQueryWithRest = ( const fetchFromApi = async () => { const response = await fetch(orchestratorApiBaseUrl + endpoint); - const data = await response.json(); + const data = (await response.json()) as Type[]; return filters ? filterDataByCriteria(data, filters) : data; }; - return useQuery( + return useQuery( filters ? [queryKey, { filters }] : [queryKey], fetchFromApi, {