This commit is contained in:
parent
da7d75641d
commit
81f86acc7b
7 changed files with 148 additions and 18 deletions
|
|
@ -1,4 +1,4 @@
|
|||
let HOST = 'http://localhost:1225'
|
||||
let HOST = '' //blank for same-origin
|
||||
|
||||
document.addEventListener("alpine:init", () => {
|
||||
Alpine.store("dictionary", {
|
||||
|
|
|
|||
|
|
@ -26,18 +26,6 @@
|
|||
--shadow-lg: 0 4px 8px var(--color-shadow);
|
||||
}
|
||||
|
||||
/* Small devices (portrait tablets and large phones, 600px and up) */
|
||||
@media (max-width: 600px) {
|
||||
.cards-container {
|
||||
grid-template-columns: 1fr;
|
||||
background-color: #fb0;
|
||||
}
|
||||
|
||||
.is-expanded {
|
||||
grid-row: span 1;
|
||||
grid-column: span 1;
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
|
|
@ -384,3 +372,19 @@ button:disabled{
|
|||
color: var(--color-text-secondary);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
/* Small devices (portrait tablets and large phones, 600px and up) */
|
||||
@media (max-width: 600px) {
|
||||
.cards-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
"google-auth-library": "^9.15.1",
|
||||
"googleapis": "^149.0.0",
|
||||
"node-fetch": "^3.3.2",
|
||||
"passport": "^0.7.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"sqlite3": "^5.1.7",
|
||||
"typeorm": "0.3.26",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import "reflect-metadata"
|
||||
import { DataSource } from "typeorm"
|
||||
import {Lemma, WordForm, Media, Example, Definition, Comment, PartOfSpeech, Lect} from "../db/dbmodel.js"
|
||||
import {Lemma, WordForm, Media, Example, Definition, Comment, PartOfSpeech, Lect, Role, User} from "../db/dbmodel.js"
|
||||
|
||||
const persistent_path = process.env.VI_DB_PERSISTENT_PATH || "./res";
|
||||
|
||||
|
|
@ -9,7 +9,7 @@ export const appDataSource = new DataSource({
|
|||
database:`${persistent_path}/dev.sqlite`,
|
||||
synchronize: true,
|
||||
logging: false,
|
||||
entities: [Lemma, WordForm, Example, Media, Definition, Comment, PartOfSpeech, Lect],
|
||||
entities: [Lemma, WordForm, Example, Media, Definition, Comment, PartOfSpeech, Lect, Role, User],
|
||||
migrations: [],
|
||||
subscribers: [],
|
||||
})
|
||||
|
|
@ -116,3 +116,24 @@ export class PartOfSpeech extends BaseEntity {
|
|||
@Column({ nullable: false, unique: true, type: "text" })
|
||||
short_form: string;
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class User extends BaseEntity {
|
||||
@PrimaryColumn({ type: "text", nullable: false })
|
||||
user_name: string;
|
||||
|
||||
@ManyToMany(() => Role, (role) => role.users, {eager:true})
|
||||
@JoinTable()
|
||||
roles: Role[];
|
||||
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class Role extends BaseEntity {
|
||||
@PrimaryColumn({ type: "text", nullable: false})
|
||||
role_name: string;
|
||||
|
||||
@ManyToMany(() => User, (user) => user.roles, {eager:true})
|
||||
@JoinTable()
|
||||
users: User[];
|
||||
}
|
||||
|
|
@ -1,16 +1,19 @@
|
|||
import "reflect-metadata";
|
||||
import { SAMPLE } from "@repo/common/sample";
|
||||
import path from "path"
|
||||
import { fileURLToPath } from 'url';
|
||||
import express from "express";
|
||||
import crypto from "crypto";
|
||||
import fs from "fs";
|
||||
import { appDataSource } from "./config/dbconfig.js";
|
||||
import { Lemma, WordForm, Lect, Definition, Example } from "./db/dbmodel.js";
|
||||
import { Lemma, WordForm, Lect, Definition, Example, Role, User } from "./db/dbmodel.js";
|
||||
import "@total-typescript/ts-reset";
|
||||
import { Like, In } from "typeorm";
|
||||
import cors from "cors";
|
||||
|
||||
const RELOAD_SHEET_ON_START = false;
|
||||
const SOURCE_FILE = "res/sample.tsv";
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
appDataSource
|
||||
.initialize()
|
||||
|
|
@ -19,15 +22,86 @@ appDataSource
|
|||
|
||||
if (RELOAD_SHEET_ON_START) {
|
||||
await loadSheet();
|
||||
await ensureDefaultRoles();
|
||||
}
|
||||
})
|
||||
.catch((error) => console.log(error));
|
||||
|
||||
async function ensureDefaultRoles(){
|
||||
const ADMIN_NAME = "admin"
|
||||
const EDITOR_NAME = "editor"
|
||||
const READER_NAME = "reader"
|
||||
|
||||
let admin_role = new Role();
|
||||
admin_role.role_name = ADMIN_NAME;
|
||||
|
||||
let editor_role = new Role();
|
||||
editor_role.role_name = EDITOR_NAME;
|
||||
|
||||
let reader_role = new Role();
|
||||
reader_role.role_name = READER_NAME;
|
||||
|
||||
Role.save([admin_role, editor_role, reader_role]);
|
||||
|
||||
let admin_user: User;
|
||||
let editor_user: User;
|
||||
let reader_user: User;
|
||||
|
||||
await User.findOne({where:
|
||||
{user_name:ADMIN_NAME}
|
||||
}).then(async (u)=>{
|
||||
//if no admin user is detected, generate one with the admin role
|
||||
if (!u){
|
||||
admin_user = new User();
|
||||
admin_user.user_name = ADMIN_NAME;
|
||||
admin_user.roles = [admin_role];
|
||||
await admin_user
|
||||
.save()
|
||||
.then((u)=>{
|
||||
admin_user = u;
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
await User.findOne({where:
|
||||
{user_name:EDITOR_NAME}
|
||||
}).then(async (u)=>{
|
||||
if (!u){
|
||||
editor_user = new User();
|
||||
editor_user.user_name = EDITOR_NAME;
|
||||
editor_user.roles = [editor_role];
|
||||
await editor_user
|
||||
.save()
|
||||
.then((u)=>{
|
||||
editor_user = u;
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
await User.findOne({where:
|
||||
{user_name:READER_NAME}
|
||||
}).then(async (u)=>{
|
||||
if (!u){
|
||||
reader_user = new User();
|
||||
reader_user.user_name = READER_NAME;
|
||||
reader_user.roles = [reader_role];
|
||||
await reader_user
|
||||
.save()
|
||||
.then((u)=>{
|
||||
reader_user = u;
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function initExpress() {
|
||||
const app = express();
|
||||
const PORT = 1225;
|
||||
|
||||
app.use(cors(), express.json());
|
||||
console.info(path.join(__dirname, '../../ktb-static'));
|
||||
|
||||
app.use(express.json(), express.static(path.join(__dirname, '../../ktb-static')));
|
||||
|
||||
app.get("/sample", (_req, res) => {
|
||||
res.status(200).send(SAMPLE);
|
||||
|
|
|
|||
32
pnpm-lock.yaml
generated
32
pnpm-lock.yaml
generated
|
|
@ -41,6 +41,9 @@ importers:
|
|||
node-fetch:
|
||||
specifier: ^3.3.2
|
||||
version: 3.3.2
|
||||
passport:
|
||||
specifier: ^0.7.0
|
||||
version: 0.7.0
|
||||
reflect-metadata:
|
||||
specifier: ^0.2.2
|
||||
version: 0.2.2
|
||||
|
|
@ -1659,7 +1662,7 @@ packages:
|
|||
|
||||
glob@7.2.3:
|
||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
|
||||
deprecated: Glob versions prior to v9 are no longer supported
|
||||
|
||||
globals@14.0.0:
|
||||
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
|
||||
|
|
@ -2210,6 +2213,14 @@ packages:
|
|||
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
passport-strategy@1.0.0:
|
||||
resolution: {integrity: sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
|
||||
passport@0.7.0:
|
||||
resolution: {integrity: sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
|
||||
path-browserify@1.0.1:
|
||||
resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
|
||||
|
||||
|
|
@ -2240,6 +2251,9 @@ packages:
|
|||
pathe@2.0.3:
|
||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||
|
||||
pause@0.0.1:
|
||||
resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==}
|
||||
|
||||
picocolors@1.1.1:
|
||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||
|
||||
|
|
@ -2760,6 +2774,10 @@ packages:
|
|||
util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
||||
utils-merge@1.0.1:
|
||||
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
|
||||
uuid@11.1.0:
|
||||
resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==}
|
||||
hasBin: true
|
||||
|
|
@ -4954,6 +4972,14 @@ snapshots:
|
|||
|
||||
parseurl@1.3.3: {}
|
||||
|
||||
passport-strategy@1.0.0: {}
|
||||
|
||||
passport@0.7.0:
|
||||
dependencies:
|
||||
passport-strategy: 1.0.0
|
||||
pause: 0.0.1
|
||||
utils-merge: 1.0.1
|
||||
|
||||
path-browserify@1.0.1: {}
|
||||
|
||||
path-exists@4.0.0: {}
|
||||
|
|
@ -4977,6 +5003,8 @@ snapshots:
|
|||
|
||||
pathe@2.0.3: {}
|
||||
|
||||
pause@0.0.1: {}
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
|
||||
picomatch@2.3.1: {}
|
||||
|
|
@ -5549,6 +5577,8 @@ snapshots:
|
|||
|
||||
util-deprecate@1.0.2: {}
|
||||
|
||||
utils-merge@1.0.1: {}
|
||||
|
||||
uuid@11.1.0: {}
|
||||
|
||||
uuid@9.0.1: {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue