Compare commits

...

12 Commits

73 changed files with 505 additions and 627 deletions

View File

@ -52,13 +52,10 @@
},
"dependencies": {
"@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",
"@intlify/unplugin-vue-i18n": "11.0.3",
"@kyvg/vue3-notification": "3.4.2",
"@phosphor-icons/vue": "^2.2.1",
"@sentry/vue": "10.36.0",
"@tiptap/core": "3.17.0",
"@tiptap/extension-code-block-lowlight": "3.17.0",

View File

@ -22,18 +22,6 @@ importers:
'@floating-ui/dom':
specifier: 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':
specifier: 3.1.1
version: 3.1.1(patch_hash=145ab3233cbcd3bc934b4961cd8710e2b15e4ae5dd20862a8d1d6621d7f9d4a8)
@ -43,6 +31,9 @@ importers:
'@kyvg/vue3-notification':
specifier: 3.4.2
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':
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))
@ -1646,28 +1637,6 @@ packages:
'@floating-ui/utils@0.2.10':
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':
resolution: {integrity: sha512-Gn9fslZdacx1m1e3/2LSUPWagLObYmIDbkgvZTtgqT/OHc17VbM71AxWEjtC/xzo5K4PI25958PjvidoEH7ufw==}
@ -1967,6 +1936,12 @@ packages:
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
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':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
@ -8074,25 +8049,6 @@ snapshots:
'@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':
dependencies:
'@ghostery/adblocker-extended-selectors': 2.5.0
@ -8417,6 +8373,10 @@ snapshots:
'@parcel/watcher-win32-x64': 2.5.1
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':
optional: true

View File

@ -42,10 +42,11 @@
</div>
<div class="control">
<XButton
icon="calendar"
variant="secondary"
data-toggle
/>
>
<template #icon><PhCalendar /></template>
</XButton>
</div>
</div>
</label>
@ -61,10 +62,11 @@
</div>
<div class="control">
<XButton
icon="calendar"
variant="secondary"
data-toggle
/>
>
<template #icon><PhCalendar /></template>
</XButton>
</div>
</div>
</label>
@ -102,6 +104,7 @@
<script lang="ts" setup>
import {computed, ref, watch} from 'vue'
import {PhCalendar} from '@phosphor-icons/vue'
import {useI18n} from 'vue-i18n'
import flatPickr from 'vue-flatpickr-component'

View File

@ -39,10 +39,11 @@
</div>
<div class="control">
<XButton
icon="calendar"
variant="secondary"
data-toggle
/>
>
<template #icon><PhCalendar /></template>
</XButton>
</div>
</div>
</label>
@ -80,6 +81,7 @@
<script lang="ts" setup>
import {computed, ref, watch} from 'vue'
import {PhCalendar} from '@phosphor-icons/vue'
import {useI18n} from 'vue-i18n'
import flatPickr from 'vue-flatpickr-component'

View File

@ -4,10 +4,7 @@
class="add-to-home-screen"
:class="{'has-update-available': hasUpdateAvailable}"
>
<Icon
icon="arrow-up-from-bracket"
class="add-icon"
/>
<PhUploadSimple class="add-icon" />
<p>
{{ $t('home.addToHomeScreen') }}
</p>
@ -15,12 +12,13 @@
class="hide-button"
@click="() => hideMessage = true"
>
<Icon icon="x" />
<PhX />
</BaseButton>
</div>
</template>
<script lang="ts" setup>
import {PhUploadSimple, PhX} from '@phosphor-icons/vue'
import BaseButton from '@/components/base/BaseButton.vue'
import {useLocalStorage} from '@vueuse/core'
import {computed} from 'vue'

View File

@ -31,7 +31,7 @@
class="project-title-button"
>
<span class="is-sr-only">{{ $t('project.description') }}</span>
<Icon icon="circle-info" />
<PhInfo />
</BaseButton>
<ProjectSettingsDropdown
@ -45,10 +45,7 @@
@click="toggleOpen"
>
<span class="is-sr-only">{{ $t('project.openSettingsMenu') }}</span>
<Icon
icon="ellipsis-h"
class="icon"
/>
<PhDotsThree class="icon" />
</BaseButton>
</template>
</ProjectSettingsDropdown>
@ -79,7 +76,7 @@
transform: open ? 'rotate(180deg)' : 'rotate(0)',
}"
>
<Icon icon="chevron-down" />
<PhCaretDown />
</span>
</BaseButton>
</template>
@ -118,6 +115,7 @@ import { computed } from 'vue'
import { PERMISSIONS as Permissions } from '@/constants/permissions'
import {PhCaretDown, PhDotsThree, PhInfo} from '@phosphor-icons/vue'
import ProjectSettingsDropdown from '@/components/project/ProjectSettingsDropdown.vue'
import Dropdown from '@/components/misc/Dropdown.vue'
import DropdownItem from '@/components/misc/DropdownItem.vue'

View File

@ -5,7 +5,7 @@
class="menu-hide-button d-print-none"
@click="baseStore.setMenuActive(false)"
>
<Icon icon="times" />
<PhX />
</BaseButton>
<div
class="app-container"
@ -64,7 +64,7 @@
@click="showKeyboardShortcuts()"
>
<span class="is-sr-only">{{ $t('keyboardShortcuts.title') }}</span>
<Icon icon="keyboard" />
<PhKeyboard />
</BaseButton>
</main>
</div>
@ -79,6 +79,7 @@ import Navigation from '@/components/home/Navigation.vue'
import QuickActions from '@/components/quick-actions/QuickActions.vue'
import BaseButton from '@/components/base/BaseButton.vue'
import {PhKeyboard, PhX} from '@phosphor-icons/vue'
import {useBaseStore} from '@/stores/base'
import {useLabelStore} from '@/stores/labels'
import {useProjectStore} from '@/stores/projects'

View File

@ -1,6 +1,7 @@
<script setup lang="ts">
import {computed, ref} from 'vue'
import {useConfigStore} from '@/stores/config'
import {PhX} from '@phosphor-icons/vue'
import BaseButton from '@/components/base/BaseButton.vue'
const configStore = useConfigStore()
@ -21,7 +22,7 @@ const enabled = computed(() => configStore.demoModeEnabled && !hide.value)
class="hide-button"
@click="() => hide = true"
>
<Icon icon="times" />
<PhX />
</BaseButton>
</div>
</template>

View File

@ -22,7 +22,7 @@
:to="{ name: 'home'}"
>
<span class="menu-item-icon icon">
<Icon icon="calendar" />
<PhCalendar />
</span>
{{ $t('navigation.overview') }}
</RouterLink>
@ -33,7 +33,7 @@
:to="{ name: 'tasks.range'}"
>
<span class="menu-item-icon icon">
<Icon :icon="['far', 'calendar-alt']" />
<PhCalendarBlank />
</span>
{{ $t('navigation.upcoming') }}
</RouterLink>
@ -44,7 +44,7 @@
:to="{ name: 'projects.index'}"
>
<span class="menu-item-icon icon">
<Icon icon="layer-group" />
<PhStack />
</span>
{{ $t('project.projects') }}
</RouterLink>
@ -55,7 +55,7 @@
:to="{ name: 'labels.index'}"
>
<span class="menu-item-icon icon">
<Icon icon="tags" />
<PhTag />
</span>
{{ $t('label.title') }}
</RouterLink>
@ -66,7 +66,7 @@
:to="{ name: 'teams.index'}"
>
<span class="menu-item-icon icon">
<Icon icon="users" />
<PhUsers />
</span>
{{ $t('team.title') }}
</RouterLink>
@ -131,6 +131,8 @@ import PoweredByLink from '@/components/home/PoweredByLink.vue'
import Logo from '@/components/home/Logo.vue'
import Loading from '@/components/misc/Loading.vue'
import {PhCalendar, PhCalendarBlank, PhStack, PhTag, PhUsers} from '@phosphor-icons/vue'
import {useBaseStore} from '@/stores/base'
import {useProjectStore} from '@/stores/projects'
import ProjectsNavigation from '@/components/home/ProjectsNavigation.vue'

View File

@ -13,10 +13,7 @@
class="collapse-project-button"
@click="childProjectsOpen = !childProjectsOpen"
>
<Icon
icon="chevron-down"
:class="{ 'project-is-collapsed': !childProjectsOpen }"
/>
<PhCaretDown :class="{ 'project-is-collapsed': !childProjectsOpen }" />
</BaseButton>
<span
v-if="canEditOrder && project.id > 0 && project.maxPermission !== null && project.maxPermission > PERMISSIONS.READ"
@ -25,7 +22,7 @@
@click.stop.prevent
@touchstart.stop
>
<Icon icon="grip-lines" />
<PhDotsSix />
</span>
<BaseButton
:to="{ name: 'project.index', params: { projectId: project.id} }"
@ -46,7 +43,7 @@
v-else-if="project.id < -1"
class="saved-filter-icon icon menu-item-icon"
>
<Icon icon="filter" />
<PhFunnel />
</span>
</div>
<span class="project-menu-title">{{ getProjectTitle(project) }}</span>
@ -58,7 +55,7 @@
@click="projectStore.toggleProjectFavorite(project)"
>
<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>
<ProjectSettingsDropdown
v-if="project.maxPermission !== null && project.maxPermission > PERMISSIONS.READ"
@ -72,10 +69,7 @@
@click="toggleOpen"
>
<span class="is-sr-only">{{ $t('project.openSettingsMenu') }}</span>
<Icon
icon="ellipsis-h"
class="icon"
/>
<PhDotsThree class="icon" />
</BaseButton>
</template>
</ProjectSettingsDropdown>
@ -98,6 +92,7 @@ import {useStorage} from '@vueuse/core'
import type {IProject} from '@/modelTypes/IProject'
import {PhCaretDown, PhDotsThree, PhDotsSix, PhFunnel, PhStar} from '@phosphor-icons/vue'
import BaseButton from '@/components/base/BaseButton.vue'
import ProjectSettingsDropdown from '@/components/project/ProjectSettingsDropdown.vue'
import {getProjectTitle} from '@/helpers/getProjectTitle'

View File

