diff --git a/src/components/ContactCard/ContactFields/ContactField.jsx b/src/components/ContactCard/ContactFields/ContactField.jsx index 5442bb968..c81cb29f8 100644 --- a/src/components/ContactCard/ContactFields/ContactField.jsx +++ b/src/components/ContactCard/ContactFields/ContactField.jsx @@ -9,6 +9,7 @@ const iconsByType = { birthday: 'calendar', note: 'comment', company: 'company', + relationship: 'relationship', jobTitle: 'people', cozy: 'cloud', email: 'email', diff --git a/src/components/ContactCard/ContactFields/FieldByType.jsx b/src/components/ContactCard/ContactFields/FieldByType.jsx index d5ef2b361..be6f0d0ee 100644 --- a/src/components/ContactCard/ContactFields/FieldByType.jsx +++ b/src/components/ContactCard/ContactFields/FieldByType.jsx @@ -3,7 +3,15 @@ import React from 'react' import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n' -import { Birthday, Location, Email, Phone, Cozy, Default } from './FieldTypes' +import { + Birthday, + Location, + Email, + Phone, + Cozy, + Default, + Relationship +} from './FieldTypes' const FieldByType = ({ value, type }) => { const { t, f } = useI18n() @@ -20,6 +28,8 @@ const FieldByType = ({ value, type }) => { return case 'cozy': return + case 'relationship': + return default: return } diff --git a/src/components/ContactCard/ContactFields/FieldTypes/index.jsx b/src/components/ContactCard/ContactFields/FieldTypes/index.jsx index 9969910c9..fa66ce67f 100644 --- a/src/components/ContactCard/ContactFields/FieldTypes/index.jsx +++ b/src/components/ContactCard/ContactFields/FieldTypes/index.jsx @@ -1,5 +1,7 @@ import React from 'react' +import { generateWebLink, useClient } from 'cozy-client' + import { getFormattedAddress } from '../../../../helpers/contacts' export const Location = ({ value, t }) => { @@ -37,6 +39,23 @@ export const Cozy = ({ url }) => { ) } +export const Relationship = ({ name, id }) => { + const client = useClient() + const link = generateWebLink({ + slug: 'contacts', + cozyUrl: client.getStackClient().uri, + subDomainType: client.getInstanceOptions().subdomain, + pathname: '/', + hash: id + }) + + return ( + + {name} + + ) +} + export const Birthday = ({ value, t, f }) => { return f(new Date(value), t('formatted.date')) } diff --git a/src/components/ContactCard/ContactFields/helpers.js b/src/components/ContactCard/ContactFields/helpers.js index 2bd95f235..00eb1fb63 100644 --- a/src/components/ContactCard/ContactFields/helpers.js +++ b/src/components/ContactCard/ContactFields/helpers.js @@ -7,6 +7,11 @@ const makeCustomOrSupportedLabel = ({ type, value, hasPrefix, t }) => { return makeCustomLabel(JSON.stringify(value), t) } + // If contact has a related contact, but no relation type + if (value.label === 'related') { + return '' + } + if (value.label) { return hasPrefix ? t(`label.${type}.${value.label}`) @@ -26,7 +31,7 @@ const makeCustomOrSupportedLabel = ({ type, value, hasPrefix, t }) => { * @returns {string|null} */ export const makeTLabel = ({ type, value, t, polyglot }) => { - const hasPrefix = ['phone', 'address'].includes(type) + const hasPrefix = ['phone', 'address', 'relationship'].includes(type) if (hasPrefix) { if (type === 'phone') { diff --git a/src/helpers/contacts.js b/src/helpers/contacts.js index a183c45d9..539d2581c 100644 --- a/src/helpers/contacts.js +++ b/src/helpers/contacts.js @@ -1,6 +1,7 @@ import sortBy from 'lodash/sortBy' import { models, HasMany } from 'cozy-client' +import { getHasManyItem } from 'cozy-client/dist/associations/HasMany' const { makeFullname, makeDefaultSortIndexValue, makeDisplayName } = models.contact @@ -13,6 +14,7 @@ export const supportedFieldsInOrder = [ 'company', 'jobTitle', 'birthday', + 'relationship', 'note' ] @@ -63,6 +65,26 @@ export const groupUnsupportedFields = (fields, supportedFieldTypes) => { ]) } +export const makeRelatedContactField = contact => { + if (!contact.related) return null + + const relatedFieldValues = contact.related.data.flatMap(related => { + const relatedRelationships = getHasManyItem(contact, 'related', related._id) + return relatedRelationships.metadata.relationTypes.map(type => { + return { + label: type, + name: related.displayName, + id: related._id + } + }) + }) + + return { + type: 'relationship', // To match the translation key already in place + values: relatedFieldValues + } +} + export const orderFieldList = (fields, fieldsInOrder) => fields.slice().sort((a, b) => { const indexA = fieldsInOrder.includes(a.type) @@ -85,7 +107,11 @@ export const getConnectedAccounts = contact => export const normalizeFields = contact => { const fields = getFieldListFrom(contact) - const filteredFields = filterFieldList(fields) + const filteredFields = filterFieldList(fields, contact) + const relatedField = makeRelatedContactField(contact) + if (relatedField) { + filteredFields.push(relatedField) + } const groupedFields = groupUnsupportedFields( filteredFields, supportedFieldsInOrder diff --git a/src/helpers/contacts.spec.js b/src/helpers/contacts.spec.js index f36e55662..1daab94e5 100644 --- a/src/helpers/contacts.spec.js +++ b/src/helpers/contacts.spec.js @@ -10,7 +10,7 @@ import { getFormattedAddress, makeContactWithIdentitiesAddresses } from './contacts' -import { johnDoeContact } from './testData' +import { johnDoeContact, johnDoeContactWithRelated } from './testData' const MOCKED_DATE = '2018-01-01T12:00:00.210Z' @@ -127,6 +127,16 @@ describe('normalizeFields', () => { { type: 'company', values: ['Cozy cloud'] }, { type: 'jobTitle', values: ['Dreamer'] }, { type: 'birthday', values: ['1999-5-1'] }, + { + type: 'relationship', + values: [ + { + name: 'Alice Doe', + label: 'spouse', + id: '5b49553c5916cf7b5b2a5f48600078a8' + } + ] + }, { type: 'note', values: [ @@ -136,7 +146,7 @@ describe('normalizeFields', () => { { type: 'other', values: [] } ] - expect(normalizeFields(johnDoeContact)).toEqual(expected) + expect(normalizeFields(johnDoeContactWithRelated)).toEqual(expected) }) }) diff --git a/src/helpers/testData.js b/src/helpers/testData.js index 055117af3..9d0f98b29 100644 --- a/src/helpers/testData.js +++ b/src/helpers/testData.js @@ -146,6 +146,108 @@ export const johnDoeFormValues = { ] } +export const johnDoeContactWithRelated = { + id: '9ecfbf4b-20e7-4bac-87f1-eea53350857d', + _id: '9ecfbf4b-20e7-4bac-87f1-eea53350857d', + _type: 'io.cozy.contacts', + _rev: '1-19c313536e8b27473aa26bf105b03269', + address: [ + { + formattedAddress: '94 Hinton Road 05034 Fresno, Singapore', + type: 'Home', + primary: true + }, + { + pobox: '2', + street: '426 Runolfsson Knolls', + city: 'Port Easter', + region: undefined, + country: 'Cocos (Keeling) Islands', + postcode: '84573', + type: 'Work' + } + ], + email: [ + { + address: 'john.doe@posteo.net', + type: 'personal', + primary: false + }, + { + address: 'john.doe@cozycloud.cc', + primary: true + } + ], + birthday: '1999-5-1', + birthplace: 'somewhere', + gender: 'male', + company: 'Cozy cloud', + jobTitle: 'Dreamer', + cozy: [ + { + type: 'MyCozy', + primary: true, + url: 'https://johndoe.mycozy.cloud' + } + ], + fullname: 'John Doe', + name: { + givenName: 'John', + familyName: 'Doe', + additionalName: 'J.' + }, + metadata: { + cozy: true, + version: 1 + }, + note: 'Atque cupiditate saepe omnis quos ut molestiae labore voluptates omnis.', + phone: [ + { + number: '+33 (2)0 90 00 54 04', + primary: true + }, + { + number: '+33 6 77 11 22 33', + primary: false + } + ], + + relationships: { + accounts: { data: [] }, + groups: { data: [] }, + related: { + data: [ + { + metadata: { relationTypes: ['spouse'] }, + _id: '5b49553c5916cf7b5b2a5f48600078a8', + _type: 'io.cozy.contacts' + } + ] + } + }, + related: { + target: { + id: '4e33fd27e1d8e55a34742bac6d16d3bd', + _id: '4e33fd27e1d8e55a34742bac6d16d3bd', + _type: 'io.cozy.contacts', + _rev: '6-57f4ab78b1fb97bb90ea273ec881f196', + company: '', + fullname: 'John Doe', + me: true, + note: '' + }, + name: 'related', + doctype: 'io.cozy.contacts', + data: [ + { + displayName: 'Alice Doe', + _id: '5b49553c5916cf7b5b2a5f48600078a8', + _type: 'io.cozy.contacts' + } + ] + } +} + export const contactWithGroup = { id: '4e33fd27e1d8e55a34742bac6d16d3bd', _id: '4e33fd27e1d8e55a34742bac6d16d3bd',