wip fix idx-map

This commit is contained in:
Riz 2023-12-07 04:33:17 +07:00
parent 390a832d76
commit 9ac3990511
12 changed files with 254 additions and 166 deletions

View File

@ -184,6 +184,7 @@ const scanMeta = async (doc: DPage, sync: SyncConnection) => {
await Promise.all( await Promise.all(
childs.map((m) => serverWalkLoad(m, scope_comps, sync, loaded)) childs.map((m) => serverWalkLoad(m, scope_comps, sync, loaded))
); );
childs.map((m, i) => { childs.map((m, i) => {
serverWalkMap( serverWalkMap(
{ sync, scope, scope_comps, note: "page-load" }, { sync, scope, scope_comps, note: "page-load" },

View File

@ -29,7 +29,8 @@ export const loadComponent = async (id: string, sync: SyncConnection) => {
const sv_local = await gzipAsync(update); const sv_local = await gzipAsync(update);
user.active.findAll({ comp_id: id }).map((e) => { const all = user.active.findAll({ comp_id: id });
all.map((e) => {
if (origin !== um) { if (origin !== um) {
if (e.client_id === origin) return; if (e.client_id === origin) return;
} }

View File

@ -15,7 +15,11 @@ import { SyncConnection } from "../type";
import { loadComponent } from "./load-component"; import { loadComponent } from "./load-component";
import { extractMItemProps } from "./load-page-comp"; import { extractMItemProps } from "./load-page-comp";
import { ArgParentMComp, parseJs } from "./parser/parse-js"; import { ArgParentMComp, parseJs } from "./parser/parse-js";
import { user } from "../entity/user";
const defaultActive = {
select: "" as "" | "comp" | "item" | "section" | "text",
};
export const serverWalkLoad = async ( export const serverWalkLoad = async (
mitem: MItem, mitem: MItem,
scope_comps: IScopeComp, scope_comps: IScopeComp,
@ -35,6 +39,18 @@ export const serverWalkLoad = async (
loaded.add(id); loaded.add(id);
if (!docs.comp[id]) { if (!docs.comp[id]) {
await loadComponent(id, sync); await loadComponent(id, sync);
} else {
const conf = sync.conf;
if (conf) {
user.active.add({
...defaultActive,
client_id: sync.client_id,
user_id: sync.user_id,
site_id: conf.site_id,
page_id: conf.page_id,
comp_id: comp.id,
});
}
} }
const pcomp = docs.comp[id]; const pcomp = docs.comp[id];

View File

@ -5,7 +5,6 @@ import { EdAddText } from "./panel/header/mid/add-text";
import { EdCompPicker } from "./panel/header/mid/comp-picker"; import { EdCompPicker } from "./panel/header/mid/comp-picker";
import { EdPagePicker } from "./panel/header/mid/page-picker"; import { EdPagePicker } from "./panel/header/mid/page-picker";
import { TopBtn } from "./panel/header/top-btn"; import { TopBtn } from "./panel/header/top-btn";
import { EdMain } from "./panel/main/main";
export const EdMid: FC<{}> = () => { export const EdMid: FC<{}> = () => {
return ( return (
@ -15,12 +14,12 @@ export const EdMid: FC<{}> = () => {
"h-[35px] border-b flex p-1 items-stretch text-[12px] justify-between" "h-[35px] border-b flex p-1 items-stretch text-[12px] justify-between"
)} )}
> >
<div className="flex items-stretch flex-1 "> <div className="flex items-stretch flex-1">
<EdPagePicker /> <EdPagePicker />
</div> </div>
<div className="flex items-stretch flex-1 justify-center "> <div className="flex items-stretch flex-1 justify-center">
<div className="flex items-stretch "> <div className="flex items-stretch">
<div className="border-r border-r-slate-100 text-slate-400 text-[9px] flex items-center px-1 mr-1"> <div className="border-r border-r-slate-100 text-slate-400 text-[9px] flex items-center px-1 mr-1">
ADD ADD
</div> </div>

View File

@ -43,23 +43,37 @@ export const EdMain = () => {
p.page.render = render; p.page.render = render;
}} }}
hidden={(meta) => { hidden={(meta) => {
if (meta.item.hidden) return true if (meta.item.hidden) return true;
return false; return false;
}} }}
hover={{ hover={{
get(meta) { get(meta) {
const item = meta.item; const item = meta.item;
if (item.originalId === active.hover_id || item.id === active.hover_id) if (active.comp_id) {
if (meta.parent_mcomp) {
if (
meta.parent_mcomp?.mcomp.get("component")?.get("id") !==
active.comp_id
)
return false;
}
}
if (
item.originalId === active.hover_id ||
item.id === active.hover_id
)
return true; return true;
return false return false;
}, },
set(meta) { set(meta) {
if (meta.parent_mcomp) { if (meta.parent_mcomp) {
const id = meta.parent_mcomp.mitem.get('id'); const id = meta.parent_mcomp.mitem.get("id");
if (active.instance.item_id !== id) { if (active.instance.item_id !== id) {
const original_id = meta.parent_mcomp.mitem.get('originalId'); const original_id =
meta.parent_mcomp.mitem.get("originalId");
if (active.comp_id && original_id) { if (active.comp_id && original_id) {
active.hover_id = original_id; active.hover_id = original_id;
@ -79,14 +93,14 @@ export const EdMain = () => {
const parent = meta.parent_mcomp; const parent = meta.parent_mcomp;
if (parent) { if (parent) {
const mcomp = parent.mcomp; const mcomp = parent.mcomp;
if (mcomp.get('component')?.get('id') === active.comp_id) { if (mcomp.get("component")?.get("id") === active.comp_id) {
active.hover_id = meta.item.originalId || meta.item.id; active.hover_id = meta.item.originalId || meta.item.id;
} }
} else { } else {
active.hover_id = meta.item.id; active.hover_id = meta.item.id;
} }
} else { } else {
active.hover_id = meta.item.id active.hover_id = meta.item.id;
} }
p.render(); p.render();
@ -97,18 +111,32 @@ export const EdMain = () => {
get(meta) { get(meta) {
const item = meta.item; const item = meta.item;
if (item.originalId === active.item_id || item.id === active.item_id) if (active.comp_id) {
if (meta.parent_mcomp) {
if (
meta.parent_mcomp?.mcomp.get("component")?.get("id") !==
active.comp_id
)
return false;
}
}
if (
item.originalId === active.item_id ||
item.id === active.item_id
)
return true; return true;
return false return false;
}, },
set(meta) { set(meta) {
if (meta.parent_mcomp) { if (meta.parent_mcomp) {
const id = meta.parent_mcomp.mitem.get('id'); const id = meta.parent_mcomp.mitem.get("id");
if (active.instance.item_id !== id) { if (active.instance.item_id !== id) {
const original_id = meta.parent_mcomp.mitem.get('originalId'); const original_id =
meta.parent_mcomp.mitem.get("originalId");
let active_id = "" let active_id = "";
if (active.comp_id && original_id) { if (active.comp_id && original_id) {
active_id = original_id; active_id = original_id;
} else if (id) { } else if (id) {
@ -119,7 +147,9 @@ export const EdMain = () => {
if (active.item_id !== active_id) { if (active.item_id !== active_id) {
active.item_id = active_id; active.item_id = active_id;
} else { } else {
const comp_id = meta.parent_mcomp.mcomp.get('component')?.get('id'); const comp_id = meta.parent_mcomp.mcomp
.get("component")
?.get("id");
if (comp_id) { if (comp_id) {
active.instance.item_id = active_id; active.instance.item_id = active_id;
active.instance.comp_id = active.comp_id; active.instance.comp_id = active.comp_id;
@ -147,7 +177,7 @@ export const EdMain = () => {
const parent = meta.parent_mcomp; const parent = meta.parent_mcomp;
if (parent) { if (parent) {
const mcomp = parent.mcomp; const mcomp = parent.mcomp;
if (mcomp.get('component')?.get('id') === active.comp_id) { if (mcomp.get("component")?.get("id") === active.comp_id) {
active.item_id = meta.item.originalId || meta.item.id; active.item_id = meta.item.originalId || meta.item.id;
} }
} else { } else {
@ -157,13 +187,12 @@ export const EdMain = () => {
active.instance.comp_id = ""; active.instance.comp_id = "";
} }
} else { } else {
active.item_id = meta.item.id active.item_id = meta.item.id;
} }
p.render(); p.render();
p.page.render(); p.page.render();
focus(); focus();
}, },
text(meta) { text(meta) {
const { item } = meta; const { item } = meta;
@ -172,33 +201,40 @@ export const EdMain = () => {
active.text.content = item.html || ""; active.text.content = item.html || "";
} }
return <div return (
className={cx(`v-text-${item.id} v-text-${item.originalId} outline-none`)} <div
ref={(ref) => { className={cx(
if (ref !== document.activeElement && ref) { `v-text-${item.id} v-text-${item.originalId} outline-none`
const renaming = document.querySelector('.rename-item'); )}
const modals = document.querySelectorAll('[data-floating-ui-portal]'); ref={(ref) => {
if (modals.length === 0 && !renaming) { if (ref !== document.activeElement && ref) {
ref.focus(); const renaming = document.querySelector(".rename-item");
setEndOfContenteditable(ref) const modals = document.querySelectorAll(
"[data-floating-ui-portal]"
);
if (modals.length === 0 && !renaming) {
ref.focus();
setEndOfContenteditable(ref);
}
} }
} }}
}} contentEditable
contentEditable spellCheck={false}
spellCheck={false} onInput={(e) => {
onInput={(e) => { const val = e.currentTarget.innerHTML;
const val = e.currentTarget.innerHTML; active.text.id = item.id;
active.text.id = item.id; active.text.content = val;
active.text.content = val; }}
}} onBlur={() => {
onBlur={() => { const meta = getMetaById(p, item.id);
const meta = getMetaById(p, item.id); if (meta && meta.mitem && active.text.id === item.id) {
if (meta && meta.mitem && active.text.id === item.id) { meta.mitem.set("html", active.text.content);
meta.mitem.set('html', active.text.content) }
} }}
}} dangerouslySetInnerHTML={{ __html: item.html || "" }}
dangerouslySetInnerHTML={{ __html: item.html || "" }}></div> ></div>
} );
},
}} }}
/> />
)} )}
@ -209,12 +245,12 @@ export const EdMain = () => {
function setEndOfContenteditable(div: any) { function setEndOfContenteditable(div: any) {
let range: any, sel: any; let range: any, sel: any;
if (document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+ if (document.createRange) {
{ //Firefox, Chrome, Opera, Safari, IE 9+
range = document.createRange(); range = document.createRange();
range.selectNodeContents(div); range.selectNodeContents(div);
sel = window.getSelection(); sel = window.getSelection();
sel.removeAllRanges(); sel.removeAllRanges();
sel.addRange(range); sel.addRange(range);
} }
} }

View File

@ -7,7 +7,7 @@ import { useGlobal, useLocal } from "web-utils";
import { jscript } from "../../../../../utils/script/jscript"; import { jscript } from "../../../../../utils/script/jscript";
import { jsMount } from "../../../../../utils/script/mount"; import { jsMount } from "../../../../../utils/script/mount";
import { monacoTypings } from "../../../../../utils/script/typings"; import { monacoTypings } from "../../../../../utils/script/typings";
import { EDGlobal, active } from "../../../logic/ed-global"; import { EDGlobal, EdMeta, active } from "../../../logic/ed-global";
import { getMetaById } from "../../../logic/tree/build"; import { getMetaById } from "../../../logic/tree/build";
import { declareScope } from "./scope"; import { declareScope } from "./scope";
@ -30,9 +30,11 @@ export const ScriptMonaco = () => {
const Editor = jscript.editor; const Editor = jscript.editor;
if (!Editor) return null; if (!Editor) return null;
let meta = p.page.meta[active.item_id]; let meta: EdMeta | null = p.page.meta[active.item_id];
if (active.comp_id && p.comp.list[active.comp_id]) { if (active.comp_id) {
meta = p.comp.list[active.comp_id].meta[active.item_id]; if (p.comp.list[active.comp_id]) {
meta = p.comp.list[active.comp_id].meta[active.item_id];
} else meta = null;
} }
let val = ""; let val = "";
@ -164,6 +166,8 @@ async () => {
} }
} }
if (!meta) return null;
return ( return (
<Editor <Editor
value={val} value={val}

View File

@ -5,7 +5,7 @@ import {
PlaceholderRender, PlaceholderRender,
TreeMethods, TreeMethods,
} from "@minoru/react-dnd-treeview"; } from "@minoru/react-dnd-treeview";
import { FC, useEffect } from "react"; import { FC } from "react";
import { useGlobal, useLocal } from "web-utils"; import { useGlobal, useLocal } from "web-utils";
import { EDGlobal, EdMeta, active } from "../../logic/ed-global"; import { EDGlobal, EdMeta, active } from "../../logic/ed-global";
import { DEPTH_WIDTH } from "./node/item/indent"; import { DEPTH_WIDTH } from "./node/item/indent";
@ -13,7 +13,6 @@ import { expandTreeHook } from "./node/item/indent-hook";
import { canDrop, nodeOnDrop } from "./node/on-drop"; import { canDrop, nodeOnDrop } from "./node/on-drop";
import { nodeRender } from "./node/render"; import { nodeRender } from "./node/render";
import { doTreeSearch } from "./search"; import { doTreeSearch } from "./search";
import { getMetaById } from "../../logic/tree/build";
export const EdTreeBody = () => { export const EdTreeBody = () => {
const p = useGlobal(EDGlobal, "EDITOR"); const p = useGlobal(EDGlobal, "EDITOR");

View File

@ -1,7 +1,7 @@
import { NodeModel } from "@minoru/react-dnd-treeview"; import { NodeModel } from "@minoru/react-dnd-treeview";
import { useEffect } from "react"; import { useEffect } from "react";
import { useGlobal, useLocal } from "web-utils"; import { useGlobal, useLocal } from "web-utils";
import { EDGlobal, EdMeta, PG } from "../../logic/ed-global"; import { EDGlobal, EdMeta, PG, active } from "../../logic/ed-global";
import { fuzzy } from "../../../../utils/ui/fuzzy"; import { fuzzy } from "../../../../utils/ui/fuzzy";
export const EdTreeSearch = () => { export const EdTreeSearch = () => {
@ -115,7 +115,13 @@ export const doTreeSearch = (p: PG) => {
const search = p.ui.tree.search.toLowerCase(); const search = p.ui.tree.search.toLowerCase();
let i = 0; let i = 0;
for (const row of p.page.tree) {
let ptree = p.page.tree;
if (active.comp_id && p.comp.list[active.comp_id].tree) {
ptree = p.comp.list[active.comp_id].tree;
}
for (const row of ptree) {
const item = row.data?.item; const item = row.data?.item;
if (item) { if (item) {
const js = item.adv?.js; const js = item.adv?.js;

View File

@ -136,7 +136,6 @@ export const ViewMetaScript: FC<{
} }
const output = { jsx: null as any }; const output = { jsx: null as any };
args = { args = {
...w.exports, ...w.exports,
...finalScope, ...finalScope,

View File

@ -22,93 +22,90 @@ export const compPropVal = (
props = icomp.props; props = icomp.props;
cprops = Object.entries({ ...icomp.props }); cprops = Object.entries({ ...icomp.props });
if (v.script.api_url) { if (!v.script.db) v.script.db = createDB(v.script.api_url);
if (!v.script.db) v.script.db = createDB(v.script.api_url); if (!v.script.api) v.script.api = createAPI(v.script.api_url);
if (!v.script.api) v.script.api = createAPI(v.script.api_url);
const w = window as any; const w = window as any;
const finalScope = mergeScopeUpwards(v, item.id, scopeIndex); const finalScope = mergeScopeUpwards(v, item.id, scopeIndex);
const args = { const args = {
...w.exports, ...w.exports,
...finalScope, ...finalScope,
db: v.script.db, db: v.script.db,
api: v.script.api, api: v.script.api,
}; };
const result: any = {}; const result: any = {};
for (const [name, _prop] of cprops) { for (const [name, _prop] of cprops) {
const prop = props[name] || _prop; const prop = props[name] || _prop;
let value: any = null; let value: any = null;
if (prop.valueBuilt) { if (prop.valueBuilt) {
const fn = new Function( const fn = new Function(
...Object.keys(args), ...Object.keys(args),
`return ${prop.valueBuilt}` `return ${prop.valueBuilt}`
);
try {
value = fn(...Object.values(args)) || null;
const navs = extractNavigate(prop.valueBuilt || "");
if (navs.length > 0) {
navs.map((nav) => preload(v, nav));
}
} catch (e) {
const cname = meta.item.name;
console.warn(e);
console.warn(
`ERROR in Component [${cname}], in prop [${name}]:\n ` +
prop.value
); );
try {
value = fn(...Object.values(args)) || null;
const navs = extractNavigate(prop.valueBuilt || "");
if (navs.length > 0) {
navs.map((nav) => preload(v, nav));
}
} catch (e) {
const cname = meta.item.name;
console.warn(e);
console.warn(
`ERROR in Component [${cname}], in prop [${name}]:\n ` +
prop.value
);
}
} }
if (prop.meta?.type === "content-element") {
if (!(typeof value === "object" && !!value && value._jsx)) {
const id = `${meta.item.id}-${name}`;
if (!jsxProps[id]) {
jsxProps[id] = {
_jsx: true,
Comp: ({
parent_id,
scopeIndex,
}: {
parent_id: string;
scopeIndex?: Record<string, any>;
}) => {
if (prop.content) {
const meta = v.meta[prop.content.id] as EdMeta;
let parent = v.meta[parent_id];
if (meta && parent) {
if (v.scope) {
while (parent) {
if (v.scope[parent.item.id]) {
v.scope[prop.content.id] =
v.scope[parent.item.id];
}
parent = v.meta[parent.parent_item.id];
}
}
return (
<ViewMeta
id={prop.content.id}
scopeIndex={scopeIndex}
/>
);
}
}
return <></>;
},
};
}
value = jsxProps[id];
}
}
result[name] = value;
} }
if (prop.meta?.type === "content-element") {
if (!(typeof value === "object" && !!value && value._jsx)) {
const id = `${meta.item.id}-${name}`;
if (!jsxProps[id]) {
jsxProps[id] = {
_jsx: true,
Comp: ({
parent_id,
scopeIndex,
}: {
parent_id: string;
scopeIndex?: Record<string, any>;
}) => {
if (prop.content) {
const meta = v.meta[prop.content.id] as EdMeta;
let parent = v.meta[parent_id];
if (meta && parent) {
if (v.scope) {
while (parent) {
if (v.scope[parent.item.id]) {
v.scope[prop.content.id] = v.scope[parent.item.id];
}
parent = v.meta[parent.parent_item.id];
}
}
return (
<ViewMeta
id={prop.content.id}
scopeIndex={scopeIndex}
/>
);
}
}
return <></>;
},
};
}
value = jsxProps[id];
}
}
result[name] = value;
meta.propval = result; meta.propval = result;
} }
} }

View File

@ -21,7 +21,7 @@ export const createAPI = (url: string) => {
w.prasiApi = {}; w.prasiApi = {};
} }
if (!url) { if (!url) {
throw new Error("No URL provided"); return null;
} }
return w.apiClient(w.prasiApi[url]?.apiEntry, url); return w.apiClient(w.prasiApi[url]?.apiEntry, url);

View File

@ -1,38 +1,68 @@
import hash_sum from "hash-sum";
const match = (item: any, where: any) => {
for (const [k, v] of Object.entries(where)) {
if (item[k] !== v) return false;
}
return true;
};
export const IndexedMap = { export const IndexedMap = {
create: <OBJ extends Record<string, any>, KEY extends string>(id: KEY) => { create: <OBJ extends Record<string, any>, KEY extends string>(id: KEY) => {
const all = {} as Record<string, OBJ & Record<KEY, string>>; const all = {} as Record<KEY, Record<string, OBJ>>;
return { return {
add(item: OBJ & Record<KEY, string>) { add(item: OBJ & Record<KEY, any>) {
const _id = item[id]; const pk = item[id] as KEY;
all[_id] = item as any;
return _id; if (!all[pk]) {
all[pk] = {};
}
const _id = hash_sum(item) as any;
const items = all[pk] as Record<string, OBJ>;
items[_id] = item;
return pk;
}, },
find(id: string) { findAll(where: Partial<OBJ & Record<KEY, string>>, withId?: boolean) {
return all[id]; const founds = [];
}, if (where[id]) {
del(id: string) { const _id = where[id] as KEY;
delete all[id];
}, if (all[_id]) {
findAll(where: Partial<OBJ & Record<KEY, string>>) { for (const [k, item] of Object.entries(all[_id])) {
return Object.entries(all) if (match(item, where)) {
.filter(([k, item]) => { if (withId) {
for (const f in where) { founds.push({ ...item, _id: k });
if (f === id) { } else {
if (k !== where[f]) { founds.push(item);
return false;
} }
} else if (item[f] !== where[f]) {
return false;
} }
} }
return true; }
}) } else {
.map(([_, item]) => item); for (const _items of Object.values(all)) {
const items = _items as Record<string, OBJ>;
for (const [k, item] of Object.entries(items)) {
if (match(item, where)) {
if (withId) {
founds.push({ ...item, _id: k });
} else {
founds.push(item);
}
}
}
}
}
return founds;
}, },
delAll(where: Partial<OBJ & Record<KEY, string>>) { delAll(where: Partial<OBJ & Record<KEY, string>>) {
for (const item of this.findAll(where)) { for (const item of this.findAll(where, true)) {
delete all[item[id]]; delete all[item[id]][item._id];
} }
}, },
}; };