Skip to content

Commit

Permalink
feat: case floor plan pins editing (#881)
Browse files Browse the repository at this point in the history
* feat: case floor plan pins editing

* feat: allow to add floor plan pins to a case after creation

* fix: prevent saving same pins set as new floor plan comment

* feat: refactor floor plan renderer/editor to component

* fix: revert sync issue with associated mongo documents

* feat: upload floor plan from case views; add pins to case after creation
  • Loading branch information
nbiton authored and franck-boullier committed Sep 30, 2019
1 parent 32336b8 commit 5e6a62d
Show file tree
Hide file tree
Showing 14 changed files with 532 additions and 271 deletions.
1 change: 1 addition & 0 deletions imports/api/base/associations-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const withDocs = ({ cursorMaker, collectionName }) => (publishedItem, add
// TODO: Consider implementing "removed" for cases where docs are disassociated with an entity
})
cursor.forEach(doc => {
subHandle.removed(collectionName, doc._id) // Resetting existing items in case they exist to avoid revert sync issue -nbiton
addingFn(collectionName, doc._id, doc)
})

Expand Down
40 changes: 13 additions & 27 deletions imports/api/cases.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ PendingInvitations,
findUnitRoleConflictErrors,
TYPE_ASSIGNED
} from './pending-invitations'
import { createFloorPlanComment } from './comments'

