Merge branch 'main' into vue3
# Conflicts: # src/components/input/editor.vue # src/components/list/partials/filters.vue # src/components/tasks/partials/editAssignees.vue # src/helpers/find.ts # src/helpers/time/formatDate.js # src/main.ts # src/store/modules/attachments.js # src/store/modules/kanban.js # src/views/list/views/List.vue # yarn.lock
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
>
|
||||
<div class="container has-text-centered link-share-view">
|
||||
<div class="column is-10 is-offset-1">
|
||||
<img alt="Vikunja" class="logo" src="/images/logo-full.svg"/>
|
||||
<img alt="Vikunja" class="logo" :src="logoUrl" />
|
||||
<h1
|
||||
:style="{ 'opacity': currentList.title === '' ? '0': '1' }"
|
||||
class="title">
|
||||
@ -27,8 +27,15 @@
|
||||
import {mapState} from 'vuex'
|
||||
import {CURRENT_LIST} from '@/store/mutation-types'
|
||||
|
||||
import logoUrl from '@/assets/logo-full.svg'
|
||||
|
||||
export default {
|
||||
name: 'contentLinkShare',
|
||||
data() {
|
||||
return {
|
||||
logoUrl,
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
currentList: CURRENT_LIST,
|
||||
background: 'background',
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="no-auth-wrapper">
|
||||
<div class="noauth-container">
|
||||
<img alt="Vikunja" src="/images/logo-full.svg" width="400" height="117"/>
|
||||
<img alt="Vikunja" :src="logoUrl" width="400" height="117" />
|
||||
<div class="message is-info" v-if="motd !== ''">
|
||||
<div class="message-header">
|
||||
<p>{{ $t('misc.info') }}</p>
|
||||
@ -18,8 +18,15 @@
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
import logoUrl from '@/assets/logo-full.svg'
|
||||
|
||||
export default {
|
||||
name: 'contentNoAuth',
|
||||
data() {
|
||||
return {
|
||||
logoUrl,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.redirectToHome()
|
||||
},
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div :class="{'is-active': menuActive}" class="namespace-container">
|
||||
<div class="menu top-menu">
|
||||
<router-link :to="{name: 'home'}" class="logo">
|
||||
<img alt="Vikunja" src="/images/logo-full.svg" width="164" height="48"/>
|
||||
<img alt="Vikunja" :src="logoUrl" width="164" height="48"/>
|
||||
</router-link>
|
||||
<ul class="menu-list">
|
||||
<li>
|
||||
@ -162,6 +162,8 @@ import NamespaceSettingsDropdown from '@/components/namespace/namespace-settings
|
||||
import draggable from 'vuedraggable'
|
||||
import {calculateItemPosition} from '@/helpers/calculateItemPosition'
|
||||
|
||||
import logoUrl from '@/assets/logo-full.svg'
|
||||
|
||||
export default {
|
||||
name: 'navigation',
|
||||
data() {
|
||||
@ -173,6 +175,7 @@ export default {
|
||||
ghostClass: 'ghost',
|
||||
},
|
||||
listUpdating: {},
|
||||
logoUrl,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
@ -7,8 +7,7 @@
|
||||
>
|
||||
<div class="navbar-brand">
|
||||
<router-link :to="{name: 'home'}" class="navbar-item logo">
|
||||
<img width="164" height="48" alt="Vikunja" src="/images/logo-full-pride.svg" v-if="(new Date()).getMonth() === 5"/>
|
||||
<img width="164" height="48" alt="Vikunja" src="/images/logo-full.svg" v-else/>
|
||||
<img width="164" height="48" alt="Vikunja" :src="logoUrl" />
|
||||
</router-link>
|
||||
<a
|
||||
@click="$store.commit('toggleMenu')"
|
||||
@ -103,6 +102,9 @@ import ListSettingsDropdown from '@/components/list/list-settings-dropdown.vue'
|
||||
import Dropdown from '@/components/misc/dropdown.vue'
|
||||
import Notifications from '@/components/notifications/notifications.vue'
|
||||
|
||||
import logoUrl from '@/assets/logo-full.svg'
|
||||
import logoFullPrideUrl from '@/assets/logo-full-pride.svg'
|
||||
|
||||
export default {
|
||||
name: 'topNavigation',
|
||||
components: {
|
||||
@ -111,16 +113,21 @@ export default {
|
||||
ListSettingsDropdown,
|
||||
Update,
|
||||
},
|
||||
computed: mapState({
|
||||
userInfo: state => state.auth.info,
|
||||
userAvatar: state => state.auth.avatarUrl,
|
||||
userAuthenticated: state => state.auth.authenticated,
|
||||
currentList: CURRENT_LIST,
|
||||
background: 'background',
|
||||
imprintUrl: state => state.config.legal.imprintUrl,
|
||||
privacyPolicyUrl: state => state.config.legal.privacyPolicyUrl,
|
||||
canWriteCurrentList: state => state.currentList.maxRight > Rights.READ,
|
||||
}),
|
||||
computed: {
|
||||
logoUrl() {
|
||||
return (new Date()).getMonth() === 5 ? logoFullPrideUrl : logoUrl
|
||||
},
|
||||
...mapState({
|
||||
userInfo: state => state.auth.info,
|
||||
userAvatar: state => state.auth.avatarUrl,
|
||||
userAuthenticated: state => state.auth.authenticated,
|
||||
currentList: CURRENT_LIST,
|
||||
background: 'background',
|
||||
imprintUrl: state => state.config.legal.imprintUrl,
|
||||
privacyPolicyUrl: state => state.config.legal.privacyPolicyUrl,
|
||||
canWriteCurrentList: state => state.currentList.maxRight > Rights.READ,
|
||||
}),
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
if (typeof this.$refs.usernameDropdown === 'undefined' || typeof this.$refs.listTitle === 'undefined') {
|
||||
|
@ -13,7 +13,7 @@
|
||||
<div class="preview content" v-html="preview" v-if="isPreviewActive && text !== ''">
|
||||
</div>
|
||||
|
||||
<p class="has-text-centered has-text-grey is-italic" v-if="showPreviewText">
|
||||
<p class="has-text-centered has-text-grey is-italic my-5" v-if="showPreviewText">
|
||||
{{ emptyText }}
|
||||
<template v-if="isEditEnabled">
|
||||
<a @click="toggleEdit">{{ $t('input.editor.edit') }}</a>.
|
||||
@ -22,20 +22,20 @@
|
||||
|
||||
<ul class="actions" v-if="bottomActions.length > 0">
|
||||
<li v-if="isEditEnabled && !showPreviewText && showSave">
|
||||
<a v-if="!isEditActive" @click="toggleEdit">{{ $t('input.editor.edit') }}</a>
|
||||
<a v-else @click="toggleEdit" class="done-edit">{{ $t('misc.save') }}</a>
|
||||
<a v-if="showEditButton" @click="toggleEdit">{{ $t('input.editor.edit') }}</a>
|
||||
<a v-else-if="isEditActive" @click="toggleEdit" class="done-edit">{{ $t('misc.save') }}</a>
|
||||
</li>
|
||||
<li v-for="(action, k) in bottomActions" :key="k">
|
||||
<a @click="action.action">{{ action.title }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<template v-else-if="isEditEnabled && showSave">
|
||||
<ul v-if="!isEditActive" class="actions">
|
||||
<ul v-if="showEditButton" class="actions">
|
||||
<li>
|
||||
<a @click="toggleEdit">{{ $t('input.editor.edit') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<x-button v-else @click="toggleEdit" type="secondary" :shadow="false">
|
||||
<x-button v-else-if="isEditActive" @click="toggleEdit" type="secondary" :shadow="false">
|
||||
{{ $t('misc.save') }}
|
||||
</x-button>
|
||||
</template>
|
||||
@ -103,6 +103,9 @@ export default {
|
||||
showPreviewText() {
|
||||
return this.isPreviewActive && this.text === '' && this.emptyText !== ''
|
||||
},
|
||||
showEditButton() {
|
||||
return !this.isEditActive && this.text !== ''
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -178,9 +178,8 @@ import Fancycheckbox from '../../input/fancycheckbox'
|
||||
import flatPickr from 'vue-flatpickr-component'
|
||||
import 'flatpickr/dist/flatpickr.css'
|
||||
|
||||
import {includesById} from '@/helpers/utils'
|
||||
import {formatISO} from 'date-fns'
|
||||
import differenceWith from 'lodash/differenceWith'
|
||||
|
||||
import PrioritySelect from '@/components/tasks/partials/prioritySelect.vue'
|
||||
import PercentDoneSelect from '@/components/tasks/partials/percentDoneSelect.vue'
|
||||
import Multiselect from '@/components/input/multiselect.vue'
|
||||
@ -270,13 +269,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
foundLabels() {
|
||||
const labels = (Object.values(this.$store.state.labels.labels).filter(l => {
|
||||
return l.title.toLowerCase().includes(this.labelQuery.toLowerCase())
|
||||
}) ?? [])
|
||||
|
||||
return differenceWith(labels, this.labels, (first, second) => {
|
||||
return first.id === second.id
|
||||
})
|
||||
return this.$store.getters['labels/filterLabelsByQuery'](this.labels, this.query)
|
||||
},
|
||||
flatPickerConfig() {
|
||||
return {
|
||||
@ -310,8 +303,13 @@ export default {
|
||||
this.prepareRelatedObjectFilter('namespace')
|
||||
|
||||
this.prepareSingleValue('labels')
|
||||
const labelIds = (typeof this.filters.labels === 'string' ? this.filters.labels : '').split(',').map(i => parseInt(i))
|
||||
this.labels = (Object.values(this.$store.state.labels.labels).filter(l => labelIds.includes(l.id)) ?? [])
|
||||
|
||||
const labels = typeof this.filters.labels === 'string'
|
||||
? this.filters.labels
|
||||
: ''
|
||||
const labelIds = labels.split(',').map(i => parseInt(i))
|
||||
|
||||
this.labels = this.$store.getters['labels/getLabelsByIds'](labelIds)
|
||||
},
|
||||
removePropertyFromFilter(propertyName) {
|
||||
// Because of the way arrays work, we can only ever remove one element at once.
|
||||
@ -534,10 +532,8 @@ export default {
|
||||
|
||||
this[`${kind}Service`].getAll({}, {s: query})
|
||||
.then(response => {
|
||||
// Filter the results to not include users who are already assigneid
|
||||
this[`found${kind}`] = differenceWith(response, this[kind], (first, second) => {
|
||||
return first.id === second.id
|
||||
})
|
||||
// Filter users from the results who are already assigned
|
||||
this[`found${kind}`] = response.filter(({id}) => !includesById(this[kind], id))
|
||||
})
|
||||
.catch(e => {
|
||||
this.$message.error(e)
|
||||
|
@ -34,11 +34,11 @@
|
||||
class="migration-in-progress-container"
|
||||
v-else-if="isMigrating === true && message === '' && lastMigrationDate === null">
|
||||
<div class="migration-in-progress">
|
||||
<img :alt="name" :src="`/images/migration/${identifier}.png`"/>
|
||||
<img :alt="name" :src="serviceIconSource"/>
|
||||
<div class="progress-dots">
|
||||
<span v-for="i in progressDotsCount" :key="i" />
|
||||
</div>
|
||||
<img alt="Vikunja" src="/images/logo.svg">
|
||||
<img alt="Vikunja" :src="logoUrl">
|
||||
</div>
|
||||
<p>{{ $t('migrate.inProgress') }}</p>
|
||||
</div>
|
||||
@ -66,6 +66,9 @@
|
||||
<script>
|
||||
import AbstractMigrationService from '../../services/migrator/abstractMigration'
|
||||
import AbstractMigrationFileService from '../../services/migrator/abstractMigrationFile'
|
||||
import {SERVICE_ICONS} from '../../helpers/migrator'
|
||||
|
||||
import logoUrl from '@/assets/logo.svg'
|
||||
|
||||
const PROGRESS_DOTS_COUNT = 8
|
||||
|
||||
@ -80,6 +83,7 @@ export default {
|
||||
message: '',
|
||||
migratorAuthCode: '',
|
||||
migrationService: null,
|
||||
logoUrl,
|
||||
}
|
||||
},
|
||||
props: {
|
||||
@ -96,6 +100,11 @@ export default {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
serviceIconSource() {
|
||||
return SERVICE_ICONS[this.identifier]()
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.message = ''
|
||||
|
||||
|
@ -102,7 +102,7 @@
|
||||
>
|
||||
{{ t.title }}
|
||||
</span>
|
||||
<priority-label :priority="t.priority"/>
|
||||
<priority-label :priority="t.priority" :done="t.done"/>
|
||||
<!-- using the key here forces vue to use the updated version model and not the response returned by the api -->
|
||||
<a @click="editTask(theTasks[k])" class="edit-toggle">
|
||||
<icon icon="pen"/>
|
||||
@ -192,7 +192,6 @@ import TaskCollectionService from '../../services/taskCollection'
|
||||
import {mapState} from 'vuex'
|
||||
import Rights from '../../models/constants/rights.json'
|
||||
import FilterPopup from '@/components/list/partials/filter-popup.vue'
|
||||
import {format} from 'date-fns'
|
||||
|
||||
export default {
|
||||
name: 'GanttChart',
|
||||
@ -466,7 +465,7 @@ export default {
|
||||
})
|
||||
},
|
||||
formatYear(date) {
|
||||
return format(date, 'MMMM, yyyy')
|
||||
return this.format(date, 'MMMM, yyyy')
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import TaskCollectionService from '@/services/taskCollection'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
// FIXME: merge with DEFAULT_PARAMS in filters.vue
|
||||
const DEFAULT_PARAMS = {
|
||||
@ -83,7 +82,7 @@ export default {
|
||||
this.tasks = r
|
||||
this.currentPage = page
|
||||
|
||||
this.loadedList = cloneDeep(currentList)
|
||||
this.loadedList = JSON.parse(JSON.stringify(currentList))
|
||||
})
|
||||
.catch(e => {
|
||||
this.$message.error(e)
|
||||
|
@ -29,8 +29,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import differenceWith from 'lodash/differenceWith'
|
||||
|
||||
import {includesById} from '@/helpers/utils'
|
||||
import UserModel from '../../../models/user'
|
||||
import ListUserService from '../../../services/listUsers'
|
||||
import TaskAssigneeService from '../../../services/taskAssignee'
|
||||
@ -112,9 +111,7 @@ export default {
|
||||
this.listUserService.getAll({listId: this.listId}, {s: query})
|
||||
.then(response => {
|
||||
// Filter the results to not include users who are already assigned
|
||||
this.foundUsers = differenceWith(response, this.assignees, (first, second) => {
|
||||
return first.id === second.id
|
||||
})
|
||||
this.foundUsers = response.filter(({id}) => !includesById(this.assignees, id))
|
||||
})
|
||||
.catch(e => {
|
||||
this.$message.error(e)
|
||||
|
@ -38,8 +38,6 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import differenceWith from 'lodash/differenceWith'
|
||||
|
||||
import LabelModel from '../../../models/label'
|
||||
import LabelTaskService from '../../../services/labelTask'
|
||||
|
||||
@ -84,13 +82,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
foundLabels() {
|
||||
const labels = (Object.values(this.$store.state.labels.labels).filter(l => {
|
||||
return l.title.toLowerCase().includes(this.query.toLowerCase())
|
||||
}) ?? [])
|
||||
|
||||
return differenceWith(labels, this.labels, (first, second) => {
|
||||
return first.id === second.id
|
||||
})
|
||||
return this.$store.getters['labels/filterLabelsByQuery'](this.labels, this.query)
|
||||
},
|
||||
loading() {
|
||||
return this.labelTaskService.loading || (this.$store.state[LOADING] && this.$store.state[LOADING_MODULE] === 'labels')
|
||||
@ -157,7 +149,7 @@ export default {
|
||||
.then(r => {
|
||||
this.addLabel(r, false)
|
||||
this.labels.push(r)
|
||||
this.$message.success({message: this.$t('task.label.removeSuccess')})
|
||||
this.$message.success({message: this.$t('task.label.addCreateSuccess')})
|
||||
})
|
||||
.catch(e => {
|
||||
this.$message.error(e)
|
||||
|
@ -41,7 +41,7 @@
|
||||
</progress>
|
||||
<div class="footer">
|
||||
<labels :labels="task.labels"/>
|
||||
<priority-label :priority="task.priority"/>
|
||||
<priority-label :priority="task.priority" :done="task.done"/>
|
||||
<div class="assignees" v-if="task.assignees.length > 0">
|
||||
<user
|
||||
:avatar-size="24"
|
||||
@ -51,6 +51,7 @@
|
||||
v-for="u in task.assignees"
|
||||
/>
|
||||
</div>
|
||||
<checklist-summary :task="task"/>
|
||||
<span class="icon" v-if="task.attachments.length > 0">
|
||||
<icon icon="paperclip"/>
|
||||
</span>
|
||||
@ -66,10 +67,12 @@ import {playPop} from '../../../helpers/playPop'
|
||||
import PriorityLabel from '../../../components/tasks/partials/priorityLabel'
|
||||
import User from '../../../components/misc/user'
|
||||
import Labels from '../../../components/tasks/partials/labels'
|
||||
import ChecklistSummary from './checklist-summary'
|
||||
|
||||
export default {
|
||||
name: 'kanban-card',
|
||||
components: {
|
||||
ChecklistSummary,
|
||||
PriorityLabel,
|
||||
User,
|
||||
Labels,
|
||||
|
@ -2,7 +2,7 @@
|
||||
<span
|
||||
:class="{'not-so-high': priority === priorities.HIGH, 'high-priority': priority >= priorities.HIGH}"
|
||||
class="priority-label"
|
||||
v-if="showAll || priority >= priorities.HIGH">
|
||||
v-if="!done && (showAll || priority >= priorities.HIGH)">
|
||||
<span class="icon" v-if="priority >= priorities.HIGH">
|
||||
<icon icon="exclamation"/>
|
||||
</span>
|
||||
@ -39,6 +39,10 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
done: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
@ -56,9 +56,9 @@
|
||||
<div class="control is-expanded">
|
||||
<div class="select is-fullwidth has-defaults">
|
||||
<select v-model="newTaskRelationKind">
|
||||
<option value="unset">Select a relation kind</option>
|
||||
<option :key="rk" :value="rk" v-for="(label, rk) in relationKinds">
|
||||
{{ label[0] }}
|
||||
<option value="unset">{{ $t('task.relation.select') }}</option>
|
||||
<option :key="rk" :value="rk" v-for="rk in relationKinds">
|
||||
{{ $tc(`task.relation.kinds.${rk}`, 1) }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
@ -256,10 +256,7 @@ export default {
|
||||
})
|
||||
},
|
||||
relationKindTitle(kind, length) {
|
||||
if (length > 1) {
|
||||
return relationKinds[kind][1]
|
||||
}
|
||||
return relationKinds[kind][0]
|
||||
return this.$tc(`task.relation.kinds.${kind}`, length)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -50,7 +50,7 @@
|
||||
<transition name="fade">
|
||||
<defer-task v-if="+new Date(task.dueDate) > 0 && showDefer" v-model="task" ref="deferDueDate"/>
|
||||
</transition>
|
||||
<priority-label :priority="task.priority"/>
|
||||
<priority-label :priority="task.priority" :done="task.done"/>
|
||||
<span>
|
||||
<span class="list-task-icon" v-if="task.attachments.length > 0">
|
||||
<icon icon="paperclip"/>
|
||||
|
Reference in New Issue
Block a user