kempo 4.2.5 → 4.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +7 -0
- package/dist/admin/components/AddGroupControl.js +1 -1
- package/dist/admin/components/AddGroupControl.js.map +1 -1
- package/dist/admin/components/ClearExpiredSessionsControl.js +1 -1
- package/dist/admin/components/ClearExpiredSessionsControl.js.map +1 -1
- package/dist/admin/components/FragmentEditor.js +1 -1
- package/dist/admin/components/FragmentEditor.js.map +1 -1
- package/dist/admin/components/GlobalContentEditor.js +1 -1
- package/dist/admin/components/GlobalContentEditor.js.map +1 -1
- package/dist/admin/components/GroupDeleteSelected.js +1 -1
- package/dist/admin/components/GroupDeleteSelected.js.map +1 -1
- package/dist/admin/components/GroupRemoveRecord.js +1 -1
- package/dist/admin/components/GroupRemoveRecord.js.map +1 -1
- package/dist/admin/components/Monaco.js +1 -1
- package/dist/admin/components/Monaco.js.map +1 -1
- package/dist/admin/components/PageEditor.js +1 -1
- package/dist/admin/components/PageEditor.js.map +1 -1
- package/dist/admin/components/TableRowDelete.js +1 -1
- package/dist/admin/components/TableRowDelete.js.map +1 -1
- package/dist/admin/components/TableRowLink.js +1 -1
- package/dist/admin/components/TableRowLink.js.map +1 -1
- package/dist/admin/components/TemplateEditor.js +1 -1
- package/dist/admin/components/TemplateEditor.js.map +1 -1
- package/dist/admin/components/ValueEditor.js +1 -1
- package/dist/admin/components/ValueEditor.js.map +1 -1
- package/dist/admin/components/tableControls/AddMember.js +1 -1
- package/dist/admin/components/tableControls/AddMember.js.map +1 -1
- package/dist/admin/components/tableControls/AddPermission.js +1 -1
- package/dist/admin/components/tableControls/AddPermission.js.map +1 -1
- package/dist/admin/components/tableControls/InstallExtension.js +1 -1
- package/dist/admin/components/tableControls/InstallExtension.js.map +1 -1
- package/dist/admin/components/tableControls/UninstallExtension.js +1 -1
- package/dist/admin/components/tableControls/UninstallExtension.js.map +1 -1
- package/dist/admin/init.js +1 -1
- package/dist/admin/init.js.map +1 -1
- package/dist/kempo/api/admin-globals/DELETE.js +1 -1
- package/dist/kempo/api/admin-globals/DELETE.js.map +1 -1
- package/dist/kempo/api/admin-globals/GET.js +1 -1
- package/dist/kempo/api/admin-globals/GET.js.map +1 -1
- package/dist/kempo/api/admin-globals/POST.js +1 -1
- package/dist/kempo/api/admin-globals/POST.js.map +1 -1
- package/dist/kempo/api/admin-globals/[id]/GET.js +1 -1
- package/dist/kempo/api/admin-globals/[id]/GET.js.map +1 -1
- package/dist/kempo/api/admin-globals/[id]/PUT.js +1 -1
- package/dist/kempo/api/admin-globals/[id]/PUT.js.map +1 -1
- package/dist/kempo/api/admin-globals/[id]/disable/PUT.js +1 -1
- package/dist/kempo/api/admin-globals/[id]/disable/PUT.js.map +1 -1
- package/dist/kempo/api/admin-globals/[id]/enable/PUT.js +1 -1
- package/dist/kempo/api/admin-globals/[id]/enable/PUT.js.map +1 -1
- package/dist/kempo/api/auth/change-password/POST.js +1 -1
- package/dist/kempo/api/auth/change-password/POST.js.map +1 -1
- package/dist/kempo/api/auth/login/email/POST.js +1 -1
- package/dist/kempo/api/auth/login/email/POST.js.map +1 -1
- package/dist/kempo/api/auth/logout/POST.js +1 -1
- package/dist/kempo/api/auth/logout/POST.js.map +1 -1
- package/dist/kempo/api/auth/register/email/POST.js +1 -1
- package/dist/kempo/api/auth/register/email/POST.js.map +1 -1
- package/dist/kempo/api/auth/reset-password/POST.js +1 -1
- package/dist/kempo/api/auth/reset-password/POST.js.map +1 -1
- package/dist/kempo/api/auth/session/GET.js +1 -1
- package/dist/kempo/api/auth/session/GET.js.map +1 -1
- package/dist/kempo/api/auth/verify-email/POST.js +1 -1
- package/dist/kempo/api/auth/verify-email/POST.js.map +1 -1
- package/dist/kempo/api/extensions/DELETE.js +1 -1
- package/dist/kempo/api/extensions/DELETE.js.map +1 -1
- package/dist/kempo/api/extensions/GET.js +1 -1
- package/dist/kempo/api/extensions/GET.js.map +1 -1
- package/dist/kempo/api/extensions/POST.js +1 -1
- package/dist/kempo/api/extensions/POST.js.map +1 -1
- package/dist/kempo/api/extensions/[name]/disable/POST.js +1 -1
- package/dist/kempo/api/extensions/[name]/disable/POST.js.map +1 -1
- package/dist/kempo/api/extensions/[name]/enable/POST.js +1 -1
- package/dist/kempo/api/extensions/[name]/enable/POST.js.map +1 -1
- package/dist/kempo/api/extensions/[name]/update/POST.js +1 -1
- package/dist/kempo/api/extensions/[name]/update/POST.js.map +1 -1
- package/dist/kempo/api/extensions/[name]/update-check/GET.js +1 -1
- package/dist/kempo/api/extensions/[name]/update-check/GET.js.map +1 -1
- package/dist/kempo/api/extensions/available/GET.js +1 -1
- package/dist/kempo/api/extensions/available/GET.js.map +1 -1
- package/dist/kempo/api/extensions/known/GET.js +1 -1
- package/dist/kempo/api/extensions/known/GET.js.map +1 -1
- package/dist/kempo/api/forgot-password/POST.js +1 -1
- package/dist/kempo/api/forgot-password/POST.js.map +1 -1
- package/dist/kempo/api/fragments/DELETE.js +1 -1
- package/dist/kempo/api/fragments/DELETE.js.map +1 -1
- package/dist/kempo/api/fragments/GET.js +1 -1
- package/dist/kempo/api/fragments/GET.js.map +1 -1
- package/dist/kempo/api/fragments/POST.js +1 -1
- package/dist/kempo/api/fragments/POST.js.map +1 -1
- package/dist/kempo/api/fragments/disable/PUT.js +1 -1
- package/dist/kempo/api/fragments/disable/PUT.js.map +1 -1
- package/dist/kempo/api/fragments/enable/PUT.js +1 -1
- package/dist/kempo/api/fragments/enable/PUT.js.map +1 -1
- package/dist/kempo/api/fragments/file/GET.js +1 -1
- package/dist/kempo/api/fragments/file/GET.js.map +1 -1
- package/dist/kempo/api/fragments/file/PATCH.js +1 -1
- package/dist/kempo/api/fragments/file/PATCH.js.map +1 -1
- package/dist/kempo/api/fragments/file/PUT.js +1 -1
- package/dist/kempo/api/fragments/file/PUT.js.map +1 -1
- package/dist/kempo/api/globals/DELETE.js +1 -1
- package/dist/kempo/api/globals/DELETE.js.map +1 -1
- package/dist/kempo/api/globals/GET.js +1 -1
- package/dist/kempo/api/globals/GET.js.map +1 -1
- package/dist/kempo/api/globals/POST.js +1 -1
- package/dist/kempo/api/globals/POST.js.map +1 -1
- package/dist/kempo/api/globals/disable/PUT.js +1 -1
- package/dist/kempo/api/globals/disable/PUT.js.map +1 -1
- package/dist/kempo/api/globals/enable/PUT.js +1 -1
- package/dist/kempo/api/globals/enable/PUT.js.map +1 -1
- package/dist/kempo/api/globals/entry/GET.js +1 -1
- package/dist/kempo/api/globals/entry/GET.js.map +1 -1
- package/dist/kempo/api/globals/entry/PUT.js +1 -1
- package/dist/kempo/api/globals/entry/PUT.js.map +1 -1
- package/dist/kempo/api/groups/DELETE.js +1 -1
- package/dist/kempo/api/groups/DELETE.js.map +1 -1
- package/dist/kempo/api/groups/GET.js +1 -1
- package/dist/kempo/api/groups/GET.js.map +1 -1
- package/dist/kempo/api/groups/PATCH.js +1 -1
- package/dist/kempo/api/groups/PATCH.js.map +1 -1
- package/dist/kempo/api/groups/POST.js +1 -1
- package/dist/kempo/api/groups/POST.js.map +1 -1
- package/dist/kempo/api/groups/[name]/GET.js +1 -1
- package/dist/kempo/api/groups/[name]/GET.js.map +1 -1
- package/dist/kempo/api/groups/[name]/members/DELETE.js +1 -1
- package/dist/kempo/api/groups/[name]/members/DELETE.js.map +1 -1
- package/dist/kempo/api/groups/[name]/members/GET.js +1 -1
- package/dist/kempo/api/groups/[name]/members/GET.js.map +1 -1
- package/dist/kempo/api/groups/[name]/members/POST.js +1 -1
- package/dist/kempo/api/groups/[name]/members/POST.js.map +1 -1
- package/dist/kempo/api/groups/[name]/permissions/DELETE.js +1 -1
- package/dist/kempo/api/groups/[name]/permissions/DELETE.js.map +1 -1
- package/dist/kempo/api/groups/[name]/permissions/GET.js +1 -1
- package/dist/kempo/api/groups/[name]/permissions/GET.js.map +1 -1
- package/dist/kempo/api/groups/[name]/permissions/POST.js +1 -1
- package/dist/kempo/api/groups/[name]/permissions/POST.js.map +1 -1
- package/dist/kempo/api/pages/DELETE.js +1 -1
- package/dist/kempo/api/pages/DELETE.js.map +1 -1
- package/dist/kempo/api/pages/GET.js +1 -1
- package/dist/kempo/api/pages/GET.js.map +1 -1
- package/dist/kempo/api/pages/POST.js +1 -1
- package/dist/kempo/api/pages/POST.js.map +1 -1
- package/dist/kempo/api/pages/directories/GET.js +1 -1
- package/dist/kempo/api/pages/directories/GET.js.map +1 -1
- package/dist/kempo/api/pages/disable/PUT.js +1 -1
- package/dist/kempo/api/pages/disable/PUT.js.map +1 -1
- package/dist/kempo/api/pages/enable/PUT.js +1 -1
- package/dist/kempo/api/pages/enable/PUT.js.map +1 -1
- package/dist/kempo/api/pages/file/GET.js +1 -1
- package/dist/kempo/api/pages/file/GET.js.map +1 -1
- package/dist/kempo/api/pages/file/PATCH.js +1 -1
- package/dist/kempo/api/pages/file/PATCH.js.map +1 -1
- package/dist/kempo/api/pages/file/PUT.js +1 -1
- package/dist/kempo/api/pages/file/PUT.js.map +1 -1
- package/dist/kempo/api/pages/templates/GET.js +1 -1
- package/dist/kempo/api/pages/templates/GET.js.map +1 -1
- package/dist/kempo/api/permissions/DELETE.js +1 -1
- package/dist/kempo/api/permissions/DELETE.js.map +1 -1
- package/dist/kempo/api/permissions/GET.js +1 -1
- package/dist/kempo/api/permissions/GET.js.map +1 -1
- package/dist/kempo/api/permissions/PATCH.js +1 -1
- package/dist/kempo/api/permissions/PATCH.js.map +1 -1
- package/dist/kempo/api/permissions/POST.js +1 -1
- package/dist/kempo/api/permissions/POST.js.map +1 -1
- package/dist/kempo/api/settings/[owner]/GET.js +1 -1
- package/dist/kempo/api/settings/[owner]/GET.js.map +1 -1
- package/dist/kempo/api/settings/[owner]/[name]/DELETE.js +1 -1
- package/dist/kempo/api/settings/[owner]/[name]/DELETE.js.map +1 -1
- package/dist/kempo/api/settings/[owner]/[name]/GET.js +1 -1
- package/dist/kempo/api/settings/[owner]/[name]/GET.js.map +1 -1
- package/dist/kempo/api/settings/[owner]/[name]/POST.js +1 -1
- package/dist/kempo/api/settings/[owner]/[name]/POST.js.map +1 -1
- package/dist/kempo/api/settings/public/GET.js +1 -1
- package/dist/kempo/api/settings/public/GET.js.map +1 -1
- package/dist/kempo/api/templates/DELETE.js +1 -1
- package/dist/kempo/api/templates/DELETE.js.map +1 -1
- package/dist/kempo/api/templates/GET.js +1 -1
- package/dist/kempo/api/templates/GET.js.map +1 -1
- package/dist/kempo/api/templates/POST.js +1 -1
- package/dist/kempo/api/templates/POST.js.map +1 -1
- package/dist/kempo/api/templates/disable/PUT.js +1 -1
- package/dist/kempo/api/templates/disable/PUT.js.map +1 -1
- package/dist/kempo/api/templates/enable/PUT.js +1 -1
- package/dist/kempo/api/templates/enable/PUT.js.map +1 -1
- package/dist/kempo/api/templates/file/GET.js +1 -1
- package/dist/kempo/api/templates/file/GET.js.map +1 -1
- package/dist/kempo/api/templates/file/PATCH.js +1 -1
- package/dist/kempo/api/templates/file/PATCH.js.map +1 -1
- package/dist/kempo/api/templates/file/PUT.js +1 -1
- package/dist/kempo/api/templates/file/PUT.js.map +1 -1
- package/dist/kempo/api/user/DELETE.js +1 -1
- package/dist/kempo/api/user/DELETE.js.map +1 -1
- package/dist/kempo/api/user/GET.js +1 -1
- package/dist/kempo/api/user/GET.js.map +1 -1
- package/dist/kempo/api/user/PATCH.js +1 -1
- package/dist/kempo/api/user/PATCH.js.map +1 -1
- package/dist/kempo/api/user/[userid]/GET.js +1 -1
- package/dist/kempo/api/user/[userid]/GET.js.map +1 -1
- package/dist/kempo/api/user/[userid]/groups/DELETE.js +1 -1
- package/dist/kempo/api/user/[userid]/groups/DELETE.js.map +1 -1
- package/dist/kempo/api/user/[userid]/groups/GET.js +1 -1
- package/dist/kempo/api/user/[userid]/groups/GET.js.map +1 -1
- package/dist/kempo/api/user/[userid]/groups/POST.js +1 -1
- package/dist/kempo/api/user/[userid]/groups/POST.js.map +1 -1
- package/dist/kempo/api/user/[userid]/permissions/GET.js +1 -1
- package/dist/kempo/api/user/[userid]/permissions/GET.js.map +1 -1
- package/dist/kempo/api/user/[userid]/permissions/all/GET.js +1 -1
- package/dist/kempo/api/user/[userid]/permissions/all/GET.js.map +1 -1
- package/dist/kempo/api/user/[userid]/permissions/list/GET.js +1 -1
- package/dist/kempo/api/user/[userid]/permissions/list/GET.js.map +1 -1
- package/dist/kempo/api/user/[userid]/permissions/some/GET.js +1 -1
- package/dist/kempo/api/user/[userid]/permissions/some/GET.js.map +1 -1
- package/dist/kempo/api/user/[userid]/sessions/DELETE.js +1 -1
- package/dist/kempo/api/user/[userid]/sessions/DELETE.js.map +1 -1
- package/dist/kempo/api/user/[userid]/sessions/GET.js +1 -1
- package/dist/kempo/api/user/[userid]/sessions/GET.js.map +1 -1
- package/dist/kempo/api/user/[userid]/sessions/expired/DELETE.js +1 -1
- package/dist/kempo/api/user/[userid]/sessions/expired/DELETE.js.map +1 -1
- package/dist/kempo/api/user/create/POST.js +1 -1
- package/dist/kempo/api/user/create/POST.js.map +1 -1
- package/dist/kempo/api/user/search/GET.js +1 -1
- package/dist/kempo/api/user/search/GET.js.map +1 -1
- package/dist/kempo/components/LogoutBtn.js +1 -1
- package/dist/kempo/components/LogoutBtn.js.map +1 -1
- package/dist/kempo/components/Menu.js +1 -1
- package/dist/kempo/components/Menu.js.map +1 -1
- package/dist/kempo/components/Permission.js +1 -1
- package/dist/kempo/components/Permission.js.map +1 -1
- package/dist/kempo/components/Role.js +1 -1
- package/dist/kempo/components/Role.js.map +1 -1
- package/dist/kempo/components/UserCreatedAt.js +1 -1
- package/dist/kempo/components/UserCreatedAt.js.map +1 -1
- package/dist/kempo/components/UserEmail.js +1 -1
- package/dist/kempo/components/UserEmail.js.map +1 -1
- package/dist/kempo/components/UserEmailVerified.js +1 -1
- package/dist/kempo/components/UserEmailVerified.js.map +1 -1
- package/dist/kempo/components/UserName.js +1 -1
- package/dist/kempo/components/UserName.js.map +1 -1
- package/dist/kempo/fetch.js +1 -1
- package/dist/kempo/fetch.js.map +1 -1
- package/dist/kempo/sdk.js +1 -1
- package/dist/kempo/sdk.js.map +1 -1
- package/package.json +1 -1
- package/server/db/migrations/0000_initial.sql +0 -91
- package/server/db/migrations/0001_soft_master_chief.sql +0 -1
- package/server/db/migrations/meta/0000_snapshot.json +0 -588
- package/server/db/migrations/meta/0001_snapshot.json +0 -594
- package/server/db/migrations/meta/_journal.json +0 -20
package/bin/cli.js
CHANGED
|
@@ -407,6 +407,13 @@ if(containerMode === 'new'){
|
|
|
407
407
|
*/
|
|
408
408
|
|
|
409
409
|
console.log('\n--- Initializing database ---\n');
|
|
410
|
+
|
|
411
|
+
// On a fresh install, clear migration history so drizzle-kit push doesn't prompt about schema diffs
|
|
412
|
+
const migrationDir = join(projectDir, 'drizzle', 'migrations');
|
|
413
|
+
if(existsSync(migrationDir)){
|
|
414
|
+
rmSync(migrationDir, { recursive: true, force: true });
|
|
415
|
+
}
|
|
416
|
+
|
|
410
417
|
execSync('npx drizzle-kit push', { cwd: projectDir, stdio: 'inherit' });
|
|
411
418
|
execSync('node node_modules/kempo/scripts/init-db.js', { cwd: projectDir, stdio: 'inherit' });
|
|
412
419
|
|
|
@@ -3,4 +3,4 @@ import TableControl from"/kempo-ui/components/tableControls/TableControl.js";imp
|
|
|
3
3
|
<k-icon name="add"></k-icon>
|
|
4
4
|
</button>
|
|
5
5
|
`}}customElements.define("admin-add-group-control",AddGroupControl);
|
|
6
|
-
//# sourceMappingURL=AddGroupControl.js.map
|
|
6
|
+
//# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\admin\components\AddGroupControl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src
|
|
1
|
+
{"version":3,"file":"src\\admin\\components\\AddGroupControl.js","names":["TableControl","html","AddGroupControl","render","customElements","define"],"sources":["0"],"sourcesContent":["import TableControl from '/kempo-ui/components/tableControls/TableControl.js';\r\nimport { html } from '/kempo-ui/lit-all.min.js';\r\nimport '/kempo-ui/components/Icon.js';\r\n\r\nexport default class AddGroupControl extends TableControl {\r\n render() {\r\n return html`\r\n <button class=\"no-btn icon-btn\" title=\"Add to Group\">\r\n <k-icon name=\"add\"></k-icon>\r\n </button>\r\n `;\r\n }\r\n}\r\n\r\ncustomElements.define('admin-add-group-control', AddGroupControl);\r\n"],"mappings":"OAAOA,iBAAkB,4DAChBC,SAAY,iCACd,8CAEQ,MAAMC,wBAAwBF,aAC3C,MAAAG,GACE,OAAOF,IAAI;;;;KAKb,EAGFG,eAAeC,OAAO,0BAA2BH","ignoreList":[]}
|
|
@@ -3,4 +3,4 @@ import TableControl from"/kempo-ui/components/tableControls/TableControl.js";imp
|
|
|
3
3
|
<k-icon name="timer_off"></k-icon>
|
|
4
4
|
</button>
|
|
5
5
|
`}}customElements.define("admin-clear-expired-sessions",ClearExpiredSessionsControl);
|
|
6
|
-
//# sourceMappingURL=ClearExpiredSessionsControl.js.map
|
|
6
|
+
//# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\admin\components\ClearExpiredSessionsControl.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src
|
|
1
|
+
{"version":3,"file":"src\\admin\\components\\ClearExpiredSessionsControl.js","names":["TableControl","html","ClearExpiredSessionsControl","render","customElements","define"],"sources":["0"],"sourcesContent":["import TableControl from '/kempo-ui/components/tableControls/TableControl.js';\r\nimport { html } from '/kempo-ui/lit-all.min.js';\r\nimport '/kempo-ui/components/Icon.js';\r\n\r\nexport default class ClearExpiredSessionsControl extends TableControl {\r\n render() {\r\n return html`\r\n <button class=\"no-btn icon-btn\" title=\"Clear Expired Sessions\">\r\n <k-icon name=\"timer_off\"></k-icon>\r\n </button>\r\n `;\r\n }\r\n}\r\n\r\ncustomElements.define('admin-clear-expired-sessions', ClearExpiredSessionsControl);\r\n"],"mappings":"OAAOA,iBAAkB,4DAChBC,SAAY,iCACd,8CAEQ,MAAMC,oCAAoCF,aACvD,MAAAG,GACE,OAAOF,IAAI;;;;KAKb,EAGFG,eAAeC,OAAO,+BAAgCH","ignoreList":[]}
|
|
@@ -98,4 +98,4 @@ import ShadowComponent from"/kempo-ui/components/ShadowComponent.js";import{html
|
|
|
98
98
|
</k-accordion-panel>
|
|
99
99
|
</k-accordion>
|
|
100
100
|
`}}customElements.define("admin-fragment-editor",FragmentEditor);
|
|
101
|
-
//# sourceMappingURL=FragmentEditor.js.map
|
|
101
|
+
//# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\admin\components\FragmentEditor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src/admin/components/FragmentEditor.js","names":["ShadowComponent","html","getFragment","updateFragment","deleteFragments","moveFragment","listDirectories","Dialog","Toast","FragmentEditor","static","loading","state","error","saving","fragment","constructor","super","this","file","connectedCallback","document","addEventListener","handleKeyDown","param","URLSearchParams","window","location","search","get","err","title","name","disconnectedCallback","removeEventListener","getFormState","root","shadowRoot","querySelector","value","markup","getValue","e","ctrlKey","metaKey","key","preventDefault","locked","handleSave","handleDelete","confirm","async","confirmed","msg","success","setTimeout","href","handleMove","dirData","directories","parts","replace","split","currentName","pop","currentDir","join","dirToInternal","p","currentDirDisplay","$dialog","create","map","d","confirmText","confirmAction","dirInput","trim","newName","test","includes","newDir","newFile","saveError","moveError","moved","newParam","encodeURIComponent","cancelText","updatePreview","dir","prefix","textContent","handleReset","saved","updatedAt","currentSlug","newSlug","toLowerCase","render","isCustom","owner","isLocked","length","author","createdAt","Date","toLocaleString","customElements","define"],"sources":["0"],"sourcesContent":["import ShadowComponent from '/kempo-ui/components/ShadowComponent.js';\nimport { html } from '/kempo-ui/lit-all.min.js';\nimport { getFragment, updateFragment, deleteFragments, moveFragment, listDirectories } from '/kempo/sdk.js';\nimport Dialog from '/kempo-ui/components/Dialog.js';\nimport Toast from '/kempo-ui/components/Toast.js';\nimport '/kempo-ui/components/Icon.js';\nimport '/kempo-ui/components/Accordion.js';\nimport '/kempo-ui/components/CodeEditor.js';\n\nexport default class FragmentEditor extends ShadowComponent {\n static properties = {\n loading: { state: true },\n error: { state: true },\n saving: { state: true },\n fragment: { state: true }\n };\n\n constructor() {\n super();\n this.loading = true;\n this.error = false;\n this.saving = false;\n this.fragment = null;\n this.file = '';\n }\n\n async connectedCallback() {\n super.connectedCallback();\n document.addEventListener('keydown', this.handleKeyDown);\n const param = new URLSearchParams(window.location.search).get('fragment');\n this.file = param ? param + '.fragment.html' : '';\n\n if(!this.file){\n this.loading = false;\n this.error = true;\n return;\n }\n\n const [err, fragment] = await getFragment(this.file);\n this.loading = false;\n\n if(err){\n this.error = true;\n return;\n }\n\n this.fragment = fragment;\n document.title = `Edit: ${fragment.name} - Admin`;\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n /*\n Helpers\n */\n\n getFormState() {\n const root = this.shadowRoot;\n return {\n name: root.querySelector('#metaName')?.value ?? this.fragment.name,\n markup: root.querySelector('k-code-editor')?.getValue() ?? this.fragment.markup\n };\n }\n\n /*\n Event Handlers\n */\n\n handleKeyDown = e => {\n if((e.ctrlKey || e.metaKey) && e.key === 's'){\n e.preventDefault();\n if(!this.saving && !this.fragment?.locked) this.handleSave();\n }\n };\n\n handleDelete = () => {\n Dialog.confirm('Delete this fragment? This action cannot be undone.', async confirmed => {\n if(!confirmed) return;\n const [error] = await deleteFragments([this.file]);\n if(error){\n Toast.error(error.msg || 'Failed to delete fragment');\n return;\n }\n Toast.success('Fragment deleted');\n setTimeout(() => { window.location.href = '/admin/content/fragments'; }, 1000);\n });\n };\n\n handleMove = async () => {\n const [, dirData] = await listDirectories();\n const directories = dirData?.directories || ['.'];\n\n const parts = this.file.replace(/\\.fragment\\.html$/, '').split('/');\n const currentName = parts.pop();\n const currentDir = parts.join('/') || '.';\n\n const isValidDir = p => /^\\/[a-zA-Z0-9_\\-\\[\\]\\/]*$/.test(p) && !p.includes('..') && !p.includes('//');\n const dirToInternal = p => { const t = (p || '/').replace(/^\\//, '').replace(/\\/$/, ''); return t || '.'; };\n const currentDirDisplay = currentDir === '.' ? '/' : '/' + currentDir;\n\n const $dialog = Dialog.create(html`\n <div class=\"p\">\n <div class=\"mb\">\n <label class=\"d-b mb-sm\"><strong>Location</strong></label>\n <input type=\"text\" id=\"dlg-move-dir\" class=\"full\" list=\"dlg-move-dir-list\" .value=\"${currentDirDisplay}\" placeholder=\"/\">\n <datalist id=\"dlg-move-dir-list\">\n ${directories.map(d => html`<option value=\"${d === '.' ? '/' : '/' + d}\">`)}\n </datalist>\n </div>\n <div>\n <label class=\"d-b mb-sm\"><strong>Fragment Name</strong></label>\n <input type=\"text\" id=\"dlg-move-name\" class=\"full\" .value=\"${currentName}\">\n <p class=\"mt-sm muted\"><small id=\"dlg-move-preview\"></small></p>\n </div>\n </div>\n `, {\n title: 'Move Fragment',\n confirmText: 'Save and Move Fragment',\n confirmAction: async () => {\n const dirInput = $dialog.querySelector('#dlg-move-dir').value.trim() || '/';\n const newName = $dialog.querySelector('#dlg-move-name').value.trim();\n if(!newName){\n Toast.error('Fragment name is required');\n return;\n }\n if(!isValidDir(dirInput)){\n Toast.error('Invalid directory path');\n return;\n }\n const newDir = dirToInternal(dirInput);\n const newFile = newDir === '.'\n ? `${newName}.fragment.html`\n : `${newDir}/${newName}.fragment.html`;\n\n this.saving = true;\n const [saveError] = await updateFragment({ file: this.file, markup: this.getFormState().markup });\n this.saving = false;\n if(saveError){\n Toast.error(saveError.msg || 'Failed to save fragment');\n return;\n }\n\n const [moveError, moved] = await moveFragment({ file: this.file, newFile });\n if(moveError){\n Toast.error(moveError.msg || 'Failed to move fragment');\n return;\n }\n\n Toast.success('Fragment saved and moved');\n const newParam = moved.file.replace(/\\.fragment\\.html$/, '');\n setTimeout(() => {\n window.location.href = `/admin/content/fragments/edit?fragment=${encodeURIComponent(newParam)}`;\n }, 1000);\n },\n cancelText: 'Cancel'\n });\n\n const updatePreview = () => {\n const dir = dirToInternal($dialog.querySelector('#dlg-move-dir').value || '/');\n const name = $dialog.querySelector('#dlg-move-name').value;\n const prefix = dir === '.' ? '/' : '/' + dir + '/';\n $dialog.querySelector('#dlg-move-preview').textContent = name ? prefix + name : '';\n };\n $dialog.querySelector('#dlg-move-dir').addEventListener('input', updatePreview);\n $dialog.querySelector('#dlg-move-name').addEventListener('input', updatePreview);\n updatePreview();\n };\n\n handleReset = () => {\n Dialog.confirm('Reset this fragment? Any unsaved changes will be lost.', confirmed => {\n if(!confirmed) return;\n this.fragment = { ...this.fragment };\n });\n };\n\n handleSave = async () => {\n this.saving = true;\n const state = this.getFormState();\n const [saveError, saved] = await updateFragment({ file: this.file, markup: state.markup });\n this.saving = false;\n\n if(saveError){\n Toast.error(saveError.msg || 'Failed to save fragment');\n return;\n }\n\n this.fragment = { ...this.fragment, markup: state.markup, updatedAt: saved.updatedAt };\n\n const slugify = n => n.toLowerCase().trim().replace(/[^\\w\\s-]/g, '').replace(/[\\s_]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');\n const parts = this.file.replace(/\\.fragment\\.html$/, '').split('/');\n const currentSlug = parts.pop();\n const dir = parts.join('/');\n const newSlug = slugify(state.name);\n\n if(newSlug && newSlug !== currentSlug){\n const newFile = dir ? `${dir}/${newSlug}.fragment.html` : `${newSlug}.fragment.html`;\n const [moveError, moved] = await moveFragment({ file: this.file, newFile });\n if(moveError){\n Toast.error(moveError.msg || 'Failed to rename fragment file');\n return;\n }\n Toast.success('Fragment saved and renamed');\n const newParam = moved.file.replace(/\\.fragment\\.html$/, '');\n setTimeout(() => {\n window.location.href = `/admin/content/fragments/edit?fragment=${encodeURIComponent(newParam)}`;\n }, 1000);\n return;\n }\n\n document.title = `Edit: ${this.fragment.name} - Admin`;\n Toast.success('Fragment saved');\n };\n\n /*\n Render\n */\n\n render() {\n if(this.loading) return html`<div>Loading fragment...</div>`;\n\n if(this.error) return html`\n <div>\n <p>Fragment not found.</p>\n <a href=\"/admin/content/fragments\">Back to Fragments</a>\n </div>\n `;\n\n const { fragment } = this;\n const isCustom = fragment.owner === 'custom';\n const isLocked = fragment.locked;\n\n return html`\n ${isLocked ? html`\n <div class=\"p r mb bc-warning tc-warning\">\n <k-icon name=\"lock\"></k-icon> This fragment is locked and cannot be edited. It is managed by ${isCustom ? 'an extension' : 'the system'}.\n </div>\n ` : ''}\n <div class=\"d-f mb\">\n <div class=\"btn-grp mrh mb\">\n <a href=\"/admin/content/fragments\" class=\"btn\">\n <k-icon name=\"arrow\" direction=\"left\"></k-icon> Fragments\n </a>\n </div>\n <div class=\"flex\"></div>\n ${isCustom && !isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button class=\"danger\" @click=\"${this.handleDelete}\"><k-icon name=\"delete\"></k-icon> Delete</button>\n <button @click=\"${this.handleMove}\"><k-icon name=\"drive_file_move\"></k-icon> Move Fragment</button>\n </div>\n ` : ''}\n ${!isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button @click=\"${this.handleReset}\"><k-icon name=\"restart_alt\"></k-icon> Reset</button>\n <button id=\"saveBtn\" class=\"primary\" ?disabled=\"${this.saving}\" @click=\"${this.handleSave}\">\n <k-icon name=\"save\"></k-icon> Save\n </button>\n </div>\n ` : ''}\n </div>\n\n <h1 class=\"mb\">Fragment: ${fragment.name}</h1>\n\n <k-accordion>\n <k-accordion-header for-panel=\"metadata\">Metadata</k-accordion-header>\n <k-accordion-panel name=\"metadata\">\n <div class=\"p\">\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Name</strong></label>\n <input type=\"text\" id=\"metaName\" class=\"flex\" .value=\"${fragment.name || ''}\" ?disabled=\"${!isCustom || isLocked}\">\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Directory</strong></label>\n <span class=\"muted\">${(() => { const parts = this.file.replace(/\\.fragment\\.html$/, '').split('/'); parts.pop(); return parts.length ? parts.join('/') : '/'; })()}</span>\n ${isCustom && !isLocked ? html`\n <button class=\"icon-btn no-btn ph\" title=\"Move Fragment\" @click=\"${this.handleMove}\"><k-icon name=\"drive_file_move\"></k-icon></button>\n ` : ''}\n </div>\n ${fragment.author ? html`\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Author</strong></label>\n <span class=\"muted\">${fragment.author}</span>\n </div>\n ` : ''}\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Owner</strong></label>\n <span class=\"muted\">${fragment.owner || ''}</span>\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Created</strong></label>\n <span class=\"muted\">${fragment.createdAt ? new Date(fragment.createdAt).toLocaleString() : ''}</span>\n </div>\n <div class=\"d-f\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Updated</strong></label>\n <span class=\"muted\">${fragment.updatedAt ? new Date(fragment.updatedAt).toLocaleString() : ''}</span>\n </div>\n </div>\n </k-accordion-panel>\n <k-accordion-header for-panel=\"fragment\" active>Fragment</k-accordion-header>\n <k-accordion-panel name=\"fragment\" active>\n <div class=\"p\">\n <k-code-editor\n class=\"r b\"\n language=\"html\"\n .value=\"${fragment.markup || ''}\"\n style=\"height: 500px;\"\n ?disabled=\"${isLocked}\"\n ></k-code-editor>\n </div>\n </k-accordion-panel>\n </k-accordion>\n `;\n }\n}\n\ncustomElements.define('admin-fragment-editor', FragmentEditor);\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"src\\admin\\components\\FragmentEditor.js","names":["ShadowComponent","html","getFragment","updateFragment","deleteFragments","moveFragment","listDirectories","Dialog","Toast","FragmentEditor","static","loading","state","error","saving","fragment","constructor","super","this","file","connectedCallback","document","addEventListener","handleKeyDown","param","URLSearchParams","window","location","search","get","err","title","name","disconnectedCallback","removeEventListener","getFormState","root","shadowRoot","querySelector","value","markup","getValue","e","ctrlKey","metaKey","key","preventDefault","locked","handleSave","handleDelete","confirm","async","confirmed","msg","success","setTimeout","href","handleMove","dirData","directories","parts","replace","split","currentName","pop","currentDir","join","dirToInternal","p","currentDirDisplay","$dialog","create","map","d","confirmText","confirmAction","dirInput","trim","newName","test","includes","newDir","newFile","saveError","moveError","moved","newParam","encodeURIComponent","cancelText","updatePreview","dir","prefix","textContent","handleReset","saved","updatedAt","currentSlug","newSlug","toLowerCase","render","isCustom","owner","isLocked","length","author","createdAt","Date","toLocaleString","customElements","define"],"sources":["0"],"sourcesContent":["import ShadowComponent from '/kempo-ui/components/ShadowComponent.js';\nimport { html } from '/kempo-ui/lit-all.min.js';\nimport { getFragment, updateFragment, deleteFragments, moveFragment, listDirectories } from '/kempo/sdk.js';\nimport Dialog from '/kempo-ui/components/Dialog.js';\nimport Toast from '/kempo-ui/components/Toast.js';\nimport '/kempo-ui/components/Icon.js';\nimport '/kempo-ui/components/Accordion.js';\nimport '/kempo-ui/components/CodeEditor.js';\n\nexport default class FragmentEditor extends ShadowComponent {\n static properties = {\n loading: { state: true },\n error: { state: true },\n saving: { state: true },\n fragment: { state: true }\n };\n\n constructor() {\n super();\n this.loading = true;\n this.error = false;\n this.saving = false;\n this.fragment = null;\n this.file = '';\n }\n\n async connectedCallback() {\n super.connectedCallback();\n document.addEventListener('keydown', this.handleKeyDown);\n const param = new URLSearchParams(window.location.search).get('fragment');\n this.file = param ? param + '.fragment.html' : '';\n\n if(!this.file){\n this.loading = false;\n this.error = true;\n return;\n }\n\n const [err, fragment] = await getFragment(this.file);\n this.loading = false;\n\n if(err){\n this.error = true;\n return;\n }\n\n this.fragment = fragment;\n document.title = `Edit: ${fragment.name} - Admin`;\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n /*\n Helpers\n */\n\n getFormState() {\n const root = this.shadowRoot;\n return {\n name: root.querySelector('#metaName')?.value ?? this.fragment.name,\n markup: root.querySelector('k-code-editor')?.getValue() ?? this.fragment.markup\n };\n }\n\n /*\n Event Handlers\n */\n\n handleKeyDown = e => {\n if((e.ctrlKey || e.metaKey) && e.key === 's'){\n e.preventDefault();\n if(!this.saving && !this.fragment?.locked) this.handleSave();\n }\n };\n\n handleDelete = () => {\n Dialog.confirm('Delete this fragment? This action cannot be undone.', async confirmed => {\n if(!confirmed) return;\n const [error] = await deleteFragments([this.file]);\n if(error){\n Toast.error(error.msg || 'Failed to delete fragment');\n return;\n }\n Toast.success('Fragment deleted');\n setTimeout(() => { window.location.href = '/admin/content/fragments'; }, 1000);\n });\n };\n\n handleMove = async () => {\n const [, dirData] = await listDirectories();\n const directories = dirData?.directories || ['.'];\n\n const parts = this.file.replace(/\\.fragment\\.html$/, '').split('/');\n const currentName = parts.pop();\n const currentDir = parts.join('/') || '.';\n\n const isValidDir = p => /^\\/[a-zA-Z0-9_\\-\\[\\]\\/]*$/.test(p) && !p.includes('..') && !p.includes('//');\n const dirToInternal = p => { const t = (p || '/').replace(/^\\//, '').replace(/\\/$/, ''); return t || '.'; };\n const currentDirDisplay = currentDir === '.' ? '/' : '/' + currentDir;\n\n const $dialog = Dialog.create(html`\n <div class=\"p\">\n <div class=\"mb\">\n <label class=\"d-b mb-sm\"><strong>Location</strong></label>\n <input type=\"text\" id=\"dlg-move-dir\" class=\"full\" list=\"dlg-move-dir-list\" .value=\"${currentDirDisplay}\" placeholder=\"/\">\n <datalist id=\"dlg-move-dir-list\">\n ${directories.map(d => html`<option value=\"${d === '.' ? '/' : '/' + d}\">`)}\n </datalist>\n </div>\n <div>\n <label class=\"d-b mb-sm\"><strong>Fragment Name</strong></label>\n <input type=\"text\" id=\"dlg-move-name\" class=\"full\" .value=\"${currentName}\">\n <p class=\"mt-sm muted\"><small id=\"dlg-move-preview\"></small></p>\n </div>\n </div>\n `, {\n title: 'Move Fragment',\n confirmText: 'Save and Move Fragment',\n confirmAction: async () => {\n const dirInput = $dialog.querySelector('#dlg-move-dir').value.trim() || '/';\n const newName = $dialog.querySelector('#dlg-move-name').value.trim();\n if(!newName){\n Toast.error('Fragment name is required');\n return;\n }\n if(!isValidDir(dirInput)){\n Toast.error('Invalid directory path');\n return;\n }\n const newDir = dirToInternal(dirInput);\n const newFile = newDir === '.'\n ? `${newName}.fragment.html`\n : `${newDir}/${newName}.fragment.html`;\n\n this.saving = true;\n const [saveError] = await updateFragment({ file: this.file, markup: this.getFormState().markup });\n this.saving = false;\n if(saveError){\n Toast.error(saveError.msg || 'Failed to save fragment');\n return;\n }\n\n const [moveError, moved] = await moveFragment({ file: this.file, newFile });\n if(moveError){\n Toast.error(moveError.msg || 'Failed to move fragment');\n return;\n }\n\n Toast.success('Fragment saved and moved');\n const newParam = moved.file.replace(/\\.fragment\\.html$/, '');\n setTimeout(() => {\n window.location.href = `/admin/content/fragments/edit?fragment=${encodeURIComponent(newParam)}`;\n }, 1000);\n },\n cancelText: 'Cancel'\n });\n\n const updatePreview = () => {\n const dir = dirToInternal($dialog.querySelector('#dlg-move-dir').value || '/');\n const name = $dialog.querySelector('#dlg-move-name').value;\n const prefix = dir === '.' ? '/' : '/' + dir + '/';\n $dialog.querySelector('#dlg-move-preview').textContent = name ? prefix + name : '';\n };\n $dialog.querySelector('#dlg-move-dir').addEventListener('input', updatePreview);\n $dialog.querySelector('#dlg-move-name').addEventListener('input', updatePreview);\n updatePreview();\n };\n\n handleReset = () => {\n Dialog.confirm('Reset this fragment? Any unsaved changes will be lost.', confirmed => {\n if(!confirmed) return;\n this.fragment = { ...this.fragment };\n });\n };\n\n handleSave = async () => {\n this.saving = true;\n const state = this.getFormState();\n const [saveError, saved] = await updateFragment({ file: this.file, markup: state.markup });\n this.saving = false;\n\n if(saveError){\n Toast.error(saveError.msg || 'Failed to save fragment');\n return;\n }\n\n this.fragment = { ...this.fragment, markup: state.markup, updatedAt: saved.updatedAt };\n\n const slugify = n => n.toLowerCase().trim().replace(/[^\\w\\s-]/g, '').replace(/[\\s_]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');\n const parts = this.file.replace(/\\.fragment\\.html$/, '').split('/');\n const currentSlug = parts.pop();\n const dir = parts.join('/');\n const newSlug = slugify(state.name);\n\n if(newSlug && newSlug !== currentSlug){\n const newFile = dir ? `${dir}/${newSlug}.fragment.html` : `${newSlug}.fragment.html`;\n const [moveError, moved] = await moveFragment({ file: this.file, newFile });\n if(moveError){\n Toast.error(moveError.msg || 'Failed to rename fragment file');\n return;\n }\n Toast.success('Fragment saved and renamed');\n const newParam = moved.file.replace(/\\.fragment\\.html$/, '');\n setTimeout(() => {\n window.location.href = `/admin/content/fragments/edit?fragment=${encodeURIComponent(newParam)}`;\n }, 1000);\n return;\n }\n\n document.title = `Edit: ${this.fragment.name} - Admin`;\n Toast.success('Fragment saved');\n };\n\n /*\n Render\n */\n\n render() {\n if(this.loading) return html`<div>Loading fragment...</div>`;\n\n if(this.error) return html`\n <div>\n <p>Fragment not found.</p>\n <a href=\"/admin/content/fragments\">Back to Fragments</a>\n </div>\n `;\n\n const { fragment } = this;\n const isCustom = fragment.owner === 'custom';\n const isLocked = fragment.locked;\n\n return html`\n ${isLocked ? html`\n <div class=\"p r mb bc-warning tc-warning\">\n <k-icon name=\"lock\"></k-icon> This fragment is locked and cannot be edited. It is managed by ${isCustom ? 'an extension' : 'the system'}.\n </div>\n ` : ''}\n <div class=\"d-f mb\">\n <div class=\"btn-grp mrh mb\">\n <a href=\"/admin/content/fragments\" class=\"btn\">\n <k-icon name=\"arrow\" direction=\"left\"></k-icon> Fragments\n </a>\n </div>\n <div class=\"flex\"></div>\n ${isCustom && !isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button class=\"danger\" @click=\"${this.handleDelete}\"><k-icon name=\"delete\"></k-icon> Delete</button>\n <button @click=\"${this.handleMove}\"><k-icon name=\"drive_file_move\"></k-icon> Move Fragment</button>\n </div>\n ` : ''}\n ${!isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button @click=\"${this.handleReset}\"><k-icon name=\"restart_alt\"></k-icon> Reset</button>\n <button id=\"saveBtn\" class=\"primary\" ?disabled=\"${this.saving}\" @click=\"${this.handleSave}\">\n <k-icon name=\"save\"></k-icon> Save\n </button>\n </div>\n ` : ''}\n </div>\n\n <h1 class=\"mb\">Fragment: ${fragment.name}</h1>\n\n <k-accordion>\n <k-accordion-header for-panel=\"metadata\">Metadata</k-accordion-header>\n <k-accordion-panel name=\"metadata\">\n <div class=\"p\">\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Name</strong></label>\n <input type=\"text\" id=\"metaName\" class=\"flex\" .value=\"${fragment.name || ''}\" ?disabled=\"${!isCustom || isLocked}\">\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Directory</strong></label>\n <span class=\"muted\">${(() => { const parts = this.file.replace(/\\.fragment\\.html$/, '').split('/'); parts.pop(); return parts.length ? parts.join('/') : '/'; })()}</span>\n ${isCustom && !isLocked ? html`\n <button class=\"icon-btn no-btn ph\" title=\"Move Fragment\" @click=\"${this.handleMove}\"><k-icon name=\"drive_file_move\"></k-icon></button>\n ` : ''}\n </div>\n ${fragment.author ? html`\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Author</strong></label>\n <span class=\"muted\">${fragment.author}</span>\n </div>\n ` : ''}\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Owner</strong></label>\n <span class=\"muted\">${fragment.owner || ''}</span>\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Created</strong></label>\n <span class=\"muted\">${fragment.createdAt ? new Date(fragment.createdAt).toLocaleString() : ''}</span>\n </div>\n <div class=\"d-f\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Updated</strong></label>\n <span class=\"muted\">${fragment.updatedAt ? new Date(fragment.updatedAt).toLocaleString() : ''}</span>\n </div>\n </div>\n </k-accordion-panel>\n <k-accordion-header for-panel=\"fragment\" active>Fragment</k-accordion-header>\n <k-accordion-panel name=\"fragment\" active>\n <div class=\"p\">\n <k-code-editor\n class=\"r b\"\n language=\"html\"\n .value=\"${fragment.markup || ''}\"\n style=\"height: 500px;\"\n ?disabled=\"${isLocked}\"\n ></k-code-editor>\n </div>\n </k-accordion-panel>\n </k-accordion>\n `;\n }\n}\n\ncustomElements.define('admin-fragment-editor', FragmentEditor);\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -82,4 +82,4 @@ import ShadowComponent from"/kempo-ui/components/ShadowComponent.js";import{html
|
|
|
82
82
|
</k-accordion-panel>
|
|
83
83
|
</k-accordion>
|
|
84
84
|
`}}customElements.define("admin-global-content-editor",GlobalContentEditor);
|
|
85
|
-
//# sourceMappingURL=GlobalContentEditor.js.map
|
|
85
|
+
//# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\admin\components\GlobalContentEditor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src/admin/components/GlobalContentEditor.js","names":["ShadowComponent","html","getGlobalContent","updateGlobalContent","deleteGlobalContent","Dialog","Toast","GlobalContentEditor","static","loading","state","error","saving","entry","constructor","super","this","entryId","connectedCallback","document","addEventListener","handleKeyDown","URLSearchParams","window","location","search","get","err","title","name","disconnectedCallback","removeEventListener","e","ctrlKey","metaKey","key","preventDefault","locked","handleSave","async","root","shadowRoot","querySelector","value","priority","editor","markup","getValue","saveError","saved","id","msg","updatedAt","success","handleReset","confirm","confirmed","handleDelete","setTimeout","href","render","isSystem","owner","isLocked","author","createdAt","Date","toLocaleString","customElements","define"],"sources":["0"],"sourcesContent":["import ShadowComponent from '/kempo-ui/components/ShadowComponent.js';\nimport { html } from '/kempo-ui/lit-all.min.js';\nimport { getGlobalContent, updateGlobalContent, deleteGlobalContent } from '/kempo/sdk.js';\nimport Dialog from '/kempo-ui/components/Dialog.js';\nimport Toast from '/kempo-ui/components/Toast.js';\nimport '/kempo-ui/components/Icon.js';\nimport '/kempo-ui/components/Accordion.js';\nimport '/kempo-ui/components/CodeEditor.js';\n\nexport default class GlobalContentEditor extends ShadowComponent {\n static properties = {\n loading: { state: true },\n error: { state: true },\n saving: { state: true },\n entry: { state: true }\n };\n\n constructor() {\n super();\n this.loading = true;\n this.error = false;\n this.saving = false;\n this.entry = null;\n this.entryId = '';\n }\n\n async connectedCallback() {\n super.connectedCallback();\n document.addEventListener('keydown', this.handleKeyDown);\n this.entryId = new URLSearchParams(window.location.search).get('id') || '';\n\n if(!this.entryId){\n this.loading = false;\n this.error = true;\n return;\n }\n\n const [err, entry] = await getGlobalContent(this.entryId);\n this.loading = false;\n\n if(err){\n this.error = true;\n return;\n }\n\n this.entry = entry;\n document.title = `Edit: ${entry.name || this.entryId} - Admin`;\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n /*\n Event Handlers\n */\n\n handleKeyDown = e => {\n if((e.ctrlKey || e.metaKey) && e.key === 's'){\n e.preventDefault();\n if(!this.saving && !this.entry?.locked) this.handleSave();\n }\n };\n\n handleSave = async () => {\n this.saving = true;\n const root = this.shadowRoot;\n const name = root.querySelector('#metaName').value;\n const location = root.querySelector('#metaLocation').value;\n const priority = root.querySelector('#metaPriority').value;\n const editor = root.querySelector('k-code-editor');\n const markup = editor ? editor.getValue() : this.entry.markup;\n\n const [saveError, saved] = await updateGlobalContent({\n id: this.entryId, name, location, priority, markup\n });\n this.saving = false;\n\n if(saveError){\n Toast.error(saveError.msg || 'Failed to save global content');\n return;\n }\n\n this.entry = { ...this.entry, name, location, priority, markup, updatedAt: saved.updatedAt };\n document.title = `Edit: ${name || this.entryId} - Admin`;\n Toast.success('Global content saved');\n };\n\n handleReset = () => {\n Dialog.confirm('Reset this entry? Any unsaved changes will be lost.', confirmed => {\n if(!confirmed) return;\n this.entry = { ...this.entry };\n });\n };\n\n handleDelete = () => {\n Dialog.confirm('Delete this global content entry? This action cannot be undone.', async confirmed => {\n if(!confirmed) return;\n const [error] = await deleteGlobalContent([this.entryId]);\n if(error){\n Toast.error(error.msg || 'Failed to delete global content');\n return;\n }\n Toast.success('Global content deleted');\n setTimeout(() => { window.location.href = '/admin/content/globals'; }, 1000);\n });\n };\n\n /*\n Render\n */\n\n render() {\n if(this.loading) return html`<div>Loading global content...</div>`;\n\n if(this.error) return html`\n <div>\n <p>Global content entry not found.</p>\n <a href=\"/admin/content/globals\">Back to Global Content</a>\n </div>\n `;\n\n const { entry } = this;\n const isSystem = entry.owner === 'system';\n const isLocked = entry.locked;\n\n return html`\n ${isLocked ? html`\n <div class=\"p r mb bc-warning tc-warning\">\n <k-icon name=\"lock\"></k-icon> This entry is locked and cannot be edited. It is managed by ${isSystem ? 'the system' : 'an extension'}.\n </div>\n ` : ''}\n <div class=\"d-f mb\">\n <div class=\"btn-grp mrh mb\">\n <a href=\"/admin/content/globals\" class=\"btn\">\n <k-icon name=\"arrow\" direction=\"left\"></k-icon> Global Content\n </a>\n </div>\n <div class=\"flex\"></div>\n ${!isSystem && !isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button class=\"danger\" @click=\"${this.handleDelete}\"><k-icon name=\"delete\"></k-icon> Delete</button>\n </div>\n ` : ''}\n ${!isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button @click=\"${this.handleReset}\"><k-icon name=\"restart_alt\"></k-icon> Reset</button>\n <button id=\"saveBtn\" class=\"primary\" ?disabled=\"${this.saving}\" @click=\"${this.handleSave}\">\n <k-icon name=\"save\"></k-icon> Save\n </button>\n </div>\n ` : ''}\n </div>\n <h1 class=\"mb\">Global Content: ${entry.name || this.entryId}</h1>\n\n <k-accordion>\n <k-accordion-header for-panel=\"metadata\">Metadata</k-accordion-header>\n <k-accordion-panel name=\"metadata\">\n <div class=\"p\">\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Name</strong></label>\n <input type=\"text\" id=\"metaName\" class=\"flex\" .value=\"${entry.name || ''}\" ?disabled=\"${isSystem || isLocked}\">\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Location</strong></label>\n <input type=\"text\" id=\"metaLocation\" class=\"flex\" .value=\"${entry.location || ''}\" ?disabled=\"${isSystem || isLocked}\">\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Priority</strong></label>\n <input type=\"number\" id=\"metaPriority\" class=\"flex\" .value=\"${entry.priority ?? 0}\" ?disabled=\"${isSystem || isLocked}\">\n </div>\n ${!isSystem ? html`\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Author</strong></label>\n <span class=\"muted\">${entry.author || ''}</span>\n </div>\n ` : ''}\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Owner</strong></label>\n <span class=\"muted\">${entry.owner || ''}</span>\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Created</strong></label>\n <span class=\"muted\">${entry.createdAt ? new Date(entry.createdAt).toLocaleString() : ''}</span>\n </div>\n <div class=\"d-f\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Updated</strong></label>\n <span class=\"muted\">${entry.updatedAt ? new Date(entry.updatedAt).toLocaleString() : ''}</span>\n </div>\n </div>\n </k-accordion-panel>\n <k-accordion-header for-panel=\"content\" active>Content</k-accordion-header>\n <k-accordion-panel name=\"content\" active>\n <div class=\"p\">\n <k-code-editor\n class=\"r b\"\n language=\"html\"\n .value=\"${entry.markup || ''}\"\n style=\"height: 500px;\"\n ?disabled=\"${isLocked}\"\n ></k-code-editor>\n </div>\n </k-accordion-panel>\n </k-accordion>\n `;\n }\n}\n\ncustomElements.define('admin-global-content-editor', GlobalContentEditor);\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"src\\admin\\components\\GlobalContentEditor.js","names":["ShadowComponent","html","getGlobalContent","updateGlobalContent","deleteGlobalContent","Dialog","Toast","GlobalContentEditor","static","loading","state","error","saving","entry","constructor","super","this","entryId","connectedCallback","document","addEventListener","handleKeyDown","URLSearchParams","window","location","search","get","err","title","name","disconnectedCallback","removeEventListener","e","ctrlKey","metaKey","key","preventDefault","locked","handleSave","async","root","shadowRoot","querySelector","value","priority","editor","markup","getValue","saveError","saved","id","msg","updatedAt","success","handleReset","confirm","confirmed","handleDelete","setTimeout","href","render","isSystem","owner","isLocked","author","createdAt","Date","toLocaleString","customElements","define"],"sources":["0"],"sourcesContent":["import ShadowComponent from '/kempo-ui/components/ShadowComponent.js';\nimport { html } from '/kempo-ui/lit-all.min.js';\nimport { getGlobalContent, updateGlobalContent, deleteGlobalContent } from '/kempo/sdk.js';\nimport Dialog from '/kempo-ui/components/Dialog.js';\nimport Toast from '/kempo-ui/components/Toast.js';\nimport '/kempo-ui/components/Icon.js';\nimport '/kempo-ui/components/Accordion.js';\nimport '/kempo-ui/components/CodeEditor.js';\n\nexport default class GlobalContentEditor extends ShadowComponent {\n static properties = {\n loading: { state: true },\n error: { state: true },\n saving: { state: true },\n entry: { state: true }\n };\n\n constructor() {\n super();\n this.loading = true;\n this.error = false;\n this.saving = false;\n this.entry = null;\n this.entryId = '';\n }\n\n async connectedCallback() {\n super.connectedCallback();\n document.addEventListener('keydown', this.handleKeyDown);\n this.entryId = new URLSearchParams(window.location.search).get('id') || '';\n\n if(!this.entryId){\n this.loading = false;\n this.error = true;\n return;\n }\n\n const [err, entry] = await getGlobalContent(this.entryId);\n this.loading = false;\n\n if(err){\n this.error = true;\n return;\n }\n\n this.entry = entry;\n document.title = `Edit: ${entry.name || this.entryId} - Admin`;\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n /*\n Event Handlers\n */\n\n handleKeyDown = e => {\n if((e.ctrlKey || e.metaKey) && e.key === 's'){\n e.preventDefault();\n if(!this.saving && !this.entry?.locked) this.handleSave();\n }\n };\n\n handleSave = async () => {\n this.saving = true;\n const root = this.shadowRoot;\n const name = root.querySelector('#metaName').value;\n const location = root.querySelector('#metaLocation').value;\n const priority = root.querySelector('#metaPriority').value;\n const editor = root.querySelector('k-code-editor');\n const markup = editor ? editor.getValue() : this.entry.markup;\n\n const [saveError, saved] = await updateGlobalContent({\n id: this.entryId, name, location, priority, markup\n });\n this.saving = false;\n\n if(saveError){\n Toast.error(saveError.msg || 'Failed to save global content');\n return;\n }\n\n this.entry = { ...this.entry, name, location, priority, markup, updatedAt: saved.updatedAt };\n document.title = `Edit: ${name || this.entryId} - Admin`;\n Toast.success('Global content saved');\n };\n\n handleReset = () => {\n Dialog.confirm('Reset this entry? Any unsaved changes will be lost.', confirmed => {\n if(!confirmed) return;\n this.entry = { ...this.entry };\n });\n };\n\n handleDelete = () => {\n Dialog.confirm('Delete this global content entry? This action cannot be undone.', async confirmed => {\n if(!confirmed) return;\n const [error] = await deleteGlobalContent([this.entryId]);\n if(error){\n Toast.error(error.msg || 'Failed to delete global content');\n return;\n }\n Toast.success('Global content deleted');\n setTimeout(() => { window.location.href = '/admin/content/globals'; }, 1000);\n });\n };\n\n /*\n Render\n */\n\n render() {\n if(this.loading) return html`<div>Loading global content...</div>`;\n\n if(this.error) return html`\n <div>\n <p>Global content entry not found.</p>\n <a href=\"/admin/content/globals\">Back to Global Content</a>\n </div>\n `;\n\n const { entry } = this;\n const isSystem = entry.owner === 'system';\n const isLocked = entry.locked;\n\n return html`\n ${isLocked ? html`\n <div class=\"p r mb bc-warning tc-warning\">\n <k-icon name=\"lock\"></k-icon> This entry is locked and cannot be edited. It is managed by ${isSystem ? 'the system' : 'an extension'}.\n </div>\n ` : ''}\n <div class=\"d-f mb\">\n <div class=\"btn-grp mrh mb\">\n <a href=\"/admin/content/globals\" class=\"btn\">\n <k-icon name=\"arrow\" direction=\"left\"></k-icon> Global Content\n </a>\n </div>\n <div class=\"flex\"></div>\n ${!isSystem && !isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button class=\"danger\" @click=\"${this.handleDelete}\"><k-icon name=\"delete\"></k-icon> Delete</button>\n </div>\n ` : ''}\n ${!isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button @click=\"${this.handleReset}\"><k-icon name=\"restart_alt\"></k-icon> Reset</button>\n <button id=\"saveBtn\" class=\"primary\" ?disabled=\"${this.saving}\" @click=\"${this.handleSave}\">\n <k-icon name=\"save\"></k-icon> Save\n </button>\n </div>\n ` : ''}\n </div>\n <h1 class=\"mb\">Global Content: ${entry.name || this.entryId}</h1>\n\n <k-accordion>\n <k-accordion-header for-panel=\"metadata\">Metadata</k-accordion-header>\n <k-accordion-panel name=\"metadata\">\n <div class=\"p\">\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Name</strong></label>\n <input type=\"text\" id=\"metaName\" class=\"flex\" .value=\"${entry.name || ''}\" ?disabled=\"${isSystem || isLocked}\">\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Location</strong></label>\n <input type=\"text\" id=\"metaLocation\" class=\"flex\" .value=\"${entry.location || ''}\" ?disabled=\"${isSystem || isLocked}\">\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Priority</strong></label>\n <input type=\"number\" id=\"metaPriority\" class=\"flex\" .value=\"${entry.priority ?? 0}\" ?disabled=\"${isSystem || isLocked}\">\n </div>\n ${!isSystem ? html`\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Author</strong></label>\n <span class=\"muted\">${entry.author || ''}</span>\n </div>\n ` : ''}\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Owner</strong></label>\n <span class=\"muted\">${entry.owner || ''}</span>\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Created</strong></label>\n <span class=\"muted\">${entry.createdAt ? new Date(entry.createdAt).toLocaleString() : ''}</span>\n </div>\n <div class=\"d-f\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Updated</strong></label>\n <span class=\"muted\">${entry.updatedAt ? new Date(entry.updatedAt).toLocaleString() : ''}</span>\n </div>\n </div>\n </k-accordion-panel>\n <k-accordion-header for-panel=\"content\" active>Content</k-accordion-header>\n <k-accordion-panel name=\"content\" active>\n <div class=\"p\">\n <k-code-editor\n class=\"r b\"\n language=\"html\"\n .value=\"${entry.markup || ''}\"\n style=\"height: 500px;\"\n ?disabled=\"${isLocked}\"\n ></k-code-editor>\n </div>\n </k-accordion-panel>\n </k-accordion>\n `;\n }\n}\n\ncustomElements.define('admin-global-content-editor', GlobalContentEditor);\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -3,4 +3,4 @@ import TableControl from"/kempo-ui/components/tableControls/TableControl.js";imp
|
|
|
3
3
|
<k-icon name="delete"></k-icon>
|
|
4
4
|
</button>
|
|
5
5
|
`}}customElements.define("admin-group-delete-selected",GroupDeleteSelected);
|
|
6
|
-
//# sourceMappingURL=GroupDeleteSelected.js.map
|
|
6
|
+
//# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\admin\components\GroupDeleteSelected.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src
|
|
1
|
+
{"version":3,"file":"src\\admin\\components\\GroupDeleteSelected.js","names":["TableControl","html","GroupDeleteSelected","constructor","super","maxWidth","this","selectionChangeHandler","requestUpdate","connectedCallback","onTableEvent","disconnectedCallback","table","removeEventListener","deleteSelected","selected","getSelectedRecords","records","filter","r","name","length","systemUsersSkipped","some","dispatchEvent","CustomEvent","detail","bubbles","deletableCount","render","customElements","define"],"sources":["0"],"sourcesContent":["import TableControl from '/kempo-ui/components/tableControls/TableControl.js';\r\nimport { html } from '/kempo-ui/lit-all.min.js';\r\nimport '/kempo-ui/components/Icon.js';\r\n\r\nexport default class GroupDeleteSelected extends TableControl {\r\n constructor() {\r\n super({ maxWidth: null });\r\n this.selectionChangeHandler = () => this.requestUpdate();\r\n }\r\n\r\n connectedCallback() {\r\n super.connectedCallback();\r\n this.onTableEvent('selectionChange', this.selectionChangeHandler);\r\n }\r\n\r\n disconnectedCallback() {\r\n super.disconnectedCallback();\r\n if(this.table) this.table.removeEventListener('selectionChange', this.selectionChangeHandler);\r\n }\r\n\r\n deleteSelected = () => {\r\n if(!this.table) return;\r\n const selected = this.table.getSelectedRecords();\r\n const records = selected.filter(r => r.name !== 'system:Users');\r\n if(!records.length) return;\r\n const systemUsersSkipped = selected.some(r => r.name === 'system:Users');\r\n this.dispatchEvent(new CustomEvent('groupRemoveSelected', {\r\n detail: { records, systemUsersSkipped },\r\n bubbles: true\r\n }));\r\n };\r\n\r\n get deletableCount() {\r\n if(!this.table) return 0;\r\n return this.table.getSelectedRecords().filter(r => r.name !== 'system:Users').length;\r\n }\r\n\r\n render() {\r\n return html`\r\n <button class=\"no-btn icon-btn\" ?disabled=\"${this.deletableCount === 0}\" @click=\"${this.deleteSelected}\">\r\n <k-icon name=\"delete\"></k-icon>\r\n </button>\r\n `;\r\n }\r\n}\r\n\r\ncustomElements.define('admin-group-delete-selected', GroupDeleteSelected);\r\n"],"mappings":"OAAOA,iBAAkB,4DAChBC,SAAY,iCACd,8CAEQ,MAAMC,4BAA4BF,aAC/C,WAAAG,GACEC,MAAM,CAAEC,SAAU,OAClBC,KAAKC,uBAAyB,IAAMD,KAAKE,eAC3C,CAEA,iBAAAC,GACEL,MAAMK,oBACNH,KAAKI,aAAa,kBAAmBJ,KAAKC,uBAC5C,CAEA,oBAAAI,GACEP,MAAMO,uBACHL,KAAKM,OAAON,KAAKM,MAAMC,oBAAoB,kBAAmBP,KAAKC,uBACxE,CAEAO,eAAiB,KACf,IAAIR,KAAKM,MAAO,OAChB,MAAMG,EAAWT,KAAKM,MAAMI,qBACtBC,EAAUF,EAASG,OAAOC,GAAgB,iBAAXA,EAAEC,MACvC,IAAIH,EAAQI,OAAQ,OACpB,MAAMC,EAAqBP,EAASQ,KAAKJ,GAAgB,iBAAXA,EAAEC,MAChDd,KAAKkB,cAAc,IAAIC,YAAY,sBAAuB,CACxDC,OAAQ,CAAET,UAASK,sBACnBK,SAAS,MAIb,kBAAIC,GACF,OAAItB,KAAKM,MACFN,KAAKM,MAAMI,qBAAqBE,OAAOC,GAAgB,iBAAXA,EAAEC,MAAyBC,OADvD,CAEzB,CAEA,MAAAQ,GACE,OAAO5B,IAAI;mDAC4D,IAAxBK,KAAKsB,2BAAiCtB,KAAKQ;;;KAI5F,EAGFgB,eAAeC,OAAO,8BAA+B7B","ignoreList":[]}
|
|
@@ -3,4 +3,4 @@ import TableControl from"/kempo-ui/components/tableControls/TableControl.js";imp
|
|
|
3
3
|
<k-icon name="delete"></k-icon>
|
|
4
4
|
</button>
|
|
5
5
|
`}}customElements.define("admin-group-remove-record",GroupRemoveRecord);
|
|
6
|
-
//# sourceMappingURL=GroupRemoveRecord.js.map
|
|
6
|
+
//# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\admin\components\GroupRemoveRecord.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src
|
|
1
|
+
{"version":3,"file":"src\\admin\\components\\GroupRemoveRecord.js","names":["TableControl","html","GroupRemoveRecord","remove","this","record","table","deleteRecord","render","name","customElements","define"],"sources":["0"],"sourcesContent":["import TableControl from '/kempo-ui/components/tableControls/TableControl.js';\r\nimport { html } from '/kempo-ui/lit-all.min.js';\r\nimport '/kempo-ui/components/Icon.js';\r\n\r\nexport default class GroupRemoveRecord extends TableControl {\r\n remove = () => {\r\n if(this.record) this.table.deleteRecord(this.record);\r\n };\r\n\r\n render() {\r\n if(this.record?.name === 'system:Users') return html``;\r\n return html`\r\n <button class=\"no-btn icon-btn\" @click=\"${this.remove}\">\r\n <k-icon name=\"delete\"></k-icon>\r\n </button>\r\n `;\r\n }\r\n}\r\n\r\ncustomElements.define('admin-group-remove-record', GroupRemoveRecord);\r\n"],"mappings":"OAAOA,iBAAkB,4DAChBC,SAAY,iCACd,8CAEQ,MAAMC,0BAA0BF,aAC7CG,OAAS,KACJC,KAAKC,QAAQD,KAAKE,MAAMC,aAAaH,KAAKC,SAG/C,MAAAG,GACE,MAAyB,iBAAtBJ,KAAKC,QAAQI,KAAgCR,IAAI,GAC7CA,IAAI;gDACiCG,KAAKD;;;KAInD,EAGFO,eAAeC,OAAO,4BAA6BT","ignoreList":[]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import LightComponent from"/kempo-ui/components/LightComponent.js";import{html}from"/kempo-ui/lit-all.min.js";let monacoLoadPromise=null;const ensureMonacoLoaded=()=>monacoLoadPromise||(monacoLoadPromise=new Promise(e=>{if(window.monaco)return void e();const t=document.createElement("script");t.src="/monaco-editor/vs/loader.js",t.onload=()=>{require.config({paths:{vs:"/monaco-editor/vs"}}),require(["vs/editor/editor.main"],()=>e())},document.head.appendChild(t)}),monacoLoadPromise);export default class Monaco extends LightComponent{static get properties(){return{language:{type:String},readOnly:{type:Boolean,attribute:"readonly"},height:{type:String}}}#e=null;#t=!1;#i="";constructor(){super(),this.language="json",this.readOnly=!1,this.height="400px"}get value(){return this.#e?this.#e.getValue():this.#i}set value(e){this.#e?this.#e.getValue()!==e&&this.#e.setValue(e):this.#i=e}updated(e){super.updated(e),this.#e||this.#t||(this.#t=!0,this.#o()),this.#e&&(e.has("readOnly")&&this.#e.updateOptions({readOnly:this.readOnly}),e.has("language")&&monaco.editor.setModelLanguage(this.#e.getModel(),this.language))}disconnectedCallback(){super.disconnectedCallback(),this.#e&&(this.#e.dispose(),this.#e=null)}#o=async()=>{await ensureMonacoLoaded();const e=this.querySelector("[data-monaco-container]");if(!e)return;const t="dark"===document.documentElement.getAttribute("theme")||"auto"===document.documentElement.getAttribute("theme")&&window.matchMedia("(prefers-color-scheme: dark)").matches;this.#e=monaco.editor.create(e,{value:this.#i,language:this.language,minimap:{enabled:!1},automaticLayout:!0,theme:t?"vs-dark":"vs",scrollBeyondLastLine:!1,fontSize:14,tabSize:2,readOnly:this.readOnly}),this.#e.onDidChangeModelContent(()=>{this.dispatchEvent(new Event("change"))})};renderLightDom(){return html`<div data-monaco-container style="height: ${this.height}; border: 1px solid var(--c_border); border-radius: var(--radius);"></div>`}}customElements.define("admin-monaco",Monaco);
|
|
2
|
-
//# sourceMappingURL=Monaco.js.map
|
|
2
|
+
//# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\admin\components\Monaco.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src
|
|
1
|
+
{"version":3,"file":"src\\admin\\components\\Monaco.js","names":["LightComponent","html","monacoLoadPromise","ensureMonacoLoaded","Promise","resolve","window","monaco","script","document","createElement","src","onload","require","config","paths","vs","head","appendChild","Monaco","properties","language","type","String","readOnly","Boolean","attribute","height","editor","initializing","pendingValue","constructor","super","this","value","getValue","v","setValue","updated","changedProperties","initEditor","has","updateOptions","setModelLanguage","getModel","disconnectedCallback","dispose","async","container","querySelector","isDark","documentElement","getAttribute","matchMedia","matches","create","minimap","enabled","automaticLayout","theme","scrollBeyondLastLine","fontSize","tabSize","onDidChangeModelContent","dispatchEvent","Event","renderLightDom","customElements","define"],"sources":["0"],"sourcesContent":["import LightComponent from '/kempo-ui/components/LightComponent.js';\r\nimport { html } from '/kempo-ui/lit-all.min.js';\r\n\r\nlet monacoLoadPromise = null;\r\n\r\nconst ensureMonacoLoaded = () => {\r\n\tif(monacoLoadPromise) return monacoLoadPromise;\r\n\tmonacoLoadPromise = new Promise(resolve => {\r\n\t\tif(window.monaco){\r\n\t\t\tresolve();\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst script = document.createElement('script');\r\n\t\tscript.src = '/monaco-editor/vs/loader.js';\r\n\t\tscript.onload = () => {\r\n\t\t\trequire.config({ paths: { vs: '/monaco-editor/vs' } });\r\n\t\t\trequire(['vs/editor/editor.main'], () => resolve());\r\n\t\t};\r\n\t\tdocument.head.appendChild(script);\r\n\t});\r\n\treturn monacoLoadPromise;\r\n};\r\n\r\nexport default class Monaco extends LightComponent {\r\n\tstatic get properties() {\r\n\t\treturn {\r\n\t\t\tlanguage: { type: String },\r\n\t\t\treadOnly: { type: Boolean, attribute: 'readonly' },\r\n\t\t\theight: { type: String }\r\n\t\t};\r\n\t}\r\n\r\n\t#editor = null;\r\n\t#initializing = false;\r\n\t#pendingValue = '';\r\n\r\n\tconstructor() {\r\n\t\tsuper();\r\n\t\tthis.language = 'json';\r\n\t\tthis.readOnly = false;\r\n\t\tthis.height = '400px';\r\n\t}\r\n\r\n\t/*\r\n\t\tValue accessors\r\n\t*/\r\n\r\n\tget value() {\r\n\t\tif(this.#editor) return this.#editor.getValue();\r\n\t\treturn this.#pendingValue;\r\n\t}\r\n\r\n\tset value(v) {\r\n\t\tif(this.#editor){\r\n\t\t\tif(this.#editor.getValue() !== v) this.#editor.setValue(v);\r\n\t\t} else {\r\n\t\t\tthis.#pendingValue = v;\r\n\t\t}\r\n\t}\r\n\r\n\t/*\r\n\t\tLifecycle\r\n\t*/\r\n\r\n\tupdated(changedProperties) {\r\n\t\tsuper.updated(changedProperties);\r\n\t\tif(!this.#editor && !this.#initializing){\r\n\t\t\tthis.#initializing = true;\r\n\t\t\tthis.#initEditor();\r\n\t\t}\r\n\t\tif(this.#editor){\r\n\t\t\tif(changedProperties.has('readOnly')){\r\n\t\t\t\tthis.#editor.updateOptions({ readOnly: this.readOnly });\r\n\t\t\t}\r\n\t\t\tif(changedProperties.has('language')){\r\n\t\t\t\tmonaco.editor.setModelLanguage(this.#editor.getModel(), this.language);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tdisconnectedCallback() {\r\n\t\tsuper.disconnectedCallback();\r\n\t\tif(this.#editor){\r\n\t\t\tthis.#editor.dispose();\r\n\t\t\tthis.#editor = null;\r\n\t\t}\r\n\t}\r\n\r\n\t/*\r\n\t\tEditor initialization\r\n\t*/\r\n\r\n\t#initEditor = async () => {\r\n\t\tawait ensureMonacoLoaded();\r\n\t\tconst container = this.querySelector('[data-monaco-container]');\r\n\t\tif(!container) return;\r\n\t\tconst isDark = document.documentElement.getAttribute('theme') === 'dark'\r\n\t\t\t|| (document.documentElement.getAttribute('theme') === 'auto'\r\n\t\t\t\t&& window.matchMedia('(prefers-color-scheme: dark)').matches);\r\n\t\tthis.#editor = monaco.editor.create(container, {\r\n\t\t\tvalue: this.#pendingValue,\r\n\t\t\tlanguage: this.language,\r\n\t\t\tminimap: { enabled: false },\r\n\t\t\tautomaticLayout: true,\r\n\t\t\ttheme: isDark ? 'vs-dark' : 'vs',\r\n\t\t\tscrollBeyondLastLine: false,\r\n\t\t\tfontSize: 14,\r\n\t\t\ttabSize: 2,\r\n\t\t\treadOnly: this.readOnly\r\n\t\t});\r\n\t\tthis.#editor.onDidChangeModelContent(() => {\r\n\t\t\tthis.dispatchEvent(new Event('change'));\r\n\t\t});\r\n\t};\r\n\r\n\t/*\r\n\t\tRender\r\n\t*/\r\n\r\n\trenderLightDom() {\r\n\t\treturn html`<div data-monaco-container style=\"height: ${this.height}; border: 1px solid var(--c_border); border-radius: var(--radius);\"></div>`;\r\n\t}\r\n}\r\n\r\ncustomElements.define('admin-monaco', Monaco);\r\n"],"mappings":"OAAOA,mBAAoB,gDAClBC,SAAY,2BAErB,IAAIC,kBAAoB,KAExB,MAAMC,mBAAqB,IACvBD,oBACHA,kBAAoB,IAAIE,QAAQC,IAC/B,GAAGC,OAAOC,OAET,YADAF,IAGD,MAAMG,EAASC,SAASC,cAAc,UACtCF,EAAOG,IAAM,8BACbH,EAAOI,OAAS,KACfC,QAAQC,OAAO,CAAEC,MAAO,CAAEC,GAAI,uBAC9BH,QAAQ,CAAC,yBAA0B,IAAMR,MAE1CI,SAASQ,KAAKC,YAAYV,KAEpBN,kCAGO,MAAMiB,eAAenB,eACnC,qBAAWoB,GACV,MAAO,CACNC,SAAU,CAAEC,KAAMC,QAClBC,SAAU,CAAEF,KAAMG,QAASC,UAAW,YACtCC,OAAQ,CAAEL,KAAMC,QAElB,CAEAK,GAAU,KACVC,IAAgB,EAChBC,GAAgB,GAEhB,WAAAC,GACCC,QACAC,KAAKZ,SAAW,OAChBY,KAAKT,UAAW,EAChBS,KAAKN,OAAS,OACf,CAMA,SAAIO,GACH,OAAGD,MAAKL,EAAgBK,MAAKL,EAAQO,WAC9BF,MAAKH,CACb,CAEA,SAAII,CAAME,GACNH,MAAKL,EACJK,MAAKL,EAAQO,aAAeC,GAAGH,MAAKL,EAAQS,SAASD,GAExDH,MAAKH,EAAgBM,CAEvB,CAMA,OAAAE,CAAQC,GACPP,MAAMM,QAAQC,GACVN,MAAKL,GAAYK,MAAKJ,IACzBI,MAAKJ,GAAgB,EACrBI,MAAKO,KAEHP,MAAKL,IACJW,EAAkBE,IAAI,aACxBR,MAAKL,EAAQc,cAAc,CAAElB,SAAUS,KAAKT,WAE1Ce,EAAkBE,IAAI,aACxBlC,OAAOqB,OAAOe,iBAAiBV,MAAKL,EAAQgB,WAAYX,KAAKZ,UAGhE,CAEA,oBAAAwB,GACCb,MAAMa,uBACHZ,MAAKL,IACPK,MAAKL,EAAQkB,UACbb,MAAKL,EAAU,KAEjB,CAMAY,GAAcO,gBACP5C,qBACN,MAAM6C,EAAYf,KAAKgB,cAAc,2BACrC,IAAID,EAAW,OACf,MAAME,EAA4D,SAAnDzC,SAAS0C,gBAAgBC,aAAa,UACG,SAAnD3C,SAAS0C,gBAAgBC,aAAa,UACtC9C,OAAO+C,WAAW,gCAAgCC,QACvDrB,MAAKL,EAAUrB,OAAOqB,OAAO2B,OAAOP,EAAW,CAC9Cd,MAAOD,MAAKH,EACZT,SAAUY,KAAKZ,SACfmC,QAAS,CAAEC,SAAS,GACpBC,iBAAiB,EACjBC,MAAOT,EAAS,UAAY,KAC5BU,sBAAsB,EACtBC,SAAU,GACVC,QAAS,EACTtC,SAAUS,KAAKT,WAEhBS,MAAKL,EAAQmC,wBAAwB,KACpC9B,KAAK+B,cAAc,IAAIC,MAAM,cAQ/B,cAAAC,GACC,OAAOjE,IAAI,6CAA6CgC,KAAKN,kFAC9D,EAGDwC,eAAeC,OAAO,eAAgBjD","ignoreList":[]}
|
|
@@ -135,4 +135,4 @@ import ShadowComponent from"/kempo-ui/components/ShadowComponent.js";import{html
|
|
|
135
135
|
`})}
|
|
136
136
|
</k-accordion>
|
|
137
137
|
`}}customElements.define("admin-page-editor",PageEditor);
|
|
138
|
-
//# sourceMappingURL=PageEditor.js.map
|
|
138
|
+
//# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\admin\components\PageEditor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src/admin/components/PageEditor.js","names":["ShadowComponent","html","repeat","getPage","updatePage","listTemplates","deletePages","listDirectories","movePage","Dialog","Toast","CODE_MODE_LOCATIONS","Set","slugify","name","toLowerCase","trim","replace","PageEditor","static","loading","state","error","saving","page","templates","contents","constructor","super","this","file","connectedCallback","document","addEventListener","handleKeyDown","URLSearchParams","window","location","search","get","err","tmplData","Promise","all","buildContents","template","title","disconnectedCallback","removeEventListener","getPageUrl","split","filter","Boolean","join","templateName","existingContents","tmpl","find","t","locations","label","map","l","result","block","b","content","orphaned","some","push","getFormState","root","shadowRoot","editorMap","Map","querySelectorAll","ed","dataset","getValue","querySelector","value","description","e","ctrlKey","metaKey","key","preventDefault","locked","handleSave","handleTemplateChange","newTemplate","target","currentContents","handleDelete","confirm","async","confirmed","msg","success","setTimeout","href","handleMove","dirData","directories","parts","currentName","pop","currentDir","isValidDir","p","test","includes","dirToInternal","currentDirDisplay","$dialog","create","d","alert","confirmText","confirmAction","dirInput","newName","newDir","newFile","saveError","moveError","moved","encodeURIComponent","cancelText","updatePreview","dir","prefix","textContent","classList","toggle","handleReset","saved","c","current","x","updatedAt","render","isSystem","owner","isLocked","author","pageDir","slice","reachable","tDir","directory","pDir","startsWith","currentFound","templateLabel","createdAt","Date","toLocaleString","isDefault","headerTitle","toUpperCase","has","customElements","define"],"sources":["0"],"sourcesContent":["import ShadowComponent from '/kempo-ui/components/ShadowComponent.js';\nimport { html, repeat } from '/kempo-ui/lit-all.min.js';\nimport { getPage, updatePage, listTemplates, deletePages, listDirectories, movePage } from '/kempo/sdk.js';\nimport Dialog from '/kempo-ui/components/Dialog.js';\nimport Toast from '/kempo-ui/components/Toast.js';\nimport '/kempo-ui/components/Icon.js';\nimport '/kempo-ui/components/Accordion.js';\nimport '/kempo-ui/components/HtmlEditor.js';\n\nconst CODE_MODE_LOCATIONS = new Set(['head', 'scripts']);\n\nconst slugify = name => name\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/[\\s_]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n\nexport default class PageEditor extends ShadowComponent {\n static properties = {\n loading: { state: true },\n error: { state: true },\n saving: { state: true },\n page: { state: true },\n templates: { state: true },\n contents: { state: true }\n };\n\n constructor() {\n super();\n this.loading = true;\n this.error = false;\n this.saving = false;\n this.page = null;\n this.templates = [];\n this.contents = [];\n this.file = '';\n }\n\n async connectedCallback() {\n super.connectedCallback();\n document.addEventListener('keydown', this.handleKeyDown);\n this.file = new URLSearchParams(window.location.search).get('path') + '.page.html';\n\n if (!this.file || this.file === '.page.html') {\n this.loading = false;\n this.error = true;\n return;\n }\n\n const [[err, page], [, tmplData]] = await Promise.all([\n getPage(this.file),\n listTemplates()\n ]);\n\n this.loading = false;\n\n if (err) {\n this.error = true;\n return;\n }\n\n this.templates = tmplData?.templates || [];\n this.page = page;\n this.contents = this.buildContents(page.template, page.contents);\n document.title = `Edit: ${page.name || page.title || this.file} - Admin`;\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n /*\n Helpers\n */\n\n getPageUrl() {\n const path = this.file.replace(/\\.page\\.html$/, '');\n return '/' + path.split('/').filter(Boolean).join('/');\n }\n\n buildContents(templateName, existingContents) {\n const tmpl = this.templates.find(t => t.name === templateName);\n const raw = tmpl?.locations || [{ name: 'default', label: null }];\n const locations = raw.map(l => typeof l === 'string' ? { name: l, label: null } : l);\n const result = locations.map(({ name, label }) => {\n const block = existingContents.find(b => b.location === name);\n return { location: name, label: label || null, content: block?.content || '', orphaned: false };\n });\n for (const block of existingContents) {\n if (!locations.some(l => l.name === block.location))\n result.push({ location: block.location, label: null, content: block.content, orphaned: true });\n }\n return result;\n }\n\n getFormState() {\n const root = this.shadowRoot;\n const editorMap = new Map(\n [...root.querySelectorAll('k-html-editor[data-location]')].map(ed => [ed.dataset.location, ed.getValue()])\n );\n return {\n name: root.querySelector('#metaName').value,\n title: root.querySelector('#metaTitle').value,\n description: root.querySelector('#metaDescription').value,\n template: root.querySelector('#metaTemplate').value,\n contents: this.contents.map(({ location, content, orphaned }) => ({\n location,\n content: orphaned\n ? (editorMap.get(location)?.trim() || content)\n : (editorMap.get(location) ?? content)\n }))\n };\n }\n\n /*\n Event Handlers\n */\n\n handleKeyDown = e => {\n if((e.ctrlKey || e.metaKey) && e.key === 's'){\n e.preventDefault();\n if(!this.saving && !this.page?.locked) this.handleSave();\n }\n };\n\n handleTemplateChange = e => {\n const newTemplate = e.target.value;\n const editorMap = new Map(\n [...this.shadowRoot.querySelectorAll('k-html-editor[data-location]')].map(ed => [ed.dataset.location, ed.getValue()])\n );\n // Fall back to state content for any editor that hasn't initialized (Monaco lazy-loads)\n const currentContents = this.contents.map(({ location, content }) => ({\n location,\n content: editorMap.get(location)?.trim() || content\n }));\n this.contents = this.buildContents(newTemplate, currentContents);\n this.page = { ...this.page, template: newTemplate };\n };\n\n handleDelete = () => {\n Dialog.confirm('Delete this page? This action cannot be undone.', async confirmed => {\n if (!confirmed) return;\n const [error] = await deletePages([this.file]);\n if (error) {\n Toast.error(error.msg || 'Failed to delete page');\n return;\n }\n Toast.success('Page deleted');\n setTimeout(() => { window.location.href = '/admin/pages'; }, 1000);\n });\n };\n\n handleMove = async () => {\n const [, dirData] = await listDirectories();\n const directories = dirData?.directories || ['.'];\n\n const parts = this.file.replace(/\\.page\\.html$/, '').split('/');\n const currentName = parts.pop();\n const currentDir = parts.join('/') || '.';\n\n const isValidDir = p => /^\\/[a-zA-Z0-9_\\-\\[\\]\\/]*$/.test(p) && !p.includes('..') && !p.includes('//');\n const dirToInternal = p => { const t = (p || '/').replace(/^\\//, '').replace(/\\/$/, ''); return t || '.'; };\n const currentDirDisplay = currentDir === '.' ? '/' : '/' + currentDir;\n\n const openLearnMore = () => Dialog.alert(html`\n <div class=\"p\">\n <p>Directory paths define where a page lives in the URL structure.</p>\n <p><strong>Examples:</strong></p>\n <ul>\n <li><code>/</code> — root, e.g. <code>/about</code></li>\n <li><code>/blog</code> — e.g. <code>/blog/my-post</code></li>\n <li><code>/blog/[slug]</code> — dynamic segment; <code>[slug]</code> matches any value</li>\n </ul>\n <p>Dynamic segments like <code>[token]</code> allow a single page to handle many URLs. The segment name is available to the page as a URL parameter.</p>\n <p>You can nest segments: <code>/store/[category]/[id]</code></p>\n </div>\n `, null, { title: 'About Directory Paths' });\n\n const $dialog = Dialog.create(html`\n <div class=\"p\">\n <div class=\"mb\">\n <label class=\"d-b mb-sm\"><strong>Location</strong></label>\n <input type=\"text\" id=\"dlg-move-dir\" class=\"full\" list=\"dlg-move-dir-list\" .value=\"${currentDirDisplay}\" placeholder=\"/\">\n <datalist id=\"dlg-move-dir-list\">\n ${directories.map(d => html`<option value=\"${d === '.' ? '/' : '/' + d}\">`)} \n </datalist>\n <p id=\"dlg-move-dir-error\" class=\"mt-sm tc-danger d-n\"><small>Invalid path — use format: /path/to/directory</small></p>\n <p class=\"mt-sm muted\"><small>Supports dynamic segments e.g. <code>/blog/[slug]</code>. <button class=\"link\" @click=\"${openLearnMore}\">Learn more</button></small></p>\n </div>\n <div>\n <label class=\"d-b mb-sm\"><strong>Page Name</strong></label>\n <input type=\"text\" id=\"dlg-move-name\" class=\"full\" .value=\"${currentName}\">\n <p class=\"mt-sm muted\"><small id=\"dlg-move-preview\"></small></p>\n </div>\n </div>\n `, {\n title: 'Move Page',\n confirmText: 'Save and Move Page',\n confirmAction: async () => {\n const dirInput = $dialog.querySelector('#dlg-move-dir').value.trim() || '/';\n const newName = slugify($dialog.querySelector('#dlg-move-name').value.trim());\n if (!newName) {\n Toast.error('Page name is required');\n return;\n }\n if (!isValidDir(dirInput)) {\n Toast.error('Invalid directory path');\n return;\n }\n const newDir = dirToInternal(dirInput);\n const newFile = newDir === '.'\n ? `${newName}.page.html`\n : `${newDir}/${newName}.page.html`;\n\n this.saving = true;\n const [saveError] = await updatePage({ file: this.file, ...this.getFormState() });\n this.saving = false;\n if (saveError) {\n Toast.error(saveError.msg || 'Failed to save page');\n return;\n }\n\n const [moveError, moved] = await movePage({ file: this.file, newFile });\n if (moveError) {\n Toast.error(moveError.msg || 'Failed to move page');\n return;\n }\n\n Toast.success('Page saved and moved');\n setTimeout(() => {\n window.location.href = `/admin/pages/edit?path=${encodeURIComponent(moved.file.replace(/\\.page\\.html$/, ''))}`;\n }, 1000);\n },\n cancelText: 'Cancel'\n });\n\n const updatePreview = () => {\n const dir = dirToInternal($dialog.querySelector('#dlg-move-dir').value || '/');\n const name = slugify($dialog.querySelector('#dlg-move-name').value);\n const prefix = dir === '.' ? '/' : '/' + dir + '/';\n $dialog.querySelector('#dlg-move-preview').textContent = name ? prefix + name : '';\n };\n $dialog.querySelector('#dlg-move-dir').addEventListener('input', e => {\n $dialog.querySelector('#dlg-move-dir-error').classList.toggle('d-n', isValidDir(e.target.value || '/'));\n updatePreview();\n });\n $dialog.querySelector('#dlg-move-name').addEventListener('input', updatePreview);\n updatePreview();\n };\n\n handleReset = () => {\n Dialog.confirm('Reset this page? Any unsaved changes will be lost.', confirmed => {\n if (!confirmed) return;\n this.contents = this.buildContents(this.page.template, this.page.contents);\n this.page = { ...this.page };\n });\n };\n\n handleSave = async () => {\n this.saving = true;\n const state = this.getFormState();\n const [saveError, saved] = await updatePage({ file: this.file, ...state });\n this.saving = false;\n\n if (saveError) {\n Toast.error(saveError.msg || 'Failed to save page');\n return;\n }\n\n this.contents = this.contents.map(c => {\n const current = state.contents.find(x => x.location === c.location);\n return current ? { ...c, content: current.content } : c;\n });\n this.page = {\n ...this.page,\n ...state,\n contents: state.contents.filter(b => b.content.trim()),\n updatedAt: saved.updatedAt\n };\n\n document.title = `Edit: ${state.name || state.title || this.file} - Admin`;\n Toast.success('Page saved');\n };\n\n /*\n Render\n */\n\n render() {\n if (this.loading) return html`<div>Loading page...</div>`;\n\n if (this.error) return html`\n <div>\n <p>Page not found.</p>\n <a href=\"/admin/pages\">Back to Pages</a>\n </div>\n `;\n\n const { page, templates, contents } = this;\n const isSystem = page.owner === 'system';\n const isLocked = page.locked;\n\n return html`\n ${isLocked ? html`\n <div class=\"p r mb bc-warning tc-warning\">\n <k-icon name=\"lock\"></k-icon> This page is locked and cannot be edited. It is managed by an extension.\n </div>\n ` : ''}\n <div class=\"d-f mb\">\n <div class=\"btn-grp mrh mb\">\n <a href=\"/admin/content/pages\" class=\"btn\">\n <k-icon name=\"arrow\" direction=\"left\"></k-icon> Pages\n </a>\n <a href=\"${this.getPageUrl()}\" id=\"page-link\" class=\"btn\">\n <k-icon name=\"visibility\"></k-icon> View Page\n </a>\n </div>\n \n <div class=\"flex\"></div>\n ${!isSystem && !isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button class=\"danger\" @click=\"${this.handleDelete}\"><k-icon name=\"delete\"></k-icon> Delete</button>\n <button @click=\"${this.handleMove}\"><k-icon name=\"drive_file_move\"></k-icon> Move Page</button>\n </div>\n ` : ''}\n ${!isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button @click=\"${this.handleReset}\"><k-icon name=\"restart_alt\"></k-icon> Reset</button>\n <button id=\"saveBtn\" class=\"primary\" ?disabled=\"${this.saving}\" @click=\"${this.handleSave}\">\n <k-icon name=\"save\"></k-icon> Save\n </button>\n </div>\n ` : ''}\n </div>\n <h1 class=\"mb0\">Page: ${page.name || page.title || this.file}</h1>\n\n <a href=\"${this.getPageUrl()}\" class=\"d-b mb\"><code>${this.getPageUrl()}</code></a>\n\n <k-accordion>\n <k-accordion-header for-panel=\"metadata\">Metadata</k-accordion-header>\n <k-accordion-panel name=\"metadata\">\n <div class=\"p\">\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Name</strong></label>\n <input type=\"text\" id=\"metaName\" class=\"flex\" .value=\"${page.name || ''}\" ?disabled=\"${isSystem || isLocked}\">\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Title</strong></label>\n <input type=\"text\" id=\"metaTitle\" class=\"flex\" .value=\"${page.title || ''}\" ?disabled=\"${isLocked}\">\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Description</strong></label>\n <input type=\"text\" id=\"metaDescription\" class=\"flex\" .value=\"${page.description || ''}\" ?disabled=\"${isSystem || isLocked}\">\n </div>\n ${!isSystem ? html`\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Author</strong></label>\n <span class=\"muted\">${page.author || ''}</span>\n </div>\n ` : ''}\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Template</strong></label>\n ${(() => {\n const pageDir = this.file.replace(/\\.page\\.html$/, '').split('/').slice(0, -1).join('/') || '.';\n const reachable = templates.filter(t => {\n const tDir = t.directory === '.' ? '' : t.directory;\n const pDir = pageDir === '.' ? '' : pageDir;\n return tDir === '' || pDir === tDir || pDir.startsWith(tDir + '/');\n });\n const templateLabel = t => t.directory === '.' ? `/${t.name}` : `/${t.directory}/${t.name}`;\n const currentFound = reachable.some(t => t.name === page.template);\n return html`\n <select id=\"metaTemplate\" class=\"flex\" @change=\"${this.handleTemplateChange}\" ?disabled=\"${isLocked}\">\n ${!currentFound ? html`<option value=\"${page.template}\" selected>${page.template} (Not Found, using default)</option>` : ''}\n ${reachable.map(t => html`\n <option value=\"${t.name}\" ?selected=\"${t.name === page.template}\">${templateLabel(t)}</option>\n `)}\n </select>\n `;\n })()}\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Owner</strong></label>\n <span class=\"muted\">${page.owner || ''}</span>\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Created</strong></label>\n <span class=\"muted\">${page.createdAt ? new Date(page.createdAt).toLocaleString() : ''}</span>\n </div>\n <div class=\"d-f\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Updated</strong></label>\n <span class=\"muted\">${page.updatedAt ? new Date(page.updatedAt).toLocaleString() : ''}</span>\n </div>\n </div>\n </k-accordion-panel>\n ${repeat(contents, c => c.location, ({ location, label, content, orphaned }) => {\n const isDefault = location === 'default';\n const headerTitle = label || (isDefault ? 'Content' : location.slice(0, 1).toUpperCase() + location.slice(1));\n return html`\n <k-accordion-header for-panel=\"content-${location}\" ?active=\"${isDefault}\">\n ${headerTitle}${orphaned ? html` <span class=\"tc-warning\"><small>(not in template)</small></span>` : ''}\n </k-accordion-header>\n <k-accordion-panel name=\"content-${location}\" ?active=\"${isDefault}\">\n <div class=\"p\">\n <k-html-editor\n class=\"r b\"\n data-location=\"${location}\"\n controls=\"full\"\n .value=\"${content}\"\n mode=\"${CODE_MODE_LOCATIONS.has(location) ? 'code' : 'visual'}\"\n style=\"height: 400px;\"\n ?disabled=\"${isLocked}\"\n ></k-html-editor>\n </div>\n </k-accordion-panel>\n `;\n })}\n </k-accordion>\n `;\n }\n}\n\ncustomElements.define('admin-page-editor', PageEditor);\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"src\\admin\\components\\PageEditor.js","names":["ShadowComponent","html","repeat","getPage","updatePage","listTemplates","deletePages","listDirectories","movePage","Dialog","Toast","CODE_MODE_LOCATIONS","Set","slugify","name","toLowerCase","trim","replace","PageEditor","static","loading","state","error","saving","page","templates","contents","constructor","super","this","file","connectedCallback","document","addEventListener","handleKeyDown","URLSearchParams","window","location","search","get","err","tmplData","Promise","all","buildContents","template","title","disconnectedCallback","removeEventListener","getPageUrl","split","filter","Boolean","join","templateName","existingContents","tmpl","find","t","locations","label","map","l","result","block","b","content","orphaned","some","push","getFormState","root","shadowRoot","editorMap","Map","querySelectorAll","ed","dataset","getValue","querySelector","value","description","e","ctrlKey","metaKey","key","preventDefault","locked","handleSave","handleTemplateChange","newTemplate","target","currentContents","handleDelete","confirm","async","confirmed","msg","success","setTimeout","href","handleMove","dirData","directories","parts","currentName","pop","currentDir","isValidDir","p","test","includes","dirToInternal","currentDirDisplay","$dialog","create","d","alert","confirmText","confirmAction","dirInput","newName","newDir","newFile","saveError","moveError","moved","encodeURIComponent","cancelText","updatePreview","dir","prefix","textContent","classList","toggle","handleReset","saved","c","current","x","updatedAt","render","isSystem","owner","isLocked","author","pageDir","slice","reachable","tDir","directory","pDir","startsWith","currentFound","templateLabel","createdAt","Date","toLocaleString","isDefault","headerTitle","toUpperCase","has","customElements","define"],"sources":["0"],"sourcesContent":["import ShadowComponent from '/kempo-ui/components/ShadowComponent.js';\nimport { html, repeat } from '/kempo-ui/lit-all.min.js';\nimport { getPage, updatePage, listTemplates, deletePages, listDirectories, movePage } from '/kempo/sdk.js';\nimport Dialog from '/kempo-ui/components/Dialog.js';\nimport Toast from '/kempo-ui/components/Toast.js';\nimport '/kempo-ui/components/Icon.js';\nimport '/kempo-ui/components/Accordion.js';\nimport '/kempo-ui/components/HtmlEditor.js';\n\nconst CODE_MODE_LOCATIONS = new Set(['head', 'scripts']);\n\nconst slugify = name => name\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/[\\s_]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n\nexport default class PageEditor extends ShadowComponent {\n static properties = {\n loading: { state: true },\n error: { state: true },\n saving: { state: true },\n page: { state: true },\n templates: { state: true },\n contents: { state: true }\n };\n\n constructor() {\n super();\n this.loading = true;\n this.error = false;\n this.saving = false;\n this.page = null;\n this.templates = [];\n this.contents = [];\n this.file = '';\n }\n\n async connectedCallback() {\n super.connectedCallback();\n document.addEventListener('keydown', this.handleKeyDown);\n this.file = new URLSearchParams(window.location.search).get('path') + '.page.html';\n\n if (!this.file || this.file === '.page.html') {\n this.loading = false;\n this.error = true;\n return;\n }\n\n const [[err, page], [, tmplData]] = await Promise.all([\n getPage(this.file),\n listTemplates()\n ]);\n\n this.loading = false;\n\n if (err) {\n this.error = true;\n return;\n }\n\n this.templates = tmplData?.templates || [];\n this.page = page;\n this.contents = this.buildContents(page.template, page.contents);\n document.title = `Edit: ${page.name || page.title || this.file} - Admin`;\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n /*\n Helpers\n */\n\n getPageUrl() {\n const path = this.file.replace(/\\.page\\.html$/, '');\n return '/' + path.split('/').filter(Boolean).join('/');\n }\n\n buildContents(templateName, existingContents) {\n const tmpl = this.templates.find(t => t.name === templateName);\n const raw = tmpl?.locations || [{ name: 'default', label: null }];\n const locations = raw.map(l => typeof l === 'string' ? { name: l, label: null } : l);\n const result = locations.map(({ name, label }) => {\n const block = existingContents.find(b => b.location === name);\n return { location: name, label: label || null, content: block?.content || '', orphaned: false };\n });\n for (const block of existingContents) {\n if (!locations.some(l => l.name === block.location))\n result.push({ location: block.location, label: null, content: block.content, orphaned: true });\n }\n return result;\n }\n\n getFormState() {\n const root = this.shadowRoot;\n const editorMap = new Map(\n [...root.querySelectorAll('k-html-editor[data-location]')].map(ed => [ed.dataset.location, ed.getValue()])\n );\n return {\n name: root.querySelector('#metaName').value,\n title: root.querySelector('#metaTitle').value,\n description: root.querySelector('#metaDescription').value,\n template: root.querySelector('#metaTemplate').value,\n contents: this.contents.map(({ location, content, orphaned }) => ({\n location,\n content: orphaned\n ? (editorMap.get(location)?.trim() || content)\n : (editorMap.get(location) ?? content)\n }))\n };\n }\n\n /*\n Event Handlers\n */\n\n handleKeyDown = e => {\n if((e.ctrlKey || e.metaKey) && e.key === 's'){\n e.preventDefault();\n if(!this.saving && !this.page?.locked) this.handleSave();\n }\n };\n\n handleTemplateChange = e => {\n const newTemplate = e.target.value;\n const editorMap = new Map(\n [...this.shadowRoot.querySelectorAll('k-html-editor[data-location]')].map(ed => [ed.dataset.location, ed.getValue()])\n );\n // Fall back to state content for any editor that hasn't initialized (Monaco lazy-loads)\n const currentContents = this.contents.map(({ location, content }) => ({\n location,\n content: editorMap.get(location)?.trim() || content\n }));\n this.contents = this.buildContents(newTemplate, currentContents);\n this.page = { ...this.page, template: newTemplate };\n };\n\n handleDelete = () => {\n Dialog.confirm('Delete this page? This action cannot be undone.', async confirmed => {\n if (!confirmed) return;\n const [error] = await deletePages([this.file]);\n if (error) {\n Toast.error(error.msg || 'Failed to delete page');\n return;\n }\n Toast.success('Page deleted');\n setTimeout(() => { window.location.href = '/admin/pages'; }, 1000);\n });\n };\n\n handleMove = async () => {\n const [, dirData] = await listDirectories();\n const directories = dirData?.directories || ['.'];\n\n const parts = this.file.replace(/\\.page\\.html$/, '').split('/');\n const currentName = parts.pop();\n const currentDir = parts.join('/') || '.';\n\n const isValidDir = p => /^\\/[a-zA-Z0-9_\\-\\[\\]\\/]*$/.test(p) && !p.includes('..') && !p.includes('//');\n const dirToInternal = p => { const t = (p || '/').replace(/^\\//, '').replace(/\\/$/, ''); return t || '.'; };\n const currentDirDisplay = currentDir === '.' ? '/' : '/' + currentDir;\n\n const openLearnMore = () => Dialog.alert(html`\n <div class=\"p\">\n <p>Directory paths define where a page lives in the URL structure.</p>\n <p><strong>Examples:</strong></p>\n <ul>\n <li><code>/</code> — root, e.g. <code>/about</code></li>\n <li><code>/blog</code> — e.g. <code>/blog/my-post</code></li>\n <li><code>/blog/[slug]</code> — dynamic segment; <code>[slug]</code> matches any value</li>\n </ul>\n <p>Dynamic segments like <code>[token]</code> allow a single page to handle many URLs. The segment name is available to the page as a URL parameter.</p>\n <p>You can nest segments: <code>/store/[category]/[id]</code></p>\n </div>\n `, null, { title: 'About Directory Paths' });\n\n const $dialog = Dialog.create(html`\n <div class=\"p\">\n <div class=\"mb\">\n <label class=\"d-b mb-sm\"><strong>Location</strong></label>\n <input type=\"text\" id=\"dlg-move-dir\" class=\"full\" list=\"dlg-move-dir-list\" .value=\"${currentDirDisplay}\" placeholder=\"/\">\n <datalist id=\"dlg-move-dir-list\">\n ${directories.map(d => html`<option value=\"${d === '.' ? '/' : '/' + d}\">`)} \n </datalist>\n <p id=\"dlg-move-dir-error\" class=\"mt-sm tc-danger d-n\"><small>Invalid path — use format: /path/to/directory</small></p>\n <p class=\"mt-sm muted\"><small>Supports dynamic segments e.g. <code>/blog/[slug]</code>. <button class=\"link\" @click=\"${openLearnMore}\">Learn more</button></small></p>\n </div>\n <div>\n <label class=\"d-b mb-sm\"><strong>Page Name</strong></label>\n <input type=\"text\" id=\"dlg-move-name\" class=\"full\" .value=\"${currentName}\">\n <p class=\"mt-sm muted\"><small id=\"dlg-move-preview\"></small></p>\n </div>\n </div>\n `, {\n title: 'Move Page',\n confirmText: 'Save and Move Page',\n confirmAction: async () => {\n const dirInput = $dialog.querySelector('#dlg-move-dir').value.trim() || '/';\n const newName = slugify($dialog.querySelector('#dlg-move-name').value.trim());\n if (!newName) {\n Toast.error('Page name is required');\n return;\n }\n if (!isValidDir(dirInput)) {\n Toast.error('Invalid directory path');\n return;\n }\n const newDir = dirToInternal(dirInput);\n const newFile = newDir === '.'\n ? `${newName}.page.html`\n : `${newDir}/${newName}.page.html`;\n\n this.saving = true;\n const [saveError] = await updatePage({ file: this.file, ...this.getFormState() });\n this.saving = false;\n if (saveError) {\n Toast.error(saveError.msg || 'Failed to save page');\n return;\n }\n\n const [moveError, moved] = await movePage({ file: this.file, newFile });\n if (moveError) {\n Toast.error(moveError.msg || 'Failed to move page');\n return;\n }\n\n Toast.success('Page saved and moved');\n setTimeout(() => {\n window.location.href = `/admin/pages/edit?path=${encodeURIComponent(moved.file.replace(/\\.page\\.html$/, ''))}`;\n }, 1000);\n },\n cancelText: 'Cancel'\n });\n\n const updatePreview = () => {\n const dir = dirToInternal($dialog.querySelector('#dlg-move-dir').value || '/');\n const name = slugify($dialog.querySelector('#dlg-move-name').value);\n const prefix = dir === '.' ? '/' : '/' + dir + '/';\n $dialog.querySelector('#dlg-move-preview').textContent = name ? prefix + name : '';\n };\n $dialog.querySelector('#dlg-move-dir').addEventListener('input', e => {\n $dialog.querySelector('#dlg-move-dir-error').classList.toggle('d-n', isValidDir(e.target.value || '/'));\n updatePreview();\n });\n $dialog.querySelector('#dlg-move-name').addEventListener('input', updatePreview);\n updatePreview();\n };\n\n handleReset = () => {\n Dialog.confirm('Reset this page? Any unsaved changes will be lost.', confirmed => {\n if (!confirmed) return;\n this.contents = this.buildContents(this.page.template, this.page.contents);\n this.page = { ...this.page };\n });\n };\n\n handleSave = async () => {\n this.saving = true;\n const state = this.getFormState();\n const [saveError, saved] = await updatePage({ file: this.file, ...state });\n this.saving = false;\n\n if (saveError) {\n Toast.error(saveError.msg || 'Failed to save page');\n return;\n }\n\n this.contents = this.contents.map(c => {\n const current = state.contents.find(x => x.location === c.location);\n return current ? { ...c, content: current.content } : c;\n });\n this.page = {\n ...this.page,\n ...state,\n contents: state.contents.filter(b => b.content.trim()),\n updatedAt: saved.updatedAt\n };\n\n document.title = `Edit: ${state.name || state.title || this.file} - Admin`;\n Toast.success('Page saved');\n };\n\n /*\n Render\n */\n\n render() {\n if (this.loading) return html`<div>Loading page...</div>`;\n\n if (this.error) return html`\n <div>\n <p>Page not found.</p>\n <a href=\"/admin/pages\">Back to Pages</a>\n </div>\n `;\n\n const { page, templates, contents } = this;\n const isSystem = page.owner === 'system';\n const isLocked = page.locked;\n\n return html`\n ${isLocked ? html`\n <div class=\"p r mb bc-warning tc-warning\">\n <k-icon name=\"lock\"></k-icon> This page is locked and cannot be edited. It is managed by an extension.\n </div>\n ` : ''}\n <div class=\"d-f mb\">\n <div class=\"btn-grp mrh mb\">\n <a href=\"/admin/content/pages\" class=\"btn\">\n <k-icon name=\"arrow\" direction=\"left\"></k-icon> Pages\n </a>\n <a href=\"${this.getPageUrl()}\" id=\"page-link\" class=\"btn\">\n <k-icon name=\"visibility\"></k-icon> View Page\n </a>\n </div>\n \n <div class=\"flex\"></div>\n ${!isSystem && !isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button class=\"danger\" @click=\"${this.handleDelete}\"><k-icon name=\"delete\"></k-icon> Delete</button>\n <button @click=\"${this.handleMove}\"><k-icon name=\"drive_file_move\"></k-icon> Move Page</button>\n </div>\n ` : ''}\n ${!isLocked ? html`\n <div class=\"btn-grp mrh mb\">\n <button @click=\"${this.handleReset}\"><k-icon name=\"restart_alt\"></k-icon> Reset</button>\n <button id=\"saveBtn\" class=\"primary\" ?disabled=\"${this.saving}\" @click=\"${this.handleSave}\">\n <k-icon name=\"save\"></k-icon> Save\n </button>\n </div>\n ` : ''}\n </div>\n <h1 class=\"mb0\">Page: ${page.name || page.title || this.file}</h1>\n\n <a href=\"${this.getPageUrl()}\" class=\"d-b mb\"><code>${this.getPageUrl()}</code></a>\n\n <k-accordion>\n <k-accordion-header for-panel=\"metadata\">Metadata</k-accordion-header>\n <k-accordion-panel name=\"metadata\">\n <div class=\"p\">\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Name</strong></label>\n <input type=\"text\" id=\"metaName\" class=\"flex\" .value=\"${page.name || ''}\" ?disabled=\"${isSystem || isLocked}\">\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Title</strong></label>\n <input type=\"text\" id=\"metaTitle\" class=\"flex\" .value=\"${page.title || ''}\" ?disabled=\"${isLocked}\">\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Description</strong></label>\n <input type=\"text\" id=\"metaDescription\" class=\"flex\" .value=\"${page.description || ''}\" ?disabled=\"${isSystem || isLocked}\">\n </div>\n ${!isSystem ? html`\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Author</strong></label>\n <span class=\"muted\">${page.author || ''}</span>\n </div>\n ` : ''}\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Template</strong></label>\n ${(() => {\n const pageDir = this.file.replace(/\\.page\\.html$/, '').split('/').slice(0, -1).join('/') || '.';\n const reachable = templates.filter(t => {\n const tDir = t.directory === '.' ? '' : t.directory;\n const pDir = pageDir === '.' ? '' : pageDir;\n return tDir === '' || pDir === tDir || pDir.startsWith(tDir + '/');\n });\n const templateLabel = t => t.directory === '.' ? `/${t.name}` : `/${t.directory}/${t.name}`;\n const currentFound = reachable.some(t => t.name === page.template);\n return html`\n <select id=\"metaTemplate\" class=\"flex\" @change=\"${this.handleTemplateChange}\" ?disabled=\"${isLocked}\">\n ${!currentFound ? html`<option value=\"${page.template}\" selected>${page.template} (Not Found, using default)</option>` : ''}\n ${reachable.map(t => html`\n <option value=\"${t.name}\" ?selected=\"${t.name === page.template}\">${templateLabel(t)}</option>\n `)}\n </select>\n `;\n })()}\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Owner</strong></label>\n <span class=\"muted\">${page.owner || ''}</span>\n </div>\n <div class=\"d-f mb\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Created</strong></label>\n <span class=\"muted\">${page.createdAt ? new Date(page.createdAt).toLocaleString() : ''}</span>\n </div>\n <div class=\"d-f\" style=\"align-items: center; gap: var(--spacer);\">\n <label style=\"min-width: 120px;\"><strong>Updated</strong></label>\n <span class=\"muted\">${page.updatedAt ? new Date(page.updatedAt).toLocaleString() : ''}</span>\n </div>\n </div>\n </k-accordion-panel>\n ${repeat(contents, c => c.location, ({ location, label, content, orphaned }) => {\n const isDefault = location === 'default';\n const headerTitle = label || (isDefault ? 'Content' : location.slice(0, 1).toUpperCase() + location.slice(1));\n return html`\n <k-accordion-header for-panel=\"content-${location}\" ?active=\"${isDefault}\">\n ${headerTitle}${orphaned ? html` <span class=\"tc-warning\"><small>(not in template)</small></span>` : ''}\n </k-accordion-header>\n <k-accordion-panel name=\"content-${location}\" ?active=\"${isDefault}\">\n <div class=\"p\">\n <k-html-editor\n class=\"r b\"\n data-location=\"${location}\"\n controls=\"full\"\n .value=\"${content}\"\n mode=\"${CODE_MODE_LOCATIONS.has(location) ? 'code' : 'visual'}\"\n style=\"height: 400px;\"\n ?disabled=\"${isLocked}\"\n ></k-html-editor>\n </div>\n </k-accordion-panel>\n `;\n })}\n </k-accordion>\n `;\n }\n}\n\ncustomElements.define('admin-page-editor', PageEditor);\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import{html}from"/kempo-ui/lit-all.min.js";import TableControl from"/kempo-ui/components/tableControls/TableControl.js";import Dialog from"/kempo-ui/components/Dialog.js";import Toast from"/kempo-ui/components/Toast.js";import"/kempo-ui/components/Icon.js";export default class TableRowDelete extends TableControl{static properties={maxWidth:{type:Number,attribute:"max-width"},sdkMethod:{type:String,attribute:"sdk-method"},primaryKey:{type:String,attribute:"primary-key"}};constructor(){super(),this.maxWidth=40,this.sdkMethod="deleteUsers",this.idField="id"}delete=()=>{this.record&&Dialog.confirm("Are you sure you want to delete this record? This action cannot be undone.",async e=>{if(!e)return;const t=(await import("../../kempo/sdk.js"))[this.sdkMethod];if(!t)return void Toast.error("Delete method not found");const[o,r]=await t([this.record[this.primaryKey]]);o?Toast.error(o.msg||"Failed to delete record"):(this.table.deleteRecord(this.record),Toast.success("Record deleted successfully"))})};render(){return html`<button class="no-btn icon-btn" @click="${this.delete}">
|
|
2
2
|
<slot><k-icon name="delete"></k-icon></slot>
|
|
3
3
|
</button>`}}customElements.define("admin-table-row-delete",TableRowDelete);
|
|
4
|
-
//# sourceMappingURL=TableRowDelete.js.map
|
|
4
|
+
//# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\admin\components\TableRowDelete.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src
|
|
1
|
+
{"version":3,"file":"src\\admin\\components\\TableRowDelete.js","names":["html","TableControl","Dialog","Toast","TableRowDelete","static","maxWidth","type","Number","attribute","sdkMethod","String","primaryKey","constructor","super","this","idField","delete","record","confirm","async","confirmed","deleteMethod","import","error","result","msg","table","deleteRecord","success","render","customElements","define"],"sources":["0"],"sourcesContent":["import { html } from '/kempo-ui/lit-all.min.js';\r\nimport TableControl from '/kempo-ui/components/tableControls/TableControl.js';\r\nimport Dialog from '/kempo-ui/components/Dialog.js';\r\nimport Toast from '/kempo-ui/components/Toast.js';\r\nimport '/kempo-ui/components/Icon.js';\r\n\r\nexport default class TableRowDelete extends TableControl {\r\n static properties = {\r\n maxWidth: { type: Number, attribute: 'max-width' },\r\n sdkMethod: { type: String, attribute: 'sdk-method' },\r\n primaryKey: { type: String, attribute: 'primary-key' }\r\n };\r\n\r\n constructor(){\r\n super();\r\n this.maxWidth = 40;\r\n this.sdkMethod = 'deleteUsers';\r\n this.idField = 'id';\r\n }\r\n\r\n delete = () => {\r\n if(!this.record) return;\r\n\r\n Dialog.confirm('Are you sure you want to delete this record? This action cannot be undone.', async (confirmed) => {\r\n if(!confirmed) return;\r\n\r\n const module = await import('../../kempo/sdk.js');\r\n const deleteMethod = module[this.sdkMethod];\r\n\r\n if(!deleteMethod){\r\n Toast.error('Delete method not found');\r\n return;\r\n }\r\n\r\n const [error, result] = await deleteMethod([this.record[this.primaryKey]]);\r\n\r\n if(error){\r\n Toast.error(error.msg || 'Failed to delete record');\r\n return;\r\n }\r\n\r\n this.table.deleteRecord(this.record);\r\n Toast.success('Record deleted successfully');\r\n });\r\n };\r\n\r\n render(){\r\n return html`<button class=\"no-btn icon-btn\" @click=\"${this.delete}\">\r\n <slot><k-icon name=\"delete\"></k-icon></slot>\r\n </button>`;\r\n }\r\n}\r\n\r\ncustomElements.define('admin-table-row-delete', TableRowDelete);\r\n"],"mappings":"OAASA,SAAY,kCACdC,iBAAkB,4DAClBC,WAAY,wCACZC,UAAW,sCACX,8CAEQ,MAAMC,uBAAuBH,aAC1CI,kBAAoB,CAClBC,SAAU,CAAEC,KAAMC,OAAQC,UAAW,aACrCC,UAAW,CAAEH,KAAMI,OAAQF,UAAW,cACtCG,WAAY,CAAEL,KAAMI,OAAQF,UAAW,gBAGzC,WAAAI,GACEC,QACAC,KAAKT,SAAW,GAChBS,KAAKL,UAAY,cACjBK,KAAKC,QAAU,IACjB,CAEAC,OAAS,KACHF,KAAKG,QAEThB,OAAOiB,QAAQ,6EAA8EC,MAAOC,IAClG,IAAIA,EAAW,OAEf,MACMC,SADeC,OAAO,uBACAR,KAAKL,WAEjC,IAAIY,EAEF,YADAnB,MAAMqB,MAAM,2BAId,MAAOA,EAAOC,SAAgBH,EAAa,CAACP,KAAKG,OAAOH,KAAKH,cAE1DY,EACDrB,MAAMqB,MAAMA,EAAME,KAAO,4BAI3BX,KAAKY,MAAMC,aAAab,KAAKG,QAC7Bf,MAAM0B,QAAQ,mCAIlB,MAAAC,GACE,OAAO9B,IAAI,2CAA2Ce,KAAKE;;cAG7D,EAGFc,eAAeC,OAAO,yBAA0B5B","ignoreList":[]}
|
|
@@ -5,4 +5,4 @@ import TableControl from"/kempo-ui/components/tableControls/TableControl.js";imp
|
|
|
5
5
|
</slot>
|
|
6
6
|
</button>
|
|
7
7
|
`}}customElements.define("admin-table-row-link",TableRowLink);
|
|
8
|
-
//# sourceMappingURL=TableRowLink.js.map
|
|
8
|
+
//# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\admin\components\TableRowLink.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src
|
|
1
|
+
{"version":3,"file":"src\\admin\\components\\TableRowLink.js","names":["TableControl","html","TableRowLink","properties","urlPattern","type","String","attribute","fieldName","constructor","super","this","maxWidth","navigate","record","fieldValue","url","replace","window","location","href","render","customElements","define"],"sources":["0"],"sourcesContent":["import TableControl from '/kempo-ui/components/tableControls/TableControl.js';\r\nimport { html } from '/kempo-ui/lit-all.min.js';\r\nimport '/kempo-ui/components/Icon.js';\r\n\r\nexport default class TableRowLink extends TableControl {\r\n static get properties() {\r\n return {\r\n urlPattern: { type: String, attribute: 'url-pattern' },\r\n fieldName: { type: String, attribute: 'field-name' }\r\n };\r\n }\r\n\r\n constructor() {\r\n super();\r\n this.fieldName = 'id';\r\n this.maxWidth = 40;\r\n }\r\n\r\n navigate = () => {\r\n if(!this.record) return;\r\n\r\n const fieldValue = this.record[this.fieldName];\r\n if(!fieldValue) return;\r\n\r\n const url = this.urlPattern.replace(`{${this.fieldName}}`, fieldValue);\r\n window.location.href = url;\r\n };\r\n\r\n render() {\r\n return html`\r\n <button class=\"no-btn icon-btn\" @click=\"${this.navigate}\">\r\n <slot>\r\n <k-icon name=\"visibility\"></k-icon>\r\n </slot>\r\n </button>\r\n `;\r\n }\r\n}\r\n\r\ncustomElements.define('admin-table-row-link', TableRowLink);\r\n\r\n"],"mappings":"OAAOA,iBAAkB,4DAChBC,SAAY,iCACd,8CAEQ,MAAMC,qBAAqBF,aACxC,qBAAWG,GACT,MAAO,CACLC,WAAY,CAAEC,KAAMC,OAAQC,UAAW,eACvCC,UAAW,CAAEH,KAAMC,OAAQC,UAAW,cAE1C,CAEA,WAAAE,GACEC,QACAC,KAAKH,UAAY,KACjBG,KAAKC,SAAW,EAClB,CAEAC,SAAW,KACT,IAAIF,KAAKG,OAAQ,OAEjB,MAAMC,EAAaJ,KAAKG,OAAOH,KAAKH,WACpC,IAAIO,EAAY,OAEhB,MAAMC,EAAML,KAAKP,WAAWa,QAAQ,IAAIN,KAAKH,aAAcO,GAC3DG,OAAOC,SAASC,KAAOJ,GAGzB,MAAAK,GACE,OAAOpB,IAAI;gDACiCU,KAAKE;;;;;KAMnD,EAGFS,eAAeC,OAAO,uBAAwBrB","ignoreList":[]}
|
|
@@ -122,4 +122,4 @@ import ShadowComponent from"/kempo-ui/components/ShadowComponent.js";import{html
|
|
|
122
122
|
</k-accordion-panel>
|
|
123
123
|
</k-accordion>
|
|
124
124
|
`}}customElements.define("admin-template-editor",TemplateEditor);
|
|
125
|
-
//# sourceMappingURL=TemplateEditor.js.map
|
|
125
|
+
//# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\admin\components\TemplateEditor.js.map
|