refactor: update nuxt.js and composition api

This commit is contained in:
DCsunset 2022-11-09 10:13:09 -05:00
parent 2dd183e9dd
commit cbd6f27c1e
11 changed files with 1141 additions and 1210 deletions

View file

@ -21,14 +21,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, computed } from '@vue/composition-api'; import { defineComponent, computed } from '@nuxtjs/composition-api';
export default defineComponent({ export default defineComponent({
props: { props: {
value: { value: Boolean,
type: Boolean,
required: true
},
title: { title: {
type: String, type: String,
required: true required: true

View file

@ -82,20 +82,20 @@
</template> </template>
<script lang="ts"> <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({ export default defineComponent({
props: { props: {
value: { value: Boolean,
type: Boolean,
required: true
}
}, },
setup(props, context) { setup(props, ctx) {
const store = useStore<typeof accessorType>();
const showDialog = computed({ const showDialog = computed({
get: () => props.value, get: () => props.value,
set: val => context.emit('input', val) set: val => ctx.emit('input', val)
}); });
const numberRules = [ const numberRules = [
@ -104,15 +104,15 @@ export default defineComponent({
const formRef = ref(null); const formRef = ref(null);
const settings = reactive({ const settings = reactive({
dark: context.root.$store.state.settings.dark, dark: store.state.settings.dark,
autoRefresh: context.root.$store.state.settings.autoRefresh, autoRefresh: store.state.settings.autoRefresh,
autoSync: context.root.$store.state.settings.autoSync autoSync: store.state.settings.autoSync
}); });
const reset = () => { const reset = () => {
settings.dark = context.root.$store.state.settings.dark; settings.dark = store.state.settings.dark;
settings.autoRefresh = context.root.$store.state.settings.autoRefresh; settings.autoRefresh = store.state.settings.autoRefresh;
settings.autoSync = context.root.$store.state.settings.autoSync; settings.autoSync = store.state.settings.autoSync;
}; };
const closeDialog = () => { const closeDialog = () => {
@ -123,7 +123,7 @@ export default defineComponent({
const save = () => { const save = () => {
const valid = (formRef as any).value.validate(); const valid = (formRef as any).value.validate();
if (valid) { if (valid) {
context.root.$store.dispatch('updateSettings', { store.dispatch('updateSettings', {
...settings ...settings
}); });
closeDialog(); closeDialog();
@ -131,7 +131,7 @@ export default defineComponent({
}; };
const sync = async () => { const sync = async () => {
await context.root.$store.dispatch('syncTasks'); await store.dispatch('syncTasks');
}; };
return { return {

View file

@ -130,33 +130,27 @@
</template> </template>
<script lang="ts"> <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'; import { Task } from 'taskwarrior-lib';
import { accessorType } from "../store";
interface Props {
[key: string]: unknown,
value: boolean,
task?: Task;
}
export default defineComponent({ export default defineComponent({
props: { props: {
value: { value: Boolean,
type: Boolean,
required: true
},
task: { task: {
type: Object, type: Object as () => Task,
required: false required: false
} }
}, },
setup(props: Props, context) { setup(props, ctx) {
const projects = computed(() => context.root.$store.getters.projects); const store = useStore<typeof accessorType>();
const tags = computed(() => context.root.$store.getters.tags);
const projects = computed(() => store.getters.projects);
const tags = computed(() => store.getters.tags);
const showDialog = computed({ const showDialog = computed({
get: () => props.value, get: () => props.value,
set: val => context.emit('input', val) set: val => ctx.emit('input', val)
}); });
const requiredRules = [ const requiredRules = [
@ -224,7 +218,7 @@ export default defineComponent({
const submit = async () => { const submit = async () => {
const valid = (formRef.value as any).validate(); const valid = (formRef.value as any).validate();
if (valid) { if (valid) {
await context.root.$store.dispatch('updateTasks', [{ await store.dispatch('updateTasks', [{
...formData.value, ...formData.value,
annotations: formData.value.annotations || [], annotations: formData.value.annotations || [],
project: formData.value.project || undefined, project: formData.value.project || undefined,
@ -235,7 +229,7 @@ export default defineComponent({
priority: formData.value.priority === 'N' ? undefined : formData.value.priority, priority: formData.value.priority === 'N' ? undefined : formData.value.priority,
recur: recur.value ? formData.value.recur : undefined recur: recur.value ? formData.value.recur : undefined
}]); }]);
context.root.$store.commit('setNotification', { store.commit('setNotification', {
color: 'success', color: 'success',
text: `Successfully ${props.task ? 'update' : 'create'} the task` text: `Successfully ${props.task ? 'update' : 'create'} the task`
}); });

View file

@ -6,7 +6,7 @@
:text="confirmation.text" :text="confirmation.text"
@yes="confirmation.handler" @yes="confirmation.handler"
/> />
<TaskDialog v-model="showTaskDialog" :task="currentTask" /> <TaskDialog v-model="showTaskDialog" :task="currentTask || undefined" />
<v-row class="px-4 pt-4"> <v-row class="px-4 pt-4">
<v-btn-toggle v-model="status" mandatory background-color="rgba(0, 0, 0, 0)"> <v-btn-toggle v-model="status" mandatory background-color="rgba(0, 0, 0, 0)">
@ -27,8 +27,8 @@
</v-icon> </v-icon>
{{ st }} {{ st }}
<v-badge <v-badge
v-if="st === 'pending' && classifiedTasks[st].length" v-if="st === 'pending' && classifiedTasks[st].value && classifiedTasks[st].value.length"
:content="classifiedTasks[st].length" :content="classifiedTasks[st].value.length"
:color="st === status ? 'primary' : 'grey'" :color="st === status ? 'primary' : 'grey'"
inline inline
/> />
@ -188,7 +188,7 @@
</template> </template>
<script lang="ts"> <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 { Task } from 'taskwarrior-lib';
import _ from 'lodash'; import _ from 'lodash';
import TaskDialog from '../components/TaskDialog.vue'; import TaskDialog from '../components/TaskDialog.vue';
@ -196,6 +196,7 @@ import ConfirmationDialog from '../components/ConfirmationDialog.vue';
import moment from 'moment'; import moment from 'moment';
import urlRegex from 'url-regex-safe'; import urlRegex from 'url-regex-safe';
import normalizeUrl from 'normalize-url'; import normalizeUrl from 'normalize-url';
import { accessorType } from "../store";
function displayDate(str?: string) { function displayDate(str?: string) {
if (!str) if (!str)
@ -254,24 +255,21 @@ function linkify(text: string) {
return result; return result;
} }
interface Props {
[key: string]: unknown,
tasks: Task[]
}
export default defineComponent({ export default defineComponent({
props: { props: {
tasks: { 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 selected = ref([] as Task[]);
const status = ref('pending'); const status = ref('pending');
const allStatus = ['pending', 'waiting', 'completed', 'deleted', 'recurring']; const allStatus = ['pending', 'waiting', 'completed', 'deleted', 'recurring'];
const statusIcons = { const statusIcons: { [st: string]: string } = {
pending: 'mdi-clock-outline', pending: 'mdi-clock-outline',
waiting: 'mdi-pause', waiting: 'mdi-pause',
completed: 'mdi-check', completed: 'mdi-check',
@ -314,7 +312,7 @@ export default defineComponent({
const classifiedTasks = reactive(tempTasks); const classifiedTasks = reactive(tempTasks);
const refresh = () => { const refresh = () => {
context.root.$store.dispatch('fetchTasks'); store.dispatch('fetchTasks');
}; };
const showConfirmationDialog = ref(false); const showConfirmationDialog = ref(false);
@ -337,14 +335,14 @@ export default defineComponent({
}; };
const completeTasks = async (tasks: Task[]) => { const completeTasks = async (tasks: Task[]) => {
await context.root.$store.dispatch('updateTasks', tasks.map(task => { await store.dispatch('updateTasks', tasks.map(task => {
return { return {
...task, ...task,
status: 'completed' status: 'completed'
}; };
})); }));
selected.value = selected.value.filter(task => tasks.findIndex(t => t.uuid === task.uuid) === -1); selected.value = selected.value.filter(task => tasks.findIndex(t => t.uuid === task.uuid) === -1);
context.root.$store.commit('setNotification', { store.commit('setNotification', {
color: 'success', color: 'success',
text: 'Successfully complete the task(s)' text: 'Successfully complete the task(s)'
}); });
@ -353,9 +351,9 @@ export default defineComponent({
const deleteTasks = (tasks: Task[]) => { const deleteTasks = (tasks: Task[]) => {
confirmation.text = 'Are you sure to delete the task(s)?'; confirmation.text = 'Are you sure to delete the task(s)?';
confirmation.handler = async () => { 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); selected.value = selected.value.filter(task => tasks.findIndex(t => t.uuid === task.uuid) === -1);
context.root.$store.commit('setNotification', { store.commit('setNotification', {
color: 'success', color: 'success',
text: 'Successfully delete the task(s)' text: 'Successfully delete the task(s)'
}); });
@ -366,14 +364,14 @@ export default defineComponent({
const restoreTasks = (tasks: Task[]) => { const restoreTasks = (tasks: Task[]) => {
confirmation.text = 'Are you sure to restore the task(s)?'; confirmation.text = 'Are you sure to restore the task(s)?';
confirmation.handler = async () => { confirmation.handler = async () => {
await context.root.$store.dispatch('updateTasks', tasks.map(task => { await store.dispatch('updateTasks', tasks.map(task => {
return { return {
...task, ...task,
status: 'pending' status: 'pending'
}; };
})); }));
selected.value = selected.value.filter(task => tasks.findIndex(t => t.uuid === task.uuid) === -1); selected.value = selected.value.filter(task => tasks.findIndex(t => t.uuid === task.uuid) === -1);
context.root.$store.commit('setNotification', { store.commit('setNotification', {
color: 'success', color: 'success',
text: 'Successfully restore the task(s)' text: 'Successfully restore the task(s)'
}); });

View file

@ -42,37 +42,40 @@
</v-icon> </v-icon>
</v-app-bar> </v-app-bar>
<v-content> <v-main>
<v-container fluid> <v-container fluid>
<nuxt /> <nuxt />
</v-container> </v-container>
</v-content> </v-main>
</v-app> </v-app>
</template> </template>
<script lang="ts"> <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 SettingsDialog from '../components/SettingsDialog.vue';
import { accessorType } from "../store";
export default defineComponent({ export default defineComponent({
setup(_props, context) { setup(_props, ctx) {
context.root.$store.dispatch('fetchSettings'); 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({ const dark = computed({
get: () => context.root.$vuetify.theme.dark, get: () => context.$vuetify.theme.dark,
set: val => { set: val => {
context.root.$vuetify.theme.dark = val; context.$vuetify.theme.dark = val;
} }
}); });
const settingsDialog = ref(false); const settingsDialog = ref(false);
const notification = computed(() => context.root.$store.state.notification); const notification = computed(() => store.state.notification);
const snackbar = computed({ const snackbar = computed({
get: () => context.root.$store.state.snackbar, get: () => store.state.snackbar,
set: val => context.root.$store.commit('setSnackbar', val) set: val => store.commit('setSnackbar', val)
}); });
onErrorCaptured((err: any) => { onErrorCaptured((err: any) => {
@ -92,7 +95,7 @@ export default defineComponent({
text: `Error ${name}: ${message}` text: `Error ${name}: ${message}`
}; };
} }
context.root.$store.commit('setNotification', notification); store.commit('setNotification', notification);
return false; return false;
}); });

View file

@ -13,15 +13,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from '@vue/composition-api'; import { defineComponent } from '@nuxtjs/composition-api';
import { NuxtError } from '@nuxt/types'; import { NuxtError } from '@nuxt/types';
interface Props {
error: NuxtError
};
export default defineComponent({ export default defineComponent({
layout: 'empty',
data () { data () {
return { return {
pageNotFound: '404 Not Found', 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 { return {
error: props.error error: props.error
}; };

View file

@ -45,7 +45,6 @@ export default {
** https://nuxtjs.org/guide/plugins ** https://nuxtjs.org/guide/plugins
*/ */
plugins: [ plugins: [
'@/plugins/composition-api'
], ],
/* /*
** Auto import components ** Auto import components
@ -57,7 +56,8 @@ export default {
*/ */
buildModules: [ buildModules: [
'@nuxt/typescript-build', '@nuxt/typescript-build',
'@nuxtjs/vuetify' '@nuxtjs/vuetify',
'@nuxtjs/composition-api/module'
], ],
/* /*
** Nuxt.js modules ** Nuxt.js modules

File diff suppressed because it is too large Load diff

View file

@ -14,9 +14,9 @@
"@mdi/font": "^5.8.55", "@mdi/font": "^5.8.55",
"@nuxt/typescript-runtime": "^2.0.0", "@nuxt/typescript-runtime": "^2.0.0",
"@nuxtjs/axios": "^5.12.2", "@nuxtjs/axios": "^5.12.2",
"@nuxtjs/composition-api": "^0.33.1",
"@nuxtjs/proxy": "^2.0.1", "@nuxtjs/proxy": "^2.0.1",
"@nuxtjs/pwa": "^3.2.2", "@nuxtjs/pwa": "^3.2.2",
"@vue/composition-api": "^1.0.0-beta.18",
"lodash": "^4.17.20", "lodash": "^4.17.20",
"moment": "^2.29.4", "moment": "^2.29.4",
"normalize-url": "4.5.1", "normalize-url": "4.5.1",

View file

@ -43,24 +43,27 @@
</template> </template>
<script lang="ts"> <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 TaskList from '../components/TaskList.vue';
import { Task } from 'taskwarrior-lib'; import { Task } from 'taskwarrior-lib';
import { accessorType } from "../store";
export default defineComponent({ export default defineComponent({
setup(_props, context) { setup() {
context.root.$store.dispatch('fetchTasks'); const store = useStore<typeof accessorType>();
const context = useContext();
store.dispatch('fetchTasks');
// Auto Refresh // Auto Refresh
let refreshInterval: NodeJS.Timeout | null = null; let refreshInterval: NodeJS.Timeout | null = null;
const setAutoRefresh = () => { const setAutoRefresh = () => {
if (refreshInterval) if (refreshInterval)
clearInterval(refreshInterval); clearInterval(refreshInterval);
const freq = +context.root.$store.state.settings.autoRefresh; const freq = +store.state.settings.autoRefresh;
if (freq > 0) { if (freq > 0) {
refreshInterval = setInterval(() => { refreshInterval = setInterval(() => {
context.root.$store.dispatch('fetchTasks'); store.dispatch('fetchTasks');
}, +context.root.$store.state.settings.autoRefresh * 60000); }, +store.state.settings.autoRefresh * 60000);
} }
}; };
setAutoRefresh(); setAutoRefresh();
@ -70,27 +73,27 @@ export default defineComponent({
const setAutoSync = () => { const setAutoSync = () => {
if (syncInterval) if (syncInterval)
clearInterval(syncInterval); clearInterval(syncInterval);
const freq = +context.root.$store.state.settings.autoSync; const freq = +store.state.settings.autoSync;
if (freq > 0) { if (freq > 0) {
syncInterval = setInterval(() => { syncInterval = setInterval(() => {
context.root.$store.dispatch('syncTasks'); store.dispatch('syncTasks');
}, +context.root.$store.state.settings.autoSync * 60000); }, +store.state.settings.autoSync * 60000);
} }
}; };
setAutoSync(); setAutoSync();
// Update settings // Update settings
watch(() => context.root.$store.state.settings, () => { watch(() => store.state.settings, () => {
setAutoSync(); setAutoSync();
setAutoRefresh(); 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 mode = ref('Tasks');
const allModes = ['Tasks', 'Projects']; const allModes = ['Tasks', 'Projects'];
const project = ref(''); const project = ref('');
const projects: ComputedRef<string[]> = computed(() => context.root.$store.getters.projects); const projects: ComputedRef<string[]> = computed(() => store.getters.projects);
watch(projects, () => { watch(projects, () => {
if (projects.value.includes(project.value)) if (projects.value.includes(project.value))
return; return;
@ -102,10 +105,10 @@ export default defineComponent({
const tasks: ComputedRef<Task[]> = computed(() => { const tasks: ComputedRef<Task[]> = computed(() => {
if (mode.value === 'Tasks') if (mode.value === 'Tasks')
return context.root.$store.state.tasks; return store.state.tasks;
if (project.value) if (project.value)
return context.root.$store.state.tasks.filter( return store.state.tasks.filter(
(task: Task) => task.project === project.value (task: Task) => task.project === project.value
); );

View file

@ -1,5 +0,0 @@
// plugins/composition-api.js
import Vue from 'vue';
import VueCompositionApi from '@vue/composition-api';
Vue.use(VueCompositionApi);