<template> <div class="cycle-table"> <div class="text-h5 mb-0"> <span>Cycles</span> <dialog-info> <template v-slot:title>Cycles</template> <template v-slot:text> In the 'Cycles' section, you'll find all ongoing and completed cycles. Cycles have statuses like 'Done,' 'Reflect,' or 'Ongoing'. Once a cycle ends, you go through a reflection of the current cycle before proceeding to the next cycle. </template> </dialog-info> </div> <v-container class="my-0"> <v-row no-gutters> <v-col cols="6" class="text-left"> <v-chip v-for="(status, i) in statusOptions" :key="i" dark small label @click="filterCycles(status.key)" :class="`status ${status.key} ma-1`"> {{ status.name }} </v-chip> <v-fade-transition> <v-chip v-if="getCycleFilter" class="ma-1" small label @click="removeFilter()" > All</v-chip> </v-fade-transition> </v-col> <v-col cols="6" class="text-right"> <v-menu bottom right offset-y :close-on-content-click="false"> <template v-slot:activator="{ on, attrs }"> <v-chip small label class="ma-1" v-bind="attrs" v-on="on" > Sort by <v-icon right>mdi-menu-down</v-icon> </v-chip> </template> <v-list width="200"> <v-list-item-group v-model="sortBySelected" active-class="" > <v-list-item dense v-for="(item, i) in sortByOptions" :key="i" > <template v-slot:default="{ active }"> <v-list-item-action> <v-checkbox :input-value="active"></v-checkbox> </v-list-item-action> <v-list-item-content> <v-list-item-title>{{ item.name }}</v-list-item-title> </v-list-item-content> </template> </v-list-item> </v-list-item-group> </v-list> </v-menu> </v-col> </v-row> <v-container> <v-row no-gutters class="cycle body-2 font-weight-bold"> <v-col cols="3" sm="1" class="px-2"> ID </v-col> <v-col cols="9" sm="2" class="px-2"> Start Date </v-col> <v-col cols="12" sm="2" class="px-2"> Milestone </v-col> <v-col class="px-2"> Objective </v-col> <v-col cols="12" sm="auto"></v-col> </v-row> </v-container> <Cycle v-for="cycle in sortedCycles" :key="cycle.id" :cycle="cycle" ></Cycle> <add-cycle :disabled="!addCycleAllowed || addCycleDisabledFromSettings" /> <v-dialog v-model="getExpiredCycleDialog" max-width="500px" overlay-color="white" style="z-index: 99" v-if="$store.getters['site/getSettings'].includes('expiration')" > <dialog-alert v-on:on-cancel="$store.commit('site/setExpiredCycleDialog', false)" v-on:on-continue="$store.commit('site/setExpiredCycleDialog', false)"> <template v-slot:text> Cycle time passed. Close pending cycles soon. </template> </dialog-alert> </v-dialog> </v-container> </div> </template> <script> import Cycle from './Cycle'; import AddCycle from "@/components/AddCycle"; import DialogInfo from "@/components/DialogInfo"; import {mapGetters} from "vuex"; import DialogAlert from "@/components/DialogAlert"; export default { name: "CycleTable", components: { DialogAlert, DialogInfo, AddCycle, Cycle, }, props: ['cycles', 'teams'], data: () => ({ maxAddCycleAllowed: 2, teamFilterSelected: [], addCycleDisabledFromSettings: false, sortBySelected: 0, sortByOptions: [ {name: 'Cycle', key: 'id'}, {name: 'Milestone', key: 'milestone'}, {name: 'Objective', key: 'objective'}, ], statusOptions: [ {name: 'Done', key: 'complete'}, {name: 'Reflect', key: 'reflect'}, {name: 'Ongoing', key: 'todo'}, ], }), methods: { filterCycles(status) { this.$store.dispatch('site/filterCyclesByStatus', status) }, removeFilter() { this.$store.dispatch('site/removeCycleFilter') } }, computed: { ...mapGetters('site', ['getCycles', 'getCycleFilter', 'getFilteredCycles', 'getExpiredCycleDialog']), addCycleAllowed() { if (this.$store.getters['site/getSettings'].includes('limit')) { const allowed = this.cycles // maxAddCycleAllowed cycles are allowed .filter(cycle => cycle.status !== 'Done') .length < this.maxAddCycleAllowed this.$emit('update-add-cycle-allowed', allowed) return allowed } else { return true } }, sortedCycles() { let prop = this.sortByOptions[this.sortBySelected].key if (prop !== 'id') return this.getFilteredCycles.slice().sort((a, b) => a[prop].localeCompare(b[prop])) else // Always reverse order (descending) for id return this.getFilteredCycles.slice().sort((a, b) => a[prop] > b[prop] ? -1 : 1) }, }, created() { this.teamFilterSelected = Array(this.teams.length).fill(0).map((x, index) => index) if (this.$store.getters['site/getExpiredCycleDialog'] === null && this.cycles.some(cycle => cycle.expired)) { this.$store.commit('site/setExpiredCycleDialog', true) } }, } </script> <style scoped> .status.v-chip.complete { background: #F29829; } .status.v-chip.reflect { background: #156389; } .status.v-chip.todo { background: #F25C05; } </style>