466 lines
13 KiB
Vue
466 lines
13 KiB
Vue
<template>
|
|
<div v-resize="onResize" class="my-n8">
|
|
<!-- {{ events }} -->
|
|
<gz-error :error-box-message="formState.errorBoxMessage"></gz-error>
|
|
<v-sheet height="64">
|
|
<v-toolbar flat>
|
|
<v-btn outlined class="mr-4" color="grey darken-2" @click="setToday">
|
|
{{ $ay.t("DateRangeToday") }}
|
|
</v-btn>
|
|
<v-btn fab text small color="grey darken-2" @click="prev">
|
|
<v-icon small>$prev</v-icon>
|
|
</v-btn>
|
|
<v-btn fab text small color="grey darken-2" @click="next">
|
|
<v-icon small>$next</v-icon>
|
|
</v-btn>
|
|
<v-toolbar-title v-if="$refs.calendar">
|
|
{{ $refs.calendar.title }}
|
|
</v-toolbar-title>
|
|
<v-spacer></v-spacer>
|
|
<v-btn
|
|
class="mr-3"
|
|
fab
|
|
text
|
|
small
|
|
color="grey darken-2"
|
|
@click="settingsDialog = true"
|
|
>
|
|
<v-icon small>$ayiCog</v-icon>
|
|
</v-btn>
|
|
|
|
<v-menu bottom right>
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<v-btn outlined color="grey darken-2" v-bind="attrs" v-on="on">
|
|
<span>{{ typeToLabel[viewType] }}</span>
|
|
<v-icon right>$sort</v-icon>
|
|
</v-btn>
|
|
</template>
|
|
<v-list>
|
|
<v-list-item @click="viewType = 'day'">
|
|
<v-list-item-title>Day</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item @click="viewType = 'week'">
|
|
<v-list-item-title>Week</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item @click="viewType = 'month'">
|
|
<v-list-item-title>Month</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item @click="viewType = '4day'">
|
|
<v-list-item-title>4 days</v-list-item-title>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-menu>
|
|
</v-toolbar>
|
|
</v-sheet>
|
|
<v-sheet :height="calendarHeight">
|
|
<v-calendar
|
|
ref="calendar"
|
|
v-model="focus"
|
|
color="primary"
|
|
:events="events"
|
|
:event-color="getEventColor"
|
|
:type="viewType"
|
|
:locale="languageName"
|
|
@click:event="showEvent"
|
|
@click:more="viewDay"
|
|
@click:date="viewDay"
|
|
@change="fetchEvents"
|
|
>
|
|
<template v-slot:event="{ event, eventSummary }">
|
|
<v-icon small :color="event.textColor" class="mr-1">{{
|
|
iconForEvent(event.type)
|
|
}}</v-icon>
|
|
<span :class="event.textColor + '--text'" v-html="eventSummary()" />
|
|
</template>
|
|
</v-calendar>
|
|
|
|
<v-menu
|
|
v-model="selectedOpen"
|
|
:close-on-content-click="false"
|
|
:activator="selectedElement"
|
|
offset-x
|
|
>
|
|
<v-card color="grey lighten-4" min-width="350px" flat>
|
|
<v-toolbar>
|
|
<v-btn icon @click="openScheduledItem()">
|
|
<v-icon>{{ iconForSelectedEvent() }}</v-icon>
|
|
</v-btn>
|
|
<v-toolbar-title>{{ selectedEvent.name }}</v-toolbar-title>
|
|
<v-spacer></v-spacer>
|
|
<!-- <v-btn icon>
|
|
<v-icon>$ayiBell</v-icon>
|
|
</v-btn>
|
|
<v-btn icon>
|
|
<v-icon>$ayiBoxes</v-icon>
|
|
</v-btn> -->
|
|
</v-toolbar>
|
|
<v-card-text>
|
|
{{ selectedEvent }}
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-btn text color="secondary" @click="selectedOpen = false">
|
|
Cancel
|
|
</v-btn>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</v-menu>
|
|
</v-sheet>
|
|
<template>
|
|
<v-row justify="center">
|
|
<v-dialog max-width="600px" v-model="settingsDialog">
|
|
<v-card>
|
|
<v-card-title> </v-card-title>
|
|
<v-card-text>
|
|
settings here
|
|
</v-card-text>
|
|
<v-card-actions>
|
|
<v-btn text @click="settingsDialog = false" color="primary">{{
|
|
$ay.t("Cancel")
|
|
}}</v-btn>
|
|
<v-spacer></v-spacer>
|
|
<v-btn
|
|
color="primary"
|
|
text
|
|
@click="acceptSettings()"
|
|
class="ml-4"
|
|
>{{ $ay.t("OK") }}</v-btn
|
|
>
|
|
</v-card-actions>
|
|
</v-card>
|
|
</v-dialog>
|
|
</v-row>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
/*
|
|
PLAN: TODO:
|
|
|
|
What shows in schedule:
|
|
Icon, start time abbreviated for month view, for other views it's start-stop abbreviated (I guess wider is assumed), name in single line most important to the left least to the right
|
|
WO appt. color is user selected from wopriority/woitempriority/woitemstatus color, wo icon in left corner is NOT colored, color on color sucks, let the person select it to see the more info display
|
|
Name=[wonumber customername]
|
|
Reviews are review icon, appt color - none
|
|
Reminders are reminder icon, appt. color is reminder selected color
|
|
|
|
More info
|
|
unlike v7, v8 doesn't attempt to show a lot of info in the calendar appt. display, instead they click on it to bring up a more info dialog with lots of useful info and a link to open the source record
|
|
|
|
Drag / drop / extend
|
|
will try to support this but if it's not doable then possibly for convenience do it in the More info dialog
|
|
|
|
|
|
SETTINGS:
|
|
wo display section:
|
|
DISPLAY
|
|
Color: wostatus/woitemstatus/woitempriority/none
|
|
Weekdays: weekdays to display, copy from pm exclude days thingy
|
|
|
|
|
|
TODO NEXT:
|
|
|
|
Summary info to display for woitem when open dialog
|
|
settings / saving as form settings
|
|
use translations where possible
|
|
reporting?! fuck!
|
|
|
|
|
|
|
|
*/
|
|
|
|
const FORM_CUSTOM_TEMPLATE_KEY = "home-schedule";
|
|
const FORM_KEY = "home-schedule";
|
|
export default {
|
|
async created() {
|
|
let vm = this;
|
|
|
|
try {
|
|
await initForm(vm);
|
|
window.$gz.eventBus.$on("menu-click", clickHandler);
|
|
//----------------------------
|
|
generateMenu(vm);
|
|
} catch (error) {
|
|
window.$gz.errorHandler.handleFormError(error, vm);
|
|
}
|
|
},
|
|
beforeDestroy() {
|
|
window.$gz.eventBus.$off("menu-click", clickHandler);
|
|
},
|
|
data() {
|
|
return {
|
|
formCustomTemplateKey: FORM_CUSTOM_TEMPLATE_KEY,
|
|
focus: "",
|
|
viewType: "month",
|
|
typeToLabel: {
|
|
month: "Month",
|
|
week: "Week",
|
|
day: "Day",
|
|
"4day": "4 Days"
|
|
},
|
|
selectedEvent: {},
|
|
selectedElement: null,
|
|
selectedOpen: false,
|
|
events: [],
|
|
|
|
formState: {
|
|
ready: false,
|
|
dirty: false,
|
|
valid: true,
|
|
readOnly: false,
|
|
loading: true,
|
|
errorBoxMessage: null,
|
|
appError: null,
|
|
serverError: {}
|
|
},
|
|
rights: window.$gz.role.defaultRightsObject(),
|
|
calendarHeight: 600,
|
|
settingsDialog: false,
|
|
timeZoneName: window.$gz.locale.getResolvedTimeZoneName(),
|
|
languageName: window.$gz.locale.getResolvedLanguage(),
|
|
hour12: window.$gz.locale.getHour12()
|
|
};
|
|
},
|
|
mounted() {
|
|
this.$refs.calendar.checkChange();
|
|
},
|
|
methods: {
|
|
onResize() {
|
|
this.calendarHeight = window.innerHeight * 0.84;
|
|
},
|
|
viewDay({ date }) {
|
|
this.focus = date;
|
|
this.viewType = "day";
|
|
},
|
|
getEventColor(event) {
|
|
return event.color;
|
|
},
|
|
setToday() {
|
|
this.focus = "";
|
|
},
|
|
prev() {
|
|
this.$refs.calendar.prev();
|
|
},
|
|
next() {
|
|
this.$refs.calendar.next();
|
|
},
|
|
iconForSelectedEvent() {
|
|
return window.$gz.util.iconForType(this.selectedEvent.type);
|
|
},
|
|
iconForEvent(type) {
|
|
return window.$gz.util.iconForType(type);
|
|
},
|
|
openScheduledItem() {
|
|
window.$gz.eventBus.$emit("openobject", {
|
|
type: this.selectedEvent.type,
|
|
id: this.selectedEvent.id
|
|
});
|
|
},
|
|
showEvent({ nativeEvent, event }) {
|
|
const open = () => {
|
|
this.selectedEvent = event;
|
|
this.selectedElement = nativeEvent.target;
|
|
requestAnimationFrame(() =>
|
|
requestAnimationFrame(() => (this.selectedOpen = true))
|
|
);
|
|
};
|
|
|
|
if (this.selectedOpen) {
|
|
this.selectedOpen = false;
|
|
requestAnimationFrame(() => requestAnimationFrame(() => open()));
|
|
} else {
|
|
open();
|
|
}
|
|
|
|
nativeEvent.stopPropagation();
|
|
},
|
|
async fetchEvents({ start, end }) {
|
|
// console.log(
|
|
// "UPDATE RANGE:",
|
|
// JSON.stringify({ start: start.date, end: end.date })
|
|
// );
|
|
|
|
// console.log(
|
|
// "TZ Offset",
|
|
// window.$gz.locale.getTZOffset(this.timeZoneName)
|
|
// );
|
|
/*
|
|
public enum PersonalScheduleWorkOrderColorSource : int
|
|
{
|
|
None = 0,
|
|
WorkOrderStatus = 2,
|
|
WorkOrderItemStatus = 3,
|
|
WorkOrderItemPriority = 4
|
|
}
|
|
|
|
*/
|
|
|
|
try {
|
|
window.$gz.form.deleteAllErrorBoxErrors(this);
|
|
|
|
let res = await window.$gz.api.post("schedule/personal", {
|
|
view: window.$gz.util.calendarViewToAyaNovaEnum(this.viewType),
|
|
tzOffset: window.$gz.locale.getTZOffset(this.timeZoneName),
|
|
start: window.$gz.locale.localTimeDateStringToUTC8601String(
|
|
`${start.date}T00:00:00`,
|
|
this.timeZoneName
|
|
),
|
|
end: window.$gz.locale.localTimeDateStringToUTC8601String(
|
|
`${end.date}T23:59:59`,
|
|
this.timeZoneName
|
|
),
|
|
colorSource: 4,
|
|
workOrders: true,
|
|
reviews: true,
|
|
reminders: true
|
|
});
|
|
|
|
if (res.error) {
|
|
this.formState.serverError = res.error;
|
|
window.$gz.form.setErrorBoxErrors(this);
|
|
} else {
|
|
this.events = res.data;
|
|
}
|
|
} catch (error) {
|
|
window.$gz.errorHandler.handleFormError(error, this);
|
|
}
|
|
}
|
|
//eom
|
|
}
|
|
};
|
|
|
|
/////////////////////////////
|
|
//
|
|
//
|
|
async function clickHandler(menuItem) {
|
|
if (!menuItem) {
|
|
return;
|
|
}
|
|
let m = window.$gz.menu.parseMenuItem(menuItem);
|
|
if (m.owner == FORM_KEY && !m.disabled) {
|
|
switch (m.key) {
|
|
// case "report":
|
|
// let res = await m.vm.$refs.reportSelector.open(
|
|
// {
|
|
// AType: window.$gz.type.Project,
|
|
// selectedRowIds: [m.vm.obj.id]
|
|
// },
|
|
// m.id
|
|
// );
|
|
// if (res == null) {
|
|
// return;
|
|
// }
|
|
// window.$gz.form.setLastReport(FORM_KEY, res);
|
|
// generateMenu(m.vm);
|
|
// 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
|
|
}
|
|
});
|
|
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
|
|
}
|
|
});
|
|
break;
|
|
|
|
default:
|
|
window.$gz.eventBus.$emit(
|
|
"notify-warning",
|
|
FORM_KEY + "::context click: [" + m.key + "]"
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////
|
|
//
|
|
//
|
|
function generateMenu(vm) {
|
|
let menuOptions = {
|
|
isMain: true,
|
|
readOnly: vm.formState.readOnly,
|
|
icon: "$ayiCalendarDay",
|
|
title: "Schedule",
|
|
helpUrl: "home-schedule",
|
|
menuItems: []
|
|
};
|
|
|
|
// //REPORTS
|
|
// //Report not Print, print is a further option
|
|
// menuOptions.menuItems.push({
|
|
// title: "Report",
|
|
// icon: "$ayiFileAlt",
|
|
// key: FORM_KEY + ":report",
|
|
// vm: vm
|
|
// });
|
|
|
|
// //get last report selected
|
|
// let lastReport = window.$gz.form.getLastReport(FORM_KEY);
|
|
// if (lastReport != null) {
|
|
// menuOptions.menuItems.push({
|
|
// title: lastReport.name,
|
|
// notrans: true,
|
|
// icon: "$ayiFileAlt",
|
|
// key: FORM_KEY + ":report:" + lastReport.id,
|
|
// vm: vm
|
|
// });
|
|
// }
|
|
|
|
// if (vm.rights.change) {
|
|
// menuOptions.menuItems.push({
|
|
// title: "New",
|
|
// icon: "$ayiPlus",
|
|
// key: FORM_KEY + ":new",
|
|
// vm: vm
|
|
// });
|
|
// }
|
|
|
|
if (vm.$store.getters.isScheduleableUser) {
|
|
menuOptions.menuItems.push({ divider: true, inset: false });
|
|
|
|
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
|
|
});
|
|
//--- /show all ---
|
|
}
|
|
menuOptions.menuItems.push({ divider: true, inset: false });
|
|
|
|
window.$gz.eventBus.$emit("menu-change", menuOptions);
|
|
}
|
|
|
|
/////////////////////////////////
|
|
//
|
|
//
|
|
async function initForm(vm) {
|
|
await fetchTranslatedText(vm);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////
|
|
//
|
|
// Ensures UI translated text is available
|
|
//
|
|
async function fetchTranslatedText(vm) {
|
|
await window.$gz.translation.cacheTranslations(["DateRangeToday"]);
|
|
}
|
|
</script>
|