Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: setting signatures for identities #299

Merged
merged 5 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions src/types/settings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,35 @@ export type SignItemType = {
}
];
};

type IdentityProps = {
zimbraPrefForwardReplySignatureId: string;
zimbraPrefWhenSentToEnabled: string;
zimbraPrefWhenInFoldersEnabled: string;
zimbraPrefFromAddressType: string;
objectClass: string;
zimbraPrefFromAddress: string;
zimbraPrefFromDisplay: string;
zimbraPrefIdentityId: string;
zimbraPrefDefaultSignatureId: string;
zimbraCreateTimestamp: string;
zimbraPrefIdentityName: string;
zimbraPrefReplyToEnabled: string;
};

type AccountIdentity = {
name: string;
id: string;
_attrs: IdentityProps;
};
type SignatureSettingsPropsType = {
settingsObj: PrefsType;
updateSettings: (arg: {
target: {
updatedIdentities: AccountIdentity[];
updateIdentities: (arg: {
target?: {
name: string;
value: string;
};
_attrs?: IdentityProps;
}) => void;
setDisabled: (arg: boolean) => void;
signatures: SignItemType[];
Expand Down
121 changes: 121 additions & 0 deletions src/views/settings/components/select-identity-signature.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* SPDX-FileCopyrightText: 2022 Zextras <https://www.zextras.com>
*
* SPDX-License-Identifier: AGPL-3.0-only
*/

import React, { FC, ReactElement, useCallback, useMemo } from 'react';
import { Container, Text, Row, Select, SelectItem } from '@zextras/carbonio-design-system';
import { t } from '@zextras/carbonio-shell-ui';
import { find } from 'lodash';
import { NO_SIGNATURE_ID, NO_SIGNATURE_LABEL } from '../../../helpers/signatures';
import { AccountIdentity, IdentityProps, SignItemType } from '../../../types';

type SelectIdentitySignProps = {
acc: AccountIdentity;
signatures: SignItemType[];
signatureSelectItems: SelectItem[];
updateIdentities: (arg: { _attrs: IdentityProps }) => void;
};

// TODO remove the any after the DS
const SelectIdentitySignature: FC<SelectIdentitySignProps> = ({
acc,
signatures,
signatureSelectItems,
updateIdentities
}): ReactElement => {
const getSignature = useCallback(
(id: string, fallbackOnFirst = false) => {
const result = find(signatures, ['id', id]);
if (!result && fallbackOnFirst && signatures.length > 0) {
return signatures[0];
}

return result;
},
[signatures]
);

// Create the fake signature for the "no signature"
const noSignature: SignItemType = useMemo(
() => ({
label: t('label.no_signature', NO_SIGNATURE_LABEL),
name: 'no signature',
description: '',
id: NO_SIGNATURE_ID
}),
[]
);

// Get the selected signatures for the new message and for the replies
const [signatureNewMessage, signatureRepliesForwards] = useMemo(
() => [
getSignature(acc._attrs.zimbraPrefDefaultSignatureId) ?? noSignature,
getSignature(String(acc._attrs.zimbraPrefForwardReplySignatureId)) ?? noSignature
],
[
acc._attrs.zimbraPrefDefaultSignatureId,
acc._attrs.zimbraPrefForwardReplySignatureId,
getSignature,
noSignature
]
);

return (
<Row width="100%" padding={{ horizontal: 'small', vertical: 'small' }}>
<Container
width="20%"
mainAlignment="flex-start"
crossAlignment="flex-start"
padding={{ right: 'medium' }}
>
<Text>{acc.name}</Text>
</Container>
<Container width="40%" padding={{ right: 'medium' }}>
<Select
items={signatureSelectItems}
label={t('title.new_messages', 'New Messages')}
selection={
{
label: signatureNewMessage?.label,
value: signatureNewMessage?.id
} as SelectItem
}
onChange={(selectedId: any): void => {
if (selectedId === signatureNewMessage?.id) {
return;
}
updateIdentities({
...acc,
_attrs: { ...acc._attrs, zimbraPrefDefaultSignatureId: selectedId }
});
}}
/>
</Container>
<Container width="40%">
<Select
items={signatureSelectItems}
label={t('title.replies_forwards', 'Replies & Forwards')}
selection={
{
label: signatureRepliesForwards?.label,
value: signatureRepliesForwards?.id
} as SelectItem
}
onChange={(selectedId: any): void => {
if (selectedId === signatureRepliesForwards?.id) {
return;
}
updateIdentities({
...acc,
_attrs: { ...acc._attrs, zimbraPrefForwardReplySignatureId: selectedId }
});
}}
/>
</Container>
</Row>
);
};

export default SelectIdentitySignature;
19 changes: 18 additions & 1 deletion src/views/settings/components/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
/* eslint-disable no-nested-ternary */
import { t } from '@zextras/carbonio-shell-ui';
import { filter, isEqual, isObject, reduce, transform } from 'lodash';
import { filter, find, isEqual, isObject, map, reduce, transform } from 'lodash';

export const differenceObject = (object, base) => {
// eslint-disable-next-line no-shadow
Expand All @@ -21,6 +21,23 @@ export const differenceObject = (object, base) => {
return changes(object, base);
};

export const differenceIdentities = (original, modified) => {
const matched = [];
map(modified, (acc) => {
if (!isEqual(acc, find(original, ['id', acc.id]))) {
matched.push({
id: acc.id,
name: acc.name,
prefs: {
zimbraPrefDefaultSignatureId: acc._attrs.zimbraPrefDefaultSignatureId,
zimbraPrefForwardReplySignatureId: acc._attrs.zimbraPrefForwardReplySignatureId
}
});
}
});
return matched;
};

export const getPropsDiff = (original, modified) =>
reduce(
Object.keys(modified),
Expand Down
49 changes: 38 additions & 11 deletions src/views/settings/settings-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ import {
getBridgedFunctions
} from '@zextras/carbonio-shell-ui';
import { useDispatch } from 'react-redux';
import { map, forEach, isEqual, filter, find, cloneDeep, isEmpty, reduce } from 'lodash';
import { map, forEach, isEqual, filter, find, cloneDeep, isEmpty, reduce, remove } from 'lodash';
import { Container, FormSection } from '@zextras/carbonio-design-system';
import { NO_SIGNATURE_ID } from '../../helpers/signatures';
import { getPropsDiff, differenceObject } from './components/utils';
import { getPropsDiff, differenceObject, differenceIdentities } from './components/utils';
import DisplayMessagesSettings from './displaying-messages-settings';
import ReceivingMessagesSettings from './receiving-messages-settings';
import SignatureSettings from './signature-settings';
import FilterModule from './filters';
import TrusteeAddresses from './trustee-addresses';
import { SignatureRequest } from '../../store/actions/signatures';
import ComposeMessage from './compose-msg-settings';
import { PropsType, SignItemType } from '../../types';
import { AccountIdentity, PropsType, SignItemType } from '../../types';

/* to keep track of changes done to props we use 3 different values:
* - originalProps is the status of the props when you open the settings for the first time
Expand All @@ -37,8 +37,11 @@ import { PropsType, SignItemType } from '../../types';
* */
const SettingsView: FC = () => {
const { prefs, props } = useUserSettings();

const account = useUserAccount();
const { identity } = account.identities;
const defaultAccount = remove(identity, (acc: AccountIdentity) => acc.name === 'DEFAULT');
const identities = defaultAccount.concat(identity);

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const [settingsObj, setSettingsObj] = useState<PrefsType>({ ...prefs });
Expand All @@ -56,13 +59,15 @@ const SettingsView: FC = () => {
const [updatedProps, setUpdatedProps] = useState<PropsType | Record<string, unknown>>(
originalProps
);

const [currentIdentities, setCurrentIdentities] = useState(identities);
const [updatedIdentities, setUpdatedIdentities] = useState(identities);
const [signatures, setSignatures] = useState<SignItemType[]>(() => []);
const [originalSignatures, setOriginalSignatures] = useState(() => []);
const [disabled, setDisabled] = useState(true);
const [flag, setFlag] = useState(false);

const dispatch = useDispatch();
// const [fetchSigns, setFetchSigns] = useState(true);

const oldSettings = useMemo(() => {
const s = cloneDeep(prefs);
Expand All @@ -85,7 +90,8 @@ const SettingsView: FC = () => {
setUpdatedSettings({});
// we discard only latest updates keeping successfully saved changes
setUpdatedProps(currentProps);
}, [currentProps, prefs]);
setUpdatedIdentities(identities);
}, [currentProps, identities, prefs]);

const updateSettings = useCallback(
(e) => {
Expand All @@ -102,6 +108,19 @@ const SettingsView: FC = () => {
[updatedProps]
);

const updateIdentities = useCallback(
(e) => {
const data = map(updatedIdentities, (item: AccountIdentity) => {
if (item.id === e.id) {
return e;
}
return item;
});
setUpdatedIdentities(data);
},
[updatedIdentities]
);

const settingsToUpdate = useMemo(
() => differenceObject(updatedSettings, oldSettings),
[updatedSettings, oldSettings]
Expand All @@ -111,13 +130,18 @@ const SettingsView: FC = () => {
() => getPropsDiff(currentProps, updatedProps),
[currentProps, updatedProps]
);
const identitiesToUpdate = useMemo(
() => differenceIdentities(currentIdentities, updatedIdentities),
[currentIdentities, updatedIdentities]
);

const isDisabled = useMemo(
() =>
Object.keys(settingsToUpdate).length === 0 &&
disabled &&
Object.keys(propsToUpdate).length === 0,
[settingsToUpdate, disabled, propsToUpdate]
Object.keys(propsToUpdate).length === 0 &&
Object.keys(identitiesToUpdate).length === 0,
[settingsToUpdate, disabled, propsToUpdate, identitiesToUpdate]
);
const setNewOrForwardSignatureId = useCallback(
(itemsAdd, resp, oldSignatureId, isFowardSignature): void => {
Expand Down Expand Up @@ -145,7 +169,6 @@ const SettingsView: FC = () => {
},
[]
);

// eslint-disable-next-line consistent-return
const saveChanges = useCallback(() => {
let changes = {};
Expand Down Expand Up @@ -254,7 +277,9 @@ const SettingsView: FC = () => {
if (Object.keys(propsToUpdate).length > 0) {
changes = { ...changes, props: propsToUpdate };
}

if (Object.keys(identitiesToUpdate).length > 0) {
changes = { ...changes, identity: { modifyList: identitiesToUpdate } };
}
if (!isEmpty(changes)) {
editSettings(changes).then((res) => {
if (res.type.includes('fulfilled')) {
Expand Down Expand Up @@ -285,6 +310,7 @@ const SettingsView: FC = () => {
originalSignatures,
settingsToUpdate,
propsToUpdate,
identitiesToUpdate,
dispatch,
account,
setNewOrForwardSignatureId,
Expand Down Expand Up @@ -324,7 +350,8 @@ const SettingsView: FC = () => {
// @ts-ignore
setOriginalSignatures={setOriginalSignatures}
updateSettings={updateSettings}
// disabled={disabled}
updatedIdentities={updatedIdentities}
updateIdentities={updateIdentities}
setDisabled={setDisabled}
signatures={signatures}
flag={flag}
Expand Down
Loading