312 lines
10 KiB
Vue
312 lines
10 KiB
Vue
<template>
|
|
<div v-if="pvm != null">
|
|
<!-- Title and menu -->
|
|
<v-col cols="12">
|
|
<v-menu offset-y>
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<div class="text-h6">
|
|
<v-icon large color="primary">$ayiWrench</v-icon>
|
|
{{ $ay.t("WorkOrderItemList") }}
|
|
<v-btn large icon v-bind="attrs" v-on="on">
|
|
<v-icon small color="primary">$ayiEllipsisV</v-icon>
|
|
</v-btn>
|
|
</div>
|
|
</template>
|
|
<v-list>
|
|
<v-list-item v-if="canAdd" @click="newItem">
|
|
<v-list-item-icon>
|
|
<v-icon>$ayiPlus</v-icon>
|
|
</v-list-item-icon>
|
|
<v-list-item-title>{{ $ay.t("New") }}</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item v-if="canDelete" @click="deleteItem">
|
|
<v-list-item-icon>
|
|
<v-icon>$ayiTrashAlt</v-icon>
|
|
</v-list-item-icon>
|
|
<v-list-item-title>{{ $ay.t("Delete") }}</v-list-item-title>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-menu>
|
|
</v-col>
|
|
|
|
<!-- items:{{ value.items }}<br />
|
|
<span class="text-caption"
|
|
>[selected index: {{ pvm.selectedItemIndex }}]</span
|
|
>-->
|
|
<template v-if="pvm.woItemCount > 1">
|
|
<!-- ################################ WORK ORDER ITEMS TABLE ############################### -->
|
|
<v-col cols="12">
|
|
<v-data-table
|
|
:headers="headerList"
|
|
:items="itemList"
|
|
item-key="index"
|
|
v-model="selectedRow"
|
|
class="elevation-1"
|
|
disable-pagination
|
|
disable-filtering
|
|
disable-sort
|
|
hide-default-footer
|
|
data-cy="itemsTable"
|
|
dense
|
|
:item-class="itemRowClasses"
|
|
@click:row="selectItem"
|
|
:show-select="$vuetify.breakpoint.xs"
|
|
single-select
|
|
>
|
|
<!-- <template v-slot:[`item.actions`]="{ item }">
|
|
<v-btn icon @click="selectItem(item)">
|
|
<v-icon :class="itemRowClasses(item)">
|
|
$ayiEdit
|
|
</v-icon>
|
|
</v-btn>
|
|
</template> -->
|
|
</v-data-table>
|
|
</v-col>
|
|
</template>
|
|
<template v-if="pvm.hasSelectedWoItem">
|
|
<v-col v-if="form().showMe(this, 'TechNotes')" cols="12">
|
|
<v-textarea
|
|
v-model="value.items[pvm.selectedItemIndex].techNotes"
|
|
:readonly="formState.readOnly"
|
|
:label="$ay.t('WorkOrderItemTechNotes')"
|
|
:error-messages="form().serverErrors(this, 'notes')"
|
|
ref="notes"
|
|
data-cy="notes"
|
|
@input="fieldValueChanged('notes')"
|
|
auto-grow
|
|
></v-textarea>
|
|
</v-col>
|
|
|
|
<GzWoItemScheduledUsers
|
|
v-if="pvm.subRights.scheduledUsers.visible"
|
|
v-model="value"
|
|
:pvm="pvm"
|
|
data-cy="woItemScheduledUsers"
|
|
/>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/* XXXeslint-disable */
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
import GzWoItemScheduledUsers from "../components/work-order-item-scheduled-users.vue";
|
|
/*
|
|
todo: can I turn control labels into hyperlinks for getting to feeder records? If not then need to find a way to accomplish it
|
|
e.g. can workorder status title be changed to a hyper link to status list
|
|
e.g. can projects title be turned to a hyper link to projects list
|
|
ideally not in menu because it would be a lot on a workorder and need space for wo graph subitem links
|
|
todo: need an editable control at every level for proper test of partial update
|
|
todo: highlight currently selected row, mobile and full
|
|
todo: failed saved on a grandchild item shouldn't preclude the rest saving
|
|
e.g. if there is a concurrency error on a child that shouldn't block the rest but a fatal error probably should
|
|
todo: do we need a dirty indicator at every level??
|
|
*/
|
|
export default {
|
|
components: {
|
|
GzWoItemScheduledUsers
|
|
},
|
|
data() {
|
|
return { selectedRow: [] };
|
|
},
|
|
props: {
|
|
value: {
|
|
default: null,
|
|
type: Object
|
|
},
|
|
pvm: {
|
|
default: null,
|
|
type: Object
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
newItem() {
|
|
this.pvm.selectItem(
|
|
this.value.items.push({
|
|
id: 0,
|
|
concurrency: 0,
|
|
notes: null,
|
|
wiki: null,
|
|
customFields: "{}",
|
|
tags: [],
|
|
workOrderId: this.value.id,
|
|
techNotes: null,
|
|
workorderItemStatusId: null,
|
|
workorderItemPriorityId: null,
|
|
requestDate: null,
|
|
warrantyService: false,
|
|
isDirty: true,
|
|
expenses: [],
|
|
labors: [],
|
|
loans: [],
|
|
parts: [],
|
|
partRequests: [],
|
|
scheduledUsers: [],
|
|
tasks: [],
|
|
travels: [],
|
|
units: [],
|
|
outsideServices: []
|
|
}) - 1
|
|
);
|
|
},
|
|
async deleteItem() {
|
|
if ((await window.$gz.dialog.confirmDelete()) != true) {
|
|
return;
|
|
}
|
|
this.value.items.splice(this.pvm.selectedItemIndex, 1);
|
|
this.pvm.selectIndex(null); //select nothing in essence resetting a child selects and this one too clearing form
|
|
|
|
// if (this.value.items.length > 0) {
|
|
// this.pvm.selectedItemIndex = this.value.items.length - 1;
|
|
// } else {
|
|
// this.pvm.selectedItemIndex = null;
|
|
// }
|
|
},
|
|
selectItem: function(item) {
|
|
this.selectedRow = [item];
|
|
this.pvm.selectedItemIndex = item.index;
|
|
},
|
|
form() {
|
|
return window.$gz.form;
|
|
},
|
|
fieldValueChanged(ref) {
|
|
if (!this.formState.loading && !this.formState.readonly) {
|
|
//flag this record dirty so it gets picked up by save
|
|
this.value.items[this.pvm.selectedItemIndex].isDirty = true;
|
|
window.$gz.form.fieldValueChanged(this.pvm, ref);
|
|
}
|
|
},
|
|
itemRowClasses: function(item) {
|
|
if (this.form().childRowHasError(this, "Items", item.index)) {
|
|
return "font-weight-black font-italic error--text";
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
headerList: function() {
|
|
/*
|
|
public uint Concurrency { get; set; }
|
|
public string Notes { get; set; }//Was Summary
|
|
public string Wiki { get; set; }
|
|
public string CustomFields { get; set; }
|
|
public List<string> Tags { get; set; } = new List<string>();
|
|
|
|
[Required]
|
|
public long WorkOrderId { get; set; }
|
|
public string TechNotes { get; set; }
|
|
public long? WorkorderItemStatusId { get; set; }
|
|
public long? WorkorderItemPriorityId { get; set; }
|
|
public DateTime RequestDate { get; set; }
|
|
public bool WarrantyService { get; set; } = false;
|
|
|
|
|
|
IN ORDER: notes, status, date, priority, warranty, tags
|
|
|
|
except they will not prefill at server but will be set here since the wo differs from the po in that there is no instant update with new viz fields to populate from server
|
|
and it's probably not a big list to fill anyway
|
|
|
|
|
|
If the column is a text, left-align it
|
|
If the column is a number or number + unit, (or date) right-align it (like excel)
|
|
*/
|
|
let headers = [];
|
|
|
|
headers.push({
|
|
text: this.$ay.t("WorkOrderItemSummary"), //mandatory not hidden
|
|
align: "left",
|
|
value: "notes"
|
|
});
|
|
|
|
if (this.form().showMe(this, "Items.WorkOrderItemWorkOrderStatusID")) {
|
|
headers.push({
|
|
text: this.$ay.t("WorkOrderItemWorkOrderStatusID"),
|
|
align: "left",
|
|
value: "status"
|
|
});
|
|
}
|
|
|
|
if (this.form().showMe(this, "Items.RequestDate")) {
|
|
headers.push({
|
|
text: this.$ay.t("WorkOrderItemRequestDate"),
|
|
align: "right",
|
|
value: "requestDate"
|
|
});
|
|
}
|
|
|
|
if (this.form().showMe(this, "Items.WorkOrderItemPriorityID")) {
|
|
headers.push({
|
|
text: this.$ay.t("WorkOrderItemPriorityID"),
|
|
align: "left",
|
|
value: "priority"
|
|
});
|
|
}
|
|
|
|
if (this.form().showMe(this, "Items.WorkOrderItemWarrantyService")) {
|
|
headers.push({
|
|
text: this.$ay.t("WorkOrderItemWarrantyService"),
|
|
align: "center",
|
|
value: "warranty"
|
|
});
|
|
}
|
|
|
|
if (this.form().showMe(this, "Items.Tags")) {
|
|
headers.push({
|
|
text: this.$ay.t("Tags"),
|
|
align: "left",
|
|
value: "tags"
|
|
});
|
|
}
|
|
|
|
// headers.push({ text: "", value: "actions" });
|
|
|
|
return headers;
|
|
},
|
|
itemList: function() {
|
|
return this.value.items.map((x, i) => {
|
|
return {
|
|
index: i,
|
|
id: x.id,
|
|
notes: x.notes,
|
|
quantityReceived: window.$gz.locale.decimalLocalized(
|
|
x.quantityReceived,
|
|
this.pvm.languageName
|
|
),
|
|
status: x.workorderItemStatusId, //todo: get real status name etc here
|
|
requestDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
|
x.requestDate,
|
|
this.pvm.timeZoneName,
|
|
this.pvm.languageName,
|
|
this.pvm.hour12
|
|
),
|
|
priority: x.workorderItemPriorityId, //todo: get actual priority, color etc here
|
|
warranty: x.warrantyService,
|
|
tags: x.tags
|
|
};
|
|
});
|
|
},
|
|
formState: function() {
|
|
return this.pvm.formState;
|
|
},
|
|
formCustomTemplateKey: function() {
|
|
return this.pvm.formCustomTemplateKey;
|
|
},
|
|
canAdd: function() {
|
|
return (
|
|
!this.value.isLockedAtServer &&
|
|
this.pvm.rights.change &&
|
|
this.pvm.subRights.items.create
|
|
);
|
|
},
|
|
canDelete: function() {
|
|
return (
|
|
this.pvm.hasSelectedWoItem &&
|
|
!this.value.isLockedAtServer &&
|
|
this.pvm.rights.change &&
|
|
this.pvm.subRights.items.delete
|
|
);
|
|
}
|
|
}
|
|
};
|
|
</script>
|