WIP: ktb-static #5

Draft
niko wants to merge 9 commits from ktb-static into main
7 changed files with 148 additions and 18 deletions
Showing only changes of commit 81f86acc7b - Show all commits

View file

@ -1,4 +1,4 @@
let HOST = 'http://localhost:1225' let HOST = '' //blank for same-origin
document.addEventListener("alpine:init", () => { document.addEventListener("alpine:init", () => {
Alpine.store("dictionary", { Alpine.store("dictionary", {

View file

@ -26,18 +26,6 @@
--shadow-lg: 0 4px 8px var(--color-shadow); --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; margin: 0;
@ -384,3 +372,19 @@ button:disabled{
color: var(--color-text-secondary); color: var(--color-text-secondary);
font-size: 0.95rem; 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;
}
}

View file

@ -28,6 +28,7 @@
"google-auth-library": "^9.15.1", "google-auth-library": "^9.15.1",
"googleapis": "^149.0.0", "googleapis": "^149.0.0",
"node-fetch": "^3.3.2", "node-fetch": "^3.3.2",
"passport": "^0.7.0",
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",
"sqlite3": "^5.1.7", "sqlite3": "^5.1.7",
"typeorm": "0.3.26", "typeorm": "0.3.26",

View file

@ -1,6 +1,6 @@
import "reflect-metadata" import "reflect-metadata"
import { DataSource } from "typeorm" 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"; const persistent_path = process.env.VI_DB_PERSISTENT_PATH || "./res";
@ -9,7 +9,7 @@ export const appDataSource = new DataSource({
database:`${persistent_path}/dev.sqlite`, database:`${persistent_path}/dev.sqlite`,
synchronize: true, synchronize: true,
logging: false, logging: false,
entities: [Lemma, WordForm, Example, Media, Definition, Comment, PartOfSpeech, Lect], entities: [Lemma, WordForm, Example, Media, Definition, Comment, PartOfSpeech, Lect, Role, User],
migrations: [], migrations: [],
subscribers: [], subscribers: [],
}) })

View file

@ -116,3 +116,24 @@ export class PartOfSpeech extends BaseEntity {
@Column({ nullable: false, unique: true, type: "text" }) @Column({ nullable: false, unique: true, type: "text" })
short_form: string; 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[];
}

View file

@ -1,16 +1,19 @@
import "reflect-metadata"; import "reflect-metadata";
import { SAMPLE } from "@repo/common/sample"; import { SAMPLE } from "@repo/common/sample";
import path from "path"
import { fileURLToPath } from 'url';
import express from "express"; import express from "express";
import crypto from "crypto"; import crypto from "crypto";
import fs from "fs"; import fs from "fs";
import { appDataSource } from "./config/dbconfig.js"; 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 "@total-typescript/ts-reset";
import { Like, In } from "typeorm"; import { Like, In } from "typeorm";
import cors from "cors"; import cors from "cors";
const RELOAD_SHEET_ON_START = false; const RELOAD_SHEET_ON_START = false;
const SOURCE_FILE = "res/sample.tsv"; const SOURCE_FILE = "res/sample.tsv";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
appDataSource appDataSource
.initialize() .initialize()
@ -19,15 +22,86 @@ appDataSource
if (RELOAD_SHEET_ON_START) { if (RELOAD_SHEET_ON_START) {
await loadSheet(); await loadSheet();
await ensureDefaultRoles();
} }
}) })
.catch((error) => console.log(error)); .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() { function initExpress() {
const app = express(); const app = express();
const PORT = 1225; 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) => { app.get("/sample", (_req, res) => {
res.status(200).send(SAMPLE); res.status(200).send(SAMPLE);

32
pnpm-lock.yaml generated
View file

@ -41,6 +41,9 @@ importers:
node-fetch: node-fetch:
specifier: ^3.3.2 specifier: ^3.3.2
version: 3.3.2 version: 3.3.2
passport:
specifier: ^0.7.0
version: 0.7.0
reflect-metadata: reflect-metadata:
specifier: ^0.2.2 specifier: ^0.2.2
version: 0.2.2 version: 0.2.2
@ -1659,7 +1662,7 @@ packages:
glob@7.2.3: glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 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: globals@14.0.0:
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
@ -2210,6 +2213,14 @@ packages:
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
engines: {node: '>= 0.8'} 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: path-browserify@1.0.1:
resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
@ -2240,6 +2251,9 @@ packages:
pathe@2.0.3: pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
pause@0.0.1:
resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==}
picocolors@1.1.1: picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@ -2760,6 +2774,10 @@ packages:
util-deprecate@1.0.2: util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 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: uuid@11.1.0:
resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==}
hasBin: true hasBin: true
@ -4954,6 +4972,14 @@ snapshots:
parseurl@1.3.3: {} 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-browserify@1.0.1: {}
path-exists@4.0.0: {} path-exists@4.0.0: {}
@ -4977,6 +5003,8 @@ snapshots:
pathe@2.0.3: {} pathe@2.0.3: {}
pause@0.0.1: {}
picocolors@1.1.1: {} picocolors@1.1.1: {}
picomatch@2.3.1: {} picomatch@2.3.1: {}
@ -5549,6 +5577,8 @@ snapshots:
util-deprecate@1.0.2: {} util-deprecate@1.0.2: {}
utils-merge@1.0.1: {}
uuid@11.1.0: {} uuid@11.1.0: {}
uuid@9.0.1: {} uuid@9.0.1: {}