From 7361dcc5f703179ea9203e65b8ba763b0808f2b6 Mon Sep 17 00:00:00 2001 From: Hayden <64056131+hay-kot@users.noreply.github.com> Date: Tue, 30 Aug 2022 16:07:21 -0800 Subject: [PATCH] setup basic auth --- frontend/components.d.ts | 3 + frontend/package.json | 4 +- frontend/pnpm-lock.yaml | 10 +++ frontend/src/App.vue | 5 ++ frontend/src/components/App/Toast.vue | 71 +++++++++++++++++ frontend/src/composables/use-api.ts | 23 ++++++ frontend/src/composables/use-ids.ts | 31 ++++++++ frontend/src/composables/use-notifier.ts | 57 ++++++++++++++ frontend/src/layouts/default.vue | 13 ++-- frontend/src/pages/home.vue | 59 ++++++++++++++ frontend/src/pages/index.vue | 97 ++++++++++++++++++++---- frontend/src/store/auth.ts | 21 +++++ frontend/typed-router.d.ts | 3 +- frontend/vite.config.ts | 13 +++- 14 files changed, 382 insertions(+), 28 deletions(-) create mode 100644 frontend/src/components/App/Toast.vue create mode 100644 frontend/src/composables/use-api.ts create mode 100755 frontend/src/composables/use-ids.ts create mode 100644 frontend/src/composables/use-notifier.ts create mode 100644 frontend/src/pages/home.vue create mode 100644 frontend/src/store/auth.ts diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 37aaa6c..50c0ff9 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -8,11 +8,14 @@ export {} declare module '@vue/runtime-core' { export interface GlobalComponents { AppHeader: typeof import('./src/components/AppHeader.vue')['default'] + Icon: typeof import('./src/components/Icon.vue')['default'] 'Icon:bx:bxMoon': typeof import('~icons/bx/bx-moon')['default'] 'Icon:bx:bxsMoon': typeof import('~icons/bx/bxs-moon')['default'] 'IconAkarIcons:githubFill': typeof import('~icons/akar-icons/github-fill')['default'] + Notifier: typeof import('./src/components/App/Notifier.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] TextField: typeof import('./src/components/Form/TextField.vue')['default'] + Toast: typeof import('./src/components/App/Toast.vue')['default'] } } diff --git a/frontend/package.json b/frontend/package.json index 45dd54b..6c8018b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,6 +23,7 @@ "dev": "vite", "build": "vite-ssg build", "serve": "vite preview", + "test:watch": "vitest --watch", "https-preview": "serve dist" }, "dependencies": { @@ -46,6 +47,7 @@ }, "devDependencies": { "@iconify/json": "^2.1.78", + "@iconify/vue": "^3.2.1", "@intlify/vite-plugin-vue-i18n": "^5.0.0", "@vitejs/plugin-vue": "^3.0.0", "@vue/compiler-sfc": "^3.2.37", @@ -66,4 +68,4 @@ "vitest": "^0.18.0", "vue-tsc": "^0.38.5" } -} +} \ No newline at end of file diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 956b60f..b500c33 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -2,6 +2,7 @@ lockfileVersion: 5.4 specifiers: '@iconify/json': ^2.1.78 + '@iconify/vue': ^3.2.1 '@intlify/vite-plugin-vue-i18n': ^5.0.0 '@tailwindcss/aspect-ratio': ^0.4.0 '@tailwindcss/forms': ^0.5.2 @@ -60,6 +61,7 @@ dependencies: devDependencies: '@iconify/json': 2.1.78 + '@iconify/vue': 3.2.1_vue@3.2.37 '@intlify/vite-plugin-vue-i18n': 5.0.0_vite@3.0.0+vue-i18n@9.1.10 '@vitejs/plugin-vue': 3.0.0_vite@3.0.0+vue@3.2.37 '@vue/compiler-sfc': 3.2.37 @@ -1269,6 +1271,14 @@ packages: - supports-color dev: true + /@iconify/vue/3.2.1_vue@3.2.37: + resolution: {integrity: sha512-c4R6ZgFo1JrJ8aPMMgOPgfU7lBswihMGR+yWe/P4ZukC3kTkeT4+lkt9Pc/itVFMkwva/S/7u9YofmYv57fnNQ==} + peerDependencies: + vue: 3.x + dependencies: + vue: 3.2.37 + dev: true + /@intlify/bundle-utils/3.1.0_vue-i18n@9.1.10: resolution: {integrity: sha512-ghlJ0kR2cCQ8D+poKknC0Xx0ncOt3J3os7CcIAqqIWVF7k6AtGoCDnIru+YzlZcvFRNmP9wEZ7jKliojCdAWNg==} engines: {node: '>= 12'} diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 4437b0a..7dc8709 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,3 +1,8 @@ + + + diff --git a/frontend/src/components/App/Toast.vue b/frontend/src/components/App/Toast.vue new file mode 100644 index 0000000..5a92ff6 --- /dev/null +++ b/frontend/src/components/App/Toast.vue @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + {{ notify.message }} + + + + + + + + + diff --git a/frontend/src/composables/use-api.ts b/frontend/src/composables/use-api.ts new file mode 100644 index 0000000..806cb88 --- /dev/null +++ b/frontend/src/composables/use-api.ts @@ -0,0 +1,23 @@ +import { PublicApi } from '@/api/public'; +import { UserApi } from '@/api/user'; +import { Requests } from '@/lib/requests'; +import { useAuthStore } from '@/store/auth'; + +async function ApiDebugger(r: Response) { + console.table({ + 'Request Url': r.url, + 'Response Status': r.status, + 'Response Status Text': r.statusText, + }); +} + +export function usePublicApi(): PublicApi { + const requests = new Requests('', '', {}, ApiDebugger); + return new PublicApi(requests); +} + +export function useUserApi(): UserApi { + const authStore = useAuthStore(); + const requests = new Requests('', () => authStore.token, {}, ApiDebugger); + return new UserApi(requests); +} diff --git a/frontend/src/composables/use-ids.ts b/frontend/src/composables/use-ids.ts new file mode 100755 index 0000000..dd1a164 --- /dev/null +++ b/frontend/src/composables/use-ids.ts @@ -0,0 +1,31 @@ +function slugify(text: string) { + return text + .toString() + .toLowerCase() + .replace(/\s+/g, '-') // Replace spaces with - + .replace(/[^\w\-]+/g, '') // Remove all non-word chars + .replace(/\-\-+/g, '-') // Replace multiple - with single - + .replace(/^-+/, '') // Trim - from start of text + .replace(/-+$/, ''); // Trim - from end of text +} + +function idGenerator(): string { + const id = + Math.random().toString(32).substring(2, 6) + + Math.random().toString(36).substring(2, 6); + return slugify(id); +} + +/** + * useFormIds uses the provided label to generate a unique id for the + * form element. If no label is provided the id is generated using a + * random string. + */ +export function useFormIds(label: string): string { + const slug = label ? slugify(label) : idGenerator(); + return `${slug}-${idGenerator()}`; +} + +export function useId(): string { + return idGenerator(); +} diff --git a/frontend/src/composables/use-notifier.ts b/frontend/src/composables/use-notifier.ts new file mode 100644 index 0000000..4158cda --- /dev/null +++ b/frontend/src/composables/use-notifier.ts @@ -0,0 +1,57 @@ +import { useId } from './use-ids'; + +interface Notification { + id: string; + message: string; + type: 'success' | 'error' | 'info'; +} + +const notifications = ref([]); + +function addNotification(notification: Notification) { + notifications.value.unshift(notification); + + if (notifications.value.length > 4) { + notifications.value.pop(); + } else { + setTimeout(() => { + // Remove notification with ID + notifications.value = notifications.value.filter( + n => n.id !== notification.id + ); + }, 5000); + } +} + +export function useNotifications() { + return { + notifications, + dropNotification: (idx: number) => notifications.value.splice(idx, 1), + }; +} + +export function useNotifier() { + return { + success: (message: string) => { + addNotification({ + id: useId(), + message, + type: 'success', + }); + }, + error: (message: string) => { + addNotification({ + id: useId(), + message, + type: 'error', + }); + }, + info: (message: string) => { + addNotification({ + id: useId(), + message, + type: 'info', + }); + }, + }; +} diff --git a/frontend/src/layouts/default.vue b/frontend/src/layouts/default.vue index f71177c..735bf21 100644 --- a/frontend/src/layouts/default.vue +++ b/frontend/src/layouts/default.vue @@ -1,17 +1,14 @@ - + + diff --git a/frontend/src/pages/home.vue b/frontend/src/pages/home.vue new file mode 100644 index 0000000..f159a2c --- /dev/null +++ b/frontend/src/pages/home.vue @@ -0,0 +1,59 @@ + + + + + + + Homebox + + + + + {{ link.name }} + + / + + + + + + {{ user }} + + + + +name: home + diff --git a/frontend/src/pages/index.vue b/frontend/src/pages/index.vue index 0e7d151..f296f86 100644 --- a/frontend/src/pages/index.vue +++ b/frontend/src/pages/index.vue @@ -1,5 +1,8 @@