New: backendのtsconfig.jsonにesModuleInteropを追加 / Fix: 一部エンティティの時刻記録をdateからdatetimeに修正 / Fix: setup/initializationエンドポイントでのwebpushのimport方法の問題 / Chg: font-sizeを16pxから14pxに変更 / Chg: html, bodyのwidthとheightをvw/vhからdvw/dvhに変更 / Feat: レイアウトを作成 / New(frontend): /setupを作成
This commit is contained in:
@@ -27,13 +27,13 @@ export class TokenEntity {
|
|||||||
isNative!: boolean;
|
isNative!: boolean;
|
||||||
|
|
||||||
@Property({
|
@Property({
|
||||||
type: "date",
|
type: "datetime",
|
||||||
onCreate: () => new Date(),
|
onCreate: () => new Date(),
|
||||||
})
|
})
|
||||||
createdAt!: Date;
|
createdAt!: Date;
|
||||||
|
|
||||||
@Property({
|
@Property({
|
||||||
type: "date",
|
type: "datetime",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
lastUsedAt?: Date;
|
lastUsedAt?: Date;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export class UserEntity {
|
|||||||
type: "boolean",
|
type: "boolean",
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
isAdmin: boolean = false;
|
isOwner: boolean = false;
|
||||||
|
|
||||||
@Property({
|
@Property({
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
@@ -64,4 +64,10 @@ export class UserEntity {
|
|||||||
onCreate: () => new Date(),
|
onCreate: () => new Date(),
|
||||||
})
|
})
|
||||||
createdAt!: Date;
|
createdAt!: Date;
|
||||||
|
|
||||||
|
@Property({
|
||||||
|
type: "datetime",
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
lastUsedAt?: Date;
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ import { DatabaseError, ErrorBase, InputError } from "@/errors";
|
|||||||
import Logger from "@/lib/logger";
|
import Logger from "@/lib/logger";
|
||||||
import { ConfigEntity } from "@/modules/entities/Config";
|
import { ConfigEntity } from "@/modules/entities/Config";
|
||||||
import type { FastifyInstance } from "fastify";
|
import type { FastifyInstance } from "fastify";
|
||||||
import { generateVAPIDKeys } from "web-push";
|
import webpush from "web-push";
|
||||||
import z from "zod/v3";
|
import z from "zod/v3";
|
||||||
|
|
||||||
export default function SetupInitialization(fastify: FastifyInstance) {
|
export default function SetupInitialization(fastify: FastifyInstance) {
|
||||||
@@ -48,7 +48,7 @@ export default function SetupInitialization(fastify: FastifyInstance) {
|
|||||||
try {
|
try {
|
||||||
const entries = Object.entries(result.data).filter(([key]) => key !== "force");
|
const entries = Object.entries(result.data).filter(([key]) => key !== "force");
|
||||||
|
|
||||||
const vapid = generateVAPIDKeys();
|
const vapid = webpush.generateVAPIDKeys();
|
||||||
entries.push(["VAPID_PUBLIC", vapid.publicKey]);
|
entries.push(["VAPID_PUBLIC", vapid.publicKey]);
|
||||||
entries.push(["VAPID_PRIVATE", vapid.privateKey]);
|
entries.push(["VAPID_PRIVATE", vapid.privateKey]);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"exactOptionalPropertyTypes": true,
|
"exactOptionalPropertyTypes": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
|
|||||||
@@ -5,14 +5,60 @@
|
|||||||
:size="6"
|
:size="6"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<main>
|
<main class="layout">
|
||||||
|
<div class="left-menu">
|
||||||
|
<div>
|
||||||
|
ホーム
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="route-main">
|
||||||
<RouterView
|
<RouterView
|
||||||
:key="$route.fullPath"
|
:key="$route.fullPath"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
main.layout {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
width: 100dvw;
|
||||||
|
height: 100dvh;
|
||||||
|
padding: 1rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-menu {
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-menu div {
|
||||||
|
width: 6rem;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
border-radius: 2rem;
|
||||||
|
padding: 1rem;
|
||||||
|
transition: all 100ms ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-menu div:hover {
|
||||||
|
background-color: var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.route-main {
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
padding: 0.75rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.router-progress {
|
.router-progress {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0.5rem 0.5rem 0 auto;
|
inset: 0.5rem 0.5rem 0 auto;
|
||||||
@@ -21,15 +67,18 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { RouterView } from "vue-router";
|
import { RouterView, useRouter } from "vue-router";
|
||||||
import routerStatus from "@/lib/router";
|
import routerStatus from "@/lib/router";
|
||||||
import Progress from "@/components/Progress.vue";
|
import Progress from "@/components/Progress.vue";
|
||||||
import { ref } from "vue";
|
|
||||||
import serverInfo from "@/lib/account";
|
import serverInfo from "@/lib/account";
|
||||||
|
|
||||||
const isBootFailed = ref<boolean>(false);
|
const router = useRouter();
|
||||||
|
|
||||||
if (!serverInfo.success) {
|
if (!serverInfo.success) {
|
||||||
isBootFailed.value = true;
|
throw new Error();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!serverInfo.isFirstAdminExists) {
|
||||||
|
router.replace("/setup");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
:root {
|
:root {
|
||||||
--bg-color: #ffffff;
|
--bg-color: #ffffff;
|
||||||
--text-color: #000000;
|
--text-color: #000000;
|
||||||
|
--border-color: #e0e0e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
:root {
|
:root {
|
||||||
--bg-color: #1b1b1b;
|
--bg-color: #1b1b1b;
|
||||||
--text-color: #ffffff;
|
--text-color: #ffffff;
|
||||||
|
--border-color: #2c2c2c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,9 +18,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
width: 100vw;
|
width: 100dvw;
|
||||||
height: 100vh;
|
height: 100dvh;
|
||||||
font-size: 16px;
|
font-size: 14px;
|
||||||
background-color: var(--bg-color);
|
background-color: var(--bg-color);
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ const router = createRouter({
|
|||||||
path: "/",
|
path: "/",
|
||||||
component: () => import("@/routes/index.vue"),
|
component: () => import("@/routes/index.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/setup",
|
||||||
|
component: () => import("@/routes/setup.vue"),
|
||||||
|
}
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
router.beforeEach(() => {
|
router.beforeEach(() => {
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<template>
|
||||||
|
<h1>Welcome setup wizard!!</h1>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import serverInfo from "@/lib/account";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
if (!serverInfo.success) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverInfo.isFirstAdminExists) {
|
||||||
|
router.replace("/");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user