Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Admin to svelte #429

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions projects/remult-admin/index.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
<!doctype html>
<html lang="en" style="font-family: sans-serif">
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/ico" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Admin</title>
<title>remult-admin</title>
</head>
<body>
<!--PLACE_HERE-->
<div
id="root"
style="display: flex; flex-direction: column; height: 100%"
></div>
<script type="module" src="/src/main.tsx"></script>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
6,154 changes: 1,929 additions & 4,225 deletions projects/remult-admin/package-lock.json

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions projects/remult-admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "remult-admin",
"version": "0.0.11",
"license": "MIT",
"type": "module",
"contributors": [
{
"name": "Noam Honig",
Expand All @@ -16,6 +17,8 @@
"preview": "vite preview"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^3.1.0",
"@tsconfig/svelte": "^5.0.2",
"@types/express": "^4.17.17",
"@types/node": "^20.11.6",
"@types/react": "^18.0.27",
Expand All @@ -25,15 +28,18 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.21.1",
"svelte": "5.0.0-next.120",
"svelte-check": "^3.7.0",
"svelte-spa-router": "^4.0.1",
"tsx": "^3.12.3",
"typescript": "^5.3.3",
"vanilla-jsoneditor": "^0.21.2",
"vite": "^5.0.12",
"vite-plugin-singlefile": "^0.13.5",
"vite3-plugin-express": "^0.1.3"
"vite": "^5.2.8",
"vite-plugin-singlefile": "2.0.1"
},
"dependencies": {
"@paralleldrive/cuid2": "^2.2.1",
"@xyflow/svelte": "0.0.41",
"reactflow": "^11.10.2",
"reflect-metadata": "^0.1.13",
"tslib": "^2.3.1",
Expand Down
Binary file added projects/remult-admin/public/favicon.ico
Binary file not shown.
1 change: 0 additions & 1 deletion projects/remult-admin/public/vite.svg

This file was deleted.

54 changes: 54 additions & 0 deletions projects/remult-admin/src/App.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<script lang="ts">
import Router from 'svelte-spa-router'
import Schema from './routes/Schema.svelte'
import NotFound from './routes/NotFound.svelte'
import Entity from './routes/Entity.svelte'
import { onMount } from 'svelte'
import { God } from './God.svelte'
import active from 'svelte-spa-router/active'
import { god } from './global.svelte'

// export let params: { wild?: string } = {}

onMount(async () => {
await god.init()
})

const routes = {
'/': Schema,
'/entity/*': Entity,
// This is optional, but if present it must be the last
'*': NotFound,
}
</script>

<a
href="#/"
use:active={{
path: `/`,
className: 'active',
}}>Schema</a
>
{#each god?.tables ?? [] as t}
<div>
<a
href="#/entity/{t.key}"
use:active={{
path: `/entity/${t.key}`,
className: 'active',
}}
>
{t.caption}
</a>
</div>
{/each}

<Router {routes} />

<style>
/* Style for "active" links; need to mark this :global because the router adds the class directly */
:global(a.active) {
color: blue;
font-weight: bold;
}
</style>
2 changes: 1 addition & 1 deletion projects/remult-admin/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
Navigate,
NavLink,
} from 'react-router-dom'
import { God } from './God'
import { God } from './God.svelte'
import { Erd } from './components/erd/erd'

declare const entities: EntityUIInfo[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,63 @@ import { Repository } from '../../core/src/remult3/remult3'
import { Fields } from '../../core/src/remult3/Fields'
import { Entity } from '../../core/src/remult3/entity'

declare const entities: EntityUIInfo[]

export class God {
tables: (EntityUIInfo & { repo: Repository<unknown> })[] = $state()

constructor() {
this.tables = []

// RUNE We can't await in the constructor... What is a good pattern to use here?
// this.init()
}

async init() {
let myEntities: EntityUIInfo[] = []

if (import.meta.env.DEV) {
const res = await fetch('/api/dev-admin')
const json = await res.json()
myEntities = json
// .then((res) => res.json())
// .then((json) => {
// myEntities = json
// })
} else {
myEntities = entities
}

this.tables = myEntities.map((info) => {
class C {}
for (const f of info.fields) {
switch (f.type) {
case 'json':
Fields.json()(C.prototype, f.key as keyof typeof C.prototype)
break
case 'number':
Fields.number()(C.prototype, f.key)
break
case 'boolean':
Fields.boolean()(C.prototype, f.key)
break
default:
Fields.string()(C.prototype, f.key)
break
}
}
Entity(info.key, {
allowApiCrud: true,
caption: info.caption,
id: info.ids,
})(C)
return {
...info,
repo: remult.repo(C),
}
})
}

async getItemsForSelect(
relation: FieldRelationToOneInfo,
search: string | undefined,
Expand Down Expand Up @@ -41,35 +97,4 @@ export class God {
if (!item) return 'not found - ' + value
return item[relations.captionField]
}
tables: (EntityUIInfo & { repo: Repository<any> })[]
constructor(myEntities: EntityUIInfo[]) {
this.tables = myEntities.map((info) => {
class C {}
for (const f of info.fields) {
switch (f.type) {
case 'json':
Fields.json()(C.prototype, f.key as keyof typeof C.prototype)
break
case 'number':
Fields.number()(C.prototype, f.key)
break
case 'boolean':
Fields.boolean()(C.prototype, f.key)
break
default:
Fields.string()(C.prototype, f.key)
break
}
}
Entity(info.key, {
allowApiCrud: true,
caption: info.caption,
id: info.ids,
})(C)
return {
...info,
repo: remult.repo(C),
}
})
}
}
Empty file.
1 change: 0 additions & 1 deletion projects/remult-admin/src/assets/react.svg

This file was deleted.

9 changes: 9 additions & 0 deletions projects/remult-admin/src/components/EditableField.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script lang="ts">
let { value = $bindable(), ...props } = $props()

// export let value: any
// export let info: FieldUIInfo
</script>

<input bind:value {...props} />
<!-- on:Change -->
3 changes: 1 addition & 2 deletions projects/remult-admin/src/components/EditableField.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FieldUIInfo } from '../../../core/server/remult-admin'
import { God } from '../God'
import { God } from '../God.svelte'
import { RelationField } from './RelationField'
import {
Content,
Expand Down Expand Up @@ -27,7 +27,6 @@ export function EditableField({
if (info.type == 'json') {
return <EditableJson {...{ value, onChange, info, god }} />
} else {

return (
<>
<input value={value} onChange={(e) => onChange(e.target.value)} />
Expand Down
Loading