Replace all spaces with tabs
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
kolaente 2019-11-03 13:44:40 +01:00
parent c6d7b288ce
commit e00f0046b5
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
6 changed files with 691 additions and 691 deletions

View File

@ -1,182 +1,182 @@
<template> <template>
<div> <div>
<div v-if="isOnline"> <div v-if="isOnline">
<!-- This is a workaround to get the sw to "see" the to-be-cached version of the offline background image --> <!-- This is a workaround to get the sw to "see" the to-be-cached version of the offline background image -->
<div class="offline" style="height: 0;width: 0;"></div> <div class="offline" style="height: 0;width: 0;"></div>
<nav class="navbar main-theme is-fixed-top" role="navigation" aria-label="main navigation" <nav class="navbar main-theme is-fixed-top" role="navigation" aria-label="main navigation"
v-if="user.authenticated && user.infos.type === authTypes.USER"> v-if="user.authenticated && user.infos.type === authTypes.USER">
<div class="navbar-brand"> <div class="navbar-brand">
<router-link :to="{name: 'home'}" class="navbar-item logo"> <router-link :to="{name: 'home'}" class="navbar-item logo">
<img src="/images/logo-full.svg" alt="Vikunja"/> <img src="/images/logo-full.svg" alt="Vikunja"/>
</router-link> </router-link>
</div> </div>
<div class="navbar-end"> <div class="navbar-end">
<div class="user"> <div class="user">
<img :src="gravatar()" class="avatar" alt=""/> <img :src="gravatar()" class="avatar" alt=""/>
<div class="dropdown is-right is-active"> <div class="dropdown is-right is-active">
<div class="dropdown-trigger"> <div class="dropdown-trigger">
<button class="button noshadow" @click="userMenuActive = !userMenuActive"> <button class="button noshadow" @click="userMenuActive = !userMenuActive">
<span class="username">{{user.infos.username}}</span> <span class="username">{{user.infos.username}}</span>
<span class="icon is-small"> <span class="icon is-small">
<icon icon="chevron-down"/> <icon icon="chevron-down"/>
</span> </span>
</button> </button>
</div> </div>
<transition name="fade"> <transition name="fade">
<div class="dropdown-menu" v-if="userMenuActive"> <div class="dropdown-menu" v-if="userMenuActive">
<div class="dropdown-content"> <div class="dropdown-content">
<a @click="logout()" class="dropdown-item"> <a @click="logout()" class="dropdown-item">
Logout Logout
</a> </a>
</div> </div>
</div> </div>
</transition> </transition>
</div> </div>
</div> </div>
</div> </div>
</nav> </nav>
<div v-if="user.authenticated && user.infos.type === authTypes.USER"> <div v-if="user.authenticated && user.infos.type === authTypes.USER">
<a @click="mobileMenuActive = true" class="mobilemenu-show-button" v-if="!mobileMenuActive"> <a @click="mobileMenuActive = true" class="mobilemenu-show-button" v-if="!mobileMenuActive">
<icon icon="bars"></icon> <icon icon="bars"></icon>
</a> </a>
<a @click="mobileMenuActive = false" class="mobilemenu-hide-button" v-if="mobileMenuActive"> <a @click="mobileMenuActive = false" class="mobilemenu-hide-button" v-if="mobileMenuActive">
<icon icon="times"></icon> <icon icon="times"></icon>
</a> </a>
<div class="app-container"> <div class="app-container">
<div class="namespace-container" :class="{'is-active': mobileMenuActive}"> <div class="namespace-container" :class="{'is-active': mobileMenuActive}">
<div class="menu top-menu"> <div class="menu top-menu">
<ul class="menu-list"> <ul class="menu-list">
<li> <li>
<router-link :to="{ name: 'home'}"> <router-link :to="{ name: 'home'}">
<span class="icon"> <span class="icon">
<icon icon="calendar"/> <icon icon="calendar"/>
</span> </span>
Overview Overview
</router-link> </router-link>
</li> </li>
<li> <li>
<router-link :to="{ name: 'showTasksInRange', params: {type: 'month'}}"> <router-link :to="{ name: 'showTasksInRange', params: {type: 'month'}}">
<span class="icon"> <span class="icon">
<icon :icon="['far', 'calendar-alt']"/> <icon :icon="['far', 'calendar-alt']"/>
</span> </span>
Next Month Next Month
</router-link> </router-link>
</li> </li>
<li> <li>
<router-link :to="{ name: 'showTasksInRange', params: {type: 'week'}}"> <router-link :to="{ name: 'showTasksInRange', params: {type: 'week'}}">
<span class="icon"> <span class="icon">
<icon icon="calendar-week"/> <icon icon="calendar-week"/>
</span> </span>
Next Week Next Week
</router-link> </router-link>
</li> </li>
<li> <li>
<router-link :to="{ name: 'listTeams'}"> <router-link :to="{ name: 'listTeams'}">
<span class="icon"> <span class="icon">
<icon icon="users"/> <icon icon="users"/>
</span> </span>
Teams Teams
</router-link> </router-link>
</li> </li>
<li> <li>
<router-link :to="{ name: 'newNamespace'}"> <router-link :to="{ name: 'newNamespace'}">
<span class="icon"> <span class="icon">
<icon icon="layer-group"/> <icon icon="layer-group"/>
</span> </span>
New Namespace New Namespace
</router-link> </router-link>
</li> </li>
<li> <li>
<router-link :to="{ name: 'listLabels'}"> <router-link :to="{ name: 'listLabels'}">
<span class="icon"> <span class="icon">
<icon icon="tags"/> <icon icon="tags"/>
</span> </span>
Labels Labels
</router-link> </router-link>
</li> </li>
</ul> </ul>
</div> </div>
<aside class="menu namespaces-lists"> <aside class="menu namespaces-lists">
<div class="spinner" :class="{ 'is-loading': namespaceService.loading}"></div> <div class="spinner" :class="{ 'is-loading': namespaceService.loading}"></div>
<template v-for="n in namespaces"> <template v-for="n in namespaces">
<div :key="n.id"> <div :key="n.id">
<router-link v-tooltip.right="'Settings'" <router-link v-tooltip.right="'Settings'"
:to="{name: 'editNamespace', params: {id: n.id} }" class="nsettings" :to="{name: 'editNamespace', params: {id: n.id} }" class="nsettings"
v-if="n.id > 0"> v-if="n.id > 0">
<span class="icon"> <span class="icon">
<icon icon="cog"/> <icon icon="cog"/>
</span> </span>
</router-link> </router-link>
<router-link v-tooltip="'Add a new list in the ' + n.name + ' namespace'" <router-link v-tooltip="'Add a new list in the ' + n.name + ' namespace'"
:to="{ name: 'newList', params: { id: n.id} }" class="nsettings" :to="{ name: 'newList', params: { id: n.id} }" class="nsettings"
:key="n.id + 'newList'" v-if="n.id > 0"> :key="n.id + 'newList'" v-if="n.id > 0">
<span class="icon"> <span class="icon">
<icon icon="plus"/> <icon icon="plus"/>
</span> </span>
</router-link> </router-link>
<label class="menu-label" v-tooltip="n.name + ' (' + n.lists.length + ')'" :for="n.id + 'checker'"> <label class="menu-label" v-tooltip="n.name + ' (' + n.lists.length + ')'" :for="n.id + 'checker'">
{{n.name}} ({{n.lists.length}}) {{n.name}} ({{n.lists.length}})
</label> </label>
</div> </div>
<input :key="n.id + 'checker'" type="checkbox" checked="checked" :id="n.id + 'checker'" class="checkinput"/> <input :key="n.id + 'checker'" type="checkbox" checked="checked" :id="n.id + 'checker'" class="checkinput"/>
<div class="more-container" :key="n.id + 'child'"> <div class="more-container" :key="n.id + 'child'">
<ul class="menu-list can-be-hidden" > <ul class="menu-list can-be-hidden" >
<li v-for="l in n.lists" :key="l.id"> <li v-for="l in n.lists" :key="l.id">
<router-link :to="{ name: 'showList', params: { id: l.id} }">{{l.title}} <router-link :to="{ name: 'showList', params: { id: l.id} }">{{l.title}}
</router-link> </router-link>
</li> </li>
</ul> </ul>
<label class="hidden-hint" :for="n.id + 'checker'"> <label class="hidden-hint" :for="n.id + 'checker'">
Show hidden lists ({{n.lists.length}})... Show hidden lists ({{n.lists.length}})...
</label> </label>
</div> </div>
</template> </template>
</aside> </aside>
</div> </div>
<div class="app-content" :class="{'fullpage-overlay': fullpage}"> <div class="app-content" :class="{'fullpage-overlay': fullpage}">
<a class="mobile-overlay" v-if="mobileMenuActive" @click="mobileMenuActive = false"></a> <a class="mobile-overlay" v-if="mobileMenuActive" @click="mobileMenuActive = false"></a>
<transition name="fade"> <transition name="fade">
<router-view/> <router-view/>
</transition> </transition>
</div> </div>
</div> </div>
</div> </div>
<!-- FIXME: This will only be triggered when the root component is already loaded before doing link share auth. Will "fix" itself once we use vuex. --> <!-- FIXME: This will only be triggered when the root component is already loaded before doing link share auth. Will "fix" itself once we use vuex. -->
<div v-else-if="user.authenticated && user.infos.type === authTypes.LINK_SHARE"> <div v-else-if="user.authenticated && user.infos.type === authTypes.LINK_SHARE">
<div class="container has-text-centered link-share-view"> <div class="container has-text-centered link-share-view">
<div class="column is-10 is-offset-1"> <div class="column is-10 is-offset-1">
<img src="/images/logo-full.svg" alt="Vikunja" class="logo"/> <img src="/images/logo-full.svg" alt="Vikunja" class="logo"/>
<div class="box has-text-left"> <div class="box has-text-left">
<div class="logout"> <div class="logout">
<a @click="logout()" class="button logout"> <a @click="logout()" class="button logout">
<span>Logout</span> <span>Logout</span>
<span class="icon is-small"> <span class="icon is-small">
<icon icon="sign-out-alt"/> <icon icon="sign-out-alt"/>
</span> </span>
</a> </a>
</div> </div>
<router-view/> <router-view/>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div v-else> <div v-else>
<div class="container"> <div class="container">
<div class="column is-4 is-offset-4"> <div class="column is-4 is-offset-4">
<img src="/images/logo-full.svg" alt="Vikunja"/> <img src="/images/logo-full.svg" alt="Vikunja"/>
<router-view/> <router-view/>
</div> </div>
</div> </div>
</div> </div>
<notifications position="bottom left"/> <notifications position="bottom left"/>
</div> </div>
<div class="app offline" v-else> <div class="app offline" v-else>
<div class="offline-message"> <div class="offline-message">
<h1>You are offline.</h1> <h1>You are offline.</h1>
<p>Please check your network connection and try again.</p> <p>Please check your network connection and try again.</p>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>

