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

Fix updateProjectUpdateContacts #21

Merged
merged 5 commits into from
Dec 25, 2020
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
11 changes: 10 additions & 1 deletion packages/octave/lib/components/projects/ProjectMini.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,19 @@ const ProjectMini = (props) => {
return <MyLoader />
}

const TitleForProject = ({ titleForProject }) => {
return (
<>
{' '}
(<span data-cy='title-for-project'>{titleForProject}</span>)
</>
)
}

return (
<Card.Text className='card-mini' data-cy='ProjectMini'>
<b><Link to={`/projects/${project._id}/${project.slug}`} data-cy='project-link'>{project.projectTitle}</Link></b>
{titleForProject && ` (${titleForProject})`}
{titleForProject && <TitleForProject titleForProject={titleForProject} />}
<br />
<small data-cy='project-type-network-status'>
{project.projectType} {project.network && ` – ${project.network} `} ({project.status})
Expand Down
12 changes: 6 additions & 6 deletions packages/octave/lib/server/patches/callback.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ export function updatePatches ({ currentUser, document, originalDocument, collec
const trimmedDocument = cloneDeep(omitDeep(prunedDocument, doNotDiff[collectionName]))
const trimmedOriginalDocument = cloneDeep(omitDeep(prunedOriginalDocument, doNotDiff[collectionName]))

log.debug('updatePatches trimmed document:')
console.dir(trimmedDocument)
log.debug('updatePatches trimmed originalDocument:')
console.dir(trimmedOriginalDocument)
// log.debug('updatePatches trimmed document:')
// console.dir(trimmedDocument)
// log.debug('updatePatches trimmed originalDocument:')
// console.dir(trimmedOriginalDocument)

const patch = jsonpatch.compare(trimmedDocument, trimmedOriginalDocument, true)

log.debug('updatePatches patch:')
console.dir(patch)
// log.debug('updatePatches patch:')
// console.dir(patch)

if (patch.length > 0) {
const objectId = originalDocument._id
Expand Down
58 changes: 54 additions & 4 deletions packages/octave/lib/server/projects/callbacks/contacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import { Connectors } from 'meteor/vulcan:core'
import Contacts from '../../../modules/contacts/collection.js'
import differenceWith from 'lodash/differenceWith'
import findIndex from 'lodash/findIndex'
import intersectionWith from 'lodash/intersectionWith'
import isEqual from 'lodash/isEqual'
import remove from 'lodash/remove'
import { isEmptyValue } from '../../../modules/helpers.js'
import { find } from 'lodash'

// callbacks.create.async
export const createProjectUpdateContacts = ({ document }) => {
Expand All @@ -17,14 +20,27 @@ export const createProjectUpdateContacts = ({ document }) => {
export const updateProjectUpdateContacts = ({ document, originalDocument }) => {
const newProject = document
const oldProject = originalDocument
const contactsThatWereAdded = differenceWith(newProject.contacts, oldProject.contacts, isSameContact)
const contactsThatWereRemoved = differenceWith(oldProject.contacts, newProject.contacts, isSameContact)
const contactsThatWereRemoved = differenceWith(oldProject.contacts, newProject.contacts, isSameContactById)
const contactsThatWereAdded = differenceWith(newProject.contacts, oldProject.contacts, isSameContactById)
const contactsThatAreSameId = intersectionWith(newProject.contacts, oldProject.contacts, isSameContactById)
const contactsThatWereUpdated = contactsThatAreSameId.filter((newContact) => {
const oldContact = find(oldProject.contacts, { contactId: newContact.contactId })
if (isEqual(newContact, oldContact)) {
return false
} else {
return true
}
})

if (!isEmptyValue(contactsThatWereRemoved)) {
handleRemoveContacts(contactsThatWereRemoved, newProject._id)
}
if (!isEmptyValue(contactsThatWereAdded)) {
handleAddContacts(contactsThatWereAdded, newProject)
}
if (!isEmptyValue(contactsThatWereUpdated)) {
handleUpdateContacts(contactsThatWereUpdated, newProject)
}
}

const handleAddContacts = (contacts, project) => {
Expand Down Expand Up @@ -89,6 +105,40 @@ const handleRemoveContacts = (contacts, projectId) => {
})
}

const isSameContact = (a, b) => {
return a.contactId === b.contactId
const handleUpdateContacts = (contacts, project) => {
const projectId = project._id
contacts.forEach(updatedContact => {
const contact = Contacts.findOne(updatedContact.contactId)
const updatedProject = {
projectId,
projectTitle: project.projectTitle,
titleForProject: updatedContact?.contactTitle
}
let updatedProjects = []
// case 1: nothing there
if (isEmptyValue(contact.projects)) {
updatedProjects = [updatedProject]
} else {
updatedProjects = contact.projects
const i = findIndex(contact.projects, { projectId })
if (i < 0) {
// case 2: add to it
updatedProjects.push(updatedProject)
} else {
// case 3: it is there and needs to be updated <-- different from Add function!
updatedProjects[i] = updatedProject
}
}
Connectors.update(Contacts, contact._id, {
$set: {
projects: updatedProjects,
updatedAt: new Date()
}
})
})
}

const isSameContactById = (a, b) => {
const result = a.contactId === b.contactId
return result
}
4 changes: 0 additions & 4 deletions packages/octave/lib/server/projects/callbacks/offices.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Connectors } from 'meteor/vulcan:core'
import differenceWith from 'lodash/differenceWith'
import findIndex from 'lodash/findIndex'
import remove from 'lodash/remove'
import log from 'loglevel'
import Offices from '../../../modules/offices/collection.js'
import { isEmptyValue } from '../../../modules/helpers.js'

Expand All @@ -20,9 +19,6 @@ export const updateProjectUpdateOffices = ({ document, originalDocument }) => {
const oldProject = originalDocument
const officesThatWereAdded = differenceWith(newProject.offices, oldProject.offices, isSameOffice)
const officesThatWereRemoved = differenceWith(oldProject.offices, newProject.offices, isSameOffice)
log.debug('updateProjectUpdateOffices:')
log.debug('officesThatWereAdded:', officesThatWereAdded)
log.debug('officesThatWereRemoved:', officesThatWereRemoved)
if (!isEmptyValue(officesThatWereRemoved)) {
handleRemoveOffices(officesThatWereRemoved, newProject._id)
}
Expand Down
4 changes: 2 additions & 2 deletions tests/cypress/fixtures/Triad.gz
Git LFS file not shown
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ const doNotClearLocalStorage = () => { }
describe('Projects Update', () => {
before(() => {
Cypress.LocalStorage.clear = doNotClearLocalStorage
cy.downloadTriad()
cy.resetTriad()
cy.stubAlgolia()
cy.readyForCypress()
cy.login()
cy.getTestingCollection('contacts')
cy.getTestingCollection('offices')
Expand Down Expand Up @@ -114,6 +116,81 @@ describe('Projects Update', () => {
log.end()
})

it('contacts on a project: add, delete, and update titles', {
retries: {
runMode: 0,
openMode: 0
}
}, function () {
const project = Cypress._.find(this.testingProjects, { projectTitle: 'SWEDEN' })
const contact0 = Cypress._.find(this.testingContacts, { displayName: 'ADELIND ARONOW' })
const contact1 = Cypress._.find(this.testingContacts, { displayName: 'PANDORA PAFFLEY' })
const contact2 = Cypress._.find(this.testingContacts, { displayName: 'BRODIE BYRON' })
const contact3 = Cypress._.find(this.testingContacts, { displayName: 'SHANE SAVINS' })
const NEW_TITLE = 'Intern'
const log = Cypress.log({
name: 'c on a p',
displayName: 'CONTACTS ON A PROJECT',
message: 'Test handleAddContacts, handleRemoveContacts, handleUpdateContacts',
autoEnd: false
})

// verify all 5 items before
cy.goTo('projects', project)
cy.get('[data-cy=project-header]', { log: false }).contains(project.projectTitle)
cy.get('[data-cy=contact-link]').should('have.length', 3)
cy.get('[data-cy=contact-link]').first().should('contain', contact0.displayName)
cy.get('[data-cy=contact-link]').last().should('contain', contact2.displayName)
cy.goTo('contacts', contact0)
cy.get('[data-cy=contact-header]', { log: false }).contains(contact0.displayName)
cy.get('[data-cy=title-for-project]').should('not.exist')
cy.get('[data-cy=project-link]').should('contain', project.projectTitle)
cy.goTo('contacts', contact1)
cy.get('[data-cy=contact-header]', { log: false }).contains(contact1.displayName)
cy.get('[data-cy=project-link]').should('contain', project.projectTitle)
cy.goTo('contacts', contact2)
cy.get('[data-cy=contact-header]', { log: false }).contains(contact2.displayName)
cy.get('[data-cy=project-link]').should('contain', project.projectTitle)
cy.goTo('contacts', contact3)
cy.get('[data-cy=contact-header]', { log: false }).contains(contact3.displayName)
cy.get('[data-cy=project-link]').should('not.contain', project.projectTitle)
log.snapshot()

// edit
cy.goTo('projects', project)
cy.get('[data-cy=project-header]', { log: false }).contains(project.projectTitle, { log: false })
cy.edit()
cy.get('.form-section-contacts').within(() => {
cy.waitForContactOptions()
cy.clickRedRemoveButton(2)
cy.clickGreenAddButton()
cy.selectContactAndTitle(contact0.displayName, NEW_TITLE, 0)
cy.selectContactAndTitle(contact3.displayName, contact3.title, 3) // note to self: despite deletion, this is #contactId3 not #contactId2 in SmartForm
})
cy.submit()
cy.get('[data-cy=project-header]', { log: false }).contains(project.projectTitle, { log: false })

// verify all 5 items after
cy.get('[data-cy=contact-link]').should('have.length', 3)
cy.get('[data-cy=contact-link]').first().should('contain', contact0.displayName)
cy.get('[data-cy=contact-link]').last().should('contain', contact3.displayName)
cy.goTo('contacts', contact0)
cy.get('[data-cy=contact-header]', { log: false }).contains(contact0.displayName)
cy.get('[data-cy=project-link]').should('contain', project.projectTitle)
cy.get('[data-cy=title-for-project]').should('contain', NEW_TITLE)
cy.goTo('contacts', contact1)
cy.get('[data-cy=contact-header]', { log: false }).contains(contact1.displayName)
cy.get('[data-cy=project-link]').should('contain', project.projectTitle)
cy.goTo('contacts', contact2)
cy.get('[data-cy=contact-header]', { log: false }).contains(contact2.displayName)
cy.get('[data-cy=project-link]').should('not.exist')
cy.goTo('contacts', contact3)
cy.get('[data-cy=contact-header]', { log: false }).contains(contact3.displayName)
cy.get('[data-cy=project-link]').should('contain', project.projectTitle)

log.end()
})

after(() => {
Cypress.LocalStorage.clear = clear
})
Expand Down