This commit is contained in:
2022-03-01 19:36:40 +00:00
parent fa7ccfa4c4
commit 0d78a6999d
6 changed files with 784 additions and 13 deletions

View File

@@ -53,13 +53,17 @@ https://www.ayanova.com/AyaNova7webHelp/index.html?dashboard.htm
- Widgets to make for beta in order of priority - Widgets to make for beta in order of priority
**MUST HAVE*** **MUST HAVE***
* LIST CSR's with OPEN status only in reverse chronological order for service manager
* BAR/LINE Billed hours for all users available to service manager roles * BAR/LINE Billed hours for all users available to service manager roles
dupe of personal one but can select user or all users dupe of personal one but can select user or all users
criteria: criteria:
specific user or all users specific user or all users
timespan and interval timespan and interval
tags wo, woitem, USER tags also tags wo, woitem, USER tags also
BRING BACK USER COLOR? Or random assignment?
user color should be a thing I think
* 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) for current scheduleable user
criteria: criteria:
tags wo, woitem tags wo, woitem
@@ -890,3 +894,12 @@ BUILD 8.0.0-beta.1-rc3 CHANGES OF NOTE
- added dashboard widget "Reviews" available to all dashboardable users which shows today's Reviews - added dashboard widget "Reviews" available to all dashboardable users which shows today's Reviews
- added dashboard widget "Reminders" available to all dashboardable users which shows today's Reminders - added dashboard widget "Reminders" available to all dashboardable users which shows today's Reminders
================================================
204 new lady? 2022-03-01 11:20:10
or maybe she's moving out?
"I pay 917 here for a two bedroom."

View File