View File

@ -1,195 +1,195 @@
<template> <template>
<div class="card is-fullwidth"> <div class="card is-fullwidth">
<header class="card-header"> <header class="card-header">
<p class="card-header-title"> <p class="card-header-title">
Share links Share links
</p> </p>
</header> </header>
<div class="card-content content sharables-list"> <div class="card-content content sharables-list">
<form @submit.prevent="add()" class="add-form"> <form @submit.prevent="add()" class="add-form">
<div class="field is-grouped"> <div class="field is-grouped">
<div class="control"> <div class="control">
<!-- TODO: maybe move this into a modal? --> <!-- TODO: maybe move this into a modal? -->
Add a new link share: Add a new link share:
</div> </div>
<div class="control"> <div class="control">
<div class="select"> <div class="select">
<select v-model="selectedRight" class="button buttonright"> <select v-model="selectedRight" class="button buttonright">
<option :value="rights.READ">Read only</option> <option :value="rights.READ">Read only</option>
<option :value="rights.READ_WRITE">Read & write</option> <option :value="rights.READ_WRITE">Read & write</option>
<option :value="rights.ADMIN">Admin</option> <option :value="rights.ADMIN">Admin</option>
</select> </select>
</div> </div>
</div> </div>
<div class="control"> <div class="control">
<button type="submit" class="button is-success"> <button type="submit" class="button is-success">
<span class="icon is-small"> <span class="icon is-small">
<icon icon="plus"/> <icon icon="plus"/>
</span> </span>
Add Add
</button> </button>
</div> </div>
</div> </div>
</form> </form>
<table class="table is-striped is-hoverable is-fullwidth"> <table class="table is-striped is-hoverable is-fullwidth">
<tbody> <tbody>
<tr> <tr>
<th>Link</th> <th>Link</th>
<th>Shared by</th> <th>Shared by</th>
<th>Right</th> <th>Right</th>
<th>Delete</th> <th>Delete</th>
</tr> </tr>
<template v-if="linkShares.length > 0"> <template v-if="linkShares.length > 0">
<tr v-for="s in linkShares" :key="s.id"> <tr v-for="s in linkShares" :key="s.id">
<td> <td>
<div class="field has-addons"> <div class="field has-addons">
<div class="control"> <div class="control">
<input class="input" type="text" :value="getShareLink(s.hash)" readonly/> <input class="input" type="text" :value="getShareLink(s.hash)" readonly/>
</div> </div>
<div class="control"> <div class="control">
<a class="button is-success noshadow" @click="copy(getShareLink(s.hash))"> <a class="button is-success noshadow" @click="copy(getShareLink(s.hash))">
<span class="icon is-small"> <span class="icon is-small">
<icon icon="paste"/> <icon icon="paste"/>
</span> </span>
</a> </a>
</div> </div>
</div> </div>
</td> </td>
<td> <td>
{{ s.shared_by.username }} {{ s.shared_by.username }}
</td> </td>
<td class="type"> <td class="type">
<template v-if="s.right === rights.ADMIN"> <template v-if="s.right === rights.ADMIN">
<span class="icon is-small"> <span class="icon is-small">
<icon icon="lock"/> <icon icon="lock"/>
</span> </span>
Admin Admin
</template> </template>
<template v-else-if="s.right === rights.READ_WRITE"> <template v-else-if="s.right === rights.READ_WRITE">
<span class="icon is-small"> <span class="icon is-small">
<icon icon="pen"/> <icon icon="pen"/>
</span> </span>
Write Write
</template> </template>
<template v-else> <template v-else>
<span class="icon is-small"> <span class="icon is-small">
<icon icon="users"/> <icon icon="users"/>
</span> </span>
Read-only Read-only
</template> </template>
</td> </td>
<td class="actions"> <td class="actions">
<button @click="linkIDToDelete = s.id; showDeleteModal = true" class="button is-danger icon-only"> <button @click="linkIDToDelete = s.id; showDeleteModal = true" class="button is-danger icon-only">
<span class="icon is-small"> <span class="icon is-small">
<icon icon="trash-alt"/> <icon icon="trash-alt"/>
</span> </span>
</button> </button>
</td> </td>
</tr> </tr>
</template> </template>
</tbody> </tbody>
</table> </table>
</div> </div>
<modal <modal
v-if="showDeleteModal" v-if="showDeleteModal"
@close="showDeleteModal = false" @close="showDeleteModal = false"
@submit="remove()"> @submit="remove()">
<span slot="header">Remove a link share</span> <span slot="header">Remove a link share</span>
<p slot="text">Are you sure you want to remove this link share?<br/> <p slot="text">Are you sure you want to remove this link share?<br/>
It will no longer be possible to access this list with this link share.<br/> It will no longer be possible to access this list with this link share.<br/>
<b>This CANNOT BE UNDONE!</b></p> <b>This CANNOT BE UNDONE!</b></p>
</modal> </modal>
</div> </div>
</template> </template>
<script> <script>
import message from '../../message' import message from '../../message'
import rights from '../../models/rights' import rights from '../../models/rights'
import LinkShareService from '../../services/linkShare' import LinkShareService from '../../services/linkShare'
import LinkShareModel from '../../models/linkShare' import LinkShareModel from '../../models/linkShare'
import copy from 'copy-to-clipboard' import copy from 'copy-to-clipboard'
export default { export default {
name: 'linkSharing', name: 'linkSharing',
props: { props: {
listID: { listID: {
default: 0, default: 0,
required: true, required: true,
}, },
}, },
data() { data() {
return { return {
linkShares: [], linkShares: [],
linkShareService: LinkShareService, linkShareService: LinkShareService,
newLinkShare: LinkShareModel, newLinkShare: LinkShareModel,
rights: rights, rights: rights,
selectedRight: rights.READ, selectedRight: rights.READ,
showDeleteModal: false, showDeleteModal: false,
linkIDToDelete: 0, linkIDToDelete: 0,
} }
}, },
beforeMount() { beforeMount() {
this.linkShareService = new LinkShareService() this.linkShareService = new LinkShareService()
}, },
created() { created() {
this.linkShareService = new LinkShareService() this.linkShareService = new LinkShareService()
this.load() this.load()
}, },
watch: { watch: {
listID: () => { // watch it listID: () => { // watch it
this.load() this.load()
} }
}, },
methods: { methods: {
load() { load() {
// If listID == 0 the list on the calling component wasn't already loaded, so we just bail out here // If listID == 0 the list on the calling component wasn't already loaded, so we just bail out here
if (this.listID === 0) { if (this.listID === 0) {
return return
} }
this.linkShareService.getAll({listID: this.listID}) this.linkShareService.getAll({listID: this.listID})
.then(r => { .then(r => {
this.linkShares = r this.linkShares = r
}) })
.catch(e => { .catch(e => {
message.error(e, this) message.error(e, this)
}) })
}, },
add() { add() {
let newLinkShare = new LinkShareModel({right: this.selectedRight, listID: this.listID}) let newLinkShare = new LinkShareModel({right: this.selectedRight, listID: this.listID})
this.linkShareService.create(newLinkShare) this.linkShareService.create(newLinkShare)
.then(() => { .then(() => {
this.selectedRight = rights.READ this.selectedRight = rights.READ
message.success({message: 'The link share was successfully created'}, this) message.success({message: 'The link share was successfully created'}, this)
this.load() this.load()
}) })
.catch(e => { .catch(e => {
message.error(e, this) message.error(e, this)
}) })
}, },
remove() { remove() {
let linkshare = new LinkShareModel({id: this.linkIDToDelete, listID: this.listID}) let linkshare = new LinkShareModel({id: this.linkIDToDelete, listID: this.listID})
this.linkShareService.delete(linkshare) this.linkShareService.delete(linkshare)
.then(() => { .then(() => {
message.success({message: 'The link share was successfully deleted'}, this) message.success({message: 'The link share was successfully deleted'}, this)
this.load() this.load()
}) })
.catch(e => { .catch(e => {
message.error(e, this) message.error(e, this)
}) })
.finally(() => { .finally(() => {
this.showDeleteModal = false this.showDeleteModal = false
}) })
}, },
copy(text) { copy(text) {
copy(text) copy(text)
}, },
getShareLink(hash) { getShareLink(hash) {
return this.$config.frontend_url + 'share/' + hash + '/auth' return this.$config.frontend_url + 'share/' + hash + '/auth'
}, },
}, },
} }
</script> </script>

