diff --git a/src/boot/app/app-loader-functions.ts b/src/boot/app/app-loader-functions.ts index a7c3cf03..b9448963 100644 --- a/src/boot/app/app-loader-functions.ts +++ b/src/boot/app/app-loader-functions.ts @@ -27,8 +27,6 @@ import { useUserAccounts, useUserSettings, useTags, - useNotify, - useRefresh, useUserRight, useUserRights, getUserRight, @@ -45,8 +43,7 @@ import { useIntegratedFunction, useIntegratedHook } from '../../store/integrations/hooks'; -import { CarbonioModule } from '../../../types'; -import { getEditSettingsForApp } from '../../network/edit-settings'; +import { CarbonioModule, useNotify, useRefresh } from '../../../types'; import { usePushHistoryCallback, useGoBackHistoryCallback, @@ -63,11 +60,12 @@ import { useRemoveCurrentBoard, useUpdateCurrentBoard } from '../../shell/boards/board-hooks'; +import { getSoapFetch, getXmlSoapFetch } from '../../network/fetch'; // eslint-disable-next-line @typescript-eslint/ban-types export const getAppFunctions = (pkg: CarbonioModule): Record => ({ - soapFetch: useAccountStore.getState().soapFetch(pkg.name), - xmlSoapFetch: useAccountStore.getState().xmlSoapFetch(pkg.name), + soapFetch: getSoapFetch(pkg.name), + xmlSoapFetch: getXmlSoapFetch(pkg.name), // APP STORE FUNCTIONS useAppContext: useAppContext(pkg.name), diff --git a/src/boot/init.ts b/src/boot/init.ts index e6019fb2..92d49383 100644 --- a/src/boot/init.ts +++ b/src/boot/init.ts @@ -10,18 +10,16 @@ import { registerDefaultViews } from './app/default-views'; import { loadApps } from './app/load-apps'; import I18nFactory from '../i18n/i18n-factory'; import StoreFactory from '../redux/store-factory'; +import { getInfo } from '../network/get-info'; export const init = (_i18nFactory: I18nFactory, _storeFactory: StoreFactory): void => { - useAccountStore - .getState() - .init() - .then(() => { - _i18nFactory.setLocale( - ( - (useAccountStore.getState().settings?.prefs?.zimbraPrefLocale as string) ?? - (useAccountStore.getState().settings?.attrs?.zimbraLocale as string) - )?.split?.('_')?.[0] ?? 'en' - ); - loadApps(_storeFactory, Object.values(useAppStore.getState().apps)); - }); + getInfo().then(() => { + _i18nFactory.setLocale( + ( + (useAccountStore.getState().settings?.prefs?.zimbraPrefLocale as string) ?? + (useAccountStore.getState().settings?.attrs?.zimbraLocale as string) + )?.split?.('_')?.[0] ?? 'en' + ); + loadApps(_storeFactory, Object.values(useAppStore.getState().apps)); + }); }; diff --git a/src/network/edit-settings.ts b/src/network/edit-settings.ts index 21e161e3..b3fc4cb3 100644 --- a/src/network/edit-settings.ts +++ b/src/network/edit-settings.ts @@ -8,217 +8,214 @@ import { filter, find, findIndex, forEach, map, reduce } from 'lodash'; import { SHELL_APP_ID } from '../constants'; import { useAccountStore } from '../store/account/store'; import { AccountState, Mods, Account } from '../../types'; +import { getXmlSoapFetch } from './fetch'; export const editSettings = (mods: Mods, appId: string = SHELL_APP_ID): Promise => - useAccountStore - .getState() - .xmlSoapFetch(SHELL_APP_ID)( - 'Batch', - `${ - mods.props - ? `${map( - mods.props, - (prop, key) => - `${prop.value}` - )}` - : '' - }${ - mods.prefs - ? `${map( - mods.prefs, - (pref, key) => `${pref}` - ).join('')}` - : '' - }${ - mods.identity?.modifyList - ? map( - mods.identity.modifyList, - (item) => - `${map(item.prefs, (value, key) => `${value}`).join( - '' - )}sendAs` - ).join('') - : '' - }${ - mods.identity?.deleteList - ? map( - mods.identity.deleteList, - (item) => - `` - ).join('') - : '' - }${ - mods.identity?.createList - ? map( - mods.identity.createList, - (item) => - `${item.prefs.zimbraPrefIdentityName}${item.prefs.zimbraPrefFromDisplay}${item.prefs.zimbraPrefFromAddress}sendAs${item.prefs.zimbraPrefReplyToEnabled}${item.prefs.zimbraPrefReplyToDisplay}${item.prefs.zimbraPrefReplyToAddress}${item.prefs.zimbraPrefDefaultSignatureId}${item.prefs.zimbraPrefForwardReplySignatureId}${item.prefs.zimbraPrefWhenSentToEnabled}${item.prefs.zimbraPrefWhenInFoldersEnabled}` - ).join('') - : '' - }${ - mods.permissions - ? `${ - mods.permissions.freeBusy - ? map(mods.permissions.freeBusy.current, (right) => { - if (right.gt === 'dom') - return ``; - if (right.gt === 'all' && right.deny) - return ``; - if (right.gt === 'usr') - return ``; - return ``; - }).join('') - : '' - }${ - mods.permissions.inviteRight - ? map(mods.permissions.inviteRight.current, (right) => { - if (right.gt === 'all' && right.deny) - return ``; - if (right.gt === 'usr') - return ``; - return ``; - }).join('') - : '' - }${ - mods.permissions.freeBusy - ? `${((): string => { - if (mods.permissions.freeBusy.new.gt === 'dom') { - return ``; - } - if ( - mods.permissions.freeBusy.new.gt === 'all' && - mods.permissions.freeBusy.new.deny - ) { - return ``; - } - if (mods.permissions.freeBusy.new.gt === 'usr') { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - return map( - mods.permissions.freeBusy.new.d, - (u) => - `` - ).join(''); - } - return ``; - })()}` - : '' - }${ - mods.permissions.inviteRight - ? `${((): string => { - if ( - mods.permissions.inviteRight.new.gt === 'all' && - mods.permissions.inviteRight.new.deny - ) { - return ``; - } - if (mods.permissions.inviteRight.new.gt === 'usr') { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - return map( - mods.permissions.inviteRight.new.d, - (u) => - `` - ).join(''); - } - return ``; - })()}` - : '' - } - ` - : '' - }` - ) - .then((r: any) => { - useAccountStore.setState((s: AccountState) => ({ - settings: { - ...s.settings, - prefs: reduce( - mods.prefs, - (acc, pref, key) => ({ - ...acc, - [key]: pref as string - }), - s.settings.prefs - ), - props: reduce( + getXmlSoapFetch(SHELL_APP_ID)( + 'Batch', + `${ + mods.props + ? `${map( mods.props, - (acc, { app, value }, key) => { - const propIndex = findIndex(acc, (p) => p.name === key && p.zimlet === app); - if (propIndex >= 0) { - // eslint-disable-next-line no-param-reassign - acc[propIndex] = { - name: key, - zimlet: app, - _content: value as string - }; - } else { - acc.push({ - name: key, - zimlet: app, - _content: value as string - }); - } - return acc; - }, - s.settings.props - ) - }, - account: { - ...s.account, - displayName: - find(mods?.identity?.modifyList, (item) => item.id === s?.account?.id)?.prefs - .zimbraPrefIdentityName || s.account?.displayName, - name: - find(mods?.identity?.modifyList, (item) => item.id === s?.account?.id)?.prefs - .zimbraPrefFromAddress || s.account?.name, - identities: { - identity: - typeof s.account !== 'undefined' - ? reduce( - mods?.identity?.modifyList, - (acc, { id, prefs }) => { - const tempResult = []; - const propIndex = findIndex( - acc, - (itemMods, indexAccount) => acc[indexAccount].id === id - ); - if (propIndex > -1) { - forEach(Object.keys(prefs), (item, _index) => { + (prop, key) => `${prop.value}` + )}` + : '' + }${ + mods.prefs + ? `${map( + mods.prefs, + (pref, key) => `${pref}` + ).join('')}` + : '' + }${ + mods.identity?.modifyList + ? map( + mods.identity.modifyList, + (item) => + `${map(item.prefs, (value, key) => `${value}`).join( + '' + )}sendAs` + ).join('') + : '' + }${ + mods.identity?.deleteList + ? map( + mods.identity.deleteList, + (item) => + `` + ).join('') + : '' + }${ + mods.identity?.createList + ? map( + mods.identity.createList, + (item) => + `${item.prefs.zimbraPrefIdentityName}${item.prefs.zimbraPrefFromDisplay}${item.prefs.zimbraPrefFromAddress}sendAs${item.prefs.zimbraPrefReplyToEnabled}${item.prefs.zimbraPrefReplyToDisplay}${item.prefs.zimbraPrefReplyToAddress}${item.prefs.zimbraPrefDefaultSignatureId}${item.prefs.zimbraPrefForwardReplySignatureId}${item.prefs.zimbraPrefWhenSentToEnabled}${item.prefs.zimbraPrefWhenInFoldersEnabled}` + ).join('') + : '' + }${ + mods.permissions + ? `${ + mods.permissions.freeBusy + ? map(mods.permissions.freeBusy.current, (right) => { + if (right.gt === 'dom') + return ``; + if (right.gt === 'all' && right.deny) + return ``; + if (right.gt === 'usr') + return ``; + return ``; + }).join('') + : '' + }${ + mods.permissions.inviteRight + ? map(mods.permissions.inviteRight.current, (right) => { + if (right.gt === 'all' && right.deny) + return ``; + if (right.gt === 'usr') + return ``; + return ``; + }).join('') + : '' + }${ + mods.permissions.freeBusy + ? `${((): string => { + if (mods.permissions.freeBusy.new.gt === 'dom') { + return ``; + } + if ( + mods.permissions.freeBusy.new.gt === 'all' && + mods.permissions.freeBusy.new.deny + ) { + return ``; + } + if (mods.permissions.freeBusy.new.gt === 'usr') { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + return map( + mods.permissions.freeBusy.new.d, + (u) => + `` + ).join(''); + } + return ``; + })()}` + : '' + }${ + mods.permissions.inviteRight + ? `${((): string => { + if ( + mods.permissions.inviteRight.new.gt === 'all' && + mods.permissions.inviteRight.new.deny + ) { + return ``; + } + if (mods.permissions.inviteRight.new.gt === 'usr') { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + return map( + mods.permissions.inviteRight.new.d, + (u) => + `` + ).join(''); + } + return ``; + })()}` + : '' + } + ` + : '' + }` + ).then((r: any) => { + useAccountStore.setState((s: AccountState) => ({ + settings: { + ...s.settings, + prefs: reduce( + mods.prefs, + (acc, pref, key) => ({ + ...acc, + [key]: pref as string + }), + s.settings.prefs + ), + props: reduce( + mods.props, + (acc, { app, value }, key) => { + const propIndex = findIndex(acc, (p) => p.name === key && p.zimlet === app); + if (propIndex >= 0) { + // eslint-disable-next-line no-param-reassign + acc[propIndex] = { + name: key, + zimlet: app, + _content: value as string + }; + } else { + acc.push({ + name: key, + zimlet: app, + _content: value as string + }); + } + return acc; + }, + s.settings.props + ) + }, + account: { + ...s.account, + displayName: + find(mods?.identity?.modifyList, (item) => item.id === s?.account?.id)?.prefs + .zimbraPrefIdentityName || s.account?.displayName, + name: + find(mods?.identity?.modifyList, (item) => item.id === s?.account?.id)?.prefs + .zimbraPrefFromAddress || s.account?.name, + identities: { + identity: + typeof s.account !== 'undefined' + ? reduce( + mods?.identity?.modifyList, + (acc, { id, prefs }) => { + const tempResult = []; + const propIndex = findIndex( + acc, + (itemMods, indexAccount) => acc[indexAccount].id === id + ); + if (propIndex > -1) { + forEach(Object.keys(prefs), (item, _index) => { + // eslint-disable-next-line no-param-reassign + acc[propIndex]._attrs[item] = Object.values(prefs)[_index]; + if ( + item === 'zimbraPrefIdentityName' && + acc[propIndex].name !== 'DEFAULT' + ) { // eslint-disable-next-line no-param-reassign - acc[propIndex]._attrs[item] = Object.values(prefs)[_index]; - if ( - item === 'zimbraPrefIdentityName' && - acc[propIndex].name !== 'DEFAULT' - ) { - // eslint-disable-next-line no-param-reassign - acc[propIndex].name = Object.values(prefs)[_index]; - } - }); - tempResult.push(prefs); - } - return acc; - }, - [ - ...filter( - s.account.identities.identity, - (item) => !mods?.identity?.deleteList?.includes(item.id) - ).filter((i) => i.name !== 'DEFAULT'), - ...map(r?.CreateIdentityResponse, (item) => item.identity[0]), - ...filter( - s.account.identities.identity, - (item) => !mods?.identity?.deleteList?.includes(item.id) - ).filter((i) => i.name === 'DEFAULT') - ] - ) - : undefined - } - } as Account - })); - return r; - }); + acc[propIndex].name = Object.values(prefs)[_index]; + } + }); + tempResult.push(prefs); + } + return acc; + }, + [ + ...filter( + s.account.identities.identity, + (item) => !mods?.identity?.deleteList?.includes(item.id) + ).filter((i) => i.name !== 'DEFAULT'), + ...map(r?.CreateIdentityResponse, (item) => item.identity[0]), + ...filter( + s.account.identities.identity, + (item) => !mods?.identity?.deleteList?.includes(item.id) + ).filter((i) => i.name === 'DEFAULT') + ] + ) + : undefined + } + } as Account + })); + return r; + }); export const getEditSettingsForApp = (app: string) => diff --git a/src/network/fetch-locale.ts b/src/network/fetch-locale.ts index 32a776e8..d07b55a7 100644 --- a/src/network/fetch-locale.ts +++ b/src/network/fetch-locale.ts @@ -7,11 +7,9 @@ import { AvailableLocalesResponse } from '../../types'; import { SHELL_APP_ID } from '../constants'; import { useAccountStore } from '../store/account'; +import { getSoapFetch } from './fetch'; export const fetchLocales = (): Promise => - useAccountStore - .getState() - .soapFetch(SHELL_APP_ID)<{ _jsns: string }, AvailableLocalesResponse>('GetAvailableLocales', { - _jsns: 'urn:zimbraAccount' - }) - .then((r) => r); + getSoapFetch(SHELL_APP_ID)<{ _jsns: string }, AvailableLocalesResponse>('GetAvailableLocales', { + _jsns: 'urn:zimbraAccount' + }); diff --git a/src/network/fetch.ts b/src/network/fetch.ts index 0c8117e8..3ff17a62 100644 --- a/src/network/fetch.ts +++ b/src/network/fetch.ts @@ -4,20 +4,24 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { GetState, SetState } from 'zustand'; import { find } from 'lodash'; import { goToLogin } from './go-to-login'; -import { - Account, - AccountState, - ErrorSoapResponse, - SoapResponse, - SuccessSoapResponse, - Tag -} from '../../types'; +import { Account, ErrorSoapResponse, SoapResponse, SuccessSoapResponse, Tag } from '../../types'; import { userAgent } from './user-agent'; -import { noOp } from './noOp'; import { report } from '../reporting'; +import { useAccountStore } from '../store/account'; +import { SHELL_APP_ID } from '../constants'; +import { useNetworkStore } from '../store/network'; + +export const noOp = (): void => { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + getSoapFetch(SHELL_APP_ID)( + 'NoOp', + useNetworkStore.getState().pollingInterval === 500 + ? { _jsns: 'urn:zimbraMail', limitToOneBlocked: 1, wait: 1 } + : { _jsns: 'urn:zimbraMail' } + ); +}; const getAccount = ( acc?: Account, @@ -68,12 +72,9 @@ const getXmlSession = (context?: any): string => { return ''; }; -const handleResponse = ( - api: string, - res: SoapResponse, - set: SetState, - get: GetState -): R => { +const handleResponse = (api: string, res: SoapResponse): R => { + const { pollingInterval, context } = useNetworkStore.getState(); + const { tags, usedQuota } = useAccountStore.getState(); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore clearTimeout(get().noOpTimeout); @@ -93,15 +94,17 @@ const handleResponse = ( ); } if (res?.Header?.context) { - const usedQuota = + const responseUsedQuota = res.Header.context?.refresh?.mbx?.[0]?.s ?? res.Header.context?.notify?.[0]?.mbx?.[0]?.s; - const tags = res.Header.context?.refresh?.tags?.tag as Array; - set({ - noOpTimeout: setTimeout(() => noOp(get), get().pollingInterval), - tags: tags ?? get().tags, - usedQuota: usedQuota ?? get().usedQuota, + const responseTags = res.Header.context?.refresh?.tags?.tag as Array; + useAccountStore.setState({ + tags: responseTags ?? tags, + usedQuota: responseUsedQuota ?? usedQuota + }); + useNetworkStore.setState({ + noOpTimeout: setTimeout(() => noOp(), pollingInterval), context: { - ...get().context, + ...context, ...res?.Header?.context } }); @@ -109,9 +112,11 @@ const handleResponse = ( return (>res).Body[`${api}Response`] as R; }; export const getSoapFetch = - (app: string, set: SetState, get: GetState) => - (api: string, body: Request, otherAccount?: string): Promise => - fetch(`/service/soap/${api}Request`, { + (app: string) => + (api: string, body: Request, otherAccount?: string): Promise => { + const { zimbraVersion, account } = useAccountStore.getState(); + const { context } = useNetworkStore.getState(); + return fetch(`/service/soap/${api}Request`, { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -123,50 +128,51 @@ export const getSoapFetch = Header: { context: { _jsns: 'urn:zimbra', - notify: get().context?.notify?.[0]?.seq + notify: context?.notify?.[0]?.seq ? { - seq: get().context?.notify?.[0]?.seq + seq: context?.notify?.[0]?.seq } : undefined, - session: get().context?.session ?? {}, - account: getAccount(get().account as Account, otherAccount), + session: context?.session ?? {}, + account: getAccount(account as Account, otherAccount), userAgent: { name: userAgent, - version: get().zimbraVersion + version: zimbraVersion } } } }) }) // TODO proper error handling .then((res) => res?.json()) - .then((res: SoapResponse) => handleResponse(api, res, set, get)) + .then((res: SoapResponse) => handleResponse(api, res)) .catch((e) => { report(app)(e); throw e; }) as Promise; + }; export const getXmlSoapFetch = - (app: string, set: SetState, get: GetState) => - (api: string, body: Request, otherAccount?: string): Promise => - fetch(`/service/soap/${api}Request`, { + (app: string) => + (api: string, body: Request, otherAccount?: string): Promise => { + const { zimbraVersion, account } = useAccountStore.getState(); + const { context } = useNetworkStore.getState(); + return fetch(`/service/soap/${api}Request`, { method: 'POST', headers: { 'content-type': 'application/soap+xml' }, body: ` - ${getXmlSession(get().context)}${getXmlAccount( - get().account, - otherAccount - )} + ${getXmlSession( + context + )}${getXmlAccount(account, otherAccount)} ${body} ` }) // TODO proper error handling .then((res) => res?.json()) - .then((res: SoapResponse) => handleResponse(api, res, set, get)) + .then((res: SoapResponse) => handleResponse(api, res)) .catch((e) => { report(app)(e); throw e; }) as Promise; + }; diff --git a/src/network/get-info.ts b/src/network/get-info.ts index 5714af6c..986b2c67 100644 --- a/src/network/get-info.ts +++ b/src/network/get-info.ts @@ -12,6 +12,9 @@ import { normalizeAccount } from '../store/account/normalization'; import { AccountSettings, AccountState, GetInfoResponse, Tag, CarbonioModule } from '../../types'; import { goToLogin } from './go-to-login'; import { isAdmin, isFullClient, isStandalone } from '../multimode'; +import { getSoapFetch } from './fetch'; +import { useAccountStore } from '../store/account'; +import { useNetworkStore } from '../store/network'; const parsePollingInterval = (settings: AccountSettings): number => { const pollingPref = (settings.prefs?.zimbraPrefMailPollingInterval ?? '') as string; @@ -27,19 +30,20 @@ const parsePollingInterval = (settings: AccountSettings): number => { } return pollingValue * 1000; }; -export const getInfo = (set: SetState, get: GetState): Promise => - get() - .soapFetch(SHELL_APP_ID)<{ _jsns: string; rights: string }, GetInfoResponse>('GetInfo', { - _jsns: 'urn:zimbraAccount', - rights: 'sendAs,sendAsDistList,viewFreeBusy,sendOnBehalfOf,sendOnBehalfOfDistList' - }) +export const getInfo = (): Promise => + getSoapFetch(SHELL_APP_ID)<{ _jsns: string; rights: string }, GetInfoResponse>('GetInfo', { + _jsns: 'urn:zimbraAccount', + rights: 'sendAs,sendAsDistList,viewFreeBusy,sendOnBehalfOf,sendOnBehalfOfDistList' + }) .then((res: any): void => { if (res) { const { account, settings, version } = normalizeAccount(res); - set({ + useNetworkStore.setState({ + pollingInterval: parsePollingInterval(settings) + }); + useAccountStore.setState({ account, settings, - pollingInterval: parsePollingInterval(settings), zimbraVersion: version }); } diff --git a/src/network/logout.ts b/src/network/logout.ts index 9a3efbc8..4025c953 100644 --- a/src/network/logout.ts +++ b/src/network/logout.ts @@ -5,17 +5,14 @@ */ import { SHELL_APP_ID } from '../constants'; -import { useAccountStore } from '../store/account'; +import { getSoapFetch } from './fetch'; import { goToLogin } from './go-to-login'; export const logout = (): Promise => - useAccountStore - .getState() - .soapFetch(SHELL_APP_ID)('EndSession', { - _jsns: 'urn:zimbraAccount' - }) - .then(() => { - fetch('/?loginOp=logout') - .then((res) => res) - .then(goToLogin); - }); + getSoapFetch(SHELL_APP_ID)('EndSession', { + _jsns: 'urn:zimbraAccount' + }).then(() => { + fetch('/?loginOp=logout') + .then((res) => res) + .then(goToLogin); + }); diff --git a/src/network/noOp.ts b/src/network/noOp.ts deleted file mode 100644 index 6be9d405..00000000 --- a/src/network/noOp.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 Zextras - * - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { GetState } from 'zustand'; -import { AccountState } from '../../types'; -import { SHELL_APP_ID } from '../constants'; - -export const noOp = (get: GetState): void => { - get().soapFetch(SHELL_APP_ID)( - 'NoOp', - get().pollingInterval === 500 - ? { _jsns: 'urn:zimbraMail', limitToOneBlocked: 1, wait: 1 } - : { _jsns: 'urn:zimbraMail' } - ); -}; diff --git a/src/settings/accounts-settings.tsx b/src/settings/accounts-settings.tsx index 0ad6ea69..2d66c6ab 100644 --- a/src/settings/accounts-settings.tsx +++ b/src/settings/accounts-settings.tsx @@ -21,6 +21,7 @@ import Delegates from './components/account-settings/delegates'; import PersonaSettings from './components/account-settings/persona-settings'; import PersonaUseSection from './components/account-settings/persona-use-section'; import SettingsHeader from './components/settings-header'; +import { getXmlSoapFetch } from '../network/fetch'; // external accounts not yet activated, graphical part is complete // import ExternalAccount from './components/account-settings/external-account-settings'; @@ -164,42 +165,39 @@ export const AccountsSettings = ({ identitiesDefault, t }: AccountSettingsProps) const createSnackbar = useSnackbar(); useEffect(() => { - useAccountStore - .getState() - .xmlSoapFetch(SHELL_APP_ID)( - 'GetRights', - `` - ) - .then((res: any) => { - if (res.ace) { - const tempResult: UserRightsProps[] = map(res.ace, (item) => ({ - email: item.d, - right: item.right - })); - const resultReduced = reduce( - tempResult, - (result: UserRightsProps[], item) => { - const index = findIndex(result, { email: item.email }); - if (index === -1) { - result.push({ email: item.email, right: item.right }); - } else { - result.push({ - email: item.email, - right: `${item.right} and ${result[index].right}` - }); - result.splice(index, 1); - } - return result; - }, - [] - ); - const result = map(resultReduced, (item: UserRightsProps, index) => ({ - ...item, - id: index.toString() - })); - setDelegates(result); - } - }); + getXmlSoapFetch(SHELL_APP_ID)( + 'GetRights', + `` + ).then((res: any) => { + if (res.ace) { + const tempResult: UserRightsProps[] = map(res.ace, (item) => ({ + email: item.d, + right: item.right + })); + const resultReduced = reduce( + tempResult, + (result: UserRightsProps[], item) => { + const index = findIndex(result, { email: item.email }); + if (index === -1) { + result.push({ email: item.email, right: item.right }); + } else { + result.push({ + email: item.email, + right: `${item.right} and ${result[index].right}` + }); + result.splice(index, 1); + } + return result; + }, + [] + ); + const result = map(resultReduced, (item: UserRightsProps, index) => ({ + ...item, + id: index.toString() + })); + setDelegates(result); + } + }); }, []); useEffect(() => { diff --git a/src/settings/components/account-settings/accounts-list.tsx b/src/settings/components/account-settings/accounts-list.tsx index 4e7e78c8..ddc1103d 100644 --- a/src/settings/components/account-settings/accounts-list.tsx +++ b/src/settings/components/account-settings/accounts-list.tsx @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import React, { useCallback, ReactElement, useMemo, useState, useContext } from 'react'; +import React, { useCallback, ReactElement, useState, useContext } from 'react'; import { Container, Text, diff --git a/src/settings/components/account-settings/password-recovery-settings.tsx b/src/settings/components/account-settings/password-recovery-settings.tsx index 7bc4a2a8..1e79cf65 100644 --- a/src/settings/components/account-settings/password-recovery-settings.tsx +++ b/src/settings/components/account-settings/password-recovery-settings.tsx @@ -17,7 +17,7 @@ import { import { TFunction } from 'i18next'; import { SHELL_APP_ID, EMAIL_VALIDATION_REGEX } from '../../../constants'; import { IdentityProps } from '../../../../types'; -import { useAccountStore } from '../../../store/account/store'; +import { getXmlSoapFetch } from '../../../network/fetch'; interface PasswordRecoverySettingsProps { t: TFunction; @@ -65,22 +65,19 @@ const PasswordRecoverySettings = ({ ); const onSubmit = useCallback(() => { - useAccountStore - .getState() - .xmlSoapFetch(SHELL_APP_ID)( - 'SetRecoveryAccount', - `` - ) - .catch(() => { - createSnackbar({ - key: `new`, - replace: true, - type: 'error', - label: t('snackbar.error', 'Something went wrong, please try again'), - autoHideTimeout: 3000, - hideButton: true - }); + getXmlSoapFetch(SHELL_APP_ID)( + 'SetRecoveryAccount', + `` + ).catch(() => { + createSnackbar({ + key: `new`, + replace: true, + type: 'error', + label: t('snackbar.error', 'Something went wrong, please try again'), + autoHideTimeout: 3000, + hideButton: true }); + }); }, [createSnackbar, emailValue, t]); return ( diff --git a/src/settings/components/account-settings/settings-sent-messages.tsx b/src/settings/components/account-settings/settings-sent-messages.tsx index 3734722f..8695524e 100644 --- a/src/settings/components/account-settings/settings-sent-messages.tsx +++ b/src/settings/components/account-settings/settings-sent-messages.tsx @@ -18,7 +18,7 @@ import { } from '@zextras/carbonio-design-system'; import { TFunction } from 'i18next'; import { filter, find } from 'lodash'; -import { IdentityProps, Mods } from '../../../../types'; +import { IdentityProps } from '../../../../types'; import { EMAIL_VALIDATION_REGEX } from '../../../constants'; type SettingsSentMessagesProps = { diff --git a/src/settings/components/date-time-select-view.tsx b/src/settings/components/date-time-select-view.tsx index c8a96228..3ec89511 100644 --- a/src/settings/components/date-time-select-view.tsx +++ b/src/settings/components/date-time-select-view.tsx @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import React, { useState, useCallback, FC, useEffect, useMemo } from 'react'; +import React, { useState, useCallback, FC, useEffect } from 'react'; import { Container, Checkbox, Text, Icon, Padding } from '@zextras/carbonio-design-system'; import moment from 'moment'; diff --git a/src/store/account/hooks.ts b/src/store/account/hooks.ts index c3444040..b50cd532 100644 --- a/src/store/account/hooks.ts +++ b/src/store/account/hooks.ts @@ -12,7 +12,6 @@ import { AccountRights, AccountRightTarget, AccountSettings, - NotifyObject, Tag } from '../../../types'; import { useAccountStore } from './store'; @@ -38,12 +37,6 @@ export const useUserSetting = (...path: Array): string | T => useAccountStore((s) => get(s.settings, join(path, '.'))); export const useTags = (): Array => useAccountStore((s) => s.tags); -export const useNotify = (): NotifyObject[] => { - const notify = useAccountStore((s) => s.context.notify ?? []); - return notify; -}; -export const useRefresh = (): NotifyObject => useAccountStore((s) => s.context.refresh ?? {}); - export const getUserAccount = (): Account => useAccountStore.getState().account as Account; export const getUserAccounts = (): Array => [ useAccountStore.getState().account as Account diff --git a/src/store/account/store.ts b/src/store/account/store.ts index 8e76c63f..c9e9adac 100644 --- a/src/store/account/store.ts +++ b/src/store/account/store.ts @@ -5,13 +5,11 @@ */ import create, { StoreApi, UseBoundStore } from 'zustand'; -import { AccountContext, AccountState, SoapFetch } from '../../../types'; -import { getInfo } from '../../network/get-info'; -import { getSoapFetch, getXmlSoapFetch } from '../../network/fetch'; +import { AccountState } from '../../../types'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore -export const useAccountStore = create((set, get) => ({ +export const useAccountStore = create(() => ({ account: undefined, version: '', settings: { @@ -19,12 +17,6 @@ export const useAccountStore = create((set, get) => ({ attrs: {}, props: [] }, - context: {}, - setContext: (context: AccountContext): void => set({ context }), - init: (): Promise => getInfo(set, get), - soapFetch: (app: string): SoapFetch => getSoapFetch(app, set, get), - xmlSoapFetch: (app: string): SoapFetch => getXmlSoapFetch(app, set, get), usedQuota: 0, - lastNotificationTime: Date.now(), - pollingInterval: 30000 + lastNotificationTime: Date.now() })) as UseBoundStore>; diff --git a/src/store/network/hooks.ts b/src/store/network/hooks.ts new file mode 100644 index 00000000..5e29012e --- /dev/null +++ b/src/store/network/hooks.ts @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2022 Zextras + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import { NotifyObject } from '../../../types'; +import { useNetworkStore } from './store'; + +export const useNotify = (): NotifyObject[] => { + const notify = useNetworkStore((s) => s.context.notify ?? []); + return notify; +}; +export const useRefresh = (): NotifyObject => useNetworkStore((s) => s.context.refresh ?? {}); diff --git a/src/store/network/index.ts b/src/store/network/index.ts new file mode 100644 index 00000000..f3edd078 --- /dev/null +++ b/src/store/network/index.ts @@ -0,0 +1,7 @@ +/* + * SPDX-FileCopyrightText: 2022 Zextras + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export * from './store'; diff --git a/src/store/network/store.ts b/src/store/network/store.ts new file mode 100644 index 00000000..f927a7f7 --- /dev/null +++ b/src/store/network/store.ts @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2021 Zextras + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import create, { StoreApi, UseBoundStore } from 'zustand'; +import { NetworkState } from '../../../types'; + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +export const useNetworkStore = create(() => ({ + noOpTimeout: undefined, + context: {}, + pollingInterval: 30000 +})) as UseBoundStore>; diff --git a/types/account/index.d.ts b/types/account/index.d.ts index f7336910..3df81a35 100644 --- a/types/account/index.d.ts +++ b/types/account/index.d.ts @@ -17,32 +17,11 @@ export type SoapFetch = ( ) => Promise; export type AccountState = { - noOpTimeout: unknown; account?: Account; settings: AccountSettings; zimbraVersion: string; - context: AccountContext; - init: () => Promise; - setContext: (context: unknown) => void; - xmlSoapFetch: (app: string) => SoapFetch; - soapFetch: (app: string) => SoapFetch; tags: Array; usedQuota: number; - pollingInterval: number; -}; - -export type AccountContext = { - refresh?: NotifyObject; - notify?: [NotifyObject]; - change?: { token: number }; - session?: { id: number; _content: number }; -}; - -export type NotifyObject = { - seq?: number; - version?: string; - mbx?: [{ s: number }]; - folder?: Array; }; export type Account = { diff --git a/types/network/index.d.ts b/types/network/index.d.ts index 9ae92a38..ff2e7fa8 100644 --- a/types/network/index.d.ts +++ b/types/network/index.d.ts @@ -87,18 +87,18 @@ export type PermissionsMods = { export type CreateIdentityProps = { requestId: number; - zimbraPrefIdentityName: string | undfined; - zimbraPrefFromDisplay: string | undfined; - zimbraPrefFromAddress: string | undfined; - zimbraPrefFromAddress: string | undfined; - zimbraPrefFromAddressType: string | undfined; - zimbraPrefReplyToEnabled: string | undfined; - zimbraPrefReplyToDisplay: string | undfined; - zimbraPrefReplyToAddress: string | undfined; - zimbraPrefDefaultSignatureId: string | undfined; - zimbraPrefForwardReplySignatureId: string | undfined; - zimbraPrefWhenSentToEnabled: string | undfined; - zimbraPrefWhenInFoldersEnabled: string | undfined; + zimbraPrefIdentityName: string | undefined; + zimbraPrefFromDisplay: string | undefined; + zimbraPrefFromAddress: string | undefined; + zimbraPrefFromAddress: string | undefined; + zimbraPrefFromAddressType: string | undefined; + zimbraPrefReplyToEnabled: string | undefined; + zimbraPrefReplyToDisplay: string | undefined; + zimbraPrefReplyToAddress: string | undefined; + zimbraPrefDefaultSignatureId: string | undefined; + zimbraPrefForwardReplySignatureId: string | undefined; + zimbraPrefWhenSentToEnabled: string | undefined; + zimbraPrefWhenInFoldersEnabled: string | undefined; }; export type IdentityMods = { @@ -124,3 +124,22 @@ export type Locale = { export type AvailableLocalesResponse = { locale: Array; }; +export type SoapContext = { + refresh?: NotifyObject; + notify?: [NotifyObject]; + change?: { token: number }; + session?: { id: number; _content: number }; +}; + +export type NotifyObject = { + seq?: number; + version?: string; + mbx?: [{ s: number }]; + folder?: Array; +}; + +export type NetworkState = { + noOpTimeout: unknown; + context: SoapContext; + pollingInterval: number; +};