From 7a63b52e0147fa01c7fb08f685c8aec8be16c656 Mon Sep 17 00:00:00 2001 From: Rodrigo Quelca Date: Tue, 27 Jul 2021 20:38:26 +0000 Subject: [PATCH] PMCORE-3067: UI - List Sorting feature --- package-lock.json | 26 +++++++ package.json | 3 + resources/assets/js/api/Config.js | 24 +++++++ resources/assets/js/api/Services.js | 3 +- resources/assets/js/api/index.js | 5 +- .../vuetable/extends/VtSortControl.vue | 17 +++++ resources/assets/js/home/Home.vue | 69 ++++++++++++++++++- resources/assets/js/home/MyCases/MyCases.vue | 39 +++++++++-- resources/assets/js/home/main.js | 7 +- workflow/engine/methods/cases/viena_init.php | 3 +- 10 files changed, 184 insertions(+), 12 deletions(-) create mode 100644 resources/assets/js/api/Config.js create mode 100644 resources/assets/js/components/vuetable/extends/VtSortControl.vue diff --git a/package-lock.json b/package-lock.json index 4236311cd..a60d22b8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,12 +11,38 @@ "regenerator-runtime": "^0.13.2" } }, + "@fortawesome/fontawesome-common-types": { + "version": "0.2.35", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.35.tgz", + "integrity": "sha512-IHUfxSEDS9dDGqYwIW7wTN6tn/O8E0n5PcAHz9cAaBoZw6UpG20IG/YM3NNLaGPwPqgjBAFjIURzqoQs3rrtuw==" + }, "@fortawesome/fontawesome-free": { "version": "5.15.1", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.1.tgz", "integrity": "sha512-OEdH7SyC1suTdhBGW91/zBfR6qaIhThbcN8PUXtXilY4GYnSBbVqOntdHbC1vXwsDnX0Qix2m2+DSU1J51ybOQ==", "dev": true }, + "@fortawesome/fontawesome-svg-core": { + "version": "1.2.35", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.35.tgz", + "integrity": "sha512-uLEXifXIL7hnh2sNZQrIJWNol7cTVIzwI+4qcBIq9QWaZqUblm0IDrtSqbNg+3SQf8SMGHkiSigD++rHmCHjBg==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.35" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "5.15.3", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.3.tgz", + "integrity": "sha512-XPeeu1IlGYqz4VWGRAT5ukNMd4VHUEEJ7ysZ7pSSgaEtNvSo+FLurybGJVmiqkQdK50OkSja2bfZXOeyMGRD8Q==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.35" + } + }, + "@fortawesome/vue-fontawesome": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-2.0.2.tgz", + "integrity": "sha512-ecpKSBUWXsxRJVi/dbOds4tkKwEcBQ1JSDZFzE2jTFpF8xIh3OgTX8POIor6bOltjibr3cdEyvnDjecMwUmxhQ==" + }, "@nuxt/opencollective": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.3.2.tgz", diff --git a/package.json b/package.json index fc913723a..1eb77f31e 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,9 @@ "vue-template-compiler": "^2.6.10" }, "dependencies": { + "@fortawesome/fontawesome-svg-core": "^1.2.35", + "@fortawesome/free-solid-svg-icons": "^5.15.3", + "@fortawesome/vue-fontawesome": "^2.0.2", "axios": "^0.15.3", "bootstrap": "^4.5.3", "bootstrap-colorpicker": "^3.0.3", diff --git a/resources/assets/js/api/Config.js b/resources/assets/js/api/Config.js new file mode 100644 index 000000000..100bfea92 --- /dev/null +++ b/resources/assets/js/api/Config.js @@ -0,0 +1,24 @@ +import ApiInstance from "./Api.js"; +import Services from "./Services"; +let Api = new ApiInstance( Services ); + +export let config = { + get(data) { + return Api.get({ + service: "CONFIG", + params: data + }); + }, + post(data) { + return Api.post({ + service: "CONFIG", + data: data + }); + }, + put(data) { + return Api.put({ + service: "CONFIG", + data: data + }); + }, +}; diff --git a/resources/assets/js/api/Services.js b/resources/assets/js/api/Services.js index 95bcdcedb..1f9f6737f 100644 --- a/resources/assets/js/api/Services.js +++ b/resources/assets/js/api/Services.js @@ -67,5 +67,6 @@ USERS: "/home/users", TASKS: "/home/tasks", CATEGORIES: "/home/categories", - DEBUG_STATUS: "/home/process-debug-status?processUid={prj_uid}" + DEBUG_STATUS: "/home/process-debug-status?processUid={prj_uid}", + CONFIG: "/home/config" }; \ No newline at end of file diff --git a/resources/assets/js/api/index.js b/resources/assets/js/api/index.js index c4d2b47d6..d6a313f69 100644 --- a/resources/assets/js/api/index.js +++ b/resources/assets/js/api/index.js @@ -1,7 +1,7 @@ import { menu } from "./Menu"; import { cases, casesHeader } from "./Cases"; - +import { config } from "./Config"; import { caseNotes } from "./CaseNotes"; import { process } from "./Process"; import { filters } from "./Filters"; @@ -13,5 +13,6 @@ export default { casesHeader, process, caseNotes, - filters + filters, + config }; \ No newline at end of file diff --git a/resources/assets/js/components/vuetable/extends/VtSortControl.vue b/resources/assets/js/components/vuetable/extends/VtSortControl.vue new file mode 100644 index 000000000..ad6f47149 --- /dev/null +++ b/resources/assets/js/components/vuetable/extends/VtSortControl.vue @@ -0,0 +1,17 @@ + + \ No newline at end of file diff --git a/resources/assets/js/home/Home.vue b/resources/assets/js/home/Home.vue index ce8ab8d90..cb9fc4845 100644 --- a/resources/assets/js/home/Home.vue +++ b/resources/assets/js/home/Home.vue @@ -25,6 +25,7 @@ :pageUri="pageUri" :name="pageName" :defaultOption="defaultOption" + :settings="config[page]" @onSubmitFilter="onSubmitFilter" @onRemoveFilter="onRemoveFilter" @onUpdatePage="onUpdatePage" @@ -32,7 +33,8 @@ @onLastPage="onLastPage" @onUpdateFilters="onUpdateFilters" @cleanDefaultOption="cleanDefaultOption" - > + @updateUserSettings="updateUserSettings" + > @@ -85,6 +87,11 @@ export default { pageName: null, pageUri: null, filters: null, + config: {}, + configParams: { + id: window.config.userId || "1", + name: "home" + }, menuMap: { CASES_MY_CASES: "MyCases", CASES_SENT: "MyCases", @@ -103,6 +110,7 @@ export default { mounted() { this.onResize(); this.getMenu(); + this.getUserSettings(); this.listenerIframe(); window.setInterval( this.setCounter, @@ -148,6 +156,62 @@ export default { console.error(e); }); }, + /** + * Gets the user config + */ + getUserSettings() { + api.config + .get(this.configParams) + .then((response) => { + if (response.data) { + this.config = response.data; + } else { + this.createUserSettings(); + } + }) + .catch((e) => { + console.error(e); + }); + }, + /** + * Creates the user config service + */ + createUserSettings() { + api.config + .post({ + ...this.configParams, + ...{setting: '{}'} + }) + .then((response) => { + if (response.data) { + this.config = response.data; + } + }) + .catch((e) => { + console.error(e); + }); + }, + /** + * Update the user config service + */ + updateUserSettings(prop, data) { + if (!this.config.setting[this.page]) { + this.config.setting[this.page] = {}; + } + this.config.setting[this.page][prop] = data; + api.config + .put(this.config) + .then((response) => { + if (response.data) { + // this.settings = response.data; + console.log("Udated") + console.log(this.config); + } + }) + .catch((e) => { + console.error(e); + }); + }, /** * Set default cases menu option */ @@ -335,7 +399,8 @@ export default { }, onUpdateFilters(filters) { this.filters = filters; - } + }, + } }; diff --git a/resources/assets/js/home/MyCases/MyCases.vue b/resources/assets/js/home/MyCases/MyCases.vue index 612b89513..2778470ce 100644 --- a/resources/assets/js/home/MyCases/MyCases.vue +++ b/resources/assets/js/home/MyCases/MyCases.vue @@ -86,7 +86,7 @@ export default { GroupedCell, ModalComments, }, - props: ["filters", "defaultOption"], + props: ["filters", "defaultOption", "settings"], data() { let that = this; return { @@ -102,6 +102,11 @@ export default { allView: [], filterHeader: "STARTED", headers: [], + columMap: { + case_number: "APP_NUMBER", + case_title: "DEL_TITLE", + process_name: "PRO_TITLE" + }, newCase: { title: this.$i18n.t("ID_NEW_CASE"), class: "btn-success", @@ -151,6 +156,8 @@ export default { selectAllMode: "page", programmatic: false, }, + sortable: ['case_number'], + orderBy: this.settings && this.settings.orderBy ? this.settings.orderBy: {}, requestFunction(data) { return this.$parent.$parent.getCasesForVueTable(data); }, @@ -304,13 +311,14 @@ export default { */ getCasesForVueTable(data) { let that = this, - dt, + dt, paged, limit = data.limit, start = data.page === 1 ? 0 : limit * (data.page - 1), - filters = {}; - paged = start + "," + limit; - + filters = {}, + sort = ""; + paged = start + "," + limit; + debugger; filters = { filter: that.filterHeader, paged: paged, @@ -320,11 +328,20 @@ export default { filters[item.filterVar] = item.value; } }); + sort = that.prepareSortString(data); + if (sort) { + filters["sort"] = sort; + that.$emit("updateUserSettings", "orderBy", { + column: data.orderBy, + ascending: data.ascending === 1 ? true: false + }); + } return new Promise((resolutionFunc, rejectionFunc) => { api.cases .myCases(filters) .then((response) => { dt = that.formatDataResponse(response.data.data); + resolutionFunc({ data: dt, count: response.data.total, @@ -335,6 +352,18 @@ export default { }); }); }, + /** + * Prepare sort string to be sended in the service + * @param {object} data + * @returns {string} + */ + prepareSortString(data){ + let sort = ""; + if (data.orderBy && this.columMap[data.orderBy]) { + sort = `${this.columMap[data.orderBy]},${data.ascending === 1 ? "ASC": "DESC"}`; + } + return sort; + }, /** * Format Response API TODO to grid inbox and columns */ diff --git a/resources/assets/js/home/main.js b/resources/assets/js/home/main.js index ad7208823..e1ace4103 100644 --- a/resources/assets/js/home/main.js +++ b/resources/assets/js/home/main.js @@ -5,6 +5,7 @@ import VueI18n from 'vue-i18n'; import { BootstrapVue, BootstrapVueIcons } from 'bootstrap-vue'; import { ServerTable, Event, ClientTable } from 'vue-tables-2'; import VtTableHeadingCustom from './../components/vuetable/extends/VtTableHeadingCustom'; +import VtSortControl from './../components/vuetable/extends/VtSortControl'; import SettingsPopover from "../components/vuetable/SettingsPopover.vue"; import Sortable from 'sortablejs'; import "@fortawesome/fontawesome-free/css/all.css"; @@ -13,15 +14,19 @@ import 'bootstrap/dist/css/bootstrap-grid.css'; import 'bootstrap/dist/css/bootstrap.min.css' import 'bootstrap-vue/dist/bootstrap-vue.css' +import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; + import Home from "./Home"; Vue.use(VueRouter); Vue.use(VueSidebarMenu); Vue.use(BootstrapVue); Vue.use(BootstrapVueIcons); Vue.use(VueI18n); +Vue.component('font-awesome-icon', FontAwesomeIcon); Vue.use(ServerTable, {}, false, 'bootstrap3', { - tableHeading: VtTableHeadingCustom + tableHeading: VtTableHeadingCustom, + sortControl: VtSortControl }); Vue.use(ClientTable, {}, false, 'bootstrap3', {}); Vue.component('settings-popover', SettingsPopover); diff --git a/workflow/engine/methods/cases/viena_init.php b/workflow/engine/methods/cases/viena_init.php index 76822b5d0..99dc21d30 100644 --- a/workflow/engine/methods/cases/viena_init.php +++ b/workflow/engine/methods/cases/viena_init.php @@ -4,6 +4,7 @@ use Eusebiu\JavaScript\Facades\ScriptVariables; use Illuminate\Support\Facades\View; use ProcessMaker\Core\System; use ProcessMaker\Model\Application; +use ProcessMaker\Model\User; $conf = new Configurations(); @@ -127,7 +128,6 @@ $oHeadPublisher->assign('urlProxy', $urlProxy); //sending the urlProxy to make $oHeadPublisher->assign("_nodeId", isset($confDefaultOption) ? $confDefaultOption : "PM_USERS"); //User menu permissions $oHeadPublisher->assign("FORMATS", $conf->getFormats()); - $userCanAccess = 1; global $translation; @@ -142,4 +142,5 @@ ScriptVariables::add('SYS_URI', SYS_URI); ScriptVariables::add('SYS_LANG', SYS_LANG); ScriptVariables::add('TRANSLATIONS', $translation); ScriptVariables::add('FORMATS', $conf->getFormats()); +ScriptVariables::add('userId', User::getId($_SESSION['USER_LOGGED'])); echo View::make('Views::home.home', compact("userCanAccess"))->render();