Compare commits
12 Commits
main
...
feat-phosp
| Author | SHA1 | Date |
|---|---|---|
|
|
1c76dbdc08 | |
|
|
3aedeeb81e | |
|
|
75100df674 | |
|
|
b7d8f32659 | |
|
|
2083b2bd2c | |
|
|
6ec5037584 | |
|
|
288631f08c | |
|
|
b9631794ee | |
|
|
d0f18ffdfc | |
|
|
820ba348bb | |
|
|
70ada1d20b | |
|
|
8f468fa6f4 |
|
|
@ -52,13 +52,10 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/dom": "1.7.4",
|
"@floating-ui/dom": "1.7.4",
|
||||||
"@fortawesome/fontawesome-svg-core": "7.1.0",
|
|
||||||
"@fortawesome/free-regular-svg-icons": "7.1.0",
|
|
||||||
"@fortawesome/free-solid-svg-icons": "7.1.0",
|
|
||||||
"@fortawesome/vue-fontawesome": "3.1.3",
|
|
||||||
"@github/hotkey": "3.1.1",
|
"@github/hotkey": "3.1.1",
|
||||||
"@intlify/unplugin-vue-i18n": "11.0.3",
|
"@intlify/unplugin-vue-i18n": "11.0.3",
|
||||||
"@kyvg/vue3-notification": "3.4.2",
|
"@kyvg/vue3-notification": "3.4.2",
|
||||||
|
"@phosphor-icons/vue": "^2.2.1",
|
||||||
"@sentry/vue": "10.36.0",
|
"@sentry/vue": "10.36.0",
|
||||||
"@tiptap/core": "3.17.0",
|
"@tiptap/core": "3.17.0",
|
||||||
"@tiptap/extension-code-block-lowlight": "3.17.0",
|
"@tiptap/extension-code-block-lowlight": "3.17.0",
|
||||||
|
|
|
||||||
|
|
@ -22,18 +22,6 @@ importers:
|
||||||
'@floating-ui/dom':
|
'@floating-ui/dom':
|
||||||
specifier: 1.7.4
|
specifier: 1.7.4
|
||||||
version: 1.7.4
|
version: 1.7.4
|
||||||
'@fortawesome/fontawesome-svg-core':
|
|
||||||
specifier: 7.1.0
|
|
||||||
version: 7.1.0
|
|
||||||
'@fortawesome/free-regular-svg-icons':
|
|
||||||
specifier: 7.1.0
|
|
||||||
version: 7.1.0
|
|
||||||
'@fortawesome/free-solid-svg-icons':
|
|
||||||
specifier: 7.1.0
|
|
||||||
version: 7.1.0
|
|
||||||
'@fortawesome/vue-fontawesome':
|
|
||||||
specifier: 3.1.3
|
|
||||||
version: 3.1.3(@fortawesome/fontawesome-svg-core@7.1.0)(vue@3.5.27(typescript@5.9.3))
|
|
||||||
'@github/hotkey':
|
'@github/hotkey':
|
||||||
specifier: 3.1.1
|
specifier: 3.1.1
|
||||||
version: 3.1.1(patch_hash=145ab3233cbcd3bc934b4961cd8710e2b15e4ae5dd20862a8d1d6621d7f9d4a8)
|
version: 3.1.1(patch_hash=145ab3233cbcd3bc934b4961cd8710e2b15e4ae5dd20862a8d1d6621d7f9d4a8)
|
||||||
|
|
@ -43,6 +31,9 @@ importers:
|
||||||
'@kyvg/vue3-notification':
|
'@kyvg/vue3-notification':
|
||||||
specifier: 3.4.2
|
specifier: 3.4.2
|
||||||
version: 3.4.2(vue@3.5.27(typescript@5.9.3))
|
version: 3.4.2(vue@3.5.27(typescript@5.9.3))
|
||||||
|
'@phosphor-icons/vue':
|
||||||
|
specifier: ^2.2.1
|
||||||
|
version: 2.2.1(vue@3.5.27(typescript@5.9.3))
|
||||||
'@sentry/vue':
|
'@sentry/vue':
|
||||||
specifier: 10.36.0
|
specifier: 10.36.0
|
||||||
version: 10.36.0(pinia@3.0.4(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))(vue@3.5.27(typescript@5.9.3))
|
version: 10.36.0(pinia@3.0.4(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))(vue@3.5.27(typescript@5.9.3))
|
||||||
|
|
@ -1646,28 +1637,6 @@ packages:
|
||||||
'@floating-ui/utils@0.2.10':
|
'@floating-ui/utils@0.2.10':
|
||||||
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
|
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
|
||||||
|
|
||||||
'@fortawesome/fontawesome-common-types@7.1.0':
|
|
||||||
resolution: {integrity: sha512-l/BQM7fYntsCI//du+6sEnHOP6a74UixFyOYUyz2DLMXKx+6DEhfR3F2NYGE45XH1JJuIamacb4IZs9S0ZOWLA==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
|
|
||||||
'@fortawesome/fontawesome-svg-core@7.1.0':
|
|
||||||
resolution: {integrity: sha512-fNxRUk1KhjSbnbuBxlWSnBLKLBNun52ZBTcs22H/xEEzM6Ap81ZFTQ4bZBxVQGQgVY0xugKGoRcCbaKjLQ3XZA==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
|
|
||||||
'@fortawesome/free-regular-svg-icons@7.1.0':
|
|
||||||
resolution: {integrity: sha512-0e2fdEyB4AR+e6kU4yxwA/MonnYcw/CsMEP9lH82ORFi9svA6/RhDyhxIv5mlJaldmaHLLYVTb+3iEr+PDSZuQ==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
|
|
||||||
'@fortawesome/free-solid-svg-icons@7.1.0':
|
|
||||||
resolution: {integrity: sha512-Udu3K7SzAo9N013qt7qmm22/wo2hADdheXtBfxFTecp+ogsc0caQNRKEb7pkvvagUGOpG9wJC1ViH6WXs8oXIA==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
|
|
||||||
'@fortawesome/vue-fontawesome@3.1.3':
|
|
||||||
resolution: {integrity: sha512-OHHUTLPEzdwP8kcYIzhioUdUOjZ4zzmi+midwa4bqscza4OJCOvTKJEHkXNz8PgZ23kWci1HkKVX0bm8f9t9gQ==}
|
|
||||||
peerDependencies:
|
|
||||||
'@fortawesome/fontawesome-svg-core': ~1 || ~6 || ~7
|
|
||||||
vue: '>= 3.0.0 < 4'
|
|
||||||
|
|
||||||
'@ghostery/adblocker-content@2.5.0':
|
'@ghostery/adblocker-content@2.5.0':
|
||||||
resolution: {integrity: sha512-Gn9fslZdacx1m1e3/2LSUPWagLObYmIDbkgvZTtgqT/OHc17VbM71AxWEjtC/xzo5K4PI25958PjvidoEH7ufw==}
|
resolution: {integrity: sha512-Gn9fslZdacx1m1e3/2LSUPWagLObYmIDbkgvZTtgqT/OHc17VbM71AxWEjtC/xzo5K4PI25958PjvidoEH7ufw==}
|
||||||
|
|
||||||
|
|
@ -1967,6 +1936,12 @@ packages:
|
||||||
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
|
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
|
||||||
engines: {node: '>= 10.0.0'}
|
engines: {node: '>= 10.0.0'}
|
||||||
|
|
||||||
|
'@phosphor-icons/vue@2.2.1':
|
||||||
|
resolution: {integrity: sha512-3RNg1utc2Z5RwPKWFkW3eXI/0BfQAwXgtFxPUPeSzi55jGYUq16b+UqcgbKLazWFlwg5R92OCLKjDiJjeiJcnA==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
peerDependencies:
|
||||||
|
vue: '>=3.2.39'
|
||||||
|
|
||||||
'@pkgjs/parseargs@0.11.0':
|
'@pkgjs/parseargs@0.11.0':
|
||||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
|
@ -8074,25 +8049,6 @@ snapshots:
|
||||||
|
|
||||||
'@floating-ui/utils@0.2.10': {}
|
'@floating-ui/utils@0.2.10': {}
|
||||||
|
|
||||||
'@fortawesome/fontawesome-common-types@7.1.0': {}
|
|
||||||
|
|
||||||
'@fortawesome/fontawesome-svg-core@7.1.0':
|
|
||||||
dependencies:
|
|
||||||
'@fortawesome/fontawesome-common-types': 7.1.0
|
|
||||||
|
|
||||||
'@fortawesome/free-regular-svg-icons@7.1.0':
|
|
||||||
dependencies:
|
|
||||||
'@fortawesome/fontawesome-common-types': 7.1.0
|
|
||||||
|
|
||||||
'@fortawesome/free-solid-svg-icons@7.1.0':
|
|
||||||
dependencies:
|
|
||||||
'@fortawesome/fontawesome-common-types': 7.1.0
|
|
||||||
|
|
||||||
'@fortawesome/vue-fontawesome@3.1.3(@fortawesome/fontawesome-svg-core@7.1.0)(vue@3.5.27(typescript@5.9.3))':
|
|
||||||
dependencies:
|
|
||||||
'@fortawesome/fontawesome-svg-core': 7.1.0
|
|
||||||
vue: 3.5.27(typescript@5.9.3)
|
|
||||||
|
|
||||||
'@ghostery/adblocker-content@2.5.0':
|
'@ghostery/adblocker-content@2.5.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ghostery/adblocker-extended-selectors': 2.5.0
|
'@ghostery/adblocker-extended-selectors': 2.5.0
|
||||||
|
|
@ -8417,6 +8373,10 @@ snapshots:
|
||||||
'@parcel/watcher-win32-x64': 2.5.1
|
'@parcel/watcher-win32-x64': 2.5.1
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@phosphor-icons/vue@2.2.1(vue@3.5.27(typescript@5.9.3))':
|
||||||
|
dependencies:
|
||||||
|
vue: 3.5.27(typescript@5.9.3)
|
||||||
|
|
||||||
'@pkgjs/parseargs@0.11.0':
|
'@pkgjs/parseargs@0.11.0':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<XButton
|
<XButton
|
||||||
icon="calendar"
|
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
data-toggle
|
data-toggle
|
||||||
/>
|
>
|
||||||
|
<template #icon><PhCalendar /></template>
|
||||||
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -61,10 +62,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<XButton
|
<XButton
|
||||||
icon="calendar"
|
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
data-toggle
|
data-toggle
|
||||||
/>
|
>
|
||||||
|
<template #icon><PhCalendar /></template>
|
||||||
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -102,6 +104,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {computed, ref, watch} from 'vue'
|
import {computed, ref, watch} from 'vue'
|
||||||
|
import {PhCalendar} from '@phosphor-icons/vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import flatPickr from 'vue-flatpickr-component'
|
import flatPickr from 'vue-flatpickr-component'
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<XButton
|
<XButton
|
||||||
icon="calendar"
|
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
data-toggle
|
data-toggle
|
||||||
/>
|
>
|
||||||
|
<template #icon><PhCalendar /></template>
|
||||||
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -80,6 +81,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {computed, ref, watch} from 'vue'
|
import {computed, ref, watch} from 'vue'
|
||||||
|
import {PhCalendar} from '@phosphor-icons/vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import flatPickr from 'vue-flatpickr-component'
|
import flatPickr from 'vue-flatpickr-component'
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,7 @@
|
||||||
class="add-to-home-screen"
|
class="add-to-home-screen"
|
||||||
:class="{'has-update-available': hasUpdateAvailable}"
|
:class="{'has-update-available': hasUpdateAvailable}"
|
||||||
>
|
>
|
||||||
<Icon
|
<PhUploadSimple class="add-icon" />
|
||||||
icon="arrow-up-from-bracket"
|
|
||||||
class="add-icon"
|
|
||||||
/>
|
|
||||||
<p>
|
<p>
|
||||||
{{ $t('home.addToHomeScreen') }}
|
{{ $t('home.addToHomeScreen') }}
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -15,12 +12,13 @@
|
||||||
class="hide-button"
|
class="hide-button"
|
||||||
@click="() => hideMessage = true"
|
@click="() => hideMessage = true"
|
||||||
>
|
>
|
||||||
<Icon icon="x" />
|
<PhX />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import {PhUploadSimple, PhX} from '@phosphor-icons/vue'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import {useLocalStorage} from '@vueuse/core'
|
import {useLocalStorage} from '@vueuse/core'
|
||||||
import {computed} from 'vue'
|
import {computed} from 'vue'
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
class="project-title-button"
|
class="project-title-button"
|
||||||
>
|
>
|
||||||
<span class="is-sr-only">{{ $t('project.description') }}</span>
|
<span class="is-sr-only">{{ $t('project.description') }}</span>
|
||||||
<Icon icon="circle-info" />
|
<PhInfo />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
||||||
<ProjectSettingsDropdown
|
<ProjectSettingsDropdown
|
||||||
|
|
@ -45,10 +45,7 @@
|
||||||
@click="toggleOpen"
|
@click="toggleOpen"
|
||||||
>
|
>
|
||||||
<span class="is-sr-only">{{ $t('project.openSettingsMenu') }}</span>
|
<span class="is-sr-only">{{ $t('project.openSettingsMenu') }}</span>
|
||||||
<Icon
|
<PhDotsThree class="icon" />
|
||||||
icon="ellipsis-h"
|
|
||||||
class="icon"
|
|
||||||
/>
|
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</template>
|
</template>
|
||||||
</ProjectSettingsDropdown>
|
</ProjectSettingsDropdown>
|
||||||
|
|
@ -79,7 +76,7 @@
|
||||||
transform: open ? 'rotate(180deg)' : 'rotate(0)',
|
transform: open ? 'rotate(180deg)' : 'rotate(0)',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<Icon icon="chevron-down" />
|
<PhCaretDown />
|
||||||
</span>
|
</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -118,6 +115,7 @@ import { computed } from 'vue'
|
||||||
|
|
||||||
import { PERMISSIONS as Permissions } from '@/constants/permissions'
|
import { PERMISSIONS as Permissions } from '@/constants/permissions'
|
||||||
|
|
||||||
|
import {PhCaretDown, PhDotsThree, PhInfo} from '@phosphor-icons/vue'
|
||||||
import ProjectSettingsDropdown from '@/components/project/ProjectSettingsDropdown.vue'
|
import ProjectSettingsDropdown from '@/components/project/ProjectSettingsDropdown.vue'
|
||||||
import Dropdown from '@/components/misc/Dropdown.vue'
|
import Dropdown from '@/components/misc/Dropdown.vue'
|
||||||
import DropdownItem from '@/components/misc/DropdownItem.vue'
|
import DropdownItem from '@/components/misc/DropdownItem.vue'
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
class="menu-hide-button d-print-none"
|
class="menu-hide-button d-print-none"
|
||||||
@click="baseStore.setMenuActive(false)"
|
@click="baseStore.setMenuActive(false)"
|
||||||
>
|
>
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<div
|
<div
|
||||||
class="app-container"
|
class="app-container"
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
@click="showKeyboardShortcuts()"
|
@click="showKeyboardShortcuts()"
|
||||||
>
|
>
|
||||||
<span class="is-sr-only">{{ $t('keyboardShortcuts.title') }}</span>
|
<span class="is-sr-only">{{ $t('keyboardShortcuts.title') }}</span>
|
||||||
<Icon icon="keyboard" />
|
<PhKeyboard />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -79,6 +79,7 @@ import Navigation from '@/components/home/Navigation.vue'
|
||||||
import QuickActions from '@/components/quick-actions/QuickActions.vue'
|
import QuickActions from '@/components/quick-actions/QuickActions.vue'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
|
||||||
|
import {PhKeyboard, PhX} from '@phosphor-icons/vue'
|
||||||
import {useBaseStore} from '@/stores/base'
|
import {useBaseStore} from '@/stores/base'
|
||||||
import {useLabelStore} from '@/stores/labels'
|
import {useLabelStore} from '@/stores/labels'
|
||||||
import {useProjectStore} from '@/stores/projects'
|
import {useProjectStore} from '@/stores/projects'
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, ref} from 'vue'
|
import {computed, ref} from 'vue'
|
||||||
import {useConfigStore} from '@/stores/config'
|
import {useConfigStore} from '@/stores/config'
|
||||||
|
import {PhX} from '@phosphor-icons/vue'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
|
||||||
const configStore = useConfigStore()
|
const configStore = useConfigStore()
|
||||||
|
|
@ -21,7 +22,7 @@ const enabled = computed(() => configStore.demoModeEnabled && !hide.value)
|
||||||
class="hide-button"
|
class="hide-button"
|
||||||
@click="() => hide = true"
|
@click="() => hide = true"
|
||||||
>
|
>
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
:to="{ name: 'home'}"
|
:to="{ name: 'home'}"
|
||||||
>
|
>
|
||||||
<span class="menu-item-icon icon">
|
<span class="menu-item-icon icon">
|
||||||
<Icon icon="calendar" />
|
<PhCalendar />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('navigation.overview') }}
|
{{ $t('navigation.overview') }}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
:to="{ name: 'tasks.range'}"
|
:to="{ name: 'tasks.range'}"
|
||||||
>
|
>
|
||||||
<span class="menu-item-icon icon">
|
<span class="menu-item-icon icon">
|
||||||
<Icon :icon="['far', 'calendar-alt']" />
|
<PhCalendarBlank />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('navigation.upcoming') }}
|
{{ $t('navigation.upcoming') }}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
:to="{ name: 'projects.index'}"
|
:to="{ name: 'projects.index'}"
|
||||||
>
|
>
|
||||||
<span class="menu-item-icon icon">
|
<span class="menu-item-icon icon">
|
||||||
<Icon icon="layer-group" />
|
<PhStack />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('project.projects') }}
|
{{ $t('project.projects') }}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
:to="{ name: 'labels.index'}"
|
:to="{ name: 'labels.index'}"
|
||||||
>
|
>
|
||||||
<span class="menu-item-icon icon">
|
<span class="menu-item-icon icon">
|
||||||
<Icon icon="tags" />
|
<PhTag />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('label.title') }}
|
{{ $t('label.title') }}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
:to="{ name: 'teams.index'}"
|
:to="{ name: 'teams.index'}"
|
||||||
>
|
>
|
||||||
<span class="menu-item-icon icon">
|
<span class="menu-item-icon icon">
|
||||||
<Icon icon="users" />
|
<PhUsers />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('team.title') }}
|
{{ $t('team.title') }}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|
@ -131,6 +131,8 @@ import PoweredByLink from '@/components/home/PoweredByLink.vue'
|
||||||
import Logo from '@/components/home/Logo.vue'
|
import Logo from '@/components/home/Logo.vue'
|
||||||
import Loading from '@/components/misc/Loading.vue'
|
import Loading from '@/components/misc/Loading.vue'
|
||||||
|
|
||||||
|
import {PhCalendar, PhCalendarBlank, PhStack, PhTag, PhUsers} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import {useBaseStore} from '@/stores/base'
|
import {useBaseStore} from '@/stores/base'
|
||||||
import {useProjectStore} from '@/stores/projects'
|
import {useProjectStore} from '@/stores/projects'
|
||||||
import ProjectsNavigation from '@/components/home/ProjectsNavigation.vue'
|
import ProjectsNavigation from '@/components/home/ProjectsNavigation.vue'
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,7 @@
|
||||||
class="collapse-project-button"
|
class="collapse-project-button"
|
||||||
@click="childProjectsOpen = !childProjectsOpen"
|
@click="childProjectsOpen = !childProjectsOpen"
|
||||||
>
|
>
|
||||||
<Icon
|
<PhCaretDown :class="{ 'project-is-collapsed': !childProjectsOpen }" />
|
||||||
icon="chevron-down"
|
|
||||||
:class="{ 'project-is-collapsed': !childProjectsOpen }"
|
|
||||||
/>
|
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<span
|
<span
|
||||||
v-if="canEditOrder && project.id > 0 && project.maxPermission !== null && project.maxPermission > PERMISSIONS.READ"
|
v-if="canEditOrder && project.id > 0 && project.maxPermission !== null && project.maxPermission > PERMISSIONS.READ"
|
||||||
|
|
@ -25,7 +22,7 @@
|
||||||
@click.stop.prevent
|
@click.stop.prevent
|
||||||
@touchstart.stop
|
@touchstart.stop
|
||||||
>
|
>
|
||||||
<Icon icon="grip-lines" />
|
<PhDotsSix />
|
||||||
</span>
|
</span>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
:to="{ name: 'project.index', params: { projectId: project.id} }"
|
:to="{ name: 'project.index', params: { projectId: project.id} }"
|
||||||
|
|
@ -46,7 +43,7 @@
|
||||||
v-else-if="project.id < -1"
|
v-else-if="project.id < -1"
|
||||||
class="saved-filter-icon icon menu-item-icon"
|
class="saved-filter-icon icon menu-item-icon"
|
||||||
>
|
>
|
||||||
<Icon icon="filter" />
|
<PhFunnel />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="project-menu-title">{{ getProjectTitle(project) }}</span>
|
<span class="project-menu-title">{{ getProjectTitle(project) }}</span>
|
||||||
|
|
@ -58,7 +55,7 @@
|
||||||
@click="projectStore.toggleProjectFavorite(project)"
|
@click="projectStore.toggleProjectFavorite(project)"
|
||||||
>
|
>
|
||||||
<span class="is-sr-only">{{ project.isFavorite ? $t('project.unfavorite') : $t('project.favorite') }}</span>
|
<span class="is-sr-only">{{ project.isFavorite ? $t('project.unfavorite') : $t('project.favorite') }}</span>
|
||||||
<Icon :icon="project.isFavorite ? 'star' : ['far', 'star']" />
|
<PhStar :weight="project.isFavorite ? 'fill' : 'regular'" />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<ProjectSettingsDropdown
|
<ProjectSettingsDropdown
|
||||||
v-if="project.maxPermission !== null && project.maxPermission > PERMISSIONS.READ"
|
v-if="project.maxPermission !== null && project.maxPermission > PERMISSIONS.READ"
|
||||||
|
|
@ -72,10 +69,7 @@
|
||||||
@click="toggleOpen"
|
@click="toggleOpen"
|
||||||
>
|
>
|
||||||
<span class="is-sr-only">{{ $t('project.openSettingsMenu') }}</span>
|
<span class="is-sr-only">{{ $t('project.openSettingsMenu') }}</span>
|
||||||
<Icon
|
<PhDotsThree class="icon" />
|
||||||
icon="ellipsis-h"
|
|
||||||
class="icon"
|
|
||||||
/>
|
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</template>
|
</template>
|
||||||
</ProjectSettingsDropdown>
|
</ProjectSettingsDropdown>
|
||||||
|
|
@ -98,6 +92,7 @@ import {useStorage} from '@vueuse/core'
|
||||||
|
|
||||||
import type {IProject} from '@/modelTypes/IProject'
|
import type {IProject} from '@/modelTypes/IProject'
|
||||||
|
|
||||||
|
import {PhCaretDown, PhDotsThree, PhDotsSix, PhFunnel, PhStar} from '@phosphor-icons/vue'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import ProjectSettingsDropdown from '@/components/project/ProjectSettingsDropdown.vue'
|
import ProjectSettingsDropdown from '@/components/project/ProjectSettingsDropdown.vue'
|
||||||
import {getProjectTitle} from '@/helpers/getProjectTitle'
|
import {getProjectTitle} from '@/helpers/getProjectTitle'
|
||||||
|
|
|
||||||
|
|
@ -14,21 +14,17 @@
|
||||||
'--button-white-space': wrap ? 'break-spaces' : 'nowrap',
|
'--button-white-space': wrap ? 'break-spaces' : 'nowrap',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template v-if="icon">
|
<template v-if="$slots.icon">
|
||||||
<Icon
|
|
||||||
v-if="!$slots.default"
|
|
||||||
:icon="icon"
|
|
||||||
:style="{color: iconColor}"
|
|
||||||
/>
|
|
||||||
<span
|
<span
|
||||||
v-else
|
v-if="$slots.default"
|
||||||
class="icon is-small"
|
class="icon is-small"
|
||||||
>
|
>
|
||||||
<Icon
|
<slot name="icon" />
|
||||||
:icon="icon"
|
|
||||||
:style="{color: iconColor}"
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
|
<slot
|
||||||
|
v-else
|
||||||
|
name="icon"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<span>
|
<span>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
@ -39,7 +35,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed} from 'vue'
|
import {computed} from 'vue'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
|
|
||||||
|
|
||||||
const props = defineProps<ButtonProps>()
|
const props = defineProps<ButtonProps>()
|
||||||
|
|
||||||
|
|
@ -53,8 +48,6 @@ export type ButtonTypes = keyof typeof VARIANT_CLASS_MAP
|
||||||
|
|
||||||
export interface ButtonProps {
|
export interface ButtonProps {
|
||||||
variant?: ButtonTypes
|
variant?: ButtonTypes
|
||||||
icon?: IconProp
|
|
||||||
iconColor?: string
|
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
shadow?: boolean
|
shadow?: boolean
|
||||||
|
|
@ -64,7 +57,6 @@ export interface ButtonProps {
|
||||||
|
|
||||||
defineOptions({name: 'XButton'})
|
defineOptions({name: 'XButton'})
|
||||||
|
|
||||||
// @ts-expect-error - Complex union type from IconProp causes TS2590, but the code is correct
|
|
||||||
const variant = computed(() => (props.variant ?? 'primary') as ButtonTypes)
|
const variant = computed(() => (props.variant ?? 'primary') as ButtonTypes)
|
||||||
const shadow = computed(() => (props.shadow ?? true) as boolean)
|
const shadow = computed(() => (props.shadow ?? true) as boolean)
|
||||||
const wrap = computed(() => (props.wrap ?? true) as boolean)
|
const wrap = computed(() => (props.wrap ?? true) as boolean)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
class="datepicker__quick-select-date"
|
class="datepicker__quick-select-date"
|
||||||
@click.stop="setDate('today')"
|
@click.stop="setDate('today')"
|
||||||
>
|
>
|
||||||
<span class="icon"><Icon :icon="['far', 'calendar-alt']" /></span>
|
<span class="icon"><PhCalendarBlank /></span>
|
||||||
<span class="text">
|
<span class="text">
|
||||||
<span>{{ $t('input.datepicker.today') }}</span>
|
<span>{{ $t('input.datepicker.today') }}</span>
|
||||||
<span class="weekday">{{ getWeekdayFromStringInterval('today') }}</span>
|
<span class="weekday">{{ getWeekdayFromStringInterval('today') }}</span>
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
class="datepicker__quick-select-date"
|
class="datepicker__quick-select-date"
|
||||||
@click.stop="setDate('tomorrow')"
|
@click.stop="setDate('tomorrow')"
|
||||||
>
|
>
|
||||||
<span class="icon"><Icon :icon="['far', 'sun']" /></span>
|
<span class="icon"><PhSun /></span>
|
||||||
<span class="text">
|
<span class="text">
|
||||||
<span>{{ $t('input.datepicker.tomorrow') }}</span>
|
<span>{{ $t('input.datepicker.tomorrow') }}</span>
|
||||||
<span class="weekday">{{ getWeekdayFromStringInterval('tomorrow') }}</span>
|
<span class="weekday">{{ getWeekdayFromStringInterval('tomorrow') }}</span>
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
class="datepicker__quick-select-date"
|
class="datepicker__quick-select-date"
|
||||||
@click.stop="setDate('nextMonday')"
|
@click.stop="setDate('nextMonday')"
|
||||||
>
|
>
|
||||||
<span class="icon"><Icon icon="coffee" /></span>
|
<span class="icon"><PhCoffee /></span>
|
||||||
<span class="text">
|
<span class="text">
|
||||||
<span>{{ $t('input.datepicker.nextMonday') }}</span>
|
<span>{{ $t('input.datepicker.nextMonday') }}</span>
|
||||||
<span class="weekday">{{ getWeekdayFromStringInterval('nextMonday') }}</span>
|
<span class="weekday">{{ getWeekdayFromStringInterval('nextMonday') }}</span>
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
class="datepicker__quick-select-date"
|
class="datepicker__quick-select-date"
|
||||||
@click.stop="setDate('thisWeekend')"
|
@click.stop="setDate('thisWeekend')"
|
||||||
>
|
>
|
||||||
<span class="icon"><Icon icon="cocktail" /></span>
|
<span class="icon"><PhMartini /></span>
|
||||||
<span class="text">
|
<span class="text">
|
||||||
<span>{{ $t('input.datepicker.thisWeekend') }}</span>
|
<span>{{ $t('input.datepicker.thisWeekend') }}</span>
|
||||||
<span class="weekday">{{ getWeekdayFromStringInterval('thisWeekend') }}</span>
|
<span class="weekday">{{ getWeekdayFromStringInterval('thisWeekend') }}</span>
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
class="datepicker__quick-select-date"
|
class="datepicker__quick-select-date"
|
||||||
@click.stop="setDate('laterThisWeek')"
|
@click.stop="setDate('laterThisWeek')"
|
||||||
>
|
>
|
||||||
<span class="icon"><Icon icon="chess-knight" /></span>
|
<span class="icon"><PhHorse /></span>
|
||||||
<span class="text">
|
<span class="text">
|
||||||
<span>{{ $t('input.datepicker.laterThisWeek') }}</span>
|
<span>{{ $t('input.datepicker.laterThisWeek') }}</span>
|
||||||
<span class="weekday">{{ getWeekdayFromStringInterval('laterThisWeek') }}</span>
|
<span class="weekday">{{ getWeekdayFromStringInterval('laterThisWeek') }}</span>
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
class="datepicker__quick-select-date"
|
class="datepicker__quick-select-date"
|
||||||
@click.stop="setDate('nextWeek')"
|
@click.stop="setDate('nextWeek')"
|
||||||
>
|
>
|
||||||
<span class="icon"><Icon icon="forward" /></span>
|
<span class="icon"><PhFastForward /></span>
|
||||||
<span class="text">
|
<span class="text">
|
||||||
<span>{{ $t('input.datepicker.nextWeek') }}</span>
|
<span>{{ $t('input.datepicker.nextWeek') }}</span>
|
||||||
<span class="weekday">{{ getWeekdayFromStringInterval('nextWeek') }}</span>
|
<span class="weekday">{{ getWeekdayFromStringInterval('nextWeek') }}</span>
|
||||||
|
|
@ -77,6 +77,7 @@ import flatPickr from 'vue-flatpickr-component'
|
||||||
import 'flatpickr/dist/flatpickr.css'
|
import 'flatpickr/dist/flatpickr.css'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
import {PhCalendarBlank, PhSun, PhCoffee, PhMartini, PhHorse, PhFastForward} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import {formatDate} from '@/helpers/time/formatDate'
|
import {formatDate} from '@/helpers/time/formatDate'
|
||||||
import {calculateDayInterval} from '@/helpers/time/calculateDayInterval'
|
import {calculateDayInterval} from '@/helpers/time/calculateDayInterval'
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
class="removal-button"
|
class="removal-button"
|
||||||
@click="resetSelectedValue"
|
@click="resetSelectedValue"
|
||||||
>
|
>
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -134,6 +134,7 @@ import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||||
|
import {PhX} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
/** The object with the value, updated every time an entry is selected */
|
/** The object with the value, updated every time an entry is selected */
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
:aria-label="passwordFieldType === 'password' ? $t('user.auth.showPassword') : $t('user.auth.hidePassword')"
|
:aria-label="passwordFieldType === 'password' ? $t('user.auth.showPassword') : $t('user.auth.hidePassword')"
|
||||||
@click="togglePasswordFieldType"
|
@click="togglePasswordFieldType"
|
||||||
>
|
>
|
||||||
<Icon :icon="passwordFieldType === 'password' ? 'eye' : 'eye-slash'" />
|
<PhEye v-if="passwordFieldType === 'password'" /><PhEyeSlash v-else />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
|
|
@ -37,6 +37,7 @@ import {useDebounceFn} from '@vueuse/core'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import {validatePassword} from '@/helpers/validatePasswort'
|
import {validatePassword} from '@/helpers/validatePasswort'
|
||||||
|
import {PhEye, PhEyeSlash} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
modelValue: string,
|
modelValue: string,
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||||
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
||||||
import {useAuthStore} from '@/stores/auth'
|
import {useAuthStore} from '@/stores/auth'
|
||||||
import {useColorScheme} from '@/composables/useColorScheme'
|
import {useColorScheme} from '@/composables/useColorScheme'
|
||||||
|
import {PhSmiley} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
entityKind: ReactionKind,
|
entityKind: ReactionKind,
|
||||||
|
|
@ -167,7 +168,7 @@ async function toggleReaction(value: string | number) {
|
||||||
@click.stop="toggleEmojiPicker"
|
@click.stop="toggleEmojiPicker"
|
||||||
>
|
>
|
||||||
<span class="is-sr-only">{{ $t('reaction.add') }}</span>
|
<span class="is-sr-only">{{ $t('reaction.add') }}</span>
|
||||||
<Icon :icon="['far', 'face-laugh']" />
|
<PhSmiley />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<CustomTransition name="fade">
|
<CustomTransition name="fade">
|
||||||
<VuemojiPicker
|
<VuemojiPicker
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
:class="{ 'is-selected': index === selectedIndex }"
|
:class="{ 'is-selected': index === selectedIndex }"
|
||||||
@click="selectItem(index)"
|
@click="selectItem(index)"
|
||||||
>
|
>
|
||||||
<Icon :icon="item.icon" />
|
<component :is="item.icon" />
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>{{ item.title }}</p>
|
<p>{{ item.title }}</p>
|
||||||
<p>{{ item.description }}</p>
|
<p>{{ item.description }}</p>
|
||||||
|
|
@ -27,10 +27,10 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
/* eslint-disable vue/component-api-style */
|
/* eslint-disable vue/component-api-style */
|
||||||
import type {PropType} from 'vue'
|
import type {PropType} from 'vue'
|
||||||
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
|
import type {Component} from 'vue'
|
||||||
|
|
||||||
interface CommandItem {
|
interface CommandItem {
|
||||||
icon: IconProp
|
icon: Component
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
command: () => void
|
command: () => void
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
@click="editor.chain().focus().toggleHeading({ level: 1 }).run()"
|
@click="editor.chain().focus().toggleHeading({ level: 1 }).run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'header']" />
|
<PhTextH />
|
||||||
<span
|
<span
|
||||||
class="icon__lower-text"
|
class="icon__lower-text"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
@click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
|
@click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'header']" />
|
<PhTextH />
|
||||||
<span
|
<span
|
||||||
class="icon__lower-text"
|
class="icon__lower-text"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
@click="editor.chain().focus().toggleHeading({ level: 3 }).run()"
|
@click="editor.chain().focus().toggleHeading({ level: 3 }).run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'header']" />
|
<PhTextH />
|
||||||
<span
|
<span
|
||||||
class="icon__lower-text"
|
class="icon__lower-text"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
@click="editor.chain().focus().toggleBold().run()"
|
@click="editor.chain().focus().toggleBold().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'bold']" />
|
<PhTextB />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.bold') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.bold') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -67,7 +67,7 @@
|
||||||
@click="editor.chain().focus().toggleItalic().run()"
|
@click="editor.chain().focus().toggleItalic().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'italic']" />
|
<PhTextItalic />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.italic') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.italic') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -78,7 +78,7 @@
|
||||||
@click="editor.chain().focus().toggleUnderline().run()"
|
@click="editor.chain().focus().toggleUnderline().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'underline']" />
|
<PhTextUnderline />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.underline') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.underline') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -89,7 +89,7 @@
|
||||||
@click="editor.chain().focus().toggleStrike().run()"
|
@click="editor.chain().focus().toggleStrike().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'strikethrough']" />
|
<PhTextStrikethrough />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.strikethrough') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.strikethrough') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -103,7 +103,7 @@
|
||||||
@click="editor.chain().focus().toggleCodeBlock().run()"
|
@click="editor.chain().focus().toggleCodeBlock().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'code']" />
|
<PhCode />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.code') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.code') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -114,7 +114,7 @@
|
||||||
@click="editor.chain().focus().toggleBlockquote().run()"
|
@click="editor.chain().focus().toggleBlockquote().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'quote-right']" />
|
<PhQuotes />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.quote') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.quote') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -128,7 +128,7 @@
|
||||||
@click="editor.chain().focus().toggleBulletList().run()"
|
@click="editor.chain().focus().toggleBulletList().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'list-ul']" />
|
<PhListBullets />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.bulletList') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.bulletList') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -139,7 +139,7 @@
|
||||||
@click="editor.chain().focus().toggleOrderedList().run()"
|
@click="editor.chain().focus().toggleOrderedList().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'list-ol']" />
|
<PhListNumbers />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.orderedList') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.orderedList') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -150,7 +150,7 @@
|
||||||
@click="editor.chain().focus().toggleTaskList().run()"
|
@click="editor.chain().focus().toggleTaskList().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon icon="list-check" />
|
<PhListChecks />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.taskList') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.taskList') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -163,7 +163,7 @@
|
||||||
@click="e => emit('imageUploadClicked', e)"
|
@click="e => emit('imageUploadClicked', e)"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon icon="image" />
|
<PhImage />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.image') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.image') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -178,7 +178,7 @@
|
||||||
@click="setLink"
|
@click="setLink"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'link']" />
|
<PhLink />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.link') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.link') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -190,7 +190,7 @@
|
||||||
@click="editor.chain().focus().setParagraph().run()"
|
@click="editor.chain().focus().setParagraph().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'paragraph']" />
|
<PhParagraph />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.text') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.text') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -201,7 +201,7 @@
|
||||||
@click="editor.chain().focus().setHorizontalRule().run()"
|
@click="editor.chain().focus().setHorizontalRule().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'ruler-horizontal']" />
|
<PhRuler />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.horizontalRule') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.horizontalRule') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -214,7 +214,7 @@
|
||||||
@click="editor.chain().focus().undo().run()"
|
@click="editor.chain().focus().undo().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'undo']" />
|
<PhArrowCounterClockwise />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.undo') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.undo') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -224,7 +224,7 @@
|
||||||
@click="editor.chain().focus().redo().run()"
|
@click="editor.chain().focus().redo().run()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'redo']" />
|
<PhArrowClockwise />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.redo') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.redo') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -239,7 +239,7 @@
|
||||||
@click="toggleTableMode"
|
@click="toggleTableMode"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['fas', 'table']" />
|
<PhTable />
|
||||||
</span>
|
</span>
|
||||||
<span class="is-sr-only">{{ $t('input.editor.table.title') }}</span>
|
<span class="is-sr-only">{{ $t('input.editor.table.title') }}</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -366,6 +366,13 @@
|
||||||
import {ref} from 'vue'
|
import {ref} from 'vue'
|
||||||
import type {Editor} from '@tiptap/vue-3'
|
import type {Editor} from '@tiptap/vue-3'
|
||||||
|
|
||||||
|
import {
|
||||||
|
PhTextH, PhTextB, PhTextItalic, PhTextUnderline, PhTextStrikethrough,
|
||||||
|
PhCode, PhQuotes, PhListBullets, PhListNumbers, PhListChecks,
|
||||||
|
PhImage, PhLink, PhParagraph, PhRuler,
|
||||||
|
PhArrowCounterClockwise, PhArrowClockwise, PhTable,
|
||||||
|
} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import {setLinkInEditor} from '@/components/input/editor/setLinkInEditor'
|
import {setLinkInEditor} from '@/components/input/editor/setLinkInEditor'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
:class="{ 'is-active': editor.isActive('bold') }"
|
:class="{ 'is-active': editor.isActive('bold') }"
|
||||||
@click="() => editor?.chain().focus().toggleBold().run()"
|
@click="() => editor?.chain().focus().toggleBold().run()"
|
||||||
>
|
>
|
||||||
<Icon :icon="['fas', 'bold']" />
|
<PhTextB />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-tooltip="$t('input.editor.italic')"
|
v-tooltip="$t('input.editor.italic')"
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
:class="{ 'is-active': editor.isActive('italic') }"
|
:class="{ 'is-active': editor.isActive('italic') }"
|
||||||
@click="() => editor?.chain().focus().toggleItalic().run()"
|
@click="() => editor?.chain().focus().toggleItalic().run()"
|
||||||
>
|
>
|
||||||
<Icon :icon="['fas', 'italic']" />
|
<PhTextItalic />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-tooltip="$t('input.editor.underline')"
|
v-tooltip="$t('input.editor.underline')"
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
:class="{ 'is-active': editor.isActive('underline') }"
|
:class="{ 'is-active': editor.isActive('underline') }"
|
||||||
@click="() => editor?.chain().focus().toggleUnderline().run()"
|
@click="() => editor?.chain().focus().toggleUnderline().run()"
|
||||||
>
|
>
|
||||||
<Icon :icon="['fas', 'underline']" />
|
<PhTextUnderline />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-tooltip="$t('input.editor.strikethrough')"
|
v-tooltip="$t('input.editor.strikethrough')"
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
:class="{ 'is-active': editor.isActive('strike') }"
|
:class="{ 'is-active': editor.isActive('strike') }"
|
||||||
@click="() => editor?.chain().focus().toggleStrike().run()"
|
@click="() => editor?.chain().focus().toggleStrike().run()"
|
||||||
>
|
>
|
||||||
<Icon :icon="['fas', 'strikethrough']" />
|
<PhTextStrikethrough />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-tooltip="$t('input.editor.code')"
|
v-tooltip="$t('input.editor.code')"
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
:class="{ 'is-active': editor.isActive('code') }"
|
:class="{ 'is-active': editor.isActive('code') }"
|
||||||
@click="() => editor?.chain().focus().toggleCode().run()"
|
@click="() => editor?.chain().focus().toggleCode().run()"
|
||||||
>
|
>
|
||||||
<Icon :icon="['fas', 'code']" />
|
<PhCode />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-tooltip="$t('input.editor.link')"
|
v-tooltip="$t('input.editor.link')"
|
||||||
|
|
@ -63,7 +63,7 @@
|
||||||
:class="{ 'is-active': editor.isActive('link') }"
|
:class="{ 'is-active': editor.isActive('link') }"
|
||||||
@click="setLink"
|
@click="setLink"
|
||||||
>
|
>
|
||||||
<Icon :icon="['fas', 'link']" />
|
<PhLink />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</BubbleMenu>
|
</BubbleMenu>
|
||||||
|
|
@ -146,6 +146,8 @@ import {computed, nextTick, onBeforeUnmount, onMounted, ref, watch} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import {eventToHotkeyString} from '@github/hotkey'
|
import {eventToHotkeyString} from '@github/hotkey'
|
||||||
|
|
||||||
|
import {PhTextB, PhTextItalic, PhTextUnderline, PhTextStrikethrough, PhCode, PhLink} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import EditorToolbar from './EditorToolbar.vue'
|
import EditorToolbar from './EditorToolbar.vue'
|
||||||
|
|
||||||
import StarterKit from '@tiptap/starter-kit'
|
import StarterKit from '@tiptap/starter-kit'
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
import type {Editor, Range} from '@tiptap/core'
|
import type {Editor, Range} from '@tiptap/core'
|
||||||
import {VueRenderer} from '@tiptap/vue-3'
|
import {VueRenderer} from '@tiptap/vue-3'
|
||||||
|
import {
|
||||||
|
PhTextAa, PhTextH, PhListBullets, PhListNumbers, PhListChecks,
|
||||||
|
PhQuotes, PhCode, PhImage, PhRuler,
|
||||||
|
} from '@phosphor-icons/vue'
|
||||||
import {computePosition, flip, shift, offset, autoUpdate} from '@floating-ui/dom'
|
import {computePosition, flip, shift, offset, autoUpdate} from '@floating-ui/dom'
|
||||||
|
|
||||||
import CommandsList from './CommandsList.vue'
|
import CommandsList from './CommandsList.vue'
|
||||||
|
|
@ -21,7 +25,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
||||||
{
|
{
|
||||||
title: t('input.editor.text'),
|
title: t('input.editor.text'),
|
||||||
description: t('input.editor.textTooltip'),
|
description: t('input.editor.textTooltip'),
|
||||||
icon: 'fa-font',
|
icon: PhTextAa,
|
||||||
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -34,7 +38,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
||||||
{
|
{
|
||||||
title: t('input.editor.heading1'),
|
title: t('input.editor.heading1'),
|
||||||
description: t('input.editor.heading1Tooltip'),
|
description: t('input.editor.heading1Tooltip'),
|
||||||
icon: 'fa-header',
|
icon: PhTextH,
|
||||||
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -47,7 +51,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
||||||
{
|
{
|
||||||
title: t('input.editor.heading2'),
|
title: t('input.editor.heading2'),
|
||||||
description: t('input.editor.heading2Tooltip'),
|
description: t('input.editor.heading2Tooltip'),
|
||||||
icon: 'fa-header',
|
icon: PhTextH,
|
||||||
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -60,7 +64,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
||||||
{
|
{
|
||||||
title: t('input.editor.heading3'),
|
title: t('input.editor.heading3'),
|
||||||
description: t('input.editor.heading3Tooltip'),
|
description: t('input.editor.heading3Tooltip'),
|
||||||
icon: 'fa-header',
|
icon: PhTextH,
|
||||||
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -73,7 +77,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
||||||
{
|
{
|
||||||
title: t('input.editor.bulletList'),
|
title: t('input.editor.bulletList'),
|
||||||
description: t('input.editor.bulletListTooltip'),
|
description: t('input.editor.bulletListTooltip'),
|
||||||
icon: 'fa-list-ul',
|
icon: PhListBullets,
|
||||||
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -86,7 +90,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
||||||
{
|
{
|
||||||
title: t('input.editor.orderedList'),
|
title: t('input.editor.orderedList'),
|
||||||
description: t('input.editor.orderedListTooltip'),
|
description: t('input.editor.orderedListTooltip'),
|
||||||
icon: 'fa-list-ol',
|
icon: PhListNumbers,
|
||||||
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -99,7 +103,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
||||||
{
|
{
|
||||||
title: t('input.editor.taskList'),
|
title: t('input.editor.taskList'),
|
||||||
description: t('input.editor.taskListTooltip'),
|
description: t('input.editor.taskListTooltip'),
|
||||||
icon: 'fa-list-check',
|
icon: PhListChecks,
|
||||||
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -112,7 +116,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
||||||
{
|
{
|
||||||
title: t('input.editor.quote'),
|
title: t('input.editor.quote'),
|
||||||
description: t('input.editor.quoteTooltip'),
|
description: t('input.editor.quoteTooltip'),
|
||||||
icon: 'fa-quote-right',
|
icon: PhQuotes,
|
||||||
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -125,7 +129,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
||||||
{
|
{
|
||||||
title: t('input.editor.code'),
|
title: t('input.editor.code'),
|
||||||
description: t('input.editor.codeTooltip'),
|
description: t('input.editor.codeTooltip'),
|
||||||
icon: 'fa-code',
|
icon: PhCode,
|
||||||
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -138,7 +142,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
||||||
{
|
{
|
||||||
title: t('input.editor.image'),
|
title: t('input.editor.image'),
|
||||||
description: t('input.editor.imageTooltip'),
|
description: t('input.editor.imageTooltip'),
|
||||||
icon: 'fa-image',
|
icon: PhImage,
|
||||||
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
|
@ -154,7 +158,7 @@ export default function suggestionSetup(t: TranslateFunction) {
|
||||||
{
|
{
|
||||||
title: t('input.editor.horizontalRule'),
|
title: t('input.editor.horizontalRule'),
|
||||||
description: t('input.editor.horizontalRuleTooltip'),
|
description: t('input.editor.horizontalRuleTooltip'),
|
||||||
icon: 'fa-ruler-horizontal',
|
icon: PhRuler,
|
||||||
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
command: ({editor, range}: {editor: Editor, range: Range}) => {
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
@click="$emit('close')"
|
@click="$emit('close')"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</span>
|
</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</header>
|
</header>
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
import {PhX} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
withDefaults(defineProps<{
|
withDefaults(defineProps<{
|
||||||
title?: string
|
title?: string
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,19 @@
|
||||||
<XButton
|
<XButton
|
||||||
v-if="hasPrimaryAction"
|
v-if="hasPrimaryAction"
|
||||||
variant="primary"
|
variant="primary"
|
||||||
:icon="primaryIcon"
|
|
||||||
:disabled="isBusy"
|
:disabled="isBusy"
|
||||||
class="mis-2"
|
class="mis-2"
|
||||||
:loading="currentLoading"
|
:loading="currentLoading"
|
||||||
@click.prevent.stop="primary"
|
@click.prevent.stop="primary"
|
||||||
>
|
>
|
||||||
|
<template
|
||||||
|
v-if="showPrimaryIcon"
|
||||||
|
#icon
|
||||||
|
>
|
||||||
|
<slot name="primary-icon">
|
||||||
|
<PhPlus />
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
{{ primaryLabel || $t('misc.create') }}
|
{{ primaryLabel || $t('misc.create') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
@ -51,14 +58,14 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
|
import {PhPlus} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import {computed, ref, toRef, watch} from 'vue'
|
import {computed, ref, toRef, watch} from 'vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
title: string,
|
title: string,
|
||||||
primaryLabel?: string,
|
primaryLabel?: string,
|
||||||
primaryIcon?: IconProp,
|
showPrimaryIcon?: boolean,
|
||||||
primaryDisabled?: boolean,
|
primaryDisabled?: boolean,
|
||||||
hasPrimaryAction?: boolean,
|
hasPrimaryAction?: boolean,
|
||||||
tertiary?: string,
|
tertiary?: string,
|
||||||
|
|
@ -66,7 +73,7 @@ const props = withDefaults(defineProps<{
|
||||||
loading?: boolean,
|
loading?: boolean,
|
||||||
}>(), {
|
}>(), {
|
||||||
primaryLabel: '',
|
primaryLabel: '',
|
||||||
primaryIcon: 'plus',
|
showPrimaryIcon: true,
|
||||||
primaryDisabled: false,
|
primaryDisabled: false,
|
||||||
hasPrimaryAction: true,
|
hasPrimaryAction: true,
|
||||||
tertiary: '',
|
tertiary: '',
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,7 @@
|
||||||
class="dropdown-trigger is-flex"
|
class="dropdown-trigger is-flex"
|
||||||
@click="toggleOpen"
|
@click="toggleOpen"
|
||||||
>
|
>
|
||||||
<Icon
|
<PhDotsThree class="icon" />
|
||||||
:icon="triggerIcon"
|
|
||||||
class="icon"
|
|
||||||
/>
|
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
|
|
@ -42,17 +39,11 @@
|
||||||
import {ref, nextTick, watch, computed} from 'vue'
|
import {ref, nextTick, watch, computed} from 'vue'
|
||||||
import {onClickOutside} from '@vueuse/core'
|
import {onClickOutside} from '@vueuse/core'
|
||||||
import {computePosition, autoPlacement, offset, shift} from '@floating-ui/dom'
|
import {computePosition, autoPlacement, offset, shift} from '@floating-ui/dom'
|
||||||
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
|
import {PhDotsThree} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
|
||||||
withDefaults(defineProps<{
|
|
||||||
triggerIcon?: IconProp
|
|
||||||
}>(), {
|
|
||||||
triggerIcon: 'ellipsis-h',
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'close': [event: PointerEvent]
|
'close': [event: PointerEvent]
|
||||||
}>()
|
}>()
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@
|
||||||
:class="{'is-disabled': disabled}"
|
:class="{'is-disabled': disabled}"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
v-if="icon"
|
v-if="$slots.icon"
|
||||||
class="icon is-small"
|
class="icon is-small"
|
||||||
:class="iconClass"
|
:class="iconClass"
|
||||||
>
|
>
|
||||||
<Icon :icon="icon" />
|
<slot name="icon" />
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
@ -18,12 +18,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import BaseButton, {type BaseButtonProps} from '@/components/base//BaseButton.vue'
|
import BaseButton, {type BaseButtonProps} from '@/components/base/BaseButton.vue'
|
||||||
import Icon from '@/components/misc/Icon'
|
|
||||||
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
|
|
||||||
|
|
||||||
export interface DropDownItemProps extends /* @vue-ignore */ BaseButtonProps {
|
export interface DropDownItemProps extends /* @vue-ignore */ BaseButtonProps {
|
||||||
icon?: IconProp,
|
|
||||||
iconClass?: object | string,
|
iconClass?: object | string,
|
||||||
disabled?: boolean,
|
disabled?: boolean,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,206 +0,0 @@
|
||||||
import {library} from '@fortawesome/fontawesome-svg-core'
|
|
||||||
import {
|
|
||||||
faAlignLeft,
|
|
||||||
faAngleRight,
|
|
||||||
faAnglesUp,
|
|
||||||
faArchive,
|
|
||||||
faArrowLeft,
|
|
||||||
faArrowDownShortWide,
|
|
||||||
faArrowUpFromBracket,
|
|
||||||
faArrowUpRightFromSquare,
|
|
||||||
faArrowUpShortWide,
|
|
||||||
faBold,
|
|
||||||
faItalic,
|
|
||||||
faStrikethrough,
|
|
||||||
faCode,
|
|
||||||
faBars,
|
|
||||||
faBell,
|
|
||||||
faBolt,
|
|
||||||
faCalendar,
|
|
||||||
faCheck,
|
|
||||||
faCheckDouble,
|
|
||||||
faChessKnight,
|
|
||||||
faChevronDown,
|
|
||||||
faCircleInfo,
|
|
||||||
faCloudDownloadAlt,
|
|
||||||
faCloudUploadAlt,
|
|
||||||
faCocktail,
|
|
||||||
faCoffee,
|
|
||||||
faCog,
|
|
||||||
faCopy,
|
|
||||||
faDownload,
|
|
||||||
faEllipsisH,
|
|
||||||
faEllipsisV,
|
|
||||||
faExclamation,
|
|
||||||
faExclamationCircle,
|
|
||||||
faEye,
|
|
||||||
faEyeSlash,
|
|
||||||
faFile,
|
|
||||||
faFileImage,
|
|
||||||
faFillDrip,
|
|
||||||
faFilter,
|
|
||||||
faForward,
|
|
||||||
faGripLines,
|
|
||||||
faHeader,
|
|
||||||
faHistory,
|
|
||||||
faImage,
|
|
||||||
faKeyboard,
|
|
||||||
faLayerGroup,
|
|
||||||
faList,
|
|
||||||
faListOl,
|
|
||||||
faLock,
|
|
||||||
faPaperclip,
|
|
||||||
faPaste,
|
|
||||||
faPen,
|
|
||||||
faPencilAlt,
|
|
||||||
faPercent,
|
|
||||||
faPlay,
|
|
||||||
faPlus,
|
|
||||||
faPowerOff,
|
|
||||||
faSearch,
|
|
||||||
faShareAlt,
|
|
||||||
faSignOutAlt,
|
|
||||||
faSitemap,
|
|
||||||
faSort,
|
|
||||||
faSortUp,
|
|
||||||
faStar as faStarSolid,
|
|
||||||
faStop,
|
|
||||||
faTachometerAlt,
|
|
||||||
faTags,
|
|
||||||
faTasks,
|
|
||||||
faTh,
|
|
||||||
faTimes,
|
|
||||||
faTrashAlt,
|
|
||||||
faUser,
|
|
||||||
faUsers,
|
|
||||||
faQuoteRight,
|
|
||||||
faListUl,
|
|
||||||
faLink,
|
|
||||||
faUndo,
|
|
||||||
faRedo,
|
|
||||||
faUnlink,
|
|
||||||
faParagraph,
|
|
||||||
faTable,
|
|
||||||
faX, faArrowTurnDown, faListCheck, faXmark, faXmarksLines, faFont, faRulerHorizontal, faUnderline,
|
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
|
||||||
import {
|
|
||||||
faBellSlash,
|
|
||||||
faCalendarAlt,
|
|
||||||
faCheckSquare,
|
|
||||||
faClock,
|
|
||||||
faComments,
|
|
||||||
faSave,
|
|
||||||
faSquareCheck,
|
|
||||||
faStar,
|
|
||||||
faSun,
|
|
||||||
faTimesCircle,
|
|
||||||
faCircleQuestion, faFaceLaugh,
|
|
||||||
} from '@fortawesome/free-regular-svg-icons'
|
|
||||||
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome'
|
|
||||||
|
|
||||||
import type {FontAwesomeIcon as FontAwesomeIconFixedTypes} from '@/types/vue-fontawesome'
|
|
||||||
|
|
||||||
library.add(faBold)
|
|
||||||
library.add(faUndo)
|
|
||||||
library.add(faRedo)
|
|
||||||
library.add(faItalic)
|
|
||||||
library.add(faLink)
|
|
||||||
library.add(faUnlink)
|
|
||||||
library.add(faParagraph)
|
|
||||||
library.add(faSquareCheck)
|
|
||||||
library.add(faTable)
|
|
||||||
library.add(faFile)
|
|
||||||
library.add(faFileImage)
|
|
||||||
library.add(faCheckSquare)
|
|
||||||
library.add(faStrikethrough)
|
|
||||||
library.add(faCode)
|
|
||||||
library.add(faQuoteRight)
|
|
||||||
library.add(faListUl)
|
|
||||||
library.add(faAlignLeft)
|
|
||||||
library.add(faAngleRight)
|
|
||||||
library.add(faArchive)
|
|
||||||
library.add(faArrowLeft)
|
|
||||||
library.add(faBars)
|
|
||||||
library.add(faBell)
|
|
||||||
library.add(faBellSlash)
|
|
||||||
library.add(faCalendar)
|
|
||||||
library.add(faCalendarAlt)
|
|
||||||
library.add(faCheck)
|
|
||||||
library.add(faCheckDouble)
|
|
||||||
library.add(faChessKnight)
|
|
||||||
library.add(faChevronDown)
|
|
||||||
library.add(faCircleInfo)
|
|
||||||
library.add(faCircleQuestion)
|
|
||||||
library.add(faClock)
|
|
||||||
library.add(faCloudDownloadAlt)
|
|
||||||
library.add(faCloudUploadAlt)
|
|
||||||
library.add(faCocktail)
|
|
||||||
library.add(faCoffee)
|
|
||||||
library.add(faCog)
|
|
||||||
library.add(faComments)
|
|
||||||
library.add(faCopy)
|
|
||||||
library.add(faDownload)
|
|
||||||
library.add(faEllipsisH)
|
|
||||||
library.add(faEllipsisV)
|
|
||||||
library.add(faExclamationCircle)
|
|
||||||
library.add(faEye)
|
|
||||||
library.add(faEyeSlash)
|
|
||||||
library.add(faFillDrip)
|
|
||||||
library.add(faFilter)
|
|
||||||
library.add(faForward)
|
|
||||||
library.add(faGripLines)
|
|
||||||
library.add(faHeader)
|
|
||||||
library.add(faHistory)
|
|
||||||
library.add(faImage)
|
|
||||||
library.add(faKeyboard)
|
|
||||||
library.add(faLayerGroup)
|
|
||||||
library.add(faList)
|
|
||||||
library.add(faListOl)
|
|
||||||
library.add(faLock)
|
|
||||||
library.add(faPaperclip)
|
|
||||||
library.add(faPaste)
|
|
||||||
library.add(faPen)
|
|
||||||
library.add(faPencilAlt)
|
|
||||||
library.add(faPercent)
|
|
||||||
library.add(faPlay)
|
|
||||||
library.add(faPlus)
|
|
||||||
library.add(faPowerOff)
|
|
||||||
library.add(faSave)
|
|
||||||
library.add(faSearch)
|
|
||||||
library.add(faShareAlt)
|
|
||||||
library.add(faSignOutAlt)
|
|
||||||
library.add(faSitemap)
|
|
||||||
library.add(faSort)
|
|
||||||
library.add(faSortUp)
|
|
||||||
library.add(faStar)
|
|
||||||
library.add(faStarSolid)
|
|
||||||
library.add(faStop)
|
|
||||||
library.add(faSun)
|
|
||||||
library.add(faTachometerAlt)
|
|
||||||
library.add(faTags)
|
|
||||||
library.add(faTasks)
|
|
||||||
library.add(faTh)
|
|
||||||
library.add(faTimes)
|
|
||||||
library.add(faTimesCircle)
|
|
||||||
library.add(faTrashAlt)
|
|
||||||
library.add(faUser)
|
|
||||||
library.add(faUsers)
|
|
||||||
library.add(faArrowDownShortWide)
|
|
||||||
library.add(faArrowUpFromBracket)
|
|
||||||
library.add(faArrowUpShortWide)
|
|
||||||
library.add(faX)
|
|
||||||
library.add(faAnglesUp)
|
|
||||||
library.add(faBolt)
|
|
||||||
library.add(faArrowTurnDown)
|
|
||||||
library.add(faListCheck)
|
|
||||||
library.add(faXmark)
|
|
||||||
library.add(faXmarksLines)
|
|
||||||
library.add(faFont)
|
|
||||||
library.add(faRulerHorizontal)
|
|
||||||
library.add(faUnderline)
|
|
||||||
library.add(faFaceLaugh)
|
|
||||||
library.add(faExclamation)
|
|
||||||
library.add(faArrowUpRightFromSquare)
|
|
||||||
|
|
||||||
// overwriting the wrong types
|
|
||||||
export default FontAwesomeIcon as unknown as FontAwesomeIconFixedTypes
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
class="close"
|
class="close"
|
||||||
@click="$emit('close')"
|
@click="$emit('close')"
|
||||||
>
|
>
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<div
|
<div
|
||||||
class="modal-content"
|
class="modal-content"
|
||||||
|
|
@ -68,6 +68,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
import {PhX} from '@phosphor-icons/vue'
|
||||||
import {ref, useAttrs, watchEffect, onBeforeUnmount, watch} from 'vue'
|
import {ref, useAttrs, watchEffect, onBeforeUnmount, watch} from 'vue'
|
||||||
import {useScrollLock} from '@vueuse/core'
|
import {useScrollLock} from '@vueuse/core'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
import {PhMagnifyingGlass} from '@phosphor-icons/vue'
|
||||||
import {useBaseStore} from '@/stores/base'
|
import {useBaseStore} from '@/stores/base'
|
||||||
import {onBeforeUnmount, onMounted} from 'vue'
|
import {onBeforeUnmount, onMounted} from 'vue'
|
||||||
import {eventToHotkeyString} from '@github/hotkey'
|
import {eventToHotkeyString} from '@github/hotkey'
|
||||||
|
|
@ -40,6 +41,6 @@ function openQuickActions() {
|
||||||
:title="$t('keyboardShortcuts.quickSearch')"
|
:title="$t('keyboardShortcuts.quickSearch')"
|
||||||
@click="openQuickActions"
|
@click="openQuickActions"
|
||||||
>
|
>
|
||||||
<Icon icon="search" />
|
<PhMagnifyingGlass />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,23 @@
|
||||||
v-if="type === 'button'"
|
v-if="type === 'button'"
|
||||||
v-tooltip="tooltipText"
|
v-tooltip="tooltipText"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
:icon="iconName"
|
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
@click="changeSubscription"
|
@click="changeSubscription"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<component :is="iconComponent" />
|
||||||
|
</template>
|
||||||
{{ buttonText }}
|
{{ buttonText }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
v-else-if="type === 'dropdown'"
|
v-else-if="type === 'dropdown'"
|
||||||
v-tooltip="tooltipText"
|
v-tooltip="tooltipText"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:icon="iconName"
|
|
||||||
@click="changeSubscription"
|
@click="changeSubscription"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<component :is="iconComponent" />
|
||||||
|
</template>
|
||||||
{{ buttonText }}
|
{{ buttonText }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
|
|
@ -26,7 +30,7 @@
|
||||||
@click="changeSubscription"
|
@click="changeSubscription"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="iconName" />
|
<component :is="iconComponent" />
|
||||||
</span>
|
</span>
|
||||||
{{ buttonText }}
|
{{ buttonText }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
@ -44,7 +48,7 @@ import SubscriptionModel from '@/models/subscription'
|
||||||
import type {ISubscription} from '@/modelTypes/ISubscription'
|
import type {ISubscription} from '@/modelTypes/ISubscription'
|
||||||
|
|
||||||
import {success} from '@/message'
|
import {success} from '@/message'
|
||||||
import type { IconProp } from '@fortawesome/fontawesome-svg-core'
|
import {PhBell, PhBellSlash} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
modelValue: ISubscription | null,
|
modelValue: ISubscription | null,
|
||||||
|
|
@ -91,7 +95,7 @@ const tooltipText = computed(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const buttonText = computed(() => props.modelValue ? t('task.subscription.unsubscribe') : t('task.subscription.subscribe'))
|
const buttonText = computed(() => props.modelValue ? t('task.subscription.unsubscribe') : t('task.subscription.subscribe'))
|
||||||
const iconName = computed<IconProp>(() => props.modelValue ? ['far', 'bell-slash'] : 'bell')
|
const iconComponent = computed(() => props.modelValue ? PhBellSlash : PhBell)
|
||||||
const disabled = computed(() => props.modelValue && subscriptionEntity.value !== props.entity || false)
|
const disabled = computed(() => props.modelValue && subscriptionEntity.value !== props.entity || false)
|
||||||
|
|
||||||
function changeSubscription() {
|
function changeSubscription() {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
v-if="unreadNotifications > 0"
|
v-if="unreadNotifications > 0"
|
||||||
class="unread-indicator"
|
class="unread-indicator"
|
||||||
/>
|
/>
|
||||||
<Icon icon="bell" />
|
<PhBell />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
|
|
@ -87,6 +87,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {computed, onMounted, onUnmounted, ref} from 'vue'
|
import {computed, onMounted, onUnmounted, ref} from 'vue'
|
||||||
|
import {PhBell} from '@phosphor-icons/vue'
|
||||||
import {useRouter} from 'vue-router'
|
import {useRouter} from 'vue-router'
|
||||||
|
|
||||||
import NotificationService from '@/services/notification'
|
import NotificationService from '@/services/notification'
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,7 @@
|
||||||
@click="triggerProps.toggleOpen"
|
@click="triggerProps.toggleOpen"
|
||||||
>
|
>
|
||||||
<span class="is-sr-only">{{ $t('project.openSettingsMenu') }}</span>
|
<span class="is-sr-only">{{ $t('project.openSettingsMenu') }}</span>
|
||||||
<Icon
|
<PhDotsThree class="icon" />
|
||||||
icon="ellipsis-h"
|
|
||||||
class="icon"
|
|
||||||
/>
|
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</slot>
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -21,21 +18,27 @@
|
||||||
<template v-if="isSavedFilter(project)">
|
<template v-if="isSavedFilter(project)">
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
:to="{ name: 'filter.settings.edit', params: { projectId: project.id } }"
|
:to="{ name: 'filter.settings.edit', params: { projectId: project.id } }"
|
||||||
icon="pen"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPen />
|
||||||
|
</template>
|
||||||
{{ $t('menu.edit') }}
|
{{ $t('menu.edit') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
:to="{ name: 'project.settings.views', params: { projectId: project.id } }"
|
:to="{ name: 'project.settings.views', params: { projectId: project.id } }"
|
||||||
icon="eye"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhEye />
|
||||||
|
</template>
|
||||||
{{ $t('menu.views') }}
|
{{ $t('menu.views') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
:to="{ name: 'filter.settings.delete', params: { projectId: project.id } }"
|
:to="{ name: 'filter.settings.delete', params: { projectId: project.id } }"
|
||||||
icon="trash-alt"
|
|
||||||
class="has-text-danger"
|
class="has-text-danger"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTrash />
|
||||||
|
</template>
|
||||||
{{ $t('misc.delete') }}
|
{{ $t('misc.delete') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -43,51 +46,65 @@
|
||||||
<template v-else-if="project.isArchived">
|
<template v-else-if="project.isArchived">
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
:to="{ name: 'project.settings.archive', params: { projectId: project.id } }"
|
:to="{ name: 'project.settings.archive', params: { projectId: project.id } }"
|
||||||
icon="archive"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhArchive />
|
||||||
|
</template>
|
||||||
{{ $t('menu.unarchive') }}
|
{{ $t('menu.unarchive') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
:to="{ name: 'project.settings.edit', params: { projectId: project.id } }"
|
:to="{ name: 'project.settings.edit', params: { projectId: project.id } }"
|
||||||
icon="pen"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPen />
|
||||||
|
</template>
|
||||||
{{ $t('menu.edit') }}
|
{{ $t('menu.edit') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
v-if="!simple"
|
v-if="!simple"
|
||||||
:to="{ name: 'project.settings.views', params: { projectId: project.id } }"
|
:to="{ name: 'project.settings.views', params: { projectId: project.id } }"
|
||||||
icon="eye"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhEye />
|
||||||
|
</template>
|
||||||
{{ $t('menu.views') }}
|
{{ $t('menu.views') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
v-if="backgroundsEnabled && !simple"
|
v-if="backgroundsEnabled && !simple"
|
||||||
:to="{ name: 'project.settings.background', params: { projectId: project.id } }"
|
:to="{ name: 'project.settings.background', params: { projectId: project.id } }"
|
||||||
icon="image"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhImage />
|
||||||
|
</template>
|
||||||
{{ $t('menu.setBackground') }}
|
{{ $t('menu.setBackground') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
:to="{ name: 'project.settings.share', params: { projectId: project.id } }"
|
:to="{ name: 'project.settings.share', params: { projectId: project.id } }"
|
||||||
icon="share-alt"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhShareNetwork />
|
||||||
|
</template>
|
||||||
{{ $t('menu.share') }}
|
{{ $t('menu.share') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
:to="{ name: 'project.settings.duplicate', params: { projectId: project.id } }"
|
:to="{ name: 'project.settings.duplicate', params: { projectId: project.id } }"
|
||||||
icon="paste"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhClipboard />
|
||||||
|
</template>
|
||||||
{{ $t('menu.duplicate') }}
|
{{ $t('menu.duplicate') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
v-if="!simple"
|
v-if="!simple"
|
||||||
v-tooltip="isDefaultProject ? $t('menu.cantArchiveIsDefault') : ''"
|
v-tooltip="isDefaultProject ? $t('menu.cantArchiveIsDefault') : ''"
|
||||||
:to="{ name: 'project.settings.archive', params: { projectId: project.id } }"
|
:to="{ name: 'project.settings.archive', params: { projectId: project.id } }"
|
||||||
icon="archive"
|
|
||||||
:disabled="isDefaultProject"
|
:disabled="isDefaultProject"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhArchive />
|
||||||
|
</template>
|
||||||
{{ $t('menu.archive') }}
|
{{ $t('menu.archive') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<Subscription
|
<Subscription
|
||||||
|
|
@ -101,24 +118,30 @@
|
||||||
/>
|
/>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
:to="{ name: 'project.settings.webhooks', params: { projectId: project.id } }"
|
:to="{ name: 'project.settings.webhooks', params: { projectId: project.id } }"
|
||||||
icon="bolt"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhLightning />
|
||||||
|
</template>
|
||||||
{{ $t('project.webhooks.title') }}
|
{{ $t('project.webhooks.title') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
:to="{ name: 'project.createFromParent', params: { parentProjectId: project.id } }"
|
:to="{ name: 'project.createFromParent', params: { parentProjectId: project.id } }"
|
||||||
icon="layer-group"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhStack />
|
||||||
|
</template>
|
||||||
{{ $t('menu.createProject') }}
|
{{ $t('menu.createProject') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
v-if="project.maxPermission === PERMISSIONS.ADMIN"
|
v-if="project.maxPermission === PERMISSIONS.ADMIN"
|
||||||
v-tooltip="isDefaultProject ? $t('menu.cantDeleteIsDefault') : ''"
|
v-tooltip="isDefaultProject ? $t('menu.cantDeleteIsDefault') : ''"
|
||||||
:to="{ name: 'project.settings.delete', params: { projectId: project.id } }"
|
:to="{ name: 'project.settings.delete', params: { projectId: project.id } }"
|
||||||
icon="trash-alt"
|
|
||||||
class="has-text-danger"
|
class="has-text-danger"
|
||||||
:disabled="isDefaultProject"
|
:disabled="isDefaultProject"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTrash />
|
||||||
|
</template>
|
||||||
{{ $t('menu.delete') }}
|
{{ $t('menu.delete') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -140,6 +163,7 @@ import {useConfigStore} from '@/stores/config'
|
||||||
import {useProjectStore} from '@/stores/projects'
|
import {useProjectStore} from '@/stores/projects'
|
||||||
import {useAuthStore} from '@/stores/auth'
|
import {useAuthStore} from '@/stores/auth'
|
||||||
import {PERMISSIONS} from '@/constants/permissions'
|
import {PERMISSIONS} from '@/constants/permissions'
|
||||||
|
import {PhDotsThree, PhPen, PhEye, PhTrash, PhArchive, PhImage, PhShareNetwork, PhClipboard, PhLightning, PhStack} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
project: IProject
|
project: IProject
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<XButton
|
<XButton
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="filter"
|
|
||||||
:class="{'has-filters': hasFilters}"
|
:class="{'has-filters': hasFilters}"
|
||||||
@click="() => modalOpen = true"
|
@click="() => modalOpen = true"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhFunnel />
|
||||||
|
</template>
|
||||||
{{ $t('filters.title') }}
|
{{ $t('filters.title') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<Modal
|
<Modal
|
||||||
|
|
@ -32,6 +34,7 @@
|
||||||
import {computed, ref, watch, nextTick} from 'vue'
|
import {computed, ref, watch, nextTick} from 'vue'
|
||||||
|
|
||||||
import Filters from '@/components/project/partials/Filters.vue'
|
import Filters from '@/components/project/partials/Filters.vue'
|
||||||
|
import {PhFunnel} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import {type TaskFilterParams} from '@/services/taskCollection'
|
import {type TaskFilterParams} from '@/services/taskCollection'
|
||||||
import {type IProjectView} from '@/modelTypes/IProjectView'
|
import {type IProjectView} from '@/modelTypes/IProjectView'
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
v-if="project.id < -1"
|
v-if="project.id < -1"
|
||||||
class="saved-filter-icon icon"
|
class="saved-filter-icon icon"
|
||||||
>
|
>
|
||||||
<Icon icon="filter" />
|
<PhFunnel />
|
||||||
</span>
|
</span>
|
||||||
{{ getProjectTitle(project) }}
|
{{ getProjectTitle(project) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
:class="{'is-favorite': project.isFavorite}"
|
:class="{'is-favorite': project.isFavorite}"
|
||||||
@click.prevent.stop="projectStore.toggleProjectFavorite(project)"
|
@click.prevent.stop="projectStore.toggleProjectFavorite(project)"
|
||||||
>
|
>
|
||||||
<Icon :icon="project.isFavorite ? 'star' : ['far', 'star']" />
|
<PhStar :weight="project.isFavorite ? 'fill' : 'regular'" />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -57,6 +57,7 @@ import {computed} from 'vue'
|
||||||
import type {IProject} from '@/modelTypes/IProject'
|
import type {IProject} from '@/modelTypes/IProject'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
import {PhFunnel, PhStar} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import {useProjectBackground} from '@/composables/useProjectBackground'
|
import {useProjectBackground} from '@/composables/useProjectBackground'
|
||||||
import {useProjectStore} from '@/stores/projects'
|
import {useProjectStore} from '@/stores/projects'
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
class="icon is-small has-text-success mie-2"
|
class="icon is-small has-text-success mie-2"
|
||||||
@click.stop="() => collapseBucket(bucket)"
|
@click.stop="() => collapseBucket(bucket)"
|
||||||
>
|
>
|
||||||
<Icon icon="check-double" />
|
<PhChecks />
|
||||||
</span>
|
</span>
|
||||||
<h2
|
<h2
|
||||||
class="title input"
|
class="title input"
|
||||||
|
|
@ -73,9 +73,13 @@
|
||||||
<Dropdown
|
<Dropdown
|
||||||
v-if="canWrite && !collapsedBuckets[bucket.id]"
|
v-if="canWrite && !collapsedBuckets[bucket.id]"
|
||||||
class="is-right options"
|
class="is-right options"
|
||||||
trigger-icon="ellipsis-v"
|
|
||||||
@close="() => showSetLimitInput = false"
|
@close="() => showSetLimitInput = false"
|
||||||
>
|
>
|
||||||
|
<template #trigger="tp">
|
||||||
|
<BaseButton @click="tp.toggleOpen">
|
||||||
|
<PhDotsThreeVertical class="icon" />
|
||||||
|
</BaseButton>
|
||||||
|
</template>
|
||||||
<div
|
<div
|
||||||
v-if="showSetLimitInput"
|
v-if="showSetLimitInput"
|
||||||
class="field has-addons"
|
class="field has-addons"
|
||||||
|
|
@ -97,10 +101,13 @@
|
||||||
<XButton
|
<XButton
|
||||||
v-cy="'setBucketLimit'"
|
v-cy="'setBucketLimit'"
|
||||||
:disabled="bucket.limit < 0"
|
:disabled="bucket.limit < 0"
|
||||||
:icon="['far', 'save']"
|
|
||||||
:shadow="false"
|
:shadow="false"
|
||||||
@click="() => {setBucketLimit(bucket.id, true); showSetLimitInput = false}"
|
@click="() => {setBucketLimit(bucket.id, true); showSetLimitInput = false}"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhFloppyDisk />
|
||||||
|
</template>
|
||||||
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
|
|
@ -114,23 +121,29 @@
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
v-tooltip="$t('project.kanban.doneBucketHintExtended')"
|
v-tooltip="$t('project.kanban.doneBucketHintExtended')"
|
||||||
:icon-class="{'has-text-success': bucket.id === view?.doneBucketId}"
|
:icon-class="{'has-text-success': bucket.id === view?.doneBucketId}"
|
||||||
icon="check-double"
|
|
||||||
@click.stop="toggleDoneBucket(bucket)"
|
@click.stop="toggleDoneBucket(bucket)"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhChecks />
|
||||||
|
</template>
|
||||||
{{ $t('project.kanban.doneBucket') }}
|
{{ $t('project.kanban.doneBucket') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
v-tooltip="$t('project.kanban.defaultBucketHint')"
|
v-tooltip="$t('project.kanban.defaultBucketHint')"
|
||||||
:icon-class="{'has-text-primary': bucket.id === view?.defaultBucketId}"
|
:icon-class="{'has-text-primary': bucket.id === view?.defaultBucketId}"
|
||||||
icon="th"
|
|
||||||
@click.stop="toggleDefaultBucket(bucket)"
|
@click.stop="toggleDefaultBucket(bucket)"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhSquaresFour />
|
||||||
|
</template>
|
||||||
{{ $t('project.kanban.defaultBucket') }}
|
{{ $t('project.kanban.defaultBucket') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
icon="angles-up"
|
|
||||||
@click.stop="() => collapseBucket(bucket)"
|
@click.stop="() => collapseBucket(bucket)"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhCaretDoubleUp />
|
||||||
|
</template>
|
||||||
{{ $t('project.kanban.collapse') }}
|
{{ $t('project.kanban.collapse') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
|
|
@ -138,9 +151,11 @@
|
||||||
class="has-text-danger"
|
class="has-text-danger"
|
||||||
:class="{'is-disabled': buckets.length <= 1}"
|
:class="{'is-disabled': buckets.length <= 1}"
|
||||||
icon-class="has-text-danger"
|
icon-class="has-text-danger"
|
||||||
icon="trash-alt"
|
|
||||||
@click.stop="() => deleteBucketModal(bucket.id)"
|
@click.stop="() => deleteBucketModal(bucket.id)"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTrash />
|
||||||
|
</template>
|
||||||
{{ $t('misc.delete') }}
|
{{ $t('misc.delete') }}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
|
@ -197,11 +212,13 @@
|
||||||
v-tooltip="bucket.limit > 0 && bucket.count >= bucket.limit ? $t('project.kanban.bucketLimitReached') : ''"
|
v-tooltip="bucket.limit > 0 && bucket.count >= bucket.limit ? $t('project.kanban.bucketLimitReached') : ''"
|
||||||
class="is-fullwidth has-text-centered"
|
class="is-fullwidth has-text-centered"
|
||||||
:shadow="false"
|
:shadow="false"
|
||||||
icon="plus"
|
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
:disabled="bucket.limit > 0 && bucket.count >= bucket.limit"
|
:disabled="bucket.limit > 0 && bucket.count >= bucket.limit"
|
||||||
@click="toggleShowNewTaskInput(bucket.id)"
|
@click="toggleShowNewTaskInput(bucket.id)"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{
|
{{
|
||||||
bucket.tasks.length === 0 ? $t('project.kanban.addTask') : $t('project.kanban.addAnotherTask')
|
bucket.tasks.length === 0 ? $t('project.kanban.addTask') : $t('project.kanban.addAnotherTask')
|
||||||
}}
|
}}
|
||||||
|
|
@ -250,9 +267,11 @@
|
||||||
:shadow="false"
|
:shadow="false"
|
||||||
class="is-transparent is-fullwidth has-text-centered"
|
class="is-transparent is-fullwidth has-text-centered"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="plus"
|
|
||||||
@click="() => showNewBucketInput = true"
|
@click="() => showNewBucketInput = true"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('project.kanban.addBucket') }}
|
{{ $t('project.kanban.addBucket') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -300,8 +319,10 @@ import {useAuthStore} from '@/stores/auth'
|
||||||
import ProjectWrapper from '@/components/project/ProjectWrapper.vue'
|
import ProjectWrapper from '@/components/project/ProjectWrapper.vue'
|
||||||
import FilterPopup from '@/components/project/partials/FilterPopup.vue'
|
import FilterPopup from '@/components/project/partials/FilterPopup.vue'
|
||||||
import KanbanCard from '@/components/tasks/partials/KanbanCard.vue'
|
import KanbanCard from '@/components/tasks/partials/KanbanCard.vue'
|
||||||
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import Dropdown from '@/components/misc/Dropdown.vue'
|
import Dropdown from '@/components/misc/Dropdown.vue'
|
||||||
import DropdownItem from '@/components/misc/DropdownItem.vue'
|
import DropdownItem from '@/components/misc/DropdownItem.vue'
|
||||||
|
import {PhChecks, PhDotsThreeVertical, PhFloppyDisk, PhSquaresFour, PhCaretDoubleUp, PhTrash, PhPlus} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type CollapsedBuckets,
|
type CollapsedBuckets,
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,13 @@
|
||||||
<Popup>
|
<Popup>
|
||||||
<template #trigger="{toggle}">
|
<template #trigger="{toggle}">
|
||||||
<XButton
|
<XButton
|
||||||
icon="th"
|
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
class="mie-2"
|
class="mie-2"
|
||||||
@click.prevent.stop="toggle()"
|
@click.prevent.stop="toggle()"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhSquaresFour />
|
||||||
|
</template>
|
||||||
{{ $t('project.table.columns') }}
|
{{ $t('project.table.columns') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -316,6 +318,7 @@ import Sort from '@/components/tasks/partials/Sort.vue'
|
||||||
import FilterPopup from '@/components/project/partials/FilterPopup.vue'
|
import FilterPopup from '@/components/project/partials/FilterPopup.vue'
|
||||||
import Pagination from '@/components/misc/Pagination.vue'
|
import Pagination from '@/components/misc/Pagination.vue'
|
||||||
import Popup from '@/components/misc/Popup.vue'
|
import Popup from '@/components/misc/Popup.vue'
|
||||||
|
import {PhSquaresFour} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import type {SortBy} from '@/composables/useTaskList'
|
import type {SortBy} from '@/composables/useTaskList'
|
||||||
import {useTaskList} from '@/composables/useTaskList'
|
import {useTaskList} from '@/composables/useTaskList'
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import XButton from '@/components/input/Button.vue'
|
||||||
import FilterInputDocs from '@/components/input/filter/FilterInputDocs.vue'
|
import FilterInputDocs from '@/components/input/filter/FilterInputDocs.vue'
|
||||||
import FilterInput from '@/components/input/filter/FilterInput.vue'
|
import FilterInput from '@/components/input/filter/FilterInput.vue'
|
||||||
import FormField from '@/components/input/FormField.vue'
|
import FormField from '@/components/input/FormField.vue'
|
||||||
|
import {PhTrash, PhPlus} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
modelValue: IProjectView,
|
modelValue: IProjectView,
|
||||||
|
|
@ -225,7 +226,7 @@ function handleBubbleSave() {
|
||||||
class="is-danger"
|
class="is-danger"
|
||||||
@click.prevent="() => view.bucketConfiguration.splice(index, 1)"
|
@click.prevent="() => view.bucketConfiguration.splice(index, 1)"
|
||||||
>
|
>
|
||||||
<Icon icon="trash-alt" />
|
<PhTrash />
|
||||||
</button>
|
</button>
|
||||||
<div class="filter-bucket-form">
|
<div class="filter-bucket-form">
|
||||||
<FormField
|
<FormField
|
||||||
|
|
@ -250,9 +251,11 @@ function handleBubbleSave() {
|
||||||
<div class="is-flex is-justify-content-end">
|
<div class="is-flex is-justify-content-end">
|
||||||
<XButton
|
<XButton
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="plus"
|
|
||||||
@click="() => view.bucketConfiguration.push({title: '', filter: {filter: ''}})"
|
@click="() => view.bucketConfiguration.push({title: '', filter: {filter: ''}})"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('project.kanban.addBucket') }}
|
{{ $t('project.kanban.addBucket') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
class="close"
|
class="close"
|
||||||
@click="closeQuickActions"
|
@click="closeQuickActions"
|
||||||
>
|
>
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -84,7 +84,7 @@
|
||||||
v-if="i.id < -1"
|
v-if="i.id < -1"
|
||||||
class="saved-filter-icon icon"
|
class="saved-filter-icon icon"
|
||||||
>
|
>
|
||||||
<Icon icon="filter" />
|
<PhFunnel />
|
||||||
</span>
|
</span>
|
||||||
{{ i.title }}
|
{{ i.title }}
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -98,6 +98,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {type ComponentPublicInstance, computed, ref, shallowReactive, watchEffect} from 'vue'
|
import {type ComponentPublicInstance, computed, ref, shallowReactive, watchEffect} from 'vue'
|
||||||
|
import {PhX, PhFunnel} from '@phosphor-icons/vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import {useRouter} from 'vue-router'
|
import {useRouter} from 'vue-router'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,12 @@
|
||||||
<div class="sharables-project">
|
<div class="sharables-project">
|
||||||
<XButton
|
<XButton
|
||||||
v-if="!showNewForm"
|
v-if="!showNewForm"
|
||||||
icon="plus"
|
|
||||||
class="mbe-4"
|
class="mbe-4"
|
||||||
@click="showNewForm = true"
|
@click="showNewForm = true"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('project.share.links.create') }}
|
{{ $t('project.share.links.create') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
|
|
||||||
|
|
@ -60,9 +62,11 @@
|
||||||
:placeholder="$t('user.auth.passwordPlaceholder')"
|
:placeholder="$t('user.auth.passwordPlaceholder')"
|
||||||
/>
|
/>
|
||||||
<XButton
|
<XButton
|
||||||
icon="plus"
|
|
||||||
@click="add(projectId)"
|
@click="add(projectId)"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('project.share.share') }}
|
{{ $t('project.share.share') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -105,19 +109,19 @@
|
||||||
<p class="mbe-2">
|
<p class="mbe-2">
|
||||||
<template v-if="s.permission === PERMISSIONS.ADMIN">
|
<template v-if="s.permission === PERMISSIONS.ADMIN">
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="lock" />
|
<PhLock />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('project.share.permission.admin') }}
|
{{ $t('project.share.permission.admin') }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="s.permission === PERMISSIONS.READ_WRITE">
|
<template v-else-if="s.permission === PERMISSIONS.READ_WRITE">
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="pen" />
|
<PhPen />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('project.share.permission.readWrite') }}
|
{{ $t('project.share.permission.readWrite') }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="users" />
|
<PhUsers />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('project.share.permission.read') }}
|
{{ $t('project.share.permission.read') }}
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -135,7 +139,7 @@
|
||||||
@click="copy(shareLinks[s.id])"
|
@click="copy(shareLinks[s.id])"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon icon="paste" />
|
<PhClipboard />
|
||||||
</span>
|
</span>
|
||||||
</XButton>
|
</XButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -157,14 +161,17 @@
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
<XButton
|
<XButton
|
||||||
danger
|
danger
|
||||||
icon="trash-alt"
|
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
linkIdToDelete = s.id
|
linkIdToDelete = s.id
|
||||||
showDeleteModal = true
|
showDeleteModal = true
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTrash />
|
||||||
|
</template>
|
||||||
|
</XButton>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -189,6 +196,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, watch, computed, shallowReactive} from 'vue'
|
import {ref, watch, computed, shallowReactive} from 'vue'
|
||||||
|
import {PhLock, PhPen, PhUsers, PhClipboard, PhPlus, PhTrash} from '@phosphor-icons/vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import {PERMISSIONS} from '@/constants/permissions'
|
import {PERMISSIONS} from '@/constants/permissions'
|
||||||
|
|
|
||||||
|
|
@ -73,19 +73,19 @@
|
||||||
<td class="type">
|
<td class="type">
|
||||||
<template v-if="s.permission === PERMISSIONS.ADMIN">
|
<template v-if="s.permission === PERMISSIONS.ADMIN">
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="lock" />
|
<PhLock />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('project.share.permission.admin') }}
|
{{ $t('project.share.permission.admin') }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="s.permission === PERMISSIONS.READ_WRITE">
|
<template v-else-if="s.permission === PERMISSIONS.READ_WRITE">
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="pen" />
|
<PhPen />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('project.share.permission.readWrite') }}
|
{{ $t('project.share.permission.readWrite') }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="users" />
|
<PhUsers />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('project.share.permission.read') }}
|
{{ $t('project.share.permission.read') }}
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -122,14 +122,17 @@
|
||||||
</div>
|
</div>
|
||||||
<XButton
|
<XButton
|
||||||
danger
|
danger
|
||||||
icon="trash-alt"
|
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
sharable = s
|
sharable = s
|
||||||
showDeleteModal = true
|
showDeleteModal = true
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTrash />
|
||||||
|
</template>
|
||||||
|
</XButton>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -159,6 +162,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, reactive, computed, shallowReactive, type Ref} from 'vue'
|
import {ref, reactive, computed, shallowReactive, type Ref} from 'vue'
|
||||||
|
import {PhLock, PhPen, PhUsers, PhTrash} from '@phosphor-icons/vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import UserProjectService from '@/services/userProject'
|
import UserProjectService from '@/services/userProject'
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
{{ $t('project.list.addPlaceholder') }}
|
{{ $t('project.list.addPlaceholder') }}
|
||||||
</label>
|
</label>
|
||||||
<span class="icon is-small task-icon">
|
<span class="icon is-small task-icon">
|
||||||
<Icon icon="tasks" />
|
<PhListChecks />
|
||||||
</span>
|
</span>
|
||||||
<textarea
|
<textarea
|
||||||
:id="textareaId"
|
:id="textareaId"
|
||||||
|
|
@ -34,11 +34,13 @@
|
||||||
<XButton
|
<XButton
|
||||||
class="add-task-button"
|
class="add-task-button"
|
||||||
:disabled="newTaskTitle === '' || loading || undefined"
|
:disabled="newTaskTitle === '' || loading || undefined"
|
||||||
icon="plus"
|
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:aria-label="$t('project.list.add')"
|
:aria-label="$t('project.list.add')"
|
||||||
@click="addTask()"
|
@click="addTask()"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
<span class="button-text">
|
<span class="button-text">
|
||||||
{{ $t('project.list.add') }}
|
{{ $t('project.list.add') }}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -78,6 +80,7 @@ import {useTaskStore} from '@/stores/tasks'
|
||||||
import {useAutoHeightTextarea} from '@/composables/useAutoHeightTextarea'
|
import {useAutoHeightTextarea} from '@/composables/useAutoHeightTextarea'
|
||||||
import TaskService from '@/services/task'
|
import TaskService from '@/services/task'
|
||||||
import TaskModel from '@/models/task'
|
import TaskModel from '@/models/task'
|
||||||
|
import {PhListChecks, PhPlus} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
defaultPosition?: number,
|
defaultPosition?: number,
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,11 @@
|
||||||
</CustomTransition>
|
</CustomTransition>
|
||||||
<XButton
|
<XButton
|
||||||
:shadow="false"
|
:shadow="false"
|
||||||
icon="plus"
|
|
||||||
@click="showCreateTaskOrCreate"
|
@click="showCreateTaskOrCreate"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('task.new') }}
|
{{ $t('task.new') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -29,6 +31,7 @@ import {nextTick, ref} from 'vue'
|
||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
|
|
||||||
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||||
|
import {PhPlus} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'createTask', title: string): Promise<ITask>
|
(e: 'createTask', title: string): Promise<ITask>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type {IUser} from '@/modelTypes/IUser'
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
|
import {PhX} from '@phosphor-icons/vue'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import User from '@/components/misc/User.vue'
|
import User from '@/components/misc/User.vue'
|
||||||
|
|
||||||
|
|
@ -44,7 +45,7 @@ defineEmits<{
|
||||||
class="remove-assignee"
|
class="remove-assignee"
|
||||||
@click="$emit('remove', user)"
|
@click="$emit('remove', user)"
|
||||||
>
|
>
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="attachments">
|
<div class="attachments">
|
||||||
<h3>
|
<h3>
|
||||||
<span class="icon is-grey">
|
<span class="icon is-grey">
|
||||||
<Icon icon="paperclip" />
|
<PhPaperclip />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('task.attachment.title') }}
|
{{ $t('task.attachment.title') }}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
@ -77,14 +77,14 @@
|
||||||
class="attachment-info-meta-button"
|
class="attachment-info-meta-button"
|
||||||
@click.prevent.stop="downloadAttachment(a)"
|
@click.prevent.stop="downloadAttachment(a)"
|
||||||
>
|
>
|
||||||
<Icon icon="download" />
|
<PhDownload />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-tooltip="$t('task.attachment.copyUrlTooltip')"
|
v-tooltip="$t('task.attachment.copyUrlTooltip')"
|
||||||
class="attachment-info-meta-button"
|
class="attachment-info-meta-button"
|
||||||
@click.stop="copyUrl(a)"
|
@click.stop="copyUrl(a)"
|
||||||
>
|
>
|
||||||
<Icon icon="copy" />
|
<PhCopy />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-if="editEnabled"
|
v-if="editEnabled"
|
||||||
|
|
@ -92,7 +92,7 @@
|
||||||
class="attachment-info-meta-button"
|
class="attachment-info-meta-button"
|
||||||
@click.prevent.stop="setAttachmentToDelete(a)"
|
@click.prevent.stop="setAttachmentToDelete(a)"
|
||||||
>
|
>
|
||||||
<Icon icon="trash-alt" />
|
<PhTrash />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-if="editEnabled && canPreview(a)"
|
v-if="editEnabled && canPreview(a)"
|
||||||
|
|
@ -102,7 +102,8 @@
|
||||||
class="attachment-info-meta-button"
|
class="attachment-info-meta-button"
|
||||||
@click.prevent.stop="setCoverImage(task.coverImageAttachmentId === a.id ? null : a)"
|
@click.prevent.stop="setCoverImage(task.coverImageAttachmentId === a.id ? null : a)"
|
||||||
>
|
>
|
||||||
<Icon :icon="task.coverImageAttachmentId === a.id ? 'eye-slash' : 'eye'" />
|
<PhEyeSlash v-if="task.coverImageAttachmentId === a.id" />
|
||||||
|
<PhEye v-else />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -114,11 +115,13 @@
|
||||||
v-if="editEnabled"
|
v-if="editEnabled"
|
||||||
:disabled="loading"
|
:disabled="loading"
|
||||||
class="mbe-4"
|
class="mbe-4"
|
||||||
icon="cloud-upload-alt"
|
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
:shadow="false"
|
:shadow="false"
|
||||||
@click="filesRef?.click()"
|
@click="filesRef?.click()"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhCloudArrowUp />
|
||||||
|
</template>
|
||||||
{{ $t('task.attachment.upload') }}
|
{{ $t('task.attachment.upload') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
|
|
||||||
|
|
@ -131,7 +134,7 @@
|
||||||
>
|
>
|
||||||
<div class="drop-hint">
|
<div class="drop-hint">
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<Icon icon="cloud-upload-alt" />
|
<PhCloudArrowUp />
|
||||||
</div>
|
</div>
|
||||||
<div class="hint">
|
<div class="hint">
|
||||||
{{ $t('task.attachment.drop') }}
|
{{ $t('task.attachment.drop') }}
|
||||||
|
|
@ -174,6 +177,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, shallowReactive, computed, watch} from 'vue'
|
import {ref, shallowReactive, computed, watch} from 'vue'
|
||||||
import {useDropZone} from '@vueuse/core'
|
import {useDropZone} from '@vueuse/core'
|
||||||
|
import {PhPaperclip, PhDownload, PhCopy, PhTrash, PhEye, PhEyeSlash, PhCloudArrowUp} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import User from '@/components/misc/User.vue'
|
import User from '@/components/misc/User.vue'
|
||||||
import ProgressBar from '@/components/misc/ProgressBar.vue'
|
import ProgressBar from '@/components/misc/ProgressBar.vue'
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
class="comment-count"
|
class="comment-count"
|
||||||
:class="{'is-unread': task.isUnread}"
|
:class="{'is-unread': task.isUnread}"
|
||||||
>
|
>
|
||||||
<Icon :icon="['far', 'comments']" />
|
<PhChats />
|
||||||
<span class="comment-count-badge">{{ task.commentCount }}</span>
|
<span class="comment-count-badge">{{ task.commentCount }}</span>
|
||||||
<span
|
<span
|
||||||
v-if="task.isUnread"
|
v-if="task.isUnread"
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed} from 'vue'
|
import {computed} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
import {PhChats} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
<span class="icon is-grey">
|
<span class="icon is-grey">
|
||||||
<Icon :icon="['far', 'comments']" />
|
<PhChats />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('task.comment.title') }}
|
{{ $t('task.comment.title') }}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -20,7 +20,8 @@
|
||||||
class="comment-sort-button"
|
class="comment-sort-button"
|
||||||
@click="toggleSortOrder"
|
@click="toggleSortOrder"
|
||||||
>
|
>
|
||||||
<Icon :icon="commentSortOrder === 'asc' ? 'arrow-down-short-wide' : 'arrow-up-short-wide'" />
|
<PhSortAscending v-if="commentSortOrder === 'asc'" />
|
||||||
|
<PhSortDescending v-else />
|
||||||
{{ commentSortOrder === 'asc' ? $t('task.comment.sortOldestFirst') : $t('task.comment.sortNewestFirst') }}
|
{{ commentSortOrder === 'asc' ? $t('task.comment.sortOldestFirst') : $t('task.comment.sortNewestFirst') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
@ -80,7 +81,7 @@
|
||||||
@click.prevent.stop="copy(getCommentUrl(`${c.id}`))"
|
@click.prevent.stop="copy(getCommentUrl(`${c.id}`))"
|
||||||
>
|
>
|
||||||
<span class="is-sr-only">{{ $t('task.comment.permalink') }}</span>
|
<span class="is-sr-only">{{ $t('task.comment.permalink') }}</span>
|
||||||
<Icon icon="link" />
|
<PhLink />
|
||||||
</a>
|
</a>
|
||||||
<CustomTransition name="fade">
|
<CustomTransition name="fade">
|
||||||
<span
|
<span
|
||||||
|
|
@ -224,6 +225,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, reactive, computed, shallowReactive, watch} from 'vue'
|
import {ref, reactive, computed, shallowReactive, watch} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
import {PhChats, PhLink, PhSortAscending, PhSortDescending} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div>
|
<div>
|
||||||
<h3>
|
<h3>
|
||||||
<span class="icon is-grey">
|
<span class="icon is-grey">
|
||||||
<Icon icon="align-left" />
|
<PhTextAlignLeft />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('task.attributes.description') }}
|
{{ $t('task.attributes.description') }}
|
||||||
<CustomTransition name="fade">
|
<CustomTransition name="fade">
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
v-else-if="!loading && saved"
|
v-else-if="!loading && saved"
|
||||||
class="is-small has-text-success"
|
class="is-small has-text-success"
|
||||||
>
|
>
|
||||||
<Icon icon="check" />
|
<PhCheck />
|
||||||
{{ $t('misc.saved') }}
|
{{ $t('misc.saved') }}
|
||||||
</span>
|
</span>
|
||||||
</CustomTransition>
|
</CustomTransition>
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, computed, watchEffect, onBeforeUnmount} from 'vue'
|
import {ref, computed, watchEffect, onBeforeUnmount} from 'vue'
|
||||||
import {onBeforeRouteLeave} from 'vue-router'
|
import {onBeforeRouteLeave} from 'vue-router'
|
||||||
|
import {PhTextAlignLeft, PhCheck} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||||
import Editor from '@/components/input/AsyncEditor'
|
import Editor from '@/components/input/AsyncEditor'
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,13 @@
|
||||||
v-else
|
v-else
|
||||||
class="icon-wrapper"
|
class="icon-wrapper"
|
||||||
>
|
>
|
||||||
<Icon
|
<PhFile size="6em" />
|
||||||
size="6x"
|
|
||||||
icon="file"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, shallowReactive, watchEffect} from 'vue'
|
import {ref, shallowReactive, watchEffect} from 'vue'
|
||||||
|
import {PhFile} from '@phosphor-icons/vue'
|
||||||
import AttachmentService, {PREVIEW_SIZE} from '@/services/attachment'
|
import AttachmentService, {PREVIEW_SIZE} from '@/services/attachment'
|
||||||
import type {IAttachment} from '@/modelTypes/IAttachment'
|
import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||||
import {canPreview} from '@/models/attachment'
|
import {canPreview} from '@/models/attachment'
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
class="close"
|
class="close"
|
||||||
@click="$emit('close')"
|
@click="$emit('close')"
|
||||||
>
|
>
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
<h1
|
<h1
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
class="close"
|
class="close"
|
||||||
@click="$emit('close')"
|
@click="$emit('close')"
|
||||||
>
|
>
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<CustomTransition name="fade">
|
<CustomTransition name="fade">
|
||||||
<span
|
<span
|
||||||
|
|
@ -54,10 +54,7 @@
|
||||||
v-else-if="!loading && showSavedMessage"
|
v-else-if="!loading && showSavedMessage"
|
||||||
class="has-text-success is-inline-flex is-align-content-center"
|
class="has-text-success is-inline-flex is-align-content-center"
|
||||||
>
|
>
|
||||||
<Icon
|
<PhCheck class="mie-2" />
|
||||||
icon="check"
|
|
||||||
class="mie-2"
|
|
||||||
/>
|
|
||||||
{{ $t('misc.saved') }}
|
{{ $t('misc.saved') }}
|
||||||
</span>
|
</span>
|
||||||
</CustomTransition>
|
</CustomTransition>
|
||||||
|
|
@ -67,6 +64,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, computed, onMounted, onBeforeUnmount, watch} from 'vue'
|
import {ref, computed, onMounted, onBeforeUnmount, watch} from 'vue'
|
||||||
import {useRouter} from 'vue-router'
|
import {useRouter} from 'vue-router'
|
||||||
|
import {PhX, PhCheck} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
class="due-date"
|
class="due-date"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon :icon="['far', 'calendar-alt']" />
|
<PhCalendarBlank />
|
||||||
</span>
|
</span>
|
||||||
<time :datetime="formatISO(task.dueDate)">
|
<time :datetime="formatISO(task.dueDate)">
|
||||||
{{ formatDisplayDate(task.dueDate) }}
|
{{ formatDisplayDate(task.dueDate) }}
|
||||||
|
|
@ -81,19 +81,19 @@
|
||||||
v-if="task.attachments.length > 0"
|
v-if="task.attachments.length > 0"
|
||||||
class="icon"
|
class="icon"
|
||||||
>
|
>
|
||||||
<Icon icon="paperclip" />
|
<PhPaperclip />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="!isEditorContentEmpty(task.description)"
|
v-if="!isEditorContentEmpty(task.description)"
|
||||||
class="icon"
|
class="icon"
|
||||||
>
|
>
|
||||||
<Icon icon="align-left" />
|
<PhTextAlignLeft />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="task.repeatAfter.amount > 0"
|
v-if="task.repeatAfter.amount > 0"
|
||||||
class="icon"
|
class="icon"
|
||||||
>
|
>
|
||||||
<Icon icon="history" />
|
<PhClockCounterClockwise />
|
||||||
</span>
|
</span>
|
||||||
<CommentCount
|
<CommentCount
|
||||||
:task="task"
|
:task="task"
|
||||||
|
|
@ -116,6 +116,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {computed, ref, watch} from 'vue'
|
import {computed, ref, watch} from 'vue'
|
||||||
import {useRouter} from 'vue-router'
|
import {useRouter} from 'vue-router'
|
||||||
|
import {PhCalendarBlank, PhPaperclip, PhTextAlignLeft, PhClockCounterClockwise} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import {useGlobalNow} from '@/composables/useGlobalNow'
|
import {useGlobalNow} from '@/composables/useGlobalNow'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,11 @@
|
||||||
class="priority-label"
|
class="priority-label"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon
|
<PhWarningCircle
|
||||||
v-if="priority >= priorities.HIGH"
|
v-if="priority >= priorities.HIGH"
|
||||||
icon="exclamation-circle"
|
|
||||||
/>
|
/>
|
||||||
<Icon
|
<PhWarning
|
||||||
v-else
|
v-else
|
||||||
icon="exclamation"
|
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
|
|
@ -31,6 +29,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed} from 'vue'
|
import {computed} from 'vue'
|
||||||
|
import {PhWarningCircle, PhWarning} from '@phosphor-icons/vue'
|
||||||
import {PRIORITIES as priorities} from '@/constants/priorities'
|
import {PRIORITIES as priorities} from '@/constants/priorities'
|
||||||
import {useAuthStore} from '@/stores/auth'
|
import {useAuthStore} from '@/stores/auth'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
:class="{'is-highlighted': highlightHintIcon}"
|
:class="{'is-highlighted': highlightHintIcon}"
|
||||||
@click="() => visible = true"
|
@click="() => visible = true"
|
||||||
>
|
>
|
||||||
<Icon :icon="['far', 'circle-question']" />
|
<PhQuestion />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<Modal
|
<Modal
|
||||||
:enabled="visible"
|
:enabled="visible"
|
||||||
|
|
@ -101,6 +101,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, computed} from 'vue'
|
import {ref, computed} from 'vue'
|
||||||
|
import {PhQuestion} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,13 @@
|
||||||
class="is-pulled-right add-task-relation-button d-print-none"
|
class="is-pulled-right add-task-relation-button d-print-none"
|
||||||
:class="{'is-active': showNewRelationForm}"
|
:class="{'is-active': showNewRelationForm}"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="plus"
|
|
||||||
:shadow="false"
|
:shadow="false"
|
||||||
@click="showNewRelationForm = !showNewRelationForm"
|
@click="showNewRelationForm = !showNewRelationForm"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
|
</XButton>
|
||||||
<transition-group name="fade">
|
<transition-group name="fade">
|
||||||
<template v-if="editEnabled && showCreate">
|
<template v-if="editEnabled && showCreate">
|
||||||
<label
|
<label
|
||||||
|
|
@ -151,7 +154,7 @@
|
||||||
otherTaskId: task.id
|
otherTaskId: task.id
|
||||||
})"
|
})"
|
||||||
>
|
>
|
||||||
<Icon icon="trash-alt" />
|
<PhTrash />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -186,6 +189,7 @@
|
||||||
import {ref, reactive, shallowReactive, watch, computed} from 'vue'
|
import {ref, reactive, shallowReactive, watch, computed} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import {useRoute} from 'vue-router'
|
import {useRoute} from 'vue-router'
|
||||||
|
import {PhPlus, PhTrash} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import TaskService from '@/services/task'
|
import TaskService from '@/services/task'
|
||||||
import TaskModel from '@/models/task'
|
import TaskModel from '@/models/task'
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
class="remove"
|
class="remove"
|
||||||
@click="removeReminderByIndex(index)"
|
@click="removeReminderByIndex(index)"
|
||||||
>
|
>
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, watch, computed} from 'vue'
|
import {ref, watch, computed} from 'vue'
|
||||||
|
import {PhX} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import type {ITaskReminder} from '@/modelTypes/ITaskReminder'
|
import type {ITaskReminder} from '@/modelTypes/ITaskReminder'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,19 +111,19 @@
|
||||||
v-if="task.attachments.length > 0"
|
v-if="task.attachments.length > 0"
|
||||||
class="project-task-icon"
|
class="project-task-icon"
|
||||||
>
|
>
|
||||||
<Icon icon="paperclip" />
|
<PhPaperclip />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="!isEditorContentEmpty(task.description)"
|
v-if="!isEditorContentEmpty(task.description)"
|
||||||
class="project-task-icon is-mirrored-rtl"
|
class="project-task-icon is-mirrored-rtl"
|
||||||
>
|
>
|
||||||
<Icon icon="align-left" />
|
<PhTextAlignLeft />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="isRepeating"
|
v-if="isRepeating"
|
||||||
class="project-task-icon"
|
class="project-task-icon"
|
||||||
>
|
>
|
||||||
<Icon icon="history" />
|
<PhClockCounterClockwise />
|
||||||
</span>
|
</span>
|
||||||
<CommentCount
|
<CommentCount
|
||||||
:task="task"
|
:task="task"
|
||||||
|
|
@ -162,14 +162,7 @@
|
||||||
@click.stop="toggleFavorite"
|
@click.stop="toggleFavorite"
|
||||||
>
|
>
|
||||||
<span class="is-sr-only">{{ task.isFavorite ? $t('task.detail.actions.unfavorite') : $t('task.detail.actions.favorite') }}</span>
|
<span class="is-sr-only">{{ task.isFavorite ? $t('task.detail.actions.unfavorite') : $t('task.detail.actions.favorite') }}</span>
|
||||||
<Icon
|
<PhStar :weight="task.isFavorite ? 'fill' : 'regular'" />
|
||||||
v-if="task.isFavorite"
|
|
||||||
icon="star"
|
|
||||||
/>
|
|
||||||
<Icon
|
|
||||||
v-else
|
|
||||||
:icon="['far', 'star']"
|
|
||||||
/>
|
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -193,6 +186,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, watch, shallowReactive, onMounted, computed} from 'vue'
|
import {ref, watch, shallowReactive, onMounted, computed} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
import {PhPaperclip, PhTextAlignLeft, PhClockCounterClockwise, PhStar} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import TaskModel, {getHexColor} from '@/models/task'
|
import TaskModel, {getHexColor} from '@/models/task'
|
||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
|
|
|
||||||
|
|
@ -67,19 +67,19 @@
|
||||||
v-if="task.attachments.length > 0"
|
v-if="task.attachments.length > 0"
|
||||||
class="project-task-icon"
|
class="project-task-icon"
|
||||||
>
|
>
|
||||||
<Icon icon="paperclip" />
|
<PhPaperclip />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="task.description"
|
v-if="task.description"
|
||||||
class="project-task-icon"
|
class="project-task-icon"
|
||||||
>
|
>
|
||||||
<Icon icon="align-left" />
|
<PhTextAlignLeft />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="task.repeatAfter.amount > 0"
|
v-if="task.repeatAfter.amount > 0"
|
||||||
class="project-task-icon"
|
class="project-task-icon"
|
||||||
>
|
>
|
||||||
<Icon icon="history" />
|
<PhClockCounterClockwise />
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
@ -98,6 +98,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed} from 'vue'
|
import {computed} from 'vue'
|
||||||
|
import {PhPaperclip, PhTextAlignLeft, PhClockCounterClockwise} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import {getHexColor} from '@/models/task'
|
import {getHexColor} from '@/models/task'
|
||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<BaseButton>
|
<BaseButton>
|
||||||
<Icon
|
<PhSortAscending
|
||||||
v-if="order === 'asc'"
|
v-if="order === 'asc'"
|
||||||
icon="sort-up"
|
|
||||||
class="sort__icon"
|
class="sort__icon"
|
||||||
/>
|
/>
|
||||||
<Icon
|
<PhSortDescending
|
||||||
v-else-if="order === 'desc'"
|
v-else-if="order === 'desc'"
|
||||||
icon="sort-up"
|
|
||||||
rotation="180"
|
|
||||||
class="sort__icon"
|
class="sort__icon"
|
||||||
/>
|
/>
|
||||||
<Icon
|
<PhArrowsDownUp
|
||||||
v-else
|
v-else
|
||||||
icon="sort"
|
|
||||||
class="sort__icon"
|
class="sort__icon"
|
||||||
/>
|
/>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import {PhSortAscending, PhSortDescending, PhArrowsDownUp} from '@phosphor-icons/vue'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
|
||||||
withDefaults(defineProps<{
|
withDefaults(defineProps<{
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
v-if="task.attachments.length > 0"
|
v-if="task.attachments.length > 0"
|
||||||
class="task-glance-icon"
|
class="task-glance-icon"
|
||||||
>
|
>
|
||||||
<Icon icon="paperclip" />
|
<PhPaperclip />
|
||||||
</span>
|
</span>
|
||||||
<CommentCount
|
<CommentCount
|
||||||
:task="task"
|
:task="task"
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
v-if="task.dueDate"
|
v-if="task.dueDate"
|
||||||
class="task-glance-due"
|
class="task-glance-due"
|
||||||
>
|
>
|
||||||
<Icon icon="calendar" />
|
<PhCalendarBlank />
|
||||||
<span>{{ $t('task.detail.due', {at: formatDisplayDate(task.dueDate)}) }}</span>
|
<span>{{ $t('task.detail.due', {at: formatDisplayDate(task.dueDate)}) }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -82,6 +82,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, computed, onUnmounted, nextTick} from 'vue'
|
import {ref, computed, onUnmounted, nextTick} from 'vue'
|
||||||
import {computePosition, flip, offset, shift} from '@floating-ui/dom'
|
import {computePosition, flip, offset, shift} from '@floating-ui/dom'
|
||||||
|
import {PhPaperclip, PhCalendarBlank} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
import {getTaskIdentifier} from '@/models/task'
|
import {getTaskIdentifier} from '@/models/task'
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import {createPinia} from 'pinia'
|
||||||
|
|
||||||
import testid from '@/directives/testid'
|
import testid from '@/directives/testid'
|
||||||
|
|
||||||
import FontAwesomeIcon from '@/components/misc/Icon'
|
|
||||||
import XButton from '@/components/input/button.vue'
|
import XButton from '@/components/input/button.vue'
|
||||||
import Modal from '@/components/misc/Modal.vue'
|
import Modal from '@/components/misc/Modal.vue'
|
||||||
import Card from '@/components/misc/Card.vue'
|
import Card from '@/components/misc/Card.vue'
|
||||||
|
|
@ -21,7 +20,6 @@ export const setupVue3 = defineSetupVue3(({ app }) => {
|
||||||
|
|
||||||
app.directive('cy', testid)
|
app.directive('cy', testid)
|
||||||
|
|
||||||
app.component('Icon', FontAwesomeIcon)
|
|
||||||
app.component('XButton', XButton)
|
app.component('XButton', XButton)
|
||||||
app.component('Modal', Modal)
|
app.component('Modal', Modal)
|
||||||
app.component('Card', Card)
|
app.component('Card', Card)
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ import shortcut from '@/directives/shortcut'
|
||||||
import testid from '@/directives/testid'
|
import testid from '@/directives/testid'
|
||||||
|
|
||||||
// global components
|
// global components
|
||||||
import FontAwesomeIcon from '@/components/misc/Icon'
|
|
||||||
import Button from '@/components/input/Button.vue'
|
import Button from '@/components/input/Button.vue'
|
||||||
import Modal from '@/components/misc/Modal.vue'
|
import Modal from '@/components/misc/Modal.vue'
|
||||||
import Card from '@/components/misc/Card.vue'
|
import Card from '@/components/misc/Card.vue'
|
||||||
|
|
@ -62,7 +61,6 @@ setLanguage(browserLanguage).then(() => {
|
||||||
app.directive('shortcut', shortcut)
|
app.directive('shortcut', shortcut)
|
||||||
app.directive('cy', testid)
|
app.directive('cy', testid)
|
||||||
|
|
||||||
app.component('Icon', FontAwesomeIcon)
|
|
||||||
app.component('XButton', Button)
|
app.component('XButton', Button)
|
||||||
app.component('Modal', Modal)
|
app.component('Modal', Modal)
|
||||||
app.component('Card', Card)
|
app.component('Card', Card)
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
import type { FunctionalComponent } from 'vue'
|
import type {FunctionalComponent} from 'vue'
|
||||||
import type { Notifications } from '@kyvg/vue3-notification'
|
import type {Notifications} from '@kyvg/vue3-notification'
|
||||||
// import FontAwesomeIcon from '@/components/misc/Icon'
|
|
||||||
import type { FontAwesomeIcon as FontAwesomeIconFixedTypes } from './vue-fontawesome'
|
|
||||||
import type XButton from '@/components/input/Button.vue'
|
import type XButton from '@/components/input/Button.vue'
|
||||||
import type Modal from '@/components/misc/Modal.vue'
|
import type Modal from '@/components/misc/Modal.vue'
|
||||||
import type Card from '@/components/misc/Card.vue'
|
import type Card from '@/components/misc/Card.vue'
|
||||||
|
|
||||||
// Here we define globally imported components
|
|
||||||
// See: https://github.com/vuejs/language-tools/wiki/Global-Component-Types
|
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
Icon: FontAwesomeIconFixedTypes
|
|
||||||
Notifications: FunctionalComponent<Notifications>
|
Notifications: FunctionalComponent<Notifications>
|
||||||
XButton: typeof XButton,
|
XButton: typeof XButton,
|
||||||
Modal: typeof Modal,
|
Modal: typeof Modal,
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
// copied and slightly modified from unmerged pull request that corrects types
|
|
||||||
// https://github.com/FortAwesome/vue-fontawesome/pull/355
|
|
||||||
|
|
||||||
import type { FaSymbol, FlipProp, IconLookup, IconProp, PullProp, SizeProp, Transform } from '@fortawesome/fontawesome-svg-core'
|
|
||||||
import type { DefineComponent } from 'vue'
|
|
||||||
|
|
||||||
|
|
||||||
interface FontAwesomeIconProps {
|
|
||||||
border?: boolean
|
|
||||||
fixedWidth?: boolean
|
|
||||||
flip?: FlipProp
|
|
||||||
icon: IconProp
|
|
||||||
mask?: IconLookup
|
|
||||||
listItem?: boolean
|
|
||||||
pull?: PullProp
|
|
||||||
pulse?: boolean
|
|
||||||
rotation?: 90 | 180 | 270 | '90' | '180' | '270'
|
|
||||||
swapOpacity?: boolean
|
|
||||||
size?: SizeProp
|
|
||||||
spin?: boolean
|
|
||||||
transform?: Transform
|
|
||||||
symbol?: FaSymbol
|
|
||||||
title?: string | string[]
|
|
||||||
inverse?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FontAwesomeLayersProps {
|
|
||||||
fixedWidth?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FontAwesomeLayersTextProps {
|
|
||||||
value: string | number
|
|
||||||
transform?: object | string
|
|
||||||
counter?: boolean
|
|
||||||
position?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type FontAwesomeIcon = DefineComponent<FontAwesomeIconProps>
|
|
||||||
export type FontAwesomeLayers = DefineComponent<FontAwesomeLayersProps>
|
|
||||||
export type FontAwesomeLayersText = DefineComponent<FontAwesomeLayersTextProps>
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<CreateEdit
|
<CreateEdit
|
||||||
v-model:loading="loadingModel"
|
v-model:loading="loadingModel"
|
||||||
:title="$t('filters.edit.title')"
|
:title="$t('filters.edit.title')"
|
||||||
primary-icon=""
|
:show-primary-icon="false"
|
||||||
:primary-label="$t('misc.save')"
|
:primary-label="$t('misc.save')"
|
||||||
:tertiary="$t('misc.delete')"
|
:tertiary="$t('misc.delete')"
|
||||||
@primary="handleSave"
|
@primary="handleSave"
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@
|
||||||
<XButton
|
<XButton
|
||||||
:to="{name:'labels.create'}"
|
:to="{name:'labels.create'}"
|
||||||
class="is-pulled-right"
|
class="is-pulled-right"
|
||||||
icon="plus"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('label.create.header') }}
|
{{ $t('label.create.header') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
|
|
||||||
|
|
@ -42,10 +44,7 @@
|
||||||
class="label-edit-button is-small"
|
class="label-edit-button is-small"
|
||||||
@click.stop.prevent="editLabel(label)"
|
@click.stop.prevent="editLabel(label)"
|
||||||
>
|
>
|
||||||
<Icon
|
<PhPencilSimple class="icon" />
|
||||||
icon="pen"
|
|
||||||
class="icon"
|
|
||||||
/>
|
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -87,10 +86,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<XButton
|
<XButton
|
||||||
icon="trash-alt"
|
|
||||||
danger
|
danger
|
||||||
@click="showDeleteDialoge(labelEditLabel)"
|
@click="showDeleteDialoge(labelEditLabel)"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTrash />
|
||||||
|
</template>
|
||||||
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -122,6 +124,7 @@ import {computed, nextTick, ref} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
import {PhPencilSimple, PhPlus, PhTrash} from '@phosphor-icons/vue'
|
||||||
import Editor from '@/components/input/AsyncEditor'
|
import Editor from '@/components/input/AsyncEditor'
|
||||||
import ColorPicker from '@/components/input/ColorPicker.vue'
|
import ColorPicker from '@/components/input/ColorPicker.vue'
|
||||||
import FormField from '@/components/input/FormField.vue'
|
import FormField from '@/components/input/FormField.vue'
|
||||||
|
|
|
||||||
|
|
@ -15,15 +15,19 @@
|
||||||
<div class="action-buttons">
|
<div class="action-buttons">
|
||||||
<XButton
|
<XButton
|
||||||
:to="{name: 'filters.create'}"
|
:to="{name: 'filters.create'}"
|
||||||
icon="filter"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhFunnel />
|
||||||
|
</template>
|
||||||
{{ $t('filters.create.title') }}
|
{{ $t('filters.create.title') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
v-cy="'new-project'"
|
v-cy="'new-project'"
|
||||||
:to="{name: 'project.create'}"
|
:to="{name: 'project.create'}"
|
||||||
icon="plus"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('project.create.header') }}
|
{{ $t('project.create.header') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -41,6 +45,8 @@ import {computed} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
|
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
|
||||||
|
|
||||||
|
import {PhFunnel, PhPlus} from '@phosphor-icons/vue'
|
||||||
import ProjectCardGrid from '@/components/project/partials/ProjectCardGrid.vue'
|
import ProjectCardGrid from '@/components/project/partials/ProjectCardGrid.vue'
|
||||||
|
|
||||||
import {useTitle} from '@/composables/useTitle'
|
import {useTitle} from '@/composables/useTitle'
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@
|
||||||
<CreateEdit
|
<CreateEdit
|
||||||
v-model:loading="loadingModel"
|
v-model:loading="loadingModel"
|
||||||
:title="$t('project.duplicate.title')"
|
:title="$t('project.duplicate.title')"
|
||||||
primary-icon="paste"
|
|
||||||
:primary-label="$t('project.duplicate.label')"
|
:primary-label="$t('project.duplicate.label')"
|
||||||
@primary="duplicate"
|
@primary="duplicate"
|
||||||
>
|
>
|
||||||
|
<template #primary-icon>
|
||||||
|
<PhClipboard />
|
||||||
|
</template>
|
||||||
<p>{{ $t('project.duplicate.text') }}</p>
|
<p>{{ $t('project.duplicate.text') }}</p>
|
||||||
<ProjectSearch v-model="parentProject" />
|
<ProjectSearch v-model="parentProject" />
|
||||||
</CreateEdit>
|
</CreateEdit>
|
||||||
|
|
@ -17,6 +19,7 @@ import {useRoute} from 'vue-router'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import CreateEdit from '@/components/misc/CreateEdit.vue'
|
import CreateEdit from '@/components/misc/CreateEdit.vue'
|
||||||
|
import {PhClipboard} from '@phosphor-icons/vue'
|
||||||
import ProjectSearch from '@/components/tasks/partials/ProjectSearch.vue'
|
import ProjectSearch from '@/components/tasks/partials/ProjectSearch.vue'
|
||||||
|
|
||||||
import {success} from '@/message'
|
import {success} from '@/message'
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<CreateEdit
|
<CreateEdit
|
||||||
v-model:loading="loadingModel"
|
v-model:loading="loadingModel"
|
||||||
:title="$t('project.edit.header')"
|
:title="$t('project.edit.header')"
|
||||||
primary-icon=""
|
:show-primary-icon="false"
|
||||||
:primary-label="$t('misc.save')"
|
:primary-label="$t('misc.save')"
|
||||||
:tertiary="project.maxPermission === PERMISSIONS.ADMIN ? $t('misc.delete') : undefined"
|
:tertiary="project.maxPermission === PERMISSIONS.ADMIN ? $t('misc.delete') : undefined"
|
||||||
@primary="save"
|
@primary="save"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import type {IProjectView} from '@/modelTypes/IProjectView'
|
||||||
import ViewEditForm from '@/components/project/views/ViewEditForm.vue'
|
import ViewEditForm from '@/components/project/views/ViewEditForm.vue'
|
||||||
import ProjectViewService from '@/services/projectViews'
|
import ProjectViewService from '@/services/projectViews'
|
||||||
import XButton from '@/components/input/Button.vue'
|
import XButton from '@/components/input/Button.vue'
|
||||||
|
import {PhDotsSixVertical, PhPencilSimple, PhTrash} from '@phosphor-icons/vue'
|
||||||
import {error, success} from '@/message'
|
import {error, success} from '@/message'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import ProjectService from '@/services/project'
|
import ProjectService from '@/services/project'
|
||||||
|
|
@ -193,19 +194,25 @@ async function saveViewPosition(e) {
|
||||||
<XButton
|
<XButton
|
||||||
v-if="isAdmin"
|
v-if="isAdmin"
|
||||||
class="is-danger mie-2"
|
class="is-danger mie-2"
|
||||||
icon="trash-alt"
|
|
||||||
@click="() => {
|
@click="() => {
|
||||||
viewIdToDelete = v.id
|
viewIdToDelete = v.id
|
||||||
showDeleteModal = true
|
showDeleteModal = true
|
||||||
}"
|
}"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTrash />
|
||||||
|
</template>
|
||||||
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
v-if="isAdmin"
|
v-if="isAdmin"
|
||||||
icon="pen"
|
|
||||||
@click="viewToEdit = {...v}"
|
@click="viewToEdit = {...v}"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPencilSimple />
|
||||||
|
</template>
|
||||||
|
</XButton>
|
||||||
<span class="icon handle">
|
<span class="icon handle">
|
||||||
<Icon icon="grip-lines" />
|
<PhDotsSixVertical />
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import ProjectModel from '@/models/project'
|
||||||
import type {IProject} from '@/modelTypes/IProject'
|
import type {IProject} from '@/modelTypes/IProject'
|
||||||
|
|
||||||
import CreateEdit from '@/components/misc/CreateEdit.vue'
|
import CreateEdit from '@/components/misc/CreateEdit.vue'
|
||||||
|
import {PhPlus, PhTrash} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
import {useBaseStore} from '@/stores/base'
|
import {useBaseStore} from '@/stores/base'
|
||||||
import type {IWebhook} from '@/modelTypes/IWebhook'
|
import type {IWebhook} from '@/modelTypes/IWebhook'
|
||||||
|
|
@ -128,10 +129,12 @@ function validateSelectedEvents() {
|
||||||
>
|
>
|
||||||
<XButton
|
<XButton
|
||||||
v-if="!(webhooks?.length === 0 || showNewForm)"
|
v-if="!(webhooks?.length === 0 || showNewForm)"
|
||||||
icon="plus"
|
|
||||||
class="mbe-4"
|
class="mbe-4"
|
||||||
@click="showNewForm = true"
|
@click="showNewForm = true"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('project.webhooks.create') }}
|
{{ $t('project.webhooks.create') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
|
|
||||||
|
|
@ -239,9 +242,11 @@ function validateSelectedEvents() {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<XButton
|
<XButton
|
||||||
icon="plus"
|
|
||||||
@click="create"
|
@click="create"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('project.webhooks.create') }}
|
{{ $t('project.webhooks.create') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -277,9 +282,12 @@ function validateSelectedEvents() {
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
<XButton
|
<XButton
|
||||||
danger
|
danger
|
||||||
icon="trash-alt"
|
|
||||||
@click="() => {showDeleteModal = true;webhookIdToDelete = w.id}"
|
@click="() => {showDeleteModal = true;webhookIdToDelete = w.id}"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTrash />
|
||||||
|
</template>
|
||||||
|
</XButton>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
class="clear-filter-button"
|
class="clear-filter-button"
|
||||||
@click="clearLabelFilter"
|
@click="clearLabelFilter"
|
||||||
>
|
>
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</Message>
|
</Message>
|
||||||
<p
|
<p
|
||||||
|
|
@ -102,7 +102,7 @@ import {formatDate} from '@/helpers/time/formatDate'
|
||||||
import {setTitle} from '@/helpers/setTitle'
|
import {setTitle} from '@/helpers/setTitle'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import Icon from '@/components/misc/Icon'
|
import {PhX} from '@phosphor-icons/vue'
|
||||||
import Message from '@/components/misc/Message.vue'
|
import Message from '@/components/misc/Message.vue'
|
||||||
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
|
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
|
||||||
import SingleTaskInProject from '@/components/tasks/partials/SingleTaskInProject.vue'
|
import SingleTaskInProject from '@/components/tasks/partials/SingleTaskInProject.vue'
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
class="back-button mbs-2"
|
class="back-button mbs-2"
|
||||||
@click="lastProject ? router.back() : router.push(projectRoute)"
|
@click="lastProject ? router.back() : router.push(projectRoute)"
|
||||||
>
|
>
|
||||||
<Icon icon="arrow-left" />
|
<PhArrowLeft />
|
||||||
{{ $t('task.detail.back') }}
|
{{ $t('task.detail.back') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<Heading
|
<Heading
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
>
|
>
|
||||||
<!-- Assignees -->
|
<!-- Assignees -->
|
||||||
<div class="detail-title">
|
<div class="detail-title">
|
||||||
<Icon icon="users" />
|
<PhUsers />
|
||||||
{{ $t('task.attributes.assignees') }}
|
{{ $t('task.attributes.assignees') }}
|
||||||
</div>
|
</div>
|
||||||
<EditAssignees
|
<EditAssignees
|
||||||
|
|
@ -99,7 +99,7 @@
|
||||||
>
|
>
|
||||||
<!-- Priority -->
|
<!-- Priority -->
|
||||||
<div class="detail-title">
|
<div class="detail-title">
|
||||||
<Icon icon="exclamation-circle" />
|
<PhWarningCircle />
|
||||||
{{ $t('task.attributes.priority') }}
|
{{ $t('task.attributes.priority') }}
|
||||||
</div>
|
</div>
|
||||||
<PrioritySelect
|
<PrioritySelect
|
||||||
|
|
@ -120,7 +120,7 @@
|
||||||
>
|
>
|
||||||
<!-- Due Date -->
|
<!-- Due Date -->
|
||||||
<div class="detail-title">
|
<div class="detail-title">
|
||||||
<Icon icon="calendar" />
|
<PhCalendar />
|
||||||
{{ $t('task.attributes.dueDate') }}
|
{{ $t('task.attributes.dueDate') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="date-input">
|
<div class="date-input">
|
||||||
|
|
@ -137,7 +137,7 @@
|
||||||
@click="() => {task.dueDate = null;saveTask()}"
|
@click="() => {task.dueDate = null;saveTask()}"
|
||||||
>
|
>
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</span>
|
</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -153,7 +153,7 @@
|
||||||
>
|
>
|
||||||
<!-- Progress -->
|
<!-- Progress -->
|
||||||
<div class="detail-title">
|
<div class="detail-title">
|
||||||
<Icon icon="percent" />
|
<PhPercent />
|
||||||
{{ $t('task.attributes.percentDone') }}
|
{{ $t('task.attributes.percentDone') }}
|
||||||
</div>
|
</div>
|
||||||
<PercentDoneSelect
|
<PercentDoneSelect
|
||||||
|
|
@ -174,7 +174,7 @@
|
||||||
>
|
>
|
||||||
<!-- Start Date -->
|
<!-- Start Date -->
|
||||||
<div class="detail-title">
|
<div class="detail-title">
|
||||||
<Icon icon="play" />
|
<PhPlay />
|
||||||
{{ $t('task.attributes.startDate') }}
|
{{ $t('task.attributes.startDate') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="date-input">
|
<div class="date-input">
|
||||||
|
|
@ -191,7 +191,7 @@
|
||||||
@click="() => {task.startDate = null;saveTask()}"
|
@click="() => {task.startDate = null;saveTask()}"
|
||||||
>
|
>
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</span>
|
</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -207,7 +207,7 @@
|
||||||
>
|
>
|
||||||
<!-- End Date -->
|
<!-- End Date -->
|
||||||
<div class="detail-title">
|
<div class="detail-title">
|
||||||
<Icon icon="stop" />
|
<PhStop />
|
||||||
{{ $t('task.attributes.endDate') }}
|
{{ $t('task.attributes.endDate') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="date-input">
|
<div class="date-input">
|
||||||
|
|
@ -224,7 +224,7 @@
|
||||||
@click="() => {task.endDate = null;saveTask()}"
|
@click="() => {task.endDate = null;saveTask()}"
|
||||||
>
|
>
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</span>
|
</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -240,7 +240,7 @@
|
||||||
>
|
>
|
||||||
<!-- Reminders -->
|
<!-- Reminders -->
|
||||||
<div class="detail-title">
|
<div class="detail-title">
|
||||||
<Icon :icon="['far', 'clock']" />
|
<PhClock />
|
||||||
{{ $t('task.attributes.reminders') }}
|
{{ $t('task.attributes.reminders') }}
|
||||||
</div>
|
</div>
|
||||||
<Reminders
|
<Reminders
|
||||||
|
|
@ -262,7 +262,7 @@
|
||||||
<!-- Repeat after -->
|
<!-- Repeat after -->
|
||||||
<div class="is-flex is-justify-content-space-between">
|
<div class="is-flex is-justify-content-space-between">
|
||||||
<div class="detail-title">
|
<div class="detail-title">
|
||||||
<Icon icon="history" />
|
<PhClockCounterClockwise />
|
||||||
{{ $t('task.attributes.repeat') }}
|
{{ $t('task.attributes.repeat') }}
|
||||||
</div>
|
</div>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
|
|
@ -271,7 +271,7 @@
|
||||||
@click="removeRepeatAfter"
|
@click="removeRepeatAfter"
|
||||||
>
|
>
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="times" />
|
<PhX />
|
||||||
</span>
|
</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -293,7 +293,7 @@
|
||||||
>
|
>
|
||||||
<!-- Color -->
|
<!-- Color -->
|
||||||
<div class="detail-title">
|
<div class="detail-title">
|
||||||
<Icon icon="fill-drip" />
|
<PhPaintBucket />
|
||||||
{{ $t('task.attributes.color') }}
|
{{ $t('task.attributes.color') }}
|
||||||
</div>
|
</div>
|
||||||
<ColorPicker
|
<ColorPicker
|
||||||
|
|
@ -313,7 +313,7 @@
|
||||||
>
|
>
|
||||||
<div class="detail-title">
|
<div class="detail-title">
|
||||||
<span class="icon is-grey">
|
<span class="icon is-grey">
|
||||||
<Icon icon="tags" />
|
<PhTag />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('task.attributes.labels') }}
|
{{ $t('task.attributes.labels') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -365,7 +365,7 @@
|
||||||
>
|
>
|
||||||
<h3>
|
<h3>
|
||||||
<span class="icon is-grey">
|
<span class="icon is-grey">
|
||||||
<Icon icon="sitemap" />
|
<PhTreeStructure />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('task.attributes.relatedTasks') }}
|
{{ $t('task.attributes.relatedTasks') }}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
@ -386,7 +386,7 @@
|
||||||
>
|
>
|
||||||
<h3>
|
<h3>
|
||||||
<span class="icon is-grey">
|
<span class="icon is-grey">
|
||||||
<Icon icon="list" />
|
<PhList />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('task.detail.move') }}
|
{{ $t('task.detail.move') }}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
@ -426,10 +426,12 @@
|
||||||
v-shortcut="'t'"
|
v-shortcut="'t'"
|
||||||
:class="{'is-pending': !task.done}"
|
:class="{'is-pending': !task.done}"
|
||||||
class="button--mark-done"
|
class="button--mark-done"
|
||||||
icon="check-double"
|
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
@click="toggleTaskDone()"
|
@click="toggleTaskDone()"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhChecks />
|
||||||
|
</template>
|
||||||
{{ task.done ? $t('task.detail.undone') : $t('task.detail.done') }}
|
{{ task.done ? $t('task.detail.undone') : $t('task.detail.done') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<TaskSubscription
|
<TaskSubscription
|
||||||
|
|
@ -441,9 +443,11 @@
|
||||||
<XButton
|
<XButton
|
||||||
v-shortcut="'s'"
|
v-shortcut="'s'"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
:icon="task.isFavorite ? 'star' : ['far', 'star']"
|
|
||||||
@click="toggleFavorite"
|
@click="toggleFavorite"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhStar :weight="task.isFavorite ? 'fill' : 'regular'" />
|
||||||
|
</template>
|
||||||
{{
|
{{
|
||||||
task.isFavorite ? $t('task.detail.actions.unfavorite') : $t('task.detail.actions.favorite')
|
task.isFavorite ? $t('task.detail.actions.unfavorite') : $t('task.detail.actions.favorite')
|
||||||
}}
|
}}
|
||||||
|
|
@ -454,33 +458,40 @@
|
||||||
<XButton
|
<XButton
|
||||||
v-shortcut="'l'"
|
v-shortcut="'l'"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="tags"
|
|
||||||
@click="setFieldActive('labels')"
|
@click="setFieldActive('labels')"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTag />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.label') }}
|
{{ $t('task.detail.actions.label') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
v-shortcut="'p'"
|
v-shortcut="'p'"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="exclamation-circle"
|
|
||||||
@click="setFieldActive('priority')"
|
@click="setFieldActive('priority')"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhWarningCircle />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.priority') }}
|
{{ $t('task.detail.actions.priority') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="percent"
|
|
||||||
@click="setFieldActive('percentDone')"
|
@click="setFieldActive('percentDone')"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPercent />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.percentDone') }}
|
{{ $t('task.detail.actions.percentDone') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
v-shortcut="'c'"
|
v-shortcut="'c'"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="fill-drip"
|
|
||||||
:icon-color="color"
|
|
||||||
@click="setFieldActive('color')"
|
@click="setFieldActive('color')"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPaintBucket :style="{color}" />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.color') }}
|
{{ $t('task.detail.actions.color') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
|
|
||||||
|
|
@ -490,33 +501,41 @@
|
||||||
v-shortcut="'a'"
|
v-shortcut="'a'"
|
||||||
v-cy="'taskDetail.assign'"
|
v-cy="'taskDetail.assign'"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="users"
|
|
||||||
@click="setFieldActive('assignees')"
|
@click="setFieldActive('assignees')"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhUsers />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.assign') }}
|
{{ $t('task.detail.actions.assign') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
v-shortcut="'f'"
|
v-shortcut="'f'"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="paperclip"
|
|
||||||
@click="openAttachments()"
|
@click="openAttachments()"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPaperclip />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.attachments') }}
|
{{ $t('task.detail.actions.attachments') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
v-shortcut="'r'"
|
v-shortcut="'r'"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="sitemap"
|
|
||||||
@click="setRelatedTasksActive()"
|
@click="setRelatedTasksActive()"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTreeStructure />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.relatedTasks') }}
|
{{ $t('task.detail.actions.relatedTasks') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
v-shortcut="'m'"
|
v-shortcut="'m'"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="list"
|
|
||||||
@click="setFieldActive('moveProject')"
|
@click="setFieldActive('moveProject')"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhList />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.moveProject') }}
|
{{ $t('task.detail.actions.moveProject') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
|
|
||||||
|
|
@ -525,47 +544,59 @@
|
||||||
<XButton
|
<XButton
|
||||||
v-shortcut="'d'"
|
v-shortcut="'d'"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="calendar"
|
|
||||||
@click="setFieldActive('dueDate')"
|
@click="setFieldActive('dueDate')"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhCalendar />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.dueDate') }}
|
{{ $t('task.detail.actions.dueDate') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="play"
|
|
||||||
@click="setFieldActive('startDate')"
|
@click="setFieldActive('startDate')"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlay />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.startDate') }}
|
{{ $t('task.detail.actions.startDate') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="stop"
|
|
||||||
@click="setFieldActive('endDate')"
|
@click="setFieldActive('endDate')"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhStop />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.endDate') }}
|
{{ $t('task.detail.actions.endDate') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
v-shortcut="reminderShortcut"
|
v-shortcut="reminderShortcut"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
:icon="['far', 'clock']"
|
|
||||||
@click="setFieldActive('reminders')"
|
@click="setFieldActive('reminders')"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhClock />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.reminders') }}
|
{{ $t('task.detail.actions.reminders') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon="history"
|
|
||||||
@click="setFieldActive('repeatAfter')"
|
@click="setFieldActive('repeatAfter')"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhClockCounterClockwise />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.repeatAfter') }}
|
{{ $t('task.detail.actions.repeatAfter') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
<XButton
|
<XButton
|
||||||
v-shortcut="'Shift+Delete'"
|
v-shortcut="'Shift+Delete'"
|
||||||
icon="trash-alt"
|
|
||||||
:shadow="false"
|
:shadow="false"
|
||||||
class="is-danger is-outlined has-no-border"
|
class="is-danger is-outlined has-no-border"
|
||||||
@click="showDeleteModal = true"
|
@click="showDeleteModal = true"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTrash />
|
||||||
|
</template>
|
||||||
{{ $t('task.detail.actions.delete') }}
|
{{ $t('task.detail.actions.delete') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -588,7 +619,7 @@
|
||||||
:aria-label="$t('task.detail.scrollToBottom')"
|
:aria-label="$t('task.detail.scrollToBottom')"
|
||||||
@click="scrollToBottom"
|
@click="scrollToBottom"
|
||||||
>
|
>
|
||||||
<Icon icon="chevron-down" />
|
<PhCaretDown />
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
|
|
@ -631,6 +662,13 @@ import {PERMISSIONS} from '@/constants/permissions'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
|
||||||
|
import {
|
||||||
|
PhArrowLeft, PhUsers, PhWarningCircle, PhCalendar, PhX, PhPercent,
|
||||||
|
PhPlay, PhStop, PhClock, PhClockCounterClockwise, PhPaintBucket,
|
||||||
|
PhTag, PhTreeStructure, PhList, PhChecks, PhStar, PhCaretDown,
|
||||||
|
PhTrash, PhPaperclip,
|
||||||
|
} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
// partials
|
// partials
|
||||||
import Attachments from '@/components/tasks/partials/Attachments.vue'
|
import Attachments from '@/components/tasks/partials/Attachments.vue'
|
||||||
import ChecklistSummary from '@/components/tasks/partials/ChecklistSummary.vue'
|
import ChecklistSummary from '@/components/tasks/partials/ChecklistSummary.vue'
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,12 @@
|
||||||
<XButton
|
<XButton
|
||||||
:loading="teamService.loading"
|
:loading="teamService.loading"
|
||||||
danger
|
danger
|
||||||
icon="trash-alt"
|
|
||||||
@click="showDeleteModal = true"
|
@click="showDeleteModal = true"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTrash />
|
||||||
|
</template>
|
||||||
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -95,9 +98,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<XButton
|
<XButton
|
||||||
icon="plus"
|
|
||||||
@click="addUser"
|
@click="addUser"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('team.edit.addUser') }}
|
{{ $t('team.edit.addUser') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -130,13 +135,13 @@
|
||||||
<td class="type">
|
<td class="type">
|
||||||
<template v-if="m.admin">
|
<template v-if="m.admin">
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="lock" />
|
<PhLock />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('team.attributes.admin') }}
|
{{ $t('team.attributes.admin') }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span class="icon is-small">
|
<span class="icon is-small">
|
||||||
<Icon icon="user" />
|
<PhUser />
|
||||||
</span>
|
</span>
|
||||||
{{ $t('team.attributes.member') }}
|
{{ $t('team.attributes.member') }}
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -157,9 +162,12 @@
|
||||||
v-if="m.id !== userInfo.id"
|
v-if="m.id !== userInfo.id"
|
||||||
:loading="teamMemberService.loading"
|
:loading="teamMemberService.loading"
|
||||||
danger
|
danger
|
||||||
icon="trash-alt"
|
|
||||||
@click="() => {memberToDelete = m; showUserDeleteModal = true}"
|
@click="() => {memberToDelete = m; showUserDeleteModal = true}"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhTrash />
|
||||||
|
</template>
|
||||||
|
</XButton>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -236,6 +244,8 @@ import {useI18n} from 'vue-i18n'
|
||||||
import {useRoute, useRouter} from 'vue-router'
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
|
|
||||||
import Editor from '@/components/input/AsyncEditor'
|
import Editor from '@/components/input/AsyncEditor'
|
||||||
|
|
||||||
|
import {PhLock, PhPlus, PhTrash, PhUser} from '@phosphor-icons/vue'
|
||||||
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
|
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
|
||||||
import FormField from '@/components/input/FormField.vue'
|
import FormField from '@/components/input/FormField.vue'
|
||||||
import Multiselect from '@/components/input/Multiselect.vue'
|
import Multiselect from '@/components/input/Multiselect.vue'
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@
|
||||||
<XButton
|
<XButton
|
||||||
:to="{name:'teams.create'}"
|
:to="{name:'teams.create'}"
|
||||||
class="is-pulled-right"
|
class="is-pulled-right"
|
||||||
icon="plus"
|
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('team.create.title') }}
|
{{ $t('team.create.title') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
|
|
||||||
|
|
@ -44,6 +46,7 @@ import {ref, shallowReactive} from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import TeamService from '@/services/team'
|
import TeamService from '@/services/team'
|
||||||
|
import {PhPlus} from '@phosphor-icons/vue'
|
||||||
import { useTitle } from '@/composables/useTitle'
|
import { useTitle } from '@/composables/useTitle'
|
||||||
|
|
||||||
const { t } = useI18n({useScope: 'global'})
|
const { t } = useI18n({useScope: 'global'})
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,7 @@
|
||||||
{{ text }}
|
{{ text }}
|
||||||
</span>
|
</span>
|
||||||
<span class="ml-1 has-text-grey-light is-size-7">
|
<span class="ml-1 has-text-grey-light is-size-7">
|
||||||
<Icon
|
<PhArrowSquareOut />
|
||||||
icon="arrow-up-right-from-square"
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -51,6 +49,7 @@ import { useAuthStore } from '@/stores/auth'
|
||||||
import {useRoute} from 'vue-router'
|
import {useRoute} from 'vue-router'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
import {PhArrowSquareOut} from '@phosphor-icons/vue'
|
||||||
|
|
||||||
const { t } = useI18n({useScope: 'global'})
|
const { t } = useI18n({useScope: 'global'})
|
||||||
useTitle(() => t('user.settings.title'))
|
useTitle(() => t('user.settings.title'))
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import {parseScopesFromQuery} from '@/helpers/parseScopesFromQuery'
|
||||||
import {useFlatpickrLanguage} from '@/helpers/useFlatpickrLanguage'
|
import {useFlatpickrLanguage} from '@/helpers/useFlatpickrLanguage'
|
||||||
import {formatDateSince, formatDisplayDate} from '@/helpers/time/formatDate'
|
import {formatDateSince, formatDisplayDate} from '@/helpers/time/formatDate'
|
||||||
import XButton from '@/components/input/Button.vue'
|
import XButton from '@/components/input/Button.vue'
|
||||||
|
import {PhPlus} from '@phosphor-icons/vue'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import ApiTokenModel from '@/models/apiTokenModel'
|
import ApiTokenModel from '@/models/apiTokenModel'
|
||||||
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
|
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
|
||||||
|
|
@ -381,11 +382,13 @@ function toggleGroupPermissionsFromChild(group: string, checked: boolean) {
|
||||||
|
|
||||||
<XButton
|
<XButton
|
||||||
v-else
|
v-else
|
||||||
icon="plus"
|
|
||||||
class="mbe-4"
|
class="mbe-4"
|
||||||
:loading="service.loading"
|
:loading="service.loading"
|
||||||
@click="() => showCreateForm = true"
|
@click="() => showCreateForm = true"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('user.settings.apiTokens.createAToken') }}
|
{{ $t('user.settings.apiTokens.createAToken') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,12 @@
|
||||||
<XButton
|
<XButton
|
||||||
v-tooltip="$t('misc.copy')"
|
v-tooltip="$t('misc.copy')"
|
||||||
:shadow="false"
|
:shadow="false"
|
||||||
icon="paste"
|
|
||||||
@click="copy(caldavUrl)"
|
@click="copy(caldavUrl)"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhClipboard />
|
||||||
|
</template>
|
||||||
|
</XButton>
|
||||||
</template>
|
</template>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
|
@ -75,11 +78,13 @@
|
||||||
</Message>
|
</Message>
|
||||||
|
|
||||||
<XButton
|
<XButton
|
||||||
icon="plus"
|
|
||||||
class="mbe-4"
|
class="mbe-4"
|
||||||
:loading="service.loading"
|
:loading="service.loading"
|
||||||
@click="createToken"
|
@click="createToken"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<PhPlus />
|
||||||
|
</template>
|
||||||
{{ $t('user.settings.caldav.createToken') }}
|
{{ $t('user.settings.caldav.createToken') }}
|
||||||
</XButton>
|
</XButton>
|
||||||
|
|
||||||
|
|
@ -103,6 +108,7 @@ import {useTitle} from '@/composables/useTitle'
|
||||||
import {useCopyToClipboard} from '@/composables/useCopyToClipboard'
|
import {useCopyToClipboard} from '@/composables/useCopyToClipboard'
|
||||||
import {success} from '@/message'
|
import {success} from '@/message'
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
import {PhClipboard, PhPlus} from '@phosphor-icons/vue'
|
||||||
import Message from '@/components/misc/Message.vue'
|
import Message from '@/components/misc/Message.vue'
|
||||||
import FormField from '@/components/input/FormField.vue'
|
import FormField from '@/components/input/FormField.vue'
|
||||||
import CaldavTokenService from '@/services/caldavToken'
|
import CaldavTokenService from '@/services/caldavToken'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue