This commit is contained in:
2022-03-02 15:49:01 +00:00
parent 629bfb366f
commit bc6ff4168c
6 changed files with 216 additions and 124 deletions

View File

@@ -31,7 +31,7 @@ FIRST CLIENT SOURCE CODE COMMIT JAN 3rd 2019
# SEEDING ISSUES
seeder wo created date not set properly, should match the way it's generated
??seeder wo created date not set properly, should match the way it's generated
seeder make reminders and reviews for all users, just random scattering for now to future month ahead at least one per day to show off schedule and widgets
seeder wo need new fields and generate data to show off and test kpi widgets and features
@@ -44,22 +44,37 @@ seeder wo need new fields and generate data to show off and test kpi widgets and
# WIDGET ISSUES
# WIDGETS
https://www.calculator.net/percent-calculator.html
- Widgets to make for beta in order of priority
**MUST HAVE***
*** FIX FIRST: Unscheduled is showing dupes, maybe it's one per woitem??
* LIST overdue workorders (booked on, in the past, not a closed status) for current scheduleable user
* LIST overdue workorders (booked on, in the past, not a closed status, passed completeby date) for current scheduleable user
criteria:
tags wo, woitem
SELECT distinct(AWORKORDER.ID),
AWORKORDER.SERIAL,
AWORKORDER.completebydate,
ACUSTOMER.NAME,
AWORKORDER.NOTES
FROM AWORKORDER
LEFT JOIN AWORKORDERITEM ON AWORKORDER.ID = AWORKORDERITEM.WORKORDERID
LEFT JOIN AWORKORDERITEMSCHEDULEDUSER ON AWORKORDERITEM.ID = AWORKORDERITEMSCHEDULEDUSER.WORKORDERITEMID
LEFT JOIN AWORKORDERSTATUS ON (AWORKORDER.LASTSTATUSID = AWORKORDERSTATUS.ID)
LEFT JOIN ACUSTOMER ON (AWORKORDER.CUSTOMERID = ACUSTOMER.ID)
WHERE (LASTSTATUSID IS NULL OR AWORKORDERSTATUS.COMPLETED = FALSE) and aworkorder.completebydate < now()
AND AWORKORDERITEMSCHEDULEDUSER.userID = 10
ORDER BY AWORKORDER.ID ASC
* LIST overdue workorders list not user centric available to service manager roles
criteria:
tags wo, woitem
LINE/BAR Count of work orders created per day over time (from case 1882)
criteria:
timespan and INTERVAL

View File