export const collectionName = 'cases'
export const caseServerFieldMapping = {
Expand Down Expand Up @@ -198,33 +199,18 @@ export const createCase = (
}

if (floorPlanPins) {
console.log({ unitItem })

const metaData = UnitMetaData.findOne({ bzId: unitItem.id })
const lastFloorPlan = metaData.floorPlanUrls && metaData.floorPlanUrls.slice(-1)[0]
if (lastFloorPlan && !lastFloorPlan.disabled) {
const payload = {
comment: `[!floorPlan(${lastFloorPlan.id})]\n${floorPlanPins.map(({ x, y }) => `${x.toFixed(1)},${y.toFixed(1)}`).join(';')}`,
api_key: creatorUser.bugzillaCreds.apiKey
}

try {
// Creating the comment
const createData = callAPI('post', `/rest/bug/${newCaseId}/comment`, payload, false, true)
if (createData.data.error) {
throw new Meteor.Error(createData.data.error)
}
} catch (e) {
logger.error({
user: creatorUser._id,
method: `${collectionName}.insert`,
args: [params],
step: 'post /rest/bug/{id}/comment adding floor plan',
error: e
})
throw new Meteor.Error(`API Error: ${e.response ? e.response.data.message : e.message}`)
}
}
createFloorPlanComment({
unitBzId: unitItem.id,
caseId: newCaseId,
userApiKey: creatorUser.bugzillaCreds.apiKey,
errorLogParams: {
user: creatorUser._id,
method: `${collectionName}.insert`,
args: [params],
step: 'post /rest/bug/{id}/comment adding floor plan'
},
floorPlanPins
})
}

try {
Expand Down
74 changes: 73 additions & 1 deletion imports/api/comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import bugzillaApi from '../util/bugzilla-api'
import publicationFactory from './base/rest-resource-factory'
import { makeAssociationFactory, withUsers } from './base/associations-helper'
import { logger } from '../util/logger'
import UnitMetaData from './unit-meta-data'
import { idUrlTemplate, factoryOptions as casesFactoryOptions, transformCaseForClient } from './cases'
import { serverHelpers } from './units'

export const collectionName = 'comments'

Expand All @@ -16,6 +19,35 @@ export const factoryOptions = {
}
}

const formatFloorPlanCommentText = (floorPlanId, floorPlanPins) =>
`[!floorPlan(${floorPlanId})]\n${floorPlanPins.map(({ x, y }) => `${x.toFixed(1)},${y.toFixed(1)}`).join(';')}`

export const createFloorPlanComment = ({ unitBzId, caseId, userApiKey, floorPlanPins, errorLogParams }) => {
const metaData = UnitMetaData.findOne({ bzId: unitBzId })
const lastFloorPlan = metaData.floorPlanUrls && metaData.floorPlanUrls.slice(-1)[0]
if (lastFloorPlan && !lastFloorPlan.disabled) {
const payload = {
comment: formatFloorPlanCommentText(lastFloorPlan.id, floorPlanPins),
api_key: userApiKey
}

try {
// Creating the comment
const createData = bugzillaApi.callAPI('post', `/rest/bug/${caseId}/comment`, payload, false, true)
if (createData.data.error) {
throw new Meteor.Error(createData.data.error)
}
return createData.data.id
} catch (e) {
logger.error({
...errorLogParams,
error: e
})
throw new Meteor.Error(`API Error: ${e.response ? e.response.data.message : e.message}`)
}
}
}

export let publicationObj // Exported for testing purposes
let FailedComments
if (Meteor.isServer) {
Expand Down Expand Up @@ -47,7 +79,7 @@ if (Meteor.isServer) {
}

Meteor.methods({
'comments.insert' (text, caseId) {
[`${collectionName}.insert`] (text, caseId) {
check(text, String)
check(caseId, Number)

Expand Down Expand Up @@ -105,6 +137,46 @@ Meteor.methods({
throw new Meteor.Error(`API Error: ${e.response.data.message}`)
}
}
},
[`${collectionName}.insertFloorPlan`] (caseId, floorPlanPins, floorPlanId) {
check(caseId, Number)
check(floorPlanPins, Array)
const currUser = Meteor.user()
if (Meteor.isClient) {
Comments.insert({
id: Math.round(Math.random() * Number.MAX_VALUE),
creator: currUser.bugzillaCreds.login,
creation_time: (new Date()).toISOString(),
bug_id: caseId,
text: formatFloorPlanCommentText(floorPlanId, floorPlanPins)
})
}
if (Meteor.isServer) {
const { callAPI } = bugzillaApi
const resp = callAPI('get', idUrlTemplate(caseId), {}, true, true)
const caseItem = transformCaseForClient(casesFactoryOptions.dataResolver(resp.data)[0])

const unitItem = serverHelpers.getAPIUnitByName(caseItem.selectedUnit)

const commentId = createFloorPlanComment({
unitBzId: unitItem.id,
userApiKey: currUser.bugzillaCreds.apiKey,
errorLogParams: {
user: Meteor.userId(),
method: `${collectionName}.insertFloorPlan`,
args: [caseId, floorPlanPins]
},
caseId,
floorPlanPins
})

// Fetching the full comment object by the returned id from the creation operation
const commentData = callAPI(
'get', `/rest/bug/comment/${commentId}`, { api_key: currUser.bugzillaCreds.apiKey }, false, true
)
const newComment = commentData.data.comments[commentId.toString()]
publicationObj.handleAdded(newComment)
}
}
})

Expand Down
7 changes: 6 additions & 1 deletion imports/api/units.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ if (Meteor.isServer) {
getAPIUnitByName (unitName, apiKey) {
try {
const requestUrl = `/rest/product?names=${encodeURIComponent(unitName)}`
const unitResult = callAPI('get', requestUrl, { api_key: apiKey }, false, true)
let unitResult
if (apiKey) {
unitResult = callAPI('get', requestUrl, { api_key: apiKey }, false, true)
} else {
unitResult = callAPI('get', requestUrl, {}, true, true)
}
return unitResult.data.products[0]
} catch (e) {
// Pass through just to highlight this method can throw
Expand Down
15 changes: 15 additions & 0 deletions imports/state/actions/case-floor-plan-pins.actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// @flow
export const CHANGE_FLOOR_PLAN_PINS = 'change_floor_plan_pins_for_case'

type FloorPlanPins = Array<{
x: number,
y: number
}>
export function changeFloorPlanPins (caseId: number, floorPlanPins: FloorPlanPins, floorPlanId: number) {
return {
type: CHANGE_FLOOR_PLAN_PINS,
caseId,
floorPlanPins,
floorPlanId
}
}
16 changes: 16 additions & 0 deletions imports/state/epics/change-case-floor-plan-pins.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { collectionName } from '../../api/comments'

import fallibleMethodCaller from './base/fallible-method-caller'
import { genericErrorOccurred } from '../../ui/general-actions'
import { CHANGE_FLOOR_PLAN_PINS } from '../actions/case-floor-plan-pins.actions'

export const changeCaseFloorPlanPins = fallibleMethodCaller({
actionType: CHANGE_FLOOR_PLAN_PINS,
methodName: `${collectionName}.insertFloorPlan`,
argTranslator: ({ caseId, floorPlanPins, floorPlanId }) => [parseInt(caseId), floorPlanPins, floorPlanId],
actionGenerators: {
errorGen: (err, { caseId }) => genericErrorOccurred(
`Failed to update case's floor plan pins for case ${caseId} due to: "${err.error}"`
)
}
})
4 changes: 3 additions & 1 deletion imports/state/root-epic.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { editUnitMetaData } from './epics/edit-unit-meta-data'
import { uploadUnitFloorPlan } from './epics/upload-unit-floor-plan'
import { changeUnitFloorPlanUrl } from './epics/change-unit-floor-plan-url'
import { disableUnitFloorPlan } from './epics/disable-unit-floor-plan'
import { changeCaseFloorPlanPins } from './epics/change-case-floor-plan-pins'

export const rootEpic = combineEpics(
createAttachment,
Expand Down Expand Up @@ -78,5 +79,6 @@ export const rootEpic = combineEpics(
editUnitMetaData,
uploadUnitFloorPlan,
changeUnitFloorPlanUrl,
disableUnitFloorPlan
disableUnitFloorPlan,
changeCaseFloorPlanPins
)
Loading

0 comments on commit 5e6a62d

Please sign in to comment.