View File

@ -1,40 +1,40 @@
<template> <template>
<div class="message is-centered is-info" v-if="loading"> <div class="message is-centered is-info" v-if="loading">
<div class="message-header"> <div class="message-header">
<p class="has-text-centered"> <p class="has-text-centered">
Authenticating... Authenticating...
</p> </p>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import auth from '../../auth' import auth from '../../auth'
import router from '../../router' import router from '../../router'
import message from '../../message' import message from '../../message'
export default { export default {
name: 'linkSharingAuth', name: 'linkSharingAuth',
data() { data() {
return { return {
hash: '', hash: '',
loading: true, loading: true,
} }
}, },
created() { created() {
this.auth() this.auth()
}, },
methods: { methods: {
auth() { auth() {
auth.linkShareAuth(this.$route.params.share) auth.linkShareAuth(this.$route.params.share)
.then((r) => { .then((r) => {
this.loading = false this.loading = false
router.push({name: 'showList', params: {id: r.list_id}}) router.push({name: 'showList', params: {id: r.list_id}})
}) })
.catch(e => { .catch(e => {
message.error(e, this) message.error(e, this)
}) })
} }
}, },
} }
</script> </script>

View File

@ -38,7 +38,7 @@
<span class="tag" v-for="label in l.labels" :style="{'background': label.hex_color, 'color': label.textColor}" :key="label.id"> <span class="tag" v-for="label in l.labels" :style="{'background': label.hex_color, 'color': label.textColor}" :key="label.id">
<span>{{ label.title }}</span> <span>{{ label.title }}</span>
</span> </span>
<img :src="gravatar(a)" :alt="a.username" v-for="a in l.assignees" class="avatar" :key="l.id + 'assignee' + a.id"/> <img :src="gravatar(a)" :alt="a.username" v-for="a in l.assignees" class="avatar" :key="l.id + 'assignee' + a.id"/>
<i v-if="l.dueDate > 0" :class="{'overdue': (l.dueDate <= new Date())}"> - Due on {{new Date(l.dueDate).toLocaleString()}}</i> <i v-if="l.dueDate > 0" :class="{'overdue': (l.dueDate <= new Date())}"> - Due on {{new Date(l.dueDate).toLocaleString()}}</i>
<span v-if="l.priority >= priorities.HIGH" class="high-priority" :class="{'not-so-high': l.priority === priorities.HIGH}"> <span v-if="l.priority >= priorities.HIGH" class="high-priority" :class="{'not-so-high': l.priority === priorities.HIGH}">
<span class="icon"> <span class="icon">
@ -61,21 +61,21 @@
</div> </div>
<div class="column is-4" v-if="isTaskEdit"> <div class="column is-4" v-if="isTaskEdit">
<div class="card taskedit"> <div class="card taskedit">
<header class="card-header"> <header class="card-header">
<p class="card-header-title"> <p class="card-header-title">
Edit Task Edit Task
</p> </p>
<a class="card-header-icon" @click="isTaskEdit = false"> <a class="card-header-icon" @click="isTaskEdit = false">
<span class="icon"> <span class="icon">
<icon icon="angle-right"/> <icon icon="angle-right"/>
</span> </span>
</a> </a>
</header> </header>
<div class="card-content"> <div class="card-content">
<div class="content"> <div class="content">
<edit-task :task="taskEditTask"/> <edit-task :task="taskEditTask"/>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@ -88,9 +88,9 @@
import ListService from '../../services/list' import ListService from '../../services/list'
import TaskService from '../../services/task' import TaskService from '../../services/task'
import ListModel from '../../models/list' import ListModel from '../../models/list'
import EditTask from './edit-task' import EditTask from './edit-task'
import TaskModel from '../../models/task' import TaskModel from '../../models/task'
import priorities from '../../models/priorities' import priorities from '../../models/priorities'
export default { export default {
data() { data() {
@ -98,16 +98,16 @@
listID: this.$route.params.id, listID: this.$route.params.id,
listService: ListService, listService: ListService,
taskService: TaskService, taskService: TaskService,
list: {}, list: {},
isTaskEdit: false, isTaskEdit: false,
taskEditTask: TaskModel, taskEditTask: TaskModel,
newTaskText: '', newTaskText: '',
priorities: {}, priorities: {},
} }
}, },
components: { components: {
EditTask, EditTask,
}, },
props: { props: {
theList: { theList: {
type: ListModel, type: ListModel,
@ -122,8 +122,8 @@
created() { created() {
this.listService = new ListService() this.listService = new ListService()
this.taskService = new TaskService() this.taskService = new TaskService()
this.priorities = priorities this.priorities = priorities
this.taskEditTask = null this.taskEditTask = null
this.isTaskEdit = false this.isTaskEdit = false
}, },
methods: { methods: {
@ -146,7 +146,7 @@
task.done = e.target.checked task.done = e.target.checked
this.taskService.update(task) this.taskService.update(task)
.then(() => { .then(() => {
this.list.sortTasks() this.list.sortTasks()
message.success({message: 'The task was successfully ' + (task.done ? '' : 'un-') + 'marked as done.'}, this) message.success({message: 'The task was successfully ' + (task.done ? '' : 'un-') + 'marked as done.'}, this)
}) })
.catch(e => { .catch(e => {
@ -163,7 +163,7 @@
editTask(id) { editTask(id) {
// Find the selected task and set it to the current object // Find the selected task and set it to the current object
let theTask = this.list.getTaskByID(id) // Somehow this does not work if we directly assign this to this.taskEditTask let theTask = this.list.getTaskByID(id) // Somehow this does not work if we directly assign this to this.taskEditTask
this.taskEditTask = theTask this.taskEditTask = theTask
this.isTaskEdit = true this.isTaskEdit = true
}, },
gravatar(user) { gravatar(user) {

View File

@ -1,296 +1,296 @@
<template> <template>
<form @submit.prevent="editTaskSubmit()"> <form @submit.prevent="editTaskSubmit()">
<div class="field"> <div class="field">
<label class="label" for="tasktext">Task Text</label> <label class="label" for="tasktext">Task Text</label>
<div class="control"> <div class="control">
<input v-focus :class="{ 'disabled': taskService.loading}" :disabled="taskService.loading" class="input" <input v-focus :class="{ 'disabled': taskService.loading}" :disabled="taskService.loading" class="input"
type="text" id="tasktext" placeholder="The task text is here..." v-model="taskEditTask.text"> type="text" id="tasktext" placeholder="The task text is here..." v-model="taskEditTask.text">
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="label" for="taskdescription">Description</label> <label class="label" for="taskdescription">Description</label>
<div class="control"> <div class="control">
<textarea :class="{ 'disabled': taskService.loading}" :disabled="taskService.loading" class="textarea" <textarea :class="{ 'disabled': taskService.loading}" :disabled="taskService.loading" class="textarea"
placeholder="The tasks description goes here..." id="taskdescription" placeholder="The tasks description goes here..." id="taskdescription"
v-model="taskEditTask.description"></textarea> v-model="taskEditTask.description"></textarea>
</div> </div>
</div> </div>
<b>Reminder Dates</b> <b>Reminder Dates</b>
<div class="reminder-input" <div class="reminder-input"
:class="{ 'overdue': (r < nowUnix && index !== (taskEditTask.reminderDates.length - 1))}" :class="{ 'overdue': (r < nowUnix && index !== (taskEditTask.reminderDates.length - 1))}"
v-for="(r, index) in taskEditTask.reminderDates" :key="index"> v-for="(r, index) in taskEditTask.reminderDates" :key="index">
<flat-pickr <flat-pickr
:class="{ 'disabled': taskService.loading}" :class="{ 'disabled': taskService.loading}"
:disabled="taskService.loading" :disabled="taskService.loading"
:v-model="taskEditTask.reminderDates" :v-model="taskEditTask.reminderDates"
:config="flatPickerConfig" :config="flatPickerConfig"
:id="'taskreminderdate' + index" :id="'taskreminderdate' + index"
:value="r" :value="r"
:data-index="index" :data-index="index"
placeholder="Add a new reminder..."> placeholder="Add a new reminder...">
</flat-pickr> </flat-pickr>
<a v-if="index !== (taskEditTask.reminderDates.length - 1)" @click="removeReminderByIndex(index)"> <a v-if="index !== (taskEditTask.reminderDates.length - 1)" @click="removeReminderByIndex(index)">
<icon icon="times"></icon> <icon icon="times"></icon>
</a> </a>
</div> </div>
<div class="field"> <div class="field">
<label class="label" for="taskduedate">Due Date</label> <label class="label" for="taskduedate">Due Date</label>
<div class="control"> <div class="control">
<flat-pickr <flat-pickr
:class="{ 'disabled': taskService.loading}" :class="{ 'disabled': taskService.loading}"
class="input" class="input"
:disabled="taskService.loading" :disabled="taskService.loading"
v-model="taskEditTask.dueDate" v-model="taskEditTask.dueDate"
:config="flatPickerConfig" :config="flatPickerConfig"
id="taskduedate" id="taskduedate"
placeholder="The tasks due date is here..."> placeholder="The tasks due date is here...">
</flat-pickr> </flat-pickr>
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="label" for="">Duration</label> <label class="label" for="">Duration</label>
<div class="control columns"> <div class="control columns">
<div class="column"> <div class="column">
<flat-pickr <flat-pickr
:class="{ 'disabled': taskService.loading}" :class="{ 'disabled': taskService.loading}"
class="input" class="input"
:disabled="taskService.loading" :disabled="taskService.loading"
v-model="taskEditTask.startDate" v-model="taskEditTask.startDate"
:config="flatPickerConfig" :config="flatPickerConfig"
id="taskduedate" id="taskduedate"
placeholder="Start date"> placeholder="Start date">
</flat-pickr> </flat-pickr>
</div> </div>
<div class="column"> <div class="column">
<flat-pickr <flat-pickr
:class="{ 'disabled': taskService.loading}" :class="{ 'disabled': taskService.loading}"
class="input" class="input"
:disabled="taskService.loading" :disabled="taskService.loading"
v-model="taskEditTask.endDate" v-model="taskEditTask.endDate"
:config="flatPickerConfig" :config="flatPickerConfig"
id="taskduedate" id="taskduedate"
placeholder="End date"> placeholder="End date">
</flat-pickr> </flat-pickr>
</div> </div>
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="label" for="">Repeat after</label> <label class="label" for="">Repeat after</label>
<div class="control repeat-after-input columns"> <div class="control repeat-after-input columns">
<div class="column"> <div class="column">
<input class="input" placeholder="Specify an amount..." v-model="taskEditTask.repeatAfter.amount"/> <input class="input" placeholder="Specify an amount..." v-model="taskEditTask.repeatAfter.amount"/>
</div> </div>
<div class="column is-3"> <div class="column is-3">
<div class="select"> <div class="select">
<select v-model="taskEditTask.repeatAfter.type"> <select v-model="taskEditTask.repeatAfter.type">
<option value="hours">Hours</option> <option value="hours">Hours</option>
<option value="days">Days</option> <option value="days">Days</option>
<option value="weeks">Weeks</option> <option value="weeks">Weeks</option>
<option value="months">Months</option> <option value="months">Months</option>
<option value="years">Years</option> <option value="years">Years</option>
</select> </select>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="label" for="">Priority</label> <label class="label" for="">Priority</label>
<div class="control priority-select"> <div class="control priority-select">
<div class="select"> <div class="select">
<select v-model="taskEditTask.priority"> <select v-model="taskEditTask.priority">
<option :value="priorities.UNSET">Unset</option> <option :value="priorities.UNSET">Unset</option>
<option :value="priorities.LOW">Low</option> <option :value="priorities.LOW">Low</option>
<option :value="priorities.MEDIUM">Medium</option> <option :value="priorities.MEDIUM">Medium</option>
<option :value="priorities.HIGH">High</option> <option :value="priorities.HIGH">High</option>
<option :value="priorities.URGENT">Urgent</option> <option :value="priorities.URGENT">Urgent</option>
<option :value="priorities.DO_NOW">DO NOW</option> <option :value="priorities.DO_NOW">DO NOW</option>
</select> </select>
</div> </div>
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="label">Percent Done</label> <label class="label">Percent Done</label>
<div class="control"> <div class="control">
<div class="select"> <div class="select">
<select v-model.number="taskEditTask.percentDone"> <select v-model.number="taskEditTask.percentDone">
<option value="0">0%</option> <option value="0">0%</option>
<option value="0.1">10%</option> <option value="0.1">10%</option>
<option value="0.2">20%</option> <option value="0.2">20%</option>
<option value="0.3">30%</option> <option value="0.3">30%</option>
<option value="0.4">40%</option> <option value="0.4">40%</option>
<option value="0.5">50%</option> <option value="0.5">50%</option>
<option value="0.6">60%</option> <option value="0.6">60%</option>
<option value="0.7">70%</option> <option value="0.7">70%</option>
<option value="0.8">80%</option> <option value="0.8">80%</option>
<option value="0.9">90%</option> <option value="0.9">90%</option>
<option value="1">100%</option> <option value="1">100%</option>
</select> </select>
</div> </div>
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="label">Color</label> <label class="label">Color</label>
<div class="control"> <div class="control">
<verte <verte
v-model="taskEditTask.hexColor" v-model="taskEditTask.hexColor"
menuPosition="top" menuPosition="top"
picker="square" picker="square"
model="hex" model="hex"
:enableAlpha="false" :enableAlpha="false"
:rgbSliders="true"> :rgbSliders="true">
</verte> </verte>
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="label" for="">Assignees</label> <label class="label" for="">Assignees</label>
<ul class="assingees"> <ul class="assingees">
<li v-for="(a, index) in taskEditTask.assignees" :key="a.id"> <li v-for="(a, index) in taskEditTask.assignees" :key="a.id">
{{a.username}} {{a.username}}
<a @click="deleteAssigneeByIndex(index)"> <a @click="deleteAssigneeByIndex(index)">
<icon icon="times"/> <icon icon="times"/>
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
<div class="field has-addons"> <div class="field has-addons">
<div class="control is-expanded"> <div class="control is-expanded">
<multiselect <multiselect
v-model="newAssignee" v-model="newAssignee"
:options="foundUsers" :options="foundUsers"
:multiple="false" :multiple="false"
:searchable="true" :searchable="true"
:loading="listUserService.loading" :loading="listUserService.loading"
:internal-search="true" :internal-search="true"
@search-change="findUser" @search-change="findUser"
placeholder="Type to search" placeholder="Type to search"
label="username" label="username"
track-by="id"> track-by="id">
<template slot="clear" slot-scope="props"> <template slot="clear" slot-scope="props">
<div class="multiselect__clear" v-if="newAssignee !== null && newAssignee.id !== 0" <div class="multiselect__clear" v-if="newAssignee !== null && newAssignee.id !== 0"
@mousedown.prevent.stop="clearAllFoundUsers(props.search)"></div> @mousedown.prevent.stop="clearAllFoundUsers(props.search)"></div>
</template> </template>
<span slot="noResult">Oops! No user found. Consider changing the search query.</span> <span slot="noResult">Oops! No user found. Consider changing the search query.</span>
</multiselect> </multiselect>
</div> </div>
<div class="control"> <div class="control">
<a @click="addAssignee" class="button is-primary fullheight"> <a @click="addAssignee" class="button is-primary fullheight">
<span class="icon is-small"> <span class="icon is-small">
<icon icon="plus"/> <icon icon="plus"/>
</span> </span>
</a> </a>
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="label">Labels</label> <label class="label">Labels</label>
<div class="control"> <div class="control">
<multiselect <multiselect
:multiple="true" :multiple="true"
:close-on-select="false" :close-on-select="false"
:clear-on-select="true" :clear-on-select="true"
:options-limit="300" :options-limit="300"
:hide-selected="true" :hide-selected="true"
v-model="taskEditTask.labels" v-model="taskEditTask.labels"
:options="foundLabels" :options="foundLabels"
:searchable="true" :searchable="true"
:loading="labelService.loading || labelTaskService.loading" :loading="labelService.loading || labelTaskService.loading"
:internal-search="true" :internal-search="true"
@search-change="findLabel" @search-change="findLabel"
@select="addLabel" @select="addLabel"
placeholder="Type to search" placeholder="Type to search"
label="title" label="title"
track-by="id" track-by="id"
:taggable="true" :taggable="true"
@tag="createAndAddLabel" @tag="createAndAddLabel"
tag-placeholder="Add this as new label" tag-placeholder="Add this as new label"
> >
<template slot="tag" slot-scope="{ option, remove }"> <template slot="tag" slot-scope="{ option, remove }">
<span class="tag" <span class="tag"
:style="{'background': option.hex_color, 'color': option.textColor}"> :style="{'background': option.hex_color, 'color': option.textColor}">
<span>{{ option.title }}</span> <span>{{ option.title }}</span>
<a class="delete is-small" @click="removeLabel(option)"></a> <a class="delete is-small" @click="removeLabel(option)"></a>
</span> </span>
</template> </template>
<template slot="clear" slot-scope="props"> <template slot="clear" slot-scope="props">
<div class="multiselect__clear" v-if="taskEditTask.labels.length" <div class="multiselect__clear" v-if="taskEditTask.labels.length"
@mousedown.prevent.stop="clearAllLabels(props.search)"></div> @mousedown.prevent.stop="clearAllLabels(props.search)"></div>
</template> </template>
</multiselect> </multiselect>
</div> </div>
</div> </div>
<div class="field" v-for="(rts, kind ) in task.related_tasks" :key="kind" v-if="rts.length > 0"> <div class="field" v-for="(rts, kind ) in task.related_tasks" :key="kind" v-if="rts.length > 0">
<label class="label">{{ relationKinds[kind] }}</label> <label class="label">{{ relationKinds[kind] }}</label>
<div class="tasks noborder"> <div class="tasks noborder">
<div class="task" v-for="t in rts" :key="t.id"> <div class="task" v-for="t in rts" :key="t.id">
<label> <label>
<span class="tasktext" :class="{ 'done': t.done}"> <span class="tasktext" :class="{ 'done': t.done}">
{{t.text}} {{t.text}}
</span> </span>
</label> </label>
<a class="remove" @click="removeTaskRelation({relation_kind: kind, other_task_id: t.id})"> <a class="remove" @click="removeTaskRelation({relation_kind: kind, other_task_id: t.id})">
<icon icon="trash-alt"/> <icon icon="trash-alt"/>
</a> </a>
</div> </div>
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<label class="label">New Task Relation</label> <label class="label">New Task Relation</label>
<div class="field"> <div class="field">
<div class="control is-expanded"> <div class="control is-expanded">
<multiselect <multiselect
v-model="newTaskRelationTask" v-model="newTaskRelationTask"
:options="foundTasks" :options="foundTasks"
:multiple="false" :multiple="false"
:searchable="true" :searchable="true"
:loading="taskService.loading" :loading="taskService.loading"
:internal-search="true" :internal-search="true"
@search-change="findTasks" @search-change="findTasks"
placeholder="Type to search" placeholder="Type to search"
label="text" label="text"
track-by="id"> track-by="id">
<template slot="clear" slot-scope="props"> <template slot="clear" slot-scope="props">
<div class="multiselect__clear" <div class="multiselect__clear"
v-if="newTaskRelationTask !== null && newTaskRelationTask.id !== 0" v-if="newTaskRelationTask !== null && newTaskRelationTask.id !== 0"
@mousedown.prevent.stop="clearAllFoundTasks(props.search)"></div> @mousedown.prevent.stop="clearAllFoundTasks(props.search)"></div>
</template> </template>
<span slot="noResult">No task found. Consider changing the search query.</span> <span slot="noResult">No task found. Consider changing the search query.</span>
</multiselect> </multiselect>
</div> </div>
</div> </div>
<div class="field has-addons"> <div class="field has-addons">
<div class="control is-expanded"> <div class="control is-expanded">
<div class="select is-fullwidth"> <div class="select is-fullwidth">
<select v-model="newTaskRelationKind"> <select v-model="newTaskRelationKind">
<option value="unset">Select a kind of relation</option> <option value="unset">Select a kind of relation</option>
<option v-for="(label, rk) in relationKinds" :key="rk" :value="rk"> <option v-for="(label, rk) in relationKinds" :key="rk" :value="rk">
{{ label }} {{ label }}
</option> </option>
</select> </select>
</div> </div>
</div> </div>
<div class="control"> <div class="control">
<a class="button is-primary" @click="addTaskRelation()">Add task Relation</a> <a class="button is-primary" @click="addTaskRelation()">Add task Relation</a>
</div> </div>
</div> </div>
</div> </div>
<button type="submit" class="button is-success is-fullwidth" :class="{ 'is-loading': taskService.loading}"> <button type="submit" class="button is-success is-fullwidth" :class="{ 'is-loading': taskService.loading}">
Save Save
</button> </button>
</form> </form>
</template> </template>
<script> <script>
@ -573,7 +573,7 @@
</script> </script>
<style scoped> <style scoped>
form { form {
margin-bottom: 1em; margin-bottom: 1em;
} }
</style> </style>

View File

@ -29,8 +29,8 @@
<VueDragResize <VueDragResize
class="task" class="task"
:class="{'done': t.done, 'is-current-edit': taskToEdit !== null && taskToEdit.id === t.id, 'has-light-text': !t.hasDarkColor(), 'has-dark-text': t.hasDarkColor()}" :class="{'done': t.done, 'is-current-edit': taskToEdit !== null && taskToEdit.id === t.id, 'has-light-text': !t.hasDarkColor(), 'has-dark-text': t.hasDarkColor()}"
:style="{'border-color': t.hexColor, 'background-color': t.hexColor}" :style="{'border-color': t.hexColor, 'background-color': t.hexColor}"
:isActive="true" :isActive="true"
:x="t.offsetDays * dayWidth - 6" :x="t.offsetDays * dayWidth - 6"
:y="0" :y="0"
:w="t.durationDays * dayWidth" :w="t.durationDays * dayWidth"
@ -46,11 +46,11 @@
@dragstop="resizeTask" @dragstop="resizeTask"
@clicked="taskDragged = t" @clicked="taskDragged = t"
> >
<span :class="{ <span :class="{
'has-high-priority': t.priority >= priorities.HIGH, 'has-high-priority': t.priority >= priorities.HIGH,
'has-not-so-high-priority': t.priority === priorities.HIGH, 'has-not-so-high-priority': t.priority === priorities.HIGH,
'has-super-high-priority': t.priority === priorities.DO_NOW 'has-super-high-priority': t.priority === priorities.DO_NOW
}">{{t.text}}</span> }">{{t.text}}</span>
<span v-if="t.priority >= priorities.HIGH" class="high-priority" :class="{'not-so-high': t.priority === priorities.HIGH}"> <span v-if="t.priority >= priorities.HIGH" class="high-priority" :class="{'not-so-high': t.priority === priorities.HIGH}">
<span class="icon"> <span class="icon">
<icon icon="exclamation"/> <icon icon="exclamation"/>
@ -63,10 +63,10 @@
</span> </span>
</span> </span>
<!-- using the key here forces vue to use the updated version model and not the response returned by the api --> <!-- using the key here forces vue to use the updated version model and not the response returned by the api -->
<a @click="editTask(theTasks[k])" class="edit-toggle"> <a @click="editTask(theTasks[k])" class="edit-toggle">
<icon icon="pen"/> <icon icon="pen"/>
</a> </a>
</VueDragResize> </VueDragResize>
</div> </div>
<template v-if="showTaskswithoutDates"> <template v-if="showTaskswithoutDates">
<div class="row" v-for="(t, k) in tasksWithoutDates" :key="t.id" :style="{background: 'repeating-linear-gradient(90deg, #ededed, #ededed 1px, ' + (k % 2 === 0 ? '#fafafa 1px, #fafafa ' : '#fff 1px, #fff ') + dayWidth + 'px)'}"> <div class="row" v-for="(t, k) in tasksWithoutDates" :key="t.id" :style="{background: 'repeating-linear-gradient(90deg, #ededed, #ededed 1px, ' + (k % 2 === 0 ? '#fafafa 1px, #fafafa ' : '#fff 1px, #fff ') + dayWidth + 'px)'}">
@ -183,7 +183,7 @@
fullWidth: 0, fullWidth: 0,
now: null, now: null,
dayOffsetUntilToday: 0, dayOffsetUntilToday: 0,
isTaskEdit: false, isTaskEdit: false,
taskToEdit: null, taskToEdit: null,
newTaskTitle: '', newTaskTitle: '',
newTaskFieldActive: false, newTaskFieldActive: false,
@ -312,10 +312,10 @@
}) })
}, 100) }, 100)
}, },
editTask(task) { editTask(task) {
this.taskToEdit = task this.taskToEdit = task
this.isTaskEdit = true this.isTaskEdit = true
}, },
showCreateNewTask() { showCreateNewTask() {
if(!this.newTaskFieldActive) { if(!this.newTaskFieldActive) {
// Timeout to not send the form if the field isn't even shown // Timeout to not send the form if the field isn't even shown