Skip to content

Commit

Permalink
SS-764: Setup bulk unassign functionality in manage duties screen by …
Browse files Browse the repository at this point in the history
…selecting multiple duty slots using ctrl click
  • Loading branch information
Hemanth Kona authored and Hemanth Kona committed Jun 19, 2024
1 parent e28af06 commit 3faef1c
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 14 deletions.
10 changes: 5 additions & 5 deletions docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ services:

api:
image: ss-api
environment:
environment:
- LocationServicesClient__Username=${LocationServicesClientUsername}
- LocationServicesClient__Password=${LocationServicesClientPassword}
- LocationServicesClient__Url=${LocationServicesClientUrl}
Expand All @@ -36,8 +36,8 @@ services:
- ASPNETCORE_URLS=${ASPNETCORE_URLS}
- WebBaseHref=${WEB_BASE_HREF}
- SiteMinderLogoutUrl=${SiteMinderLogoutUrl}
- Logging__LogLevel__Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker=${ControllerLoggingLevel}
- Logging__LogLevel__SS.Api.infrastructure.middleware.ErrorHandlingMiddleware=${MiddlewareLoggingLevel}
- Logging__LogLevel__Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker=${ControllerLoggingLevel}
- Logging__LogLevel__SS.Api.infrastructure.middleware.ErrorHandlingMiddleware=${MiddlewareLoggingLevel}
- Logging__LogLevel__Microsoft.EntityFrameworkCore.Database.Command=${DatabaseLoggingLevel}
- ASPNETCORE_Kestrel__Certificates__Default__Password=${KestrelPassword}
- ASPNETCORE_Kestrel__Certificates__Default__Path=${KestrelPath}
Expand Down Expand Up @@ -67,8 +67,8 @@ services:
- 5432:5432
volumes:
- ./tmp:/tmp2

pdf:
image: hassananv/weasyprint
ports:
- 8083:5001
- 8083:5001
2 changes: 1 addition & 1 deletion web/src/components/DutyRoster/DutyRosterWeekView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
</template>

<template v-slot:cell(h0)="data" >
<duty-card-week-view v-on:change="getData" :dutyRosterInfo="data.item"/>
<duty-card-week-view v-on:change="getData" :dutyRostersJson="dutyRostersJson" :dutyRosterInfo="data.item"/>
</template>
</b-table>

Expand Down
44 changes: 36 additions & 8 deletions web/src/components/DutyRoster/components/DutyCardWeekView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,10 @@
<b-button style="margin:-2.95rem -0.75rem -2rem 1rem; width:2.5rem; height:2.5rem;" variant="outline-warning" class="text-light" @click="closeEditDutySheriffModalWindow()"
><div style="transform:translate(0px,1px)">&times;</div></b-button>
</template>
</b-modal>

</b-modal>

<bulk-unassign-modal :showModal="showBulkUnassignModal" :dutyRostersJson="dutyRostersJson" @close="closeBulkUnassignModelWindow($event)"/>

</div>
</template>