@ -14,21 +14,17 @@
'--button-white-space': wrap ? 'break-spaces' : 'nowrap',
}"
>
<template v-if="icon">
<Icon
v-if="!$slots.default"
:icon="icon"
:style="{color: iconColor}"
/>
<template v-if="$slots.icon">
<span
v-else
v-if="$slots.default"
class="icon is-small"
>
<Icon
:icon="icon"
:style="{color: iconColor}"
/>
<slot name="icon" />
</span>
<slot
v-else
name="icon"
/>
</template>
<span>
<slot />
@ -39,7 +35,6 @@
<script setup lang="ts">
import {computed} from 'vue'
import BaseButton from '@/components/base/BaseButton.vue'
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
const props = defineProps<ButtonProps>()
@ -53,8 +48,6 @@ export type ButtonTypes = keyof typeof VARIANT_CLASS_MAP
export interface ButtonProps {
variant?: ButtonTypes
icon?: IconProp
iconColor?: string
loading?: boolean
disabled?: boolean
shadow?: boolean
@ -64,7 +57,6 @@ export interface ButtonProps {
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 shadow = computed(() => (props.shadow ?? true) as boolean)
const wrap = computed(() => (props.wrap ?? true) as boolean)

View File

@ -4,7 +4,7 @@
class="datepicker__quick-select-date"
@click.stop="setDate('today')"
>
<span class="icon"><Icon :icon="['far', 'calendar-alt']" /></span>
<span class="icon"><PhCalendarBlank /></span>
<span class="text">
<span>{{ $t('input.datepicker.today') }}</span>
<span class="weekday">{{ getWeekdayFromStringInterval('today') }}</span>
@ -14,7 +14,7 @@
class="datepicker__quick-select-date"
@click.stop="setDate('tomorrow')"
>
<span class="icon"><Icon :icon="['far', 'sun']" /></span>
<span class="icon"><PhSun /></span>
<span class="text">
<span>{{ $t('input.datepicker.tomorrow') }}</span>
<span class="weekday">{{ getWeekdayFromStringInterval('tomorrow') }}</span>
@ -24,7 +24,7 @@
class="datepicker__quick-select-date"
@click.stop="setDate('nextMonday')"
>
<span class="icon"><Icon icon="coffee" /></span>
<span class="icon"><PhCoffee /></span>
<span class="text">
<span>{{ $t('input.datepicker.nextMonday') }}</span>
<span class="weekday">{{ getWeekdayFromStringInterval('nextMonday') }}</span>
@ -35,7 +35,7 @@
class="datepicker__quick-select-date"
@click.stop="setDate('thisWeekend')"
>
<span class="icon"><Icon icon="cocktail" /></span>
<span class="icon"><PhMartini /></span>
<span class="text">
<span>{{ $t('input.datepicker.thisWeekend') }}</span>
<span class="weekday">{{ getWeekdayFromStringInterval('thisWeekend') }}</span>
@ -45,7 +45,7 @@
class="datepicker__quick-select-date"
@click.stop="setDate('laterThisWeek')"
>
<span class="icon"><Icon icon="chess-knight" /></span>
<span class="icon"><PhHorse /></span>
<span class="text">
<span>{{ $t('input.datepicker.laterThisWeek') }}</span>
<span class="weekday">{{ getWeekdayFromStringInterval('laterThisWeek') }}</span>
@ -55,7 +55,7 @@
class="datepicker__quick-select-date"
@click.stop="setDate('nextWeek')"
>
<span class="icon"><Icon icon="forward" /></span>
<span class="icon"><PhFastForward /></span>
<span class="text">
<span>{{ $t('input.datepicker.nextWeek') }}</span>
<span class="weekday">{{ getWeekdayFromStringInterval('nextWeek') }}</span>
@ -77,6 +77,7 @@ import flatPickr from 'vue-flatpickr-component'
import 'flatpickr/dist/flatpickr.css'
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 {calculateDayInterval} from '@/helpers/time/calculateDayInterval'

View File

@ -62,7 +62,7 @@
class="removal-button"
@click="resetSelectedValue"
>
<Icon icon="times" />
<PhX />
</BaseButton>
</div>
</div>
@ -134,6 +134,7 @@ import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
import BaseButton from '@/components/base/BaseButton.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import {PhX} from '@phosphor-icons/vue'
const props = withDefaults(defineProps<{
/** The object with the value, updated every time an entry is selected */

View File

@ -20,7 +20,7 @@
:aria-label="passwordFieldType === 'password' ? $t('user.auth.showPassword') : $t('user.auth.hidePassword')"
@click="togglePasswordFieldType"
>
<Icon :icon="passwordFieldType === 'password' ? 'eye' : 'eye-slash'" />
<PhEye v-if="passwordFieldType === 'password'" /><PhEyeSlash v-else />
</BaseButton>
</div>
<p
@ -37,6 +37,7 @@ import {useDebounceFn} from '@vueuse/core'
import {useI18n} from 'vue-i18n'
import BaseButton from '@/components/base/BaseButton.vue'
import {validatePassword} from '@/helpers/validatePasswort'
import {PhEye, PhEyeSlash} from '@phosphor-icons/vue'
const props = withDefaults(defineProps<{
modelValue: string,

View File

@ -12,6 +12,7 @@ import CustomTransition from '@/components/misc/CustomTransition.vue'
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
import {useAuthStore} from '@/stores/auth'
import {useColorScheme} from '@/composables/useColorScheme'
import {PhSmiley} from '@phosphor-icons/vue'
const props = withDefaults(defineProps<{
entityKind: ReactionKind,
@ -167,7 +168,7 @@ async function toggleReaction(value: string | number) {
@click.stop="toggleEmojiPicker"
>
<span class="is-sr-only">{{ $t('reaction.add') }}</span>
<Icon :icon="['far', 'face-laugh']" />
<PhSmiley />
</BaseButton>
<CustomTransition name="fade">
<VuemojiPicker

View File

@ -8,7 +8,7 @@
:class="{ 'is-selected': index === selectedIndex }"
@click="selectItem(index)"
>
<Icon :icon="item.icon" />
<component :is="item.icon" />
<div class="description">
<p>{{ item.title }}</p>
<p>{{ item.description }}</p>
@ -27,10 +27,10 @@
<script lang="ts">
/* eslint-disable vue/component-api-style */
import type {PropType} from 'vue'
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
import type {Component} from 'vue'
interface CommandItem {
icon: IconProp
icon: Component
title: string
description: string
command: () => void

View File

@ -8,7 +8,7 @@
@click="editor.chain().focus().toggleHeading({ level: 1 }).run()"
>
<span class="icon">
<Icon :icon="['fas', 'header']" />
<PhTextH />
<span
class="icon__lower-text"
aria-hidden="true"
@ -23,7 +23,7 @@
@click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
>
<span class="icon">
<Icon :icon="['fas', 'header']" />
<PhTextH />
<span
class="icon__lower-text"
aria-hidden="true"
@ -38,7 +38,7 @@
@click="editor.chain().focus().toggleHeading({ level: 3 }).run()"
>
<span class="icon">
<Icon :icon="['fas', 'header']" />
<PhTextH />
<span
class="icon__lower-text"
aria-hidden="true"
@ -56,7 +56,7 @@
@click="editor.chain().focus().toggleBold().run()"
>
<span class="icon">
<Icon :icon="['fas', 'bold']" />
<PhTextB />
</span>
<span class="is-sr-only">{{ $t('input.editor.bold') }}</span>
</BaseButton>
@ -67,7 +67,7 @@
@click="editor.chain().focus().toggleItalic().run()"
>
<span class="icon">
<Icon :icon="['fas', 'italic']" />
<PhTextItalic />
</span>
<span class="is-sr-only">{{ $t('input.editor.italic') }}</span>
</BaseButton>
@ -78,7 +78,7 @@
@click="editor.chain().focus().toggleUnderline().run()"
>
<span class="icon">
<Icon :icon="['fas', 'underline']" />
<PhTextUnderline />
</span>
<span class="is-sr-only">{{ $t('input.editor.underline') }}</span>
</BaseButton>
@ -89,7 +89,7 @@
@click="editor.chain().focus().toggleStrike().run()"
>
<span class="icon">
<Icon :icon="['fas', 'strikethrough']" />
<PhTextStrikethrough />
</span>
<span class="is-sr-only">{{ $t('input.editor.strikethrough') }}</span>
</BaseButton>
@ -103,7 +103,7 @@
@click="editor.chain().focus().toggleCodeBlock().run()"
>
<span class="icon">
<Icon :icon="['fas', 'code']" />
<PhCode />
</span>
<span class="is-sr-only">{{ $t('input.editor.code') }}</span>
</BaseButton>
@ -114,7 +114,7 @@
@click="editor.chain().focus().toggleBlockquote().run()"
>
<span class="icon">
<Icon :icon="['fas', 'quote-right']" />
<PhQuotes />
</span>
<span class="is-sr-only">{{ $t('input.editor.quote') }}</span>
</BaseButton>
@ -128,7 +128,7 @@
@click="editor.chain().focus().toggleBulletList().run()"
>
<span class="icon">
<Icon :icon="['fas', 'list-ul']" />
<PhListBullets />
</span>
<span class="is-sr-only">{{ $t('input.editor.bulletList') }}</span>
</BaseButton>
@ -139,7 +139,7 @@
@click="editor.chain().focus().toggleOrderedList().run()"
>
<span class="icon">
<Icon :icon="['fas', 'list-ol']" />
<PhListNumbers />
</span>
<span class="is-sr-only">{{ $t('input.editor.orderedList') }}</span>
</BaseButton>
@ -150,7 +150,7 @@
@click="editor.chain().focus().toggleTaskList().run()"
>
<span class="icon">
<Icon icon="list-check" />
<PhListChecks />
</span>
<span class="is-sr-only">{{ $t('input.editor.taskList') }}</span>
</BaseButton>
@ -163,7 +163,7 @@
@click="e => emit('imageUploadClicked', e)"
>
<span class="icon">
<Icon icon="image" />
<PhImage />
</span>
<span class="is-sr-only">{{ $t('input.editor.image') }}</span>
</BaseButton>
@ -178,7 +178,7 @@
@click="setLink"
>
<span class="icon">
<Icon :icon="['fas', 'link']" />
<PhLink />
</span>
<span class="is-sr-only">{{ $t('input.editor.link') }}</span>
</BaseButton>
@ -190,7 +190,7 @@
@click="editor.chain().focus().setParagraph().run()"
>
<span class="icon">
<Icon :icon="['fas', 'paragraph']" />
<PhParagraph />
</span>
<span class="is-sr-only">{{ $t('input.editor.text') }}</span>
</BaseButton>
@ -201,7 +201,7 @@
@click="editor.chain().focus().setHorizontalRule().run()"
>
<span class="icon">
<Icon :icon="['fas', 'ruler-horizontal']" />
<PhRuler />
</span>
<span class="is-sr-only">{{ $t('input.editor.horizontalRule') }}</span>
</BaseButton>
@ -214,7 +214,7 @@
@click="editor.chain().focus().undo().run()"
>
<span class="icon">
<Icon :icon="['fas', 'undo']" />
<PhArrowCounterClockwise />
</span>
<span class="is-sr-only">{{ $t('input.editor.undo') }}</span>
</BaseButton>
@ -224,7 +224,7 @@
@click="editor.chain().focus().redo().run()"
>
<span class="icon">
<Icon :icon="['fas', 'redo']" />
<PhArrowClockwise />
</span>
<span class="is-sr-only">{{ $t('input.editor.redo') }}</span>
</BaseButton>
@ -239,7 +239,7 @@
@click="toggleTableMode"
>
<span class="icon">
<Icon :icon="['fas', 'table']" />
<PhTable />
</span>
<span class="is-sr-only">{{ $t('input.editor.table.title') }}</span>
</BaseButton>
@ -366,6 +366,13 @@
import {ref} from 'vue'
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 {setLinkInEditor} from '@/components/input/editor/setLinkInEditor'

View File

@ -23,7 +23,7 @@
:class="{ 'is-active': editor.isActive('bold') }"
@click="() => editor?.chain().focus().toggleBold().run()"
>
<Icon :icon="['fas', 'bold']" />
<PhTextB />
</BaseButton>
<BaseButton
v-tooltip="$t('input.editor.italic')"
@ -31,7 +31,7 @@
:class="{ 'is-active': editor.isActive('italic') }"
@click="() => editor?.chain().focus().toggleItalic().run()"
>
<Icon :icon="['fas', 'italic']" />
<PhTextItalic />
</BaseButton>
<BaseButton
v-tooltip="$t('input.editor.underline')"
@ -39,7 +39,7 @@
:class="{ 'is-active': editor.isActive('underline') }"
@click="() => editor?.chain().focus().toggleUnderline().run()"
>
<Icon :icon="['fas', 'underline']" />
<PhTextUnderline />
</BaseButton>
<BaseButton
v-tooltip="$t('input.editor.strikethrough')"
@ -47,7 +47,7 @@
:class="{ 'is-active': editor.isActive('strike') }"
@click="() => editor?.chain().focus().toggleStrike().run()"
>
<Icon :icon="['fas', 'strikethrough']" />
<PhTextStrikethrough />
</BaseButton>
<BaseButton
v-tooltip="$t('input.editor.code')"
@ -55,7 +55,7 @@
:class="{ 'is-active': editor.isActive('code') }"
@click="() => editor?.chain().focus().toggleCode().run()"
>
<Icon :icon="['fas', 'code']" />
<PhCode />
</BaseButton>
<BaseButton
v-tooltip="$t('input.editor.link')"
@ -63,7 +63,7 @@
:class="{ 'is-active': editor.isActive('link') }"
@click="setLink"
>
<Icon :icon="['fas', 'link']" />
<PhLink />
</BaseButton>
</div>
</BubbleMenu>
@ -146,6 +146,8 @@ import {computed, nextTick, onBeforeUnmount, onMounted, ref, watch} from 'vue'
import {useI18n} from 'vue-i18n'
import {eventToHotkeyString} from '@github/hotkey'
import {PhTextB, PhTextItalic, PhTextUnderline, PhTextStrikethrough, PhCode, PhLink} from '@phosphor-icons/vue'
import EditorToolbar from './EditorToolbar.vue'
import StarterKit from '@tiptap/starter-kit'

View File

@ -1,5 +1,9 @@
import type {Editor, Range} from '@tiptap/core'
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 CommandsList from './CommandsList.vue'
@ -21,7 +25,7 @@ export default function suggestionSetup(t: TranslateFunction) {
{
title: t('input.editor.text'),
description: t('input.editor.textTooltip'),
icon: 'fa-font',
icon: PhTextAa,
command: ({editor, range}: {editor: Editor, range: Range}) => {
editor
.chain()
@ -34,7 +38,7 @@ export default function suggestionSetup(t: TranslateFunction) {
{
title: t('input.editor.heading1'),
description: t('input.editor.heading1Tooltip'),
icon: 'fa-header',
icon: PhTextH,
command: ({editor, range}: {editor: Editor, range: Range}) => {
editor
.chain()
@ -47,7 +51,7 @@ export default function suggestionSetup(t: TranslateFunction) {
{
title: t('input.editor.heading2'),
description: t('input.editor.heading2Tooltip'),
icon: 'fa-header',
icon: PhTextH,
command: ({editor, range}: {editor: Editor, range: Range}) => {
editor
.chain()
@ -60,7 +64,7 @@ export default function suggestionSetup(t: TranslateFunction) {
{
title: t('input.editor.heading3'),
description: t('input.editor.heading3Tooltip'),
icon: 'fa-header',
icon: PhTextH,
command: ({editor, range}: {editor: Editor, range: Range}) => {
editor
.chain()
@ -73,7 +77,7 @@ export default function suggestionSetup(t: TranslateFunction) {
{
title: t('input.editor.bulletList'),
description: t('input.editor.bulletListTooltip'),
icon: 'fa-list-ul',
icon: PhListBullets,
command: ({editor, range}: {editor: Editor, range: Range}) => {
editor
.chain()
@ -86,7 +90,7 @@ export default function suggestionSetup(t: TranslateFunction) {
{
title: t('input.editor.orderedList'),
description: t('input.editor.orderedListTooltip'),
icon: 'fa-list-ol',
icon: PhListNumbers,
command: ({editor, range}: {editor: Editor, range: Range}) => {
editor
.chain()
@ -99,7 +103,7 @@ export default function suggestionSetup(t: TranslateFunction) {
{
title: t('input.editor.taskList'),
description: t('input.editor.taskListTooltip'),
icon: 'fa-list-check',
icon: PhListChecks,
command: ({editor, range}: {editor: Editor, range: Range}) => {
editor
.chain()
@ -112,7 +116,7 @@ export default function suggestionSetup(t: TranslateFunction) {
{
title: t('input.editor.quote'),
description: t('input.editor.quoteTooltip'),
icon: 'fa-quote-right',
icon: PhQuotes,
command: ({editor, range}: {editor: Editor, range: Range}) => {
editor
.chain()
@ -125,7 +129,7 @@ export default function suggestionSetup(t: TranslateFunction) {
{
title: t('input.editor.code'),
description: t('input.editor.codeTooltip'),
icon: 'fa-code',
icon: PhCode,
command: ({editor, range}: {editor: Editor, range: Range}) => {
editor
.chain()
@ -138,7 +142,7 @@ export default function suggestionSetup(t: TranslateFunction) {
{
title: t('input.editor.image'),
description: t('input.editor.imageTooltip'),
icon: 'fa-image',
icon: PhImage,
command: ({editor, range}: {editor: Editor, range: Range}) => {
editor
.chain()
@ -154,7 +158,7 @@ export default function suggestionSetup(t: TranslateFunction) {
{
title: t('input.editor.horizontalRule'),
description: t('input.editor.horizontalRuleTooltip'),
icon: 'fa-ruler-horizontal',
icon: PhRuler,
command: ({editor, range}: {editor: Editor, range: Range}) => {
editor
.chain()

View File

@ -17,7 +17,7 @@
@click="$emit('close')"
>
<span class="icon">
<Icon icon="times" />
<PhX />
</span>
</BaseButton>
</header>
@ -44,6 +44,7 @@
<script setup lang="ts">
import BaseButton from '@/components/base/BaseButton.vue'
import {PhX} from '@phosphor-icons/vue'
withDefaults(defineProps<{
title?: string

View File

@ -36,12 +36,19 @@
<XButton
v-if="hasPrimaryAction"
variant="primary"
:icon="primaryIcon"
:disabled="isBusy"
class="mis-2"
:loading="currentLoading"
@click.prevent.stop="primary"
>
<template
v-if="showPrimaryIcon"
#icon
>
<slot name="primary-icon">
<PhPlus />
</slot>
</template>
{{ primaryLabel || $t('misc.create') }}
</XButton>
</slot>
@ -51,14 +58,14 @@
</template>
<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'
const props = withDefaults(defineProps<{
title: string,
primaryLabel?: string,
primaryIcon?: IconProp,
showPrimaryIcon?: boolean,
primaryDisabled?: boolean,
hasPrimaryAction?: boolean,
tertiary?: string,
@ -66,7 +73,7 @@ const props = withDefaults(defineProps<{
loading?: boolean,
}>(), {
primaryLabel: '',
primaryIcon: 'plus',
showPrimaryIcon: true,
primaryDisabled: false,
hasPrimaryAction: true,
tertiary: '',

View File

@ -15,10 +15,7 @@
class="dropdown-trigger is-flex"
@click="toggleOpen"
>
<Icon
:icon="triggerIcon"
class="icon"
/>
<PhDotsThree class="icon" />
</BaseButton>
</slot>
@ -42,17 +39,11 @@
import {ref, nextTick, watch, computed} from 'vue'
import {onClickOutside} from '@vueuse/core'
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 BaseButton from '@/components/base/BaseButton.vue'
withDefaults(defineProps<{
triggerIcon?: IconProp
}>(), {
triggerIcon: 'ellipsis-h',
})
const emit = defineEmits<{
'close': [event: PointerEvent]
}>()

View File

@ -5,11 +5,11 @@
:class="{'is-disabled': disabled}"
>
<span
v-if="icon"
v-if="$slots.icon"
class="icon is-small"
:class="iconClass"
>
<Icon :icon="icon" />
<slot name="icon" />
</span>
<span>
<slot />
@ -18,12 +18,9 @@
</template>
<script lang="ts" setup>
import BaseButton, {type BaseButtonProps} from '@/components/base//BaseButton.vue'
import Icon from '@/components/misc/Icon'
import type {IconProp} from '@fortawesome/fontawesome-svg-core'
import BaseButton, {type BaseButtonProps} from '@/components/base/BaseButton.vue'
export interface DropDownItemProps extends /* @vue-ignore */ BaseButtonProps {
icon?: IconProp,
iconClass?: object | string,
disabled?: boolean,
}

View File

@ -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

View File

@ -24,7 +24,7 @@
class="close"
@click="$emit('close')"
>
<Icon icon="times" />
<PhX />
</BaseButton>
<div
class="modal-content"
@ -68,6 +68,7 @@
<script lang="ts" setup>
import CustomTransition from '@/components/misc/CustomTransition.vue'
import BaseButton from '@/components/base/BaseButton.vue'
import {PhX} from '@phosphor-icons/vue'
import {ref, useAttrs, watchEffect, onBeforeUnmount, watch} from 'vue'
import {useScrollLock} from '@vueuse/core'

View File

@ -1,5 +1,6 @@
<script setup lang="ts">
import BaseButton from '@/components/base/BaseButton.vue'
import {PhMagnifyingGlass} from '@phosphor-icons/vue'
import {useBaseStore} from '@/stores/base'
import {onBeforeUnmount, onMounted} from 'vue'
import {eventToHotkeyString} from '@github/hotkey'
@ -40,6 +41,6 @@ function openQuickActions() {
:title="$t('keyboardShortcuts.quickSearch')"
@click="openQuickActions"
>
<Icon icon="search" />
<PhMagnifyingGlass />
</BaseButton>
</template>

View File

@ -3,19 +3,23 @@
v-if="type === 'button'"
v-tooltip="tooltipText"
variant="secondary"
:icon="iconName"
:disabled="disabled"
@click="changeSubscription"
>
<template #icon>
<component :is="iconComponent" />
</template>
{{ buttonText }}
</XButton>
<DropdownItem
v-else-if="type === 'dropdown'"
v-tooltip="tooltipText"
:disabled="disabled"
:icon="iconName"
@click="changeSubscription"
>
<template #icon>
<component :is="iconComponent" />
</template>
{{ buttonText }}
</DropdownItem>
<BaseButton
@ -26,7 +30,7 @@
@click="changeSubscription"
>
<span class="icon">
<Icon :icon="iconName" />
<component :is="iconComponent" />
</span>
{{ buttonText }}
</BaseButton>
@ -44,7 +48,7 @@ import SubscriptionModel from '@/models/subscription'
import type {ISubscription} from '@/modelTypes/ISubscription'
import {success} from '@/message'
import type { IconProp } from '@fortawesome/fontawesome-svg-core'
import {PhBell, PhBellSlash} from '@phosphor-icons/vue'
const props = withDefaults(defineProps<{
modelValue: ISubscription | null,
@ -91,7 +95,7 @@ const tooltipText = computed(() => {
})
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)
function changeSubscription() {

View File

@ -14,7 +14,7 @@
v-if="unreadNotifications > 0"
class="unread-indicator"
/>
<Icon icon="bell" />
<PhBell />
</BaseButton>
</slot>
@ -87,6 +87,7 @@
<script lang="ts" setup>
import {computed, onMounted, onUnmounted, ref} from 'vue'
import {PhBell} from '@phosphor-icons/vue'
import {useRouter} from 'vue-router'
import NotificationService from '@/services/notification'

View File

@ -10,10 +10,7 @@
@click="triggerProps.toggleOpen"
>
<span class="is-sr-only">{{ $t('project.openSettingsMenu') }}</span>
<Icon
icon="ellipsis-h"
class="icon"
/>
<PhDotsThree class="icon" />
</BaseButton>
</slot>
</template>
@ -21,21 +18,27 @@
<template v-if="isSavedFilter(project)">
<DropdownItem
:to="{ name: 'filter.settings.edit', params: { projectId: project.id } }"
icon="pen"
>
<template #icon>
<PhPen />
</template>
{{ $t('menu.edit') }}
</DropdownItem>
<DropdownItem
:to="{ name: 'project.settings.views', params: { projectId: project.id } }"
icon="eye"
>
<template #icon>
<PhEye />
</template>
{{ $t('menu.views') }}
</DropdownItem>
<DropdownItem
:to="{ name: 'filter.settings.delete', params: { projectId: project.id } }"
icon="trash-alt"
class="has-text-danger"
>
<template #icon>
<PhTrash />
</template>
{{ $t('misc.delete') }}
</DropdownItem>
</template>
@ -43,51 +46,65 @@
<template v-else-if="project.isArchived">
<DropdownItem
:to="{ name: 'project.settings.archive', params: { projectId: project.id } }"
icon="archive"
>
<template #icon>
<PhArchive />
</template>
{{ $t('menu.unarchive') }}
</DropdownItem>
</template>
<template v-else>
<DropdownItem
:to="{ name: 'project.settings.edit', params: { projectId: project.id } }"
icon="pen"
>
<template #icon>
<PhPen />
</template>
{{ $t('menu.edit') }}
</DropdownItem>
<DropdownItem
v-if="!simple"
:to="{ name: 'project.settings.views', params: { projectId: project.id } }"
icon="eye"
>
<template #icon>
<PhEye />
</template>
{{ $t('menu.views') }}
</DropdownItem>
<DropdownItem
v-if="backgroundsEnabled && !simple"
:to="{ name: 'project.settings.background', params: { projectId: project.id } }"
icon="image"
>
<template #icon>
<PhImage />
</template>
{{ $t('menu.setBackground') }}
</DropdownItem>
<DropdownItem
:to="{ name: 'project.settings.share', params: { projectId: project.id } }"
icon="share-alt"
>
<template #icon>
<PhShareNetwork />
</template>
{{ $t('menu.share') }}
</DropdownItem>
<DropdownItem
:to="{ name: 'project.settings.duplicate', params: { projectId: project.id } }"
icon="paste"
>
<template #icon>
<PhClipboard />
</template>
{{ $t('menu.duplicate') }}
</DropdownItem>
<DropdownItem
v-if="!simple"
v-tooltip="isDefaultProject ? $t('menu.cantArchiveIsDefault') : ''"
:to="{ name: 'project.settings.archive', params: { projectId: project.id } }"
icon="archive"
:disabled="isDefaultProject"
>
<template #icon>
<PhArchive />
</template>
{{ $t('menu.archive') }}
</DropdownItem>
<Subscription
@ -101,24 +118,30 @@
/>
<DropdownItem
:to="{ name: 'project.settings.webhooks', params: { projectId: project.id } }"
icon="bolt"
>
<template #icon>
<PhLightning />
</template>
{{ $t('project.webhooks.title') }}
</DropdownItem>
<DropdownItem
:to="{ name: 'project.createFromParent', params: { parentProjectId: project.id } }"
icon="layer-group"
>
<template #icon>
<PhStack />
</template>
{{ $t('menu.createProject') }}
</DropdownItem>
<DropdownItem
v-if="project.maxPermission === PERMISSIONS.ADMIN"
v-tooltip="isDefaultProject ? $t('menu.cantDeleteIsDefault') : ''"
:to="{ name: 'project.settings.delete', params: { projectId: project.id } }"
icon="trash-alt"
class="has-text-danger"
:disabled="isDefaultProject"
>
<template #icon>
<PhTrash />
</template>
{{ $t('menu.delete') }}
</DropdownItem>
</template>
@ -140,6 +163,7 @@ import {useConfigStore} from '@/stores/config'
import {useProjectStore} from '@/stores/projects'
import {useAuthStore} from '@/stores/auth'
import {PERMISSIONS} from '@/constants/permissions'
import {PhDotsThree, PhPen, PhEye, PhTrash, PhArchive, PhImage, PhShareNetwork, PhClipboard, PhLightning, PhStack} from '@phosphor-icons/vue'
const props = withDefaults(defineProps<{
project: IProject

View File

@ -1,10 +1,12 @@
<template>
<XButton
variant="secondary"
icon="filter"
:class="{'has-filters': hasFilters}"
@click="() => modalOpen = true"
>
<template #icon>
<PhFunnel />
</template>
{{ $t('filters.title') }}
</XButton>
<Modal
@ -32,6 +34,7 @@
import {computed, ref, watch, nextTick} from 'vue'
import Filters from '@/components/project/partials/Filters.vue'
import {PhFunnel} from '@phosphor-icons/vue'
import {type TaskFilterParams} from '@/services/taskCollection'
import {type IProjectView} from '@/modelTypes/IProjectView'

View File

@ -28,7 +28,7 @@
v-if="project.id < -1"
class="saved-filter-icon icon"
>
<Icon icon="filter" />
<PhFunnel />
</span>
{{ getProjectTitle(project) }}
</div>
@ -47,7 +47,7 @@
:class="{'is-favorite': project.isFavorite}"
@click.prevent.stop="projectStore.toggleProjectFavorite(project)"
>
<Icon :icon="project.isFavorite ? 'star' : ['far', 'star']" />
<PhStar :weight="project.isFavorite ? 'fill' : 'regular'" />
</BaseButton>
</div>
</template>
@ -57,6 +57,7 @@ import {computed} from 'vue'
import type {IProject} from '@/modelTypes/IProject'
import BaseButton from '@/components/base/BaseButton.vue'
import {PhFunnel, PhStar} from '@phosphor-icons/vue'
import {useProjectBackground} from '@/composables/useProjectBackground'
import {useProjectStore} from '@/stores/projects'

View File

@ -50,7 +50,7 @@
class="icon is-small has-text-success mie-2"
@click.stop="() => collapseBucket(bucket)"
>
<Icon icon="check-double" />
<PhChecks />
</span>
<h2
class="title input"
@ -73,9 +73,13 @@
<Dropdown
v-if="canWrite && !collapsedBuckets[bucket.id]"
class="is-right options"
trigger-icon="ellipsis-v"
@close="() => showSetLimitInput = false"
>
<template #trigger="tp">
<BaseButton @click="tp.toggleOpen">
<PhDotsThreeVertical class="icon" />
</BaseButton>
</template>
<div
v-if="showSetLimitInput"
class="field has-addons"
@ -97,10 +101,13 @@
<XButton
v-cy="'setBucketLimit'"
:disabled="bucket.limit < 0"
:icon="['far', 'save']"
:shadow="false"
@click="() => {setBucketLimit(bucket.id, true); showSetLimitInput = false}"
/>
>
<template #icon>
<PhFloppyDisk />
</template>
</XButton>
</div>
</div>
<DropdownItem
@ -114,23 +121,29 @@
<DropdownItem
v-tooltip="$t('project.kanban.doneBucketHintExtended')"
:icon-class="{'has-text-success': bucket.id === view?.doneBucketId}"
icon="check-double"
@click.stop="toggleDoneBucket(bucket)"
>
<template #icon>
<PhChecks />
</template>
{{ $t('project.kanban.doneBucket') }}
</DropdownItem>
<DropdownItem
v-tooltip="$t('project.kanban.defaultBucketHint')"
:icon-class="{'has-text-primary': bucket.id === view?.defaultBucketId}"
icon="th"
@click.stop="toggleDefaultBucket(bucket)"
>
<template #icon>
<PhSquaresFour />
</template>
{{ $t('project.kanban.defaultBucket') }}
</DropdownItem>
<DropdownItem
icon="angles-up"
@click.stop="() => collapseBucket(bucket)"
>
<template #icon>
<PhCaretDoubleUp />
</template>
{{ $t('project.kanban.collapse') }}
</DropdownItem>
<DropdownItem
@ -138,9 +151,11 @@
class="has-text-danger"
:class="{'is-disabled': buckets.length <= 1}"
icon-class="has-text-danger"
icon="trash-alt"
@click.stop="() => deleteBucketModal(bucket.id)"
>
<template #icon>
<PhTrash />
</template>
{{ $t('misc.delete') }}
</DropdownItem>
</Dropdown>
@ -197,11 +212,13 @@
v-tooltip="bucket.limit > 0 && bucket.count >= bucket.limit ? $t('project.kanban.bucketLimitReached') : ''"
class="is-fullwidth has-text-centered"
:shadow="false"
icon="plus"
variant="secondary"
:disabled="bucket.limit > 0 && bucket.count >= bucket.limit"
@click="toggleShowNewTaskInput(bucket.id)"
>
<template #icon>
<PhPlus />
</template>
{{
bucket.tasks.length === 0 ? $t('project.kanban.addTask') : $t('project.kanban.addAnotherTask')
}}
@ -250,9 +267,11 @@
:shadow="false"
class="is-transparent is-fullwidth has-text-centered"
variant="secondary"
icon="plus"
@click="() => showNewBucketInput = true"
>
<template #icon>
<PhPlus />
</template>
{{ $t('project.kanban.addBucket') }}
</XButton>
</div>
@ -300,8 +319,10 @@ import {useAuthStore} from '@/stores/auth'
import ProjectWrapper from '@/components/project/ProjectWrapper.vue'
import FilterPopup from '@/components/project/partials/FilterPopup.vue'
import KanbanCard from '@/components/tasks/partials/KanbanCard.vue'
import BaseButton from '@/components/base/BaseButton.vue'
import Dropdown from '@/components/misc/Dropdown.vue'
import DropdownItem from '@/components/misc/DropdownItem.vue'
import {PhChecks, PhDotsThreeVertical, PhFloppyDisk, PhSquaresFour, PhCaretDoubleUp, PhTrash, PhPlus} from '@phosphor-icons/vue'
import {
type CollapsedBuckets,

View File

@ -10,11 +10,13 @@
<Popup>
<template #trigger="{toggle}">
<XButton
icon="th"
variant="secondary"
class="mie-2"
@click.prevent.stop="toggle()"
>
<template #icon>
<PhSquaresFour />
</template>
{{ $t('project.table.columns') }}
</XButton>
</template>
@ -316,6 +318,7 @@ import Sort from '@/components/tasks/partials/Sort.vue'
import FilterPopup from '@/components/project/partials/FilterPopup.vue'
import Pagination from '@/components/misc/Pagination.vue'
import Popup from '@/components/misc/Popup.vue'
import {PhSquaresFour} from '@phosphor-icons/vue'
import type {SortBy} from '@/composables/useTaskList'
import {useTaskList} from '@/composables/useTaskList'

View File

@ -12,6 +12,7 @@ import XButton from '@/components/input/Button.vue'
import FilterInputDocs from '@/components/input/filter/FilterInputDocs.vue'
import FilterInput from '@/components/input/filter/FilterInput.vue'
import FormField from '@/components/input/FormField.vue'
import {PhTrash, PhPlus} from '@phosphor-icons/vue'
const props = withDefaults(defineProps<{
modelValue: IProjectView,
@ -225,7 +226,7 @@ function handleBubbleSave() {
class="is-danger"
@click.prevent="() => view.bucketConfiguration.splice(index, 1)"
>
<Icon icon="trash-alt" />
<PhTrash />
</button>
<div class="filter-bucket-form">
<FormField
@ -250,9 +251,11 @@ function handleBubbleSave() {
<div class="is-flex is-justify-content-end">
<XButton
variant="secondary"
icon="plus"
@click="() => view.bucketConfiguration.push({title: '', filter: {filter: ''}})"
>
<template #icon>
<PhPlus />
</template>
{{ $t('project.kanban.addBucket') }}
</XButton>
</div>

View File

@ -32,7 +32,7 @@
class="close"
@click="closeQuickActions"
>
<Icon icon="times" />
<PhX />
</BaseButton>
</div>
@ -84,7 +84,7 @@
v-if="i.id < -1"
class="saved-filter-icon icon"
>
<Icon icon="filter" />
<PhFunnel />
</span>
{{ i.title }}
</template>
@ -98,6 +98,7 @@
<script setup lang="ts">
import {type ComponentPublicInstance, computed, ref, shallowReactive, watchEffect} from 'vue'
import {PhX, PhFunnel} from '@phosphor-icons/vue'
import {useI18n} from 'vue-i18n'
import {useRouter} from 'vue-router'

View File

@ -13,10 +13,12 @@
<div class="sharables-project">
<XButton
v-if="!showNewForm"
icon="plus"
class="mbe-4"
@click="showNewForm = true"
>
<template #icon>
<PhPlus />
</template>
{{ $t('project.share.links.create') }}
</XButton>
@ -60,9 +62,11 @@
:placeholder="$t('user.auth.passwordPlaceholder')"
/>
<XButton
icon="plus"
@click="add(projectId)"
>
<template #icon>
<PhPlus />
</template>
{{ $t('project.share.share') }}
</XButton>
</div>
@ -105,19 +109,19 @@
<p class="mbe-2">
<template v-if="s.permission === PERMISSIONS.ADMIN">
<span class="icon is-small">
<Icon icon="lock" />
<PhLock />
</span>&nbsp;
{{ $t('project.share.permission.admin') }}
</template>
<template v-else-if="s.permission === PERMISSIONS.READ_WRITE">
<span class="icon is-small">
<Icon icon="pen" />
<PhPen />
</span>&nbsp;
{{ $t('project.share.permission.readWrite') }}
</template>
<template v-else>
<span class="icon is-small">
<Icon icon="users" />
<PhUsers />
</span>&nbsp;
{{ $t('project.share.permission.read') }}
</template>
@ -135,7 +139,7 @@
@click="copy(shareLinks[s.id])"
>
<span class="icon">
<Icon icon="paste" />
<PhClipboard />
</span>
</XButton>
</template>
@ -157,14 +161,17 @@
<td class="actions">
<XButton
danger
icon="trash-alt"
@click="
() => {
linkIdToDelete = s.id
showDeleteModal = true
}
"
/>
>
<template #icon>
<PhTrash />
</template>
</XButton>
</td>
</tr>
</tbody>
@ -189,6 +196,7 @@
<script setup lang="ts">
import {ref, watch, computed, shallowReactive} from 'vue'
import {PhLock, PhPen, PhUsers, PhClipboard, PhPlus, PhTrash} from '@phosphor-icons/vue'
import {useI18n} from 'vue-i18n'
import {PERMISSIONS} from '@/constants/permissions'

View File

@ -73,19 +73,19 @@
<td class="type">
<template v-if="s.permission === PERMISSIONS.ADMIN">
<span class="icon is-small">
<Icon icon="lock" />
<PhLock />
</span>
{{ $t('project.share.permission.admin') }}
</template>
<template v-else-if="s.permission === PERMISSIONS.READ_WRITE">
<span class="icon is-small">
<Icon icon="pen" />
<PhPen />
</span>
{{ $t('project.share.permission.readWrite') }}
</template>
<template v-else>
<span class="icon is-small">
<Icon icon="users" />
<PhUsers />
</span>
{{ $t('project.share.permission.read') }}
</template>
@ -122,14 +122,17 @@
</div>
<XButton
danger
icon="trash-alt"
@click="
() => {
sharable = s
showDeleteModal = true
}
"
/>
>
<template #icon>
<PhTrash />
</template>
</XButton>
</td>
</tr>
</tbody>
@ -159,6 +162,7 @@
<script setup lang="ts">
import {ref, reactive, computed, shallowReactive, type Ref} from 'vue'
import {PhLock, PhPen, PhUsers, PhTrash} from '@phosphor-icons/vue'
import {useI18n} from 'vue-i18n'
import UserProjectService from '@/services/userProject'

View File

@ -12,7 +12,7 @@
{{ $t('project.list.addPlaceholder') }}
</label>
<span class="icon is-small task-icon">
<Icon icon="tasks" />
<PhListChecks />
</span>
<textarea
:id="textareaId"
@ -34,11 +34,13 @@
<XButton
class="add-task-button"
:disabled="newTaskTitle === '' || loading || undefined"
icon="plus"
:loading="loading"
:aria-label="$t('project.list.add')"
@click="addTask()"
>
<template #icon>
<PhPlus />
</template>
<span class="button-text">
{{ $t('project.list.add') }}
</span>
@ -78,6 +80,7 @@ import {useTaskStore} from '@/stores/tasks'
import {useAutoHeightTextarea} from '@/composables/useAutoHeightTextarea'
import TaskService from '@/services/task'
import TaskModel from '@/models/task'
import {PhListChecks, PhPlus} from '@phosphor-icons/vue'
const props = withDefaults(defineProps<{
defaultPosition?: number,

View File

@ -16,9 +16,11 @@
</CustomTransition>
<XButton
:shadow="false"
icon="plus"
@click="showCreateTaskOrCreate"
>
<template #icon>
<PhPlus />
</template>
{{ $t('task.new') }}
</XButton>
</form>
@ -29,6 +31,7 @@ import {nextTick, ref} from 'vue'
import type {ITask} from '@/modelTypes/ITask'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import {PhPlus} from '@phosphor-icons/vue'
const emit = defineEmits<{
(e: 'createTask', title: string): Promise<ITask>

View File

@ -1,5 +1,6 @@
<script setup lang="ts">
import type {IUser} from '@/modelTypes/IUser'
import {PhX} from '@phosphor-icons/vue'
import BaseButton from '@/components/base/BaseButton.vue'
import User from '@/components/misc/User.vue'
@ -44,7 +45,7 @@ defineEmits<{
class="remove-assignee"
@click="$emit('remove', user)"
>
<Icon icon="times" />
<PhX />
</BaseButton>
</span>
</div>

View File

@ -2,7 +2,7 @@
<div class="attachments">
<h3>
<span class="icon is-grey">
<Icon icon="paperclip" />
<PhPaperclip />
</span>
{{ $t('task.attachment.title') }}
</h3>
@ -77,14 +77,14 @@
class="attachment-info-meta-button"
@click.prevent.stop="downloadAttachment(a)"
>
<Icon icon="download" />
<PhDownload />
</BaseButton>
<BaseButton
v-tooltip="$t('task.attachment.copyUrlTooltip')"
class="attachment-info-meta-button"
@click.stop="copyUrl(a)"
>
<Icon icon="copy" />
<PhCopy />
</BaseButton>
<BaseButton
v-if="editEnabled"
@ -92,7 +92,7 @@
class="attachment-info-meta-button"
@click.prevent.stop="setAttachmentToDelete(a)"
>
<Icon icon="trash-alt" />
<PhTrash />
</BaseButton>
<BaseButton
v-if="editEnabled && canPreview(a)"
@ -102,7 +102,8 @@
class="attachment-info-meta-button"
@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>
</p>
</div>
@ -114,11 +115,13 @@
v-if="editEnabled"
:disabled="loading"
class="mbe-4"
icon="cloud-upload-alt"
variant="secondary"
:shadow="false"
@click="filesRef?.click()"
>
<template #icon>
<PhCloudArrowUp />
</template>
{{ $t('task.attachment.upload') }}
</XButton>
@ -131,7 +134,7 @@
>
<div class="drop-hint">
<div class="icon">
<Icon icon="cloud-upload-alt" />
<PhCloudArrowUp />
</div>
<div class="hint">
{{ $t('task.attachment.drop') }}
@ -174,6 +177,7 @@
<script setup lang="ts">
import {ref, shallowReactive, computed, watch} from 'vue'
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 ProgressBar from '@/components/misc/ProgressBar.vue'

View File

@ -5,7 +5,7 @@
class="comment-count"
:class="{'is-unread': task.isUnread}"
>
<Icon :icon="['far', 'comments']" />
<PhChats />
<span class="comment-count-badge">{{ task.commentCount }}</span>
<span
v-if="task.isUnread"
@ -17,6 +17,7 @@
<script setup lang="ts">
import {computed} from 'vue'
import {useI18n} from 'vue-i18n'
import {PhChats} from '@phosphor-icons/vue'
import type {ITask} from '@/modelTypes/ITask'

View File

@ -11,7 +11,7 @@
>
<span>
<span class="icon is-grey">
<Icon :icon="['far', 'comments']" />
<PhChats />
</span>
{{ $t('task.comment.title') }}
</span>
@ -20,7 +20,8 @@
class="comment-sort-button"
@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') }}
</BaseButton>
</h3>
@ -80,7 +81,7 @@
@click.prevent.stop="copy(getCommentUrl(`${c.id}`))"
>
<span class="is-sr-only">{{ $t('task.comment.permalink') }}</span>
<Icon icon="link" />
<PhLink />
</a>
<CustomTransition name="fade">
<span
@ -224,6 +225,7 @@
<script setup lang="ts">
import {ref, reactive, computed, shallowReactive, watch} from 'vue'
import {useI18n} from 'vue-i18n'
import {PhChats, PhLink, PhSortAscending, PhSortDescending} from '@phosphor-icons/vue'
import BaseButton from '@/components/base/BaseButton.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'

View File

@ -2,7 +2,7 @@
<div>
<h3>
<span class="icon is-grey">
<Icon icon="align-left" />
<PhTextAlignLeft />
</span>
{{ $t('task.attributes.description') }}
<CustomTransition name="fade">
@ -17,7 +17,7 @@
v-else-if="!loading && saved"
class="is-small has-text-success"
>
<Icon icon="check" />
<PhCheck />
{{ $t('misc.saved') }}
</span>
</CustomTransition>
@ -43,6 +43,7 @@
<script setup lang="ts">
import {ref, computed, watchEffect, onBeforeUnmount} from 'vue'
import {onBeforeRouteLeave} from 'vue-router'
import {PhTextAlignLeft, PhCheck} from '@phosphor-icons/vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import Editor from '@/components/input/AsyncEditor'

View File

@ -11,15 +11,13 @@
v-else
class="icon-wrapper"
>
<Icon
size="6x"
icon="file"
/>
<PhFile size="6em" />
</div>
</template>
<script setup lang="ts">
import {ref, shallowReactive, watchEffect} from 'vue'
import {PhFile} from '@phosphor-icons/vue'
import AttachmentService, {PREVIEW_SIZE} from '@/services/attachment'
import type {IAttachment} from '@/modelTypes/IAttachment'
import {canPreview} from '@/models/attachment'

View File

@ -20,7 +20,7 @@
class="close"
@click="$emit('close')"
>
<Icon icon="times" />
<PhX />
</BaseButton>
</div>
<h1
@ -40,7 +40,7 @@
class="close"
@click="$emit('close')"
>
<Icon icon="times" />
<PhX />
</BaseButton>
<CustomTransition name="fade">
<span
@ -54,10 +54,7 @@
v-else-if="!loading && showSavedMessage"
class="has-text-success is-inline-flex is-align-content-center"
>
<Icon
icon="check"
class="mie-2"
/>
<PhCheck class="mie-2" />
{{ $t('misc.saved') }}
</span>
</CustomTransition>
@ -67,6 +64,7 @@
<script setup lang="ts">
import {ref, computed, onMounted, onBeforeUnmount, watch} from 'vue'
import {useRouter} from 'vue-router'
import {PhX, PhCheck} from '@phosphor-icons/vue'
import BaseButton from '@/components/base/BaseButton.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'

View File

@ -48,7 +48,7 @@
class="due-date"
>
<span class="icon">
<Icon :icon="['far', 'calendar-alt']" />
<PhCalendarBlank />
</span>
<time :datetime="formatISO(task.dueDate)">
{{ formatDisplayDate(task.dueDate) }}
@ -81,19 +81,19 @@
v-if="task.attachments.length > 0"
class="icon"
>
<Icon icon="paperclip" />
<PhPaperclip />
</span>
<span
v-if="!isEditorContentEmpty(task.description)"
class="icon"
>
<Icon icon="align-left" />
<PhTextAlignLeft />
</span>
<span
v-if="task.repeatAfter.amount > 0"
class="icon"
>
<Icon icon="history" />
<PhClockCounterClockwise />
</span>
<CommentCount
:task="task"
@ -116,6 +116,7 @@
<script lang="ts" setup>
import {computed, ref, watch} from 'vue'
import {useRouter} from 'vue-router'
import {PhCalendarBlank, PhPaperclip, PhTextAlignLeft, PhClockCounterClockwise} from '@phosphor-icons/vue'
import {useGlobalNow} from '@/composables/useGlobalNow'

View File

@ -9,13 +9,11 @@
class="priority-label"
>
<span class="icon">
<Icon
<PhWarningCircle
v-if="priority >= priorities.HIGH"
icon="exclamation-circle"
/>
<Icon
<PhWarning
v-else
icon="exclamation"
/>
</span>
<span>
@ -31,6 +29,7 @@
<script setup lang="ts">
import {computed} from 'vue'
import {PhWarningCircle, PhWarning} from '@phosphor-icons/vue'
import {PRIORITIES as priorities} from '@/constants/priorities'
import {useAuthStore} from '@/stores/auth'

View File

@ -7,7 +7,7 @@
:class="{'is-highlighted': highlightHintIcon}"
@click="() => visible = true"
>
<Icon :icon="['far', 'circle-question']" />
<PhQuestion />
</BaseButton>
<Modal
:enabled="visible"
@ -101,6 +101,7 @@
<script setup lang="ts">
import {ref, computed} from 'vue'
import {PhQuestion} from '@phosphor-icons/vue'
import BaseButton from '@/components/base/BaseButton.vue'

View File

@ -7,10 +7,13 @@
class="is-pulled-right add-task-relation-button d-print-none"
:class="{'is-active': showNewRelationForm}"
variant="secondary"
icon="plus"
:shadow="false"
@click="showNewRelationForm = !showNewRelationForm"
/>
>
<template #icon>
<PhPlus />
</template>
</XButton>
<transition-group name="fade">
<template v-if="editEnabled && showCreate">
<label
@ -151,7 +154,7 @@
otherTaskId: task.id
})"
>
<Icon icon="trash-alt" />
<PhTrash />
</BaseButton>
</div>
</div>
@ -186,6 +189,7 @@
import {ref, reactive, shallowReactive, watch, computed} from 'vue'
import {useI18n} from 'vue-i18n'
import {useRoute} from 'vue-router'
import {PhPlus, PhTrash} from '@phosphor-icons/vue'
import TaskService from '@/services/task'
import TaskModel from '@/models/task'

View File

@ -18,7 +18,7 @@
class="remove"
@click="removeReminderByIndex(index)"
>
<Icon icon="times" />
<PhX />
</BaseButton>
</div>
@ -33,6 +33,7 @@
<script setup lang="ts">
import {ref, watch, computed} from 'vue'
import {PhX} from '@phosphor-icons/vue'
import type {ITaskReminder} from '@/modelTypes/ITaskReminder'

View File

@ -111,19 +111,19 @@
v-if="task.attachments.length > 0"
class="project-task-icon"
>
<Icon icon="paperclip" />
<PhPaperclip />
</span>
<span
v-if="!isEditorContentEmpty(task.description)"
class="project-task-icon is-mirrored-rtl"
>
<Icon icon="align-left" />
<PhTextAlignLeft />
</span>
<span
v-if="isRepeating"
class="project-task-icon"
>
<Icon icon="history" />
<PhClockCounterClockwise />
</span>
<CommentCount
:task="task"
@ -162,14 +162,7 @@
@click.stop="toggleFavorite"
>
<span class="is-sr-only">{{ task.isFavorite ? $t('task.detail.actions.unfavorite') : $t('task.detail.actions.favorite') }}</span>
<Icon
v-if="task.isFavorite"
icon="star"
/>
<Icon
v-else
:icon="['far', 'star']"
/>
<PhStar :weight="task.isFavorite ? 'fill' : 'regular'" />
</BaseButton>
<slot />
</div>
@ -193,6 +186,7 @@
<script setup lang="ts">
import {ref, watch, shallowReactive, onMounted, computed} from 'vue'
import {useI18n} from 'vue-i18n'
import {PhPaperclip, PhTextAlignLeft, PhClockCounterClockwise, PhStar} from '@phosphor-icons/vue'
import TaskModel, {getHexColor} from '@/models/task'
import type {ITask} from '@/modelTypes/ITask'

View File

@ -67,19 +67,19 @@
v-if="task.attachments.length > 0"
class="project-task-icon"
>
<Icon icon="paperclip" />
<PhPaperclip />
</span>
<span
v-if="task.description"
class="project-task-icon"
>
<Icon icon="align-left" />
<PhTextAlignLeft />
</span>
<span
v-if="task.repeatAfter.amount > 0"
class="project-task-icon"
>
<Icon icon="history" />
<PhClockCounterClockwise />
</span>
</span>
@ -98,6 +98,7 @@
<script setup lang="ts">
import {computed} from 'vue'
import {PhPaperclip, PhTextAlignLeft, PhClockCounterClockwise} from '@phosphor-icons/vue'
import {getHexColor} from '@/models/task'
import type {ITask} from '@/modelTypes/ITask'

View File

@ -1,25 +1,22 @@
<template>
<BaseButton>
<Icon
<PhSortAscending
v-if="order === 'asc'"
icon="sort-up"
class="sort__icon"
/>
<Icon
<PhSortDescending
v-else-if="order === 'desc'"
icon="sort-up"
rotation="180"
class="sort__icon"
/>
<Icon
<PhArrowsDownUp
v-else
icon="sort"
class="sort__icon"
/>
</BaseButton>
</template>
<script setup lang="ts">
import {PhSortAscending, PhSortDescending, PhArrowsDownUp} from '@phosphor-icons/vue'
import BaseButton from '@/components/base/BaseButton.vue'
withDefaults(defineProps<{

View File

@ -27,7 +27,7 @@
v-if="task.attachments.length > 0"
class="task-glance-icon"
>
<Icon icon="paperclip" />
<PhPaperclip />
</span>
<CommentCount
:task="task"
@ -58,7 +58,7 @@
v-if="task.dueDate"
class="task-glance-due"
>
<Icon icon="calendar" />
<PhCalendarBlank />
<span>{{ $t('task.detail.due', {at: formatDisplayDate(task.dueDate)}) }}</span>
</div>
@ -82,6 +82,7 @@
<script setup lang="ts">
import {ref, computed, onUnmounted, nextTick} from 'vue'
import {computePosition, flip, offset, shift} from '@floating-ui/dom'
import {PhPaperclip, PhCalendarBlank} from '@phosphor-icons/vue'
import type {ITask} from '@/modelTypes/ITask'
import {getTaskIdentifier} from '@/models/task'

View File

@ -8,7 +8,6 @@ import {createPinia} from 'pinia'
import testid from '@/directives/testid'
import FontAwesomeIcon from '@/components/misc/Icon'
import XButton from '@/components/input/button.vue'
import Modal from '@/components/misc/Modal.vue'
import Card from '@/components/misc/Card.vue'
@ -21,7 +20,6 @@ export const setupVue3 = defineSetupVue3(({ app }) => {
app.directive('cy', testid)
app.component('Icon', FontAwesomeIcon)
app.component('XButton', XButton)
app.component('Modal', Modal)
app.component('Card', Card)

View File

@ -44,7 +44,6 @@ import shortcut from '@/directives/shortcut'
import testid from '@/directives/testid'
// global components
import FontAwesomeIcon from '@/components/misc/Icon'
import Button from '@/components/input/Button.vue'
import Modal from '@/components/misc/Modal.vue'
import Card from '@/components/misc/Card.vue'
@ -62,7 +61,6 @@ setLanguage(browserLanguage).then(() => {
app.directive('shortcut', shortcut)
app.directive('cy', testid)
app.component('Icon', FontAwesomeIcon)
app.component('XButton', Button)
app.component('Modal', Modal)
app.component('Card', Card)

View File

@ -1,16 +1,11 @@
import type { FunctionalComponent } from 'vue'
import type { Notifications } from '@kyvg/vue3-notification'
// import FontAwesomeIcon from '@/components/misc/Icon'
import type { FontAwesomeIcon as FontAwesomeIconFixedTypes } from './vue-fontawesome'
import type {FunctionalComponent} from 'vue'
import type {Notifications} from '@kyvg/vue3-notification'
import type XButton from '@/components/input/Button.vue'
import type Modal from '@/components/misc/Modal.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' {
export interface GlobalComponents {
Icon: FontAwesomeIconFixedTypes
Notifications: FunctionalComponent<Notifications>
XButton: typeof XButton,
Modal: typeof Modal,

View File

@ -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>

View File

@ -2,7 +2,7 @@
<CreateEdit
v-model:loading="loadingModel"
:title="$t('filters.edit.title')"
primary-icon=""
:show-primary-icon="false"
:primary-label="$t('misc.save')"
:tertiary="$t('misc.delete')"
@primary="handleSave"

View File

@ -6,8 +6,10 @@
<XButton
:to="{name:'labels.create'}"
class="is-pulled-right"
icon="plus"
>
<template #icon>
<PhPlus />
</template>
{{ $t('label.create.header') }}
</XButton>
@ -42,10 +44,7 @@
class="label-edit-button is-small"
@click.stop.prevent="editLabel(label)"
>
<Icon
icon="pen"
class="icon"
/>
<PhPencilSimple class="icon" />
</BaseButton>
</RouterLink>
</div>
@ -87,10 +86,13 @@
</div>
<div class="control">
<XButton
icon="trash-alt"
danger
@click="showDeleteDialoge(labelEditLabel)"
/>
>
<template #icon>
<PhTrash />
</template>
</XButton>
</div>
</div>
</form>
@ -122,6 +124,7 @@ import {computed, nextTick, ref} from 'vue'
import {useI18n} from 'vue-i18n'
import BaseButton from '@/components/base/BaseButton.vue'
import {PhPencilSimple, PhPlus, PhTrash} from '@phosphor-icons/vue'
import Editor from '@/components/input/AsyncEditor'
import ColorPicker from '@/components/input/ColorPicker.vue'
import FormField from '@/components/input/FormField.vue'

View File

@ -15,15 +15,19 @@
<div class="action-buttons">
<XButton
:to="{name: 'filters.create'}"
icon="filter"
>
<template #icon>
<PhFunnel />
</template>
{{ $t('filters.create.title') }}
</XButton>
<XButton
v-cy="'new-project'"
:to="{name: 'project.create'}"
icon="plus"
>
<template #icon>
<PhPlus />
</template>
{{ $t('project.create.header') }}
</XButton>
</div>
@ -41,6 +45,8 @@ import {computed} from 'vue'
import {useI18n} from 'vue-i18n'
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
import {PhFunnel, PhPlus} from '@phosphor-icons/vue'
import ProjectCardGrid from '@/components/project/partials/ProjectCardGrid.vue'
import {useTitle} from '@/composables/useTitle'

View File

@ -2,10 +2,12 @@
<CreateEdit
v-model:loading="loadingModel"
:title="$t('project.duplicate.title')"
primary-icon="paste"
:primary-label="$t('project.duplicate.label')"
@primary="duplicate"
>
<template #primary-icon>
<PhClipboard />
</template>
<p>{{ $t('project.duplicate.text') }}</p>
<ProjectSearch v-model="parentProject" />
</CreateEdit>
@ -17,6 +19,7 @@ import {useRoute} from 'vue-router'
import {useI18n} from 'vue-i18n'
import CreateEdit from '@/components/misc/CreateEdit.vue'
import {PhClipboard} from '@phosphor-icons/vue'
import ProjectSearch from '@/components/tasks/partials/ProjectSearch.vue'
import {success} from '@/message'

View File

@ -2,7 +2,7 @@
<CreateEdit
v-model:loading="loadingModel"
:title="$t('project.edit.header')"
primary-icon=""
:show-primary-icon="false"
:primary-label="$t('misc.save')"
:tertiary="project.maxPermission === PERMISSIONS.ADMIN ? $t('misc.delete') : undefined"
@primary="save"

View File

@ -7,6 +7,7 @@ import type {IProjectView} from '@/modelTypes/IProjectView'
import ViewEditForm from '@/components/project/views/ViewEditForm.vue'
import ProjectViewService from '@/services/projectViews'
import XButton from '@/components/input/Button.vue'
import {PhDotsSixVertical, PhPencilSimple, PhTrash} from '@phosphor-icons/vue'
import {error, success} from '@/message'
import {useI18n} from 'vue-i18n'
import ProjectService from '@/services/project'
@ -193,19 +194,25 @@ async function saveViewPosition(e) {
<XButton
v-if="isAdmin"
class="is-danger mie-2"
icon="trash-alt"
@click="() => {
viewIdToDelete = v.id
showDeleteModal = true
}"
/>
>
<template #icon>
<PhTrash />
</template>
</XButton>
<XButton
v-if="isAdmin"
icon="pen"
@click="viewToEdit = {...v}"
/>
>
<template #icon>
<PhPencilSimple />
</template>
</XButton>
<span class="icon handle">
<Icon icon="grip-lines" />
<PhDotsSixVertical />
</span>
</td>
</template>

View File

@ -9,6 +9,7 @@ import ProjectModel from '@/models/project'
import type {IProject} from '@/modelTypes/IProject'
import CreateEdit from '@/components/misc/CreateEdit.vue'
import {PhPlus, PhTrash} from '@phosphor-icons/vue'
import {useBaseStore} from '@/stores/base'
import type {IWebhook} from '@/modelTypes/IWebhook'
@ -128,10 +129,12 @@ function validateSelectedEvents() {
>
<XButton
v-if="!(webhooks?.length === 0 || showNewForm)"
icon="plus"
class="mbe-4"
@click="showNewForm = true"
>
<template #icon>
<PhPlus />
</template>
{{ $t('project.webhooks.create') }}
</XButton>
@ -239,9 +242,11 @@ function validateSelectedEvents() {
</p>
</div>
<XButton
icon="plus"
@click="create"
>
<template #icon>
<PhPlus />
</template>
{{ $t('project.webhooks.create') }}
</XButton>
</div>
@ -277,9 +282,12 @@ function validateSelectedEvents() {
<td class="actions">
<XButton
danger
icon="trash-alt"
@click="() => {showDeleteModal = true;webhookIdToDelete = w.id}"
/>
>
<template #icon>
<PhTrash />
</template>
</XButton>
</td>
</tr>
</tbody>

View File

@ -28,7 +28,7 @@
class="clear-filter-button"
@click="clearLabelFilter"
>
<Icon icon="times" />
<PhX />
</BaseButton>
</Message>
<p
@ -102,7 +102,7 @@ import {formatDate} from '@/helpers/time/formatDate'
import {setTitle} from '@/helpers/setTitle'
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 FancyCheckbox from '@/components/input/FancyCheckbox.vue'
import SingleTaskInProject from '@/components/tasks/partials/SingleTaskInProject.vue'

View File

@ -17,7 +17,7 @@
class="back-button mbs-2"
@click="lastProject ? router.back() : router.push(projectRoute)"
>
<Icon icon="arrow-left" />
<PhArrowLeft />
{{ $t('task.detail.back') }}
</BaseButton>
<Heading
@ -73,7 +73,7 @@
>
<!-- Assignees -->
<div class="detail-title">
<Icon icon="users" />
<PhUsers />
{{ $t('task.attributes.assignees') }}
</div>
<EditAssignees
@ -99,7 +99,7 @@
>
<!-- Priority -->
<div class="detail-title">
<Icon icon="exclamation-circle" />
<PhWarningCircle />
{{ $t('task.attributes.priority') }}
</div>
<PrioritySelect
@ -120,7 +120,7 @@
>
<!-- Due Date -->
<div class="detail-title">
<Icon icon="calendar" />
<PhCalendar />
{{ $t('task.attributes.dueDate') }}
</div>
<div class="date-input">
@ -137,7 +137,7 @@
@click="() => {task.dueDate = null;saveTask()}"
>
<span class="icon is-small">
<Icon icon="times" />
<PhX />
</span>
</BaseButton>
</div>
@ -153,7 +153,7 @@
>
<!-- Progress -->
<div class="detail-title">
<Icon icon="percent" />
<PhPercent />
{{ $t('task.attributes.percentDone') }}
</div>
<PercentDoneSelect
@ -174,7 +174,7 @@
>
<!-- Start Date -->
<div class="detail-title">
<Icon icon="play" />
<PhPlay />
{{ $t('task.attributes.startDate') }}
</div>
<div class="date-input">
@ -191,7 +191,7 @@
@click="() => {task.startDate = null;saveTask()}"
>
<span class="icon is-small">
<Icon icon="times" />
<PhX />
</span>
</BaseButton>
</div>
@ -207,7 +207,7 @@
>
<!-- End Date -->
<div class="detail-title">
<Icon icon="stop" />
<PhStop />
{{ $t('task.attributes.endDate') }}
</div>
<div class="date-input">
@ -224,7 +224,7 @@
@click="() => {task.endDate = null;saveTask()}"
>
<span class="icon is-small">
<Icon icon="times" />
<PhX />
</span>
</BaseButton>
</div>
@ -240,7 +240,7 @@
>
<!-- Reminders -->
<div class="detail-title">
<Icon :icon="['far', 'clock']" />
<PhClock />
{{ $t('task.attributes.reminders') }}
</div>
<Reminders
@ -262,7 +262,7 @@
<!-- Repeat after -->
<div class="is-flex is-justify-content-space-between">
<div class="detail-title">
<Icon icon="history" />
<PhClockCounterClockwise />
{{ $t('task.attributes.repeat') }}
</div>
<BaseButton
@ -271,7 +271,7 @@
@click="removeRepeatAfter"
>
<span class="icon is-small">
<Icon icon="times" />
<PhX />
</span>
</BaseButton>
</div>
@ -293,7 +293,7 @@
>
<!-- Color -->
<div class="detail-title">
<Icon icon="fill-drip" />
<PhPaintBucket />
{{ $t('task.attributes.color') }}
</div>
<ColorPicker
@ -313,7 +313,7 @@
>
<div class="detail-title">
<span class="icon is-grey">
<Icon icon="tags" />
<PhTag />
</span>
{{ $t('task.attributes.labels') }}
</div>
@ -365,7 +365,7 @@
>
<h3>
<span class="icon is-grey">
<Icon icon="sitemap" />
<PhTreeStructure />
</span>
{{ $t('task.attributes.relatedTasks') }}
</h3>
@ -386,7 +386,7 @@
>
<h3>
<span class="icon is-grey">
<Icon icon="list" />
<PhList />
</span>
{{ $t('task.detail.move') }}
</h3>
@ -426,10 +426,12 @@
v-shortcut="'t'"
:class="{'is-pending': !task.done}"
class="button--mark-done"
icon="check-double"
variant="secondary"
@click="toggleTaskDone()"
>
<template #icon>
<PhChecks />
</template>
{{ task.done ? $t('task.detail.undone') : $t('task.detail.done') }}
</XButton>
<TaskSubscription
@ -441,9 +443,11 @@
<XButton
v-shortcut="'s'"
variant="secondary"
:icon="task.isFavorite ? 'star' : ['far', 'star']"
@click="toggleFavorite"
>
<template #icon>
<PhStar :weight="task.isFavorite ? 'fill' : 'regular'" />
</template>
{{
task.isFavorite ? $t('task.detail.actions.unfavorite') : $t('task.detail.actions.favorite')
}}
@ -454,33 +458,40 @@
<XButton
v-shortcut="'l'"
variant="secondary"
icon="tags"
@click="setFieldActive('labels')"
>
<template #icon>
<PhTag />
</template>
{{ $t('task.detail.actions.label') }}
</XButton>
<XButton
v-shortcut="'p'"
variant="secondary"
icon="exclamation-circle"
@click="setFieldActive('priority')"
>
<template #icon>
<PhWarningCircle />
</template>
{{ $t('task.detail.actions.priority') }}
</XButton>
<XButton
variant="secondary"
icon="percent"
@click="setFieldActive('percentDone')"
>
<template #icon>
<PhPercent />
</template>
{{ $t('task.detail.actions.percentDone') }}
</XButton>
<XButton
v-shortcut="'c'"
variant="secondary"
icon="fill-drip"
:icon-color="color"
@click="setFieldActive('color')"
>
<template #icon>
<PhPaintBucket :style="{color}" />
</template>
{{ $t('task.detail.actions.color') }}
</XButton>
@ -490,33 +501,41 @@
v-shortcut="'a'"
v-cy="'taskDetail.assign'"
variant="secondary"
icon="users"
@click="setFieldActive('assignees')"
>
<template #icon>
<PhUsers />
</template>
{{ $t('task.detail.actions.assign') }}
</XButton>
<XButton
v-shortcut="'f'"
variant="secondary"
icon="paperclip"
@click="openAttachments()"
>
<template #icon>
<PhPaperclip />
</template>
{{ $t('task.detail.actions.attachments') }}
</XButton>
<XButton
v-shortcut="'r'"
variant="secondary"
icon="sitemap"
@click="setRelatedTasksActive()"
>
<template #icon>
<PhTreeStructure />
</template>
{{ $t('task.detail.actions.relatedTasks') }}
</XButton>
<XButton
v-shortcut="'m'"
variant="secondary"
icon="list"
@click="setFieldActive('moveProject')"
>
<template #icon>
<PhList />
</template>
{{ $t('task.detail.actions.moveProject') }}
</XButton>
@ -525,47 +544,59 @@
<XButton
v-shortcut="'d'"
variant="secondary"
icon="calendar"
@click="setFieldActive('dueDate')"
>
<template #icon>
<PhCalendar />
</template>
{{ $t('task.detail.actions.dueDate') }}
</XButton>
<XButton
variant="secondary"
icon="play"
@click="setFieldActive('startDate')"
>
<template #icon>
<PhPlay />
</template>
{{ $t('task.detail.actions.startDate') }}
</XButton>
<XButton
variant="secondary"
icon="stop"
@click="setFieldActive('endDate')"
>
<template #icon>
<PhStop />
</template>
{{ $t('task.detail.actions.endDate') }}
</XButton>
<XButton
v-shortcut="reminderShortcut"
variant="secondary"
:icon="['far', 'clock']"
@click="setFieldActive('reminders')"
>
<template #icon>
<PhClock />
</template>
{{ $t('task.detail.actions.reminders') }}
</XButton>
<XButton
variant="secondary"
icon="history"
@click="setFieldActive('repeatAfter')"
>
<template #icon>
<PhClockCounterClockwise />
</template>
{{ $t('task.detail.actions.repeatAfter') }}
</XButton>
<XButton
v-shortcut="'Shift+Delete'"
icon="trash-alt"
:shadow="false"
class="is-danger is-outlined has-no-border"
@click="showDeleteModal = true"
>
<template #icon>
<PhTrash />
</template>
{{ $t('task.detail.actions.delete') }}
</XButton>
</template>
@ -588,7 +619,7 @@
:aria-label="$t('task.detail.scrollToBottom')"
@click="scrollToBottom"
>
<Icon icon="chevron-down" />
<PhCaretDown />
</BaseButton>
<Modal
@ -631,6 +662,13 @@ import {PERMISSIONS} from '@/constants/permissions'
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
import Attachments from '@/components/tasks/partials/Attachments.vue'
import ChecklistSummary from '@/components/tasks/partials/ChecklistSummary.vue'

View File

@ -57,9 +57,12 @@
<XButton
:loading="teamService.loading"
danger
icon="trash-alt"
@click="showDeleteModal = true"
/>
>
<template #icon>
<PhTrash />
</template>
</XButton>
</div>
</div>
</Card>
@ -95,9 +98,11 @@
</div>
<div class="control">
<XButton
icon="plus"
@click="addUser"
>
<template #icon>
<PhPlus />
</template>
{{ $t('team.edit.addUser') }}
</XButton>
</div>
@ -130,13 +135,13 @@
<td class="type">
<template v-if="m.admin">
<span class="icon is-small">
<Icon icon="lock" />
<PhLock />
</span>
{{ $t('team.attributes.admin') }}
</template>
<template v-else>
<span class="icon is-small">
<Icon icon="user" />
<PhUser />
</span>
{{ $t('team.attributes.member') }}
</template>
@ -157,9 +162,12 @@
v-if="m.id !== userInfo.id"
:loading="teamMemberService.loading"
danger
icon="trash-alt"
@click="() => {memberToDelete = m; showUserDeleteModal = true}"
/>
>
<template #icon>
<PhTrash />
</template>
</XButton>
</td>
</tr>
</tbody>
@ -236,6 +244,8 @@ import {useI18n} from 'vue-i18n'
import {useRoute, useRouter} from 'vue-router'
import Editor from '@/components/input/AsyncEditor'
import {PhLock, PhPlus, PhTrash, PhUser} from '@phosphor-icons/vue'
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
import FormField from '@/components/input/FormField.vue'
import Multiselect from '@/components/input/Multiselect.vue'

View File

@ -6,8 +6,10 @@
<XButton
:to="{name:'teams.create'}"
class="is-pulled-right"
icon="plus"
>
<template #icon>
<PhPlus />
</template>
{{ $t('team.create.title') }}
</XButton>
@ -44,6 +46,7 @@ import {ref, shallowReactive} from 'vue'
import { useI18n } from 'vue-i18n'
import TeamService from '@/services/team'
import {PhPlus} from '@phosphor-icons/vue'
import { useTitle } from '@/composables/useTitle'
const { t } = useI18n({useScope: 'global'})

View File

@ -27,9 +27,7 @@
{{ text }}
</span>
<span class="ml-1 has-text-grey-light is-size-7">
<Icon
icon="arrow-up-right-from-square"
/>
<PhArrowSquareOut />
</span>
</BaseButton>
</li>
@ -51,6 +49,7 @@ import { useAuthStore } from '@/stores/auth'
import {useRoute} from 'vue-router'
import BaseButton from '@/components/base/BaseButton.vue'
import {PhArrowSquareOut} from '@phosphor-icons/vue'
const { t } = useI18n({useScope: 'global'})
useTitle(() => t('user.settings.title'))

View File

@ -6,6 +6,7 @@ import {parseScopesFromQuery} from '@/helpers/parseScopesFromQuery'
import {useFlatpickrLanguage} from '@/helpers/useFlatpickrLanguage'
import {formatDateSince, formatDisplayDate} from '@/helpers/time/formatDate'
import XButton from '@/components/input/Button.vue'
import {PhPlus} from '@phosphor-icons/vue'
import BaseButton from '@/components/base/BaseButton.vue'
import ApiTokenModel from '@/models/apiTokenModel'
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
@ -381,11 +382,13 @@ function toggleGroupPermissionsFromChild(group: string, checked: boolean) {
<XButton
v-else
icon="plus"
class="mbe-4"
:loading="service.loading"
@click="() => showCreateForm = true"
>
<template #icon>
<PhPlus />
</template>
{{ $t('user.settings.apiTokens.createAToken') }}
</XButton>

View File

@ -15,9 +15,12 @@
<XButton
v-tooltip="$t('misc.copy')"
:shadow="false"
icon="paste"
@click="copy(caldavUrl)"
/>
>
<template #icon>
<PhClipboard />
</template>
</XButton>
</template>
</FormField>
@ -75,11 +78,13 @@
</Message>
<XButton
icon="plus"
class="mbe-4"
:loading="service.loading"
@click="createToken"
>
<template #icon>
<PhPlus />
</template>
{{ $t('user.settings.caldav.createToken') }}
</XButton>
@ -103,6 +108,7 @@ import {useTitle} from '@/composables/useTitle'
import {useCopyToClipboard} from '@/composables/useCopyToClipboard'
import {success} from '@/message'
import BaseButton from '@/components/base/BaseButton.vue'
import {PhClipboard, PhPlus} from '@phosphor-icons/vue'
import Message from '@/components/misc/Message.vue'
import FormField from '@/components/input/FormField.vue'
import CaldavTokenService from '@/services/caldavToken'