mirror of
https://github.com/DCsunset/taskwarrior-webui.git
synced 2025-08-18 21:43:06 +02:00
refactor: update nuxt.js and composition api
This commit is contained in:
parent
2dd183e9dd
commit
cbd6f27c1e
11 changed files with 1141 additions and 1210 deletions
|
@ -21,14 +21,11 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed } from '@vue/composition-api';
|
||||
import { defineComponent, computed } from '@nuxtjs/composition-api';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
value: Boolean,
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
|
|
|
@ -82,20 +82,20 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, ref, reactive } from '@vue/composition-api';
|
||||
import { watch, defineComponent, useStore, computed, ref, reactive } from '@nuxtjs/composition-api';
|
||||
import { accessorType } from "../store";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
value: Boolean,
|
||||
},
|
||||
|
||||
setup(props, context) {
|
||||
setup(props, ctx) {
|
||||
const store = useStore<typeof accessorType>();
|
||||
|
||||
const showDialog = computed({
|
||||
get: () => props.value,
|
||||
set: val => context.emit('input', val)
|
||||
set: val => ctx.emit('input', val)
|
||||
});
|
||||
|
||||
const numberRules = [
|
||||
|
@ -104,15 +104,15 @@ export default defineComponent({
|
|||
|
||||
const formRef = ref(null);
|
||||
const settings = reactive({
|
||||
dark: context.root.$store.state.settings.dark,
|
||||
autoRefresh: context.root.$store.state.settings.autoRefresh,
|
||||
autoSync: context.root.$store.state.settings.autoSync
|
||||
dark: store.state.settings.dark,
|
||||
autoRefresh: store.state.settings.autoRefresh,
|
||||
autoSync: store.state.settings.autoSync
|
||||
});
|
||||
|
||||
const reset = () => {
|
||||
settings.dark = context.root.$store.state.settings.dark;
|
||||
settings.autoRefresh = context.root.$store.state.settings.autoRefresh;
|
||||
settings.autoSync = context.root.$store.state.settings.autoSync;
|
||||
settings.dark = store.state.settings.dark;
|
||||
settings.autoRefresh = store.state.settings.autoRefresh;
|
||||
settings.autoSync = store.state.settings.autoSync;
|
||||
};
|
||||
|
||||
const closeDialog = () => {
|
||||
|
@ -123,7 +123,7 @@ export default defineComponent({
|
|||
const save = () => {
|
||||
const valid = (formRef as any).value.validate();
|
||||
if (valid) {
|
||||
context.root.$store.dispatch('updateSettings', {
|
||||
store.dispatch('updateSettings', {
|
||||
...settings
|
||||
});
|
||||
closeDialog();
|
||||
|
@ -131,7 +131,7 @@ export default defineComponent({
|
|||
};
|
||||
|
||||
const sync = async () => {
|
||||
await context.root.$store.dispatch('syncTasks');
|
||||
await store.dispatch('syncTasks');
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
@ -130,33 +130,27 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, watch, computed, ref } from '@vue/composition-api';
|
||||
import { defineComponent, useStore, watch, computed, ref } from '@nuxtjs/composition-api';
|
||||
import { Task } from 'taskwarrior-lib';
|
||||
|
||||
interface Props {
|
||||
[key: string]: unknown,
|
||||
value: boolean,
|
||||
task?: Task;
|
||||
}
|
||||
import { accessorType } from "../store";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
value: Boolean,
|
||||
task: {
|
||||
type: Object,
|
||||
type: Object as () => Task,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
setup(props: Props, context) {
|
||||
const projects = computed(() => context.root.$store.getters.projects);
|
||||
const tags = computed(() => context.root.$store.getters.tags);
|
||||
setup(props, ctx) {
|
||||
const store = useStore<typeof accessorType>();
|
||||
|
||||
const projects = computed(() => store.getters.projects);
|
||||
const tags = computed(() => store.getters.tags);
|
||||
|
||||
const showDialog = computed({
|
||||
get: () => props.value,
|
||||
set: val => context.emit('input', val)
|
||||
set: val => ctx.emit('input', val)
|
||||
});
|
||||
|
||||
const requiredRules = [
|
||||
|
@ -224,7 +218,7 @@ export default defineComponent({
|
|||
const submit = async () => {
|
||||
const valid = (formRef.value as any).validate();
|
||||
if (valid) {
|
||||
await context.root.$store.dispatch('updateTasks', [{
|
||||
await store.dispatch('updateTasks', [{
|
||||
...formData.value,
|
||||
annotations: formData.value.annotations || [],
|
||||
project: formData.value.project || undefined,
|
||||
|
@ -235,7 +229,7 @@ export default defineComponent({
|
|||
priority: formData.value.priority === 'N' ? undefined : formData.value.priority,
|
||||
recur: recur.value ? formData.value.recur : undefined
|
||||
}]);
|
||||
context.root.$store.commit('setNotification', {
|
||||
store.commit('setNotification', {
|
||||
color: 'success',
|
||||
text: `Successfully ${props.task ? 'update' : 'create'} the task`
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
:text="confirmation.text"
|
||||
@yes="confirmation.handler"
|
||||
/>
|
||||
<TaskDialog v-model="showTaskDialog" :task="currentTask" />
|
||||
<TaskDialog v-model="showTaskDialog" :task="currentTask || undefined" />
|
||||
|
||||
<v-row class="px-4 pt-4">
|
||||
<v-btn-toggle v-model="status" mandatory background-color="rgba(0, 0, 0, 0)">
|
||||
|
@ -27,8 +27,8 @@
|
|||
</v-icon>
|
||||
{{ st }}
|
||||
<v-badge
|
||||
v-if="st === 'pending' && classifiedTasks[st].length"
|
||||
:content="classifiedTasks[st].length"
|
||||
v-if="st === 'pending' && classifiedTasks[st].value && classifiedTasks[st].value.length"
|
||||
:content="classifiedTasks[st].value.length"
|
||||
:color="st === status ? 'primary' : 'grey'"
|
||||
inline
|
||||
/>
|
||||
|
@ -188,7 +188,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, reactive, ref, ComputedRef, Ref } from '@vue/composition-api';
|
||||
import { defineComponent, useStore, computed, reactive, ref, ComputedRef, Ref } from '@nuxtjs/composition-api';
|
||||
import { Task } from 'taskwarrior-lib';
|
||||
import _ from 'lodash';
|
||||
import TaskDialog from '../components/TaskDialog.vue';
|
||||
|
@ -196,6 +196,7 @@ import ConfirmationDialog from '../components/ConfirmationDialog.vue';
|
|||
import moment from 'moment';
|
||||
import urlRegex from 'url-regex-safe';
|
||||
import normalizeUrl from 'normalize-url';
|
||||
import { accessorType } from "../store";
|
||||
|
||||
function displayDate(str?: string) {
|
||||
if (!str)
|
||||
|
@ -254,24 +255,21 @@ function linkify(text: string) {
|
|||
return result;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
[key: string]: unknown,
|
||||
tasks: Task[]
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
tasks: {
|
||||
type: Array as () => Task[]
|
||||
type: Array as () => Task[],
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
setup(props: Props, context) {
|
||||
setup(props) {
|
||||
const store = useStore<typeof accessorType>();
|
||||
const selected = ref([] as Task[]);
|
||||
|
||||
const status = ref('pending');
|
||||
const allStatus = ['pending', 'waiting', 'completed', 'deleted', 'recurring'];
|
||||
const statusIcons = {
|
||||
const statusIcons: { [st: string]: string } = {
|
||||
pending: 'mdi-clock-outline',
|
||||
waiting: 'mdi-pause',
|
||||
completed: 'mdi-check',
|
||||
|
@ -314,7 +312,7 @@ export default defineComponent({
|
|||
const classifiedTasks = reactive(tempTasks);
|
||||
|
||||
const refresh = () => {
|
||||
context.root.$store.dispatch('fetchTasks');
|
||||
store.dispatch('fetchTasks');
|
||||
};
|
||||
|
||||
const showConfirmationDialog = ref(false);
|
||||
|
@ -337,14 +335,14 @@ export default defineComponent({
|
|||
};
|
||||
|
||||
const completeTasks = async (tasks: Task[]) => {
|
||||
await context.root.$store.dispatch('updateTasks', tasks.map(task => {
|
||||
await store.dispatch('updateTasks', tasks.map(task => {
|
||||
return {
|
||||
...task,
|
||||
status: 'completed'
|
||||
};
|
||||
}));
|
||||
selected.value = selected.value.filter(task => tasks.findIndex(t => t.uuid === task.uuid) === -1);
|
||||
context.root.$store.commit('setNotification', {
|
||||
store.commit('setNotification', {
|
||||
color: 'success',
|
||||
text: 'Successfully complete the task(s)'
|
||||
});
|
||||
|
@ -353,9 +351,9 @@ export default defineComponent({
|
|||
const deleteTasks = (tasks: Task[]) => {
|
||||
confirmation.text = 'Are you sure to delete the task(s)?';
|
||||
confirmation.handler = async () => {
|
||||
await context.root.$store.dispatch('deleteTasks', tasks);
|
||||
await store.dispatch('deleteTasks', tasks);
|
||||
selected.value = selected.value.filter(task => tasks.findIndex(t => t.uuid === task.uuid) === -1);
|
||||
context.root.$store.commit('setNotification', {
|
||||
store.commit('setNotification', {
|
||||
color: 'success',
|
||||
text: 'Successfully delete the task(s)'
|
||||
});
|
||||
|
@ -366,14 +364,14 @@ export default defineComponent({
|
|||
const restoreTasks = (tasks: Task[]) => {
|
||||
confirmation.text = 'Are you sure to restore the task(s)?';
|
||||
confirmation.handler = async () => {
|
||||
await context.root.$store.dispatch('updateTasks', tasks.map(task => {
|
||||
await store.dispatch('updateTasks', tasks.map(task => {
|
||||
return {
|
||||
...task,
|
||||
status: 'pending'
|
||||
};
|
||||
}));
|
||||
selected.value = selected.value.filter(task => tasks.findIndex(t => t.uuid === task.uuid) === -1);
|
||||
context.root.$store.commit('setNotification', {
|
||||
store.commit('setNotification', {
|
||||
color: 'success',
|
||||
text: 'Successfully restore the task(s)'
|
||||
});
|
||||
|
|
|
@ -42,37 +42,40 @@
|
|||
</v-icon>
|
||||
</v-app-bar>
|
||||
|
||||
<v-content>
|
||||
<v-main>
|
||||
<v-container fluid>
|
||||
<nuxt />
|
||||
</v-container>
|
||||
</v-content>
|
||||
</v-main>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, onErrorCaptured, ref } from '@vue/composition-api';
|
||||
import { defineComponent, useContext, useStore, computed, onErrorCaptured, ref, watch } from '@nuxtjs/composition-api';
|
||||
import SettingsDialog from '../components/SettingsDialog.vue';
|
||||
import { accessorType } from "../store";
|
||||
|
||||
export default defineComponent({
|
||||
setup(_props, context) {
|
||||
context.root.$store.dispatch('fetchSettings');
|
||||
setup(_props, ctx) {
|
||||
const context = useContext();
|
||||
const store = useStore<typeof accessorType>();
|
||||
store.dispatch('fetchSettings');
|
||||
|
||||
context.root.$vuetify.theme.dark = context.root.$store.state.settings.dark;
|
||||
context.$vuetify.theme.dark = store.state.settings.dark;
|
||||
|
||||
const dark = computed({
|
||||
get: () => context.root.$vuetify.theme.dark,
|
||||
get: () => context.$vuetify.theme.dark,
|
||||
set: val => {
|
||||
context.root.$vuetify.theme.dark = val;
|
||||
context.$vuetify.theme.dark = val;
|
||||
}
|
||||
});
|
||||
|
||||
const settingsDialog = ref(false);
|
||||
|
||||
const notification = computed(() => context.root.$store.state.notification);
|
||||
const notification = computed(() => store.state.notification);
|
||||
const snackbar = computed({
|
||||
get: () => context.root.$store.state.snackbar,
|
||||
set: val => context.root.$store.commit('setSnackbar', val)
|
||||
get: () => store.state.snackbar,
|
||||
set: val => store.commit('setSnackbar', val)
|
||||
});
|
||||
|
||||
onErrorCaptured((err: any) => {
|
||||
|
@ -92,7 +95,7 @@ export default defineComponent({
|
|||
text: `Error ${name}: ${message}`
|
||||
};
|
||||
}
|
||||
context.root.$store.commit('setNotification', notification);
|
||||
store.commit('setNotification', notification);
|
||||
return false;
|
||||
});
|
||||
|
||||
|
|
|
@ -13,15 +13,10 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from '@vue/composition-api';
|
||||
import { defineComponent } from '@nuxtjs/composition-api';
|
||||
import { NuxtError } from '@nuxt/types';
|
||||
|
||||
interface Props {
|
||||
error: NuxtError
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
layout: 'empty',
|
||||
data () {
|
||||
return {
|
||||
pageNotFound: '404 Not Found',
|
||||
|
@ -29,7 +24,14 @@ export default defineComponent({
|
|||
};
|
||||
},
|
||||
|
||||
setup(props: Props, _context) {
|
||||
props: {
|
||||
error: {
|
||||
type: Object as () => NuxtError,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
return {
|
||||
error: props.error
|
||||
};
|
||||
|
|
|
@ -45,7 +45,6 @@ export default {
|
|||
** https://nuxtjs.org/guide/plugins
|
||||
*/
|
||||
plugins: [
|
||||
'@/plugins/composition-api'
|
||||
],
|
||||
/*
|
||||
** Auto import components
|
||||
|
@ -57,7 +56,8 @@ export default {
|
|||
*/
|
||||
buildModules: [
|
||||
'@nuxt/typescript-build',
|
||||
'@nuxtjs/vuetify'
|
||||
'@nuxtjs/vuetify',
|
||||
'@nuxtjs/composition-api/module'
|
||||
],
|
||||
/*
|
||||
** Nuxt.js modules
|
||||
|
|
2163
frontend/package-lock.json
generated
2163
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -14,9 +14,9 @@
|
|||
"@mdi/font": "^5.8.55",
|
||||
"@nuxt/typescript-runtime": "^2.0.0",
|
||||
"@nuxtjs/axios": "^5.12.2",
|
||||
"@nuxtjs/composition-api": "^0.33.1",
|
||||
"@nuxtjs/proxy": "^2.0.1",
|
||||
"@nuxtjs/pwa": "^3.2.2",
|
||||
"@vue/composition-api": "^1.0.0-beta.18",
|
||||
"lodash": "^4.17.20",
|
||||
"moment": "^2.29.4",
|
||||
"normalize-url": "4.5.1",
|
||||
|
|
|
@ -43,24 +43,27 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, computed, watch, ComputedRef } from '@vue/composition-api';
|
||||
import { defineComponent, ref, computed, watch, ComputedRef, useStore, useContext } from '@nuxtjs/composition-api';
|
||||
import TaskList from '../components/TaskList.vue';
|
||||
import { Task } from 'taskwarrior-lib';
|
||||
import { accessorType } from "../store";
|
||||
|
||||
export default defineComponent({
|
||||
setup(_props, context) {
|
||||
context.root.$store.dispatch('fetchTasks');
|
||||
setup() {
|
||||
const store = useStore<typeof accessorType>();
|
||||
const context = useContext();
|
||||
store.dispatch('fetchTasks');
|
||||
|
||||
// Auto Refresh
|
||||
let refreshInterval: NodeJS.Timeout | null = null;
|
||||
const setAutoRefresh = () => {
|
||||
if (refreshInterval)
|
||||
clearInterval(refreshInterval);
|
||||
const freq = +context.root.$store.state.settings.autoRefresh;
|
||||
const freq = +store.state.settings.autoRefresh;
|
||||
if (freq > 0) {
|
||||
refreshInterval = setInterval(() => {
|
||||
context.root.$store.dispatch('fetchTasks');
|
||||
}, +context.root.$store.state.settings.autoRefresh * 60000);
|
||||
store.dispatch('fetchTasks');
|
||||
}, +store.state.settings.autoRefresh * 60000);
|
||||
}
|
||||
};
|
||||
setAutoRefresh();
|
||||
|
@ -70,27 +73,27 @@ export default defineComponent({
|
|||
const setAutoSync = () => {
|
||||
if (syncInterval)
|
||||
clearInterval(syncInterval);
|
||||
const freq = +context.root.$store.state.settings.autoSync;
|
||||
const freq = +store.state.settings.autoSync;
|
||||
if (freq > 0) {
|
||||
syncInterval = setInterval(() => {
|
||||
context.root.$store.dispatch('syncTasks');
|
||||
}, +context.root.$store.state.settings.autoSync * 60000);
|
||||
store.dispatch('syncTasks');
|
||||
}, +store.state.settings.autoSync * 60000);
|
||||
}
|
||||
};
|
||||
setAutoSync();
|
||||
|
||||
// Update settings
|
||||
watch(() => context.root.$store.state.settings, () => {
|
||||
watch(() => store.state.settings, () => {
|
||||
setAutoSync();
|
||||
setAutoRefresh();
|
||||
context.root.$vuetify.theme.dark = context.root.$store.state.settings.dark;
|
||||
context.$vuetify.theme.dark = store.state.settings.dark;
|
||||
});
|
||||
|
||||
const mode = ref('Tasks');
|
||||
const allModes = ['Tasks', 'Projects'];
|
||||
|
||||
const project = ref('');
|
||||
const projects: ComputedRef<string[]> = computed(() => context.root.$store.getters.projects);
|
||||
const projects: ComputedRef<string[]> = computed(() => store.getters.projects);
|
||||
watch(projects, () => {
|
||||
if (projects.value.includes(project.value))
|
||||
return;
|
||||
|
@ -102,10 +105,10 @@ export default defineComponent({
|
|||
|
||||
const tasks: ComputedRef<Task[]> = computed(() => {
|
||||
if (mode.value === 'Tasks')
|
||||
return context.root.$store.state.tasks;
|
||||
return store.state.tasks;
|
||||
|
||||
if (project.value)
|
||||
return context.root.$store.state.tasks.filter(
|
||||
return store.state.tasks.filter(
|
||||
(task: Task) => task.project === project.value
|
||||
);
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
// plugins/composition-api.js
|
||||
import Vue from 'vue';
|
||||
import VueCompositionApi from '@vue/composition-api';
|
||||
|
||||
Vue.use(VueCompositionApi);
|
Loading…
Add table
Add a link
Reference in a new issue