Expand All @@ -277,9 +279,10 @@
import * as _ from 'underscore';
import moment from 'moment-timezone';
import AddDutySlotWeekForm from './AddDutySlotWeekForm.vue'
import {dutyRangeInfoType, dutySlotInfoType, assignDutySlotsInfoType, assignDutyInfoType, assignmentCardInfoType, dutyBlockWeekInfoType, myTeamShiftInfoType, selectedDutyCardInfoType, assignmentCardWeekInfoType } from '@/types/DutyRoster';
import {dutyRangeInfoType, dutySlotInfoType, assignDutySlotsInfoType, assignDutyInfoType, assignmentCardInfoType, dutyBlockWeekInfoType, myTeamShiftInfoType, selectedDutyCardInfoType, assignmentCardWeekInfoType, attachedDutyInfoType } from '@/types/DutyRoster';
import {localTimeInfoType, userInfoType} from '@/types/common';
import SheriffModal from './SheriffModal.vue'
import SheriffModal from './SheriffModal.vue';
import BulkUnassignModal from '../../common/BulkUnassignModal.vue';
import { namespace } from "vuex-class";
import "@store/modules/CommonInformation";
Expand All @@ -290,7 +293,8 @@
@Component({
components: {
AddDutySlotWeekForm,
SheriffModal
SheriffModal,
BulkUnassignModal
}
})
export default class DutyCardWeekView extends Vue {
Expand All @@ -304,6 +308,9 @@
@commonState.State
public userDetails!: userInfoType;
@Prop({required: true})
dutyRostersJson!: attachedDutyInfoType[];
@Prop({required: true})
dutyRosterInfo!: assignmentCardInfoType;
Expand Down Expand Up @@ -370,6 +377,8 @@
showEditDutySheriffModal = false;
editingBlockId=''
showBulkUnassignModal = false;
editDutyError = false;
editDutyErrorMsg = '';
Expand Down Expand Up @@ -424,7 +433,7 @@
}
public editDutySheriffModal(day, e?, blkId?){
public editDutySheriffModal(day, e?, blkId?){
if(e?.ctrlKey == true){
const block = this.dutyBlocks.filter(blk => blk.id==blkId)
const assignment = this.dutyRosterInfo.assignment+'D'+day
Expand All @@ -441,7 +450,10 @@
}
this.UpdateSelectedDuties(selectedDuties)
}
else if (blkId.includes('i')){
else if (this.selectedDuties.length > 1 && this.shouldAllowBulkUnassign()) {
this.showBulkUnassignModal = true;
} else if (blkId.includes('i')){
this.editDuty(day)
}
else{
Expand All @@ -453,6 +465,16 @@
}
}
shouldAllowBulkUnassign() {
// show if all the selectedDuites are assigned to a sheriff
return this.selectedDuties.every((s) =>
s.dutyBlock?.every((d) => {
if (!d.sheriffId || !d.dutyId) return false;
return true;
})
)
}
public editDuty(day, e?, blkId?){

Check warning on line 478 in web/src/components/DutyRoster/components/DutyCardWeekView.vue

View workflow job for this annotation

GitHub Actions / build (10.x)

'e' is defined but never used
this.isDutyDataMounted = false;
this.dutyBlocksDay = (this.dutyBlocks.filter(dutyBlock=>{if(dutyBlock.day==day)return true;}));
Expand Down Expand Up @@ -544,6 +566,13 @@
this.showEditDutySheriffModal = false;
}
public closeBulkUnassignModelWindow(refreshData: boolean) {
this.showBulkUnassignModal = false;
if (refreshData) {
this.$emit('change', this.scrollPositions());
}
}
public closeDutySlotForm() {
this.addNewDutySlotForm= false;
this.addFormColor = 'secondary';
Expand Down Expand Up @@ -571,7 +600,6 @@
}
public extractDuty(){
for(let day=0; day<7; day++){
if(this.dutyRosterInfo[day]){
const dutyInfo = this.dutyRosterInfo[day];
Expand Down
192 changes: 192 additions & 0 deletions web/src/components/common/BulkUnassignModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
<template>
<div>
<b-modal v-model="showModal" id="bv-modal-bulk-unassign" size="lg bulk-unassign" no-close-on-backdrop centered header-class="bg-primary pt-3 pb-2 text-light">
<template v-slot:modal-header-close>
<b-button style="margin:-2.95rem -0.75rem -2rem 1rem; width:2.5rem; height:2.5rem;" variant="outline-warning" class="text-light" @click="closeBulkUnassignModal">
<div style="transform:translate(0px,1px)">&times;</div>
</b-button>
</template>

<template v-slot:modal-title>
<div class="h2 mb-2 text-light"> Bulk Unassign: </div>
</template>

<loading-spinner v-if="loadingData" />

<h1> Duty Slots </h1>

<b-row v-if="showBulkUnassignError" id="BulkUnassignError" class="h4 mx-2">
<b-badge class="mx-1 mt-2"
style="width: 20rem;"
v-b-tooltip.hover
:title="showBulkUnassignErrorMsg"
variant="danger">

{{showBulkUnassignErrorMsg | truncate(40)}}

<b-icon class="ml-3"
icon = x-square-fill
@click="showBulkUnassignError = false"
/>
</b-badge>
</b-row>

<b-table
:items="dutyBlocksToUnassign"
:fields="fields"
head-row-variant="primary"
striped
borderless
small
sort-by="startTimeString"
responsive="sm"
>
<template v-slot:cell(sheriffName)="data">
{{ data.item.firstName }} {{ data.item.lastName }}
</template>

<template v-slot:cell(dutyDate)="data">
{{ data.value|beautify-date-weekday }}
</template>
</b-table>

<template v-slot:modal-footer>
<b-button variant="danger" class="mr-auto" @click="confirmBulkUnassign()">
<b-icon-trash-fill style="padding:0; vertical-align: middle; margin-right: 0.25rem;"></b-icon-trash-fill>
Unassign
</b-button>
<b-button variant="primary" @click="closeBulkUnassignModal">Cancel</b-button>
</template>
</b-modal>

<!-- confirm bulk unassign modal -->
<b-modal v-model="showConfirmBulkUnassignModal" id="bv-modal-confirm-bulk-unassign" header-class="bg-warning text-light">
<template v-slot:modal-title>
<h2 class="mb-0 text-light">Confirm Bulk Unassign Duties</h2>
</template>

<h4 >Are you sure you want to bulk unassign the below list of assignments? Please double check the list of assignments.</h4>

<template v-slot:modal-footer>
<b-button variant="danger" @click="bulkUnassign()">Confirm</b-button>
<b-button variant="primary" @click="$bvModal.hide('bv-modal-confirm-bulk-unassign')">Cancel</b-button>
</template>
<template v-slot:modal-header-close>
<b-button variant="outline-warning" class="text-light closeButton" @click="$bvModal.hide('bv-modal-confirm-bulk-unassign')"
>&times;</b-button>
</template>
</b-modal>
</div>
</template>

<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator';
import { assignDutyInfoType, assignmentCardWeekInfoType, attachedDutyInfoType, dutyBlockWeekInfoType, selectedDutyCardInfoType} from '@/types/DutyRoster';
import * as _ from 'underscore';
import { namespace } from "vuex-class";
import "@store/modules/DutyRosterInformation";
const dutyState = namespace("DutyRosterInformation");
@Component({
components: {
}
})
export default class BulkUnassignModal extends Vue {
@Prop({required: true})
showModal = false;
@Prop({required: true})
dutyRostersJson!: attachedDutyInfoType[];
@dutyState.State
public dutyRosterAssignmentsWeek!: assignmentCardWeekInfoType[];
@dutyState.State
public selectedDuties!: selectedDutyCardInfoType[];
loadingData = false;
showConfirmBulkUnassignModal = false;
fields = [
{key:'assignmentName', label:'Assignment', sortable:false, tdClass: 'border-top', thClass:'h6 align-middle',},
{key:'sheriffName', label:'Sheriff', sortable:false, tdClass: 'border-top', thClass:'h6 align-middle',},
{key:'dutyDate', label:'Duty Date', sortable:false, tdClass: 'border-top', thClass:'h6 align-middle',},
{key:'startTimeString', label:'Start Time', sortable:false, tdClass: 'border-top', thClass:'h6 align-middle',},
{key:'endTimeString', label:'End Time', sortable:false, tdClass: 'border-top', thClass:'h6 align-middle',},
];
dutyBlocksToUnassign: Array<dutyBlockWeekInfoType & { assignmentName: string }> = [];
showBulkUnassignError = false;
showBulkUnassignErrorMsg = '';
mounted() {
this.$root.$on('bv::modal::show', (bvEvent, modalId) => {
const constructDutyBlocks: Array<dutyBlockWeekInfoType & { assignmentName: string }> = [];
this.selectedDuties.forEach((sd) => {
sd.dutyBlock?.forEach((db) => {
const assignmentId = this.dutyRostersJson.find((dr) => dr.id === db.dutyId)?.assignmentId;
const findAssignment = this.dutyRosterAssignmentsWeek.find((aw) => aw.assignmentDetail.id === assignmentId);
const assignmentName = findAssignment?.assignmentDetail?.name ? findAssignment.assignmentDetail.name : '';
constructDutyBlocks.push({...db, assignmentName: assignmentName});
});
});
this.dutyBlocksToUnassign = constructDutyBlocks;
});
}
confirmBulkUnassign() {
this.showConfirmBulkUnassignModal = true;
}
bulkUnassign() {
this.showConfirmBulkUnassignModal = false;
// remove the selected dutyslots from DutyRoster.dutySlots[]
const dutyIds = _.flatten(this.selectedDuties.map((s) => s.dutyBlock?.map((d) => d.dutyId)))
const dutySlotIds = _.flatten(this.selectedDuties.map((s) => s.dutyBlock?.map((d) => d.dutySlotId)));
const updateDutyRosterDto: assignDutyInfoType[] = this.dutyRostersJson.filter((s) => {
if (dutyIds.includes(s.id)) {
s.dutySlots = s.dutySlots.filter((ds) => !dutySlotIds.includes(ds.id));
return true;
}
return false;
});
this.showBulkUnassignError = false;
this.loadingData = true;
const updateDutyRosterUrl = 'api/dutyroster';
this.$http.put(updateDutyRosterUrl, updateDutyRosterDto).then(response => {
if(response.data){
this.$emit('close', true);
}
this.showBulkUnassignError = false;
this.loadingData = false;
}, err => {
this.showBulkUnassignErrorMsg = 'Error Bulk unassigning duty slots';
if (err.response.data.error) {
this.showBulkUnassignErrorMsg = err.response.data.error;
}
this.showBulkUnassignError = true;
this.loadingData = false;
});
}
closeBulkUnassignModal() {
this.showBulkUnassignError = false;
this.showModal = false;
this.$emit('close', false);
}
}
</script>

0 comments on commit 3faef1c

Please sign in to comment.