@@ -128,6 +128,54 @@ export default {
interval: "day", interval: "day",
color: "#00205B" color: "#00205B"
} }
},
{
roles: [
role.BizAdmin,
role.BizAdminRestricted,
role.ServiceRestricted,
role.Service,
role.Accounting
],
title: "DashboardServiceRateQuantityAllUsers",
icon: "$ayiChartLine",
type: "GzDashLaborHoursEveryoneLine",
scheduleableUserOnly: false,
singleOnly: false,
settings: {
customTitle: null,
timeSpan: "*thismonth*",
interval: "day",
wotags: [],
woitemtags: [],
techtags: [],
userid: null,
color: "#00205B"
}
},
{
roles: [
role.BizAdmin,
role.BizAdminRestricted,
role.ServiceRestricted,
role.Service,
role.Accounting
],
title: "DashboardServiceRateQuantityAllUsers",
icon: "$ayiChartBar",
type: "GzDashLaborHoursEveryoneBar",
scheduleableUserOnly: false,
singleOnly: false,
settings: {
customTitle: null,
timeSpan: "*thismonth*",
wotags: [],
woitemtags: [],
techtags: [],
userid: null,
interval: "day",
color: "#00205B"
}
} }
], ],
availableItems() { availableItems() {

View File

@@ -0,0 +1,356 @@
<template>
<gz-dash
icon="$ayiUser"
:show-context-button="true"
:update-frequency="900000"
v-bind="[$props, $attrs]"
@dash-refresh="getDataFromApi()"
@dash-context="showContext()"
v-on="$listeners"
>
<template slot="main">
<div>
<gz-chart-bar :chart-data="chartData" :options="chartOptions" />
</div>
</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>
<v-select
v-model="localSettings.timeSpan"
:items="selectLists.dateFilterTokens"
item-text="name"
item-value="id"
:label="$ay.t('TimeSpan')"
></v-select>
<v-select
v-model="localSettings.interval"
:items="selectLists.units"
item-text="name"
item-value="id"
:label="$ay.t('Interval')"
></v-select>
<gz-pick-list
v-model="localSettings.userid"
allow-no-selection
:aya-type="$ay.ayt().User"
variant="tech"
:label="$ay.t('WorkOrderItemLaborUserID')"
></gz-pick-list>
<gz-tag-picker
v-model="localSettings.techtags"
:label="$ay.t('Tags') + ' - ' + $ay.t('User')"
></gz-tag-picker>
<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-color-picker
v-model="localSettings.color"
hide-mode-switch
hide-inputs
mode="hexa"
></v-color-picker>
</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: {},
selectLists: {
dateFilterTokens: [],
units: []
},
chartOptions: {
responsive: true,
maintainAspectRatio: false,
scales: {
xAxes: [
{
type: "time",
time: {
unit: "day"
},
gridLines: {
drawOnChartArea: false
}
}
],
yAxes: [
{
gridLines: {
drawOnChartArea: false
},
ticks: {
beginAtZero: true
}
}
]
}
}
};
},
computed: {
chartData() {
return {
datasets: [
{
label: "usernamehere",
backgroundColor: this.settings.color ?? "#000000",
data: this.obj
}
]
};
}
},
async created() {
await initWidget(this);
},
async mounted() {
//must be called from mounted to have refs available
//console.log("reminders-mounted");
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.timeSpan = this.localSettings.timeSpan;
this.settings.interval = this.localSettings.interval;
this.settings.wotags = this.localSettings.wotags;
this.settings.woitemtags = this.localSettings.woitemtags;
this.settings.techtags = this.localSettings.techtags;
this.settings.userid = this.localSettings.userid;
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: "WorkOrderItemLaborQuantityEveryoneSummary",
criteria: {
timeSpan: this.settings.timeSpan,
interval: this.settings.interval,
wotags: this.settings.wotags,
woitemtags: this.settings.woitemtags,
techtags: this.settings.techtags,
userid: this.settings.userid
},
clientTimeStamp: window.$gz.locale.clientLocalZoneTimeStamp()
});
if (res.error) {
this.errorMessage = res.error;
} else {
this.chartOptions.scales.xAxes[0].time.unit = this.settings.interval;
res.data.forEach(z => {
z.x = new Date(z.x) //convert to locale timezone and output in the closest thing to iso-8601 format
.toLocaleString("sv-SE", {
timeZone: this.timeZoneName
});
});
this.obj = res.data;
}
} catch (error) {
this.errorMessage = error.toString();
}
}
}
};
/////////////////////////////////
//
//
async function initWidget(vm) {
await fetchTranslatedText();
populateSelectionLists(vm);
}
//////////////////////////////////////////////////////////
//
// Ensures UI translated text is available
//
async function fetchTranslatedText() {
await window.$gz.translation.cacheTranslations([
"Filter",
"DateRangeYesterday",
"DateRangeToday",
"DateRangeLastWeek",
"DateRangeThisWeek",
"DateRangeNextWeek",
"DateRangeLastMonth",
"DateRangeThisMonth",
"DateRangeNextMonth",
"DateRange14DayWindow",
"DateRangePast",
"DateRangeLastYear",
"DateRangeThisYear",
"DateRangeInTheLastThreeMonths",
"DateRangeInTheLastSixMonths",
"DateRangePastYear",
"DateRangePast90Days",
"DateRangePast30Days",
"DateRangePast7Days",
"DateRangePast24Hours",
"DateRangePast6Hours",
"DateRangeJanuary",
"DateRangeFebruary",
"DateRangeMarch",
"DateRangeApril",
"DateRangeMay",
"DateRangeJune",
"DateRangeJuly",
"DateRangeAugust",
"DateRangeSeptember",
"DateRangeOctober",
"DateRangeNovember",
"DateRangeDecember",
"DateRangePreviousYearThisMonth",
"DateRangePreviousYearLastMonth",
"DateRangePreviousYearNextMonth",
"TimeSpanDays",
"TimeSpanMonths",
"Name",
"TimeSpan",
"Interval",
"WorkOrder",
"WorkOrderItem",
"WorkOrderItemLaborUserID"
]);
}
/////////////////////////////////
//
//
function populateSelectionLists(vm) {
vm.selectLists.dateFilterTokens.push(
...[
// { name: vm.$ay.t("DateRangeYesterday"), id: "*yesterday*" },
// { name: vm.$ay.t("DateRangeToday"), id: "*today*" },
{ name: vm.$ay.t("DateRangeThisYear"), id: "*thisyear*" },
{ name: vm.$ay.t("DateRangeThisMonth"), id: "*thismonth*" },
{ name: vm.$ay.t("DateRangeThisWeek"), id: "*thisweek*" },
{ name: vm.$ay.t("DateRangeLastYear"), id: "*lastyear*" }, //prior year from jan to dec
{ name: vm.$ay.t("DateRangeLastMonth"), id: "*lastmonth*" },
{ name: vm.$ay.t("DateRangeLastWeek"), id: "*lastweek*" },
//-------------------------- rando ones -------------------
{ name: vm.$ay.t("DateRange14DayWindow"), id: "*14daywindow*" },
{ name: vm.$ay.t("DateRangePast"), id: "*past*" },
{
name: vm.$ay.t("DateRangeInTheLastThreeMonths"),
id: "*last3months*"
},
{
name: vm.$ay.t("DateRangeInTheLastSixMonths"),
id: "*last6months*"
},
{ name: vm.$ay.t("DateRangePastYear"), id: "*pastyear*" }, //last 365 days
{ name: vm.$ay.t("DateRangePast90Days"), id: "*past90days*" },
{ name: vm.$ay.t("DateRangePast30Days"), id: "*past30days*" },
{ name: vm.$ay.t("DateRangePast7Days"), id: "*past7days*" },
// { name: vm.$ay.t("DateRangePast24Hours"), id: "*past24hours*" },
// { name: vm.$ay.t("DateRangePast6Hours"), id: "*past6hours*" },
{ name: vm.$ay.t("DateRangeJanuary"), id: "*january*" },
{ name: vm.$ay.t("DateRangeFebruary"), id: "*february*" },
{ name: vm.$ay.t("DateRangeMarch"), id: "*march*" },
{ name: vm.$ay.t("DateRangeApril"), id: "*april*" },
{ name: vm.$ay.t("DateRangeMay"), id: "*may*" },
{ name: vm.$ay.t("DateRangeJune"), id: "*june*" },
{ name: vm.$ay.t("DateRangeJuly"), id: "*july*" },
{ name: vm.$ay.t("DateRangeAugust"), id: "*august*" },
{ name: vm.$ay.t("DateRangeSeptember"), id: "*september*" },
{ name: vm.$ay.t("DateRangeOctober"), id: "*october*" },
{ name: vm.$ay.t("DateRangeNovember"), id: "*november*" },
{ name: vm.$ay.t("DateRangeDecember"), id: "*december*" },
{
name: vm.$ay.t("DateRangePreviousYearThisMonth"),
id: "*lastyearthismonth*"
},
{
name: vm.$ay.t("DateRangePreviousYearLastMonth"),
id: "*lastyearlastmonth*"
},
{
name: vm.$ay.t("DateRangePreviousYearNextMonth"),
id: "*lastyearnextmonth*"
}
]
);
vm.selectLists.units.push(
...[
{ name: vm.$ay.t("TimeSpanDays"), id: "day" },
{
name: vm.$ay.t("TimeSpanMonths"),
id: "month"
}
]
);
}
</script>

