Files
raven-client/ayanova/src/views/home-dashboard.vue
2022-03-03 19:25:18 +00:00

423 lines
12 KiB
Vue

<template>
<div class="my-n8">
<v-row v-if="formState.ready">
<gz-error :error-box-message="formState.errorBoxMessage"></gz-error>
<v-col v-if="showSelector" cols="12">
<v-dialog
v-model="showSelector"
scrollable
max-width="600px"
data-cy="dashSelector"
@keydown.esc="cancel"
>
<v-card elevation="24">
<v-card-title class="text-h5 lighten-2" primary-title>
<span> {{ $ay.t("Add") }} </span>
</v-card-title>
<v-card-text style="height: 500px;">
<v-list>
<v-list-item
v-for="item in availableItems()"
:key="item.id"
@click="addItem(item)"
>
<v-list-item-icon
><v-icon>{{ item.icon }}</v-icon></v-list-item-icon
>
<v-list-item-title>{{ $ay.t(item.title) }}</v-list-item-title>
</v-list-item>
</v-list>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-btn
color="primary"
text
data-cy="dashSelector:cancel"
@click.native="showSelector = false"
>{{ $ay.t("Cancel") }}</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-col>
</v-row>
<v-row>
<v-col
v-for="item in effectiveView"
:key="item.id"
class="d-flex child-flex"
cols="12"
sm="6"
lg="4"
>
<component
:is="item.type"
v-bind="item"
:max-list-items="10"
@dash-remove="dashRemove"
@dash-move-start="dashMoveStart"
@dash-move-back="dashMoveBack"
@dash-move-forward="dashMoveForward"
@dash-move-end="dashMoveEnd"
@dash-change="dashSaveSettings"
>
</component>
</v-col>
<v-col cols="12">
<v-btn
v-if="formState.ready"
text
@click.native="showSelector = true"
>{{ $ay.t("Add") }}</v-btn
>
</v-col>
</v-row>
</div>
</template>
<script>
const FORM_KEY = "home-dashboard";
import DashRegistry from "../api/dash-registry";
//---------- DASH ITEMS ----------
import GzDashTodayScheduledWo from "../components/dash-today-scheduled-wo.vue";
import GzDashTodayReminders from "../components/dash-today-reminders.vue";
import GzDashTodayReviews from "../components/dash-today-reviews.vue";
import GzDashLaborHoursPersonalLine from "../components/dash-labor-hours-personal-line.vue";
import GzDashLaborHoursPersonalBar from "../components/dash-labor-hours-personal-bar.vue";
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.vue";
import GzDashWorkorderOverduePersonalList from "../components/dash-workorder-overdue-personal-list.vue";
import GzDashWorkorderOverdueAllList from "../components/dash-workorder-overdue-all-list.vue";
import GzDashWorkOrderCreatedCountLine from "../components/dash-work-order-created-count-line.vue";
import GzDashWorkOrderCreatedCountBar from "../components/dash-work-order-created-count-bar.vue";
import GzDashPctWorkOrderCompletedOnTimeBar from "../components/dash-work-order-completed-on-time-pct-bar.vue";
import GzDashWorkOrderStatusCount from "../components/dash-work-order-status-count-bar.vue";
import GzDashWorkOrderStatusPct from "../components/dash-work-order-status-pct-bar.vue";
import GzDashWorkorderByStatusList from "../components/dash-workorder-by-status-list.vue";
export default {
components: {
GzDashLaborHoursPersonalLine,
GzDashLaborHoursPersonalBar,
GzDashTodayScheduledWo,
GzDashTodayReminders,
GzDashTodayReviews,
GzDashWorkorderUnscheduledOpenList,
GzDashCSROpenList,
GzDashLaborHoursEveryoneLine,
GzDashLaborHoursEveryoneBar,
GzDashWorkorderOverduePersonalList,
GzDashWorkorderOverdueAllList,
GzDashWorkOrderCreatedCountLine,
GzDashWorkOrderCreatedCountBar,
GzDashPctWorkOrderCompletedOnTimeBar,
GzDashWorkOrderStatusCount,
GzDashWorkOrderStatusPct,
GzDashWorkorderByStatusList
},
data() {
return {
effectiveView: [],
showSelector: false,
formState: {
ready: false,
dirty: false,
valid: true,
readOnly: false,
loading: true,
errorBoxMessage: null,
appError: null,
serverError: {}
}
};
},
beforeCreate() {
window.$gz.eventBus.$emit("menu-change", {
isMain: true,
icon: "$ayiTachometer",
title: "Dashboard",
helpUrl: "home-dashboard"
});
},
async created() {
const vm = this;
try {
await DashRegistry.cacheTranslationsForAvailableItems();
//users have full rights to their dashboard config
vm.rights = window.$gz.role.fullRightsObject();
vm.formState.readOnly = false;
window.$gz.eventBus.$on("menu-click", clickHandler);
await vm.getDataFromApi();
window.$gz.form.setFormState({
vm: vm,
dirty: false,
valid: true
});
generateMenu(vm);
} catch (error) {
window.$gz.errorHandler.handleFormError(error, vm);
} finally {
vm.formState.ready = true;
}
},
methods: {
dashSaveSettings: function() {
this.saveView();
},
dashMoveStart: function(id) {
this.move("start", id);
},
dashMoveBack: function(id) {
this.move("left", id);
},
dashMoveForward: function(id) {
this.move("right", id);
},
dashMoveEnd: function(id) {
this.move("end", id);
},
dashRemove: function(id) {
const index = this.getEffectiveViewItemIndexById(id);
if (index == -1) {
return;
}
this.effectiveView.splice(index, 1);
this.saveView();
},
move: function(direction, id) {
const index = this.getEffectiveViewItemIndexById(id);
if (index == -1) {
return;
}
const totalItems = this.effectiveView.length;
let newIndex = 0;
//calculate new index
switch (direction) {
case "start":
newIndex = 0;
break;
case "left":
newIndex = index - 1;
if (newIndex < 0) {
newIndex = 0;
}
break;
case "right":
newIndex = index + 1;
if (newIndex > totalItems - 1) {
newIndex = totalItems - 1;
}
break;
case "end":
newIndex = totalItems - 1;
break;
}
this.effectiveView.splice(
newIndex,
0,
this.effectiveView.splice(index, 1)[0]
);
this.saveView();
},
getEffectiveViewItemIndexById: function(id) {
return this.effectiveView.findIndex(z => z.id == id);
},
addItem: function(item) {
this.showSelector = false;
const newItem = JSON.parse(JSON.stringify(item));
newItem.id = Date.now();
this.effectiveView.push(newItem);
this.saveView();
},
availableItems: function() {
const allItems = DashRegistry.availableItems();
// console.log("availableItems:allItems", JSON.stringify(allItems));
// console.log(
// "availableItems:effectiveView",
// JSON.stringify(this.effectiveView)
// );
const ret = [];
allItems.forEach(z => {
if (!z.singleOnly) {
ret.push(z);
} else {
if (this.effectiveView.findIndex(m => m.type == z.type) == -1) {
ret.push(z);
}
}
});
// console.log("availableItems:ret", JSON.stringify(ret));
return ret;
},
async getDataFromApi() {
const vm = this;
window.$gz.form.setFormState({
vm: vm,
loading: true
});
try {
window.$gz.form.deleteAllErrorBoxErrors(vm);
const res = await window.$gz.api.get("dashboard-view");
if (res.error) {
if (res.error.code == "2010") {
window.$gz.form.handleObjectNotFound(vm);
}
vm.formState.serverError = res.error;
window.$gz.form.setErrorBoxErrors(vm);
} else {
const savedView = JSON.parse(res.data.view);
const availableItems = DashRegistry.availableItems();
//filter out any that are deprecated or no longer accessible due to role change
const allowedView = savedView.filter(z =>
availableItems.find(m => m.type == z.type)
);
vm.effectiveView = allowedView;
generateMenu(vm);
window.$gz.form.setFormState({
vm: vm,
dirty: false,
valid: true,
loading: false
});
}
} catch (error) {
window.$gz.errorHandler.handleFormError(error, vm);
} finally {
window.$gz.form.setFormState({
vm: vm,
loading: false
});
}
},
async saveView() {
const vm = this;
if (vm.canSave == false) {
return;
}
try {
window.$gz.form.setFormState({
vm: vm,
loading: true
});
window.$gz.form.deleteAllErrorBoxErrors(vm);
const res = await window.$gz.api.put(
"dashboard-view",
JSON.stringify(vm.effectiveView)
);
if (res.error) {
vm.formState.serverError = res.error;
window.$gz.form.setErrorBoxErrors(vm);
} else {
window.$gz.form.setFormState({
vm: vm,
dirty: false,
valid: true
});
}
} catch (ex) {
window.$gz.errorHandler.handleFormError(ex, vm);
} finally {
window.$gz.form.setFormState({
vm: vm,
loading: false
});
}
}
}
};
/////////////////////////////
//
//
async function clickHandler(menuItem) {
if (!menuItem) {
return;
}
const m = window.$gz.menu.parseMenuItem(menuItem);
if (m.owner == FORM_KEY && !m.disabled) {
switch (m.key) {
case "add-dash":
m.vm.showSelector = true;
break;
case "WorkOrderItemScheduledUserList":
m.vm.$router
.push({
name: "svc-workorder-item-scheduled-users",
params: {
aType: window.$gz.type.User,
objectId: m.vm.$store.state.userId,
name: m.vm.$store.state.userName
}
})
.catch(() => {});
break;
case "WorkOrderItemLaborList":
m.vm.$router
.push({
name: "svc-workorder-item-labors",
params: {
aType: window.$gz.type.User,
objectId: m.vm.$store.state.userId,
name: m.vm.$store.state.userName
}
})
.catch(() => {});
break;
default:
window.$gz.eventBus.$emit(
"notify-warning",
FORM_KEY + "::context click: [" + m.key + "]"
);
}
}
}
//////////////////////
//
//
function generateMenu(vm) {
const menuOptions = {
isMain: true,
icon: "$ayiTachometer",
title: "Dashboard",
helpUrl: "home-dashboard",
menuItems: []
};
menuOptions.menuItems.push({
title: "Add",
icon: "$ayiPlus",
key: FORM_KEY + ":add-dash",
vm: vm
});
menuOptions.menuItems.push({ divider: true, inset: false });
if (vm.$store.getters.isScheduleableUser) {
menuOptions.menuItems.push({
title: "WorkOrderItemScheduledUserList",
icon: "$ayiUserClock",
key: FORM_KEY + ":WorkOrderItemScheduledUserList",
vm: vm
});
menuOptions.menuItems.push({
title: "WorkOrderItemLaborList",
icon: "$ayiHammer",
key: FORM_KEY + ":WorkOrderItemLaborList",
vm: vm
});
}
window.$gz.eventBus.$emit("menu-change", menuOptions);
}
</script>