importPackage(Packages.de.elo.ix.client); //@include lib_Class.js //@include lib_sol.common.Config.js //@include lib_sol.common.SordUtils.js //@include lib_sol.common.DateUtils.js //@include lib_sol.common.ix.ServiceBase.js //@include lib_sol.checklist.Utils.js var logger = sol.create("sol.Logger", { scope: "sol.checklist.ix.services.Checklist" }); /** * Provides service functions for the checklist module. * * The element used as checklist, has to define a `SOL_TYPE` field with the value from the checklist configuration defined in `checklist.solObjectType`. * * # Model * The model of the checklist is stored in the description of a sord as JSON string. * * A checklist contains an `items` property which holds an array of checklist items. * * Each checklist item has the following form: * * { * id: 23, * text: "a label", * notes: "a description", // optional * checked: true, * checkDate: "20160824113000", // only set, if checked=true * checkUser: { id: "7", name: "mmustermann" }, // only set, if checked=true * marked: false * } * * # Results * All function (except {@link #RF_sol_checklist_service_ReadChecklist ReadChecklist}) return a standardized response format: * * { * status: "SUCCESS" // possible values: SUCCESS|FAILURE|RECURRENCE * item: {...} // optional, e.g. added, removed, updated item * error: "some.error.code" // only if 'status' is 'FAILURE' * } * * ## Errorcodes * * |Code|Description| * |:------|:------| * |checklist.save|Error while saving checklist| * |checklist.item.invalid|| * |checklist.item.notFound|Item not found| * |checklist.item.notMoved|Item not moved| * |checklist.missing.itemId|Missing property 'itemId'| * |checklist.missing.check|Missing property 'check'| * |checklist.missing.mark|Missing property 'mark'| * |checklist.missing.item.id|Edit item has not defined an 'id'| * |checklist.missing.fromIdx|Missing property 'fromIdx'| * |checklist.missing.toIdx|Missing property 'toIdx'| * * # Usage * * ## Edit checklist * * sol.common.IxUtils.execute("RF_sol_checklist_service_EditChecklist", { objId: "4711", checklistname: "checklist4711", checklistdesc: "Water cologne" }); * * // result // * { * status: "SUCCESS" * } * * ## Read checklist * * sol.common.IxUtils.execute("RF_sol_checklist_service_ReadChecklist", { objId: "4711" }); * * // result // * { * items: [ ... ], * writable: true * } * * ## Move an checklist item * * sol.common.IxUtils.execute("RF_sol_checklist_service_MoveItem", { * objId: "4711", * fromIdx: 2, * toIdx: 4 * }); * * // result (the added item) // * { * status: "SUCCESS" * } * * ## Add checklist item * * sol.common.IxUtils.execute("RF_sol_checklist_service_AddItem", { * objId: "4711", * item: { * text: "a label", * notes: "optional description" * } * }); * * // result (the added item) // * { * status: "SUCCESS", * item: { * id: 23, * text: "a label", * notes: "optional description", * checked: false, * marked: false * } * } * * ## Remove checklist item * * sol.common.IxUtils.execute("RF_sol_checklist_service_RemoveItem", { * objId: "4711", * itemId: 23 * }); * * // result (including the removed item) // * { * status: "SUCCESS", * item: { * id: 23, * text: "a label", * notes: "optional description", * checked: false, * marked: false * } * } * * ## Edit checklist item * Only `text` and `notes` can be edited this way. * * sol.common.IxUtils.execute("RF_sol_checklist_service_EditItem", { * objId: "4711", * item: { * id: 23, * text: "an edited label", * notes: "edit" * } * }); * * // result // * { * status: "SUCCESS", * item: { * id: 23, * text: "an edited label", * notes: "edit", * checked: false, * marked: false * } * } * * ## Check checklist item * Check an item: * * sol.common.IxUtils.execute("RF_sol_checklist_service_CheckItem", { * objId: "4711", * itemId: 23, * check: true * }); * * // result // * { * status: "SUCCESS", * item: { * id: 23, * text: "a label", * notes: "optional description", * checked: true, * checkDate: "20160824113000", * checkUser: { id: "7", name: "mmustermann" }, * marked: false * } * } * * Uncheck an item: * * sol.common.IxUtils.execute("RF_sol_checklist_service_CheckItem", { * objId: "4711", * itemId: 23, * check: false * }); * * // result // * { * status: "SUCCESS", * item: { * id: 23, * text: "a label", * notes: "optional description", * checked: false, * marked: false * } * } * * Uncheck again: * * sol.common.IxUtils.execute("RF_sol_checklist_service_CheckItem", { * objId: "4711", * itemId: 23, * check: false * }); * * // result, item was not altered, but will be returned anyway (it might have been altered by another user) // * { * status: "RECURRENCE", * item: { * id: 23, * text: "a label", * notes: "optional description", * checked: false, * marked: false * } * } * * ## Mark checklist item * Mark an item: * * sol.common.IxUtils.execute("RF_sol_checklist_service_MarkItem", { * objId: "4711", * itemId: 23, * mark: true * }); * * Unmark an item: * * sol.common.IxUtils.execute("RF_sol_checklist_service_MarkItem", { * objId: "4711", * itemId: 23, * mark: false * }); * * Results equivalent to checking and unchecking. * * @author PZ, ELO Digital Office GmbH * @version 1.00.000 * * @eloix * @requires moment.js * @requires sol.common.Config * @requires sol.common.SordUtils * @requires sol.common.DateUtils * @requires sol.common.ix.RfUtils * @requires sol.common.ix.ServiceBase */ sol.define("sol.checklist.ix.services.Checklist", { extend: "sol.common.ix.ServiceBase", requiredConfig: ["objId"], /** * @private * @property {de.elo.ix.client.SordZ} */ sordZ: SordC.mbAllIndex, /** * @private * @property {Object} */ STATUS: { SUCCESS: "SUCCESS", FAILURE: "FAILURE", RECURRENCE: "RECURRENCE" }, initialize: function (config) { var me = this; me.$super("sol.common.ix.ServiceBase", "initialize", [config]); me.sord = ixConnect.ix().checkoutSord(me.objId, me.sordZ, LockC.NO); if (!sol.checklist.Utils.isChecklist(me.sord)) { throw "selected element is not a checklist"; } }, /** * Loads the checklist object from the description of a Sord. * @return {Object} The checklist */ readChecklist: function () { var me = this, desc, checklist; try { desc = String(me.sord.desc); if (desc && (desc.length > 0)) { checklist = JSON.parse(desc); } } catch (ex) { me.logger.warn("error parsing checklist from sord description", ex); } if (!checklist || !checklist.items) { checklist = { items: [] }; } checklist.writable = me.hasWriteAccess(me.sord); return checklist; }, /** * Moves an item. * @return {Object} The checklist */ moveItem: function () { var me = this, checklist, moved, success, status, error; if (typeof me.fromIdx === "undefined") { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.fromIdx"); } if (typeof me.toIdx === "undefined") { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.toIdx"); } checklist = me.readChecklist(); moved = me.moveItemInArray(checklist.items, me.fromIdx, me.toIdx); if (!moved) { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.item.notMoved"); } success = me.saveChecklist(checklist); status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE; error = (!success) ? "checklist.save" : null; return me.buildResponse(status, null, error); }, /** * Adds an item to a checklist. * @return {Object} */ addItem: function () { var me = this, checklist, newItem, success, status, error; if (!me.validateItem(me.item)) { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.item.invalid"); } checklist = me.readChecklist(); newItem = { id: sol.checklist.Utils.getNextId(checklist), text: me.item.text, checked: false, marked: false }; if (me.item.notes) { newItem.notes = me.item.notes; } checklist.items.push(newItem); success = me.saveChecklist(checklist); status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE; error = (!success) ? "checklist.save" : null; return me.buildResponse(status, newItem, error); }, /** * Removes an item from a checklist. * @return {Object} */ removeItem: function () { var me = this, checklist, idx, removedItems, success, status, error, removedItem; if (typeof me.itemId === "undefined") { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.itemId"); } checklist = me.readChecklist(); idx = me.getItemIndex(checklist, me.itemId); if (typeof idx !== "undefined") { removedItems = checklist.items.splice(idx, 1); success = me.saveChecklist(checklist); status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE; error = (!success) ? "checklist.save" : null; } else { status = me.STATUS.FAILURE; error = "checklist.item.notFound"; } removedItem = (success && removedItems && (removedItems.length === 1)) ? removedItems[0] : null; return me.buildResponse(status, removedItem, error); }, /** * Edits an item of a checklist. * @return {Boolean} */ editItem: function () { var me = this, checklist, idx, editedItem, success, status, error; if (!me.validateItem(me.item)) { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.item.invalid"); } if (typeof me.item.id === "undefined") { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.item.id"); } checklist = me.readChecklist(); idx = me.getItemIndex(checklist, me.item.id); if (typeof idx !== "undefined") { me.mergeItem(checklist.items[idx], me.item); editedItem = checklist.items[idx]; success = me.saveChecklist(checklist); status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE; error = (!success) ? "checklist.save" : null; } else { status = me.STATUS.FAILURE; error = "checklist.item.notFound"; } return me.buildResponse(status, editedItem, error); }, /** * Marks an item as checked/unchecked and handles the `checkUser` and `checkDate` attributes. * @return {Object} */ checkItem: function () { var me = this, checklist, idx, checkedItem, dirty, success, status, error; if (typeof me.itemId === "undefined") { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.itemId"); } if (typeof me.check === "undefined") { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.check"); } if (!me.user) { me.user = ixConnect.loginResult.user; me.logger.debug(["use user from ixConnect: name={0}, id={1}", me.user.name, me.user.id]); } checklist = me.readChecklist(); idx = me.getItemIndex(checklist, me.itemId); if (typeof idx !== "undefined") { checkedItem = checklist.items[idx]; dirty = me.checkItemObject(checklist.items[idx], me.check, me.user); if (dirty) { success = me.saveChecklist(checklist); status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE; error = (!success) ? "checklist.save" : null; } else { status = me.STATUS.RECURRENCE; } } else { status = me.STATUS.FAILURE; error = "checklist.item.notFound"; } return me.buildResponse(status, checkedItem, error); }, /** * Marks an item as marked. * @return {Object} */ markItem: function () { var me = this, checklist, idx, markedItem, success, status, error; if (typeof me.itemId === "undefined") { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.itemId"); } if (typeof me.mark === "undefined") { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.mark"); } checklist = me.readChecklist(); idx = me.getItemIndex(checklist, me.itemId); if (typeof idx !== "undefined") { markedItem = checklist.items[idx]; if (checklist.items[idx].marked !== me.mark) { checklist.items[idx].marked = me.mark; success = me.saveChecklist(checklist); status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE; error = (!success) ? "checklist.save" : null; } else { status = me.STATUS.RECURRENCE; } } else { status = me.STATUS.FAILURE; error = "checklist.item.notFound"; } return me.buildResponse(status, markedItem, error); }, /** * @private * Checks, if a sord was checked out with write access. * @param {de.elo.ix.client.Sord} sord * @return {Boolean} */ hasWriteAccess: function (sord) { var flags, hasWriteAccess; flags = sord.access; hasWriteAccess = (flags & CONST.ACCESS.LUR_WRITE) === CONST.ACCESS.LUR_WRITE; return hasWriteAccess; }, /** * @private * Checks if an item is valid. * @param {Object} item * @return {Boolean} */ validateItem: function (item) { if (!item || !item.text) { return false; } return true; }, /** * @private * Saves a checklist * @param {Object} checklist * @return {Boolean} */ saveChecklist: function (checklist) { var me = this, success = false, desc; try { checklist.writable = undefined; desc = JSON.stringify(checklist, null, 2); me.sord.desc = desc; ixConnect.ix().checkinSord(me.sord, me.sordZ, LockC.NO); success = true; } catch (ex) { me.logger.warn("error saving checklist to sord description", ex); } return success; }, /** * @private * Edits a checklist * @param {Object} checklist * @return {Boolean} */ editChecklist: function () { var me = this, checklist, success, status, error; if (typeof me.checklistname === "undefined") { return me.buildResponse(me.STATUS.FAILURE, null, "checklist.missing.name"); } checklist = me.readChecklist(); if (me.checklistname) { me.sord.name = me.checklistname; } if (me.checklistdesc) { sol.common.SordUtils.setObjKeyValue(me.sord, "CHECKLIST_DESC", me.checklistdesc); } success = me.saveChecklist(checklist); status = (success) ? me.STATUS.SUCCESS : me.STATUS.FAILURE; error = (!success) ? "checklist.save" : null; return me.buildResponse(status, null, error); }, /** * @private * Retrieves the index of an item by the ID. * @param {Object} checklist * @param {Number} id * @return {Number} */ getItemIndex: function (checklist, id) { var i, idx; for (i = 0; i < checklist.items.length; i++) { if (checklist.items[i].id === id) { idx = i; break; } } return idx; }, /** * @private * Merges an item to another. * @param {Object} dst Destination item * @param {Object} src Source item */ mergeItem: function (dst, src) { if (!dst || !src) { return; } if (src.text) { dst.text = src.text; } if (!sol.common.StringUtils.isBlank(src.notes)) { dst.notes = src.notes; } else { dst.notes = undefined; } }, /** * @private * Moves an element inside an array from one position to another. * @param {Object[]} items * @param {Number} fromIdx * @param {Number} toIdx * @return {Boolean} */ moveItemInArray: function (items, fromIdx, toIdx) { if ((fromIdx < 0) || (fromIdx >= items.length)) { return false; } if (toIdx < 0) { toIdx = 0; } if (toIdx >= items.length) { toIdx = items.length - 1; } items.splice(toIdx, 0, items.splice(fromIdx, 1)[0]); return true; }, /** * @private * Checks, or unchecks an item. * @param {Object} item * @param {Boolean} check * @param {de.elo.ix.client.UserInfo} user (optional) only required if `check` is `true` * @return {Boolean} */ checkItemObject: function (item, check, user) { var me = this, edited = false; if ((check === true) && (item.checked !== true)) { item.checked = true; item.checkDate = sol.common.DateUtils.dateToIso(new Date()); item.checkUser = me.createUser(user); edited = true; } else if ((check === false) && (item.checked === true)) { item.checked = false; item.checkDate = undefined; item.checkUser = undefined; edited = true; } return edited; }, /** * @private * Creates a user representation. * @param {de.elo.ix.client.UserInfo} user * @return {Object} A user representation * @return {String} return.id The user id * @return {String} return.name The ELO user name */ createUser: function (user) { var userObj; if (user) { userObj = { id: String(user.id), name: String(user.name) }; } return userObj; }, /** * @private * Builds the response object. * @param {String} status * @param {Object} item (optional) * @param {String} error (optional) * @return {Object} */ buildResponse: function (status, item, error) { var response = { status: status }; if (item) { response.item = item; } if (error) { response.error = error; } return response; } }); /** * @member sol.checklist.ix.services.Checklist * @method RF_sol_checklist_service_ReadChecklist * @static * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName */ function RF_sol_checklist_service_ReadChecklist(ec, args) { var rfUtils = sol.common.ix.RfUtils, params, service, result; logger.enter("RF_sol_checklist_service_ReadChecklist", args); params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId"); service = sol.create("sol.checklist.ix.services.Checklist", params); result = rfUtils.stringify(service.readChecklist()); logger.exit("RF_sol_checklist_service_ReadChecklist", result); return result; } /** * @member sol.checklist.ix.services.Checklist * @method RF_sol_checklist_service_EditChecklist * @static * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName */ function RF_sol_checklist_service_EditChecklist(ec, args) { var rfUtils = sol.common.ix.RfUtils, params, service, result; logger.enter("RF_sol_checklist_service_EditChecklist", args); params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId"); service = sol.create("sol.checklist.ix.services.Checklist", params); result = rfUtils.stringify(service.editChecklist()); logger.exit("RF_sol_checklist_service_EditChecklist", result); return result; } /** * @member sol.checklist.ix.services.Checklist * @method RF_sol_checklist_service_MoveItem * @static * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName */ function RF_sol_checklist_service_MoveItem(ec, args) { var rfUtils = sol.common.ix.RfUtils, params, service, result; logger.enter("RF_sol_checklist_service_MoveItem", args); params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId"); service = sol.create("sol.checklist.ix.services.Checklist", params); result = rfUtils.stringify(service.moveItem()); logger.exit("RF_sol_checklist_service_MoveItem", result); return result; } /** * @member sol.checklist.ix.services.Checklist * @method RF_sol_checklist_service_AddItem * @static * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName */ function RF_sol_checklist_service_AddItem(ec, args) { var rfUtils = sol.common.ix.RfUtils, params, service, result; logger.enter("RF_sol_checklist_service_AddItem", args); params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId"); service = sol.create("sol.checklist.ix.services.Checklist", params); result = rfUtils.stringify(service.addItem()); logger.exit("RF_sol_checklist_service_AddItem", result); return result; } /** * @member sol.checklist.ix.services.Checklist * @method RF_sol_checklist_service_RemoveItem * @static * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName */ function RF_sol_checklist_service_RemoveItem(ec, args) { var rfUtils = sol.common.ix.RfUtils, params, service, result; logger.enter("RF_sol_checklist_service_RemoveItem", args); params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId"); service = sol.create("sol.checklist.ix.services.Checklist", params); result = rfUtils.stringify(service.removeItem()); logger.exit("RF_sol_checklist_service_RemoveItem", result); return result; } /** * @member sol.checklist.ix.services.Checklist * @method RF_sol_checklist_service_EditItem * @static * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName */ function RF_sol_checklist_service_EditItem(ec, args) { var rfUtils = sol.common.ix.RfUtils, params, service, result; logger.enter("RF_sol_checklist_service_EditItem", args); params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId"); service = sol.create("sol.checklist.ix.services.Checklist", params); result = rfUtils.stringify(service.editItem()); logger.exit("RF_sol_checklist_service_EditItem", result); return result; } /** * @member sol.checklist.ix.services.Checklist * @method RF_sol_checklist_service_CheckItem * @static * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName */ function RF_sol_checklist_service_CheckItem(ec, args) { var rfUtils = sol.common.ix.RfUtils, params, service, result; logger.enter("RF_sol_checklist_service_CheckItem", args); params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId"); params.user = ec.user; service = sol.create("sol.checklist.ix.services.Checklist", params); result = rfUtils.stringify(service.checkItem()); logger.exit("RF_sol_checklist_service_CheckItem", result); return result; } /** * @member sol.checklist.ix.services.Checklist * @method RF_sol_checklist_service_MarkItem * @static * @inheritdoc sol.common.ix.ServiceBase#RF_ServiceBaseName */ function RF_sol_checklist_service_MarkItem(ec, args) { var rfUtils = sol.common.ix.RfUtils, params, service, result; logger.enter("RF_sol_checklist_service_MarkItem", args); params = rfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId"); service = sol.create("sol.checklist.ix.services.Checklist", params); result = rfUtils.stringify(service.markItem()); logger.exit("RF_sol_checklist_service_MarkItem", result); return result; }