View File

@@ -0,0 +1,366 @@
<template>
<gz-dash
icon="$ayiUser"
:show-context-button="true"
:update-frequency="900000"
v-bind="[$props, $attrs]"
@dash-refresh="getDataFromApi()"
@dash-context="showContext()"
v-on="$listeners"
>
<template slot="main">
<div>
<gz-chart-line
v-if="visible"
:chart-data="chartData"
:options="chartOptions"
/>
</div>
</template>
<template slot="settings">
<div></div>
<v-col v-if="context" cols="12">
<v-dialog
v-model="context"
scrollable
max-width="600px"
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>
<v-select
v-model="localSettings.timeSpan"
:items="selectLists.dateFilterTokens"
item-text="name"
item-value="id"
:label="$ay.t('TimeSpan')"
></v-select>
<v-select
v-model="localSettings.interval"
:items="selectLists.units"
item-text="name"
item-value="id"
:label="$ay.t('Interval')"
></v-select>
<gz-pick-list
v-model="localSettings.userid"
allow-no-selection
:aya-type="$ay.ayt().User"
variant="tech"
:label="$ay.t('WorkOrderItemLaborUserID')"
></gz-pick-list>
<gz-tag-picker
v-model="localSettings.techtags"
:label="$ay.t('Tags') + ' - ' + $ay.t('User')"
></gz-tag-picker>
<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-color-picker
v-model="localSettings.color"
hide-mode-switch
hide-inputs
mode="hexa"
></v-color-picker>
</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: {},
visible: true,
context: false,
localSettings: {},
selectLists: {
dateFilterTokens: [],
units: []
},
chartOptions: {
responsive: true,
maintainAspectRatio: false,
// legend: { display: false },
scales: {
xAxes: [
{
type: "time",
time: {
unit: "day"
},
gridLines: {
drawOnChartArea: false
}
}
],
yAxes: [
{
gridLines: {
drawOnChartArea: false
},
ticks: {
beginAtZero: true
}
}
]
}
}
};
},
computed: {
chartData() {
return {
datasets: [
{
label: "UserNameHere",
borderColor: this.settings.color ?? "#000000",
fill: false,
pointRadius: 2,
pointHoverRadius: 6,
pointHitRadius: 3,
data: this.obj
}
]
};
}
},
async created() {
await initWidget(this);
},
async mounted() {
//must be called from mounted to have refs available
//console.log("reminders-mounted");
await this.getDataFromApi();
},
methods: {
showContext: function() {
this.localSettings = window.$gz.util.deepCopySkip(this.settings);
this.context = true;
},
updateSettings: function() {
//copy settings from local to
this.settings.customTitle = this.localSettings.customTitle;
this.settings.timeSpan = this.localSettings.timeSpan;
this.settings.interval = this.localSettings.interval;
this.settings.wotags = this.localSettings.wotags;
this.settings.woitemtags = this.localSettings.woitemtags;
this.settings.techtags = this.localSettings.techtags;
this.settings.userid = this.localSettings.userid;
this.$emit("dash-change");
this.context = false;
this.getDataFromApi();
},
async getDataFromApi() {
try {
this.errorMessage = null;
const res = await window.$gz.api.post("kpi", {
KPIName: "WorkOrderItemLaborQuantityEveryoneSummary",
criteria: {
timeSpan: this.settings.timeSpan,
interval: this.settings.interval,
wotags: this.settings.wotags,
woitemtags: this.settings.woitemtags,
techtags: this.settings.techtags,
userid: this.settings.userid
},
clientTimeStamp: window.$gz.locale.clientLocalZoneTimeStamp()
});
if (res.error) {
this.errorMessage = res.error;
} else {
this.chartOptions.scales.xAxes[0].time.unit = this.settings.interval;
res.data.forEach(z => {
z.x = new Date(z.x) //convert to locale timezone and output in the closest thing to iso-8601 format
.toLocaleString("sv-SE", {
timeZone: this.timeZoneName
});
});
this.obj = res.data;
}
} catch (error) {
this.errorMessage = error.toString();
}
}
}
};
/////////////////////////////////
//
//
async function initWidget(vm) {
await fetchTranslatedText();
populateSelectionLists(vm);
}
//////////////////////////////////////////////////////////
//
// Ensures UI translated text is available
//
async function fetchTranslatedText() {
await window.$gz.translation.cacheTranslations([
"Filter",
"DateRangeYesterday",
"DateRangeToday",
"DateRangeLastWeek",
"DateRangeThisWeek",
"DateRangeNextWeek",
"DateRangeLastMonth",
"DateRangeThisMonth",
"DateRangeNextMonth",
"DateRange14DayWindow",
"DateRangePast",
"DateRangeLastYear",
"DateRangeThisYear",
"DateRangeInTheLastThreeMonths",
"DateRangeInTheLastSixMonths",
"DateRangePastYear",
"DateRangePast90Days",
"DateRangePast30Days",
"DateRangePast7Days",
"DateRangePast24Hours",
"DateRangePast6Hours",
"DateRangeJanuary",
"DateRangeFebruary",
"DateRangeMarch",
"DateRangeApril",
"DateRangeMay",
"DateRangeJune",
"DateRangeJuly",
"DateRangeAugust",
"DateRangeSeptember",
"DateRangeOctober",
"DateRangeNovember",
"DateRangeDecember",
"DateRangePreviousYearThisMonth",
"DateRangePreviousYearLastMonth",
"DateRangePreviousYearNextMonth",
"TimeSpanDays",
"TimeSpanMonths",
"Name",
"TimeSpan",
"Interval",
"WorkOrder",
"WorkOrderItem",
"WorkOrderItemLaborUserID"
]);
}
/////////////////////////////////
//
//
function populateSelectionLists(vm) {
vm.selectLists.dateFilterTokens.push(
...[
// { name: vm.$ay.t("DateRangeYesterday"), id: "*yesterday*" },
// { name: vm.$ay.t("DateRangeToday"), id: "*today*" },
{ name: vm.$ay.t("DateRangeThisYear"), id: "*thisyear*" },
{ name: vm.$ay.t("DateRangeThisMonth"), id: "*thismonth*" },
{ name: vm.$ay.t("DateRangeThisWeek"), id: "*thisweek*" },
{ name: vm.$ay.t("DateRangeLastYear"), id: "*lastyear*" }, //prior year from jan to dec
{ name: vm.$ay.t("DateRangeLastMonth"), id: "*lastmonth*" },
{ name: vm.$ay.t("DateRangeLastWeek"), id: "*lastweek*" },
//-------------------------- rando ones -------------------
{ name: vm.$ay.t("DateRange14DayWindow"), id: "*14daywindow*" },
{ name: vm.$ay.t("DateRangePast"), id: "*past*" },
{
name: vm.$ay.t("DateRangeInTheLastThreeMonths"),
id: "*last3months*"
},
{
name: vm.$ay.t("DateRangeInTheLastSixMonths"),
id: "*last6months*"
},
{ name: vm.$ay.t("DateRangePastYear"), id: "*pastyear*" }, //last 365 days
{ name: vm.$ay.t("DateRangePast90Days"), id: "*past90days*" },
{ name: vm.$ay.t("DateRangePast30Days"), id: "*past30days*" },
{ name: vm.$ay.t("DateRangePast7Days"), id: "*past7days*" },
// { name: vm.$ay.t("DateRangePast24Hours"), id: "*past24hours*" },
// { name: vm.$ay.t("DateRangePast6Hours"), id: "*past6hours*" },
{ name: vm.$ay.t("DateRangeJanuary"), id: "*january*" },
{ name: vm.$ay.t("DateRangeFebruary"), id: "*february*" },
{ name: vm.$ay.t("DateRangeMarch"), id: "*march*" },
{ name: vm.$ay.t("DateRangeApril"), id: "*april*" },
{ name: vm.$ay.t("DateRangeMay"), id: "*may*" },
{ name: vm.$ay.t("DateRangeJune"), id: "*june*" },
{ name: vm.$ay.t("DateRangeJuly"), id: "*july*" },
{ name: vm.$ay.t("DateRangeAugust"), id: "*august*" },
{ name: vm.$ay.t("DateRangeSeptember"), id: "*september*" },
{ name: vm.$ay.t("DateRangeOctober"), id: "*october*" },
{ name: vm.$ay.t("DateRangeNovember"), id: "*november*" },
{ name: vm.$ay.t("DateRangeDecember"), id: "*december*" },
{
name: vm.$ay.t("DateRangePreviousYearThisMonth"),
id: "*lastyearthismonth*"
},
{
name: vm.$ay.t("DateRangePreviousYearLastMonth"),
id: "*lastyearlastmonth*"
},
{
name: vm.$ay.t("DateRangePreviousYearNextMonth"),
id: "*lastyearnextmonth*"
}
]
);
vm.selectLists.units.push(
...[
{ name: vm.$ay.t("TimeSpanDays"), id: "day" },
{
name: vm.$ay.t("TimeSpanMonths"),
id: "month"
}
]
);
}
</script>