@@ -5,6 +5,19 @@ const role = authorizationroles.AUTHORIZATION_ROLES;
*/
export default {
registry: [
{
roles: [role.Tech, role.TechRestricted],
title: "DashboardOverdue",
icon: "$ayiListAlt",
type: "GzDashWorkorderOverduePersonalList",
scheduleableUserOnly: true,
singleOnly: true,
settings: {
customTitle: null,
wotags: [],
woitemtags: []
}
},
{
roles: [
role.BizAdmin,

View File

@@ -1,108 +0,0 @@
<template>
<gz-dash
ref="dashbase"
icon="$ayiUser"
:add-url="'cust-customers/0'"
:update-frequency="58000"
:count="23"
v-bind="[$props, $attrs]"
@dash-refresh="loadData"
v-on="$listeners"
>
<template slot="main">
settings:{{ settings }}
<gz-chart-bar-horizontal
:width="400"
:height="240"
:chart-data="obj"
:options="{
maintainAspectRatio: false,
responsive: true,
legend: { display: false },
scales: {
xAxes: [
{
gridLines: { display: true },
ticks: {
beginAtZero: true
}
}
],
yAxes: [
{
gridLines: { display: false }
}
]
},
onClick: function(e, items) {
clicked(e, items);
}
}"
></gz-chart-bar-horizontal>
</template>
</gz-dash>
</template>
<script>
import GzDash from "../components/dash-base.vue";
import Palette from "../api/palette";
export default {
components: {
GzDash
},
props: {
updateFrequency: { type: Number, default: null },
settings: { type: Object, default: null }
},
data() {
return {
obj: {}
};
},
computed: {},
created() {},
methods: {
loadData: function() {
this.obj = {
labels: [
"Customer",
"Head office",
"Service",
"Non Service",
"Subcontractor"
],
datasets: [
{
label: "",
data: [2, 4, 6, 8, 10],
backgroundColor: Palette.getSoftPaletteArray(5)
}
],
//this is added for my use, not part of chart js, used to get special id value of bar since labels are localized and data is not unique
//https://stackoverflow.com/a/42635435/8939
datakeys: [
{ id: 11, type: 34 },
{ id: 22, type: 34 },
{ id: 33, type: 34 },
{ id: 44, type: 34 },
{ id: 55, type: 34 }
]
};
},
clicked: function(c, i) {
if (i.length == 0) return; //Clicked outside any bar.
const e = i[0]; //get index of bar clicked on
//this gets the label
//let x_value = this.obj.labels[e._index];
//this gets the value
//let y_value = this.obj.datasets[0].data[e._index];
//this gets my custom id stuff
//https://stackoverflow.com/a/42635435/8939
const dataKeyValue = this.obj.datakeys[e._index];
alert(`STUB: OPEN ITEM (data: ${JSON.stringify(dataKeyValue)})`);
//clickOnChart(lastHoveredIndex);
}
}
};
</script>

View File

@@ -0,0 +1,170 @@
<template>
<gz-dash
icon="$ayiTools"
:count="obj.length"
:add-url="'svc-workorders/0'"
:show-context-button="true"
:update-frequency="300000"
v-bind="[$props, $attrs]"
@dash-refresh="getDataFromApi()"
@dash-context="showContext()"
v-on="$listeners"
>
<template slot="main">
<v-sheet height="400" class="overflow-y-auto">
<div
v-if="obj.length == 0"
class="ml-6 mt-6 text-h4 grey--text text--lighten-1"
>
{{ $ay.t("NoData") }}
</div>
<template v-for="(item, i) in obj">
<v-list-item :key="i" two-line :to="'/svc-workorders/' + item.id">
<v-list-item-content>
<v-list-item-title
><span class="text-h6 primary--text">{{ item.serial }}</span
><span class="ml-4">{{ $ay.dt(item.completebydate) }}</span>
<span class="ml-4">{{ item.name }}</span></v-list-item-title
>
<v-list-item-subtitle>{{ item.notes }}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</template>
</v-sheet>
</template>
<template slot="settings">
<div></div>
<v-col v-if="context" cols="12">
<v-dialog
v-model="context"
scrollable
max-width="400px"
data-cy="dashSettings"
@keydown.esc="cancel"
>
<v-card elevation="24">
<v-card-title class="text-h5 lighten-2" primary-title>
<span> {{ $ay.t("Settings") }} </span>
</v-card-title>
<v-card-text>
<gz-tag-picker
v-model="localSettings.wotags"
:label="$ay.t('Tags') + ' - ' + $ay.t('WorkOrder')"
></gz-tag-picker>
<gz-tag-picker
v-model="localSettings.woitemtags"
:label="$ay.t('Tags') + ' - ' + $ay.t('WorkOrderItem')"
></gz-tag-picker>
<v-text-field
v-model="localSettings.customTitle"
:label="$ay.t('Name')"
></v-text-field>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-btn color="primary" text @click.native="context = false">{{
$ay.t("Cancel")
}}</v-btn>
<v-spacer></v-spacer>
<v-btn
color="primary"
text
class="ml-4"
@click="updateSettings"
>{{ $ay.t("Save") }}</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-col>
</template>
</gz-dash>
</template>
<script>
import GzDash from "./dash-base.vue";
export default {
components: {
GzDash
},
props: {
settings: { type: Object, default: null }
},
data() {
return {
obj: {},
context: false,
localSettings: {}
};
},
computed: {},
async created() {
await initWidget(this);
},
async mounted() {
//must be called from mounted to have refs available
await this.getDataFromApi();
},
methods: {
showContext: function() {
this.localSettings = window.$gz.util.deepCopySkip(this.settings);
this.context = true;
},
updateSettings: function() {
//copy settings from local to parent settings, need to do it this way or get error about mutating prop directly which is vexing and has no easy solution seemingly
this.settings.customTitle = this.localSettings.customTitle;
this.settings.wotags = this.localSettings.wotags;
this.settings.woitemtags = this.localSettings.woitemtags;
this.$emit("dash-change"); //trigger save to server
this.context = false;
this.getDataFromApi();
},
async getDataFromApi() {
try {
this.errorMessage = null;
const res = await window.$gz.api.post("kpi", {
KPIName: "WorkOrderOverduePersonalList",
criteria: {
wotags: this.settings.wotags,
woitemtags: this.settings.woitemtags
},
clientTimeStamp: window.$gz.locale.clientLocalZoneTimeStamp()
});
if (res.error) {
this.errorMessage = res.error;
} else {
this.obj = res.data;
}
} catch (error) {
this.errorMessage = error.toString();
}
}
}
};
/////////////////////////////////
//
//
async function initWidget() {
await fetchTranslatedText();
}
//////////////////////////////////////////////////////////
//
// Ensures UI translated text is available
//
async function fetchTranslatedText() {
await window.$gz.translation.cacheTranslations([
"Name",
"WorkOrder",
"WorkOrderItem",
"NoData"
]);
}
</script>

View File

@@ -91,7 +91,8 @@ import GzDashLaborHoursPersonalBar from "../components/dash-labor-hours-personal
import GzDashLaborHoursEveryoneLine from "../components/dash-labor-hours-everyone-line.vue";
import GzDashLaborHoursEveryoneBar from "../components/dash-labor-hours-everyone-bar.vue";
import GzDashWorkorderUnscheduledOpenList from "../components/dash-workorder-unscheduled-open-list.vue";
import GzDashCSROpenList from "../components/dash-csr-open-list";
import GzDashCSROpenList from "../components/dash-csr-open-list.vue";
import GzDashWorkorderOverduePersonalList from "../components/dash-workorder-overdue-personal-list.vue";
export default {
components: {
@@ -103,7 +104,8 @@ export default {
GzDashWorkorderUnscheduledOpenList,
GzDashCSROpenList,
GzDashLaborHoursEveryoneLine,
GzDashLaborHoursEveryoneBar
GzDashLaborHoursEveryoneBar,
GzDashWorkorderOverduePersonalList
},
data() {
return {

View File

@@ -77,7 +77,11 @@
:error-box-message="formState.errorBoxMessage"
></gz-error>
</v-col>
<v-col cols="12" md="7">
<span class="text-h5 text-md-h3 red--text"
>BETA TEST - NOT FOR PRODUCTION USE</span
>
</v-col>
<v-col v-if="showEvalUsers == true" cols="12" md="7">
<v-select
v-model="selectedTrialUserId"
@@ -93,11 +97,7 @@
>
</v-select>
</v-col>
<v-col cols="12">
<span class="text-sm-h5 text-md-h3 red--text"
>BETA TEST - NOT FOR PRODUCTION USE</span
>
</v-col>
<v-col cols="12" md="7">
<v-text-field
id="username"