From c6c2a687cf25c761557af3d6d1fbb0c0b4d547e0 Mon Sep 17 00:00:00 2001 From: Danielle Mayabb Date: Fri, 8 Mar 2024 09:15:12 -0800 Subject: [PATCH] Add total hours to reports --- web/js/include/ExportableGridPanel.js | 96 ++- web/js/userTasksReport.js | 1075 +++++++++++++------------ web/viewUserDetails.php | 43 +- 3 files changed, 632 insertions(+), 582 deletions(-) diff --git a/web/js/include/ExportableGridPanel.js b/web/js/include/ExportableGridPanel.js index 2a7284d4f..1ac28d815 100644 --- a/web/js/include/ExportableGridPanel.js +++ b/web/js/include/ExportableGridPanel.js @@ -24,29 +24,33 @@ * @param columnModel with column data. * @return string in CSV format. */ -function fromStoreToCSV(store, columnModel) { - var csv = ""; +function fromStoreToCSV(store, columnModel, totalRow = null) { + var csv = ''; - var columns = columnModel.getColumnsBy(function (c) { - return !c.hidden; - }); + var columns = columnModel.getColumnsBy(function (c) { + return !c.hidden; + }); - // header with column names - Ext.each(columns, function(column) { - csv += column.header + ","; - }); - csv += "\n"; + // header with column names + Ext.each(columns, function (column) { + csv += column.header + ','; + }); + csv += '\n'; - // data - store.each(function (record) { - Ext.each(columns, function(column) { - var item = store.fields.get(column.dataIndex); - csv += record.data[item.name] + ","; - }); - csv += "\n"; + // data + store.each(function (record) { + Ext.each(columns, function (column) { + var item = store.fields.get(column.dataIndex); + csv += record.data[item.name] + ','; }); + csv += '\n'; + }); + + if (totalRow) { + csv += `\n\n ${totalRow}`; + } - return csv; + return csv; } /** @@ -56,29 +60,37 @@ function fromStoreToCSV(store, columnModel) { * @extends Ext.GridPanel */ Ext.ux.ExportableGridPanel = Ext.extend(Ext.grid.GridPanel, { + initComponent: function () { + Ext.apply(this, { + bbar: [ + { + xtype: 'button', + text: 'Download as CSV', + handler: function () { + //FIXME there must be a better way to get the grid + var gridComponent = this.ownerCt.ownerCt; + const linkSource = `data:text/csv;charset=UTF-8,${encodeURIComponent( + fromStoreToCSV( + gridComponent.getStore(), + gridComponent.getColumnModel(), + gridComponent.footer.dom.innerHTML + ) + )}`; + const downloadLink = document.createElement('a'); + downloadLink.href = linkSource; + downloadLink.download = `${this.ownerCt.ownerCt.title.replace(/ /g, '')}.csv`; + downloadLink.click(); + } + } + ], + footerCfg: { + tag: 'span', + cls: 'exportable-footer x-toolbar x-small-editor x-toolbar-layout-ct', + html: '' + } + }); - initComponent: function () { - Ext.apply(this, { - bbar: [ - { - xtype: 'button', - text: 'Download as CSV', - handler: function () { - //FIXME there must be a better way to get the grid - var gridComponent = this.ownerCt.ownerCt; - const linkSource = `data:text/csv;charset=UTF-8,${encodeURIComponent( - fromStoreToCSV(gridComponent.getStore(), gridComponent.getColumnModel()))}`; - const downloadLink = document.createElement("a"); - downloadLink.href = linkSource; - downloadLink.download = `${this.ownerCt.ownerCt.title.replace(/ /g, '')}.csv`; - downloadLink.click(); - } - }, - ], - }); - - /* call the superclass to preserve base class functionality */ - Ext.ux.ExportableGridPanel.superclass.initComponent.apply(this, arguments); - }, - + /* call the superclass to preserve base class functionality */ + Ext.ux.ExportableGridPanel.superclass.initComponent.apply(this, arguments); + } }); diff --git a/web/js/userTasksReport.js b/web/js/userTasksReport.js index d099053e9..a504d5154 100644 --- a/web/js/userTasksReport.js +++ b/web/js/userTasksReport.js @@ -18,561 +18,586 @@ */ Ext.onReady(function () { - var App = new Ext.App({}); + var App = new Ext.App({}); - /* Schema of the information about customers */ - var customerRecord = new Ext.data.Record.create([ - {name:'id'}, - {name:'name'}, - ]); + /* Schema of the information about customers */ + var customerRecord = new Ext.data.Record.create([{ name: 'id' }, { name: 'name' }]); - /* Schema of the information about projects */ - var projectRecord = new Ext.data.Record.create([ - {name:'id'}, - {name:'description'}, - {name:'customerName'} - ]); + /* Schema of the information about projects */ + var projectRecord = new Ext.data.Record.create([ + { name: 'id' }, + { name: 'description' }, + { name: 'customerName' } + ]); - //schema of the information about users - var userRecord = new Ext.data.Record.create([ - {name: 'id', type: 'int'}, - {name: "login", type: 'string'} - ]); + //schema of the information about users + var userRecord = new Ext.data.Record.create([ + { name: 'id', type: 'int' }, + { name: 'login', type: 'string' } + ]); - // store to load users - var usersStore = new Ext.data.Store({ - id: 'usersStore', - autoLoad: true, //initial data are loaded in the application init - autoSave: false, //if set true, changes will be sent instantly - baseParams: { - }, - proxy: new Ext.data.HttpProxy({ - method: 'GET', - api: { - read: {url: 'services/getAllUsersService.php'} - }, - }), - storeId: 'users', - reader:new Ext.data.XmlReader({ - record: 'user', - idProperty:'id' - }, userRecord), - remoteSort: false, - sortInfo: { - field: 'login', - direction: 'ASC', - }, - listeners: { - 'load': function () { - /* Set the default value of the combobox to the logged in user on load */ - Ext.getCmp('userLogin').setValue(userId); - } - }, - }); + // store to load users + var usersStore = new Ext.data.Store({ + id: 'usersStore', + autoLoad: true, //initial data are loaded in the application init + autoSave: false, //if set true, changes will be sent instantly + baseParams: {}, + proxy: new Ext.data.HttpProxy({ + method: 'GET', + api: { + read: { url: 'services/getAllUsersService.php' } + } + }), + storeId: 'users', + reader: new Ext.data.XmlReader( + { + record: 'user', + idProperty: 'id' + }, + userRecord + ), + remoteSort: false, + sortInfo: { + field: 'login', + direction: 'ASC' + }, + listeners: { + load: function () { + /* Set the default value of the combobox to the logged in user on load */ + Ext.getCmp('userLogin').setValue(userId); + } + } + }); - /* Store object for customers */ - var customersStore = new Ext.data.Store({ - autoLoad: true, - autoSave: false, - baseParams: { - 'order': 'name', - }, - proxy: new Ext.data.HttpProxy({ - url: 'services/getUserCustomersService.php', - method: 'GET' - }), - reader: new Ext.data.XmlReader( - {record: 'customer', id:'id'}, customerRecord), - remoteSort: false, - }); + /* Store object for customers */ + var customersStore = new Ext.data.Store({ + autoLoad: true, + autoSave: false, + baseParams: { + order: 'name' + }, + proxy: new Ext.data.HttpProxy({ + url: 'services/getUserCustomersService.php', + method: 'GET' + }), + reader: new Ext.data.XmlReader({ record: 'customer', id: 'id' }, customerRecord), + remoteSort: false + }); - /* Store object for the projects */ - var projectsStore = new Ext.data.Store({ - parent: this, - autoLoad: true, - autoSave: false, - baseParams: { - 'order': 'description', - }, - filter: function(property, value, anyMatch, caseSensitive) { - var fn; - if (((property == 'description') || (property == 'customerName')) && !Ext.isEmpty(value, false)) { - value = this.data.createValueMatcher(value, anyMatch, caseSensitive); - fn = function(r){ - return value.test(r.data['description']) || value.test(r.data['customerName']); - }; - } else { - fn = this.createFilterFn(property, value, anyMatch, caseSensitive); - } - return fn ? this.filterBy(fn) : this.clearFilter(); - }, - proxy: new Ext.data.HttpProxy({ - url: 'services/getProjectsService.php', - method: 'GET' - }), - reader: new Ext.data.XmlReader( - {record: 'project', id:'id'}, projectRecord), - remoteSort: false, - sortInfo: { - field: 'description', - direction: 'ASC', - }, - }); + /* Store object for the projects */ + var projectsStore = new Ext.data.Store({ + parent: this, + autoLoad: true, + autoSave: false, + baseParams: { + order: 'description' + }, + filter: function (property, value, anyMatch, caseSensitive) { + var fn; + if ((property == 'description' || property == 'customerName') && !Ext.isEmpty(value, false)) { + value = this.data.createValueMatcher(value, anyMatch, caseSensitive); + fn = function (r) { + return value.test(r.data['description']) || value.test(r.data['customerName']); + }; + } else { + fn = this.createFilterFn(property, value, anyMatch, caseSensitive); + } + return fn ? this.filterBy(fn) : this.clearFilter(); + }, + proxy: new Ext.data.HttpProxy({ + url: 'services/getProjectsService.php', + method: 'GET' + }), + reader: new Ext.data.XmlReader({ record: 'project', id: 'id' }, projectRecord), + remoteSort: false, + sortInfo: { + field: 'description', + direction: 'ASC' + } + }); - /* Store object and data for task types */ - var taskTypeStore = new Ext.data.JsonStore({ - fields: [ - 'value', - 'displayText' - ], - root: 'records', - idProperty: 'value', - successProperty: 'success', - url: 'services/getTaskTypes.php', - autoLoad: 'true', - }); + /* Store object and data for task types */ + var taskTypeStore = new Ext.data.JsonStore({ + fields: ['value', 'displayText'], + root: 'records', + idProperty: 'value', + successProperty: 'success', + url: 'services/getTaskTypes.php', + autoLoad: 'true' + }); - /* Renderer to show the project name in the grid */ - function projectRenderer(id) { - var record = projectsStore.getById(id); - if (record) { - return record.get('description'); - } - return id; - }; + /* Renderer to show the project name in the grid */ + function projectRenderer(id) { + var record = projectsStore.getById(id); + if (record) { + return record.get('description'); + } + return id; + } - /* Renderer for html */ - function descriptionRenderer(text){ - return Ext.util.Format.htmlEncode(text) + /* Renderer for html */ + function descriptionRenderer(text) { + return Ext.util.Format.htmlEncode(text); + } + + /* Renderer to show the task type in the grid */ + function taskTypeRenderer(value) { + var record = taskTypeStore.getById(value); + if (record) { + return record.get('displayText'); } + return value; + } - /* Renderer to show the task type in the grid */ - function taskTypeRenderer(value) { - var record = taskTypeStore.getById(value); - if (record) { - return record.get('displayText'); + filtersPanelItems = [ + { + fieldLabel: 'User', + name: 'user', + xtype: 'combo', + allowBlank: false, + autoLoad: true, + typeAhead: true, + mode: 'local', + store: usersStore, + valueField: 'id', + displayField: 'login', + triggerAction: 'all', + forceSelection: true, + id: 'userLogin' + }, + { + fieldLabel: 'Dates between', + name: 'start', + xtype: 'datefieldplus', + format: 'd/m/Y', + startDay: 1, + useQuickTips: false, + id: 'startDate', + listeners: { + change: function (field, newValue, oldValue) { + if (!field.isValid()) return; + var date = field.parseDate(newValue); + Ext.getCmp('endDate').setMinValue(date); } - return value; - }; + } + }, + { + fieldLabel: 'and', + name: 'end', + xtype: 'datefieldplus', + format: 'd/m/Y', + startDay: 1, + useQuickTips: false, + id: 'endDate', + listeners: { + change: function (field, newValue, oldValue) { + if (!field.isValid()) return; + var date = field.parseDate(newValue); + Ext.getCmp('startDate').setMaxValue(date); + } + } + }, + { + fieldLabel: 'Task description', + name: 'filterText', + xtype: 'combo', + id: 'filterText', + store: ['[empty]', '[not empty]'], + triggerAction: 'all', + forceSelection: false, + autoSelect: false + }, + { + fieldLabel: 'Project', + name: 'project', + xtype: 'combo', + id: 'project', + store: projectsStore, + mode: 'local', + valueField: 'id', + typeAhead: false, + triggerAction: 'all', + displayField: 'description', + forceSelection: true, + tpl: + '' + + '
{description} ' + + '- {customerName}' + + '
' + + '
', + listeners: { + select: function (combo, record, index) { + selectText = record.data['description']; - filtersPanelItems = [{ - fieldLabel: 'User', - name: 'user', - xtype: 'combo', - allowBlank: false, - autoLoad: true, - typeAhead: true, - mode: 'local', - store: usersStore, - valueField: 'id', - displayField: 'login', - triggerAction: 'all', - forceSelection: true, - id: 'userLogin' - },{ - fieldLabel: 'Dates between', - name: 'start', - xtype: 'datefieldplus', - format: 'd/m/Y', - startDay: 1, - useQuickTips: false, - id: 'startDate', - listeners: { - 'change': function (field, newValue, oldValue) { - if(!field.isValid()) return; - var date = field.parseDate(newValue); - Ext.getCmp('endDate').setMinValue(date); - } - } - },{ - fieldLabel: 'and', - name: 'end', - xtype: 'datefieldplus', - format: 'd/m/Y', - startDay: 1, - useQuickTips: false, - id: 'endDate', - listeners: { - 'change': function (field, newValue, oldValue) { - if(!field.isValid()) return; - var date = field.parseDate(newValue); - Ext.getCmp('startDate').setMaxValue(date); - } - } - },{ - fieldLabel: 'Task description', - name: 'filterText', - xtype: 'combo', - id: 'filterText', - store: ['[empty]', '[not empty]'], - triggerAction:'all', - forceSelection: false, - autoSelect: false, - },{ - fieldLabel: 'Project', - name: 'project', - xtype: 'combo', - id: 'project', - store: projectsStore, - mode: 'local', - valueField: 'id', - typeAhead: false, - triggerAction: 'all', - displayField: 'description', - forceSelection: true, - tpl: '' + - '
{description} ' + - '- {customerName}' + - '
' + - '
', - listeners: { - 'select': function (combo, record, index) { - selectText = record.data['description']; + // We take customer name from the select combo, and injects its id to the taskRecord + if (record.data['customerName']) { + selectText = record.data['description'] + ' - ' + record.data['customerName']; + } - // We take customer name from the select combo, and injects its id to the taskRecord - if (record.data['customerName']) { - selectText = record.data['description'] + " - " + record.data['customerName']; - } + this.setValue(selectText); + combo.value = record.id; + } + } + }, + { + fieldLabel: 'Customer', + name: 'customer', + xtype: 'combo', + id: 'customer', + store: customersStore, + mode: 'local', + valueField: 'id', + displayField: 'name', + typeAhead: true, + triggerAction: 'all', + displayField: 'name', + forceSelection: true + }, + { + fieldLabel: 'Task type', + name: 'type', + xtype: 'combo', + id: 'type', + store: taskTypeStore, + mode: 'local', + valueField: 'value', + displayField: 'displayText', + typeAhead: true, + triggerAction: 'all', + forceSelection: true + }, + { + fieldLabel: 'Telework', + name: 'telework', + xtype: 'combo', + id: 'telework', + mode: 'local', + triggerAction: 'all', + store: ['yes', 'no'] + }, + { + fieldLabel: 'Onsite', + name: 'onsite', + xtype: 'combo', + id: 'onsite', + mode: 'local', + triggerAction: 'all', + store: ['yes', 'no'] + }, + { + fieldLabel: 'Story', + name: 'filterStory', + xtype: 'combo', + id: 'filterStory', + store: ['[empty]', '[not empty]'], + triggerAction: 'all', + forceSelection: false, + autoSelect: false + } + ]; - this.setValue(selectText); - combo.value = record.id; - } - } - },{ - fieldLabel: 'Customer', - name: 'customer', - xtype: 'combo', - id: 'customer', - store: customersStore, - mode: 'local', - valueField: 'id', - displayField: 'name', - typeAhead: true, - triggerAction: 'all', - displayField: 'name', - forceSelection: true, - },{ - fieldLabel: 'Task type', - name: 'type', - xtype: 'combo', - id: 'type', - store: taskTypeStore, - mode: 'local', - valueField: 'value', - displayField: 'displayText', - typeAhead: true, - triggerAction: 'all', - forceSelection: true, - },{ - fieldLabel: 'Telework', - name: 'telework', - xtype: 'combo', - id: 'telework', - mode: 'local', - triggerAction:'all', - store: ['yes', 'no'], - },{ - fieldLabel: 'Onsite', - name: 'onsite', - xtype: 'combo', - id: 'onsite', - mode: 'local', - triggerAction:'all', - store: ['yes', 'no'], - },{ - fieldLabel: 'Story', - name: 'filterStory', - xtype: 'combo', - id: 'filterStory', - store: ['[empty]', '[not empty]'], - triggerAction:'all', - forceSelection: false, - autoSelect: false, - }] + /* Panel containing all the search parameters */ + var filtersPanel = new Ext.FormPanel({ + labelWidth: 100, + frame: true, + width: 350, + renderTo: 'content', + defaults: { width: 230 }, + items: filtersPanelItems, - /* Panel containing all the search parameters */ - var filtersPanel = new Ext.FormPanel({ - labelWidth: 100, - frame: true, - width: 350, - renderTo: 'content', - defaults: {width: 230}, - items: filtersPanelItems, + buttons: [ + { + text: 'Find tasks', + handler: findTasks + } + ], - buttons: [{ - text: 'Find tasks', - handler: findTasks, - }], + keys: [ + { + key: [Ext.EventObject.ENTER], + handler: findTasks + } + ] + }); + /* Allow listing of user tasks of other users only for an admin user */ + if (admin == '') { + Ext.getCmp('userLogin').setDisabled(true); + } - keys: [{ - key: [Ext.EventObject.ENTER], - handler: findTasks, - }], - }); - /* Allow listing of user tasks of other users only for an admin user */ - if ( admin == "" ) { - Ext.getCmp('userLogin').setDisabled(true); + /* Handler to invoke the search service */ + function findTasks() { + if (Ext.getCmp('userLogin').getRawValue() == '') { + App.setAlert(false, 'Check For Invalid Field Values'); + return; } + var baseParams = { + userId: Ext.getCmp('userLogin').getValue(), + dateFormat: 'm/d/Y' + }; - /* Handler to invoke the search service */ - function findTasks () { - if (Ext.getCmp('userLogin').getRawValue() == ""){ - App.setAlert(false, "Check For Invalid Field Values"); - return; - } - var baseParams = { - userId: Ext.getCmp('userLogin').getValue(), - dateFormat: "m/d/Y", - }; - - if (Ext.getCmp('startDate').getRawValue() != "") { - var date = Ext.getCmp('startDate').getValue(); - baseParams.filterStartDate = (date.getMonth()+1) + "/" + - date.getDate() + "/" + date.getFullYear(); - } - if (Ext.getCmp('endDate').getRawValue() != "") { - var date = Ext.getCmp('endDate').getValue(); - baseParams.filterEndDate = (date.getMonth()+1) + "/" + - date.getDate() + "/" + date.getFullYear(); - } - if (Ext.getCmp('filterText').getRawValue() != "") { - //this field is the selector for two different, incompatible - //parameters in the service - var value = Ext.getCmp('filterText').getValue(); - if (value == '[empty]') { - baseParams.emptyText = true; - } - else if (value == '[not empty]') { - baseParams.emptyText = false; - } - else { - baseParams.filterText = value; - } - } - if (Ext.getCmp('project').getRawValue() != "") { - var value = Ext.getCmp('project').getValue(); - baseParams.projectId = value; - } - if (Ext.getCmp('customer').getRawValue() != "") { - var value = Ext.getCmp('customer').getValue(); - baseParams.customerId = value; - } - if (Ext.getCmp('type').getRawValue() != "") { - var value = Ext.getCmp('type').getValue(); - baseParams.type = value; - } - if (Ext.getCmp('filterStory').getRawValue() != "") { - //this field is the selector for two different, incompatible - //parameters in the service - var value = Ext.getCmp('filterStory').getValue(); - if (value == '[empty]') { - baseParams.emptyStory = true; - } - else if (value == '[not empty]') { - baseParams.emptyStory = false; - } - else { - baseParams.filterStory = value; - } - } - if (Ext.getCmp('telework').getRawValue() != "") { - var value = Ext.getCmp('telework').getValue(); - baseParams.telework = (value == 'yes')? true : false; - } - if (Ext.getCmp('onsite').getRawValue() != "") { - var value = Ext.getCmp('onsite').getValue(); - baseParams.onsite = (value == 'yes')? true : false; - } - - tasksStore.baseParams = baseParams; - tasksStore.load(); + if (Ext.getCmp('startDate').getRawValue() != '') { + var date = Ext.getCmp('startDate').getValue(); + baseParams.filterStartDate = + date.getMonth() + 1 + '/' + date.getDate() + '/' + date.getFullYear(); + } + if (Ext.getCmp('endDate').getRawValue() != '') { + var date = Ext.getCmp('endDate').getValue(); + baseParams.filterEndDate = + date.getMonth() + 1 + '/' + date.getDate() + '/' + date.getFullYear(); + } + if (Ext.getCmp('filterText').getRawValue() != '') { + //this field is the selector for two different, incompatible + //parameters in the service + var value = Ext.getCmp('filterText').getValue(); + if (value == '[empty]') { + baseParams.emptyText = true; + } else if (value == '[not empty]') { + baseParams.emptyText = false; + } else { + baseParams.filterText = value; + } + } + if (Ext.getCmp('project').getRawValue() != '') { + var value = Ext.getCmp('project').getValue(); + baseParams.projectId = value; + } + if (Ext.getCmp('customer').getRawValue() != '') { + var value = Ext.getCmp('customer').getValue(); + baseParams.customerId = value; + } + if (Ext.getCmp('type').getRawValue() != '') { + var value = Ext.getCmp('type').getValue(); + baseParams.type = value; + } + if (Ext.getCmp('filterStory').getRawValue() != '') { + //this field is the selector for two different, incompatible + //parameters in the service + var value = Ext.getCmp('filterStory').getValue(); + if (value == '[empty]') { + baseParams.emptyStory = true; + } else if (value == '[not empty]') { + baseParams.emptyStory = false; + } else { + baseParams.filterStory = value; + } + } + if (Ext.getCmp('telework').getRawValue() != '') { + var value = Ext.getCmp('telework').getValue(); + baseParams.telework = value == 'yes' ? true : false; + } + if (Ext.getCmp('onsite').getRawValue() != '') { + var value = Ext.getCmp('onsite').getValue(); + baseParams.onsite = value == 'yes' ? true : false; } - taskRecordColumns = [ - {name:'id'}, - {name:'date'}, - {name:'initTime'}, - {name:'endTime'}, - {name:'hours'}, - {name:'story'}, - {name:'telework'}, - {name:'onsite'}, - {name:'ttype'}, - {name:'text'}, - {name:'phase'}, - {name:'userId'}, - {name:'projectId'} - ] + tasksStore.baseParams = baseParams; + tasksStore.load(); + } - /* Schema of the information about tasks */ - var taskRecord = new Ext.data.Record.create(taskRecordColumns); + taskRecordColumns = [ + { name: 'id' }, + { name: 'date' }, + { name: 'initTime' }, + { name: 'endTime' }, + { name: 'hours' }, + { name: 'story' }, + { name: 'telework' }, + { name: 'onsite' }, + { name: 'ttype' }, + { name: 'text' }, + { name: 'phase' }, + { name: 'userId' }, + { name: 'projectId' } + ]; - /* Proxy to the services related with load/save Projects */ - var proxy = new Ext.data.HttpProxy({ - api: { - read: {url: 'services/getTasksFiltered.php', method: 'GET'}, - }, - }); + /* Schema of the information about tasks */ + var taskRecord = new Ext.data.Record.create(taskRecordColumns); - /* Store object for the tasks */ - var tasksStore = new Ext.data.Store({ - id: 'tasksStore', - autoLoad: false, - autoSave: false, - storeId: 'tasks', - proxy: proxy, - reader: new Ext.data.XmlReader( - {record: 'task', idProperty:'id' }, taskRecord), - remoteSort: false, - sortInfo: { - field: 'date', - direction: 'ASC', - }, - }); + /* Proxy to the services related with load/save Projects */ + var proxy = new Ext.data.HttpProxy({ + api: { + read: { url: 'services/getTasksFiltered.php', method: 'GET' } + } + }); - columnModelItems = [ - { - header: 'Date', - xtype: 'datecolumn', - format: 'd/m/Y', - sortable: true, - dataIndex: 'date', - },{ - header: 'Init time', - sortable: true, - dataIndex: 'initTime', - },{ - header: 'End time', - sortable: true, - dataIndex: 'endTime', - },{ - header: 'Hours', - sortable: true, - dataIndex: 'hours', - }, { - header: "Project", - sortable: true, - dataIndex: 'projectId', - renderer: projectRenderer, - },{ - header: "Task type", - sortable: true, - dataIndex: 'ttype', - renderer: taskTypeRenderer, - },{ - header: 'Telework', - sortable: true, - dataIndex: 'telework', - xtype: 'booleancolumn', - trueText: "Yes", - falseText: "No", - },{ - header: 'Onsite', - sortable: true, - dataIndex: 'onsite', - xtype: 'booleancolumn', - trueText: "Yes", - falseText: "No", - },{ - header: 'Description', - sortable: true, - dataIndex: 'text', - renderer: descriptionRenderer - },{ - header: 'Story', - sortable: true, - dataIndex: 'story', - } - ] + function getMinutes(time) { + const hours = Number(time.split(':')[0]); + const minutes = Number(time.split(':')[1]); + return hours * 60 + minutes; + } + let taskHoursTotalDisplay = ''; + /* Store object for the tasks */ + var tasksStore = new Ext.data.Store({ + id: 'tasksStore', + autoLoad: false, + autoSave: false, + storeId: 'tasks', + proxy: proxy, + reader: new Ext.data.XmlReader({ record: 'task', idProperty: 'id' }, taskRecord), + remoteSort: false, + sortInfo: { + field: 'date', + direction: 'ASC' + }, + listeners: { + load: function (store, records, options) { + let total = 0; + records.forEach((task) => { + let minutes = getMinutes(task.data.hours); + total += minutes; + }); + let totalString = (total / 60).toFixed(2).toString(); + taskHoursTotalDisplay = totalString; + document.getElementsByClassName('exportable-footer')[0].innerHTML = + `Total hours: ${taskHoursTotalDisplay}`; + } + } + }); - var columnModel = new Ext.grid.ColumnModel(columnModelItems); + columnModelItems = [ + { + header: 'Date', + xtype: 'datecolumn', + format: 'd/m/Y', + sortable: true, + dataIndex: 'date' + }, + { + header: 'Init time', + sortable: true, + dataIndex: 'initTime' + }, + { + header: 'End time', + sortable: true, + dataIndex: 'endTime' + }, + { + header: 'Hours', + sortable: true, + dataIndex: 'hours' + }, + { + header: 'Project', + sortable: true, + dataIndex: 'projectId', + renderer: projectRenderer + }, + { + header: 'Task type', + sortable: true, + dataIndex: 'ttype', + renderer: taskTypeRenderer + }, + { + header: 'Telework', + sortable: true, + dataIndex: 'telework', + xtype: 'booleancolumn', + trueText: "Yes", + falseText: "No" + }, + { + header: 'Onsite', + sortable: true, + dataIndex: 'onsite', + xtype: 'booleancolumn', + trueText: "Yes", + falseText: "No" + }, + { + header: 'Description', + sortable: true, + dataIndex: 'text', + renderer: descriptionRenderer + }, + { + header: 'Story', + sortable: true, + dataIndex: 'story' + } + ]; - // setup the panel for the grid of tasks - var tasksGrid = new Ext.grid.GridPanel({ - id: 'tasksGrid', - renderTo: 'content', - frame: true, - height: 500, - width: '100%', - iconCls: 'silk-book', - store: tasksStore, - frame: true, - title: 'Tasks', - style: 'margin-top: 10px', - renderTo: 'content', - loadMask: true, - stripeRows: true, - colModel: columnModel, - columnLines: true, - buttons: [{ - text: 'Standard view', - handler: showStandardView, - },{ - text: 'Extended view', - handler: showExtendedView, - }], - bbar: [{ - xtype: 'button', - text: 'Download as CSV', - handler: function () { - urlParams = "format=csv&showProjectNames=true"; - for (var parameter in tasksStore.baseParams) { - urlParams += "&" + parameter + "=" + - tasksStore.baseParams[parameter]; - } - window.open("services/getTasksFiltered.php?" + urlParams); - } - }], - }); + var columnModel = new Ext.grid.ColumnModel(columnModelItems); - //function to show only a subset of columns and hide the others - function showStandardView() { - columnModel.setHidden(0, false); //date - columnModel.setHidden(1, true); //init - columnModel.setHidden(2, true); //end - columnModel.setHidden(3, false); //hours - columnModel.setHidden(4, false); //project - columnModel.setHidden(5, true); //task type - columnModel.setHidden(6, true); //telework - columnModel.setHidden(7, true); //onsite - columnModel.setHidden(8, false); //description - columnModel.setHidden(9, false); //story - columnModel.setColumnWidth(0, 80); - columnModel.setColumnWidth(1, 55); - columnModel.setColumnWidth(2, 55); - columnModel.setColumnWidth(3, 55); - columnModel.setColumnWidth(4, 200); - columnModel.setColumnWidth(5, 120); - columnModel.setColumnWidth(8, 435); - columnModel.setColumnWidth(9, 120); - } + // setup the panel for the grid of tasks + var tasksGrid = new Ext.ux.ExportableGridPanel({ + id: 'tasksGrid', + renderTo: 'content', + frame: true, + height: 500, + width: '100%', + iconCls: 'silk-book', + store: tasksStore, + frame: true, + title: 'Tasks', + style: 'margin-top: 10px', + renderTo: 'content', + loadMask: true, + stripeRows: true, + colModel: columnModel, + columnLines: true, + buttons: [ + { + text: 'Standard view', + handler: showStandardView + }, + { + text: 'Extended view', + handler: showExtendedView + } + ], + footerStyle: 'color: #15428b; font-size: 12px; font-weight: bold; padding-left: 4px' + }); - //function to show all the columns - function showExtendedView() { - columnModel.setHidden(0, false); //date - columnModel.setHidden(1, false); //init - columnModel.setHidden(2, false); //end - columnModel.setHidden(3, false); //hours - columnModel.setHidden(4, false); //project - columnModel.setHidden(5, false); //task type - columnModel.setHidden(6, false); //telework - columnModel.setHidden(7, false); //onsite - columnModel.setHidden(8, false); //description - columnModel.setHidden(9, false); //story - columnModel.setColumnWidth(0, 80); - columnModel.setColumnWidth(1, 55); - columnModel.setColumnWidth(2, 55); - columnModel.setColumnWidth(3, 55); - columnModel.setColumnWidth(4, 200); - columnModel.setColumnWidth(5, 100); - columnModel.setColumnWidth(6, 80); - columnModel.setColumnWidth(7, 50); - columnModel.setColumnWidth(8, 435); - columnModel.setColumnWidth(9, 100); - } + //function to show only a subset of columns and hide the others + function showStandardView() { + columnModel.setHidden(0, false); //date + columnModel.setHidden(1, true); //init + columnModel.setHidden(2, true); //end + columnModel.setHidden(3, false); //hours + columnModel.setHidden(4, false); //project + columnModel.setHidden(5, true); //task type + columnModel.setHidden(6, true); //telework + columnModel.setHidden(7, true); //onsite + columnModel.setHidden(8, false); //description + columnModel.setHidden(9, false); //story + columnModel.setColumnWidth(0, 80); + columnModel.setColumnWidth(1, 55); + columnModel.setColumnWidth(2, 55); + columnModel.setColumnWidth(3, 55); + columnModel.setColumnWidth(4, 200); + columnModel.setColumnWidth(5, 120); + columnModel.setColumnWidth(8, 435); + columnModel.setColumnWidth(9, 120); + } + + //function to show all the columns + function showExtendedView() { + columnModel.setHidden(0, false); //date + columnModel.setHidden(1, false); //init + columnModel.setHidden(2, false); //end + columnModel.setHidden(3, false); //hours + columnModel.setHidden(4, false); //project + columnModel.setHidden(5, false); //task type + columnModel.setHidden(6, false); //telework + columnModel.setHidden(7, false); //onsite + columnModel.setHidden(8, false); //description + columnModel.setHidden(9, false); //story + columnModel.setColumnWidth(0, 80); + columnModel.setColumnWidth(1, 55); + columnModel.setColumnWidth(2, 55); + columnModel.setColumnWidth(3, 55); + columnModel.setColumnWidth(4, 200); + columnModel.setColumnWidth(5, 100); + columnModel.setColumnWidth(6, 80); + columnModel.setColumnWidth(7, 50); + columnModel.setColumnWidth(8, 435); + columnModel.setColumnWidth(9, 100); + } - //hide the advanced columns - showStandardView(); + //hide the advanced columns + showStandardView(); - Ext.getCmp("startDate").focus(); + Ext.getCmp('startDate').focus(); }); diff --git a/web/viewUserDetails.php b/web/viewUserDetails.php index 57be9314a..6e0cd0ab2 100644 --- a/web/viewUserDetails.php +++ b/web/viewUserDetails.php @@ -18,19 +18,19 @@ * along with PhpReport. If not, see . */ - define('PHPREPORT_ROOT', __DIR__ . '/../'); +define('PHPREPORT_ROOT', __DIR__ . '/../'); - /* We check authentication and authorization */ - require_once(PHPREPORT_ROOT . '/web/auth.php'); +/* We check authentication and authorization */ +require_once(PHPREPORT_ROOT . '/web/auth.php'); - /* Include the generic header and sidebar*/ - define('PAGE_TITLE', "PhpReport - User Details"); - include_once("include/header.php"); - include_once(PHPREPORT_ROOT . '/model/facade/UsersFacade.php'); - include_once(PHPREPORT_ROOT . '/model/facade/ProjectsFacade.php'); - include_once(PHPREPORT_ROOT . '/web/services/WebServicesFunctions.php'); +/* Include the generic header and sidebar*/ +define('PAGE_TITLE', "PhpReport - User Details"); +include_once("include/header.php"); +include_once(PHPREPORT_ROOT . '/model/facade/UsersFacade.php'); +include_once(PHPREPORT_ROOT . '/model/facade/ProjectsFacade.php'); +include_once(PHPREPORT_ROOT . '/web/services/WebServicesFunctions.php'); - $userToShow = $_SESSION['user']; +$userToShow = $_SESSION['user']; ?> @@ -160,14 +160,16 @@ } }); + let taskHoursTotalDisplay = ''; + var grid = new Ext.ux.DynamicGridPanel({ id: 'my-grid', storeUrl: 'services/getUserProjectCustomerReportJsonService.php?getId(); ?>', + echo "&uid=" . $userToShow->getId(); ?>', rowNumberer: false, checkboxSelModel: false, @@ -176,10 +178,19 @@ frame: false, title: 'User Project Worked Hours Report', iconCls: 'icon-grid', + footerStyle: 'color: #15428b; font-size: 12px; font-weight: bold; padding-left: 4px' }); grid.store.on('load', function(){ + let total = 0; + grid.store.data.items.forEach((task) => { + total += task.data.total; + }); + let totalString = (total).toFixed(2).toString(); + taskHoursTotalDisplay = totalString; + document.getElementsByClassName('exportable-footer')[0].innerHTML = + `Total hours: ${taskHoursTotalDisplay}`; /** * Thats the magic! * @@ -199,6 +210,7 @@ columns.push(column); }); + /** * Setting column model configuration */ @@ -219,8 +231,8 @@ grid.store.proxy.conn.url= 'services/getUserProjectCustomerReportJsonService.php?' + '&uid=' + Ext.getCmp('userLogin').getValue() + if ($sid != "") + echo "&sid=" . $sid; ?>' + '&uid=' + Ext.getCmp('userLogin').getValue() + '&init=' + init.getFullYear() + "-" + (init.getMonth()+1) + "-" + init.getDate() + "&end=" + end.getFullYear() + "-" + (end.getMonth() + 1) + "-" + end.getDate(); @@ -246,3 +258,4 @@ /* Include the footer to close the header */ include("include/footer.php"); ?> +