diff --git a/app.ts b/app.ts
index b1a9d4d..a6a1a2e 100644
--- a/app.ts
+++ b/app.ts
@@ -1,5 +1,5 @@
import { app, BrowserWindow, session, dialog } from "electron";
-import { get_setting } from "./src/setting";
+import { get_setting } from "./src/SettingConfig";
import { create_server, start_server } from "./src/server";
import { getAdminAccessTokenValue,getAdminRefreshTokenValue, accessTokenName, refreshTokenName } from "./src/login";
@@ -14,8 +14,8 @@ if (!setting.cli) {
center: true,
useContentSize: true,
});
- //await window.loadURL(`data:text/html;base64,`+Buffer.from(get_loading_html()).toString('base64'));
- await wnd.loadFile('../loading.html');
+ await wnd.loadURL(`data:text/html;base64,`+Buffer.from(loading_html).toString('base64'));
+ //await wnd.loadURL('../loading.html');
await session.defaultSession.cookies.set({
url:`http://localhost:${setting.port}`,
name:accessTokenName,
@@ -88,3 +88,35 @@ if (!setting.cli) {
start_server(server);
})();
}
+const loading_html = `
+
+
+loading
+
+
+
+
+
+ Loading...
+
+
+`;
\ No newline at end of file
diff --git a/gen_conf_schema.ts b/gen_conf_schema.ts
new file mode 100644
index 0000000..5a2071d
--- /dev/null
+++ b/gen_conf_schema.ts
@@ -0,0 +1,48 @@
+import { promises } from 'fs';
+const { readdir, writeFile } = promises;
+import {createGenerator} from 'ts-json-schema-generator';
+import {dirname,join} from 'path';
+
+async function genSchema(path:string,typename:string){
+ const gen = createGenerator({
+ path:path,
+ type:typename,
+ tsconfig:"tsconfig.json"
+ });
+ const schema = gen.createSchema(typename);
+ if(schema.definitions != undefined){
+ const definitions = schema.definitions;
+ const definition = definitions[typename];
+ if(typeof definition == "object" ){
+ let property = definition.properties;
+ if(property){
+ property['$schema'] = {
+ type:"string"
+ };
+ }
+ }
+ }
+ const text = JSON.stringify(schema);
+ await writeFile(join(dirname(path),`${typename}.schema.json`),text);
+}
+function capitalize(s:string){
+ return s.charAt(0).toUpperCase() + s.slice(1);
+}
+async function setToALL(path:string) {
+ console.log(`scan ${path}`)
+ const direntry = await readdir(path,{withFileTypes:true});
+ const works = direntry.filter(x=>x.isFile()&&x.name.endsWith("Config.ts")).map(x=>{
+ const name = x.name;
+ const m = /(.+)\.ts/.exec(name);
+ if(m !== null){
+ const typename = m[1];
+ return genSchema(join(path,typename),capitalize(typename));
+ }
+ })
+ await Promise.all(works);
+ const subdir = direntry.filter(x=>x.isDirectory()).map(x=>x.name);
+ for(const x of subdir){
+ await setToALL(join(path,x));
+ }
+}
+setToALL("src")
\ No newline at end of file
diff --git a/loading.html b/loading.html
deleted file mode 100644
index e0ac6a5..0000000
--- a/loading.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-loading
-
-
-
-
-
- Loading...
-
-
-
\ No newline at end of file
diff --git a/migrations/initial.ts b/migrations/initial.ts
index 86a16d3..36178b6 100644
--- a/migrations/initial.ts
+++ b/migrations/initial.ts
@@ -14,7 +14,8 @@ export async function up(knex:Knex) {
b.string("filename",256).notNullable().comment("filename");
b.string("content_hash").nullable();
b.json("additional").nullable();
- b.timestamps();
+ b.integer("created_at").notNullable();
+ b.integer("deleted_at");
b.index("content_type","content_type_index");
});
await knex.schema.createTable("tags", (b)=>{
diff --git a/package.json b/package.json
index 52e83ab..85c9989 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,8 @@
"files": [
"build/**/*",
"node_modules/**/*",
- "package.json"
+ "package.json",
+ "!node_modules/@material-ui/**/*"
],
"appId": "com.prelude.ionian.app",
"productName": "Ionian",
@@ -82,6 +83,7 @@
"eslint-plugin-node": "^11.1.0",
"mini-css-extract-plugin": "^1.3.3",
"style-loader": "^2.0.0",
+ "ts-json-schema-generator": "^0.82.0",
"ts-node": "^9.1.1",
"typescript": "^4.1.3",
"webpack": "^5.11.0",
diff --git a/preload.ts b/preload.ts
new file mode 100644
index 0000000..fd3d7bf
--- /dev/null
+++ b/preload.ts
@@ -0,0 +1 @@
+import {} from 'electron';
\ No newline at end of file
diff --git a/src/SettingConfig.schema.json b/src/SettingConfig.schema.json
new file mode 100644
index 0000000..aedb7ab
--- /dev/null
+++ b/src/SettingConfig.schema.json
@@ -0,0 +1,66 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$ref": "#/definitions/SettingConfig",
+ "definitions": {
+ "SettingConfig": {
+ "type": "object",
+ "properties": {
+ "localmode": {
+ "type": "boolean",
+ "description": "if true, server will bind on '127.0.0.1' rather than '0.0.0.0'"
+ },
+ "guest": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Permission"
+ },
+ "description": "guest permission"
+ },
+ "jwt_secretkey": {
+ "type": "string",
+ "description": "JWT secret key. if you change its value, all access tokens are invalidated."
+ },
+ "port": {
+ "type": "number",
+ "description": "the port which running server is binding on."
+ },
+ "mode": {
+ "type": "string",
+ "enum": [
+ "development",
+ "production"
+ ]
+ },
+ "cli": {
+ "type": "boolean",
+ "description": "if true, do not show 'electron' window and show terminal only."
+ },
+ "forbid_remote_admin_login": {
+ "type": "boolean",
+ "description": "forbid to login admin from remote client. but, it do not invalidate access token. \r if you want to invalidate access token, change 'jwt_secretkey'."
+ },
+ "$schema": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "localmode",
+ "guest",
+ "jwt_secretkey",
+ "port",
+ "mode",
+ "cli",
+ "forbid_remote_admin_login"
+ ],
+ "additionalProperties": false
+ },
+ "Permission": {
+ "type": "string",
+ "enum": [
+ "ModifyTag",
+ "QueryContent",
+ "ModifyTagDesc"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/setting.ts b/src/SettingConfig.ts
similarity index 85%
rename from src/setting.ts
rename to src/SettingConfig.ts
index 6378071..944f911 100644
--- a/src/setting.ts
+++ b/src/SettingConfig.ts
@@ -1,9 +1,8 @@
-import { Settings } from '@material-ui/icons';
import { randomBytes } from 'crypto';
import { existsSync, readFileSync, writeFileSync } from 'fs';
import { Permission } from './permission/permission';
-export type Setting = {
+export interface SettingConfig {
/**
* if true, server will bind on '127.0.0.1' rather than '0.0.0.0'
*/
@@ -31,7 +30,7 @@ export type Setting = {
* if you want to invalidate access token, change 'jwt_secretkey'.*/
forbid_remote_admin_login:boolean,
}
-const default_setting:Setting = {
+const default_setting:SettingConfig = {
localmode: true,
guest:[],
@@ -41,15 +40,15 @@ const default_setting:Setting = {
cli:false,
forbid_remote_admin_login:true,
}
-let setting: null|Setting = null;
+let setting: null|SettingConfig = null;
-const setEmptyToDefault = (target:any,default_table:Setting)=>{
+const setEmptyToDefault = (target:any,default_table:SettingConfig)=>{
let diff_occur = false;
for(const key in default_table){
if(key === undefined || key in target){
continue;
}
- target[key] = default_table[key as keyof Setting];
+ target[key] = default_table[key as keyof SettingConfig];
diff_occur = true;
}
return diff_occur;
@@ -61,9 +60,9 @@ export const read_setting_from_file = ()=>{
if(partial_occur){
writeFileSync("settings.json",JSON.stringify(ret));
}
- return ret as Setting;
+ return ret as SettingConfig;
}
-export function get_setting():Setting{
+export function get_setting():SettingConfig{
if(setting === null){
setting = read_setting_from_file();
const env = process.env.NODE_ENV || 'development';
diff --git a/src/client/accessor/document.ts b/src/client/accessor/document.ts
index 98d442f..36d25fa 100644
--- a/src/client/accessor/document.ts
+++ b/src/client/accessor/document.ts
@@ -44,6 +44,7 @@ export class ClientDocumentAccessor implements DocumentAccessor{
return ret;
}
async add(c: DocumentBody): Promise{
+ throw new Error("not allow");
const res = await fetch(`${baseurl}`,{
method: "POST",
body: JSON.stringify(c)
diff --git a/src/client/page/difference.tsx b/src/client/page/difference.tsx
index ca7ffed..8257eac 100644
--- a/src/client/page/difference.tsx
+++ b/src/client/page/difference.tsx
@@ -1,11 +1,51 @@
-import React from 'react';
+import React, { useContext, useEffect, useState } from 'react';
import { CommonMenuList, Headline } from "../component/mod";
import { UserContext } from "../state";
-import { Grid, Typography } from "@material-ui/core";
+import { Grid, Paper, Typography } from "@material-ui/core";
export function DifferencePage(){
+ const ctx = useContext(UserContext);
+ const [diffList,setDiffList] = useState<
+ {type:string,value:{path:string,type:string}[]}[]
+ >([]);
+ const doLoad = async ()=>{
+ const list = await fetch('/api/diff/list');
+ if(list.ok){
+ const inner = await list.json();
+ setDiffList(inner);
+ }
+ else{
+ //setDiffList([]);
+ }
+ };
+ useEffect(
+ ()=>{
+ doLoad();
+ const i = setInterval(doLoad,5000);
+ return ()=>{
+ clearInterval(i);
+ }
+ },[]
+ )
+ const Commit = async(x:{type:string,path:string})=>{
+ const res = await fetch('/api/diff/commit',{
+ method:'POST',
+ body: JSON.stringify([{...x}]),
+ headers:{
+ 'content-type':'application/json'
+ }
+ });
+ const bb = await res.json();
+ if(bb.ok){
+ doLoad();
+ }
+ }
const menu = CommonMenuList();
+
return (
- Not implemented
+ {diffList.map(x=>
+ {x.type}
+ {x.value.map(y=>Commit(y)}>{y.path})}
+ )}
)
}
\ No newline at end of file
diff --git a/src/content/file.ts b/src/content/file.ts
index 894cbce..8339c59 100644
--- a/src/content/file.ts
+++ b/src/content/file.ts
@@ -3,37 +3,65 @@ import Router from 'koa-router';
import {createHash} from 'crypto';
import {promises} from 'fs'
import {extname} from 'path';
+import { DocumentBody } from '../model/mod';
+import path from 'path';
/**
* content file or directory referrer
*/
export interface ContentFile{
getHash():Promise;
- getDesc():Promise