View File

@@ -223,12 +223,6 @@ async function initWidget(vm) {
async function fetchTranslatedText() { async function fetchTranslatedText() {
await window.$gz.translation.cacheTranslations([ await window.$gz.translation.cacheTranslations([
"Filter", "Filter",
"GridRowFilterDropDownBlanksItem",
"GridRowFilterDropDownNonBlanksItem",
"GridRowFilterDropDownEquals",
"GridRowFilterDropDownNotEquals",
"GridRowFilterDropDownDoesNotContain",
"GridRowFilterDropDownContains",
"DateRangeYesterday", "DateRangeYesterday",
"DateRangeToday", "DateRangeToday",
"DateRangeLastWeek", "DateRangeLastWeek",

View File

@@ -233,12 +233,6 @@ async function initWidget(vm) {
async function fetchTranslatedText() { async function fetchTranslatedText() {
await window.$gz.translation.cacheTranslations([ await window.$gz.translation.cacheTranslations([
"Filter", "Filter",
"GridRowFilterDropDownBlanksItem",
"GridRowFilterDropDownNonBlanksItem",
"GridRowFilterDropDownEquals",
"GridRowFilterDropDownNotEquals",
"GridRowFilterDropDownDoesNotContain",
"GridRowFilterDropDownContains",
"DateRangeYesterday", "DateRangeYesterday",
"DateRangeToday", "DateRangeToday",
"DateRangeLastWeek", "DateRangeLastWeek",