feat(tasks): functional summary modal

This commit is contained in:
SabreCat
2022-07-25 22:31:33 -05:00
parent 30d3892fb4
commit 18db432f7f
5 changed files with 211 additions and 92 deletions
@@ -1,79 +1,96 @@
<template>
<div class="checklist-component">
<lockable-label
:locked="disabled || disableItems"
:text="$t('checklist')"
/>
<draggable
v-model="checklist"
:options="{
handle: '.grippy',
filter: '.task-dropdown',
disabled: disabled,
}"
@update="updateChecklist"
<div
class="d-flex"
>
<lockable-label
:locked="disabled"
:text="$t('checklist')"
/>
<div
v-for="(item, $index) in checklist"
:key="item.id"
class="inline-edit-input-group checklist-group input-group"
class="svg-icon icon-16 my-auto ml-auto"
:class="{'chevron-flip': !hideChecklist}"
v-html="icons.chevron"
@click="hideChecklist = !hideChecklist"
>
</div>
</div>
<div
v-if="!hideChecklist"
>
<draggable
v-model="checklist"
:options="{
handle: '.grippy',
filter: '.task-dropdown',
disabled: disabled,
}"
@update="updateChecklist"
>
<div
v-for="(item, $index) in checklist"
:key="item.id"
class="inline-edit-input-group checklist-group input-group"
>
<span
v-if="!disabled && !disableDrag"
class="grippy"
v-html="icons.grip"
>
</span>
<checkbox
v-if="!disableEdit"
:id="`checklist-${item.id}`"
:checked.sync="item.completed"
:disabled="disabled"
class="input-group-prepend"
:class="{'cursor-auto': disabled}"
/>
<input
v-model="item.text"
class="inline-edit-input checklist-item form-control"
type="text"
:disabled="disabled || disableEdit"
:class="summaryClass(item)"
>
<span
v-if="!disabled && !disableEdit"
class="input-group-append"
@click="removeChecklistItem($index)"
>
<div
v-once
class="svg-icon destroy-icon"
v-html="icons.destroy"
>
</div>
</span>
</div>
</draggable>
<div
v-if="!disabled && !disableEdit"
class="inline-edit-input-group checklist-group input-group new-checklist"
:class="{'top-border': items.length === 0}"
>
<span
v-if="!disabled && !disableDrag"
class="grippy"
v-html="icons.grip"
v-once
class="input-group-prepend new-icon"
v-html="icons.positive"
>
</span>
<checkbox
:id="`checklist-${item.id}`"
:checked.sync="item.completed"
:disabled="disabled || disableItems"
class="input-group-prepend"
:class="{'cursor-auto': disabled || disableItems}"
/>
<input
v-model="item.text"
v-model="newChecklistItem"
class="inline-edit-input checklist-item form-control"
type="text"
:disabled="disabled || disableItems"
:placeholder="$t('newChecklistItem')"
@keypress.enter="setHasPossibilityOfIMEConversion(false)"
@keyup.enter="addChecklistItem($event, true)"
@blur="addChecklistItem($event, false)"
>
<span
v-if="!disabled && !disableItems"
class="input-group-append"
@click="removeChecklistItem($index)"
>
<div
v-once
class="svg-icon destroy-icon"
v-html="icons.destroy"
>
</div>
</span>
</div>
</draggable>
<div
v-if="!disabled && !disableItems"
class="inline-edit-input-group checklist-group input-group new-checklist"
:class="{'top-border': items.length === 0}"
>
<span
v-once
class="input-group-prepend new-icon"
v-html="icons.positive"
>
</span>
<input
v-model="newChecklistItem"
class="inline-edit-input checklist-item form-control"
type="text"
:placeholder="$t('newChecklistItem')"
@keypress.enter="setHasPossibilityOfIMEConversion(false)"
@keyup.enter="addChecklistItem($event, true)"
@blur="addChecklistItem($event, false)"
>
</div>
</div>
</template>
@@ -104,7 +121,7 @@ export default {
disableDrag: {
type: Boolean,
},
disableItems: {
disableEdit: {
type: Boolean,
},
items: {
@@ -114,6 +131,7 @@ export default {
data () {
return {
checklist: this.items,
hideChecklist: false,
hasPossibilityOfIMEConversion: true,
newChecklistItem: null,
icons: Object.freeze({
@@ -125,6 +143,11 @@ export default {
};
},
methods: {
summaryClass (item) {
if (!this.disableEdit) return '';
if (item.completed) return 'summary-completed';
return 'summary-incomplete';
},
updateChecklist () {
this.$emit('update:items', this.checklist);
},
@@ -166,6 +189,10 @@ export default {
.checklist-component {
.chevron-flip {
transform: translateY(-5px) rotate(180deg);
}
.top-border {
border-top: 1px solid $gray-500;
}
@@ -251,6 +278,13 @@ export default {
border-radius: 0px;
border: none !important;
padding-left: 36px;
&.summary-incomplete {
opacity: 1;
}
&.summary-completed {
text-decoration: line-through;
}
}
.checklist-group {
@@ -100,25 +100,6 @@
:placeholder="$t('addNotes')"
></textarea>
</div>
<div
v-if="task.group && task.group.assignedDate && !task.group.assigningUsername"
class="mt-3 mb-n2"
:class="cssClass('headings')"
v-html="$t('assignedDateOnly', {
date: formattedDate(task.group.assignedDate),
})"
>
</div>
<div
v-if="task.group && task.group.assignedDate && task.group.assigningUsername"
class="mt-3 mb-n2"
:class="cssClass('headings')"
v-html="$t('assignedDateAndUser', {
username: task.group.assigningUsername,
date: formattedDate(task.group.assignedDate),
})"
>
</div>
</div>
<div
v-if="task"
@@ -429,7 +410,7 @@
<label
v-once
class="col-10 mb-1"
>{{ $t('assignedTo') }}</label>
>{{ $t('assignTo') }}</label>
<a
v-if="assignedMembers.length > 0"
class="col-2 text-right mt-1"
@@ -18,7 +18,7 @@
{{ title }}
</h2>
<div
class="svg-icon color-stroke icon-12 close-x ml-auto my-auto"
class="svg-icon color close-x ml-auto my-auto"
:class="cssClass('headings')"
aria-hidden="true"
tabindex="0"
@@ -27,12 +27,70 @@
v-html="icons.close"
></div>
</div>
<div
v-if="task"
class="task-modal-content pt-3 px-4 pb-4"
>
<div class="summary-block">
<h3> {{ $t('title') }} </h3>
<p> {{ task.text }} </p>
</div>
<div
v-if="task.notes"
class="summary-block"
>
<h3> {{ $t('notes') }} </h3>
<p> {{ task.notes }} </p>
</div>
<div class="summary-block">
<h3> {{ $t('description') }} </h3>
<p v-html="summarySentence" ></p>
</div>
<div
v-if="task.checklist && task.checklist.length > 0"
class="summary-block"
>
<checklist
:items.sync="task.checklist"
:disableDrag="true"
:disableEdit="true"
/>
</div>
<div
class="summary-block"
v-if="assignedMembers.length > 0"
>
<h3> {{ $t('assignedTo') }} </h3>
<div
class="d-flex flex-wrap"
>
<span
v-for="member in assignedMembers"
:key="member"
class="assigned-member py-1 px-75 mr-1"
v-html="memberNamesById[member]"
>
</span>
</div>
</div>
</div>
<div
v-if="task && task.group.assignedUsersDetail && task.group.assignedUsersDetail[user._id]"
class="assignment-footer text-center py-2"
v-html="$t('assignedDateAndUser', {
username: task.group.assignedUsersDetail[user._id].assigningUsername,
date: formattedDate(task.group.assignedUsersDetail[user._id].assignedDate),
})"
>
</div>
</b-modal>
</template>
<style lang="scss">
@import '~@/assets/scss/colors.scss';
#task-summary {
overflow-y: hidden;
.modal-content {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
@@ -60,9 +118,24 @@
<style lang="scss" scoped>
@import '~@/assets/scss/colors.scss';
.assigned-member {
border: 1px solid $gray-400;
border-radius: 100px;
color: $gray-100;
font-size: 12px;
line-height: 1.33;
}
.assignment-footer {
color: $gray-100;
background-color: $gray-700;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
}
.close-x {
height: 12px;
width: 12px;
height: 16px;
width: 16px;
position: relative;
opacity: 0.75;
@@ -71,6 +144,22 @@
}
}
.summary-block:not(:last-of-type) {
margin-bottom: 1rem;
}
.task-modal-content {
h3 {
margin-bottom: 0.25rem;
}
p {
margin-bottom: 0px;
}
h3, p {
color: $gray-50;
}
}
.task-modal-header {
color: $white;
height: 60px;
@@ -89,12 +178,16 @@ import keys from 'lodash/keys';
import moment from 'moment';
import pickBy from 'lodash/pickBy';
import checklist from './modal-controls/checklist';
import syncTask from '../../mixins/syncTask';
import { mapGetters } from '@/libs/store';
import { mapGetters, mapState } from '@/libs/store';
import closeIcon from '@/assets/svg/close.svg';
export default {
components: {
checklist,
},
mixins: [syncTask],
props: ['task'],
data () {
@@ -111,12 +204,19 @@ export default {
icons: Object.freeze({
close: closeIcon,
}),
assignedMembers: [],
members: [],
membersNameAndId: [],
memberNamesById: {},
};
},
computed: {
...mapGetters({
getTaskClasses: 'tasks:getTaskClasses',
}),
...mapState({
user: 'user.data',
}),
summarySentence () {
if (this.task.type === 'daily' && moment().isBefore(this.task.startDate)) {
return `This is ${this.formattedDifficulty(this.task.priority)} task that will repeat
@@ -148,6 +248,9 @@ export default {
return this.getTaskClasses(this.task, `edit-modal-${suffix}`);
},
formattedDate (date) {
return moment(date).format('MM/DD/YYYY');
},
formattedDays (frequency, repeat, daysOfMonth, weeksOfMonth, startDate) {
let activeDays;
const dayStringArray = [];
+3 -3
View File
@@ -3,9 +3,9 @@ import clone from 'lodash/clone';
export default {
methods: {
async syncTask () {
if (this.groupId) {
if (this.groupId || this.task?.group.id) {
const members = await this.$store.dispatch('members:getGroupMembers', {
groupId: this.groupId,
groupId: this.groupId || this.task?.group.id,
includeAllPublicFields: true,
});
this.members = members;
@@ -19,7 +19,7 @@ export default {
this.memberNamesById[member._id] = member.profile.name;
});
this.assignedMembers = [];
if (this.task.group?.assignedUsers) {
if (this.task?.group?.assignedUsers) {
this.assignedMembers = this.task.group.assignedUsers;
}
}
+3 -2
View File
@@ -175,7 +175,8 @@
"onlyCreatorOrAdminCanDeleteChat": "Not authorized to delete this message!",
"onlyGroupLeaderCanEditTasks": "Not authorized to manage tasks!",
"onlyGroupTasksCanBeAssigned": "Only group tasks can be assigned",
"assignedTo": "Assign To",
"assignTo": "Assign To",
"assignedTo": "Assigned to",
"assignedToUser": "Assigned: <strong>@<%- userName %></strong>",
"assignedToMembers": "<%= userCount %> users",
"assignedToYouAndMembers": "<strong>You</strong>, <%= userCount %> users",
@@ -363,7 +364,7 @@
"groupActivityNotificationTitle": "<%= user %> posted in <%= group %>",
"managerNotes": "Manager's Notes",
"assignedDateOnly": "Assigned on <strong><%= date %></strong>",
"assignedDateAndUser": "Assigned by <strong>@<%- username %></strong> on <strong><%= date %></strong>",
"assignedDateAndUser": "Assigned by @<%- username %> on <%= date %>",
"claimRewards": "Claim Rewards",
"dayStart": "<strong>Day start</strong>: <%= startTime %>",
"viewStatus": "Status",