chore: apply lint fixes

This commit is contained in:
kolaente 2024-02-07 12:18:19 +01:00 committed by konrad
parent 362be53a47
commit 447641c222
151 changed files with 4336 additions and 2630 deletions

View File

@ -19,7 +19,7 @@ module.exports = {
'semi': ['error', 'never'],
'vue/v-on-event-hyphenation': ['warn', 'never', { 'autofix': true }],
'vue/multi-word-component-names': 'warn',
'vue/multi-word-component-names': 'off',
// uncategorized rules:
'vue/component-api-style': ['error', ['script-setup']],
@ -43,6 +43,7 @@ module.exports = {
'vue/no-required-prop-with-default': ['error', { 'autofix': true }],
'vue/no-duplicate-attr-inheritance': 'error',
'vue/no-empty-component-block': 'error',
'vue/html-indent': ['error', 'tab'],
// vue3
'vue/no-ref-object-destructure': 'error',

View File

@ -1,122 +0,0 @@
// import originalEslintPluginVue from 'eslint-plugin-vue'
import vueTsRecommended from '@vue/eslint-config-typescript/recommended.js'
// import vueParser from 'vue-eslint-parser'
import tsParser from "@typescript-eslint/parser"
const vue3Recommended = vue.configs['vue3-recommended']
import {default as originalVuePlugin} from "eslint-plugin-vue";
// see https://github.com/eslint/eslint/issues/16875#issuecomment-1426594123
const eslintPluginVue = {
...originalVuePlugin,
parsers: {
'parser': {
parseForESLint: originalVuePlugin.parseForESLint
}
}
}
// export default [{
// files: ["**/*.json", "**/*.jsonc", "**/*.json5"],
// plugins: {
// vue: { ...vue, parsers}
// /* same as
// jsonc: {
// parsers: {
// 'jsonc-eslint-parser': {
// parseForESLint
// }
// }
// } */
// },
// languageOptions: {
// parser: 'vue/vue-eslint-parser'
// },
// rules: {...}
// }];
export default [
// 'eslint:recommended',
{
files: ["**/*.vue"],
plugins: {
vue: eslintPluginVue,
},
languageOptions: {
parser: 'vue/parser'
},
},
// {
// plugins: {
// // vue: vue3Recommended,
// // '@typescript-eslint': vueTsRecommended,
// },
// languageOptions: {
// // parser: eslintPluginVue,
// // parser: 'vue/vue-eslint-parser',
// parserOptions: {
// parser: '@typescript-eslint/parser',
// // 'ecmaVersion': 2022,
// // 'sourceType': 'module',
// },
// }
// }
// {
// files: ["./src/**/*.vue"],
// // files: ["./src/**/*.js"],
// // ignores: ["**/*.config.js"],
// rules: {
// semi: "error"
// },
// plugins: {
// vue: vue3Recommended,
// // '@typescript-eslint': vueTsRecommended,
// },
// },
// {
// files: ["src/**/*.vue"],
// // files: [
// // 'src/**/*.vue',
// // 'src/**/*.js',
// // 'src/**/*.ts',
// // // 'src/**/*.+(vue|js|ts)',
// // ],
// ignores: [
// '*.test.*',
// 'cypress/*',
// ],
// plugins: {
// vue: vue3Recommended,
// '@typescript-eslint': vueTsRecommended,
// },
// rules: {
// 'vue/html-quotes': ['error', 'double'],
// 'quotes': ['error', 'single'],
// 'comma-dangle': ['error', 'always-multiline'],
// 'semi': ['error', 'never'],
// 'vue/multi-word-component-names': 0,
// // disabled until we have support for reactivityTransform
// // See https://github.com/vuejs/eslint-plugin-vue/issues/1948
// // see also setting in `vite.config`
// 'vue/no-setup-props-destructure': 0,
// },
// // overwrite the following with correct values
// // eslint-plugin-vue/lib/configs/base.js
// // parser:
// parserOptions: {
// ecmaVersion: 2022,
// 'parser': '@typescript-eslint/parser',
// 'sourceType': 'module',
// },
// globals: {
// 'browser': true,
// 'es2022': true,
// 'node': true,
// 'vue/setup-compiler-macros': true,
// }
// },
]

View File

@ -31,7 +31,7 @@
"build:modern-only": "BUILD_MODERN_ONLY=true vite build && workbox copyLibraries dist/",
"build:dev": "vite build --mode development --outDir dist-dev/",
"lint": "eslint 'src/**/*.{js,ts,vue}'",
"lint:fix": "eslint --fix 'src/**/*.{js,ts,vue}' ",
"lint:fix": "pnpm run lint --fix",
"test:e2e": "start-server-and-test preview http://127.0.0.1:4173 'cypress run --e2e --browser chrome'",
"test:e2e-record": "start-server-and-test preview http://127.0.0.1:4173 'cypress run --e2e --browser chrome --record'",
"test:e2e-dev-dev": "start-server-and-test preview:dev http://127.0.0.1:4173 'cypress open --e2e'",

View File

@ -1,23 +1,23 @@
<template>
<ready>
<Ready>
<template v-if="authUser">
<TheNavigation/>
<content-auth/>
<TheNavigation />
<ContentAuth />
</template>
<content-link-share v-else-if="authLinkShare"/>
<no-auth-wrapper v-else>
<router-view/>
</no-auth-wrapper>
<ContentLinkShare v-else-if="authLinkShare" />
<NoAuthWrapper v-else>
<router-view />
</NoAuthWrapper>
<keyboard-shortcuts v-if="keyboardShortcutsActive"/>
<KeyboardShortcuts v-if="keyboardShortcutsActive" />
<Teleport to="body">
<AddToHomeScreen/>
<UpdateNotification/>
<Notification/>
<DemoMode/>
<AddToHomeScreen />
<UpdateNotification />
<Notification />
<DemoMode />
</Teleport>
</ready>
</Ready>
</template>
<script lang="ts" setup>

View File

@ -21,10 +21,16 @@ const state = reactive({
</script>
<template>
<Story :setup-app="setupApp" :layout="{ type: 'grid', width: '200px' }">
<Story
:setup-app="setupApp"
:layout="{ type: 'grid', width: '200px' }"
>
<Variant title="custom">
<template #controls>
<HstCheckbox v-model="state.disabled" title="Disabled" />
<HstCheckbox
v-model="state.disabled"
title="Disabled"
/>
</template>
<BaseButton :disabled="state.disabled">
Hello!

View File

@ -6,38 +6,39 @@
<template>
<div
v-if="disabled === true && (to !== undefined || href !== undefined)"
ref="button"
class="base-button"
:aria-disabled="disabled || undefined"
ref="button"
>
<slot/>
<slot />
</div>
<router-link
v-else-if="to !== undefined"
ref="button"
:to="to"
class="base-button"
ref="button"
>
<slot/>
<slot />
</router-link>
<a v-else-if="href !== undefined"
<a
v-else-if="href !== undefined"
ref="button"
class="base-button"
:href="href"
rel="noreferrer noopener nofollow"
target="_blank"
ref="button"
>
<slot/>
<slot />
</a>
<button
v-else
ref="button"
:type="type"
class="base-button base-button--type-button"
:disabled="disabled || undefined"
ref="button"
@click="(event: MouseEvent) => emit('click', event)"
>
<slot/>
<slot />
</button>
</template>

View File

@ -1,17 +1,26 @@
<template>
<div class="base-checkbox" v-cy="'checkbox'">
<div
v-cy="'checkbox'"
class="base-checkbox"
>
<input
type="checkbox"
:id="checkboxId"
type="checkbox"
class="is-sr-only"
:checked="modelValue"
@change="(event) => emit('update:modelValue', (event.target as HTMLInputElement).checked)"
:disabled="disabled || undefined"
/>
@change="(event) => emit('update:modelValue', (event.target as HTMLInputElement).checked)"
>
<slot name="label" :checkboxId="checkboxId">
<label :for="checkboxId" class="base-checkbox__label">
<slot/>
<slot
name="label"
:checkbox-id="checkboxId"
>
<label
:for="checkboxId"
class="base-checkbox__label"
>
<slot />
</label>
</slot>
</div>

View File

@ -1,27 +1,30 @@
<template>
<transition
name="expandable-slide"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
@leave-cancelled="leaveCancelled"
>
<div
v-if="initialHeight"
class="expandable-initial-height"
:style="{ maxHeight: `${initialHeight}px` }"
:class="{ 'expandable-initial-height--expanded': open }"
>
<slot />
</div>
<div v-else-if="open" class="expandable">
<slot />
</div>
</transition>
<transition
name="expandable-slide"
@beforeEnter="beforeEnter"
@enter="enter"
@afterEnter="afterEnter"
@enterCancelled="enterCancelled"
@beforeLeave="beforeLeave"
@leave="leave"
@afterLeave="afterLeave"
@leaveCancelled="leaveCancelled"
>
<div
v-if="initialHeight"
class="expandable-initial-height"
:style="{ maxHeight: `${initialHeight}px` }"
:class="{ 'expandable-initial-height--expanded': open }"
>
<slot />
</div>
<div
v-else-if="open"
class="expandable"
>
<slot />
</div>
</transition>
</template>
<script setup lang="ts">

View File

@ -3,9 +3,9 @@ import datemathHelp from './datemathHelp.vue'
</script>
<template>
<Story>
<Variant title="Default">
<datemathHelp />
</Variant>
</Story>
<Story>
<Variant title="Default">
<datemathHelp />
</Variant>
</Story>
</template>

View File

@ -7,21 +7,29 @@
{{ $t('input.datemathHelp.intro') }}
</p>
<p>
<i18n-t keypath="input.datemathHelp.expression" scope="global">
<i18n-t
keypath="input.datemathHelp.expression"
scope="global"
>
<code>now</code>
<code>||</code>
</i18n-t>
</p>
<p>
<i18n-t keypath="input.datemathHelp.similar" scope="global">
<i18n-t
keypath="input.datemathHelp.similar"
scope="global"
>
<BaseButton
href="https://grafana.com/docs/grafana/latest/dashboards/time-range-controls/"
target="_blank">
target="_blank"
>
Grafana
</BaseButton>
<BaseButton
href="https://www.elastic.co/guide/en/elasticsearch/reference/7.3/common-options.html#date-math"
target="_blank">
target="_blank"
>
Elasticsearch
</BaseButton>
</i18n-t>
@ -35,76 +43,79 @@
<h3>{{ $t('input.datemathHelp.supportedUnits') }}</h3>
<table class="table">
<tbody>
<tr>
<td><code>s</code></td>
<td>{{ $t('input.datemathHelp.units.seconds') }}</td>
</tr>
<tr>
<td><code>m</code></td>
<td>{{ $t('input.datemathHelp.units.minutes') }}</td>
</tr>
<tr>
<td><code>h</code></td>
<td>{{ $t('input.datemathHelp.units.hours') }}</td>
</tr>
<tr>
<td><code>H</code></td>
<td>{{ $t('input.datemathHelp.units.hours') }}</td>
</tr>
<tr>
<td><code>d</code></td>
<td>{{ $t('input.datemathHelp.units.days') }}</td>
</tr>
<tr>
<td><code>w</code></td>
<td>{{ $t('input.datemathHelp.units.weeks') }}</td>
</tr>
<tr>
<td><code>M</code></td>
<td>{{ $t('input.datemathHelp.units.months') }}</td>
</tr>
<tr>
<td><code>y</code></td>
<td>{{ $t('input.datemathHelp.units.years') }}</td>
</tr>
<tr>
<td><code>s</code></td>
<td>{{ $t('input.datemathHelp.units.seconds') }}</td>
</tr>
<tr>
<td><code>m</code></td>
<td>{{ $t('input.datemathHelp.units.minutes') }}</td>
</tr>
<tr>
<td><code>h</code></td>
<td>{{ $t('input.datemathHelp.units.hours') }}</td>
</tr>
<tr>
<td><code>H</code></td>
<td>{{ $t('input.datemathHelp.units.hours') }}</td>
</tr>
<tr>
<td><code>d</code></td>
<td>{{ $t('input.datemathHelp.units.days') }}</td>
</tr>
<tr>
<td><code>w</code></td>
<td>{{ $t('input.datemathHelp.units.weeks') }}</td>
</tr>
<tr>
<td><code>M</code></td>
<td>{{ $t('input.datemathHelp.units.months') }}</td>
</tr>
<tr>
<td><code>y</code></td>
<td>{{ $t('input.datemathHelp.units.years') }}</td>
</tr>
</tbody>
</table>
<h3>{{ $t('input.datemathHelp.someExamples') }}</h3>
<table class="table">
<tbody>
<tr>
<td><code>now</code></td>
<td>{{ $t('input.datemathHelp.examples.now') }}</td>
</tr>
<tr>
<td><code>now+24h</code></td>
<td>{{ $t('input.datemathHelp.examples.in24h') }}</td>
</tr>
<tr>
<td><code>now/d</code></td>
<td>{{ $t('input.datemathHelp.examples.today') }}</td>
</tr>
<tr>
<td><code>now/w</code></td>
<td>{{ $t('input.datemathHelp.examples.beginningOfThisWeek') }}</td>
</tr>
<tr>
<td><code>now/w+1w</code></td>
<td>{{ $t('input.datemathHelp.examples.endOfThisWeek') }}</td>
</tr>
<tr>
<td><code>now+30d</code></td>
<td>{{ $t('input.datemathHelp.examples.in30Days') }}</td>
</tr>
<tr>
<td><code>{{ exampleDate }}||+1M/d</code></td>
<td>
<i18n-t keypath="input.datemathHelp.examples.datePlusMonth" scope="global">
<strong>{{ exampleDate }}</strong>
</i18n-t>
</td>
</tr>
<tr>
<td><code>now</code></td>
<td>{{ $t('input.datemathHelp.examples.now') }}</td>
</tr>
<tr>
<td><code>now+24h</code></td>
<td>{{ $t('input.datemathHelp.examples.in24h') }}</td>
</tr>
<tr>
<td><code>now/d</code></td>
<td>{{ $t('input.datemathHelp.examples.today') }}</td>
</tr>
<tr>
<td><code>now/w</code></td>
<td>{{ $t('input.datemathHelp.examples.beginningOfThisWeek') }}</td>
</tr>
<tr>
<td><code>now/w+1w</code></td>
<td>{{ $t('input.datemathHelp.examples.endOfThisWeek') }}</td>
</tr>
<tr>
<td><code>now+30d</code></td>
<td>{{ $t('input.datemathHelp.examples.in30Days') }}</td>
</tr>
<tr>
<td><code>{{ exampleDate }}||+1M/d</code></td>
<td>
<i18n-t
keypath="input.datemathHelp.examples.datePlusMonth"
scope="global"
>
<strong>{{ exampleDate }}</strong>
</i18n-t>
</td>
</tr>
</tbody>
</table>
</card>

View File

@ -1,20 +1,31 @@
<template>
<div class="datepicker-with-range-container">
<popup>
<Popup>
<template #trigger="{toggle}">
<slot name="trigger" :toggle="toggle" :buttonText="buttonText"></slot>
<slot
name="trigger"
:toggle="toggle"
:button-text="buttonText"
/>
</template>
<template #content="{isOpen}">
<div class="datepicker-with-range" :class="{'is-open': isOpen}">
<div
class="datepicker-with-range"
:class="{'is-open': isOpen}"
>
<div class="selections">
<BaseButton @click="setDateRange(null)" :class="{'is-active': customRangeActive}">
<BaseButton
:class="{'is-active': customRangeActive}"
@click="setDateRange(null)"
>
{{ $t('misc.custom') }}
</BaseButton>
<BaseButton
v-for="(value, text) in DATE_RANGES"
:key="text"
:class="{'is-active': from === value[0] && to === value[1]}"
@click="setDateRange(value)"
:class="{'is-active': from === value[0] && to === value[1]}">
>
{{ $t(`input.datepickerRange.ranges.${text}`) }}
</BaseButton>
</div>
@ -23,10 +34,18 @@
{{ $t('input.datepickerRange.from') }}
<div class="field has-addons">
<div class="control is-fullwidth">
<input class="input" type="text" v-model="from"/>
<input
v-model="from"
class="input"
type="text"
>
</div>
<div class="control">
<x-button icon="calendar" variant="secondary" data-toggle/>
<x-button
icon="calendar"
variant="secondary"
data-toggle
/>
</div>
</div>
</label>
@ -34,38 +53,49 @@
{{ $t('input.datepickerRange.to') }}
<div class="field has-addons">
<div class="control is-fullwidth">
<input class="input" type="text" v-model="to"/>
<input
v-model="to"
class="input"
type="text"
>
</div>
<div class="control">
<x-button icon="calendar" variant="secondary" data-toggle/>
<x-button
icon="calendar"
variant="secondary"
data-toggle
/>
</div>
</div>
</label>
<flat-pickr
:config="flatPickerConfig"
v-model="flatpickrRange"
:config="flatPickerConfig"
/>
<p>
{{ $t('input.datemathHelp.canuse') }}
<BaseButton class="has-text-primary" @click="showHowItWorks = true">
<BaseButton
class="has-text-primary"
@click="showHowItWorks = true"
>
{{ $t('input.datemathHelp.learnhow') }}
</BaseButton>
</p>
<modal
:enabled="showHowItWorks"
@close="() => showHowItWorks = false"
transition-name="fade"
:overflow="true"
variant="hint-modal"
@close="() => showHowItWorks = false"
>
<DatemathHelp/>
<DatemathHelp />
</modal>
</div>
</div>
</template>
</popup>
</Popup>
</div>
</template>
@ -83,15 +113,16 @@ import BaseButton from '@/components/base/BaseButton.vue'
import DatemathHelp from '@/components/date/datemathHelp.vue'
import { getFlatpickrLanguage } from '@/helpers/flatpickrLanguage'
const {t} = useI18n({useScope: 'global'})
const emit = defineEmits(['update:modelValue'])
const props = defineProps({
modelValue: {
required: false,
},
})
const emit = defineEmits(['update:modelValue'])
const {t} = useI18n({useScope: 'global'})
const flatPickerConfig = computed(() => ({
altFormat: t('date.altFormatLong'),
altInput: true,

View File

@ -4,12 +4,18 @@
class="add-to-home-screen"
:class="{'has-update-available': hasUpdateAvailable}"
>
<icon icon="arrow-up-from-bracket" class="add-icon"/>
<icon
icon="arrow-up-from-bracket"
class="add-icon"
/>
<p>
{{ $t('home.addToHomeScreen') }}
</p>
<BaseButton @click="() => hideMessage = true" class="hide-button">
<icon icon="x"/>
<BaseButton
class="hide-button"
@click="() => hideMessage = true"
>
<icon icon="x" />
</BaseButton>
</div>
</template>

View File

@ -17,8 +17,11 @@ const enabled = computed(() => configStore.demoModeEnabled && !hide.value)
{{ $t('demo.title') }}
<strong class="is-uppercase">{{ $t('demo.everythingWillBeDeleted') }}</strong>
</p>
<BaseButton @click="() => hide = true" class="hide-button">
<icon icon="times"/>
<BaseButton
class="hide-button"
@click="() => hide = true"
>
<icon icon="times" />
</BaseButton>
</div>
</template>

View File

@ -15,8 +15,17 @@ const CustomLogo = computed(() => window.CUSTOM_LOGO_URL)
<template>
<div>
<Logo v-if="!CustomLogo" alt="Vikunja" class="logo" />
<img v-show="CustomLogo" :src="CustomLogo" alt="Vikunja" class="logo" />
<Logo
v-if="!CustomLogo"
alt="Vikunja"
class="logo"
/>
<img
v-show="CustomLogo"
:src="CustomLogo"
alt="Vikunja"
class="logo"
>
</div>
</template>

View File

@ -1,11 +1,11 @@
<template>
<BaseButton
class="menu-show-button"
@click="baseStore.toggleMenu()"
@shortkey="() => baseStore.toggleMenu()"
v-shortcut="'Mod+e'"
class="menu-show-button"
:title="$t('keyboardShortcuts.toggleMenu')"
:aria-label="menuActive ? $t('misc.hideMenu') : $t('misc.showMenu')"
@click="baseStore.toggleMenu()"
@shortkey="() => baseStore.toggleMenu()"
/>
</template>

View File

@ -1,7 +1,11 @@
<template>
<BaseButton class="menu-bottom-link" :href="poweredByUrl" target="_blank">
{{ $t('misc.poweredBy') }}
</BaseButton>
<BaseButton
class="menu-bottom-link"
:href="poweredByUrl"
target="_blank"
>
{{ $t('misc.poweredBy') }}
</BaseButton>
</template>
<script setup lang="ts">

View File

@ -2,10 +2,8 @@
<draggable
v-model="availableProjects"
animation="100"
ghostClass="ghost"
ghost-class="ghost"
group="projects"
@start="() => drag = true"
@end="saveProjectPosition"
handle=".handle"
tag="menu"
item-key="id"
@ -19,6 +17,8 @@
{ 'dragging-disabled': !canEditOrder }
],
}"
@start="() => drag = true"
@end="saveProjectPosition"
>
<template #item="{element: project}">
<ProjectsNavigationItem

View File

@ -6,10 +6,13 @@
<div>
<BaseButton
v-if="canCollapse && childProjects?.length > 0"
@click="childProjectsOpen = !childProjectsOpen"
class="collapse-project-button"
@click="childProjectsOpen = !childProjectsOpen"
>
<icon icon="chevron-down" :class="{ 'project-is-collapsed': !childProjectsOpen }"/>
<icon
icon="chevron-down"
:class="{ 'project-is-collapsed': !childProjectsOpen }"
/>
</BaseButton>
<BaseButton
:to="{ name: 'project.index', params: { projectId: project.id} }"
@ -19,21 +22,27 @@
<span
v-if="!canCollapse || childProjects?.length === 0"
class="collapse-project-button-placeholder"
></span>
<div class="color-bubble-handle-wrapper" :class="{'is-draggable': project.id > 0}">
/>
<div
class="color-bubble-handle-wrapper"
:class="{'is-draggable': project.id > 0}"
>
<ColorBubble
v-if="project.hexColor !== ''"
:color="project.hexColor"
/>
<span v-else-if="project.id < -1" class="saved-filter-icon icon menu-item-icon">
<icon icon="filter"/>
<span
v-else-if="project.id < -1"
class="saved-filter-icon icon menu-item-icon"
>
<icon icon="filter" />
</span>
<span
v-if="project.id > 0"
class="icon menu-item-icon handle"
:class="{'has-color-bubble': project.hexColor !== ''}"
>
<icon icon="grip-lines"/>
<icon icon="grip-lines" />
</span>
</div>
<span class="project-menu-title">{{ getProjectTitle(project) }}</span>
@ -44,7 +53,7 @@
:class="{'is-favorite': project.isFavorite}"
@click="projectStore.toggleProjectFavorite(project)"
>
<icon :icon="project.isFavorite ? 'star' : ['far', 'star']"/>
<icon :icon="project.isFavorite ? 'star' : ['far', 'star']" />
</BaseButton>
<ProjectSettingsDropdown
class="menu-list-dropdown"
@ -52,8 +61,14 @@
:level="level"
>
<template #trigger="{toggleOpen}">
<BaseButton class="menu-list-dropdown-trigger" @click="toggleOpen">
<icon icon="ellipsis-h" class="icon"/>
<BaseButton
class="menu-list-dropdown-trigger"
@click="toggleOpen"
>
<icon
icon="ellipsis-h"
class="icon"
/>
</BaseButton>
</template>
</ProjectSettingsDropdown>

View File

@ -1,66 +1,110 @@
<template>
<header :class="{ 'has-background': background, 'menu-active': menuActive }" aria-label="main navigation"
class="navbar d-print-none">
<router-link :to="{ name: 'home' }" class="logo-link">
<Logo width="164" height="48" />
<header
:class="{ 'has-background': background, 'menu-active': menuActive }"
aria-label="main navigation"
class="navbar d-print-none"
>
<router-link
:to="{ name: 'home' }"
class="logo-link"
>
<Logo
width="164"
height="48"
/>
</router-link>
<MenuButton class="menu-button" />
<div v-if="currentProject?.id" class="project-title-wrapper">
<div
v-if="currentProject?.id"
class="project-title-wrapper"
>
<h1 class="project-title">
{{ currentProject.title === '' ? $t('misc.loading') : getProjectTitle(currentProject) }}
</h1>
<BaseButton :to="{ name: 'project.info', params: { projectId: currentProject.id } }" class="project-title-button">
<BaseButton
:to="{ name: 'project.info', params: { projectId: currentProject.id } }"
class="project-title-button"
>
<icon icon="circle-info" />
</BaseButton>
<project-settings-dropdown v-if="canWriteCurrentProject && currentProject.id !== -1"
class="project-title-dropdown" :project="currentProject">
<ProjectSettingsDropdown
v-if="canWriteCurrentProject && currentProject.id !== -1"
class="project-title-dropdown"
:project="currentProject"
>
<template #trigger="{ toggleOpen }">
<BaseButton class="project-title-button" @click="toggleOpen">
<icon icon="ellipsis-h" class="icon" />
<BaseButton
class="project-title-button"
@click="toggleOpen"
>
<icon
icon="ellipsis-h"
class="icon"
/>
</BaseButton>
</template>
</project-settings-dropdown>
</ProjectSettingsDropdown>
</div>
<div class="navbar-end">
<OpenQuickActions/>
<OpenQuickActions />
<Notifications />
<dropdown>
<Dropdown>
<template #trigger="{ toggleOpen, open }">
<BaseButton class="username-dropdown-trigger" @click="toggleOpen" variant="secondary" :shadow="false">
<img :src="authStore.avatarUrl" alt="" class="avatar" width="40" height="40" />
<BaseButton
class="username-dropdown-trigger"
variant="secondary"
:shadow="false"
@click="toggleOpen"
>
<img
:src="authStore.avatarUrl"
alt=""
class="avatar"
width="40"
height="40"
>
<span class="username">{{ authStore.userDisplayName }}</span>
<span class="icon is-small" :style="{
transform: open ? 'rotate(180deg)' : 'rotate(0)',
}">
<span
class="icon is-small"
:style="{
transform: open ? 'rotate(180deg)' : 'rotate(0)',
}"
>
<icon icon="chevron-down" />
</span>
</BaseButton>
</template>
<dropdown-item :to="{ name: 'user.settings' }">
<DropdownItem :to="{ name: 'user.settings' }">
{{ $t('user.settings.title') }}
</dropdown-item>
<dropdown-item v-if="imprintUrl" :href="imprintUrl">
</DropdownItem>
<DropdownItem
v-if="imprintUrl"
:href="imprintUrl"
>
{{ $t('navigation.imprint') }}
</dropdown-item>
<dropdown-item v-if="privacyPolicyUrl" :href="privacyPolicyUrl">
</DropdownItem>
<DropdownItem
v-if="privacyPolicyUrl"
:href="privacyPolicyUrl"
>
{{ $t('navigation.privacy') }}
</dropdown-item>
<dropdown-item @click="baseStore.setKeyboardShortcutsActive(true)">
</DropdownItem>
<DropdownItem @click="baseStore.setKeyboardShortcutsActive(true)">
{{ $t('keyboardShortcuts.title') }}
</dropdown-item>
<dropdown-item :to="{ name: 'about' }">
</DropdownItem>
<DropdownItem :to="{ name: 'about' }">
{{ $t('about.title') }}
</dropdown-item>
<dropdown-item @click="authStore.logout()">
</DropdownItem>
<DropdownItem @click="authStore.logout()">
{{ $t('user.auth.logout') }}
</dropdown-item>
</dropdown>
</DropdownItem>
</Dropdown>
</div>
</header>
</template>

View File

@ -1,11 +1,16 @@
<template>
<div class="update-notification" v-if="updateAvailable">
<p class="update-notification__message">{{ $t('update.available') }}</p>
<div
v-if="updateAvailable"
class="update-notification"
>
<p class="update-notification__message">
{{ $t('update.available') }}
</p>
<x-button
@click="refreshApp()"
:shadow="false"
:wrap="false"
>
@click="refreshApp()"
>
{{ $t('update.do') }}
</x-button>
</div>

View File

@ -2,10 +2,10 @@
<div class="content-auth">
<BaseButton
v-show="menuActive"
@click="baseStore.setMenuActive(false)"
class="menu-hide-button d-print-none"
@click="baseStore.setMenuActive(false)"
>
<icon icon="times"/>
<icon icon="times" />
</BaseButton>
<div
class="app-container"
@ -15,8 +15,9 @@
<div
:class="{'is-visible': background}"
class="app-container-background background-fade-in d-print-none"
:style="{'background-image': background && `url(${background})`}"></div>
<navigation class="d-print-none"/>
:style="{'background-image': background && `url(${background})`}"
/>
<Navigation class="d-print-none" />
<main
class="app-content"
:class="[
@ -26,33 +27,36 @@
>
<BaseButton
v-show="menuActive"
@click="baseStore.setMenuActive(false)"
class="mobile-overlay d-print-none"
@click="baseStore.setMenuActive(false)"
/>
<quick-actions/>
<QuickActions />
<router-view :route="routeWithModal" v-slot="{ Component }">
<router-view
v-slot="{ Component }"
:route="routeWithModal"
>
<keep-alive :include="['project.list', 'project.gantt', 'project.table', 'project.kanban']">
<component :is="Component"/>
<component :is="Component" />
</keep-alive>
</router-view>
<modal
:enabled="typeof currentModal !== 'undefined'"
@close="closeModal()"
variant="scrolling"
class="task-detail-view-modal"
@close="closeModal()"
>
<component :is="currentModal"/>
<component :is="currentModal" />
</modal>
<BaseButton
v-shortcut="'?'"
class="keyboard-shortcuts-button d-print-none"
@click="showKeyboardShortcuts()"
v-shortcut="'?'"
>
<icon icon="keyboard"/>
<icon icon="keyboard" />
</BaseButton>
</main>
</div>

View File

@ -6,16 +6,20 @@
>
<div class="container has-text-centered link-share-view">
<div class="column is-10 is-offset-1">
<Logo class="logo" v-if="logoVisible"/>
<Logo
v-if="logoVisible"
class="logo"
/>
<h1
:class="{'m-0': !logoVisible}"
:style="{ 'opacity': currentProject?.title === '' ? '0': '1' }"
class="title">
class="title"
>
{{ currentProject?.title === '' ? $t('misc.loading') : currentProject?.title }}
</h1>
<div class="box has-text-left view">
<router-view/>
<PoweredByLink/>
<router-view />
<PoweredByLink />
</div>
</div>
</div>

View File

@ -1,46 +1,70 @@
<template>
<aside :class="{'is-active': baseStore.menuActive}" class="menu-container">
<aside
:class="{'is-active': baseStore.menuActive}"
class="menu-container"
>
<nav class="menu top-menu">
<router-link :to="{name: 'home'}" class="logo">
<Logo width="164" height="48"/>
<router-link
:to="{name: 'home'}"
class="logo"
>
<Logo
width="164"
height="48"
/>
</router-link>
<menu class="menu-list other-menu-items">
<li>
<router-link :to="{ name: 'home'}" v-shortcut="'g o'">
<router-link
v-shortcut="'g o'"
:to="{ name: 'home'}"
>
<span class="menu-item-icon icon">
<icon icon="calendar"/>
<icon icon="calendar" />
</span>
{{ $t('navigation.overview') }}
</router-link>
</li>
<li>
<router-link :to="{ name: 'tasks.range'}" v-shortcut="'g u'">
<router-link
v-shortcut="'g u'"
:to="{ name: 'tasks.range'}"
>
<span class="menu-item-icon icon">
<icon :icon="['far', 'calendar-alt']"/>
<icon :icon="['far', 'calendar-alt']" />
</span>
{{ $t('navigation.upcoming') }}
</router-link>
</li>
<li>
<router-link :to="{ name: 'projects.index'}" v-shortcut="'g p'">
<router-link
v-shortcut="'g p'"
:to="{ name: 'projects.index'}"
>
<span class="menu-item-icon icon">
<icon icon="layer-group"/>
<icon icon="layer-group" />
</span>
{{ $t('project.projects') }}
</router-link>
</li>
<li>
<router-link :to="{ name: 'labels.index'}" v-shortcut="'g a'">
<router-link
v-shortcut="'g a'"
:to="{ name: 'labels.index'}"
>
<span class="menu-item-icon icon">
<icon icon="tags"/>
<icon icon="tags" />
</span>
{{ $t('label.title') }}
</router-link>
</li>
<li>
<router-link :to="{ name: 'teams.index'}" v-shortcut="'g m'">
<router-link
v-shortcut="'g m'"
:to="{ name: 'teams.index'}"
>
<span class="menu-item-icon icon">
<icon icon="users"/>
<icon icon="users" />
</span>
{{ $t('team.title') }}
</router-link>
@ -53,7 +77,10 @@
variant="small"
/>
<template v-else>
<nav class="menu" v-if="favoriteProjects">
<nav
v-if="favoriteProjects"
class="menu"
>
<ProjectsNavigation
:model-value="favoriteProjects"
:can-edit-order="false"
@ -61,7 +88,10 @@
/>
</nav>
<nav class="menu" v-if="savedFilterProjects">
<nav
v-if="savedFilterProjects"
class="menu"
>
<ProjectsNavigation
:model-value="savedFilterProjects"
:can-edit-order="false"
@ -79,7 +109,7 @@
</nav>
</template>
<PoweredByLink/>
<PoweredByLink />
</aside>
</template>

View File

@ -6,19 +6,28 @@ import XButton from './button.vue'
<template>
<Story :layout="{ type: 'grid', width: '200px' }">
<Variant title="primary">
<XButton @click="logEvent('Click', $event)" variant="primary">
<XButton
variant="primary"
@click="logEvent('Click', $event)"
>
Order pizza!
</XButton>
</Variant>
<Variant title="secondary">
<XButton @click="logEvent('Click', $event)" variant="secondary">
<XButton
variant="secondary"
@click="logEvent('Click', $event)"
>
Order spaghetti!
</XButton>
</Variant>
<Variant title="tertiary">
<XButton @click="logEvent('Click', $event)" variant="tertiary">
<XButton
variant="tertiary"
@click="logEvent('Click', $event)"
>
Order tortellini!
</XButton>
</Variant>

View File

@ -1,36 +1,67 @@
<template>
<div class="color-picker-container">
<datalist :id="colorListID">
<option v-for="defaultColor in defaultColors" :key="defaultColor" :value="defaultColor" />
<option
v-for="defaultColor in defaultColors"
:key="defaultColor"
:value="defaultColor"
/>
</datalist>