From de6e9a54a01dfef8a1de04ef8bc8bb2dd49c4ec7 Mon Sep 17 00:00:00 2001 From: jsyang Date: Wed, 23 Jan 2019 20:54:27 +0000 Subject: [PATCH] Fix issue with object keys not always in predictable order --- index.html | 6 +++--- readme.md | 2 +- src/client/components/AdminScreen/SpreadSheet.tsx | 5 +++-- src/client/components/AdminScreen/TableRow.tsx | 7 +++++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index 083a6a8..707e1d6 100755 --- a/index.html +++ b/index.html @@ -121,7 +121,7 @@ },{"../time":"uzoe"}],"qZPz":[function(require,module,exports) { "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getAllUsers=d,exports.getAllRooms=l,exports.getAllTasks=f,exports.undoTask=p,exports.finishTask=h,exports.createTaskAdmin=y,exports.destroyTaskAdmin=m,exports.updateTaskAdmin=g;var e=t(require("../store"));function t(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,r):{};n.get||n.set?Object.defineProperty(t,r,n):t[r]=e[r]}return t.default=e,t}function r(e){return o(e)||s(e)||n()}function n(){throw new TypeError("Invalid attempt to spread non-iterable instance")}function s(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}function o(e){if(Array.isArray(e)){for(var t=0,r=new Array(e.length);t1&&void 0!==arguments[1]?arguments[1]:{headers:{}},n=arguments.length>2?arguments[2]:void 0;if((0,e.setIsFetching)(!0),!n){var s=e.default.getState(),o=s.username,u=s.password;if(!o||!u)return Promise.reject();r.headers["x-username"]=o.toLowerCase(),r.headers["x-password"]=u}return fetch("".concat(a).concat(t),r).finally(i)},c=function(e){if(200===e.status)return e.json();throw new Error(e.message)};function d(){return u("/users",void 0,!0).then(c).then(e.setUsers)}function l(){return u("/rooms").then(c).then(e.setRooms)}function f(){return u("/tasks").then(c).then(function(e){return e.sort(function(e,t){return e.timeLastCleaned-t.timeLastCleaned})}).then(e.setTasks)}function p(e){var t=e._id,r=e.history,n={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({history:r.slice(1),userLastCleaned:r[0].userLastCleaned,timeLastCleaned:r[0].timeLastCleaned})};return u("/tasks/".concat(t),n)}function h(t){var n=t._id,s=t.history,o=t.timeLastCleaned,a=t.userLastCleaned,i=Date.now(),c={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({history:[{timeLastCleaned:o,userLastCleaned:a}].concat(r(s)),timeLastCleaned:i,userLastCleaned:e.default.getState().username})};return u("/tasks/".concat(n),c)}function y(){return u("/tasks",{method:"POST",headers:{"Content-Type":"application/json"},body:"{}"})}function m(e){var t=e._id;return u("/tasks/".concat(t),{method:"DELETE",headers:{}})}function g(e){var t=e._id,r=Object.assign({},e);delete r._id;var n={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)};return u("/tasks/".concat(t),n)} },{"../store":"NJMh"}],"YmhT":[function(require,module,exports) { -"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var e=require("preact"),t=require("preact-router"),n=require("unistore/preact"),o=l(require("./style")),r=require("./colors"),i=require("../store"),a=require("../network/db");function l(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var o=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,n):{};o.get||o.set?Object.defineProperty(t,n,o):t[n]=e[n]}return t.default=e,t}function s(e){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function u(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function c(e,t){for(var n=0;n0?(0,e.h)("div",null,t.map(function(t){var o=t.name;return(0,e.h)(v,{onClick:r.onClickUser,style:"Admin"===o?"background: ".concat(u.Color.Red0):""},o)})):"Loading users..."}}]),o}(),O=(0,t.connect)("users,username",{setUsernamePassword:n.setUsernamePassword})(h);exports.default=O; },{"preact":"qWa+","preact-router":"v/Kv","unistore/preact":"WwVf","../style":"aYnU","../../store":"NJMh","../colors":"JOjF","../../network/db":"qZPz"}],"TiW6":[function(require,module,exports) { @@ -136,9 +136,9 @@ },{}],"BXnq":[function(require,module,exports) { "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getFormattedTaskValue=void 0;var e=require("preact"),t=o(require("../../store")),n=o(require("../style"));function o(e){return e&&e.__esModule?e:{default:e}}function r(e){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function u(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var n=0;nt.toLowerCase()?-1:1};exports.byAlphabet=v;var k=function(t){function r(){var e;return i(this,r),(e=s(this,p(r).apply(this,arguments))).onClickAdd=function(){return(0,n.createTaskAdmin)().then(n.getAllTasks)},e}return d(r,e.Component),c(r,[{key:"render",value:function(){var t=this.props.data,r=Object.keys(t[0]).filter(g).sort(v);return(0,e.h)(m,null,(0,e.h)("tr",null,r.map(function(t){return(0,e.h)(h,null,t)}),(0,e.h)(h,null,"Delete")),t.sort(w).map(function(t){return(0,e.h)(o.default,{row:t,headerKeys:r})}),(0,e.h)("tr",null,(0,e.h)(b,{colSpan:r.length+1,onClick:this.onClickAdd},"Add new row")))}}]),r}();exports.default=k; },{"preact":"qWa+","../style":"aYnU","../colors":"JOjF","./TableRow":"KO+G","../../network/db":"qZPz"}],"ONHk":[function(require,module,exports) { "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var e=require("preact"),t=require("preact-router"),r=require("unistore/preact"),o=require("../../network/db"),n=require("../../store"),u=i(require("./SpreadSheet"));function i(e){return e&&e.__esModule?e:{default:e}}function c(e){return(c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function f(e,t){for(var r=0;r /room|name|description|isDeep/g.test(k); -const byRoom = (a, b) => a.room.toLowerCase() < b.room.toLowerCase() ? -1 : 1; +const byRoom = (a, b) => a.room.toLowerCase() < b.room.toLowerCase() ? -1 : 1; +export const byAlphabet = (a, b) => a.toLowerCase() > b.toLowerCase() ? -1 : 1; export default class SpreadSheet extends Component<{ data: any[] }> { onClickAdd = () => createTaskAdmin().then(getAllTasks); render() { const {data} = this.props; - const headerKeys = Object.keys(data[0]).filter(getRelevantTaskFields); + const headerKeys = Object.keys(data[0]).filter(getRelevantTaskFields).sort(byAlphabet); return ( diff --git a/src/client/components/AdminScreen/TableRow.tsx b/src/client/components/AdminScreen/TableRow.tsx index c123b49..a106318 100644 --- a/src/client/components/AdminScreen/TableRow.tsx +++ b/src/client/components/AdminScreen/TableRow.tsx @@ -4,7 +4,7 @@ import debounce from 'lodash.debounce'; import style from '../style'; import {Color} from '../colors'; import {getFormattedTaskValue} from './RoomSelect'; -import {getRelevantTaskFields} from './SpreadSheet'; +import {byAlphabet, getRelevantTaskFields} from './SpreadSheet'; import {destroyTaskAdmin, getAllTasks, updateTaskAdmin} from '../../network/db'; const TableCell: any = style('td')({ @@ -12,7 +12,10 @@ const TableCell: any = style('td')({ padding: '0.25em' }); -const getRelevantTaskFieldValues = task => Object.keys(task).filter(getRelevantTaskFields).map(key => task[key]); +const getRelevantTaskFieldValues = task => Object.keys(task) + .filter(getRelevantTaskFields) + .sort(byAlphabet) + .map(key => task[key]); export default class TableRow extends Component<{ row: any, headerKeys: string[] }> { onClickDelete = () => destroyTaskAdmin(this.props.row)