Skip to content

Commit

Permalink
UIORGS-397: add privileged donor contacts and crud operation for priv…
Browse files Browse the repository at this point in the history
…ileged contacts
  • Loading branch information
alisher-epam committed Dec 6, 2023
1 parent cf2c36c commit db5327f
Show file tree
Hide file tree
Showing 14 changed files with 98 additions and 39 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* Modify summary display in organization view mode. Refs UIORGS-398.
* Protection of viewing and changes of banking information by permissions. Refs UIORGS-388.
* Search organization on bank account number. Refs UIORGS-392.
* Create Privileged donor information accordion in organization record. Refs UIORGS-397.

## [5.0.0](https://github.com/folio-org/ui-organizations/tree/v5.0.0) (2023-10-12)
[Full Changelog](https://github.com/folio-org/ui-organizations/compare/v4.0.0...v5.0.0)
Expand Down
20 changes: 10 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@ class Organizations extends Component {
<Switch>
<Route
component={ContactsContainer}
path="/organizations/contacts/"
path={[
'/organizations/contacts/',
'/organizations/privileged-contacts/',
'/organizations/:orgId/contacts/',
'/organizations/:orgId/privileged-contacts/',
]}
/>
<Route
component={InterfaceContainer}
path="/organizations/interface/"
/>
<Route
component={ContactsContainer}
path="/organizations/:orgId/contacts/"
/>
<Route
component={InterfaceContainer}
path="/organizations/:orgId/interface/"
path={[
'/organizations/interface/',
'/organizations/:orgId/interface/',
]}
/>
<Route
path="/organizations/:orgId/integration/"
Expand Down
13 changes: 7 additions & 6 deletions src/Organizations/OrganizationDetails/OrganizationDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
import { NotesSmartAccordion } from '@folio/stripes/smart-components';
import {
handleKeyCommand,
PrivilegedDonorsListContainer,
TagsBadge,
TagsPane,
useAcqRestrictions,
Expand Down Expand Up @@ -68,7 +69,7 @@ const {
bankingInformationSection,
contactInformationSection,
contactPeopleSection,
donorContacts,
privilegedDonorInformation,
integrationDetailsSection,
interfacesSection,
notesSection,
Expand Down Expand Up @@ -341,12 +342,12 @@ const OrganizationDetails = ({
{
isDonorVisible && (
<Accordion
id={donorContacts}
label={ORGANIZATION_SECTION_LABELS[donorContacts]}
id={privilegedDonorInformation}
label={ORGANIZATION_SECTION_LABELS[privilegedDonorInformation]}
>
{/*
TODO: add Privileged donor information component https://issues.folio.org/browse/UIORGS-397
*/}
<PrivilegedDonorsListContainer
privilegedContactIds={organization.privilegedContacts}
/>
</Accordion>
)
}
Expand Down
16 changes: 16 additions & 0 deletions src/Organizations/OrganizationForm/OrganizationForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { ViewMetaData } from '@folio/stripes/smart-components';
import {
FormFooter,
PrivilegedDonorContacts,
handleKeyCommand,
useAccordionToggle,
} from '@folio/stripes-acq-components';
Expand Down Expand Up @@ -55,6 +56,7 @@ const OrganizationForm = ({
[ORGANIZATION_SECTIONS.contactInformationSection]: false,
[ORGANIZATION_SECTIONS.contactPeopleSection]: false,
[ORGANIZATION_SECTIONS.interfacesSection]: false,
[ORGANIZATION_SECTIONS.privilegedDonorInformation]: false,
[ORGANIZATION_SECTIONS.vendorInformationSection]: false,
[ORGANIZATION_SECTIONS.bankingInformationSection]: false,
[ORGANIZATION_SECTIONS.vendorTermsSection]: false,
Expand Down Expand Up @@ -199,6 +201,20 @@ const OrganizationForm = ({
{
formValues.isVendor && (
<>
{
formValues.isDonor && (
<Accordion
id={ORGANIZATION_SECTIONS.privilegedDonorInformation}
label={ORGANIZATION_SECTION_LABELS[ORGANIZATION_SECTIONS.privilegedDonorInformation]}
>
<PrivilegedDonorContacts
orgId={id}
privilegedContactIds={formValues.privilegedContacts}
isPrivilegedContactEnabled
/>
</Accordion>
)
}
<Accordion
id={ORGANIZATION_SECTIONS.vendorInformationSection}
label={ORGANIZATION_SECTION_LABELS[ORGANIZATION_SECTIONS.vendorInformationSection]}
Expand Down
4 changes: 2 additions & 2 deletions src/Organizations/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const ORGANIZATION_SECTIONS = {
notesSection: 'notesSection',
integrationDetailsSection: 'integrationDetailsSection',
agreements: 'linkedAgreements',
donorContacts: 'donorContacts',
privilegedDonorInformation: 'privilegedDonorInformation',
};

export const ORGANIZATION_SECTION_LABELS = {
Expand All @@ -26,7 +26,7 @@ export const ORGANIZATION_SECTION_LABELS = {
[ORGANIZATION_SECTIONS.accountsSection]: <FormattedMessage id="ui-organizations.accounts" />,
[ORGANIZATION_SECTIONS.integrationDetailsSection]: <FormattedMessage id="ui-organizations.integrationDetails" />,
[ORGANIZATION_SECTIONS.agreements]: <FormattedMessage id="ui-organizations.linkedAgreements.section" />,
[ORGANIZATION_SECTIONS.donorContacts]: <FormattedMessage id="ui-organizations.donorContacts" />,
[ORGANIZATION_SECTIONS.privilegedDonorInformation]: <FormattedMessage id="ui-organizations.privilegedDonorInformation" />,
};

export const CREATE_UNITS_PERM = 'organizations.acquisitions-units-assignments.assign';
Expand Down
1 change: 1 addition & 0 deletions src/common/constants/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const BANKING_INFORMATION_API = 'organizations/banking-information';
export const CATEGORIES_API = 'organizations-storage/categories';
export const CONTACTS_API = 'organizations-storage/contacts';
export const INTERFACES_API = 'organizations-storage/interfaces';
export const PRIVILEGED_CONTACTS_API = 'organizations-storage/privileged-contacts';
export const SETTINGS_API = 'organizations-storage/settings';
export const TYPES_API = 'organizations-storage/organization-types';

Expand Down
15 changes: 14 additions & 1 deletion src/common/resources/contacts.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { CONTACTS_API, MAX_LIMIT } from '../constants';
import {
CONTACTS_API,
MAX_LIMIT,
PRIVILEGED_CONTACTS_API,
} from '../constants';

export const contactResource = {
throwErrors: false,
Expand All @@ -9,6 +13,15 @@ export const contactResource = {
},
};

export const privilegedContactResource = {
throwErrors: false,
type: 'okapi',
path: `${PRIVILEGED_CONTACTS_API}/:{id}`,
POST: {
path: PRIVILEGED_CONTACTS_API,
},
};

export const baseContactsResource = {
throwErrors: false,
type: 'okapi',
Expand Down
8 changes: 5 additions & 3 deletions src/contacts/ContactsContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ import {
} from '@folio/stripes-acq-components';

import { VIEW_ORG_DETAILS } from '../common/constants';
import ViewContact from './ViewContact';
import { PRIVILEGED_CONTACT_URL_PATH } from './constants';
import EditContact from './EditContact';
import ViewContact from './ViewContact';

function ContactsContainer({ history, match: { params, url } }) {
const sendCallout = useShowCallout();
const contactsUrlPath = url.includes(PRIVILEGED_CONTACT_URL_PATH) ? PRIVILEGED_CONTACT_URL_PATH : 'contacts';
const showMessage = useCallback((messageKey, messageType = 'success') => {
sendCallout({
type: messageType,
Expand All @@ -32,9 +34,9 @@ function ContactsContainer({ history, match: { params, url } }) {
if (!contactId) {
history.push(`${VIEW_ORG_DETAILS}${orgId}`);
} else {
history.push(`/organizations/${orgId}/contacts/details/${contactId}/view`);
history.push(`/organizations/${orgId}/${contactsUrlPath}/details/${contactId}/view`);
}
}, [history]);
}, [contactsUrlPath, history]);

const goToEdit = useCallback((props) => (
<EditContact
Expand Down
27 changes: 17 additions & 10 deletions src/contacts/EditContact/EditContactContainer.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import React, { useCallback } from 'react';
import { FormattedMessage } from 'react-intl';
import { get } from 'lodash';
import PropTypes from 'prop-types';
import { useCallback } from 'react';
import { FormattedMessage } from 'react-intl';
import ReactRouterPropTypes from 'react-router-prop-types';

import { Icon } from '@folio/stripes/components';
import { stripesConnect } from '@folio/stripes/core';

import { DICT_CATEGORIES } from '../../common/constants';
import { useTranslatedCategories } from '../../common/hooks';
import {
categoriesResource,
contactResource,
organizationResource,
privilegedContactResource,
} from '../../common/resources';
import { saveContact } from './util';
import EditContact from './EditContact';
import { getBackPath } from '../../common/utils/createItem';
import { DICT_CATEGORIES } from '../../common/constants';
import { useTranslatedCategories } from '../../common/hooks';
import { PRIVILEGED_CONTACT_URL_PATH } from '../constants';
import EditContact from './EditContact';
import { saveContact } from './util';

export const EditContactContainer = ({
history,
Expand All @@ -27,7 +30,9 @@ export const EditContactContainer = ({
showMessage,
}) => {
const isNew = !match.params.id;
const loadedContact = resources?.contact?.records?.[0];
const isPrivilegedContactUrl = match.path.includes(PRIVILEGED_CONTACT_URL_PATH);
const contactResources = isPrivilegedContactUrl ? 'privilegedContact' : 'contact';
const loadedContact = get(resources[contactResources], 'records[0]');
const categories = resources?.[DICT_CATEGORIES]?.records;
const [translatedCategories] = useTranslatedCategories(categories);
const contactsOrganization = resources?.contactsOrg?.records?.[0];
Expand All @@ -36,12 +41,12 @@ export const EditContactContainer = ({
if (onClose) {
onClose(orgId, contactId);
} else {
history.push(getBackPath(orgId, contactId, 'contacts'));
history.push(getBackPath(orgId, contactId, isPrivilegedContactUrl ? PRIVILEGED_CONTACT_URL_PATH : 'contacts'));
}
}, [match.params.id, onClose, history, orgId]);
}, [match.params.id, onClose, orgId, history, isPrivilegedContactUrl]);

const onSubmit = useCallback(contactValues => {
saveContact(mutator, contactValues, contactsOrganization)
saveContact(mutator, contactValues, contactsOrganization, isPrivilegedContactUrl)
.then(({ id }) => {
showMessage('ui-organizations.contacts.message.saved.success', 'success');
onCloseForm(id);
Expand All @@ -63,6 +68,7 @@ export const EditContactContainer = ({
const contact = isNew ? {} : loadedContact;
const { firstName, lastName } = contact;
const name = `${lastName}, ${firstName}`;

const paneTitle = isNew
? <FormattedMessage id="ui-organizations.contacts.create.paneTitle" />
: <FormattedMessage id="ui-organizations.contacts.edit.paneTitle" values={{ name }} />;
Expand All @@ -82,6 +88,7 @@ EditContactContainer.manifest = Object.freeze({
contact: contactResource,
[DICT_CATEGORIES]: categoriesResource,
contactsOrg: organizationResource,
privilegedContact: privilegedContactResource,
});

EditContactContainer.propTypes = {
Expand Down
5 changes: 3 additions & 2 deletions src/contacts/EditContact/util.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// eslint-disable-next-line import/prefer-default-export
export const saveContact = (mutator, contact, org) => {
export const saveContact = (mutator, contact, org, isPrivilegedContactUrl = false) => {
const isNew = !contact.id;
const httpMethod = isNew ? mutator.contact.POST : mutator.contact.PUT;
const currentMutator = isPrivilegedContactUrl ? mutator.privilegedContact : mutator.contact;
const httpMethod = isNew ? currentMutator.POST : currentMutator.PUT;

return httpMethod(contact)
.then(savedContact => {
Expand Down
5 changes: 4 additions & 1 deletion src/contacts/ViewContact/ViewContact.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { ORGANIZATIONS_ROUTE } from '../../common/constants';
import {
CONTACT_PERSON_ACCORDIONS,
CONTACT_PERSON_ACCORDION_LABELS,
PRIVILEGED_CONTACT_URL_PATH,
} from '../constants';
import ContactDetails from './ContactDetails';
import ContactAddresses from './ContactAddresses';
Expand All @@ -51,6 +52,7 @@ const ViewContact = ({
}) => {
const history = useHistory();
const accordionStatusRef = useRef();
const isPrivilegedContactUrl = history.location?.pathname?.includes(PRIVILEGED_CONTACT_URL_PATH);

const stripes = useStripes();

Expand Down Expand Up @@ -81,6 +83,7 @@ const ViewContact = ({
// eslint-disable-next-line react/prop-types
const getActionMenu = ({ onToggle }) => {
const contactId = contact.id;
const isUnassignVisible = contactId && !isPrivilegedContactUrl;

return (
<div data-test-view-contact-actions>
Expand All @@ -95,7 +98,7 @@ const ViewContact = ({
</Icon>
</Button>
</IfPermission>
{contactId && (
{isUnassignVisible && (
<Button
data-test-contacts-action-unassign
data-testid="unassign-contact"
Expand Down
18 changes: 15 additions & 3 deletions src/contacts/ViewContact/ViewContactContainer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useState } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { get } from 'lodash';
import { FormattedMessage } from 'react-intl';
Expand All @@ -14,6 +14,7 @@ import {
categoriesResource,
contactResource,
organizationResource,
privilegedContactResource,
} from '../../common/resources';
import { DICT_CATEGORIES } from '../../common/constants';
import { getBackPath } from '../../common/utils/createItem';
Expand All @@ -24,6 +25,7 @@ import {
deleteContact,
unassign,
} from './util';
import { PRIVILEGED_CONTACT_URL_PATH } from '../constants';

export function ViewContactContainer({
baseUrl,
Expand All @@ -37,6 +39,7 @@ export function ViewContactContainer({
}) {
const [confirmDelete, setConfirmDelete] = useState(false);
const [confirmUnassign, setConfirmUnassign] = useState(false);
const isPrivilegedContactUrl = match.path.includes(PRIVILEGED_CONTACT_URL_PATH);

const _onClose = useCallback(() => {
if (onClose) {
Expand Down Expand Up @@ -67,14 +70,22 @@ export function ViewContactContainer({
}, [_onClose, contactId, hideConfirmUnassign, org, showMessage]);

const onDeleteContact = useCallback(() => {
const contactMutator = isPrivilegedContactUrl ? mutator.privilegedContact : mutator.contact;

hideConfirmDelete();
deleteContact(mutator.organization, mutator.contact, contactId, org)
deleteContact(mutator.organization, contactMutator, contactId, org)
.then(() => _onClose())
.catch(() => showMessage('ui-organizations.contacts.message.deleted.fail', 'error'));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [_onClose, contactId, hideConfirmDelete, org, showMessage]);

const contact = get(resources, 'contact.records[0]', {});
const contact = useMemo(() => {
if (isPrivilegedContactUrl) {
return get(resources, 'privilegedContact.records[0]', {});
}

return get(resources, 'contact.records[0]', {});
}, [isPrivilegedContactUrl, resources]);
const contactCategories = get(resources, `${DICT_CATEGORIES}.records`);
const [translatedCategories] = useTranslatedCategories(contactCategories);
const editUrl = `${baseUrl}/${contact.id}/edit`;
Expand Down Expand Up @@ -124,6 +135,7 @@ ViewContactContainer.manifest = Object.freeze({
contact: contactResource,
[DICT_CATEGORIES]: categoriesResource,
organization: organizationResource,
privilegedContact: privilegedContactResource,
});

ViewContactContainer.propTypes = {
Expand Down
2 changes: 2 additions & 0 deletions src/contacts/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ export const CONTACT_PERSON_ACCORDION_LABELS = {
[CONTACT_PERSON_ACCORDIONS.URLS]: <FormattedMessage id="ui-organizations.contactPeople.urls" />,
[CONTACT_PERSON_ACCORDIONS.ADDRESSES]: <FormattedMessage id="ui-organizations.contactPeople.addresses" />,
};

export const PRIVILEGED_CONTACT_URL_PATH = 'privileged-contacts';
2 changes: 1 addition & 1 deletion translations/ui-organizations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
"contactPeople": "Contact people",
"agreements": "Agreements",
"vendorInformation": "Vendor information",
"donorContacts": "Donor contacts",
"privilegedDonorInformation": "Privileged donor information",
"ediInformation": "EDI information",
"interface": "Interface",
"accounts": "Accounts",
Expand Down

0 comments on commit db5327f

Please sign in to comment.