|
|
|
@ -246,8 +246,8 @@
|
|
|
|
|
<!-- Comments -->
|
|
|
|
|
<comments :can-write="canWrite" :task-id="taskId"/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="column is-one-third action-buttons">
|
|
|
|
|
<a @click="$router.back()" class="is-fullwidth is-block has-text-centered mb-4" v-if="shouldShowClosePopup">
|
|
|
|
|
<div class="column is-one-third action-buttons" v-if="canWrite || shouldShowClosePopup">
|
|
|
|
|
<a @click="$router.back()" class="is-fullwidth is-block has-text-centered mb-4">
|
|
|
|
|
<icon icon="arrow-left"/>
|
|
|
|
|
{{ $t('task.detail.closePopup') }}
|
|
|
|
|
</a>
|
|
|
|
@ -385,27 +385,11 @@
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<!-- Created / Updated [by] -->
|
|
|
|
|
<p class="created">
|
|
|
|
|
<i18n-t keypath="task.detail.created">
|
|
|
|
|
<span v-tooltip="formatDate(task.created)">{{ formatDateSince(task.created) }}</span>
|
|
|
|
|
{{ task.createdBy.getDisplayName() }}
|
|
|
|
|
</i18n-t>
|
|
|
|
|
<template v-if="+new Date(task.created) !== +new Date(task.updated)">
|
|
|
|
|
<br/>
|
|
|
|
|
<!-- Computed properties to show the actual date every time it gets updated -->
|
|
|
|
|
<i18n-t keypath="task.detail.updated">
|
|
|
|
|
<span v-tooltip="updatedFormatted">{{ updatedSince }}</span>
|
|
|
|
|
</i18n-t>
|
|
|
|
|
</template>
|
|
|
|
|
<template v-if="task.done">
|
|
|
|
|
<br/>
|
|
|
|
|
<i18n-t keypath="task.detail.doneAt">
|
|
|
|
|
<span v-tooltip="doneFormatted">{{ doneSince }}</span>
|
|
|
|
|
</i18n-t>
|
|
|
|
|
</template>
|
|
|
|
|
</p>
|
|
|
|
|
<created-updated :task="task"/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- Created / Updated [by] -->
|
|
|
|
|
<created-updated :task="task" v-if="!canWrite && !shouldShowClosePopup"/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<transition name="modal">
|
|
|
|
@ -452,10 +436,12 @@ import {CURRENT_LIST} from '@/store/mutation-types'
|
|
|
|
|
|
|
|
|
|
import {uploadFile} from '@/helpers/attachments'
|
|
|
|
|
import ChecklistSummary from '../../components/tasks/partials/checklist-summary'
|
|
|
|
|
import CreatedUpdated from '@/components/tasks/partials/createdUpdated'
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
name: 'TaskDetailView',
|
|
|
|
|
components: {
|
|
|
|
|
CreatedUpdated,
|
|
|
|
|
ChecklistSummary,
|
|
|
|
|
TaskSubscription,
|
|
|
|
|
Datepicker,
|
|
|
|
@ -547,18 +533,6 @@ export default {
|
|
|
|
|
canWrite() {
|
|
|
|
|
return typeof this.task !== 'undefined' && typeof this.task.maxRight !== 'undefined' && this.task.maxRight > rights.READ
|
|
|
|
|
},
|
|
|
|
|
updatedSince() {
|
|
|
|
|
return this.formatDateSince(this.task.updated)
|
|
|
|
|
},
|
|
|
|
|
updatedFormatted() {
|
|
|
|
|
return this.formatDate(this.task.updated)
|
|
|
|
|
},
|
|
|
|
|
doneSince() {
|
|
|
|
|
return this.formatDateSince(this.task.doneAt)
|
|
|
|
|
},
|
|
|
|
|
doneFormatted() {
|
|
|
|
|
return this.formatDate(this.task.doneAt)
|
|
|
|
|
},
|
|
|
|
|
hasAttachments() {
|
|
|
|
|
return this.$store.state.attachments.attachments.length > 0
|
|
|
|
|
},
|
|
|
|
@ -697,239 +671,239 @@ export default {
|
|
|
|
|
$flash-background-duration: 750ms;
|
|
|
|
|
|
|
|
|
|
.task-view {
|
|
|
|
|
// This is a workaround to hide the llama background from the top on the task detail page
|
|
|
|
|
margin-top: -1.5rem;
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
background-color: var(--site-background);
|
|
|
|
|
// This is a workaround to hide the llama background from the top on the task detail page
|
|
|
|
|
margin-top: -1.5rem;
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
background-color: var(--site-background);
|
|
|
|
|
|
|
|
|
|
@media screen and (max-width: $desktop) {
|
|
|
|
|
padding-bottom: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.subtitle {
|
|
|
|
|
color: var(--grey-500);
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
|
|
|
|
|
a {
|
|
|
|
|
color: var(--grey-800);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
h3 .button {
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.icon.is-grey {
|
|
|
|
|
color: var(--grey-400);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.heading) {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
text-transform: none;
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
@media screen and (max-width: $tablet) {
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
@media screen and (max-width: $desktop) {
|
|
|
|
|
padding-bottom: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.title.input {
|
|
|
|
|
// 1.8rem is the font-size, 1.125 is the line-height, .3rem padding everywhere, 1px border around the whole thing.
|
|
|
|
|
min-height: calc(1.8rem * 1.125 + .6rem + 2px);
|
|
|
|
|
.subtitle {
|
|
|
|
|
color: var(--grey-500);
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
|
|
|
|
|
a {
|
|
|
|
|
color: var(--grey-800);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
h3 .button {
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.icon.is-grey {
|
|
|
|
|
color: var(--grey-400);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.heading) {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
text-transform: none;
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
@media screen and (max-width: $tablet) {
|
|
|
|
|
margin: 0 -.3rem .5rem -.3rem; // the title has 0.3rem padding - this make the text inside of it align with the rest
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: start;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.title.task-id {
|
|
|
|
|
color: var(--grey-400);
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
}
|
|
|
|
|
.title {
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
.title.input {
|
|
|
|
|
// 1.8rem is the font-size, 1.125 is the line-height, .3rem padding everywhere, 1px border around the whole thing.
|
|
|
|
|
min-height: calc(1.8rem * 1.125 + .6rem + 2px);
|
|
|
|
|
|
|
|
|
|
.date-input {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
@media screen and (max-width: $tablet) {
|
|
|
|
|
margin: 0 -.3rem .5rem -.3rem; // the title has 0.3rem padding - this make the text inside of it align with the rest
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a.remove {
|
|
|
|
|
color: var(--danger);
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
padding-left: .5rem;
|
|
|
|
|
line-height: 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.title.task-id {
|
|
|
|
|
color: var(--grey-400);
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.datepicker) {
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a.show {
|
|
|
|
|
color: var(--text);
|
|
|
|
|
padding: .25rem .5rem;
|
|
|
|
|
transition: background-color $transition;
|
|
|
|
|
border-radius: $radius;
|
|
|
|
|
display: block;
|
|
|
|
|
margin: .1rem 0;
|
|
|
|
|
.date-input {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
background: var(--white);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
a.remove {
|
|
|
|
|
color: var(--danger);
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
padding-left: .5rem;
|
|
|
|
|
line-height: 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&.disabled a.show:hover {
|
|
|
|
|
background: transparent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
:deep(.datepicker) {
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
|
|
.details {
|
|
|
|
|
padding-bottom: 0.75rem;
|
|
|
|
|
flex-flow: row wrap;
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
a.show {
|
|
|
|
|
color: var(--text);
|
|
|
|
|
padding: .25rem .5rem;
|
|
|
|
|
transition: background-color $transition;
|
|
|
|
|
border-radius: $radius;
|
|
|
|
|
display: block;
|
|
|
|
|
margin: .1rem 0;
|
|
|
|
|
|
|
|
|
|
.detail-title {
|
|
|
|
|
display: block;
|
|
|
|
|
color: var(--grey-400);
|
|
|
|
|
}
|
|
|
|
|
&:hover {
|
|
|
|
|
background: var(--white);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.none {
|
|
|
|
|
font-style: italic;
|
|
|
|
|
}
|
|
|
|
|
&.disabled a.show:hover {
|
|
|
|
|
background: transparent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Break after the 2nd element
|
|
|
|
|
.column:nth-child(2n) {
|
|
|
|
|
page-break-after: always; // CSS 2.1 syntax
|
|
|
|
|
break-after: always; // New syntax
|
|
|
|
|
}
|
|
|
|
|
.details {
|
|
|
|
|
padding-bottom: 0.75rem;
|
|
|
|
|
flex-flow: row wrap;
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
|
|
|
|
&.labels-list,
|
|
|
|
|
.assignees {
|
|
|
|
|
:deep(.multiselect) {
|
|
|
|
|
.input-wrapper {
|
|
|
|
|
&:not(:focus-within):not(:hover) {
|
|
|
|
|
background: transparent !important;
|
|
|
|
|
border-color: transparent !important;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.detail-title {
|
|
|
|
|
display: block;
|
|
|
|
|
color: var(--grey-400);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:deep(.details),
|
|
|
|
|
:deep(.heading) {
|
|
|
|
|
.input:not(.has-defaults),
|
|
|
|
|
.textarea,
|
|
|
|
|
.select:not(.has-defaults) select {
|
|
|
|
|
border-color: transparent;
|
|
|
|
|
background: transparent;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: all $transition-duration;
|
|
|
|
|
.none {
|
|
|
|
|
font-style: italic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&::placeholder {
|
|
|
|
|
color: var(--text-light);
|
|
|
|
|
opacity: 1;
|
|
|
|
|
font-style: italic;
|
|
|
|
|
}
|
|
|
|
|
// Break after the 2nd element
|
|
|
|
|
.column:nth-child(2n) {
|
|
|
|
|
page-break-after: always; // CSS 2.1 syntax
|
|
|
|
|
break-after: always; // New syntax
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&:not(:disabled) {
|
|
|
|
|
&:hover,
|
|
|
|
|
&:active,
|
|
|
|
|
&:focus {
|
|
|
|
|
background: var(--scheme-main);
|
|
|
|
|
border-color: var(--border);
|
|
|
|
|
cursor: text;
|
|
|
|
|
}
|
|
|
|
|
&.labels-list,
|
|
|
|
|
.assignees {
|
|
|
|
|
:deep(.multiselect) {
|
|
|
|
|
.input-wrapper {
|
|
|
|
|
&:not(:focus-within):not(:hover) {
|
|
|
|
|
background: transparent !important;
|
|
|
|
|
border-color: transparent !important;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&:hover,
|
|
|
|
|
&:active {
|
|
|
|
|
cursor: text;
|
|
|
|
|
border-color: var(--link)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
:deep(.details),
|
|
|
|
|
:deep(.heading) {
|
|
|
|
|
.input:not(.has-defaults),
|
|
|
|
|
.textarea,
|
|
|
|
|
.select:not(.has-defaults) select {
|
|
|
|
|
border-color: transparent;
|
|
|
|
|
background: transparent;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: all $transition-duration;
|
|
|
|
|
|
|
|
|
|
.select:not(.has-defaults):after {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
&::placeholder {
|
|
|
|
|
color: var(--text-light);
|
|
|
|
|
opacity: 1;
|
|
|
|
|
font-style: italic;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.select:not(.has-defaults):hover:after {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
&:not(:disabled) {
|
|
|
|
|
&:hover,
|
|
|
|
|
&:active,
|
|
|
|
|
&:focus {
|
|
|
|
|
background: var(--scheme-main);
|
|
|
|
|
border-color: var(--border);
|
|
|
|
|
cursor: text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.attachments {
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
&:hover,
|
|
|
|
|
&:active {
|
|
|
|
|
cursor: text;
|
|
|
|
|
border-color: var(--link)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
table tr:last-child td {
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.select:not(.has-defaults):after {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-buttons {
|
|
|
|
|
a.button {
|
|
|
|
|
width: 100%;
|
|
|
|
|
margin-bottom: .5rem;
|
|
|
|
|
justify-content: left;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.select:not(.has-defaults):hover:after {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.created {
|
|
|
|
|
font-size: .75rem;
|
|
|
|
|
color: var(--grey-500);
|
|
|
|
|
text-align: right;
|
|
|
|
|
}
|
|
|
|
|
.attachments {
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
|
|
|
|
.checklist-summary {
|
|
|
|
|
margin-left: .25rem;
|
|
|
|
|
}
|
|
|
|
|
table tr:last-child td {
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-buttons {
|
|
|
|
|
a.button {
|
|
|
|
|
width: 100%;
|
|
|
|
|
margin-bottom: .5rem;
|
|
|
|
|
justify-content: left;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.created {
|
|
|
|
|
font-size: .75rem;
|
|
|
|
|
color: var(--grey-500);
|
|
|
|
|
text-align: right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.checklist-summary {
|
|
|
|
|
margin-left: .25rem;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.task-view-container {
|
|
|
|
|
padding-bottom: 1rem;
|
|
|
|
|
padding-bottom: 1rem;
|
|
|
|
|
|
|
|
|
|
@media screen and (max-width: $desktop) {
|
|
|
|
|
padding-bottom: 0;
|
|
|
|
|
}
|
|
|
|
|
@media screen and (max-width: $desktop) {
|
|
|
|
|
padding-bottom: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.task-view * {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transition: opacity 50ms ease;
|
|
|
|
|
}
|
|
|
|
|
.task-view * {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transition: opacity 50ms ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&.is-loading {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
&.is-loading {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
|
|
|
|
.task-view * {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.task-view * {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&.visible:not(.is-loading) .task-view * {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
&.visible:not(.is-loading) .task-view * {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.task-view-container {
|
|
|
|
|
// simulate sass lighten($primary, 30) by increasing lightness 30% to 73%
|
|
|
|
|
--primary-light: hsla(var(--primary-h), var(--primary-s), 73%, var(--primary-a));
|
|
|
|
|
// simulate sass lighten($primary, 30) by increasing lightness 30% to 73%
|
|
|
|
|
--primary-light: hsla(var(--primary-h), var(--primary-s), 73%, var(--primary-a));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.flash-background-enter-from,
|
|
|
|
|
.flash-background-enter-active {
|
|
|
|
|
animation: flash-background $flash-background-duration ease 1;
|
|
|
|
|
.flash-background-enter-active {
|
|
|
|
|
animation: flash-background $flash-background-duration ease 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes flash-background {
|
|
|
|
|
0% {
|
|
|
|
|
background: var(--primary-light);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
background: transparent;
|
|
|
|
|
}
|
|
|
|
|
0% {
|
|
|
|
|
background: var(--primary-light);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
background: transparent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|