- Fixed: aggBy.total and aggBy.avg to return null when no record has a valid number value
361 lines
14 KiB
JavaScript
361 lines
14 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
const logSheet = window.logSheet = {};
|
|
const TYPE_SHEET_ENTRY = "sheet_entry";
|
|
|
|
logSheet.init = function () {
|
|
return new Promise((resolve, reject) => {
|
|
floCloudAPI.requestObjectData("logSheet").then(result => {
|
|
if (!floGlobals.appObjects.logSheet || typeof floGlobals.appObjects.logSheet !== "object")
|
|
floGlobals.appObjects.logSheet = {};
|
|
if (!floGlobals.appObjects.logSheet.personDetails || typeof floGlobals.appObjects.logSheet.personDetails !== "object")
|
|
floGlobals.appObjects.logSheet.personDetails = {};
|
|
if (!floGlobals.appObjects.logSheet.sheetList || typeof floGlobals.appObjects.logSheet.sheetList !== "object")
|
|
floGlobals.appObjects.logSheet.sheetList = {};
|
|
resolve(result)
|
|
}).catch(error => reject(error))
|
|
})
|
|
}
|
|
logSheet.addPerson = function (floID, name, otherDetails = {}) {
|
|
if (floGlobals.appObjects.logSheet.personDetails[floID])
|
|
throw ("floID already exist")
|
|
floGlobals.appObjects.logSheet.personDetails[floID] = {};
|
|
floGlobals.appObjects.logSheet.personDetails[floID].name = name;
|
|
for (d in otherDetails) {
|
|
if (d === "name" || d === "floID" || !d || !otherDetails[d])
|
|
continue;
|
|
else
|
|
floGlobals.appObjects.logSheet.personDetails[floID][d] = otherDetails[d]
|
|
}
|
|
}
|
|
|
|
logSheet.rmPerson = function (floID) {
|
|
if (!floGlobals.appObjects.logSheet.personDetails[floID])
|
|
throw ("floID not found")
|
|
delete floGlobals.appObjects.logSheet.personDetails[floID]
|
|
}
|
|
|
|
logSheet.editPerson = function (floID, details) {
|
|
if (!floGlobals.appObjects.logSheet.personDetails[floID])
|
|
throw ("floID not found")
|
|
for (d in details) {
|
|
if (details[d] === undefined || details[d] === null)
|
|
delete floGlobals.appObjects.logSheet.personDetails[floID][d];
|
|
else if (d === "floID")
|
|
continue;
|
|
else
|
|
floGlobals.appObjects.logSheet.personDetails[floID][d] = details[d];
|
|
}
|
|
}
|
|
|
|
logSheet.listPersons = function () {
|
|
return floGlobals.appObjects.logSheet.personDetails
|
|
}
|
|
|
|
logSheet.viewPerson = function (floID) {
|
|
if (!floGlobals.appObjects.logSheet.personDetails[floID])
|
|
throw ("floID not found")
|
|
return floGlobals.appObjects.logSheet.personDetails[floID]
|
|
}
|
|
|
|
logSheet.createNewSheet = function (title, description, attributes, editors = floGlobals.subAdmins) {
|
|
let sheet_id = floCrypto.tmpID;
|
|
floGlobals.appObjects.logSheet.sheetList[sheet_id] = {
|
|
title: title,
|
|
description: description,
|
|
editors: editors,
|
|
attributes: attributes
|
|
}
|
|
return sheet_id;
|
|
}
|
|
|
|
logSheet.manageSheetControl = function (sheet_id, addList, rmList) {
|
|
if (addList === null && rmList === null) {
|
|
floGlobals.appObjects.logSheet.sheetList[sheet_id].editors = null
|
|
return
|
|
}
|
|
let editorList = floGlobals.appObjects.logSheet.sheetList[sheet_id].editors || [];
|
|
if (Array.isArray(addList))
|
|
addList.forEach(e => editorList.includes(e) ? null : editorList.push(e))
|
|
if (Array.isArray(rmList))
|
|
editorList = editorList.filter(e => !rmList.includes(e));
|
|
floGlobals.appObjects.logSheet.sheetList[sheet_id].editors = editorList
|
|
}
|
|
|
|
logSheet.editSheetDescription = function (sheet_id, description) {
|
|
floGlobals.appObjects.logSheet.sheetList[sheet_id].description = description
|
|
}
|
|
|
|
logSheet.listSheets = function () {
|
|
return floGlobals.appObjects.logSheet.sheetList
|
|
}
|
|
|
|
logSheet.commitUpdates = function () {
|
|
return new Promise((resolve, reject) => {
|
|
if (!floGlobals.subAdmins.includes(floDapps.user.id))
|
|
reject("Access Denied! only subAdmins can commit")
|
|
floCloudAPI.updateObjectData("logSheet")
|
|
.then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
logSheet.enterLog = function (sheet_id, floID, log) {
|
|
return new Promise((resolve, reject) => {
|
|
if (floGlobals.appObjects.logSheet.sheetList[sheet_id].editors) {
|
|
// private sheet constraints
|
|
if (!floGlobals.appObjects.logSheet.sheetList[sheet_id].editors.includes(floDapps.user.id))
|
|
return reject("Only editors can update logs");
|
|
/*else if (!(floID in floGlobals.appObjects.logSheet.personDetails))
|
|
return reject("floID not found");*/
|
|
} else {
|
|
//public sheet constraint
|
|
if (!floGlobals.subAdmins.includes(floDapps.user.id) && floID != floDapps.user.id)
|
|
return reject("Public authorized to log their own floID only");
|
|
}
|
|
floCloudAPI.sendGeneralData({
|
|
floID,
|
|
log
|
|
}, TYPE_SHEET_ENTRY, {
|
|
receiverID: sheet_id
|
|
}).then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
logSheet.gradeLog = function (sheet_id, vc, grade) {
|
|
return new Promise((resolve, reject) => {
|
|
//reject if user is not subAdmin or editor
|
|
if (!floGlobals.subAdmins.includes(floDapps.user.id) && !floGlobals.trustedIDs.includes(floDapps.user.id))
|
|
return reject("Only subAdmins/trustedIDs can grade logs")
|
|
|
|
let log = floGlobals.generalDataset(TYPE_SHEET_ENTRY, {
|
|
receiverID: sheet_id
|
|
})[vc];
|
|
if (!log)
|
|
return reject("Log not found");
|
|
//else if (log.senderID === floDapps.user.id)
|
|
// return reject("Cannot grade own log")
|
|
|
|
floCloudAPI.tagApplicationData(vc, grade, {
|
|
receiverID: sheet_id
|
|
}).then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
})
|
|
}
|
|
|
|
logSheet.refreshLogs = function (sheet_id) {
|
|
return new Promise((resolve, reject) => {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
reject("Sheet not found")
|
|
else {
|
|
floCloudAPI.requestGeneralData(TYPE_SHEET_ENTRY, {
|
|
senderIDs: floGlobals.appObjects.logSheet.sheetList[sheet_id].editors,
|
|
receiverID: sheet_id
|
|
}).then(result => resolve(result))
|
|
.catch(error => reject(error))
|
|
}
|
|
})
|
|
}
|
|
|
|
logSheet.viewLogs = function (sheet_id) {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
throw ("Sheet not found")
|
|
let sheet = [],
|
|
vcIndex = {},
|
|
entries = floGlobals.generalDataset(TYPE_SHEET_ENTRY, {
|
|
receiverID: sheet_id
|
|
}),
|
|
editors = floGlobals.appObjects.logSheet.sheetList[sheet_id].editors;
|
|
for (let vc in entries) {
|
|
let l = entries[vc];
|
|
if ((!editors && (floGlobals.subAdmins.includes(l.senderID) || l.senderID === l.message.floID)) || editors.includes(l.senderID)) {
|
|
if (floCrypto.validateAddr(l.message.floID)) {
|
|
let vc = l.vectorClock
|
|
sheet.push({
|
|
vc: vc,
|
|
floID: l.message.floID,
|
|
log: l.message.log,
|
|
grade: l.tag
|
|
})
|
|
vcIndex[vc] = sheet.length - 1;
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
id: sheet_id,
|
|
title: floGlobals.appObjects.logSheet.sheetList[sheet_id].title,
|
|
description: floGlobals.appObjects.logSheet.sheetList[sheet_id].description,
|
|
editors: floGlobals.appObjects.logSheet.sheetList[sheet_id].editors,
|
|
attributes: floGlobals.appObjects.logSheet.sheetList[sheet_id].attributes,
|
|
sheet: sheet
|
|
}
|
|
}
|
|
|
|
const _isNaN = value => isNaN(value) || value === '';
|
|
|
|
const groupBy = logSheet.groupBy = {};
|
|
groupBy.count = function (sheet_id, sheet) {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
throw ("Sheet not found")
|
|
let group = {};
|
|
sheet.forEach(l => {
|
|
if (!(l.floID in group))
|
|
group[l.floID] = 1
|
|
else
|
|
group[l.floID] += 1
|
|
})
|
|
return group;
|
|
}
|
|
|
|
groupBy.total = function (sheet_id, sheet, attribute) {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
throw ("Sheet not found")
|
|
let group = {};
|
|
let attrubuteIndex = floGlobals.appObjects.logSheet.sheetList[sheet_id].attributes.indexOf(attribute)
|
|
sheet.forEach(l => {
|
|
if (!_isNaN(l.log[attrubuteIndex])) {
|
|
let value = parseFloat(l.log[attrubuteIndex])
|
|
if (!(l.floID in group))
|
|
group[l.floID] = value
|
|
else
|
|
group[l.floID] += value
|
|
}
|
|
})
|
|
return group;
|
|
}
|
|
|
|
groupBy.avg = function (sheet_id, sheet, attribute) {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
throw ("Sheet not found")
|
|
let group = {};
|
|
let attrubuteIndex = floGlobals.appObjects.logSheet.sheetList[sheet_id].attributes.indexOf(attribute)
|
|
sheet.forEach(l => {
|
|
if (!_isNaN(l.log[attrubuteIndex])) {
|
|
let value = parseFloat(l.log[attrubuteIndex])
|
|
if (!(l.floID in group))
|
|
group[l.floID] = {
|
|
total: value,
|
|
count: 1
|
|
}
|
|
else {
|
|
group[l.floID].total += value
|
|
group[l.floID].count += 1
|
|
}
|
|
}
|
|
})
|
|
for (const floID in group)
|
|
group[floID] = group[floID].total / group[floID].count
|
|
return group;
|
|
}
|
|
|
|
groupBy.min = function (sheet_id, sheet, attribute) {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
throw ("Sheet not found")
|
|
let group = {};
|
|
let attrubuteIndex = floGlobals.appObjects.logSheet.sheetList[sheet_id].attributes.indexOf(attribute)
|
|
sheet.forEach(l => {
|
|
if (!_isNaN(l.log[attrubuteIndex])) {
|
|
let value = parseFloat(l.log[attrubuteIndex])
|
|
if (!(l.floID in group))
|
|
group[l.floID] = value
|
|
else if (value < group[l.floID])
|
|
group[l.floID] = value
|
|
}
|
|
})
|
|
return group;
|
|
}
|
|
|
|
groupBy.max = function (sheet_id, sheet, attribute) {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
throw ("Sheet not found")
|
|
let group = {};
|
|
let attrubuteIndex = floGlobals.appObjects.logSheet.sheetList[sheet_id].attributes.indexOf(attribute)
|
|
sheet.forEach(l => {
|
|
if (!_isNaN(l.log[attrubuteIndex])) {
|
|
let value = parseFloat(l.log[attrubuteIndex])
|
|
if (!(l.floID in group))
|
|
group[l.floID] = value
|
|
else if (value > group[l.floID])
|
|
group[l.floID] = value
|
|
}
|
|
})
|
|
return group;
|
|
}
|
|
|
|
const aggBy = logSheet.aggBy = {};
|
|
aggBy.count = function (sheet_id, sheet) {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
throw ("Sheet not found")
|
|
let result = sheet.length;
|
|
return result;
|
|
}
|
|
|
|
aggBy.total = function (sheet_id, sheet, attribute) {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
throw ("Sheet not found")
|
|
let result = 0, count = 0;
|
|
let attrubuteIndex = floGlobals.appObjects.logSheet.sheetList[sheet_id].attributes.indexOf(attribute)
|
|
sheet.forEach(l => {
|
|
if (!_isNaN(l.log[attrubuteIndex])) {
|
|
let value = parseFloat(l.log[attrubuteIndex])
|
|
result += value;
|
|
count++;
|
|
}
|
|
});
|
|
|
|
if (count == 0)
|
|
result = null;
|
|
|
|
return result;
|
|
}
|
|
|
|
aggBy.avg = function (sheet_id, sheet, attribute) {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
throw ("Sheet not found")
|
|
let result = 0, count = 0;
|
|
let attrubuteIndex = floGlobals.appObjects.logSheet.sheetList[sheet_id].attributes.indexOf(attribute)
|
|
sheet.forEach(l => {
|
|
if (!_isNaN(l.log[attrubuteIndex])) {
|
|
let value = parseFloat(l.log[attrubuteIndex])
|
|
result += value;
|
|
count++;
|
|
}
|
|
})
|
|
if (count == 0)
|
|
result = null;
|
|
else
|
|
result = result / count;
|
|
return result;
|
|
}
|
|
|
|
aggBy.min = function (sheet_id, sheet, attribute) {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
throw ("Sheet not found")
|
|
let result = null;
|
|
let attrubuteIndex = floGlobals.appObjects.logSheet.sheetList[sheet_id].attributes.indexOf(attribute)
|
|
sheet.forEach(l => {
|
|
if (!_isNaN(l.log[attrubuteIndex])) {
|
|
let value = parseFloat(l.log[attrubuteIndex])
|
|
if (result === null || value < result)
|
|
result = value;
|
|
}
|
|
})
|
|
return result;
|
|
}
|
|
|
|
aggBy.max = function (sheet_id, sheet, attribute) {
|
|
if (!(sheet_id in floGlobals.appObjects.logSheet.sheetList))
|
|
throw ("Sheet not found")
|
|
let result = null;
|
|
let attrubuteIndex = floGlobals.appObjects.logSheet.sheetList[sheet_id].attributes.indexOf(attribute)
|
|
sheet.forEach(l => {
|
|
if (!_isNaN(l.log[attrubuteIndex])) {
|
|
let value = parseFloat(l.log[attrubuteIndex])
|
|
if (result === null || value > result)
|
|
result = value;
|
|
}
|
|
})
|
|
return result;
|
|
}
|
|
})(); |