Compare commits
20 Commits
33809e1882
...
97ac2856de
Author | SHA1 | Date |
---|---|---|
renovate | 97ac2856de | |
waza-ari | f0d695e789 | |
kolaente | 95276ceebe | |
kolaente | 1558921f42 | |
kolaente | bf5088e546 | |
kolaente | 6f366d4907 | |
kolaente | d7554d9e70 | |
kolaente | 8a72fe26f8 | |
kolaente | 13cab62d14 | |
kolaente | 81de986d8d | |
kolaente | 915f677c2a | |
kolaente | 8a6e3d5bd7 | |
kolaente | 81fe8391e4 | |
kolaente | 89e37b88d9 | |
kolaente | cc6801c5b1 | |
kolaente | 767b058915 | |
kolaente | 2c0d3f2885 | |
renovate | fa170b9397 | |
kolaente | a5fd6f834a | |
renovate | 8984e0e9f0 |
|
@ -461,7 +461,6 @@ steps:
|
|||
- cp -r dist-test dist-preview
|
||||
# Override the default api url used for preview
|
||||
- sed -i 's|http://localhost:3456|https://try.vikunja.io|g' dist-preview/index.html
|
||||
- apk add --no-cache perl-utils
|
||||
# create via:
|
||||
# `shasum -a 384 ./scripts/deploy-preview-netlify.mjs > ./scripts/deploy-preview-netlify.mjs.sha384`
|
||||
- shasum -a 384 -c ./scripts/deploy-preview-netlify.mjs.sha384
|
||||
|
@ -1401,6 +1400,6 @@ steps:
|
|||
- failure
|
||||
---
|
||||
kind: signature
|
||||
hmac: a5d31a6cb5eb6482e72bea619ee391ff2b8118b9865e3896a607b8a7e874a797
|
||||
hmac: c312afe632177a2d45f47c429bf6c7528af3c51a097430956558532ccdcc42b9
|
||||
|
||||
...
|
||||
|
|
|
@ -1 +1 @@
|
|||
20.12.0
|
||||
20.12.1
|
|
@ -21,7 +21,7 @@ describe('Project View Table', () => {
|
|||
TaskFactory.create(1)
|
||||
cy.visit('/projects/1/3')
|
||||
|
||||
cy.get('.project-table .filter-container .items .button')
|
||||
cy.get('.project-table .filter-container .button')
|
||||
.contains('Columns')
|
||||
.click()
|
||||
cy.get('.project-table .filter-container .card.columns-filter .card-content .fancycheckbox')
|
||||
|
|
|
@ -58,8 +58,8 @@
|
|||
"@infectoone/vue-ganttastic": "2.3.1",
|
||||
"@intlify/unplugin-vue-i18n": "3.0.1",
|
||||
"@kyvg/vue3-notification": "3.2.1",
|
||||
"@sentry/tracing": "7.108.0",
|
||||
"@sentry/vue": "7.108.0",
|
||||
"@sentry/tracing": "7.109.0",
|
||||
"@sentry/vue": "7.109.0",
|
||||
"@tiptap/core": "2.2.4",
|
||||
"@tiptap/extension-blockquote": "2.2.4",
|
||||
"@tiptap/extension-bold": "2.2.4",
|
||||
|
|
|
@ -38,11 +38,11 @@ dependencies:
|
|||
specifier: 3.2.1
|
||||
version: 3.2.1(vue@3.4.21)
|
||||
'@sentry/tracing':
|
||||
specifier: 7.108.0
|
||||
version: 7.108.0
|
||||
specifier: 7.109.0
|
||||
version: 7.109.0
|
||||
'@sentry/vue':
|
||||
specifier: 7.108.0
|
||||
version: 7.108.0(vue@3.4.21)
|
||||
specifier: 7.109.0
|
||||
version: 7.109.0(vue@3.4.21)
|
||||
'@tiptap/core':
|
||||
specifier: 2.2.4
|
||||
version: 2.2.4(@tiptap/pm@2.2.4)
|
||||
|
@ -3249,45 +3249,45 @@ packages:
|
|||
resolution: {integrity: sha512-0HejFckBN2W+ucM6cUOlwsByTKt9/+0tWhqUffNIcHqCXkthY/mZ7AuYPK/2IIaGWhdl0h+tICDO0ssLMd6XMQ==}
|
||||
dev: true
|
||||
|
||||
/@sentry-internal/feedback@7.108.0:
|
||||
resolution: {integrity: sha512-8JcgZEnk1uWrXJhsd3iRvFtEiVeaWOEhN0NZwhwQXHfvODqep6JtrkY1yCIyxbpA37aZmrPc2JhyotRERGfUjg==}
|
||||
/@sentry-internal/feedback@7.109.0:
|
||||
resolution: {integrity: sha512-EL7N++poxvJP9rYvh6vSu24tsKkOveNCcCj4IM7+irWPjsuD2GLYYlhp/A/Mtt9l7iqO4plvtiQU5HGk7smcTQ==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
'@sentry/core': 7.108.0
|
||||
'@sentry/types': 7.108.0
|
||||
'@sentry/utils': 7.108.0
|
||||
'@sentry/core': 7.109.0
|
||||
'@sentry/types': 7.109.0
|
||||
'@sentry/utils': 7.109.0
|
||||
dev: false
|
||||
|
||||
/@sentry-internal/replay-canvas@7.108.0:
|
||||
resolution: {integrity: sha512-R5tvjGqWUV5vSk0N1eBgVW7wIADinrkfDEBZ9FyKP2mXHBobsyNGt30heJDEqYmVqluRqjU2NuIRapsnnrpGnA==}
|
||||
/@sentry-internal/replay-canvas@7.109.0:
|
||||
resolution: {integrity: sha512-Lh/K60kmloR6lkPUcQP0iamw7B/MdEUEx/ImAx4tUSMrLj+IoUEcq/ECgnnVyQkJq59+8nPEKrVLt7x6PUPEjw==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
'@sentry/core': 7.108.0
|
||||
'@sentry/replay': 7.108.0
|
||||
'@sentry/types': 7.108.0
|
||||
'@sentry/utils': 7.108.0
|
||||
'@sentry/core': 7.109.0
|
||||
'@sentry/replay': 7.109.0
|
||||
'@sentry/types': 7.109.0
|
||||
'@sentry/utils': 7.109.0
|
||||
dev: false
|
||||
|
||||
/@sentry-internal/tracing@7.108.0:
|
||||
resolution: {integrity: sha512-zuK5XsTsb+U+hgn3SPetYDAogrXsM16U/LLoMW7+TlC6UjlHGYQvmX3o+M2vntejoU1QZS8m1bCAZSMWEypAEw==}
|
||||
/@sentry-internal/tracing@7.109.0:
|
||||
resolution: {integrity: sha512-PzK/joC5tCuh2R/PRh+7dp+uuZl7pTsBIjPhVZHMTtb9+ls65WkdZJ1/uKXPouyz8NOo9Xok7aEvEo9seongyw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@sentry/core': 7.108.0
|
||||
'@sentry/types': 7.108.0
|
||||
'@sentry/utils': 7.108.0
|
||||
'@sentry/core': 7.109.0
|
||||
'@sentry/types': 7.109.0
|
||||
'@sentry/utils': 7.109.0
|
||||
dev: false
|
||||
|
||||
/@sentry/browser@7.108.0:
|
||||
resolution: {integrity: sha512-FNpzsdTvGvdHJMUelqEouUXMZU7jC+dpN7CdT6IoHVVFEkoAgrjMVUhXZoQ/dmCkdKWHmFSQhJ8Fm6V+e9Aq0A==}
|
||||
/@sentry/browser@7.109.0:
|
||||
resolution: {integrity: sha512-yx+OFG+Ab9qUDDgV9ZDv8M9O9Mqr0fjKta/LMlWALYLjzkMvxsPlRPFj7oMBlHqOTVLDeg7lFYmsA8wyWQ8Z8g==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@sentry-internal/feedback': 7.108.0
|
||||
'@sentry-internal/replay-canvas': 7.108.0
|
||||
'@sentry-internal/tracing': 7.108.0
|
||||
'@sentry/core': 7.108.0
|
||||
'@sentry/replay': 7.108.0
|
||||
'@sentry/types': 7.108.0
|
||||
'@sentry/utils': 7.108.0
|
||||
'@sentry-internal/feedback': 7.109.0
|
||||
'@sentry-internal/replay-canvas': 7.109.0
|
||||
'@sentry-internal/tracing': 7.109.0
|
||||
'@sentry/core': 7.109.0
|
||||
'@sentry/replay': 7.109.0
|
||||
'@sentry/types': 7.109.0
|
||||
'@sentry/utils': 7.109.0
|
||||
dev: false
|
||||
|
||||
/@sentry/cli@2.19.1:
|
||||
|
@ -3306,53 +3306,53 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@sentry/core@7.108.0:
|
||||
resolution: {integrity: sha512-I/VNZCFgLASxHZaD0EtxZRM34WG9w2gozqgrKGNMzAymwmQ3K9g/1qmBy4e6iS3YRptb7J5UhQkZQHrcwBbjWQ==}
|
||||
/@sentry/core@7.109.0:
|
||||
resolution: {integrity: sha512-xwD4U0IlvvlE/x/g/W1I8b4Cfb16SsCMmiEuBf6XxvAa3OfWBxKoqLifb3GyrbxMC4LbIIZCN/SvLlnGJPgszA==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@sentry/types': 7.108.0
|
||||
'@sentry/utils': 7.108.0
|
||||
'@sentry/types': 7.109.0
|
||||
'@sentry/utils': 7.109.0
|
||||
dev: false
|
||||
|
||||
/@sentry/replay@7.108.0:
|
||||
resolution: {integrity: sha512-jo8fDOzcZJclP1+4n9jUtVxTlBFT9hXwxhAMrhrt70FV/nfmCtYQMD3bzIj79nwbhUtFP6pN39JH1o7Xqt1hxQ==}
|
||||
/@sentry/replay@7.109.0:
|
||||
resolution: {integrity: sha512-hCDjbTNO7ErW/XsaBXlyHFsUhneyBUdTec1Swf98TFEfVqNsTs6q338aUcaR8dGRLbLrJ9YU9D1qKq++v5h2CA==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
'@sentry-internal/tracing': 7.108.0
|
||||
'@sentry/core': 7.108.0
|
||||
'@sentry/types': 7.108.0
|
||||
'@sentry/utils': 7.108.0
|
||||
'@sentry-internal/tracing': 7.109.0
|
||||
'@sentry/core': 7.109.0
|
||||
'@sentry/types': 7.109.0
|
||||
'@sentry/utils': 7.109.0
|
||||
dev: false
|
||||
|
||||
/@sentry/tracing@7.108.0:
|
||||
resolution: {integrity: sha512-wfAEEK1pa/PieFjVHv7Li4z280WcL+1Eg4tL8xN8/yq1oPFHLhjOmWRvKN9cm818N8ntZIFB0jGLu4ETM5jDCw==}
|
||||
/@sentry/tracing@7.109.0:
|
||||
resolution: {integrity: sha512-lgveekdd/XLgQ6oZLvcRGUWBIOAZ7QwbjLHEd8zzeKubHbIwFzMkhIejskqLi2z2OwzrYl5q+Zo1jS1z9f62YQ==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@sentry-internal/tracing': 7.108.0
|
||||
'@sentry-internal/tracing': 7.109.0
|
||||
dev: false
|
||||
|
||||
/@sentry/types@7.108.0:
|
||||
resolution: {integrity: sha512-bKtHITmBN3kqtqE5eVvL8mY8znM05vEodENwRpcm6TSrrBjC2RnwNWVwGstYDdHpNfFuKwC8mLY9bgMJcENo8g==}
|
||||
/@sentry/types@7.109.0:
|
||||
resolution: {integrity: sha512-egCBnDv3YpVFoNzRLdP0soVrxVLCQ+rovREKJ1sw3rA2/MFH9WJ+DZZexsX89yeAFzy1IFsCp7/dEqudusml6g==}
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
|
||||
/@sentry/utils@7.108.0:
|
||||
resolution: {integrity: sha512-a45yEFD5qtgZaIFRAcFkG8C8lnDzn6t4LfLXuV4OafGAy/3ZAN3XN8wDnrruHkiUezSSANGsLg3bXaLW/JLvJw==}
|
||||
/@sentry/utils@7.109.0:
|
||||
resolution: {integrity: sha512-3RjxMOLMBwZ5VSiH84+o/3NY2An4Zldjz0EbfEQNRY9yffRiCPJSQiCJID8EoylCFOh/PAhPimBhqbtWJxX6iw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@sentry/types': 7.108.0
|
||||
'@sentry/types': 7.109.0
|
||||
dev: false
|
||||
|
||||
/@sentry/vue@7.108.0(vue@3.4.21):
|
||||
resolution: {integrity: sha512-hnqL/LIq3i4dJVMFq0oP8OP5ybMRYcW5dhtzlJFKo3A9i0BRzC4VUUcDnm1zTT9Um1YIU19mOy0cJBGplRQB9g==}
|
||||
/@sentry/vue@7.109.0(vue@3.4.21):
|
||||
resolution: {integrity: sha512-aATuLXJB7YJaezedwP71sGeVabt9moyvxlZZdTU+LdgTizdMZk3zvWF/Uen6HGCgvKerDYt52zSHWSQvDHCvLw==}
|
||||
engines: {node: '>=8'}
|
||||
peerDependencies:
|
||||
vue: 2.x || 3.x
|
||||
dependencies:
|
||||
'@sentry/browser': 7.108.0
|
||||
'@sentry/core': 7.108.0
|
||||
'@sentry/types': 7.108.0
|
||||
'@sentry/utils': 7.108.0
|
||||
'@sentry/browser': 7.109.0
|
||||
'@sentry/core': 7.109.0
|
||||
'@sentry/types': 7.109.0
|
||||
'@sentry/utils': 7.109.0
|
||||
vue: 3.4.21(typescript@5.4.2)
|
||||
dev: false
|
||||
|
||||
|
|
|
@ -16,9 +16,11 @@ import {useColorScheme} from '@/composables/useColorScheme'
|
|||
const {
|
||||
entityKind,
|
||||
entityId,
|
||||
disabled = false,
|
||||
} = defineProps<{
|
||||
entityKind: ReactionKind,
|
||||
entityId: number,
|
||||
disabled?: boolean,
|
||||
}>()
|
||||
|
||||
const authStore = useAuthStore()
|
||||
|
@ -143,11 +145,13 @@ async function toggleReaction(value: string) {
|
|||
v-tooltip="getReactionTooltip(users, value)"
|
||||
class="reaction-button"
|
||||
:class="{'current-user-has-reacted': hasCurrentUserReactedWithEmoji(value)}"
|
||||
:disabled
|
||||
@click="toggleReaction(value)"
|
||||
>
|
||||
{{ value }} {{ users.length }}
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
v-if="!disabled"
|
||||
ref="emojiPickerButtonRef"
|
||||
v-tooltip="$t('reaction.add')"
|
||||
class="reaction-button"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
}"
|
||||
>
|
||||
<template v-if="icon">
|
||||
<icon
|
||||
<icon
|
||||
v-if="showIconOnly"
|
||||
:icon="icon"
|
||||
:style="{'color': iconColor !== '' ? iconColor : undefined}"
|
||||
|
@ -22,7 +22,7 @@
|
|||
v-else
|
||||
class="icon is-small"
|
||||
>
|
||||
<icon
|
||||
<icon
|
||||
:icon="icon"
|
||||
:style="{'color': iconColor !== '' ? iconColor : undefined}"
|
||||
/>
|
||||
|
@ -34,20 +34,20 @@
|
|||
|
||||
<script lang="ts">
|
||||
const BUTTON_TYPES_MAP = {
|
||||
primary: 'is-primary',
|
||||
secondary: 'is-outlined',
|
||||
tertiary: 'is-text is-inverted underline-none',
|
||||
primary: 'is-primary',
|
||||
secondary: 'is-outlined',
|
||||
tertiary: 'is-text is-inverted underline-none',
|
||||
} as const
|
||||
|
||||
export type ButtonTypes = keyof typeof BUTTON_TYPES_MAP
|
||||
|
||||
export default { name: 'XButton' }
|
||||
export default {name: 'XButton'}
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {computed, useSlots} from 'vue'
|
||||
import BaseButton, {type BaseButtonProps} from '@/components/base/BaseButton.vue'
|
||||
import type { IconProp } from '@fortawesome/fontawesome-svg-core'
|
||||
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
|
||||
|
||||
// extending the props of the BaseButton
|
||||
export interface ButtonProps extends /* @vue-ignore */ BaseButtonProps {
|
||||
|
@ -76,37 +76,38 @@ const showIconOnly = computed(() => icon !== '' && typeof slots.default === 'und
|
|||
|
||||
<style lang="scss" scoped>
|
||||
.button {
|
||||
transition: all $transition;
|
||||
border: 0;
|
||||
text-transform: uppercase;
|
||||
font-size: 0.85rem;
|
||||
font-weight: bold;
|
||||
height: auto;
|
||||
min-height: $button-height;
|
||||
box-shadow: var(--shadow-sm);
|
||||
display: inline-flex;
|
||||
white-space: var(--button-white-space);
|
||||
transition: all $transition;
|
||||
border: 0;
|
||||
text-transform: uppercase;
|
||||
font-size: 0.85rem;
|
||||
font-weight: bold;
|
||||
height: auto;
|
||||
min-height: $button-height;
|
||||
box-shadow: var(--shadow-sm);
|
||||
display: inline-flex;
|
||||
white-space: var(--button-white-space);
|
||||
line-height: 1;
|
||||
|
||||
&:hover {
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
&:hover {
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
&.fullheight {
|
||||
padding-right: 7px;
|
||||
height: 100%;
|
||||
}
|
||||
&.fullheight {
|
||||
padding-right: 7px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&.is-active,
|
||||
&.is-focused,
|
||||
&:active,
|
||||
&:focus,
|
||||
&:focus:not(:active) {
|
||||
box-shadow: var(--shadow-xs) !important;
|
||||
}
|
||||
&.is-active,
|
||||
&.is-focused,
|
||||
&:active,
|
||||
&:focus,
|
||||
&:focus:not(:active) {
|
||||
box-shadow: var(--shadow-xs) !important;
|
||||
}
|
||||
|
||||
&.is-primary.is-outlined:hover {
|
||||
color: var(--white);
|
||||
}
|
||||
&.is-primary.is-outlined:hover {
|
||||
color: var(--white);
|
||||
}
|
||||
}
|
||||
|
||||
.is-small {
|
||||
|
@ -114,6 +115,6 @@ const showIconOnly = computed(() => icon !== '' && typeof slots.default === 'und
|
|||
}
|
||||
|
||||
.underline-none {
|
||||
text-decoration: none !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
</style>
|
|
@ -7,8 +7,14 @@
|
|||
{{ getProjectTitle(currentProject) }}
|
||||
</h1>
|
||||
|
||||
<div class="switch-view-container d-print-none">
|
||||
<div class="switch-view">
|
||||
<div
|
||||
class="switch-view-container d-print-none"
|
||||
:class="{'is-justify-content-flex-end': views.length === 1}"
|
||||
>
|
||||
<div
|
||||
v-if="views.length > 1"
|
||||
class="switch-view"
|
||||
>
|
||||
<BaseButton
|
||||
v-for="v in views"
|
||||
:key="v.id"
|
||||
|
@ -149,8 +155,14 @@ function getViewTitle(view: IProjectView) {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
.switch-view-container {
|
||||
min-height: $switch-view-height;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
@ -162,8 +174,6 @@ function getViewTitle(view: IProjectView) {
|
|||
border-radius: $radius;
|
||||
font-size: .75rem;
|
||||
box-shadow: var(--shadow-sm);
|
||||
height: $switch-view-height;
|
||||
margin: 0 auto 1rem;
|
||||
padding: .5rem;
|
||||
}
|
||||
|
||||
|
|
|
@ -379,6 +379,7 @@ const blurDebounced = useDebounceFn(() => emit('blur'), 500)
|
|||
}
|
||||
|
||||
.filter-input-highlight {
|
||||
background: var(--white);
|
||||
height: 2.5em;
|
||||
line-height: 1.5;
|
||||
padding: .5em .75em;
|
||||
|
|
|
@ -1,26 +1,10 @@
|
|||
<!-- Vikunja is a to-do list application to facilitate your life. -->
|
||||
<!-- Copyright 2018-present Vikunja and contributors. All rights reserved. -->
|
||||
<!-- -->
|
||||
<!-- This program is free software: you can redistribute it and/or modify -->
|
||||
<!-- it under the terms of the GNU Affero General Public Licensee as published by -->
|
||||
<!-- the Free Software Foundation, either version 3 of the License, or -->
|
||||
<!-- (at your option) any later version. -->
|
||||
<!-- -->
|
||||
<!-- This program is distributed in the hope that it will be useful, -->
|
||||
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||
<!-- GNU Affero General Public Licensee for more details. -->
|
||||
<!-- -->
|
||||
<!-- You should have received a copy of the GNU Affero General Public Licensee -->
|
||||
<!-- along with this program. If not, see <https://www.gnu.org/licenses/>. -->
|
||||
|
||||
<template>
|
||||
<ProjectWrapper
|
||||
class="project-gantt"
|
||||
:project-id="filters.projectId"
|
||||
:view
|
||||
:view-id
|
||||
>
|
||||
<template #header>
|
||||
<template #default>
|
||||
<card :has-content="false">
|
||||
<div class="gantt-options">
|
||||
<div class="field">
|
||||
|
@ -61,9 +45,7 @@
|
|||
</Fancycheckbox>
|
||||
</div>
|
||||
</card>
|
||||
</template>
|
||||
|
||||
<template #default>
|
||||
<div class="gantt-chart-container">
|
||||
<card
|
||||
:has-content="false"
|
||||
|
@ -95,7 +77,7 @@ import {useI18n} from 'vue-i18n'
|
|||
import type {RouteLocationNormalized} from 'vue-router'
|
||||
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import { getFlatpickrLanguage } from '@/helpers/flatpickrLanguage'
|
||||
import {getFlatpickrLanguage} from '@/helpers/flatpickrLanguage'
|
||||
|
||||
import Foo from '@/components/misc/flatpickr/Flatpickr.vue'
|
||||
import ProjectWrapper from '@/components/project/ProjectWrapper.vue'
|
||||
|
|
|
@ -6,69 +6,68 @@
|
|||
>
|
||||
<template #header>
|
||||
<div class="filter-container">
|
||||
<div class="items">
|
||||
<Popup>
|
||||
<template #trigger="{toggle}">
|
||||
<x-button
|
||||
icon="th"
|
||||
variant="secondary"
|
||||
@click.prevent.stop="toggle()"
|
||||
>
|
||||
{{ $t('project.table.columns') }}
|
||||
</x-button>
|
||||
</template>
|
||||
<template #content="{isOpen}">
|
||||
<card
|
||||
class="columns-filter"
|
||||
:class="{'is-open': isOpen}"
|
||||
>
|
||||
<Fancycheckbox v-model="activeColumns.index">
|
||||
#
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.done">
|
||||
{{ $t('task.attributes.done') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.title">
|
||||
{{ $t('task.attributes.title') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.priority">
|
||||
{{ $t('task.attributes.priority') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.labels">
|
||||
{{ $t('task.attributes.labels') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.assignees">
|
||||
{{ $t('task.attributes.assignees') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.dueDate">
|
||||
{{ $t('task.attributes.dueDate') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.startDate">
|
||||
{{ $t('task.attributes.startDate') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.endDate">
|
||||
{{ $t('task.attributes.endDate') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.percentDone">
|
||||
{{ $t('task.attributes.percentDone') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.doneAt">
|
||||
{{ $t('task.attributes.doneAt') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.created">
|
||||
{{ $t('task.attributes.created') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.updated">
|
||||
{{ $t('task.attributes.updated') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.createdBy">
|
||||
{{ $t('task.attributes.createdBy') }}
|
||||
</Fancycheckbox>
|
||||
</card>
|
||||
</template>
|
||||
</Popup>
|
||||
<FilterPopup v-model="params" />
|
||||
</div>
|
||||
<Popup>
|
||||
<template #trigger="{toggle}">
|
||||
<x-button
|
||||
icon="th"
|
||||
variant="secondary"
|
||||
class="mr-2"
|
||||
@click.prevent.stop="toggle()"
|
||||
>
|
||||
{{ $t('project.table.columns') }}
|
||||
</x-button>
|
||||
</template>
|
||||
<template #content="{isOpen}">
|
||||
<card
|
||||
class="columns-filter"
|
||||
:class="{'is-open': isOpen}"
|
||||
>
|
||||
<Fancycheckbox v-model="activeColumns.index">
|
||||
#
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.done">
|
||||
{{ $t('task.attributes.done') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.title">
|
||||
{{ $t('task.attributes.title') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.priority">
|
||||
{{ $t('task.attributes.priority') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.labels">
|
||||
{{ $t('task.attributes.labels') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.assignees">
|
||||
{{ $t('task.attributes.assignees') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.dueDate">
|
||||
{{ $t('task.attributes.dueDate') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.startDate">
|
||||
{{ $t('task.attributes.startDate') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.endDate">
|
||||
{{ $t('task.attributes.endDate') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.percentDone">
|
||||
{{ $t('task.attributes.percentDone') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.doneAt">
|
||||
{{ $t('task.attributes.doneAt') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.created">
|
||||
{{ $t('task.attributes.created') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.updated">
|
||||
{{ $t('task.attributes.updated') }}
|
||||
</Fancycheckbox>
|
||||
<Fancycheckbox v-model="activeColumns.createdBy">
|
||||
{{ $t('task.attributes.createdBy') }}
|
||||
</Fancycheckbox>
|
||||
</card>
|
||||
</template>
|
||||
</Popup>
|
||||
<FilterPopup v-model="params" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -397,4 +396,8 @@ const taskDetailRoutes = computed(() => Object.fromEntries(
|
|||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.filter-container :deep(.popup) {
|
||||
top: 7rem;
|
||||
}
|
||||
</style>
|
|
@ -2,12 +2,65 @@
|
|||
import type {IProjectView} from '@/modelTypes/IProjectView'
|
||||
import XButton from '@/components/input/button.vue'
|
||||
import FilterInput from '@/components/project/partials/FilterInput.vue'
|
||||
import {ref} from 'vue'
|
||||
import {ref, watch} from 'vue'
|
||||
import {transformFilterStringForApi, transformFilterStringFromApi} from '@/helpers/filters'
|
||||
import {useLabelStore} from '@/stores/labels'
|
||||
import {useProjectStore} from '@/stores/projects'
|
||||
|
||||
const {
|
||||
modelValue,
|
||||
} = defineProps<{
|
||||
modelValue: IProjectView,
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const view = ref<IProjectView>()
|
||||
|
||||
const labelStore = useLabelStore()
|
||||
const projectStore = useProjectStore()
|
||||
|
||||
watch(
|
||||
() => modelValue,
|
||||
newValue => {
|
||||
const transformed = {
|
||||
...newValue,
|
||||
filter: transformFilterStringFromApi(
|
||||
newValue.filter,
|
||||
labelId => labelStore.getLabelById(labelId)?.title,
|
||||
projectId => projectStore.projects[projectId]?.title || null,
|
||||
),
|
||||
}
|
||||
|
||||
if (JSON.stringify(view.value) !== JSON.stringify(transformed)) {
|
||||
view.value = transformed
|
||||
}
|
||||
},
|
||||
{immediate: true, deep: true},
|
||||
)
|
||||
|
||||
watch(
|
||||
() => view.value,
|
||||
newView => {
|
||||
emit('update:modelValue', {
|
||||
...newView,
|
||||
filter: transformFilterStringForApi(
|
||||
newView.filter,
|
||||
labelTitle => labelStore.filterLabelsByQuery([], labelTitle)[0]?.id || null,
|
||||
projectTitle => {
|
||||
const found = projectStore.findProjectByExactname(projectTitle)
|
||||
return found?.id || null
|
||||
},
|
||||
),
|
||||
})
|
||||
},
|
||||
{deep: true},
|
||||
)
|
||||
|
||||
const model = defineModel<IProjectView>()
|
||||
const titleValid = ref(true)
|
||||
|
||||
function validateTitle() {
|
||||
titleValid.value = model.value.title !== ''
|
||||
titleValid.value = view.value?.title !== ''
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -23,14 +76,14 @@ function validateTitle() {
|
|||
<div class="control">
|
||||
<input
|
||||
id="title"
|
||||
v-model="model.title"
|
||||
v-model="view.title"
|
||||
v-focus
|
||||
class="input"
|
||||
:placeholder="$t('project.share.links.namePlaceholder')"
|
||||
@blur="validateTitle"
|
||||
>
|
||||
</div>
|
||||
<p
|
||||
<p
|
||||
v-if="!titleValid"
|
||||
class="help is-danger"
|
||||
>
|
||||
|
@ -49,7 +102,7 @@ function validateTitle() {
|
|||
<div class="select">
|
||||
<select
|
||||
id="kind"
|
||||
v-model="model.viewKind"
|
||||
v-model="view.viewKind"
|
||||
>
|
||||
<option value="list">
|
||||
{{ $t('project.list.title') }}
|
||||
|
@ -69,12 +122,12 @@ function validateTitle() {
|
|||
</div>
|
||||
|
||||
<FilterInput
|
||||
v-model="model.filter"
|
||||
v-model="view.filter"
|
||||
:input-label="$t('project.views.filter')"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-if="model.viewKind === 'kanban'"
|
||||
v-if="view.viewKind === 'kanban'"
|
||||
class="field"
|
||||
>
|
||||
<label
|
||||
|
@ -87,7 +140,7 @@ function validateTitle() {
|
|||
<div class="select">
|
||||
<select
|
||||
id="configMode"
|
||||
v-model="model.bucketConfigurationMode"
|
||||
v-model="view.bucketConfigurationMode"
|
||||
>
|
||||
<option value="manual">
|
||||
{{ $t('project.views.bucketConfigManual') }}
|
||||
|
@ -101,7 +154,7 @@ function validateTitle() {
|
|||
</div>
|
||||
|
||||
<div
|
||||
v-if="model.viewKind === 'kanban' && model.bucketConfigurationMode === 'filter'"
|
||||
v-if="view.viewKind === 'kanban' && view.bucketConfigurationMode === 'filter'"
|
||||
class="field"
|
||||
>
|
||||
<label class="label">
|
||||
|
@ -109,13 +162,13 @@ function validateTitle() {
|
|||
</label>
|
||||
<div class="control">
|
||||
<div
|
||||
v-for="(b, index) in model.bucketConfiguration"
|
||||
v-for="(b, index) in view.bucketConfiguration"
|
||||
:key="'bucket_'+index"
|
||||
class="filter-bucket"
|
||||
>
|
||||
<button
|
||||
class="is-danger"
|
||||
@click.prevent="() => model.bucketConfiguration.splice(index, 1)"
|
||||
@click.prevent="() => view.bucketConfiguration.splice(index, 1)"
|
||||
>
|
||||
<icon icon="trash-alt" />
|
||||
</button>
|
||||
|
@ -130,7 +183,7 @@ function validateTitle() {
|
|||
<div class="control">
|
||||
<input
|
||||
:id="'bucket_'+index+'_title'"
|
||||
v-model="model.bucketConfiguration[index].title"
|
||||
v-model="view.bucketConfiguration[index].title"
|
||||
class="input"
|
||||
:placeholder="$t('project.share.links.namePlaceholder')"
|
||||
>
|
||||
|
@ -138,7 +191,7 @@ function validateTitle() {
|
|||
</div>
|
||||
|
||||
<FilterInput
|
||||
v-model="model.bucketConfiguration[index].filter"
|
||||
v-model="view.bucketConfiguration[index].filter"
|
||||
:input-label="$t('project.views.filter')"
|
||||
/>
|
||||
</div>
|
||||
|
@ -147,7 +200,7 @@ function validateTitle() {
|
|||
<XButton
|
||||
variant="secondary"
|
||||
icon="plus"
|
||||
@click="() => model.bucketConfiguration.push({title: '', filter: ''})"
|
||||
@click="() => view.bucketConfiguration.push({title: '', filter: ''})"
|
||||
>
|
||||
{{ $t('project.kanban.addBucket') }}
|
||||
</XButton>
|
||||
|
|
|
@ -16,7 +16,22 @@
|
|||
:search-results="found"
|
||||
:label="searchLabel"
|
||||
@search="find"
|
||||
/>
|
||||
>
|
||||
<template #searchResult="{option: result}">
|
||||
<User
|
||||
v-if="shareType === 'user'"
|
||||
:avatar-size="24"
|
||||
:show-username="true"
|
||||
:user="result"
|
||||
/>
|
||||
<span
|
||||
v-else
|
||||
class="search-result"
|
||||
>
|
||||
{{ result.name }}
|
||||
</span>
|
||||
</template>
|
||||
</Multiselect>
|
||||
</p>
|
||||
<p class="control">
|
||||
<x-button @click="add()">
|
||||
|
@ -173,6 +188,7 @@ import Nothing from '@/components/misc/nothing.vue'
|
|||
import {success} from '@/message'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
import {useConfigStore} from '@/stores/config'
|
||||
import User from '@/components/misc/user.vue'
|
||||
|
||||
// FIXME: I think this whole thing can now only manage user/team sharing for projects? Maybe remove a little generalization?
|
||||
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
@dragendBar="updateGanttTask"
|
||||
@dblclickBar="openTask"
|
||||
>
|
||||
<template #timeunit="{value, date}">
|
||||
<template #timeunit="{date}">
|
||||
<div
|
||||
class="timeunit-wrapper"
|
||||
:class="{'today': dateIsToday(date)}"
|
||||
>
|
||||
<span>{{ value }}</span>
|
||||
<span>{{ date.getDate() }}</span>
|
||||
<span class="weekday">
|
||||
{{ weekDayFromDate(date) }}
|
||||
</span>
|
||||
|
|
|
@ -102,6 +102,7 @@
|
|||
class="mt-2"
|
||||
entity-kind="comments"
|
||||
:entity-id="c.id"
|
||||
:disabled="!canWrite"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -27,13 +27,13 @@ export const AUTOCOMPLETE_FIELDS = [
|
|||
]
|
||||
|
||||
export const AVAILABLE_FILTER_FIELDS = [
|
||||
'done',
|
||||
'priority',
|
||||
'percentDone',
|
||||
...DATE_FIELDS,
|
||||
...ASSIGNEE_FIELDS,
|
||||
...LABEL_FIELDS,
|
||||
...PROJECT_FIELDS,
|
||||
'done',
|
||||
'priority',
|
||||
'percentDone',
|
||||
]
|
||||
|
||||
export const FILTER_OPERATORS = [
|
||||
|
|
|
@ -18,7 +18,7 @@ export function getDefaultTaskFilterParams(): TaskFilterParams {
|
|||
return {
|
||||
sort_by: ['position', 'id'],
|
||||
order_by: ['asc', 'desc'],
|
||||
filter: 'done = false',
|
||||
filter: '',
|
||||
filter_include_nulls: false,
|
||||
filter_timezone: '',
|
||||
s: '',
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
@import "tooltip";
|
||||
@import "labels";
|
||||
@import "project";
|
||||
@import "task";
|
||||
@import "tasks";
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
// FIXME: should be a component <FilterContainer>
|
||||
// used in
|
||||
// - Kanban.vue
|
||||
// - Project.vue
|
||||
// - Table.vue
|
||||
|
||||
$filter-container-top-default: -59px;
|
||||
$filter-container-top-link-share-gantt: -133px;
|
||||
$filter-container-top-link-share-list: -47px;
|
||||
|
||||
.filter-container {
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
min-width: 400px;
|
||||
max-width: 180px;
|
||||
position: absolute;
|
||||
right: 1.5rem;
|
||||
margin-top: $filter-container-top-default;
|
||||
z-index: 4;
|
||||
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.button:not(:last-of-type) {
|
||||
margin-right: .5rem;
|
||||
}
|
||||
|
||||
.button {
|
||||
height: $switch-view-height;
|
||||
}
|
||||
|
||||
.card {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
position: static;
|
||||
margin: 0 0 1rem 0 !important;
|
||||
max-width: 100%;
|
||||
min-width: auto;
|
||||
|
||||
.items {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.search {
|
||||
width: 100%;
|
||||
|
||||
.control:first-child {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.link-share-container .gantt-chart-container .filter-container,
|
||||
.gantt-chart-container .filter-container {
|
||||
right: 0;
|
||||
margin-top: calc(#{$filter-container-top-link-share-gantt - 2} - 7rem);
|
||||
}
|
||||
|
||||
.link-share-container .gantt-chart-container .filter-container {
|
||||
margin-top: calc(#{$filter-container-top-link-share-gantt} - 5rem);
|
||||
}
|
||||
|
||||
.link-share-container .list-view .filter-container {
|
||||
margin-top: $filter-container-top-link-share-list - 10px;
|
||||
}
|
||||
|
||||
.link-share-container.project\.table-view,
|
||||
.link-share-container.project\.list-view {
|
||||
.filter-container {
|
||||
right: 9rem;
|
||||
margin-top: $filter-container-top-default;
|
||||
}
|
||||
}
|
|
@ -89,7 +89,7 @@ async function saveView() {
|
|||
v-model="newView"
|
||||
class="mb-4"
|
||||
/>
|
||||
<div class="is-flex is-justify-content-end">
|
||||
<div class="is-flex is-justify-content-end mb-4">
|
||||
<XButton
|
||||
:loading="projectViewService.loading"
|
||||
@click="createView"
|
||||
|
|
|
@ -328,6 +328,7 @@
|
|||
entity-kind="tasks"
|
||||
:entity-id="task.id"
|
||||
class="details"
|
||||
:disabled="!canWrite"
|
||||
/>
|
||||
|
||||
<!-- Attachments -->
|
||||
|
|
2
go.mod
2
go.mod
|
@ -33,7 +33,7 @@ require (
|
|||
github.com/gabriel-vasile/mimetype v1.4.3
|
||||
github.com/ganigeorgiev/fexpr v0.4.0
|
||||
github.com/getsentry/sentry-go v0.27.0
|
||||
github.com/go-sql-driver/mysql v1.8.0
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.10.0
|
||||
github.com/gocarina/gocsv v0.0.0-20231116093920-b87c2d0e983a
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
|
|
2
go.sum
2
go.sum
|
@ -158,6 +158,8 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
|||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.0 h1:UtktXaU2Nb64z/pLiGIxY4431SJ4/dR5cjMmlVHgnT4=
|
||||
github.com/go-sql-driver/mysql v1.8.0/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.10.0 h1:BrBwN7AuC+74g5qtk9D59TLGOaEa8Bw1WmIsf+SyzWc=
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-present Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public Licensee as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public Licensee for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public Licensee
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package migration
|
||||
|
||||
import (
|
||||
"src.techknowlogick.com/xormigrate"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type projectView20240329170952 struct {
|
||||
ID int64 `xorm:"autoincr not null unique pk" json:"id" param:"view"`
|
||||
Filter string `xorm:"text null default null" query:"filter" json:"filter"`
|
||||
ViewKind int `xorm:"not null" json:"view_kind"`
|
||||
}
|
||||
|
||||
func (projectView20240329170952) TableName() string {
|
||||
return "project_views"
|
||||
}
|
||||
|
||||
func init() {
|
||||
migrations = append(migrations, &xormigrate.Migration{
|
||||
ID: "20240329170952",
|
||||
Description: "Update default filter for list views to hide completed tasks",
|
||||
Migrate: func(tx *xorm.Engine) error {
|
||||
|
||||
// Update the filter for all list views to hide completed tasks unless the filter is already set
|
||||
_, err := tx.Where("view_kind = ? AND filter = ?", 0, "").Cols("filter").Update(&projectView20240329170952{Filter: "done = false"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Rollback: func(tx *xorm.Engine) error {
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
|
@ -384,27 +384,27 @@ func (b *Bucket) Delete(s *xorm.Session, a web.Auth) (err error) {
|
|||
}
|
||||
|
||||
// Get the default bucket
|
||||
p, err := GetProjectViewByIDAndProject(s, b.ProjectViewID, b.ProjectID)
|
||||
pv, err := GetProjectViewByIDAndProject(s, b.ProjectViewID, b.ProjectID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var updateProject bool
|
||||
if b.ID == p.DefaultBucketID {
|
||||
p.DefaultBucketID = 0
|
||||
updateProject = true
|
||||
var updateProjectView bool
|
||||
if b.ID == pv.DefaultBucketID {
|
||||
pv.DefaultBucketID = 0
|
||||
updateProjectView = true
|
||||
}
|
||||
if b.ID == p.DoneBucketID {
|
||||
p.DoneBucketID = 0
|
||||
updateProject = true
|
||||
if b.ID == pv.DoneBucketID {
|
||||
pv.DoneBucketID = 0
|
||||
updateProjectView = true
|
||||
}
|
||||
if updateProject {
|
||||
err = p.Update(s, a)
|
||||
if updateProjectView {
|
||||
err = pv.Update(s, a)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
defaultBucketID, err := getDefaultBucketID(s, p)
|
||||
defaultBucketID, err := getDefaultBucketID(s, pv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -216,10 +216,10 @@ func TestBucket_Delete(t *testing.T) {
|
|||
err := b.Delete(s, u)
|
||||
require.NoError(t, err)
|
||||
|
||||
db.AssertMissing(t, "project_views", map[string]interface{}{
|
||||
db.AssertExists(t, "project_views", map[string]interface{}{
|
||||
"id": b.ProjectViewID,
|
||||
"done_bucket_id": 0,
|
||||
})
|
||||
}, false)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -991,7 +991,12 @@ func (p *Project) Create(s *xorm.Session, a web.Auth) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
return p.ReadOne(s, a)
|
||||
fullProject, err := GetProjectSimpleByID(s, p.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return fullProject.ReadOne(s, a)
|
||||
}
|
||||
|
||||
func (p *Project) isDefaultProject(s *xorm.Session) (is bool, err error) {
|
||||
|
|
|
@ -331,11 +331,19 @@ func (p *ProjectView) Update(s *xorm.Session, _ web.Auth) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
_, err = s.ID(p.ID).Update(p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.
|
||||
ID(p.ID).
|
||||
Cols(
|
||||
"title",
|
||||
"view_kind",
|
||||
"filter",
|
||||
"position",
|
||||
"bucket_configuration_mode",
|
||||
"bucket_configuration",
|
||||
"default_bucket_id",
|
||||
"done_bucket_id",
|
||||
).
|
||||
Update(p)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -383,6 +391,7 @@ func CreateDefaultViewsForProject(s *xorm.Session, project *Project, a web.Auth,
|
|||
Title: "List",
|
||||
ViewKind: ProjectViewKindList,
|
||||
Position: 100,
|
||||
Filter: "done = false",
|
||||
}
|
||||
err = createProjectView(s, list, a, createBacklogBucket)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue