1
0

Move buttons to separate component (#380)

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/380
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
This commit is contained in:
konrad
2021-01-17 17:57:57 +00:00
parent f3e0b79b26
commit 2aceca54ca
61 changed files with 2315 additions and 1825 deletions

View File

@ -3,13 +3,13 @@
<h2>Hi {{ userInfo.name !== '' ? userInfo.name : userInfo.username }}!</h2>
<template v-if="!hasTasks">
<p>Click on a list or namespace on the left to get started.</p>
<router-link
<x-button
:to="{name: 'migrate.start'}"
class="button is-primary has-no-shadow"
:shadow="false"
v-if="migratorsEnabled"
>
Import your data into Vikunja
</router-link>
</x-button>
</template>
<ShowTasks :show-all="true"/>
</div>

View File

@ -2,64 +2,60 @@
<div class="modal-mask keyboard-shortcuts-modal">
<div @click.self="$router.back()" class="modal-container">
<div class="modal-content">
<div class="card has-background-white has-no-shadow">
<header class="card-header">
<p class="card-header-title">Create A Saved Filter</p>
</header>
<div class="card-content content">
<p>
A saved filter is a virtual list which is computed from a set of filters each time it is
accessed. Once created, it will appear in a special namespace.
</p>
<div class="field">
<label class="label" for="title">Title</label>
<div class="control">
<input
v-model="savedFilter.title"
:class="{ 'disabled': savedFilterService.loading}"
:disabled="savedFilterService.loading"
class="input"
id="Title"
placeholder="The saved filter title goes here..."
type="text"
v-focus
/>
</div>
<card class="has-background-white has-no-shadow" title="Create A Saved Filter">
<p>
A saved filter is a virtual list which is computed from a set of filters each time it is
accessed. Once created, it will appear in a special namespace.
</p>
<div class="field">
<label class="label" for="title">Title</label>
<div class="control">
<input
v-model="savedFilter.title"
:class="{ 'disabled': savedFilterService.loading}"
:disabled="savedFilterService.loading"
class="input"
id="Title"
placeholder="The saved filter title goes here..."
type="text"
v-focus
/>
</div>
<div class="field">
<label class="label" for="description">Description</label>
<div class="control">
<editor
v-model="savedFilter.description"
:class="{ 'disabled': savedFilterService.loading}"
:disabled="savedFilterService.loading"
:preview-is-default="false"
id="description"
placeholder="The description goes here..."
v-if="editorActive"
/>
</div>
</div>
<div class="field">
<label class="label" for="filters">Filters</label>
<div class="control">
<filters
:class="{ 'disabled': savedFilterService.loading}"
:disabled="savedFilterService.loading"
class="has-no-shadow has-no-border"
v-model="filters"
/>
</div>
</div>
<button
:class="{ 'disabled': savedFilterService.loading}"
:disabled="savedFilterService.loading"
@click="create()"
class="button is-primary is-fullwidth">
Create new saved filter
</button>
</div>
</div>
<div class="field">
<label class="label" for="description">Description</label>
<div class="control">
<editor
v-model="savedFilter.description"
:class="{ 'disabled': savedFilterService.loading}"
:disabled="savedFilterService.loading"
:preview-is-default="false"
id="description"
placeholder="The description goes here..."
v-if="editorActive"
/>
</div>
</div>
<div class="field">
<label class="label" for="filters">Filters</label>
<div class="control">
<filters
:class="{ 'disabled': savedFilterService.loading}"
:disabled="savedFilterService.loading"
class="has-no-shadow has-no-border"
v-model="filters"
/>
</div>
</div>
<x-button
:loading="savedFilterService.loading"
:disabled="savedFilterService.loading"
@click="create()"
class="is-fullwidth"
>
Create new saved filter
</x-button>
</card>
</div>
</div>
</div>

View File

@ -1,78 +1,67 @@
<template>
<div :class="{ 'is-loading': filterService.loading}" class="loader-container edit-list is-max-width-desktop">
<div class="card">
<header class="card-header">
<p class="card-header-title">
Edit Saved Filter
</p>
</header>
<div class="card-content">
<div class="content">
<form @submit.prevent="save()">
<div class="field">
<label class="label" for="listtext">Filter Name</label>
<div class="control">
<input
:class="{ 'disabled': filterService.loading}"
:disabled="filterService.loading"
@keyup.enter="save"
class="input"
id="listtext"
placeholder="The list title goes here..."
type="text"
v-focus
v-model="filter.title"/>
</div>
</div>
<div class="field">
<label class="label" for="listdescription">Description</label>
<div class="control">
<editor
:class="{ 'disabled': filterService.loading}"
:disabled="filterService.loading"
:preview-is-default="false"
id="listdescription"
placeholder="The lists description goes here..."
v-model="filter.description"
/>
</div>
</div>
<div class="field">
<label class="label" for="filters">Filters</label>
<div class="control">
<filters
:class="{ 'disabled': filterService.loading}"
:disabled="filterService.loading"
class="has-no-shadow has-no-border"
v-model="filters"
/>
</div>
</div>
</form>
<div class="field has-addons mt-4">
<div class="control is-fullwidth">
<button
@click="save()"
:class="{ 'is-loading': filterService.loading}"
class="button is-primary is-fullwidth">
Save
</button>
</div>
<div class="control">
<button
@click="showDeleteModal = true"
:class="{ 'is-loading': filterService.loading}"
class="button is-danger">
<span class="icon">
<icon icon="trash-alt"/>
</span>
</button>
</div>
<card title="Edit Saved Filter">
<form @submit.prevent="save()">
<div class="field">
<label class="label" for="listtext">Filter Name</label>
<div class="control">
<input
:class="{ 'disabled': filterService.loading}"
:disabled="filterService.loading"
@keyup.enter="save"
class="input"
id="listtext"
placeholder="The list title goes here..."
type="text"
v-focus
v-model="filter.title"/>
</div>
</div>
<div class="field">
<label class="label" for="listdescription">Description</label>
<div class="control">
<editor
:class="{ 'disabled': filterService.loading}"
:disabled="filterService.loading"
:preview-is-default="false"
id="listdescription"
placeholder="The lists description goes here..."
v-model="filter.description"
/>
</div>
</div>
<div class="field">
<label class="label" for="filters">Filters</label>
<div class="control">
<filters
:class="{ 'disabled': filterService.loading}"
:disabled="filterService.loading"
class="has-no-shadow has-no-border"
v-model="filters"
/>
</div>
</div>
</form>
<div class="field has-addons mt-4">
<div class="control is-fullwidth">
<x-button
@click="save()"
:loading="filterService.loading"
class="is-fullwidth">
Save
</x-button>
</div>
<div class="control">
<x-button
@click="showDeleteModal = true"
:loading="filterService.loading"
class="is-danger"
icon="trash-alt"
/>
</div>
</div>
</div>
</card>
<modal
@close="showDeleteModal = false"

View File

@ -1,17 +1,23 @@
<template>
<div :class="{ 'is-loading': labelService.loading}" class="loader-container content">
<router-link :to="{name:'labels.create'}" class="button is-primary button-right">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<div :class="{ 'is-loading': labelService.loading}" class="loader-container">
<x-button
:to="{name:'labels.create'}"
class="is-pulled-right"
icon="plus"
>
New label
</router-link>
<h1>Manage labels</h1>
<p>
Click on a label to edit it.
You can edit all labels you created, you can use all labels which are associated with a task to whose list
you have access.
</p>
</x-button>
<div class="content">
<h1>Manage labels</h1>
<p>
Click on a label to edit it.
You can edit all labels you created, you can use all labels which are associated with a task to whose
list
you have access.
</p>
</div>
<div class="columns">
<div class="labels-list column">
<span
@ -35,66 +41,55 @@
</span>
</div>
<div class="column is-4" v-if="isLabelEdit">
<div class="card">
<header class="card-header">
<span class="card-header-title">
Edit Label
</span>
<a @click="isLabelEdit = false" class="card-header-icon">
<span class="icon">
<icon icon="times"/>
</span>
</a>
</header>
<div class="card-content">
<form @submit.prevent="editLabelSubmit()">
<div class="field">
<label class="label">Title</label>
<div class="control">
<input
class="input"
placeholder="Label title"
type="text"
v-model="labelEditLabel.title"/>
</div>
<card title="Edit Label" :has-close="true" @close="() => isLabelEdit = false">
<form @submit.prevent="editLabelSubmit()">
<div class="field">
<label class="label">Title</label>
<div class="control">
<input
class="input"
placeholder="Label title"
type="text"
v-model="labelEditLabel.title"/>
</div>
<div class="field">
<label class="label">Description</label>
<div class="control">
<editor
:preview-is-default="false"
placeholder="Label description"
v-if="editorActive"
v-model="labelEditLabel.description"
/>
</div>
</div>
<div class="field">
<label class="label">Description</label>
<div class="control">
<editor
:preview-is-default="false"
placeholder="Label description"
v-if="editorActive"
v-model="labelEditLabel.description"
/>
</div>
<div class="field">
<label class="label">Color</label>
<div class="control">
<color-picker v-model="labelEditLabel.hexColor"/>
</div>
</div>
<div class="field">
<label class="label">Color</label>
<div class="control">
<color-picker v-model="labelEditLabel.hexColor"/>
</div>
<div class="field has-addons">
<div class="control is-expanded">
<button :class="{ 'is-loading': labelService.loading}" class="button is-fullwidth is-primary"
type="submit">
Save
</button>
</div>
<div class="control">
<a
@click="() => {deleteLabel(labelEditLabel);isLabelEdit = false}"
class="button has-icon is-danger">
<span class="icon">
<icon icon="trash-alt"/>
</span>
</a>
</div>
</div>
<div class="field has-addons">
<div class="control is-expanded">
<x-button
:loading="labelService.loading"
class="is-fullwidth"
@click="editLabelSubmit()"
>
Save
</x-button>
</div>
</form>
</div>
</div>
<div class="control">
<x-button
@click="() => {deleteLabel(labelEditLabel);isLabelEdit = false}"
icon="trash-alt"
class="is-danger"
/>
</div>
</div>
</form>
</card>
</div>
</div>
</div>

View File

@ -15,12 +15,13 @@
v-model="label.title"/>
</p>
<p class="control">
<button class="button is-primary has-no-shadow" type="submit">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<x-button
:shadow="false"
icon="plus"
@click="newlabel"
>
Add
</button>
</x-button>
</p>
</div>
<p class="help is-danger" v-if="showError && label.title === ''">

View File

@ -4,132 +4,112 @@
This list is archived.
It is not possible to create new or edit tasks or it.
</div>
<div class="card">
<header class="card-header">
<p class="card-header-title">
Edit List
</p>
</header>
<div class="card-content">
<div class="content">
<form @submit.prevent="submit()">
<div class="field">
<label class="label" for="listtext">List Name</label>
<div class="control">
<input
:class="{ 'disabled': listService.loading}"
:disabled="listService.loading"
@keyup.enter="submit"
class="input"
id="listtext"
placeholder="The list title goes here..."
type="text"
v-focus
v-model="list.title"/>
</div>
</div>
<div class="field">
<label
class="label"
for="listtext"
v-tooltip="'The list identifier can be used to uniquely identify a task across lists. You can set it to empty to disable it.'">
List Identifier
</label>
<div class="control">
<input
:class="{ 'disabled': listService.loading}"
:disabled="listService.loading"
@keyup.enter="submit"
class="input"
id="listtext"
placeholder="The list identifier goes here..."
type="text"
v-focus
v-model="list.identifier"/>
</div>
</div>
<div class="field">
<label class="label" for="listdescription">Description</label>
<div class="control">
<editor
:class="{ 'disabled': listService.loading}"
:disabled="listService.loading"
:preview-is-default="false"
id="listdescription"
placeholder="The lists description goes here..."
v-model="list.description"
/>
</div>
</div>
<div class="field">
<label class="label" for="isArchivedCheck">Is Archived</label>
<div class="control">
<fancycheckbox
v-model="list.isArchived"
v-tooltip="'If a list is archived, you cannot create new tasks or edit the list or existing tasks.'">
This list is archived
</fancycheckbox>
</div>
</div>
<div class="field">
<label class="label">Color</label>
<div class="control">
<color-picker v-model="list.hexColor"/>
</div>
</div>
</form>
<div class="field has-addons mt-4">
<div class="control is-fullwidth">
<button
@click="submit()"
:class="{ 'is-loading': listService.loading}"
class="button is-primary is-fullwidth">
Save
</button>
</div>
<div class="control">
<button
@click="showDeleteModal = true"
:class="{ 'is-loading': listService.loading}"
class="button is-danger">
<span class="icon">
<icon icon="trash-alt"/>
</span>
</button>
</div>
<card title="Edit List">
<form @submit.prevent="submit()">
<div class="field">
<label class="label" for="listtext">List Name</label>
<div class="control">
<input
:class="{ 'disabled': listService.loading}"
:disabled="listService.loading"
@keyup.enter="submit"
class="input"
id="listtext"
placeholder="The list title goes here..."
type="text"
v-focus
v-model="list.title"/>
</div>
</div>
</div>
</div>
<div class="card has-overflow">
<header class="card-header">
<p class="card-header-title">
Duplicate this list
</p>
</header>
<div class="card-content">
<div class="content">
<p>Select a namespace which should hold the duplicated list:</p>
<div class="field has-addons">
<div class="control is-expanded">
<namespace-search @selected="selectNamespace"/>
</div>
<div class="control">
<button
:class="{'is-loading': listDuplicateService.loading}"
@click="duplicateList"
class="button is-primary"
type="submit">
Duplicate
</button>
</div>
<div class="field">
<label
class="label"
for="listtext"
v-tooltip="'The list identifier can be used to uniquely identify a task across lists. You can set it to empty to disable it.'">
List Identifier
</label>
<div class="control">
<input
:class="{ 'disabled': listService.loading}"
:disabled="listService.loading"
@keyup.enter="submit"
class="input"
id="listtext"
placeholder="The list identifier goes here..."
type="text"
v-focus
v-model="list.identifier"/>
</div>
</div>
<div class="field">
<label class="label" for="listdescription">Description</label>
<div class="control">
<editor
:class="{ 'disabled': listService.loading}"
:disabled="listService.loading"
:preview-is-default="false"
id="listdescription"
placeholder="The lists description goes here..."
v-model="list.description"
/>
</div>
</div>
<div class="field">
<label class="label" for="isArchivedCheck">Is Archived</label>
<div class="control">
<fancycheckbox
v-model="list.isArchived"
v-tooltip="'If a list is archived, you cannot create new tasks or edit the list or existing tasks.'">
This list is archived
</fancycheckbox>
</div>
</div>
<div class="field">
<label class="label">Color</label>
<div class="control">
<color-picker v-model="list.hexColor"/>
</div>
</div>
</form>
<div class="field has-addons mt-4">
<div class="control is-fullwidth">
<x-button
@click="submit()"
:loading="listService.loading"
class="is-fullwidth">
Save
</x-button>
</div>
<div class="control">
<x-button
@click="showDeleteModal = true"
:locading="listService.loading"
icon="trash-alt"
class="is-danger"
/>
</div>
</div>
</div>
</card>
<!-- Duplicate list -->
<card class="has-overflow" title="Duplicate this list">
<p>Select a namespace which should hold the duplicated list:</p>
<div class="field has-addons">
<div class="control is-expanded">
<namespace-search @selected="selectNamespace"/>
</div>
<div class="control">
<x-button
:loading="listDuplicateService.loading"
@click="duplicateList"
>
Duplicate
</x-button>
</div>
</div>
</card>
<background :list-id="$route.params.id"/>

View File

@ -18,12 +18,14 @@
v-model="list.title"/>
</p>
<p class="control">
<button :disabled="list.title === ''" @click="newList()" class="button is-primary has-no-shadow">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<x-button
:disabled="list.title === ''"
@click="newList()"
icon="plus"
:shadow="false"
>
Add
</button>
</x-button>
</p>
</div>
<p class="help is-danger" v-if="showError && list.title === ''">

View File

@ -2,12 +2,13 @@
<div class="kanban-view">
<div class="filter-container" v-if="list.isSavedFilter && !list.isSavedFilter()">
<div class="items">
<button @click.prevent.stop="showFilters = !showFilters" class="button">
<span class="icon is-small">
<icon icon="filter"/>
</span>
<x-button
@click.prevent.stop="showFilters = !showFilters"
icon="filter"
type="secondary"
>
Filters
</button>
</x-button>
</div>
<filter-popup
@change="() => {filtersChanged = true; loadBuckets()}"
@ -59,11 +60,10 @@
/>
</div>
<div class="control">
<a class="button is-primary has-no-shadow">
<span class="icon">
<icon :icon="['far', 'save']"/>
</span>
</a>
<x-button
:icon="['far', 'save']"
:shadow="false"
/>
</div>
</div>
<template v-else>
@ -191,20 +191,21 @@
Please specify a title.
</p>
</div>
<a
<x-button
@click="toggleShowNewTaskInput(bucket.id)"
class="button has-no-shadow is-transparent is-fullwidth has-text-centered"
v-if="!showNewTaskInput[bucket.id]">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<span v-if="bucket.tasks.length === 0">
Add a task
</span>
<span v-else>
Add another task
</span>
</a>
class="is-transparent is-fullwidth has-text-centered"
:shadow="false"
v-if="!showNewTaskInput[bucket.id]"
icon="plus"
type="secondary"
>
<template v-if="bucket.tasks.length === 0">
Add a task
</template>
<template v-else>
Add another task
</template>
</x-button>
</div>
</div>
@ -222,16 +223,16 @@
v-if="showNewBucketInput"
v-model="newBucketTitle"
/>
<a
<x-button
@click="() => showNewBucketInput = true"
class="button has-no-shadow is-transparent is-fullwidth has-text-centered" v-if="!showNewBucketInput">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<span>
Create a new bucket
</span>
</a>
:shadow="false"
class="is-transparent is-fullwidth has-text-centered"
v-if="!showNewBucketInput"
type="secondary"
icon="plus"
>
Create a new bucket
</x-button>
</div>
</div>
@ -269,7 +270,7 @@ import {applyDrag} from '@/helpers/applyDrag'
import {mapState} from 'vuex'
import {saveListView} from '@/helpers/saveListView'
import Rights from '../../../models/rights.json'
import { LOADING, LOADING_MODULE } from '../../../store/mutation-types'
import {LOADING, LOADING_MODULE} from '../../../store/mutation-types'
import FilterPopup from '@/components/list/partials/filter-popup'
export default {

View File

@ -1,5 +1,7 @@
<template>
<div :class="{ 'is-loading': taskCollectionService.loading}" class="loader-container is-max-width-desktop list-view">
<div
:class="{ 'is-loading': taskCollectionService.loading}"
class="loader-container is-max-width-desktop list-view">
<div class="filter-container" v-if="list.isSavedFilter && !list.isSavedFilter()">
<div class="items">
<div class="search">
@ -18,26 +20,29 @@
</span>
</div>
<div class="control">
<button
:class="{'is-loading': taskCollectionService.loading}"
<x-button
:loading="taskCollectionService.loading"
@click="searchTasks"
class="button has-no-shadow is-primary">
:shadow="false"
>
Search
</button>
</x-button>
</div>
</div>
<button @click="showTaskSearch = !showTaskSearch" class="button" v-if="!showTaskSearch">
<span class="icon">
<icon icon="search"/>
</span>
</button>
<x-button
@click="showTaskSearch = !showTaskSearch"
icon="search"
type="secondary"
v-if="!showTaskSearch"
/>
</div>
<button @click.prevent.stop="showTaskFilter = !showTaskFilter" class="button">
<span class="icon is-small">
<icon icon="filter"/>
</span>
<x-button
@click.prevent.stop="showTaskFilter = !showTaskFilter"
type="secondary"
icon="filter"
>
Filters
</button>
</x-button>
</div>
<filter-popup
@change="loadTasks(1)"
@ -62,12 +67,13 @@
</span>
</p>
<p class="control">
<button :disabled="newTaskText.length === 0" @click="addTask()" class="button is-primary">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<x-button
:disabled="newTaskText.length === 0"
@click="addTask()"
icon="plus"
>
Add
</button>
</x-button>
</p>
</div>
<p class="help is-danger" v-if="showError && newTaskText === ''">
@ -97,23 +103,9 @@
</div>
</div>
<div class="column is-4" v-if="isTaskEdit">
<div class="card taskedit">
<header class="card-header">
<p class="card-header-title">
Edit Task
</p>
<a @click="isTaskEdit = false" class="card-header-icon">
<span class="icon">
<icon icon="angle-right"/>
</span>
</a>
</header>
<div class="card-content">
<div class="content">
<edit-task :task="taskEditTask"/>
</div>
</div>
</div>
<card class="taskedit" title="Edit Task" :has-close="true" @close="() => isTaskEdit = false">
<edit-task :task="taskEditTask"/>
</card>
</div>
</div>

View File

@ -2,39 +2,37 @@
<div :class="{'is-loading': taskCollectionService.loading}" class="table-view loader-container">
<div class="filter-container">
<div class="items">
<button @click.prevent.stop="() => {showActiveColumnsFilter = !showActiveColumnsFilter; showTaskFilter = false}"
class="button">
<span class="icon is-small">
<icon icon="th"/>
</span>
<x-button
@click.prevent.stop="() => {showActiveColumnsFilter = !showActiveColumnsFilter; showTaskFilter = false}"
icon="th"
type="secondary"
>
Columns
</button>
<button @click.prevent.stop="() => {showTaskFilter = !showTaskFilter; showActiveColumnsFilter = false}"
class="button">
<span class="icon is-small">
<icon icon="filter"/>
</span>
</x-button>
<x-button
@click.prevent.stop="() => {showTaskFilter = !showTaskFilter; showActiveColumnsFilter = false}"
icon="filter"
type="secondary"
>
Filters
</button>
</x-button>
</div>
<transition name="fade">
<div class="card" v-if="showActiveColumnsFilter">
<div class="card-content">
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.id">#</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.done">Done</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.title">Title</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.priority">Priority</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.labels">Labels</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.assignees">Assignees</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.dueDate">Due Date</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.startDate">Start Date</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.endDate">End Date</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.percentDone">% Done</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.created">Created</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.updated">Updated</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.createdBy">Created By</fancycheckbox>
</div>
</div>
<card v-if="showActiveColumnsFilter">
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.id">#</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.done">Done</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.title">Title</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.priority">Priority</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.labels">Labels</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.assignees">Assignees</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.dueDate">Due Date</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.startDate">Start Date</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.endDate">End Date</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.percentDone">% Done</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.created">Created</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.updated">Updated</fancycheckbox>
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.createdBy">Created By</fancycheckbox>
</card>
</transition>
<filter-popup
@change="loadTasks(1)"
@ -174,7 +172,8 @@
:aria-label="'Goto page ' + p.number"
:class="{'is-current': p.number === currentPage}"
:to="getRouteForPagination(p.number, 'table')"
class="pagination-link">{{ p.number }}
class="pagination-link">
{{ p.number }}
</router-link>
</li>
</template>

View File

@ -4,84 +4,74 @@
This namespace is archived.
It is not possible to create new lists or edit it.
</div>
<div class="card">
<header class="card-header">
<p class="card-header-title">
Edit Namespace
</p>
</header>
<div class="card-content">
<div class="content">
<form @submit.prevent="submit()">
<div class="field">
<label class="label" for="namespacetext">Namespace Name</label>
<div class="control">
<input
:class="{ 'disabled': namespaceService.loading}"
:disabled="namespaceService.loading"
class="input"
id="namespacetext"
placeholder="The namespace text is here..."
type="text"
v-focus
v-model="namespace.title"/>
</div>
</div>
<div class="field">
<label class="label" for="namespacedescription">Description</label>
<div class="control">
<editor
:class="{ 'disabled': namespaceService.loading}"
:disabled="namespaceService.loading"
:preview-is-default="false"
id="namespacedescription"
placeholder="The namespaces description goes here..."
v-if="editorActive"
v-model="namespace.description"
/>
</div>
</div>
<div class="field">
<label class="label" for="isArchivedCheck">Is Archived</label>
<div class="control">
<fancycheckbox
v-model="namespace.isArchived"
v-tooltip="'If a namespace is archived, you cannot create new lists or edit it.'">
This namespace is archived
</fancycheckbox>
</div>
</div>
<div class="field">
<label class="label">Color</label>
<div class="control">
<color-picker v-model="namespace.hexColor"/>
</div>
</div>
</form>
<div class="field has-addons mt-4">
<div class="control is-fullwidth">
<button
@click="submit()"
:class="{ 'is-loading': namespaceService.loading}"
class="button is-primary is-fullwidth">
Save
</button>
</div>
<div class="control">
<button
@click="showDeleteModal = true"
:class="{ 'is-loading': namespaceService.loading}"
class="button is-danger">
<span class="icon">
<icon icon="trash-alt"/>
</span>
</button>
</div>
<card title="Edit Namespace">
<form @submit.prevent="submit()">
<div class="field">
<label class="label" for="namespacetext">Namespace Name</label>
<div class="control">
<input
:class="{ 'disabled': namespaceService.loading}"
:disabled="namespaceService.loading"
class="input"
id="namespacetext"
placeholder="The namespace text is here..."
type="text"
v-focus
v-model="namespace.title"/>
</div>
</div>
<div class="field">
<label class="label" for="namespacedescription">Description</label>
<div class="control">
<editor
:class="{ 'disabled': namespaceService.loading}"
:disabled="namespaceService.loading"
:preview-is-default="false"
id="namespacedescription"
placeholder="The namespaces description goes here..."
v-if="editorActive"
v-model="namespace.description"
/>
</div>
</div>
<div class="field">
<label class="label" for="isArchivedCheck">Is Archived</label>
<div class="control">
<fancycheckbox
v-model="namespace.isArchived"
v-tooltip="'If a namespace is archived, you cannot create new lists or edit it.'">
This namespace is archived
</fancycheckbox>
</div>
</div>
<div class="field">
<label class="label">Color</label>
<div class="control">
<color-picker v-model="namespace.hexColor"/>
</div>
</div>
</form>
<div class="field has-addons mt-4">
<div class="control is-fullwidth">
<x-button
@click="submit()"
:loading="namespaceService.loading"
class="is-fullwidth"
>
Save
</x-button>
</div>
<div class="control">
<x-button
@click="showDeleteModal = true"
:loading="namespaceService.loading"
class="is-danger"
icon="trash-alt"
/>
</div>
</div>
</div>
</card>
<component
:id="namespace.id"

View File

@ -1,32 +1,26 @@
<template>
<div class="content namespaces-list loader-container" :class="{'is-loading': loading}">
<router-link :to="{name: 'namespace.create'}" class="button is-primary new-namespace">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<x-button :to="{name: 'namespace.create'}" class="new-namespace" icon="plus">
Create namespace
</router-link>
<router-link :to="{name: 'filters.create'}" class="button is-primary new-namespace">
<span class="icon is-small">
<icon icon="filter"/>
</span>
</x-button>
<x-button :to="{name: 'filters.create'}" class="new-namespace" icon="filter">
Create saved filter
</router-link>
</x-button>
<fancycheckbox class="show-archived-check" v-model="showArchived">
Show Archived
</fancycheckbox>
<div :key="`n${n.id}`" class="namespace" v-for="n in namespaces">
<router-link
<x-button
:to="{name: 'list.create', params: {id: n.id}}"
class="button is-pulled-right"
v-if="n.id > 0">
<span class="icon is-small">
<icon icon="plus"/>
</span>
class="is-pulled-right"
type="secondary"
v-if="n.id > 0"
icon="plus"
>
Create list
</router-link>
</x-button>
<h1>
<span>{{ n.title }}</span>

View File

@ -18,12 +18,14 @@
v-model="namespace.title"/>
</p>
<p class="control">
<button :disabled="namespace.title === ''" @click="newNamespace()" class="button is-primary has-no-shadow">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<x-button
:disabled="namespace.title === ''"
@click="newNamespace()"
:shadow="false"
icon="plus"
>
Add
</button>
</x-button>
</p>
</div>
<p class="help is-danger" v-if="showError && namespace.title === ''">

View File

@ -30,9 +30,9 @@
/>
</h3>
<div v-if="!showAll">
<a @click="showTodaysTasks()" class="button has-no-shadow mr-2">Today</a>
<a @click="setDatesToNextWeek()" class="button has-no-shadow mr-2">Next Week</a>
<a @click="setDatesToNextMonth()" class="button has-no-shadow">Next Month</a>
<x-button type="secondary" @click="showTodaysTasks()" :shadow="false" class="mr-2">Today</x-button>
<x-button type="secondary" @click="setDatesToNextWeek()" :shadow="false" class="mr-2">Next Week</x-button>
<x-button type="secondary" @click="setDatesToNextMonth()" :shadow="false">Next Month</x-button>
</div>
<template v-if="!taskService.loading && (!hasUndoneTasks || !tasks || tasks.length === 0)">
<h3 class="nothing">Nothing to do - Have a nice day!</h3>

View File

@ -56,8 +56,11 @@
choose-date-label="Click here to set a due date"
:disabled="taskService.loading || !canWrite"
ref="dueDate"
/>
<a @click="() => {task.dueDate = null;saveTask()}" v-if="task.dueDate && canWrite" class="remove">
/>
<a
@click="() => {task.dueDate = null;saveTask()}"
v-if="task.dueDate && canWrite"
class="remove">
<span class="icon is-small">
<icon icon="times"></icon>
</span>
@ -94,7 +97,11 @@
:disabled="taskService.loading || !canWrite"
ref="startDate"
/>
<a @click="() => {task.startDate = null;saveTask()}" v-if="task.startDate && canWrite" class="remove">
<a
@click="() => {task.startDate = null;saveTask()}"
v-if="task.startDate && canWrite"
class="remove"
>
<span class="icon is-small">
<icon icon="times"></icon>
</span>
@ -117,7 +124,10 @@
:disabled="taskService.loading || !canWrite"
ref="endDate"
/>
<a @click="() => {task.endDate = null;saveTask()}" v-if="task.endDate && canWrite" class="remove">
<a
@click="() => {task.endDate = null;saveTask()}"
v-if="task.endDate && canWrite"
class="remove">
<span class="icon is-small">
<icon icon="times"></icon>
</span>
@ -235,94 +245,124 @@
<comments :can-write="canWrite" :task-id="taskId"/>
</div>
<div class="column is-one-third action-buttons" v-if="canWrite">
<a
:class="{'is-success': !task.done, 'has-no-shadow': !task.done}"
<x-button
:class="{'is-success': !task.done}"
:shadow="task.done"
@click="toggleTaskDone()"
class="button is-outlined has-no-border">
<span class="icon is-small"><icon icon="check-double"/></span>
<template v-if="task.done">
Mark as undone
</template>
<template v-else>
Done!
</template>
</a>
<a
class="is-outlined has-no-border"
icon="check-double"
type="secondary"
>
{{ task.done ? 'Mark as undone' : 'Done!' }}
</x-button>
<x-button
@click="setFieldActive('assignees')"
@shortkey="setFieldActive('assignees')"
class="button"
type="secondary"
v-shortkey="['a']">
<span class="icon is-small"><icon icon="users"/></span>
Assign this task to a user
</a>
<a
</x-button>
<x-button
@click="setFieldActive('labels')"
@shortkey="setFieldActive('labels')"
class="button"
v-shortkey="['l']">
<span class="icon is-small"><icon icon="tags"/></span>
type="secondary"
v-shortkey="['l']"
icon="tags"
>
Add labels
</a>
<a @click="setFieldActive('priority')" class="button">
<span class="icon is-small"><icon :icon="['far', 'star']"/></span>
</x-button>
<x-button
@click="setFieldActive('priority')"
type="secondary"
:icon="['far', 'star']"
>
Set Priority
</a>
<a
</x-button>
<x-button
@click="setFieldActive('dueDate')"
@shortkey="setFieldActive('dueDate')"
class="button"
v-shortkey="['d']">
<span class="icon is-small"><icon icon="calendar"/></span>
type="secondary"
v-shortkey="['d']"
icon="calendar"
>
Set Due Date
</a>
<a @click="setFieldActive('startDate')" class="button">
<span class="icon is-small"><icon icon="calendar-week"/></span>
</x-button>
<x-button
@click="setFieldActive('startDate')"
type="secondary"
icon="calendar-week"
>
Set a Start Date
</a>
<a @click="setFieldActive('endDate')" class="button">
<span class="icon is-small"><icon icon="calendar-week"/></span>
</x-button>
<x-button
@click="setFieldActive('endDate')"
type="secondary"
icon="calendar-week"
>
Set an End Date
</a>
<a @click="setFieldActive('reminders')" class="button">
<span class="icon is-small"><icon icon="history"/></span>
</x-button>
<x-button
@click="setFieldActive('reminders')"
type="secondary"
icon="history"
>
Set Reminders
</a>
<a @click="setFieldActive('repeatAfter')" class="button">
<span class="icon is-small"><icon :icon="['far', 'clock']"/></span>
</x-button>
<x-button
@click="setFieldActive('repeatAfter')"
type="secondary"
:icon="['far', 'clock']"
>
Set a repeating interval
</a>
<a @click="setFieldActive('percentDone')" class="button">
<span class="icon is-small"><icon icon="percent"/></span>
</x-button>
<x-button
@click="setFieldActive('percentDone')"
type="secondary"
icon="percent"
>
Set Percent Done
</a>
<a
</x-button>
<x-button
@click="setFieldActive('attachments')"
@shortkey="setFieldActive('attachments')"
class="button"
v-shortkey="['f']">
<span class="icon is-small"><icon icon="paperclip"/></span>
type="secondary"
v-shortkey="['f']"
icon="paperclip"
>
Add attachments
</a>
<a
</x-button>
<x-button
@click="setFieldActive('relatedTasks')"
@shortkey="setFieldActive('relatedTasks')"
class="button"
v-shortkey="['r']">
<span class="icon is-small"><icon icon="tasks"/></span>
type="secondary"
v-shortkey="['r']"
icon="tasks"
>
Add task relations
</a>
<a @click="setFieldActive('moveList')" class="button">
<span class="icon is-small"><icon icon="list"/></span>
</x-button>
<x-button
@click="setFieldActive('moveList')"
type="secondary"
icon="list"
>
Move task
</a>
<a @click="setFieldActive('color')" class="button">
<span class="icon is-small"><icon icon="fill-drip"/></span>
</x-button>
<x-button
@click="setFieldActive('color')"
type="secondary"
icon="fill-drip"
>
Set task color
</a>
<a @click="showDeleteModal = true" class="button is-danger is-outlined has-no-shadow has-no-border">
<span class="icon is-small"><icon icon="trash-alt"/></span>
</x-button>
<x-button
@click="showDeleteModal = true"
icon="trash-alt"
:shadow="false"
class="is-danger is-outlined has-no-border"
>
Delete task
</a>
</x-button>
<!-- Created / Updated [by] -->
<p class="created">
@ -335,7 +375,7 @@
</template>
<template v-if="task.done">
<br/>
Done <span v-tooltip="doneFormatted">{{ doneSince }}</span>
Done <span v-tooltip="doneFormatted">{{ doneSince }}</span>
</template>
</p>
</div>
@ -568,13 +608,17 @@ export default {
this.activeFields[fieldName] = true
this.$nextTick(() => {
if (this.$refs[fieldName]) {
this.$refs[fieldName].$el.focus();
this.$refs[fieldName].$el.focus()
// scroll the field to the center of the screen if not in viewport already
const boundingRect = this.$refs[fieldName].$el.getBoundingClientRect();
const boundingRect = this.$refs[fieldName].$el.getBoundingClientRect()
if (boundingRect.top > (window.scrollY + window.innerHeight) || boundingRect.top < window.scrollY)
this.$refs[fieldName].$el.scrollIntoView({behavior: "smooth", block: "center", inline: "nearest"});
this.$refs[fieldName].$el.scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'nearest'
})
}
})
},

