petra-tool / frontend / src / components / Board.vue
Board.vue
Raw
<template>
  <v-container class="px-0">

    <kanban-board :stages="stages" :blocks="tasks" :config="config" :status-prop="statusProp"
                  @update-block="updateBlock">
      <div v-for="stage in stages" :slot="stage" :key="stage">
        <div class="body-1 py-1" :class="stage === 'Done' ? 'font-weight-regular': 'font-weight-bold'">
          <span>{{ stage }}</span>
          <span style="color: #F29829" class="pl-2" v-if="stage === 'Done' && !tasks.every(task => task.effort_real > 0) && tasks.some(task => task.status === 'Done')">Click <v-icon dark small color="primary">mdi-dots-vertical</v-icon> to enter hours spent</span></div>
        <v-card v-if="stage === 'Backlog'"
                flat tile class="text-center" :disabled="finished">
          <v-card-text>
            <add-task :members="members" :labels="getBoard.labels"></add-task>
          </v-card-text>
        </v-card>
      </div>
      <v-card flat :disabled="finished" :class="{'no-drag':finished}" tile v-for="block in tasks"
              :slot="block.id" :key="block.id" :loading="loading ? 'accent' : false"
              :outlined="block.status === 'Done' && !!!block.effort_real"
              :style="block.status === 'Done' && !!!block.effort_real ? 'border: 2px solid #F29829' : ''"
      >
        <v-card-title class="body-2 pt-1 pb-0 pr-1">
          <v-row no-gutters>
            <v-col cols="10">
              {{ block.lens_emoji }}&nbsp;{{ block.lens }} | {{ block.purpose_emoji }}&nbsp;{{ block.purpose }}
            </v-col>
            <v-col cols="2" class="text-right">
              <edit-task :task="block" :members="members"></edit-task>
            </v-col>
          </v-row>
        </v-card-title>
        <v-card-text class="black--text body-2 pr-1">
          {{ block.name }}
        </v-card-text>
        <v-card-actions>
          <v-btn small text v-show="block.comments.length > 0" :ripple="false" plain>
            {{ block.comments.length }}
            <v-icon x-small right class="ml-0">mdi-comment-outline</v-icon>
          </v-btn>

          <v-spacer></v-spacer>

          <v-chip small dark :class="block.status === 'Done' || block.status === 'Rejected' ? null : hashColor(block.lens)">
            <v-icon small left>mdi-account-circle</v-icon>
            {{ block.owner }}
          </v-chip>
          <v-chip small dark class="mx-1" :class="block.status === 'Done' || block.status === 'Rejected' ? null : hashColor(block.lens)">
            <v-icon small left>mdi-account-circle-outline</v-icon>
            {{ block.reviewer }}
          </v-chip>
          <v-chip small dark :class="block.status === 'Done' || block.status === 'Rejected' ? null : hashColor(block.lens)">
            <v-icon small left>mdi-timelapse</v-icon>
            {{ block.effort }}
          </v-chip>
        </v-card-actions>
      </v-card>
    </kanban-board>

  </v-container>
</template>

<script>
import EditTask from "@/components/EditTask";
import {mapGetters} from "vuex";
import AddTask from "@/components/AddTask";

export default {
  name: "Board",
  components: {EditTask, AddTask},
  props: ['tasks', 'team', 'finished'],
  data() {
    return {
      stages: ['Backlog', 'Todo', 'Work-in-Progress', 'Done', 'Rejected'],
      blocks: [],
      statusProp: 'status',
      loading: false,
      config: {
        // Don't allow blocks to be moved out of the approved stage
        // accepts(block, target, source) {
        //   return source.dataset.status !== 'Done'
        // },
        // eslint-disable-next-line no-unused-vars
        moves(block, source, handle, sibling) {
          // https://github.com/valor-software/ng2-dragula/issues/784#issuecomment-336483568
          return !block.children[0].classList.contains('no-drag')
        }
      },
      members: Object.values(this.team.members),
    }
  },
  computed: {
    ...mapGetters('site', ['getBoard']),
  },
  methods: {
    updateBlock(id, status) {
      this.loading = true
      this.$http.put('/board/task', {
        id: Number(id),
        status: status
      }).then(response => {
        this.$store.dispatch('site/updateTask', {
          id: Number(id),
          name: response.data.name,
          owner: response.data.owner,
          reviewer: response.data.reviewer,
          effort: response.data.effort,
          effort_real: response.data.effort_real,
          status: status,
          lens: response.data.lens,
          lens_emoji: response.data.lens_emoji,
          purpose: response.data.purpose,
          purpose_emoji: response.data.purpose_emoji,
          description: response.data.description,
          comments: response.data.comments,
        })
      }).catch(() => {
        this.$snackbar.showMessage({
          content: 'Something went wrong, please try again!', color: 'warning'
        })
      }).finally(() => this.loading = false)
    },
    hashColor(lens) {
      switch (lens) {
        case 'Viability':
          return 'error'
        case 'Feasibility':
          return 'info'
        case 'Desirability':
          return 'primary'
        default:
          return 'secondary'
      }
    }
  },
}
</script>

<style lang="scss">
@import '../assets/kanban.scss';
</style>