From bed2ac04cd9bd4b6539da54072cf4b912a2b56fb Mon Sep 17 00:00:00 2001 From: Georgi2704 Date: Thu, 23 Jan 2025 17:45:33 +0100 Subject: [PATCH 1/5] Fix notes not cleared when changing pages --- .../WfoInlineNoteEdit/WfoInlineNoteEdit.tsx | 45 ++++++++++++++----- .../WfoSubscriptionsList.tsx | 19 +++++--- .../src/rtk/endpoints/subscriptionList.ts | 32 ++++++++++++- .../src/utils/string.spec.ts | 29 +++++++++++- .../src/utils/strings.ts | 4 ++ 5 files changed, 109 insertions(+), 20 deletions(-) diff --git a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx index 1b96e9c2b..664251786 100644 --- a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx @@ -7,32 +7,55 @@ import { WfoToolTip } from '@/components'; import { useOrchestratorTheme } from '@/hooks'; import { useStartProcessMutation } from '@/rtk/endpoints/forms'; import type { Subscription } from '@/types'; +import { useGetSubscriptionListQuery, useUpdateSubscriptionNoteLocallyMutation } from '@/rtk'; interface WfoInlineNoteEditProps { value: Subscription['note']; - subscriptionId?: Subscription['subscriptionId']; + subscriptionId: Subscription['subscriptionId']; onlyShowOnHover?: boolean; + graphqlQueryVariables: Record; } +// This is an invisible character that is used to get the component re-rendering correctly +const INVISIBLE_CHARACTER = '‎'; + export const WfoInlineNoteEdit: FC = ({ - value, + // value, subscriptionId, onlyShowOnHover = false, + graphqlQueryVariables, }) => { const { theme } = useOrchestratorTheme(); - const [note, setNote] = useState(value ?? ''); + const {subscriptionItem} = useGetSubscriptionListQuery( + graphqlQueryVariables,{ + selectFromResult: (result) => ({subscriptionItem: result?.data?.subscriptions.find((sub) => sub.subscriptionId === subscriptionId)}), + } + ); + + console.log("WfoInlineEditData: ", subscriptionItem); + const noteFromData = subscriptionItem?.note?.trim() ? subscriptionItem.note : INVISIBLE_CHARACTER; + const [note, setNote] = useState(noteFromData); const [isTooltipVisible, setIsTooltipVisible] = useState(true); const [startProcess] = useStartProcessMutation(); + const [updateSub] = useUpdateSubscriptionNoteLocallyMutation(); + + // const store = useStore(); + // const cachedQueies = store.getState().orchestratorApi.queries; + // console.log("Cached Queries: ", cachedQueies); + const triggerNoteModifyWorkflow = () => { const noteModifyPayload = [ { subscription_id: subscriptionId }, - { note }, + { note: (note === INVISIBLE_CHARACTER) ? "" : note }, ]; startProcess({ workflowName: 'modify_note', userInputs: noteModifyPayload, }); + + updateSub({ subscriptionId: subscriptionId, graphQlQueryVariables: graphqlQueryVariables, note: note }); + // console.log("Updated,", updated); }; const handleSave = () => { @@ -41,15 +64,15 @@ export const WfoInlineNoteEdit: FC = ({ }; const handleCancel = () => { - setNote(value ?? ''); + setNote(noteFromData); setIsTooltipVisible(true); }; // This useEffect makes sure the note is updated when a new value property is passed in // for example by a parent component that is update through a websocket event useEffect(() => { - setNote(value ?? ''); - }, [value]); + setNote(noteFromData); + }, [noteFromData]); return (
= ({ }} > - ) => { setNote(e.target.value); @@ -128,7 +151,7 @@ export const WfoInlineNoteEdit: FC = ({ }, }, }} - /> + />
); diff --git a/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx b/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx index f0604d261..8170c5fce 100644 --- a/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx @@ -150,13 +150,18 @@ export const WfoSubscriptionsList: FC = ({ note: { columnType: ColumnType.DATA, label: t('note'), - renderData: (cellValue, row) => ( - - ), + renderData: (cellValue, row) => { + // console.log("Cell value: ", cellValue); + // console.log("Row: ", row); + return ( + + ) + } }, metadata: { columnType: ColumnType.DATA, diff --git a/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionList.ts b/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionList.ts index a62cabfa6..a99adbdb3 100644 --- a/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionList.ts +++ b/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionList.ts @@ -82,8 +82,38 @@ const subscriptionListApi = orchestratorApi.injectEndpoints({ }, providesTags: getCacheTag(CacheTagType.subscriptions), }), + updateSubscriptionNoteLocally: builder.mutation< + void, + { subscriptionId: string; graphQlQueryVariables: GraphqlQueryVariables; note: string } + >({ + queryFn: async () => { + return { data: undefined }; + }, + async onQueryStarted({ subscriptionId, graphQlQueryVariables, ...patch }, { dispatch, queryFulfilled }) { + const patchResult = dispatch( + subscriptionListApi.util.updateQueryData('getSubscriptionList', graphQlQueryVariables, (draft) => { + const subscription = draft.subscriptions.find( + (item) => item.subscriptionId === subscriptionId + ); + if (subscription) { + subscription.note = patch.note; + } + })); + try { + await queryFulfilled + } catch { + patchResult.undo() + + /** + * Alternatively, on failure you can invalidate the corresponding cache tags + * to trigger a re-fetch: + * dispatch(api.util.invalidateTags(['Post'])) + */ + } + }, + }), }), }); -export const { useGetSubscriptionListQuery, useLazyGetSubscriptionListQuery } = +export const { useGetSubscriptionListQuery, useLazyGetSubscriptionListQuery, useUpdateSubscriptionNoteLocallyMutation } = subscriptionListApi; diff --git a/packages/orchestrator-ui-components/src/utils/string.spec.ts b/packages/orchestrator-ui-components/src/utils/string.spec.ts index 806593d83..6e3a85899 100644 --- a/packages/orchestrator-ui-components/src/utils/string.spec.ts +++ b/packages/orchestrator-ui-components/src/utils/string.spec.ts @@ -1,6 +1,6 @@ import { camelToHuman, - isAllUpperCase, + isAllUpperCase, isNullOrEmpty, removeSuffix, snakeToHuman, snakeToKebab, @@ -132,3 +132,30 @@ describe('isAllUpperCase()', () => { expect(result).toBe(false); }); }); + +describe('isNullOrEmpty', () => { + it('should return true for null', () => { + expect(isNullOrEmpty(null)).toBe(true); + }); + + it('should return true for undefined', () => { + expect(isNullOrEmpty(undefined)).toBe(true); + }); + + it('should return true for an empty string', () => { + expect(isNullOrEmpty('')).toBe(true); + }); + + it('should return true for a string with only spaces', () => { + expect(isNullOrEmpty(' ')).toBe(true); + }); + + it('should return false for a non-empty string', () => { + expect(isNullOrEmpty('Hello')).toBe(false); + }); + + it('should return false for a string with spaces and text', () => { + expect(isNullOrEmpty(' Hello ')).toBe(false); + }); +}); + diff --git a/packages/orchestrator-ui-components/src/utils/strings.ts b/packages/orchestrator-ui-components/src/utils/strings.ts index 6a17fdfbe..54f762406 100644 --- a/packages/orchestrator-ui-components/src/utils/strings.ts +++ b/packages/orchestrator-ui-components/src/utils/strings.ts @@ -24,3 +24,7 @@ export const snakeToKebab = (value: string): string => { }; export const isAllUpperCase = (str: string) => str === str.toUpperCase(); + +export const isNullOrEmpty = (str: string | null | undefined): boolean => { + return str === null || str === undefined || str.trim() === ''; +} From 2db85f84cfc779874d06107e603aaa8c86df5c53 Mon Sep 17 00:00:00 2001 From: Georgi2704 Date: Tue, 28 Jan 2025 19:41:01 +0100 Subject: [PATCH 2/5] Fixed some type issues, detail pages work in progress --- apps/wfo-ui | 2 +- package-lock.json | 6 +- .../WfoInlineNoteEdit/WfoInlineNoteEdit.tsx | 80 +++++++++---------- .../WfoSubscriptionDetailNoteEdit.tsx | 58 ++++++++++++++ .../WfoSubscriptionNoteEdit.tsx | 58 ++++++++++++++ .../src/components/WfoInlineNoteEdit/index.ts | 1 + .../WfoSubscriptionsList.tsx | 13 ++- .../orchestrator-ui-components/src/rtk/api.ts | 29 ++++++- .../src/rtk/endpoints/subscriptionList.ts | 32 +------- .../rtk/endpoints/subscriptionListMutation.ts | 33 ++++++++ .../src/types/types.ts | 5 ++ .../src/utils/strings.ts | 3 + 12 files changed, 237 insertions(+), 83 deletions(-) create mode 100644 packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionDetailNoteEdit.tsx create mode 100644 packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionNoteEdit.tsx create mode 100644 packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionListMutation.ts diff --git a/apps/wfo-ui b/apps/wfo-ui index 859b99c0e..fafc3eea7 160000 --- a/apps/wfo-ui +++ b/apps/wfo-ui @@ -1 +1 @@ -Subproject commit 859b99c0e4622dce0881744e79ce6f0ea2abff94 +Subproject commit fafc3eea7f9eef89e809b7f5d3dd70a906f22d94 diff --git a/package-lock.json b/package-lock.json index 0f696f6a3..860578546 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "@elastic/eui": "^97.3.0", "@emotion/css": "^11.11.2", "@emotion/react": "^11.11.1", - "@orchestrator-ui/orchestrator-ui-components": "^2.8.2", + "@orchestrator-ui/orchestrator-ui-components": "*", "@reduxjs/toolkit": "^2.0.1", "eslint": "^8.57.0", "moment": "^2.29.4", @@ -63,7 +63,7 @@ "@emotion/css": "^11.11.2", "@emotion/react": "^11.11.1", "@open-policy-agent/opa-wasm": "^1.2.0", - "@orchestrator-ui/orchestrator-ui-components": "^2.8.2", + "@orchestrator-ui/orchestrator-ui-components": "*", "@reduxjs/toolkit": "^2.0.1", "@sentry/nextjs": "^8.37.1", "eslint": "^8.57.0", @@ -25760,7 +25760,7 @@ }, "packages/orchestrator-ui-components": { "name": "@orchestrator-ui/orchestrator-ui-components", - "version": "2.15.0", + "version": "3.0.3", "license": "Apache-2.0", "dependencies": { "@elastic/eui": "^97.0.0", diff --git a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx index 664251786..0be7a8294 100644 --- a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx @@ -5,74 +5,74 @@ import { EuiInlineEditText } from '@elastic/eui'; import { WfoToolTip } from '@/components'; import { useOrchestratorTheme } from '@/hooks'; -import { useStartProcessMutation } from '@/rtk/endpoints/forms'; -import type { Subscription } from '@/types'; -import { useGetSubscriptionListQuery, useUpdateSubscriptionNoteLocallyMutation } from '@/rtk'; +import { INVISIBLE_CHARACTER } from '@/utils'; interface WfoInlineNoteEditProps { - value: Subscription['note']; - subscriptionId: Subscription['subscriptionId']; + value: string; + // subscriptionId: Subscription['subscriptionId']; onlyShowOnHover?: boolean; - graphqlQueryVariables: Record; + // graphqlQueryVariables: Record; + // useQuery: any + triggerNoteModifyWorkflow? : (note: string) => void; } // This is an invisible character that is used to get the component re-rendering correctly -const INVISIBLE_CHARACTER = '‎'; +// const INVISIBLE_CHARACTER = '‎'; export const WfoInlineNoteEdit: FC = ({ - // value, - subscriptionId, + value, + // subscriptionId, onlyShowOnHover = false, - graphqlQueryVariables, + // graphqlQueryVariables, + // useQuery, + triggerNoteModifyWorkflow = () => {} }) => { const { theme } = useOrchestratorTheme(); - const {subscriptionItem} = useGetSubscriptionListQuery( - graphqlQueryVariables,{ - selectFromResult: (result) => ({subscriptionItem: result?.data?.subscriptions.find((sub) => sub.subscriptionId === subscriptionId)}), - } - ); - - console.log("WfoInlineEditData: ", subscriptionItem); - const noteFromData = subscriptionItem?.note?.trim() ? subscriptionItem.note : INVISIBLE_CHARACTER; - const [note, setNote] = useState(noteFromData); + // const {subscriptionItem} = useQuery( + // graphqlQueryVariables,{ + // selectFromResult: (result) => ({subscriptionItem: result?.data?.subscriptions?.find((sub) => sub.subscriptionId === subscriptionId)}), + // } + // ); + // const endpointName = useQuery().endpointName; + // const noteFromData = subscriptionItem?.note?.trim() ? subscriptionItem.note : INVISIBLE_CHARACTER; + console.log("Value now: ", value); + // const trimmedNote = value ? value.trim() : INVISIBLE_CHARACTER; + const [note, setNote] = useState(value); const [isTooltipVisible, setIsTooltipVisible] = useState(true); - const [startProcess] = useStartProcessMutation(); - const [updateSub] = useUpdateSubscriptionNoteLocallyMutation(); + // const [startProcess] = useStartProcessMutation(); + // const [updateSub] = useUpdateSubscriptionNoteOptimisticMutation(); - // const store = useStore(); - // const cachedQueies = store.getState().orchestratorApi.queries; - // console.log("Cached Queries: ", cachedQueies); + // const triggerNoteModifyWorkflow = () => { + // const noteModifyPayload = [ + // { subscription_id: subscriptionId }, + // { note: (note === INVISIBLE_CHARACTER) ? "" : note }, + // ]; + // startProcess({ + // workflowName: 'modify_note', + // userInputs: noteModifyPayload, + // }); + // + // updateSub({queryName: endpointName, subscriptionId: subscriptionId, graphQlQueryVariables: graphqlQueryVariables, note: note }); + // }; - const triggerNoteModifyWorkflow = () => { - const noteModifyPayload = [ - { subscription_id: subscriptionId }, - { note: (note === INVISIBLE_CHARACTER) ? "" : note }, - ]; - startProcess({ - workflowName: 'modify_note', - userInputs: noteModifyPayload, - }); - updateSub({ subscriptionId: subscriptionId, graphQlQueryVariables: graphqlQueryVariables, note: note }); - // console.log("Updated,", updated); - }; const handleSave = () => { - triggerNoteModifyWorkflow(); + triggerNoteModifyWorkflow(note); setIsTooltipVisible(true); }; const handleCancel = () => { - setNote(noteFromData); + setNote(value); setIsTooltipVisible(true); }; // This useEffect makes sure the note is updated when a new value property is passed in // for example by a parent component that is update through a websocket event useEffect(() => { - setNote(noteFromData); - }, [noteFromData]); + setNote(value); + }, [value]); return (
; + useQuery: UseQuery; +} + + +export const WfoSubscriptionNoteEdit: FC = ({ + subscriptionId, + onlyShowOnHover = false, + queryVariables, + useQuery +}) => { + const {selectedItem} = useQuery(queryVariables,{ + selectFromResult: (result: ApiResult) => ({ + selectedItem: result?.data?.subscriptions?.find( + (sub) => sub.subscriptionId === subscriptionId, + ), + }), + }); + const endpointName = useQuery().endpointName; + const [startProcess] = useStartProcessMutation(); + const [updateSub] = useUpdateSubscriptionNoteOptimisticMutation(); + + const triggerNoteModifyWorkflow = (note: string) => { + const noteModifyPayload = [ + { subscription_id: subscriptionId }, + { note: (note === INVISIBLE_CHARACTER) ? "" : note }, + ]; + startProcess({ + workflowName: 'modify_note', + userInputs: noteModifyPayload, + }); + + updateSub({queryName: endpointName ?? "", subscriptionId: subscriptionId, graphQlQueryVariables: queryVariables, note: note }); + }; + + + return ( + + ); +}; diff --git a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionNoteEdit.tsx b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionNoteEdit.tsx new file mode 100644 index 000000000..881d632f6 --- /dev/null +++ b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionNoteEdit.tsx @@ -0,0 +1,58 @@ +import type { FC } from 'react'; +import React from 'react'; + + +import { WfoInlineNoteEdit } from '@/components'; +import { useStartProcessMutation } from '@/rtk/endpoints/forms'; +import { Subscription, SubscriptionList } from '@/types'; +import { useUpdateSubscriptionNoteOptimisticMutation } from '@/rtk/endpoints/subscriptionListMutation'; +import { INVISIBLE_CHARACTER } from '@/utils'; +import { ApiResult, UseQuery } from '@/rtk'; + +interface WfoSubscriptionNoteEditProps { + subscriptionId: Subscription['subscriptionId']; + onlyShowOnHover?: boolean; + queryVariables: Record; + useQuery: UseQuery; +} + + +export const WfoSubscriptionNoteEdit: FC = ({ + subscriptionId, + onlyShowOnHover = false, + queryVariables, + useQuery +}) => { + const {selectedItem} = useQuery(queryVariables,{ + selectFromResult: (result: ApiResult) => ({ + selectedItem: result?.data?.subscriptions?.find( + (sub) => sub.subscriptionId === subscriptionId, + ), + }), + }); + const endpointName = useQuery().endpointName; + const [startProcess] = useStartProcessMutation(); + const [updateSub] = useUpdateSubscriptionNoteOptimisticMutation(); + + const triggerNoteModifyWorkflow = (note: string) => { + const noteModifyPayload = [ + { subscription_id: subscriptionId }, + { note: (note === INVISIBLE_CHARACTER) ? "" : note }, + ]; + startProcess({ + workflowName: 'modify_note', + userInputs: noteModifyPayload, + }); + + updateSub({queryName: endpointName ?? "", subscriptionId: subscriptionId, graphQlQueryVariables: queryVariables, note: note }); + }; + + + return ( + + ); +}; diff --git a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/index.ts b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/index.ts index a1484d8bd..880152231 100644 --- a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/index.ts +++ b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/index.ts @@ -1 +1,2 @@ export * from './WfoInlineNoteEdit'; +export * from './WfoSubscriptionNoteEdit'; diff --git a/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx b/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx index 8170c5fce..44b33f7ce 100644 --- a/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx @@ -10,7 +10,6 @@ import { Pagination, WfoDateTime, WfoInlineJson, - WfoInlineNoteEdit, WfoInsyncIcon, WfoJsonCodeBlock, WfoSubscriptionStatusBadge, @@ -27,7 +26,7 @@ import { useLazyGetSubscriptionListQuery, } from '@/rtk/endpoints/subscriptionList'; import { mapRtkErrorToWfoError } from '@/rtk/utils'; -import { GraphqlQueryVariables, SortOrder } from '@/types'; +import { GraphqlQueryVariables, SortOrder, Subscription, SubscriptionList } from '@/types'; import { getQueryVariablesForExport, getTypedFieldFromObject, @@ -52,6 +51,8 @@ import { mapGraphQlSubscriptionsResultToPageInfo, mapGraphQlSubscriptionsResultToSubscriptionListItems, } from './subscriptionResultMappers'; +import { WfoSubscriptionNoteEdit } from '@/components/WfoInlineNoteEdit/WfoSubscriptionNoteEdit'; +import { UseQuery } from '@/rtk'; export type WfoSubscriptionsListProps = { alwaysOnFilters?: FilterQuery[]; @@ -151,14 +152,12 @@ export const WfoSubscriptionsList: FC = ({ columnType: ColumnType.DATA, label: t('note'), renderData: (cellValue, row) => { - // console.log("Cell value: ", cellValue); - // console.log("Row: ", row); return ( - } /> ) } diff --git a/packages/orchestrator-ui-components/src/rtk/api.ts b/packages/orchestrator-ui-components/src/rtk/api.ts index e69e12b6f..acaa74bf1 100644 --- a/packages/orchestrator-ui-components/src/rtk/api.ts +++ b/packages/orchestrator-ui-components/src/rtk/api.ts @@ -6,9 +6,11 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import type { WfoSession } from '@/hooks'; import { wfoGraphqlRequestBaseQuery } from '@/rtk/wfoGraphqlRequestBaseQuery'; -import { CacheTagType } from '@/types'; +import { CacheTagType, GraphqlQueryVariables, Subscription, SubscriptionList } from '@/types'; import type { RootState } from './store'; +import { ErrorResponse } from '@rtk-query/graphql-request-base-query/dist/GraphqlBaseQueryTypes'; +import { SubscriptionListItem } from '@/components'; export enum BaseQueryTypes { fetch = 'fetch', @@ -28,6 +30,31 @@ export enum HttpStatus { MultipleChoices = 300, } +export interface ApiResult { + data?: T; + error?: ErrorResponse; + isLoading?: boolean; + isFetching?: boolean; + isError?: boolean; + refetch?: () => void; + selectFromResult?: (result: T) => T; + endpointName?: string; +} + +interface UseQueryOptions { + selectFromResult?: (result: ApiResult) => Partial> & { selectedItem?: U }; +} + +interface UseQueryReturn extends ApiResult { + selectedItem?: U; + endpointName?: string; +} + +export type UseQuery = ( + queryVariables?: GraphqlQueryVariables, + options?: UseQueryOptions +) => UseQueryReturn; + type ExtraOptions = { baseQueryType?: BaseQueryTypes; apiName?: string; diff --git a/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionList.ts b/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionList.ts index a99adbdb3..a62cabfa6 100644 --- a/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionList.ts +++ b/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionList.ts @@ -82,38 +82,8 @@ const subscriptionListApi = orchestratorApi.injectEndpoints({ }, providesTags: getCacheTag(CacheTagType.subscriptions), }), - updateSubscriptionNoteLocally: builder.mutation< - void, - { subscriptionId: string; graphQlQueryVariables: GraphqlQueryVariables; note: string } - >({ - queryFn: async () => { - return { data: undefined }; - }, - async onQueryStarted({ subscriptionId, graphQlQueryVariables, ...patch }, { dispatch, queryFulfilled }) { - const patchResult = dispatch( - subscriptionListApi.util.updateQueryData('getSubscriptionList', graphQlQueryVariables, (draft) => { - const subscription = draft.subscriptions.find( - (item) => item.subscriptionId === subscriptionId - ); - if (subscription) { - subscription.note = patch.note; - } - })); - try { - await queryFulfilled - } catch { - patchResult.undo() - - /** - * Alternatively, on failure you can invalidate the corresponding cache tags - * to trigger a re-fetch: - * dispatch(api.util.invalidateTags(['Post'])) - */ - } - }, - }), }), }); -export const { useGetSubscriptionListQuery, useLazyGetSubscriptionListQuery, useUpdateSubscriptionNoteLocallyMutation } = +export const { useGetSubscriptionListQuery, useLazyGetSubscriptionListQuery } = subscriptionListApi; diff --git a/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionListMutation.ts b/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionListMutation.ts new file mode 100644 index 000000000..1053c5354 --- /dev/null +++ b/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionListMutation.ts @@ -0,0 +1,33 @@ +import { SubscriptionListItem } from '@/components/WfoSubscriptionsList'; +import { orchestratorApi, SubscriptionListResponse } from '@/rtk'; +import { GraphqlQueryVariables } from '@/types'; + +const subscriptionListMutationApi = orchestratorApi.injectEndpoints({ + endpoints: (builder) => ({ + emptyQuery: builder.query>({ query: () => ({}), }), + updateSubscriptionNoteOptimistic: builder.mutation< + { mockResponse: boolean }, + { queryName: string, subscriptionId: string; graphQlQueryVariables: GraphqlQueryVariables; note: string } + >({ + queryFn: async () => ({ data: { mockResponse: true } }), + async onQueryStarted({ queryName, subscriptionId, graphQlQueryVariables, ...patch }, { dispatch, queryFulfilled }) { + const patchResult = dispatch( + subscriptionListMutationApi.util.updateQueryData(queryName as 'emptyQuery', graphQlQueryVariables, (draft: SubscriptionListResponse) => { + const subscription = draft.subscriptions.find((item) => item.subscriptionId === subscriptionId + ); + if (subscription) { + subscription.note = patch.note; + } + })); + try { + await queryFulfilled + } catch { + patchResult.undo() + } + }, + }), + }), +}); + +export const { useUpdateSubscriptionNoteOptimisticMutation } = + subscriptionListMutationApi; diff --git a/packages/orchestrator-ui-components/src/types/types.ts b/packages/orchestrator-ui-components/src/types/types.ts index fa3eebbbd..1e90d111f 100644 --- a/packages/orchestrator-ui-components/src/types/types.ts +++ b/packages/orchestrator-ui-components/src/types/types.ts @@ -3,6 +3,7 @@ import { ReactNode } from 'react'; import { Toast } from '@elastic/eui/src/components/toast/global_toast_list'; import { InputForm } from './forms'; +import { SubscriptionListItem } from '@/components'; export type Nullable = T | null; @@ -311,6 +312,10 @@ export interface SubscriptionsResult { subscriptions: GraphQlResultPage; } +export type SubscriptionList = { + subscriptions: Subscription[]; +}; + export interface SubscriptionDropdownOptionsResult { subscriptions: GraphQlSinglePage; } diff --git a/packages/orchestrator-ui-components/src/utils/strings.ts b/packages/orchestrator-ui-components/src/utils/strings.ts index 54f762406..7bb87d953 100644 --- a/packages/orchestrator-ui-components/src/utils/strings.ts +++ b/packages/orchestrator-ui-components/src/utils/strings.ts @@ -28,3 +28,6 @@ export const isAllUpperCase = (str: string) => str === str.toUpperCase(); export const isNullOrEmpty = (str: string | null | undefined): boolean => { return str === null || str === undefined || str.trim() === ''; } + +export const INVISIBLE_CHARACTER = '‎'; + From 1e92cfdce66936eda2aaf665625f76e78bfccdbe Mon Sep 17 00:00:00 2001 From: Georgi2704 Date: Wed, 29 Jan 2025 16:44:35 +0100 Subject: [PATCH 3/5] Working build, added note detail page editor --- .../WfoInlineNoteEdit/WfoInlineNoteEdit.tsx | 157 +++++++----------- .../WfoSubscriptionDetailNoteEdit.tsx | 51 +++--- .../WfoSubscriptionNoteEdit.tsx | 36 ++-- .../src/components/WfoInlineNoteEdit/index.ts | 1 + .../WfoSubscriptionDetailSection.tsx | 7 +- .../WfoSubscriptionsList.tsx | 18 +- .../orchestrator-ui-components/src/rtk/api.ts | 13 +- .../rtk/endpoints/subscriptionListMutation.ts | 87 ++++++++-- .../src/types/types.ts | 5 - .../src/utils/string.spec.ts | 4 +- .../src/utils/strings.ts | 3 +- 11 files changed, 208 insertions(+), 174 deletions(-) diff --git a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx index 0be7a8294..ba19660f2 100644 --- a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoInlineNoteEdit.tsx @@ -9,55 +9,19 @@ import { INVISIBLE_CHARACTER } from '@/utils'; interface WfoInlineNoteEditProps { value: string; - // subscriptionId: Subscription['subscriptionId']; onlyShowOnHover?: boolean; - // graphqlQueryVariables: Record; - // useQuery: any - triggerNoteModifyWorkflow? : (note: string) => void; + triggerNoteModifyWorkflow?: (note: string) => void; } -// This is an invisible character that is used to get the component re-rendering correctly -// const INVISIBLE_CHARACTER = '‎'; - export const WfoInlineNoteEdit: FC = ({ value, - // subscriptionId, onlyShowOnHover = false, - // graphqlQueryVariables, - // useQuery, - triggerNoteModifyWorkflow = () => {} + triggerNoteModifyWorkflow = () => {}, }) => { const { theme } = useOrchestratorTheme(); - // const {subscriptionItem} = useQuery( - // graphqlQueryVariables,{ - // selectFromResult: (result) => ({subscriptionItem: result?.data?.subscriptions?.find((sub) => sub.subscriptionId === subscriptionId)}), - // } - // ); - // const endpointName = useQuery().endpointName; - // const noteFromData = subscriptionItem?.note?.trim() ? subscriptionItem.note : INVISIBLE_CHARACTER; - console.log("Value now: ", value); - // const trimmedNote = value ? value.trim() : INVISIBLE_CHARACTER; const [note, setNote] = useState(value); const [isTooltipVisible, setIsTooltipVisible] = useState(true); - // const [startProcess] = useStartProcessMutation(); - // const [updateSub] = useUpdateSubscriptionNoteOptimisticMutation(); - - // const triggerNoteModifyWorkflow = () => { - // const noteModifyPayload = [ - // { subscription_id: subscriptionId }, - // { note: (note === INVISIBLE_CHARACTER) ? "" : note }, - // ]; - // startProcess({ - // workflowName: 'modify_note', - // userInputs: noteModifyPayload, - // }); - // - // updateSub({queryName: endpointName, subscriptionId: subscriptionId, graphQlQueryVariables: graphqlQueryVariables, note: note }); - // }; - - - const handleSave = () => { triggerNoteModifyWorkflow(note); setIsTooltipVisible(true); @@ -86,72 +50,79 @@ export const WfoInlineNoteEdit: FC = ({ }} > - ) => { - setNote(e.target.value); - }} - onCancel={handleCancel} - onSave={handleSave} - size={'s'} - css={{ - width: theme.base * 16, - '.euiFlexItem:nth-of-type(2)': { - justifyContent: 'center', - }, - '.euiButtonEmpty__content': { - justifyContent: 'left', - }, - }} - readModeProps={{ - onClick: () => setIsTooltipVisible(false), - title: '', - css: { - minWidth: '100%', - '.euiIcon': { - visibility: onlyShowOnHover - ? 'hidden' - : 'visible', + + ) => { + setNote(e.target.value); + }} + onCancel={handleCancel} + onSave={handleSave} + size={'s'} + css={{ + width: theme.base * 16, + '.euiFlexItem:nth-of-type(2)': { + justifyContent: 'center', }, - }, - }} - editModeProps={{ - saveButtonProps: { - color: 'primary', - size: 'xs', - }, - cancelButtonProps: { - color: 'danger', - size: 'xs', - }, - inputProps: { - css: { + '.euiButtonEmpty__content': { justifyContent: 'left', - height: '32px', - paddingLeft: '4px', - margin: '0', - width: '98%', }, - }, - formRowProps: { + }} + readModeProps={{ + onClick: () => setIsTooltipVisible(false), + title: '', css: { - padding: 0, - margin: 0, - height: '32px', - '.euiFormRow__fieldWrapper': { - minHeight: '32px', + minWidth: '100%', + '.euiIcon': { + visibility: onlyShowOnHover + ? 'hidden' + : 'visible', + }, + }, + }} + editModeProps={{ + saveButtonProps: { + color: 'primary', + size: 'xs', + }, + cancelButtonProps: { + color: 'danger', + size: 'xs', + }, + inputProps: { + css: { + justifyContent: 'left', height: '32px', + paddingLeft: '4px', + margin: '0', + width: '98%', + }, + }, + formRowProps: { + css: { padding: 0, margin: 0, + height: '32px', + '.euiFormRow__fieldWrapper': { + minHeight: '32px', + height: '32px', + padding: 0, + margin: 0, + }, }, }, - }, - }} - /> + }} + /> +
); diff --git a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionDetailNoteEdit.tsx b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionDetailNoteEdit.tsx index 881d632f6..2a8b19680 100644 --- a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionDetailNoteEdit.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionDetailNoteEdit.tsx @@ -1,56 +1,53 @@ import type { FC } from 'react'; import React from 'react'; - import { WfoInlineNoteEdit } from '@/components'; +import { useGetSubscriptionDetailQuery } from '@/rtk'; import { useStartProcessMutation } from '@/rtk/endpoints/forms'; -import { Subscription, SubscriptionList } from '@/types'; -import { useUpdateSubscriptionNoteOptimisticMutation } from '@/rtk/endpoints/subscriptionListMutation'; +import { useUpdateSubscriptionDetailNoteOptimisticMutation } from '@/rtk/endpoints/subscriptionListMutation'; +import { SubscriptionDetail } from '@/types'; import { INVISIBLE_CHARACTER } from '@/utils'; -import { ApiResult, UseQuery } from '@/rtk'; -interface WfoSubscriptionNoteEditProps { - subscriptionId: Subscription['subscriptionId']; +interface WfoSubscriptionDetailNoteEditProps { + subscriptionId: SubscriptionDetail['subscriptionId']; onlyShowOnHover?: boolean; - queryVariables: Record; - useQuery: UseQuery; } - -export const WfoSubscriptionNoteEdit: FC = ({ - subscriptionId, - onlyShowOnHover = false, - queryVariables, - useQuery -}) => { - const {selectedItem} = useQuery(queryVariables,{ - selectFromResult: (result: ApiResult) => ({ - selectedItem: result?.data?.subscriptions?.find( - (sub) => sub.subscriptionId === subscriptionId, - ), - }), +export const WfoSubscriptionDetailNoteEdit: FC< + WfoSubscriptionDetailNoteEditProps +> = ({ subscriptionId, onlyShowOnHover = false }) => { + const { data, endpointName } = useGetSubscriptionDetailQuery({ + subscriptionId, }); - const endpointName = useQuery().endpointName; + + const selectedItem = data?.subscription ?? { note: '' }; const [startProcess] = useStartProcessMutation(); - const [updateSub] = useUpdateSubscriptionNoteOptimisticMutation(); + const [updateSub] = useUpdateSubscriptionDetailNoteOptimisticMutation(); const triggerNoteModifyWorkflow = (note: string) => { const noteModifyPayload = [ { subscription_id: subscriptionId }, - { note: (note === INVISIBLE_CHARACTER) ? "" : note }, + { note: note === INVISIBLE_CHARACTER ? '' : note }, ]; startProcess({ workflowName: 'modify_note', userInputs: noteModifyPayload, }); - updateSub({queryName: endpointName ?? "", subscriptionId: subscriptionId, graphQlQueryVariables: queryVariables, note: note }); + updateSub({ + queryName: endpointName ?? '', + subscriptionId: subscriptionId, + note: note, + }); }; - return ( diff --git a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionNoteEdit.tsx b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionNoteEdit.tsx index 881d632f6..a750583e3 100644 --- a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionNoteEdit.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/WfoSubscriptionNoteEdit.tsx @@ -1,30 +1,28 @@ import type { FC } from 'react'; import React from 'react'; - import { WfoInlineNoteEdit } from '@/components'; +import { ApiResult, SubscriptionListResponse, UseQuery } from '@/rtk'; import { useStartProcessMutation } from '@/rtk/endpoints/forms'; -import { Subscription, SubscriptionList } from '@/types'; import { useUpdateSubscriptionNoteOptimisticMutation } from '@/rtk/endpoints/subscriptionListMutation'; +import { Subscription } from '@/types'; import { INVISIBLE_CHARACTER } from '@/utils'; -import { ApiResult, UseQuery } from '@/rtk'; interface WfoSubscriptionNoteEditProps { subscriptionId: Subscription['subscriptionId']; onlyShowOnHover?: boolean; queryVariables: Record; - useQuery: UseQuery; + useQuery: UseQuery; } - export const WfoSubscriptionNoteEdit: FC = ({ - subscriptionId, - onlyShowOnHover = false, - queryVariables, - useQuery + subscriptionId, + onlyShowOnHover = false, + queryVariables, + useQuery, }) => { - const {selectedItem} = useQuery(queryVariables,{ - selectFromResult: (result: ApiResult) => ({ + const { selectedItem } = useQuery(queryVariables, { + selectFromResult: (result: ApiResult) => ({ selectedItem: result?.data?.subscriptions?.find( (sub) => sub.subscriptionId === subscriptionId, ), @@ -37,20 +35,28 @@ export const WfoSubscriptionNoteEdit: FC = ({ const triggerNoteModifyWorkflow = (note: string) => { const noteModifyPayload = [ { subscription_id: subscriptionId }, - { note: (note === INVISIBLE_CHARACTER) ? "" : note }, + { note: note === INVISIBLE_CHARACTER ? '' : note }, ]; startProcess({ workflowName: 'modify_note', userInputs: noteModifyPayload, }); - updateSub({queryName: endpointName ?? "", subscriptionId: subscriptionId, graphQlQueryVariables: queryVariables, note: note }); + updateSub({ + queryName: endpointName ?? '', + subscriptionId: subscriptionId, + graphQlQueryVariables: queryVariables, + note: note, + }); }; - return ( diff --git a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/index.ts b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/index.ts index 880152231..130c6cb2d 100644 --- a/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/index.ts +++ b/packages/orchestrator-ui-components/src/components/WfoInlineNoteEdit/index.ts @@ -1,2 +1,3 @@ export * from './WfoInlineNoteEdit'; export * from './WfoSubscriptionNoteEdit'; +export * from './WfoSubscriptionDetailNoteEdit'; diff --git a/packages/orchestrator-ui-components/src/components/WfoSubscription/WfoSubscriptionGeneralSections/WfoSubscriptionDetailSection.tsx b/packages/orchestrator-ui-components/src/components/WfoSubscription/WfoSubscriptionGeneralSections/WfoSubscriptionDetailSection.tsx index df637b229..87b789c46 100644 --- a/packages/orchestrator-ui-components/src/components/WfoSubscription/WfoSubscriptionGeneralSections/WfoSubscriptionDetailSection.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoSubscription/WfoSubscriptionGeneralSections/WfoSubscriptionDetailSection.tsx @@ -6,7 +6,7 @@ import { SubscriptionKeyValueBlock, WfoCustomerDescriptionsField, WfoInSyncField, - WfoInlineNoteEdit, + WfoSubscriptionDetailNoteEdit, WfoSubscriptionStatusBadge, } from '@/components'; import { SubscriptionDetail } from '@/types'; @@ -35,7 +35,6 @@ export const WfoSubscriptionDetailSection = ({ status, customer, customerDescriptions, - note, } = subscriptionDetail; const subscriptionDetailBlockData = [ @@ -102,9 +101,9 @@ export const WfoSubscriptionDetailSection = ({ { key: t('note'), value: ( - ), }, diff --git a/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx b/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx index 44b33f7ce..a18f0d810 100644 --- a/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx +++ b/packages/orchestrator-ui-components/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx @@ -16,17 +16,20 @@ import { getPageIndexChangeHandler, getPageSizeChangeHandler, } from '@/components'; +import { WfoSubscriptionNoteEdit } from '@/components/WfoInlineNoteEdit/WfoSubscriptionNoteEdit'; import { WfoAdvancedTable } from '@/components/WfoTable/WfoAdvancedTable'; import { WfoAdvancedTableColumnConfig } from '@/components/WfoTable/WfoAdvancedTable/types'; import { ColumnType } from '@/components/WfoTable/WfoTable'; import { mapSortableAndFilterableValuesToTableColumnConfig } from '@/components/WfoTable/WfoTable/utils'; import { DataDisplayParams, useShowToastMessage } from '@/hooks'; +import { UseQuery } from '@/rtk'; import { + SubscriptionListResponse, useGetSubscriptionListQuery, useLazyGetSubscriptionListQuery, } from '@/rtk/endpoints/subscriptionList'; import { mapRtkErrorToWfoError } from '@/rtk/utils'; -import { GraphqlQueryVariables, SortOrder, Subscription, SubscriptionList } from '@/types'; +import { GraphqlQueryVariables, SortOrder, Subscription } from '@/types'; import { getQueryVariablesForExport, getTypedFieldFromObject, @@ -51,8 +54,6 @@ import { mapGraphQlSubscriptionsResultToPageInfo, mapGraphQlSubscriptionsResultToSubscriptionListItems, } from './subscriptionResultMappers'; -import { WfoSubscriptionNoteEdit } from '@/components/WfoInlineNoteEdit/WfoSubscriptionNoteEdit'; -import { UseQuery } from '@/rtk'; export type WfoSubscriptionsListProps = { alwaysOnFilters?: FilterQuery[]; @@ -157,10 +158,15 @@ export const WfoSubscriptionsList: FC = ({ queryVariables={graphqlQueryVariables} subscriptionId={row.subscriptionId} onlyShowOnHover={true} - useQuery={useGetSubscriptionListQuery as UseQuery} + useQuery={ + useGetSubscriptionListQuery as UseQuery< + SubscriptionListResponse, + Subscription + > + } /> - ) - } + ); + }, }, metadata: { columnType: ColumnType.DATA, diff --git a/packages/orchestrator-ui-components/src/rtk/api.ts b/packages/orchestrator-ui-components/src/rtk/api.ts index acaa74bf1..c518ba616 100644 --- a/packages/orchestrator-ui-components/src/rtk/api.ts +++ b/packages/orchestrator-ui-components/src/rtk/api.ts @@ -3,14 +3,14 @@ import { GraphQLErrorExtensions } from 'graphql/error/GraphQLError'; import { getSession, signOut } from 'next-auth/react'; import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; +import { ErrorResponse } from '@rtk-query/graphql-request-base-query/dist/GraphqlBaseQueryTypes'; +import { SubscriptionListItem } from '@/components'; import type { WfoSession } from '@/hooks'; import { wfoGraphqlRequestBaseQuery } from '@/rtk/wfoGraphqlRequestBaseQuery'; -import { CacheTagType, GraphqlQueryVariables, Subscription, SubscriptionList } from '@/types'; +import { CacheTagType, GraphqlQueryVariables } from '@/types'; import type { RootState } from './store'; -import { ErrorResponse } from '@rtk-query/graphql-request-base-query/dist/GraphqlBaseQueryTypes'; -import { SubscriptionListItem } from '@/components'; export enum BaseQueryTypes { fetch = 'fetch', @@ -42,7 +42,10 @@ export interface ApiResult { } interface UseQueryOptions { - selectFromResult?: (result: ApiResult) => Partial> & { selectedItem?: U }; + selectFromResult?: ( + result: ApiResult, + ) => Partial> & { selectedItem?: U }; + subscriptionId?: string; } interface UseQueryReturn extends ApiResult { @@ -52,7 +55,7 @@ interface UseQueryReturn extends ApiResult { export type UseQuery = ( queryVariables?: GraphqlQueryVariables, - options?: UseQueryOptions + options?: UseQueryOptions, ) => UseQueryReturn; type ExtraOptions = { diff --git a/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionListMutation.ts b/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionListMutation.ts index 1053c5354..476b07b33 100644 --- a/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionListMutation.ts +++ b/packages/orchestrator-ui-components/src/rtk/endpoints/subscriptionListMutation.ts @@ -1,33 +1,90 @@ import { SubscriptionListItem } from '@/components/WfoSubscriptionsList'; -import { orchestratorApi, SubscriptionListResponse } from '@/rtk'; +import { + SubscriptionDetailResponse, + SubscriptionListResponse, + orchestratorApi, +} from '@/rtk'; import { GraphqlQueryVariables } from '@/types'; const subscriptionListMutationApi = orchestratorApi.injectEndpoints({ endpoints: (builder) => ({ - emptyQuery: builder.query>({ query: () => ({}), }), + emptyQuery: builder.query< + SubscriptionListResponse, + GraphqlQueryVariables + >({ query: () => ({}) }), + emptyDetailQuery: builder.query< + SubscriptionDetailResponse, + { subscriptionId: string } + >({ query: () => ({}) }), updateSubscriptionNoteOptimistic: builder.mutation< { mockResponse: boolean }, - { queryName: string, subscriptionId: string; graphQlQueryVariables: GraphqlQueryVariables; note: string } + { + queryName: string; + subscriptionId: string; + graphQlQueryVariables: GraphqlQueryVariables; + note: string; + } >({ queryFn: async () => ({ data: { mockResponse: true } }), - async onQueryStarted({ queryName, subscriptionId, graphQlQueryVariables, ...patch }, { dispatch, queryFulfilled }) { + async onQueryStarted( + { queryName, subscriptionId, graphQlQueryVariables, ...patch }, + { dispatch, queryFulfilled }, + ) { const patchResult = dispatch( - subscriptionListMutationApi.util.updateQueryData(queryName as 'emptyQuery', graphQlQueryVariables, (draft: SubscriptionListResponse) => { - const subscription = draft.subscriptions.find((item) => item.subscriptionId === subscriptionId - ); - if (subscription) { - subscription.note = patch.note; - } - })); + subscriptionListMutationApi.util.updateQueryData( + // @ts-expect-error - Suggest ts ignore because of the type mismatch between emptyQuery and queryName + queryName, + graphQlQueryVariables, + (draft: SubscriptionListResponse) => { + const subscription = draft.subscriptions.find( + (item) => + item.subscriptionId === subscriptionId, + ); + if (subscription) { + subscription.note = patch.note; + } + }, + ), + ); try { - await queryFulfilled + await queryFulfilled; } catch { - patchResult.undo() + patchResult.undo(); + } + }, + }), + updateSubscriptionDetailNoteOptimistic: builder.mutation< + { mockResponse: boolean }, + { queryName: string; subscriptionId: string; note: string } + >({ + queryFn: async () => ({ data: { mockResponse: true } }), + async onQueryStarted( + { queryName, subscriptionId, ...patch }, + { dispatch, queryFulfilled }, + ) { + const patchResult = dispatch( + subscriptionListMutationApi.util.updateQueryData( + // @ts-expect-error - Suggest ts ignore because of the type mismatch between emptyDetailQuery and queryName + queryName, + { subscriptionId: subscriptionId }, + (draft: SubscriptionDetailResponse) => { + if (draft) { + draft.subscription.note = patch.note; + } + }, + ), + ); + try { + await queryFulfilled; + } catch { + patchResult.undo(); } }, }), }), }); -export const { useUpdateSubscriptionNoteOptimisticMutation } = - subscriptionListMutationApi; +export const { + useUpdateSubscriptionNoteOptimisticMutation, + useUpdateSubscriptionDetailNoteOptimisticMutation, +} = subscriptionListMutationApi; diff --git a/packages/orchestrator-ui-components/src/types/types.ts b/packages/orchestrator-ui-components/src/types/types.ts index 1e90d111f..fa3eebbbd 100644 --- a/packages/orchestrator-ui-components/src/types/types.ts +++ b/packages/orchestrator-ui-components/src/types/types.ts @@ -3,7 +3,6 @@ import { ReactNode } from 'react'; import { Toast } from '@elastic/eui/src/components/toast/global_toast_list'; import { InputForm } from './forms'; -import { SubscriptionListItem } from '@/components'; export type Nullable = T | null; @@ -312,10 +311,6 @@ export interface SubscriptionsResult { subscriptions: GraphQlResultPage; } -export type SubscriptionList = { - subscriptions: Subscription[]; -}; - export interface SubscriptionDropdownOptionsResult { subscriptions: GraphQlSinglePage; } diff --git a/packages/orchestrator-ui-components/src/utils/string.spec.ts b/packages/orchestrator-ui-components/src/utils/string.spec.ts index 6e3a85899..7c0e6867f 100644 --- a/packages/orchestrator-ui-components/src/utils/string.spec.ts +++ b/packages/orchestrator-ui-components/src/utils/string.spec.ts @@ -1,6 +1,7 @@ import { camelToHuman, - isAllUpperCase, isNullOrEmpty, + isAllUpperCase, + isNullOrEmpty, removeSuffix, snakeToHuman, snakeToKebab, @@ -158,4 +159,3 @@ describe('isNullOrEmpty', () => { expect(isNullOrEmpty(' Hello ')).toBe(false); }); }); - diff --git a/packages/orchestrator-ui-components/src/utils/strings.ts b/packages/orchestrator-ui-components/src/utils/strings.ts index 7bb87d953..516d5c9c9 100644 --- a/packages/orchestrator-ui-components/src/utils/strings.ts +++ b/packages/orchestrator-ui-components/src/utils/strings.ts @@ -27,7 +27,6 @@ export const isAllUpperCase = (str: string) => str === str.toUpperCase(); export const isNullOrEmpty = (str: string | null | undefined): boolean => { return str === null || str === undefined || str.trim() === ''; -} +}; export const INVISIBLE_CHARACTER = '‎'; - From 216012adc35fc093c57fa835e752ccabd25010ea Mon Sep 17 00:00:00 2001 From: Georgi2704 Date: Wed, 29 Jan 2025 16:46:48 +0100 Subject: [PATCH 4/5] Added changeset --- .changeset/olive-carrots-change.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/olive-carrots-change.md diff --git a/.changeset/olive-carrots-change.md b/.changeset/olive-carrots-change.md new file mode 100644 index 000000000..072850667 --- /dev/null +++ b/.changeset/olive-carrots-change.md @@ -0,0 +1,5 @@ +--- +'@orchestrator-ui/orchestrator-ui-components': minor +--- + +Fix notes not updating when changing pages, fix cancel button resetting note to older value From 67e077c9c8aefb01781c337d4d9ac8bd77d9a016 Mon Sep 17 00:00:00 2001 From: Georgi2704 Date: Mon, 3 Feb 2025 14:56:57 +0100 Subject: [PATCH 5/5] Make boolean parameters non-optional --- packages/orchestrator-ui-components/src/rtk/api.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/orchestrator-ui-components/src/rtk/api.ts b/packages/orchestrator-ui-components/src/rtk/api.ts index c518ba616..1feda651a 100644 --- a/packages/orchestrator-ui-components/src/rtk/api.ts +++ b/packages/orchestrator-ui-components/src/rtk/api.ts @@ -33,9 +33,9 @@ export enum HttpStatus { export interface ApiResult { data?: T; error?: ErrorResponse; - isLoading?: boolean; - isFetching?: boolean; - isError?: boolean; + isLoading: boolean; + isFetching: boolean; + isError: boolean; refetch?: () => void; selectFromResult?: (result: T) => T; endpointName?: string;