Skip to content

Instantly share code, notes, and snippets.

@rmoskal
Last active August 30, 2018 15:21
Show Gist options
  • Save rmoskal/6197556b6d24d5e46e5fa926e384516c to your computer and use it in GitHub Desktop.
Save rmoskal/6197556b6d24d5e46e5fa926e384516c to your computer and use it in GitHub Desktop.
The source code for the time sheet nanny POC application created by stripmall.software. You can read more about it here: https://stripmall.software
/**
* Created by rob on 5/31/16.
*
* What's it do?
*
* It listens to events emitted by the BPM engine via pubsub, then rebroadcast on an
* internal bus for finer grained consumptuin
*
* Then it tranforms them into a representation of a UI interaction that is sent to
* a client side application.
*
*/
const R = require('ramda')
const rp = require('request-promise-native')
const stripCommon = require('stripmall_gcloud_services')
module.exports = function (deps) {
const bus = deps.bus
const fb = deps.firebase
const config = deps.config
const logger = deps.logger
const oauth = stripCommon.CredentialsService(deps)
const {_setVariable, sendBPMMessage} = stripCommon.CamundaServices(deps)
const tps = require('../templates')(deps)
const messagingService = stripCommon.MessagingService(deps)
const OAuth = require('oauthio')
const {
pLog, objectToTuple, arrayToObject,
transformPropertyArray, objectFromValues
} = stripCommon.Helpers
const {
prepareUserTask
} = stripCommon.UXServices
OAuth.setOAuthdUrl(config.OAUTHD_URL)
OAuth.initialize(config.OAUTHD_PUBLIC, config.OAUTHD_PRIVATE)
bus.subscribe('#', msg => {
logger.info('>>>>>>>>', msg.topic)
})
//const preparedUserTask = prepareUserTask(deps.config.BPM_URL)
function getClient (msg) {
return oauth.getClient(OAuth, msg)
}
function commit (taskPayload) {
let userData = fb.database().ref('users/' + taskPayload.assignee)
userData.once('value', snapshot => {
if (snapshot.exists()) {
userData.child('ux').push({data: taskPayload})
} else logger.error('No user???', taskPayload)
})
return taskPayload
}
const processRequest = R.curry(
(body, payload) => {
R.pipe(
preparedUserTask,
tenplateOrNot(body),
commit
)(payload)
}
)
const tenplateOrNot = R.curry((body, payload) => body
? R.assocPath(['vars', 'body'], template(body, payload.vars), payload) : payload)
const massage = R.curry((body, taskPayload) => {
let _body = body
if (typeof body === 'function') {
_body = body(taskPayload)
}
let msg = {
notification: {
body: _body,
title: 'Fill out your timesheet!',
icon: `${deps.config.STRIPMALL_HOST}/images/logos/harvest.png`,
click_action: deps.config.STRIPMALL_HOST
}
}
messagingService.sendMessages(msg, taskPayload)
return taskPayload
})
bus.subscribe('*.Oauth.create', helpers.pipeP(
preparedUserTask,
R.assocPath(['style'], 'oauth'),
commit))
bus.subscribe('*.pause.create', processRequest())
bus.subscribe('*.fetch_projects.start', sysTask => helpers.pipeP(
getClient,
client => client.get('daily').fail((err) => console.log({err})),
R.prop('projects'),
_in => sendBPMMessage(sysTask, [
['PROJECT_LIST', 'Json', JSON.stringify(extractProjectList(_in))],
['PROJECT_TASKS', 'Json', JSON.stringify(extractProjectTaskList(_in))],
['ACTIVE_PROJECTS', 'Json', JSON.stringify([{placeholder: 'placeholder'}])]
])
)(sysTask))
bus.subscribe('*.select_projects.create', processRequest(null))
bus.subscribe('*.select_additional_project.create',
processRequest('Do you want to report times for any other projects for ${moment(WORK_DATE).format(\'dddd MMM Do\')}?')) // eslint-disable-line
bus.subscribe('*.last_thing.create', processRequest(null))
bus.subscribe('*.info_task.*', processRequest('This is my body'))
bus.subscribe('*.duplicate_process.*', processRequest(`You've already been set up for this client.\n
When the time comes, we'll ping you.`))
bus.subscribe('*.process_timesheets.start', processRequest(`You're all set!
You'll be able to fill out your timesheet at the end of the day.
The nanny will learn about your work style over time and endlessly improve in her ability to serve.`))
bus.subscribe('*.record_time.create', helpers.pipeP(
preparedUserTask,
fixTargetProject,
createTimeEntryScreen,
commit,
massage(tps.makeRecordTimeMessage)
))
function fixTargetProject (payLoad) {
let p = payLoad.vars.TARGET_PROJECT
if (typeof p !== 'string') return payLoad
payLoad.vars.TARGET_PROJECT = R.find(each => objectToTuple(each)[0] === p, payLoad.vars.PROJECT_LIST)
return _setVariable(payLoad.processInstanceId, {
name: 'TARGET_PROJECT',
value: JSON.stringify(payLoad.vars.TARGET_PROJECT),
type: 'Json'})
.then(() => { return payLoad })
}
function createTimeEntryScreen (payLoad) {
let p = objectToTuple(payLoad.vars.TARGET_PROJECT)[0]
payLoad.vars.body = tps.makeRecordTimeMessage(payLoad)
payLoad.vars.TASK_LIST = payLoad.vars.PROJECT_TASKS[p].tasks
return payLoad
}
/*********************************************************************/
bus.subscribe('*.harvest_record_time.start', sysTask => helpers.pipeP(
getClient,
client => client.post('daily/add', formatTimesheetRecord(sysTask)).fail(sendAbortMessage(sysTask)),
res => sendBPMMessage(sysTask)
)(sysTask)).catch(pLog)
function extractProjectList (_in) {
return R.map(objectFromValues('id', 'name'))(_in)
}
function extractProjectTaskList (_in) {
return R.pipe(
R.map(transformPropertyArray(objectFromValues('id', 'name'), 'tasks')),
arrayToObject('id')
)(_in)
}
function formatTimesheetRecord (_in) {
let result = {}
let p = _in._vars.TARGET_PROJECT
if (typeof _in._vars.TARGET_PROJECT !== 'string') {
p = Object.keys(_in._vars.TARGET_PROJECT)[0]
}
result.project_id = p
result.hours = parseFloat(_in._vars.hours).toFixed(2)
result.notes = _in._vars.notes
result.spent_at = _in._vars.WORK_DATE
result.task_id = _in._vars.task_id
return result
}
return {
extractProjectList,
extractProjectTaskList
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment