petra-tool / frontend / src / components / EditTask.vue
EditTask.vue
Raw
<template>
  <v-dialog
    v-model="dialog"
    persistent
    max-width="1200"
    overlay-color="white"
    content-class="rounded-xl"
    scrollable
  >
    <template v-slot:activator="{ on, attrs }">
      <v-btn
        small
        icon
        light
        v-bind="attrs"
        v-on="on"
        :color="task.status === 'Done' && !!!task.effort_real ? 'primary' : ''"
      >
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>
    </template>

    <v-card>
      <v-card-title class="accent white--text pt-10 pb-4 text-h5 pl-9">
        Quick Edit
      </v-card-title>
      <v-card-text>
        <v-container fluid>
          <v-row>
            <v-col cols="12" md="8">
              <task-form :form="form" :disabled="taskDisabled" ref="form"></task-form>
            </v-col>
            <v-col cols="12" md="4">
              <v-row class="no-gutters flex-wrap flex-column fill-height">
                <v-col cols="auto" class="shrink" v-show="task.status === 'Done'">
                  <v-card class="mb-2 shrink" color="rgba(104,166,148,0.11)" flat>
                    <v-card-title class="text-h5">Real hours spent in hours</v-card-title>
                    <v-card-text>

                      <v-text-field
                        label="Insert the amount of hours spent on the task..."
                        v-model="form.effortReal"
                        outlined
                        required
                        type="number"
                        :rules="[
                          value => !!value || 'Amount of hours is required.',
                          value => value > 0 || 'Amount of hours must be greater zero.',
                          value => value <= 150 || 'Amount of hours must be smaller than 150.'
                        ]"
                      ></v-text-field>

                    </v-card-text>
                  </v-card>
                </v-col>
                <v-col cols="auto" class="shrink mb-2">
                  <v-card flat color="#F6F6F6" :disabled="taskDisabled">
                    <v-card-title class="text-h5">Comments</v-card-title>
                    <v-card-text>
                      <v-form ref="formComment">
                        <v-text-field
                          background-color="white"
                          outlined
                          label="Write a comment"
                          class=""
                          single-line
                          hide-details
                          v-model="form.comment"
                          @keydown.enter.prevent="addComment"
                          :rules="[value => !!value || 'Comment is required.']"
                        >
                          <template v-slot:append-outer>
                            <v-icon large @click="addComment">mdi-send-circle</v-icon>
                          </template>
                        </v-text-field>
                      </v-form>
                    </v-card-text>
                  </v-card>
                </v-col>
                <v-col cols="auto" class="grow">
                  <v-card flat color="#F6F6F6" height="100%" max-height="500" class="overflow-y-auto">
                    <v-card-text>
                      <single-comment
                        v-for="comment in form.comments"
                        :key="comment.id"
                        :comment="comment"
                        v-on:delete-comment="deleteComment"
                      ></single-comment>
                    </v-card-text>
                  </v-card>
                </v-col>
                <v-col cols="auto" class="shrink">
                  <v-card class="mt-2 shrink" color="#FBE8E8" flat :disabled="taskDisabled">
                    <v-card-title class="text-h5">Danger Zone</v-card-title>
                    <v-card-text>

                      <v-btn block min-width="150" color="#B20505" dark depressed @click="dialogDelete = true">Delete
                        Task
                      </v-btn>

                      <v-dialog
                        v-model="dialogDelete"
                        max-width="500px"
                        overlay-color="white"
                      >
                        <dialog-alert v-on:on-cancel="dialogDelete = false" v-on:on-continue="removeTask">
                          <template v-slot:title>Delete Task</template>
                          <template v-slot:text>
                            Are you sure? This can't be undone!
                          </template>
                        </dialog-alert>
                      </v-dialog>
                    </v-card-text>
                  </v-card>
                </v-col>
              </v-row>
            </v-col>
          </v-row>

        </v-container>

      </v-card-text>
      <v-card-actions class="ma-7">
        <v-btn
          text
          @click="onClose"
        >
          Cancel
        </v-btn>
        <v-spacer></v-spacer>
        <v-btn
          color="primary"
          depressed
          min-width="150"
          :loading="loading"
          @click="onSubmit"
        >
          Save
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script>
import TaskForm from "@/components/TaskForm";
import DialogAlert from "@/components/DialogAlert";
import SingleComment from "@/components/SingleComment";

export default {
  name: "EditTask",
  components: {SingleComment, DialogAlert, TaskForm},
  props: ['task', 'members'],
  data: () => ({
    dialog: false,
    loading: false,
    dialogDelete: false,
    loadingDelete: false,

    form: {
      valid: true,
      name: '',
      description: '',
      effortOptions: [1, 3, 5],
      effortReal: 0,
      selectedEffort: 1,
      ownerOptions: [],
      selectedOwner: '',
      reviewerOptions: [],
      selectedReviewer: '',
      lensOptions: [],
      lensSelected: '',
      purposeOptions: [],
      purposeSelected: '',
      comments: [],
      commentsDeleted: [],
      comment: '',
    },
  }),
  methods: {
    onSubmit() {
      if (this.$refs.form.$refs.form.validate()) {
        this.loading = true
        this.$http.put('/board/task', {
          id: this.task.id,
          name: this.form.name,
          description: this.form.description,
          lens: this.form.lensSelected,
          purpose: this.form.purposeSelected,
          owner: this.form.selectedOwner,
          reviewer: this.form.selectedReviewer,
          effort: this.form.selectedEffort,
          effort_real: this.form.effortReal,
          status: this.task.status,
          comments: this.form.comments,
          comments_deleted: this.form.commentsDeleted,
        }).then((resp) => {
          this.$store.dispatch('site/updateTask', {
            id: this.task.id,
            name: this.form.name,
            description: this.form.description,
            lens: this.form.lensSelected,
            lens_emoji:  {"Desirability":"๐Ÿ’ก", "Feasibility":"โš™๏ธ", "Viability":"๐Ÿš€"}[this.form.lensSelected],
            purpose: this.form.purposeSelected,
            purpose_emoji: {"Explore":"๐Ÿงญ", "Evaluate":"๐Ÿ”Ž", "Communicate":"๐Ÿ—ฃ๏ธ"}[this.form.purposeSelected],
            owner: this.form.selectedOwner,
            reviewer: this.form.selectedReviewer,
            effort: this.form.selectedEffort,
            effort_real: this.form.effortReal,
            status: this.task.status,
            comments: resp.data.comments,
          })
          this.$snackbar.showMessage({
            content: 'Task saved!'
          })
          this.dialog = false
        }).catch(() => {
          this.$snackbar.showMessage({
            content: 'Something went wrong, please try again!', color: 'warning'
          })
        }).finally(() => (this.loading = false))
      }
    },
    onClose() {
      this.dialog = false
      this.$refs.form.$refs.form.resetValidation()
      this.fillForm()
    },
    removeTask() {
      this.loadingDelete = true
      this.$http.delete('/board/task', {
        data: {
          id: this.task.id,
        }
      }).then(() => {
        this.$store.dispatch('site/removeTask', {
          labelId: this.task.label.id,
          id: this.task.id,
        })
        this.$snackbar.showMessage({
          content: 'Task deleted!'
        })
      }).catch(() => {
        this.$snackbar.showMessage({
          content: 'Something went wrong, please try again!', color: 'warning'
        })
      })
      this.loadingDelete = false
    },
    fillForm() {
      this.form.name = this.task.name
      this.form.description = this.task.description
      this.form.ownerOptions = this.members
      this.form.reviewerOptions = this.members
      this.form.selectedEffort = this.task.effort
      this.form.effortReal = this.task.effort_real
      this.form.selectedOwner = this.task.owner
      this.form.selectedReviewer = this.task.reviewer
      this.form.lensSelected = this.task.lens
      this.form.purposeSelected = this.task.purpose
      this.form.comments = this.task.comments
    },
    addComment() {
      if (this.$refs.formComment.validate()) {
        this.form.comments.push({
          timestamp: "just now",
          id: Math.max(0, Math.max(...this.form.comments.map(comment => comment.id))) + 1,
          text: this.form.comment
        })
        this.form.comment = ''
        this.$refs.formComment.reset()
      }
    },
    deleteComment(id) {
      this.form.comments = this.form.comments.filter(comment => comment.id !== id)
      this.form.commentsDeleted.push(id)
    }
  },
  created() {
    this.fillForm()
  },
  computed: {
    taskDisabled() {
      return this.task.status === 'Done'
    }
  }
}
</script>

<style scoped>
::v-deep input::-webkit-outer-spin-button,
::v-deep input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
</style>