Files
raven-client/ayanova/src/components/work-order-state.vue
2022-11-03 20:48:08 +00:00

305 lines
9.9 KiB
Vue

<template>
<div>
<div class="mb-n2 ml-10">
<span class="text-caption">{{ $ay.t("WorkOrderStatus") }}</span>
</div>
<template>
<div
class="mb-6 mb-sm-0"
:data-cy="`${dataCy}:open`"
@click="openDialog = true"
>
<v-btn icon class="ml-n1 mr-2">
<v-icon>{{ openIcon() }}</v-icon>
</v-btn>
<span class="text-h6">{{ pvm.currentState.name }}</span>
<v-icon :color="pvm.currentState.color" class="ml-4">$ayiFlag</v-icon>
<v-icon v-if="pvm.currentState.locked" color="primary" class="ml-4"
>$ayiLock</v-icon
>
<v-icon v-if="pvm.currentState.completed" color="primary" class="ml-4"
>$ayiCheckCircle</v-icon
>
</div>
</template>
<v-row dense justify="center">
<v-dialog v-model="openDialog" max-width="600px">
<v-card>
<v-card-title>
<span class="text-h5">{{ $ay.t("WorkOrderStatus") }}</span>
</v-card-title>
<v-card-text>
<template v-if="$vuetify.breakpoint.smAndUp">
<!-- WIDE VIEW -->
<div v-for="item in stateDisplayList" :key="item.id">
<span>{{ item.timeStamp }}</span>
<span class="ml-3">{{ item.user }}</span>
<span class="font-weight-bold ml-3">{{ item.name }}</span>
<v-icon small :color="item.color" class="ml-4">$ayiFlag</v-icon>
<v-icon v-if="item.locked" small color="primary" class="ml-4"
>$ayiLock</v-icon
>
<v-icon v-if="item.completed" small color="primary" class="ml-4"
>$ayiCheckCircle</v-icon
>
</div>
</template>
<template v-else>
<!-- NARROW VIEW -->
<div v-for="item in stateDisplayList" :key="item.id">
<span>{{ item.timeStamp }}&nbsp;</span>
<span>{{ item.user }}</span>
<div class="mb-2">
<span class="font-weight-bold">{{ item.name }}</span>
<v-icon small :color="item.color" class="ml-4"
>$ayiFlag</v-icon
>
<v-icon v-if="item.locked" small color="primary" class="ml-4"
>$ayiLock</v-icon
>
<v-icon
v-if="item.completed"
small
color="primary"
class="ml-4"
>$ayiCheckCircle</v-icon
>
</div>
</div>
</template>
<template v-if="canAdd">
<div class="mt-8">
<v-autocomplete
v-model="selectedStatus"
:items="pvm.selectLists.allowedwostatus"
item-text="name"
item-value="id"
dense
:label="$ay.t('NewStatus')"
prepend-icon="$ayiEdit"
:data-cy="`${dataCy}:picker`"
@click:prepend="handleEditStateClick()"
>
<template v-slot:item="data">
<v-list-item-avatar>
<v-icon :color="data.item.color">$ayiFlag</v-icon>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title
><span class="text-subtitle-2">{{
data.item.name
}}</span
><v-icon
v-if="data.item.locked"
small
color="disabled"
class="ml-2"
>$ayiLock</v-icon
>
<v-icon
v-if="data.item.completed"
color="disabled"
class="ml-1"
small
>$ayiCheckCircle</v-icon
></v-list-item-title
>
<v-list-item-subtitle>
{{ data.item.notes }}</v-list-item-subtitle
>
</v-list-item-content>
<v-list-item-action> </v-list-item-action>
</template>
</v-autocomplete>
</div>
</template>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="cancelDialog()">{{
$ay.t("Cancel")
}}</v-btn>
<v-btn
color="blue darken-1"
:disabled="selectedStatus == null"
text
:data-cy="`${dataCy}:btnok`"
@click="save()"
>{{ $ay.t("OK") }}</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
<div class="v-messages theme--light error--text mt-6" role="alert">
<div class="v-messages__wrapper">
<div class="v-messages__message">{{ allErrors }}</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
value: {
default: null,
type: Object
},
pvm: {
default: null,
type: Object
},
allStates: {
default: null,
type: Array
},
allowedStates: {
default: null,
type: Array
},
dataCy: { type: String, default: null },
formKey: { type: String, default: "" }, //used to grab template from store
readonly: Boolean,
disabled: Boolean,
errorMessages: { type: Array, default: null }
},
data() {
return {
selectedStatus: null,
openDialog: false
};
},
computed: {
hasState() {
return this.value.states != null && this.value.states.length > 0;
},
stateDisplayList() {
const ret = [];
this.value.states.forEach(z => {
ret.push(this.getStateForDisplay(z));
});
return ret;
},
canAdd: function() {
//first check most obvious disqualifying property which is that user is not allowed to change at all
if (!this.pvm.rights.change) {
return false;
}
//FACT: isLockedAtServer is *only* set when the status is a locking status, no other time, it's poorly named
//and should be isSetToALockedStatus but here we are, it's post release, can't change it now
//for purposes of making changes here it doesn't really matter if it's locked status or not, all that needs to be known is
//can the user remove this status
const cs = this.pvm.currentState;
if (cs == null || cs.removeRoles == null || cs.removeRoles == 0) {
//no state set yet or no remove roles set so nothing to check against
return true;
}
//We have a state set already, need to check the role here against current user roles to see if this user is allowed to add a state
if (window.$gz.role.hasRole(cs.removeRoles)) {
return true;
}
//it's locked and there seems to be no reason to allow a change so no
return false;
},
allErrors: function() {
let ret = "";
if (this.errorMessages != null && this.errorMessages.length > 0) {
ret += this.errorMessages.toString();
}
return ret;
}
},
methods: {
addState() {
if (this.selectedStatus != null) {
//first remove any other non saved states in collection, no need to send them to the server if there was multiple state changes since last save
this.value.states = this.value.states.filter(
z => z.concurrency != null
);
//is it a different state?
if (this.selectedStatus == this.pvm.currentState.id) {
return;
}
//push in new state
this.value.states.push({
workOrderId: this.value.id,
workOrderStatusId: this.selectedStatus,
userId: window.$gz.store.state.userId,
userViz: window.$gz.store.state.userName,
created: window.$gz.locale.nowUTC8601String()
});
this.selectedStatus = null;
this.pvm.formState.dirty = true;
}
},
getStateForDisplay(state) {
const ret = {
id: Date.now,
name: "??",
color: "#ffffffff",
locked: false,
completed: false,
timeStamp: "??",
user: "??"
};
const s = this.allStates.find(z => z.id == state.workOrderStatusId);
if (s == null) {
return ret;
}
//make for display
ret.id = state.id;
ret.name = s.name;
ret.color = s.color;
ret.locked = s.locked;
ret.completed = s.completed;
ret.user = state.userViz;
ret.timeStamp = window.$gz.locale.utcDateToShortDateAndTimeLocalized(
state.created,
this.pvm.timeZoneName,
this.pvm.languageName,
this.pvm.hour12
);
return ret;
},
form() {
return window.$gz.form;
},
openIcon: function() {
if (this.canAdd) {
return "$ayiEdit";
}
return "$ayiHistory";
},
handleEditStateClick: function() {
window.$gz.eventBus.$emit("openobject", {
type: window.$gz.type.WorkOrderStatus,
id: this.selectedStatus
});
},
save() {
this.addState();
this.openDialog = false;
},
cancelDialog() {
this.selectedStatus = null;
this.openDialog = false;
},
fieldValueChanged(ref) {
if (!this.pvm.formState.loading && !this.pvm.formState.readonly) {
window.$gz.form.fieldValueChanged(this.pvm, ref);
}
}
}
};
</script>