View File

@ -1,77 +1,75 @@
<template>
<div class="loader-container is-max-width-desktop" :class="{ 'is-loading': teamService.loading}">
<div class="card is-fullwidth" v-if="userIsAdmin">
<header class="card-header">
<p class="card-header-title">
Edit Team
</p>
</header>
<div class="card-content">
<div class="content">
<form @submit.prevent="save()">
<div class="field">
<label class="label" for="teamtext">Team Name</label>
<div class="control">
<input
:class="{ 'disabled': teamMemberService.loading}"
:disabled="teamMemberService.loading"
class="input"
id="teamtext"
placeholder="The team text is here..."
type="text"
v-focus
v-model="team.name"/>
</div>
</div>
<p class="help is-danger" v-if="showError && team.name === ''">
Please specify a name.
</p>
<div class="field">
<label class="label" for="teamdescription">Description</label>
<div class="control">
<editor
:class="{ 'disabled': teamService.loading}"
:disabled="teamService.loading"
:preview-is-default="false"
id="teamdescription"
placeholder="The teams description goes here..."
v-model="team.description"
/>
</div>
</div>
</form>
<div class="field has-addons mt-4">
<div class="control is-fullwidth">
<button
@click="save()"
:class="{ 'is-loading': teamService.loading}"
class="button is-primary is-fullwidth">
Save
</button>
</div>
<div class="control">
<button
@click="showDeleteModal = true"
:class="{ 'is-loading': teamService.loading}"
class="button is-danger">
<span class="icon">
<icon icon="trash-alt"/>
</span>
</button>
</div>
<div
class="loader-container is-max-width-desktop"
:class="{ 'is-loading': teamService.loading }"
>
<card class="is-fullwidth" v-if="userIsAdmin" title="Edit Team">
<form @submit.prevent="save()">
<div class="field">
<label class="label" for="teamtext"
>Team Name</label
>
<div class="control">
<input
:class="{
disabled: teamMemberService.loading,
}"
:disabled="teamMemberService.loading"
class="input"
id="teamtext"
placeholder="The team text is here..."
type="text"
v-focus
v-model="team.name"
/>
</div>
</div>
</div>
</div>
<div class="card is-fullwidth has-overflow">
<header class="card-header">
<p class="card-header-title">
Team Members
<p
class="help is-danger"
v-if="showError && team.name === ''"
>
Please specify a name.
</p>
</header>
<div class="card-content" v-if="userIsAdmin">
<div class="field">
<label class="label" for="teamdescription"
>Description</label
>
<div class="control">
<editor
:class="{ disabled: teamService.loading }"
:disabled="teamService.loading"
:preview-is-default="false"
id="teamdescription"
placeholder="The teams description goes here..."
v-model="team.description"
/>
</div>
</div>
</form>
<div class="field has-addons mt-4">
<div class="control is-fullwidth">
<x-button
@click="save()"
:loading="teamService.loading"
class="is-fullwidth"
>
Save
</x-button>
</div>
<div class="control">
<x-button
@click="showDeleteModal = true"
:loading="teamService.loading"
class="is-danger"
icon="trash-alt"
/>
</div>
</div>
</card>
<card class="is-fullwidth has-overflow" title="Team Members">
<div class="p-4" v-if="userIsAdmin">
<div class="field has-addons">
<div class="control is-expanded">
<multiselect
@ -84,12 +82,9 @@
/>
</div>
<div class="control">
<button class="button is-primary" @click="addUser">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<x-button @click="addUser" icon="plus">
Add To Team
</button>
</x-button>
</div>
</div>
</div>
@ -104,57 +99,68 @@
</td>
<td class="type">
<template v-if="m.admin">
<span class="icon is-small">
<icon icon="lock"/>
</span>
<span class="icon is-small">
<icon icon="lock"/>
</span>
Admin
</template>
<template v-else>
<span class="icon is-small">
<icon icon="user"/>
</span>
<span class="icon is-small">
<icon icon="user"/>
</span>
Member
</template>
</td>
<td class="actions" v-if="userIsAdmin">
<button :class="{'is-loading': teamMemberService.loading}" @click="() => toggleUserType(m)"
class="button buttonright is-primary"
v-if="m.id !== userInfo.id">
<x-button
:loading="teamMemberService.loading"
@click="() => toggleUserType(m)"
class="mr-2"
v-if="m.id !== userInfo.id"
>
Make {{ m.admin ? 'Member' : 'Admin' }}
</button>
<button :class="{'is-loading': teamMemberService.loading}"
</x-button>
<x-button
:loading="teamMemberService.loading"
@click="() => {member = m; showUserDeleteModal = true}"
class="button is-danger"
v-if="m.id !== userInfo.id">
<span class="icon">
<icon icon="trash-alt"/>
</span>
</button>
class="is-danger"
v-if="m.id !== userInfo.id"
icon="trash-alt"
/>
</td>
</tr>
</tbody>
</table>
</div>
</card>
<!-- Team delete modal -->
<modal
@close="showDeleteModal = false"
@submit="deleteTeam()"
v-if="showDeleteModal">
v-if="showDeleteModal"
>
<span slot="header">Delete the team</span>
<p slot="text">Are you sure you want to delete this team and all of its members?<br/>
All team members will loose access to lists and namespaces shared with this team.<br/>
<b>This CANNOT BE UNDONE!</b></p>
<p slot="text">
Are you sure you want to delete this team and all of its
members?<br/>
All team members will loose access to lists and namespaces
shared with this team.<br/>
<b>This CANNOT BE UNDONE!</b>
</p>
</modal>
<!-- User delete modal -->
<modal
@close="showUserDeleteModal = false"
@submit="deleteUser()"
v-if="showUserDeleteModal">
v-if="showUserDeleteModal"
>
<span slot="header">Remove a user from the team</span>
<p slot="text">Are you sure you want to remove this user from the team?<br/>
They will loose access to all lists and namespaces this team has access to.<br/>
<b>This CANNOT BE UNDONE!</b></p>
<p slot="text">
Are you sure you want to remove this user from the team?<br/>
They will loose access to all lists and namespaces this team has
access to.<br/>
<b>This CANNOT BE UNDONE!</b>
</p>
</modal>
</div>
</template>
@ -199,7 +205,9 @@ export default {
components: {
Multiselect,
editor: () => ({
component: import(/* webpackChunkName: "editor" */ '../../components/input/editor'),
component: import(
/* webpackChunkName: "editor" */ '../../components/input/editor'
),
loading: LoadingComponent,
error: ErrorComponent,
timeout: 60000,
@ -213,25 +221,30 @@ export default {
},
watch: {
// call again the method if the route changes
'$route': 'loadTeam',
$route: 'loadTeam',
},
computed: {
userIsAdmin() {
return this.team && this.team.maxRight && this.team.maxRight > Rights.READ
return (
this.team &&
this.team.maxRight &&
this.team.maxRight > Rights.READ
)
},
...mapState({
userInfo: state => state.auth.info,
userInfo: (state) => state.auth.info,
}),
},
methods: {
loadTeam() {
this.team = new TeamModel({id: this.teamId})
this.teamService.get(this.team)
.then(response => {
this.teamService
.get(this.team)
.then((response) => {
this.$set(this, 'team', response)
this.setTitle(`Edit Team ${this.team.name}`)
})
.catch(e => {
.catch((e) => {
this.error(e, this)
})
},
@ -242,32 +255,47 @@ export default {
}
this.showError = false
this.teamService.update(this.team)
.then(response => {
this.teamService
.update(this.team)
.then((response) => {
this.team = response
this.success({message: 'The team was successfully updated.'}, this)
this.success(
{message: 'The team was successfully updated.'},
this
)
})
.catch(e => {
.catch((e) => {
this.error(e, this)
})
},
deleteTeam() {
this.teamService.delete(this.team)
this.teamService
.delete(this.team)
.then(() => {
this.success({message: 'The team was successfully deleted.'}, this)
this.success(
{message: 'The team was successfully deleted.'},
this
)
router.push({name: 'teams.index'})
})
.catch(e => {
.catch((e) => {
this.error(e, this)
})
},
deleteUser() {
this.teamMemberService.delete(this.member)
this.teamMemberService
.delete(this.member)
.then(() => {
this.success({message: 'The user was successfully deleted from the team.'}, this)
this.success(
{
message:
'The user was successfully deleted from the team.',
},
this
)
this.loadTeam()
})
.catch(e => {
.catch((e) => {
this.error(e, this)
})
.finally(() => {
@ -279,29 +307,42 @@ export default {
teamId: this.teamId,
username: this.newMember.username,
})
this.teamMemberService.create(newMember)
this.teamMemberService
.create(newMember)
.then(() => {
this.loadTeam()
this.success({message: 'The team member was successfully added.'}, this)
this.success(
{message: 'The team member was successfully added.'},
this
)
})
.catch(e => {
.catch((e) => {
this.error(e, this)
})
},
toggleUserType(member) {
member.admin = !member.admin
member.teamId = this.teamId
this.teamMemberService.update(member)
.then(r => {
this.teamMemberService
.update(member)
.then((r) => {
for (const tm in this.team.members) {
if (this.team.members[tm].id === member.id) {
this.$set(this.team.members[tm], 'admin', r.admin)
break
}
}
this.success({message: 'The team member was successfully made ' + (member.admin ? 'admin' : 'member') + '.'}, this)
this.success(
{
message:
'The team member was successfully made ' +
(member.admin ? 'admin' : 'member') +
'.',
},
this
)
})
.catch(e => {
.catch((e) => {
this.error(e, this)
})
},
@ -311,11 +352,12 @@ export default {
return
}
this.userService.getAll({}, {s: query})
.then(response => {
this.userService
.getAll({}, {s: query})
.then((response) => {
this.$set(this, 'foundUsers', response)
})
.catch(e => {
.catch((e) => {
this.error(e, this)
})
},

View File

@ -1,11 +1,12 @@
<template>
<div class="content loader-container is-max-width-desktop" v-bind:class="{ 'is-loading': teamService.loading}">
<router-link :to="{name:'teams.create'}" class="button is-primary button-right">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<x-button
:to="{name:'teams.create'}"
class="is-pulled-right"
icon="plus"
>
New Team
</router-link>
</x-button>
<h1>Teams</h1>
<ul class="teams box" v-if="teams.length > 0">

View File

@ -16,12 +16,9 @@
v-model="team.name"/>
</p>
<p class="control">
<button class="button is-primary has-no-shadow" type="submit">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<x-button :shadow="false" @click="newTeam" icon="plus">
Add
</button>
</x-button>
</p>
</div>
<p class="help is-danger" v-if="showError && team.name === ''">

View File

@ -54,12 +54,19 @@
<div class="field is-grouped login-buttons">
<div class="control is-expanded">
<button class="button is-primary" type="submit" v-bind:class="{ 'is-loading': loading}">
<x-button
@click="submit"
:loading="loading"
>
Login
</button>
<router-link :to="{ name: 'user.register' }" class="button" v-if="registrationEnabled">
</x-button>
<x-button
:to="{ name: 'user.register' }"
v-if="registrationEnabled"
type="secondary"
>
Register
</router-link>
</x-button>
</div>
<div class="control">
<router-link :to="{ name: 'user.password-reset.request' }" class="reset-password-link">
@ -73,9 +80,15 @@
</form>
<div v-if="openidConnect.enabled && openidConnect.providers && openidConnect.providers.length > 0" class="mt-4">
<a @click="redirectToProvider(p)" v-for="(p, k) in openidConnect.providers" :key="k" class="button is-fullwidth">
<x-button
@click="redirectToProvider(p)"
v-for="(p, k) in openidConnect.providers"
:key="k"
type="secondary"
class="is-fullwidth"
>
Log in with {{ p.name }}
</a>
</x-button>
</div>
<legal/>

View File

@ -35,9 +35,12 @@
<div class="field is-grouped">
<div class="control">
<button :class="{ 'is-loading': this.passwordResetService.loading}" class="button is-primary"
type="submit">Reset your password
</button>
<x-button
:loading="this.passwordResetService.loading"
@click="submit"
>
Reset your password
</x-button>
</div>
</div>
<div class="notification is-info" v-if="this.passwordResetService.loading">
@ -51,7 +54,9 @@
<div class="notification is-success">
{{ successMessage }}
</div>
<router-link :to="{ name: 'user.login' }" class="button is-primary">Login</router-link>
<x-button :to="{ name: 'user.login' }">
Login
</x-button>
</div>
<legal/>
</div>

View File

@ -62,10 +62,15 @@
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" type="submit" :class="{ 'is-loading': loading}" id="register-submit">
<x-button
:loading="loading"
id="register-submit"
@click="submit"
class="mr-2"
>
Register
</button>
<router-link :to="{ name: 'user.login' }" class="button">Login</router-link>
</x-button>
<x-button :to="{ name: 'user.login' }" type="secondary">Login</x-button>
</div>
</div>
<div class="notification is-info" v-if="loading">
@ -136,9 +141,3 @@ export default {
},
}
</script>
<style scoped>
.button {
margin: 0 0.4em 0 0;
}
</style>

View File

@ -20,11 +20,13 @@
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" type="submit"
v-bind:class="{ 'is-loading': passwordResetService.loading}">Send me a password reset
link
</button>
<router-link :to="{ name: 'user.login' }" class="button">Login</router-link>
<x-button
@click="submit"
:loading="passwordResetService.loading"
>
Send me a password reset link
</x-button>
<x-button :to="{ name: 'user.login' }" type="secondary">Login</x-button>
</div>
</div>
<div class="notification is-danger" v-if="errorMsg">
@ -35,7 +37,7 @@
<div class="notification is-success">
Check your inbox! You should have a mail with instructions on how to reset your password.
</div>
<router-link :to="{ name: 'user.login' }" class="button is-primary">Login</router-link>
<x-button :to="{ name: 'user.login' }">Login</x-button>
</div>
<legal/>
</div>

View File

@ -3,265 +3,216 @@
:class="{ 'is-loading': passwordUpdateService.loading || emailUpdateService.loading || totpService.loading }"
class="loader-container is-max-width-desktop">
<!-- Password update -->
<div class="card">
<header class="card-header">
<p class="card-header-title">
Update Your Password
</p>
</header>
<div class="card-content">
<div class="content">
<form @submit.prevent="updatePassword()">
<div class="field">
<label class="label" for="newPassword">New Password</label>
<div class="control">
<input
@keyup.enter="updatePassword"
class="input"
id="newPassword"
placeholder="The new password..."
type="password"
v-model="passwordUpdate.newPassword"/>
</div>
</div>
<div class="field">
<label class="label" for="newPasswordConfirm">New Password Confirmation</label>
<div class="control">
<input
@keyup.enter="updatePassword"
class="input"
id="newPasswordConfirm"
placeholder="Confirm your new password..."
type="password"
v-model="passwordConfirm"/>
</div>
</div>
<div class="field">
<label class="label" for="currentPassword">Current Password</label>
<div class="control">
<input
@keyup.enter="updatePassword"
class="input"
id="currentPassword"
placeholder="Your current password"
type="password"
v-model="passwordUpdate.oldPassword"/>
</div>
</div>
</form>
<div class="bigbuttons">
<button :class="{ 'is-loading': passwordUpdateService.loading}" @click="updatePassword()"
class="button is-primary is-fullwidth">
Save
</button>
<card title="Update Your Password">
<form @submit.prevent="updatePassword()">
<div class="field">
<label class="label" for="newPassword">New Password</label>
<div class="control">
<input
@keyup.enter="updatePassword"
class="input"
id="newPassword"
placeholder="The new password..."
type="password"
v-model="passwordUpdate.newPassword"/>
</div>
</div>
</div>
</div>
<div class="field">
<label class="label" for="newPasswordConfirm">New Password Confirmation</label>
<div class="control">
<input
@keyup.enter="updatePassword"
class="input"
id="newPasswordConfirm"
placeholder="Confirm your new password..."
type="password"
v-model="passwordConfirm"/>
</div>
</div>
<div class="field">
<label class="label" for="currentPassword">Current Password</label>
<div class="control">
<input
@keyup.enter="updatePassword"
class="input"
id="currentPassword"
placeholder="Your current password"
type="password"
v-model="passwordUpdate.oldPassword"/>
</div>
</div>
</form>
<x-button
:loading="passwordUpdateService.loading"
@click="updatePassword()"
class="is-fullwidth mt-4">
Save
</x-button>
</card>
<!-- Update E-Mail -->
<div class="card">
<header class="card-header">
<p class="card-header-title">
Update Your E-Mail Address
</p>
</header>
<div class="card-content">
<div class="content">
<form @submit.prevent="updateEmail()">
<div class="field">
<label class="label" for="newEmail">New Email Address</label>
<div class="control">
<input
@keyup.enter="updateEmail"
class="input"
id="newEmail"
placeholder="The new email address..."
type="email"
v-model="emailUpdate.newEmail"/>
</div>
</div>
<div class="field">
<label class="label" for="currentPassword">Current Password</label>
<div class="control">
<input
@keyup.enter="updateEmail"
class="input"
id="currentPassword"
placeholder="Your current password"
type="password"
v-model="emailUpdate.password"/>
</div>
</div>
</form>
<div class="bigbuttons">
<button :class="{ 'is-loading': emailUpdateService.loading}" @click="updateEmail()"
class="button is-primary is-fullwidth">
Save
</button>
<card title="Update Your E-Mail Address">
<form @submit.prevent="updateEmail()">
<div class="field">
<label class="label" for="newEmail">New Email Address</label>
<div class="control">
<input
@keyup.enter="updateEmail"
class="input"
id="newEmail"
placeholder="The new email address..."
type="email"
v-model="emailUpdate.newEmail"/>
</div>
</div>
</div>
</div>
<div class="field">
<label class="label" for="currentPassword">Current Password</label>
<div class="control">
<input
@keyup.enter="updateEmail"
class="input"
id="currentPassword"
placeholder="Your current password"
type="password"
v-model="emailUpdate.password"/>
</div>
</div>
</form>
<x-button
:loading="emailUpdateService.loading"
@click="updateEmail()"
class="is-fullwidth mt-4">
Save
</x-button>
</card>
<!-- General -->
<div class="card update-name">
<header class="card-header">
<p class="card-header-title">
General Settings
</p>
</header>
<div class="card-content">
<div class="content">
<div class="field">
<label class="label" for="newName">Name</label>
<div class="control">
<input
@keyup.enter="updateSettings"
class="input"
id="newName"
placeholder="The new name"
type="text"
v-model="settings.name"/>
</div>
</div>
<div class="field">
<label class="checkbox">
<input type="checkbox" v-model="settings.emailRemindersEnabled"/>
Send me Reminders for tasks via Email
</label>
</div>
<div class="bigbuttons">
<button :class="{ 'is-loading': userSettingsService.loading}" @click="updateSettings()"
class="button is-primary is-fullwidth">
Save
</button>
</div>
<card title="General Settings" class="general-settings">
<div class="field">
<label class="label" for="newName">Name</label>
<div class="control">
<input
@keyup.enter="updateSettings"
class="input"
id="newName"
placeholder="The new name"
type="text"
v-model="settings.name"/>
</div>
</div>
</div>
<div class="field">
<label class="checkbox">
<input type="checkbox" v-model="settings.emailRemindersEnabled"/>
Send me Reminders for tasks via Email
</label>
</div>
<x-button
:loading="userSettingsService.loading"
@click="updateSettings()"
class="is-fullwidth mt-4"
>
Save
</x-button>
</card>
<!-- Avatar -->
<avatar-settings/>
<!-- TOTP -->
<div class="card" v-if="totpEnabled">
<header class="card-header">
<p class="card-header-title">
Two Factor Authentication
<card title="Two Factor Authentication" v-if="totpEnabled">
<x-button
:loading="totpService.loading"
@click="totpEnroll()"
v-if="!totpEnrolled && totp.secret === ''">
Enroll
</x-button>
<template v-else-if="totp.secret !== '' && !totp.enabled">
<p>
To finish your setup, use this secret in your totp app (Google Authenticator or similar):
<strong>{{ totp.secret }}</strong><br/>
After that, enter a code from your app below.
</p>
</header>
<div class="card-content">
<a
:class="{ 'is-loading': totpService.loading }"
@click="totpEnroll()"
class="button is-primary"
v-if="!totpEnrolled && totp.secret === ''">
Enroll
</a>
<div class="content" v-else-if="totp.secret !== '' && !totp.enabled">
<p>
To finish your setup, use this secret in your totp app (Google Authenticator or similar):
<strong>{{ totp.secret }}</strong><br/>
After that, enter a code from your app below.
</p>
<p>
Alternatively you can scan this QR code:<br/>
<img :src="totpQR" alt=""/>
</p>
<p>
Alternatively you can scan this QR code:<br/>
<img :src="totpQR" alt=""/>
</p>
<div class="field">
<label class="label" for="totpConfirmPasscode">Passcode</label>
<div class="control">
<input
@keyup.enter="totpConfirm()"
class="input"
id="totpConfirmPasscode"
placeholder="A code generated by your totp application"
type="text"
v-model="totpConfirmPasscode"/>
</div>
</div>
<x-button @click="totpConfirm()">Confirm</x-button>
</template>
<template v-else-if="totp.secret !== '' && totp.enabled">
<p>
You've sucessfully set up two factor authentication!
</p>
<p v-if="!totpDisableForm">
<x-button @click="totpDisableForm = true" class="is-danger">Disable</x-button>
</p>
<div v-if="totpDisableForm">
<div class="field">
<label class="label" for="totpConfirmPasscode">Passcode</label>
<label class="label" for="currentPassword">Please Enter Your Password</label>
<div class="control">
<input
@keyup.enter="totpConfirm()"
@keyup.enter="totpDisable"
class="input"
id="totpConfirmPasscode"
placeholder="A code generated by your totp application"
type="text"
v-model="totpConfirmPasscode"/>
id="currentPassword"
placeholder="Your current password"
type="password"
v-focus
v-model="totpDisablePassword"/>
</div>
</div>
<a @click="totpConfirm()" class="button is-primary">Confirm</a>
<x-button @click="totpDisable()" class="is-danger">Disable two factor authentication</x-button>
</div>
<div class="content" v-else-if="totp.secret !== '' && totp.enabled">
<p>
You've sucessfully set up two factor authentication!
</p>
<p v-if="!totpDisableForm">
<a @click="totpDisableForm = true" class="button is-danger">Disable</a>
</p>
<div v-if="totpDisableForm">
<div class="field">
<label class="label" for="currentPassword">Please Enter Your Password</label>
<div class="control">
<input
@keyup.enter="totpDisable"
class="input"
id="currentPassword"
placeholder="Your current password"
type="password"
v-focus
v-model="totpDisablePassword"/>
</div>
</div>
<a @click="totpDisable()" class="button is-danger">Disable two factor authentication</a>
</div>
</div>
</div>
</div>
</template>
</card>
<!-- Migration -->
<div class="card" v-if="migratorsEnabled">
<header class="card-header">
<p class="card-header-title">
Migrate from other services to Vikunja
</p>
</header>
<div class="card-content">
<router-link
:to="{name: 'migrate.start'}"
class="button is-primary"
v-if="migratorsEnabled"
>
Import your data into Vikunja
</router-link>
</div>
</div>
<card title="Migrate from other services to Vikunja" v-if="migratorsEnabled">
<x-button
:to="{name: 'migrate.start'}"
>
Import your data into Vikunja
</x-button>
</card>
<!-- Caldav -->
<div class="card" v-if="caldavEnabled">
<header class="card-header">
<p class="card-header-title">
Caldav
</p>
</header>
<div class="card-content content">
<p>
You can connect Vikunja to caldav clients to view and manage all tasks from different clients.
Enter this url into your client:
</p>
<div class="field has-addons no-input-mobile">
<div class="control is-expanded">
<input type="text" v-model="caldavUrl" class="input" readonly/>
</div>
<div class="control">
<a @click="copy(caldavUrl)" class="button is-primary has-no-shadow" v-tooltip="'Copy to clipboard'">
<span class="icon">
<icon icon="paste"/>
</span>
</a>
</div>
<card v-if="caldavEnabled" title="Caldav">
<p>
You can connect Vikunja to caldav clients to view and manage all tasks from different clients.
Enter this url into your client:
</p>
<div class="field has-addons no-input-mobile">
<div class="control is-expanded">
<input type="text" v-model="caldavUrl" class="input" readonly/>
</div>
<div class="control">
<x-button
@click="copy(caldavUrl)"
:shadow="false"
v-tooltip="'Copy to clipboard'"
icon="paste"
/>
</div>
<p>
<a href="https://vikunja.io/docs/caldav/" target="_blank">
More information about caldav in Vikunja
</a>
</p>
</div>
</div>
<p>
<a href="https://vikunja.io/docs/caldav/" target="_blank">
More information about caldav in Vikunja
</a>
</p>
</card>
</div>
</template>