diff --git a/package.json b/package.json
index 40e0ac7..e00e6f0 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "@json.ms/www",
"private": true,
"type": "module",
- "version": "1.2.13",
+ "version": "1.2.15",
"scripts": {
"dev": "vite --host",
"build": "run-p type-check \"build-only {@}\" --",
diff --git a/src/components/Integration.vue b/src/components/Integration.vue
index fd6157f..dd76073 100644
--- a/src/components/Integration.vue
+++ b/src/components/Integration.vue
@@ -44,8 +44,7 @@ ${prefix}JMS_ENCRYPTED_SECRET_KEY=${modelStore.structure.server_secret}`;
-
-
+
Integration Guide
diff --git a/src/components/JSONms.vue b/src/components/JSONms.vue
index b6c7565..e92d568 100644
--- a/src/components/JSONms.vue
+++ b/src/components/JSONms.vue
@@ -22,10 +22,8 @@ import {useShortcut} from '@/composables/shortcut';
import {deepToRaw, getStructure} from '@/utils';
import NewStructureModal from '@/components/NewStructureModal.vue';
import type {VForm} from 'vuetify/components';
-import Settings from '@/components/Settings.vue';
import Docs from '@/components/Docs.vue';
import FileManager from '@/components/FileManager.vue';
-import Integration from '@/components/Integration.vue';
import {useModelStore} from '@/stores/model';
import structureMd from "../../docs/structure.md";
@@ -155,7 +153,7 @@ const onApplyNewStructure = (template: string) => {
const onSaveStructure = () => {
if (canSaveStructure.value) {
- modelStore.structure.content = modelStore.temporaryContent;
+ modelStore.structure.content = modelStore.temporaryContent || modelStore.structure.content;
saveStructure().then(() => {
bottomSheetData.value = { text: 'Structure saved!', color: 'success', icon: 'mdi-check' };
syncToFolder(modelStore.structure, 'typescript', ['structure', 'default', 'typings', 'settings', 'index']);
@@ -396,33 +394,22 @@ if (globalStore.session.loggedIn) {
ref="form"
class="fill-height"
>
-
-
-
-
+
+
+
+
Data
-
-
-
- Settings
-
- mdi-alert
-
-
-
-
- Integration
-
-
-
- Docs
-
-
-
-
+
+
+ Docs
+
+
+
+
+
-
-
-
-
-
-
diff --git a/src/components/StructureEditor.vue b/src/components/StructureEditor.vue
index 5b96ce2..b30fdf9 100644
--- a/src/components/StructureEditor.vue
+++ b/src/components/StructureEditor.vue
@@ -5,6 +5,8 @@ import type { VAceEditorInstance } from 'vue3-ace-editor/types';
import type {IStructure, IStructureData} from '@/interfaces';
import TriggerMenu from '@/components/TriggerMenu.vue';
import {useStructure} from '@/composables/structure';
+import Settings from '@/components/Settings.vue';
+import Integration from '@/components/Integration.vue';
import '@/plugins/aceeditor';
import {useGlobalStore} from '@/stores/global';
import {useTypings} from "@/composables/typings";
@@ -32,6 +34,8 @@ const blueprintTypings = ref('')
const blueprintDefault = ref('')
const blueprintLanguage = ref<'typescript' | 'php'>('typescript')
+const sectionMenu = ref(false);
+
const tab = computed({
get: () => {
return globalStore.admin.structure ? globalStore.admin.editorTab : 'structure';
@@ -43,6 +47,47 @@ const tab = computed({
},
})
+const setSection = (section: any) => {
+ globalStore.admin.editorTab = section.key;
+ sectionMenu.value = false;
+}
+
+const selectedSection = computed(() => {
+ const selected = sections.value.find(item => item.key === globalStore.admin.editorTab) || sections.value[0];
+ if (selected.disabled()) {
+ return sections.value[0];
+ }
+ return selected;
+})
+
+const sections = ref([{
+ key: 'structure',
+ icon: 'mdi-invoice-text-edit-outline',
+ title: "Structure",
+ subtitle: "YAML schema and layout",
+ disabled: () => false
+}, {
+ key: 'blueprints',
+ icon: 'mdi-ruler-square',
+ title: "Blueprints",
+ subtitle: "TypeScript types and default data",
+ disabled: () => false
+}, {
+ key: 'settings',
+ icon: 'mdi-cog',
+ title: "Settings",
+ subtitle: "Configure project behavior",
+ disabledSubtitle: 'Must be logged in',
+ disabled: () => !globalStore.session.loggedIn
+}, {
+ key: 'integration',
+ icon: 'mdi-download-circle-outline',
+ title: "Integration",
+ subtitle: "Install and connect your custom endpoint",
+ disabledSubtitle: 'Must be logged in',
+ disabled: () => !globalStore.session.loggedIn
+}])
+
let parseInterval: any;
let showParseInterval: any;
let parseValueInterval: any;
@@ -398,15 +443,28 @@ watch(() => globalStore.userSettings.data, () => {
text="Access to this template has not been granted by the owner."
/>
-
-
-
- Structure
-
-
-
- Blueprints
-
+
+
+
+
+
+ {{ selectedSection?.title }}
+
+
+
+
+
+
+
globalStore.userSettings.data, () => {
/>
-
+
@@ -562,6 +620,22 @@ watch(() => globalStore.userSettings.data, () => {
+
+
+
+
+
+
+
+
+
+
@@ -578,3 +652,9 @@ watch(() => globalStore.userSettings.data, () => {
transition: all var(--parsing-delay) linear;
}
+
+
diff --git a/src/components/Toolbar.vue b/src/components/Toolbar.vue
index 19e3daa..02e0d83 100644
--- a/src/components/Toolbar.vue
+++ b/src/components/Toolbar.vue
@@ -232,7 +232,9 @@ watch(() => currentRoute.params.locale, () => {
type="info"
icon="mdi-information-outline"
>
- Free and open-source, with data securely hosted on your server.
+
+ Free and open-source, with data securely hosted on your server.
+
diff --git a/src/composables/structure.ts b/src/composables/structure.ts
index 41205cc..2020e86 100644
--- a/src/composables/structure.ts
+++ b/src/composables/structure.ts
@@ -424,24 +424,26 @@ export function useStructure() {
structureStates.value.loadingSecretKey = true;
structureStates.value.secretKeyLoaded = false;
return getSecretKeySimple(endpoint.value?.uuid || '')
- .then(response => secretKey.value = response)
- .catch(error => globalStore.catchError(error))
- .finally(() => {
- structureStates.value.loadingSecretKey = false;
+ .then(response => {
+ secretKey.value = response;
structureStates.value.secretKeyLoaded = true;
+ return response;
})
+ .catch(error => globalStore.catchError(error))
+ .finally(() => structureStates.value.loadingSecretKey = false)
}
const getCypherKey = async (): Promise => {
structureStates.value.loadingCypherKey = true;
structureStates.value.cypherKeyLoaded = false;
return Services.get(import.meta.env.VITE_SERVER_URL + '/endpoint/cypher-key/' + endpoint.value?.uuid)
- .then(response => cypherKey.value = response)
- .catch(error => globalStore.catchError(error))
- .finally(() => {
- structureStates.value.loadingCypherKey = false;
+ .then(response => {
+ cypherKey.value = response;
structureStates.value.cypherKeyLoaded = true;
+ return response;
})
+ .catch(error => globalStore.catchError(error))
+ .finally(() => structureStates.value.loadingCypherKey = false)
}
const createStructure = (): Promise => {
@@ -504,21 +506,26 @@ export function useStructure() {
setTimeout(() => structureStates.value.saved = false, 2000);
}
- structureStates.value.saving = true;
- saveStructureSimple(structure)
- .then(response => {
- saveCallback();
- modelStore.setStructure(response);
- modelStore.setOriginalStructure(response);
- globalStore.updateStructure(response);
- resolve(modelStore.structure);
- })
- .catch(error => {
- reject(error);
- globalStore.catchError(error);
- return error;
- })
- .finally(() => structureStates.value.saving = false);
+ if (globalStore.session.loggedIn) {
+ structureStates.value.saving = true;
+ saveStructureSimple(structure)
+ .then(response => {
+ saveCallback();
+ modelStore.setStructure(response);
+ modelStore.setOriginalStructure(response);
+ globalStore.updateStructure(response);
+ resolve(modelStore.structure);
+ })
+ .catch(error => {
+ reject(error);
+ globalStore.catchError(error);
+ return error;
+ })
+ .finally(() => structureStates.value.saving = false);
+ } else {
+ saveCallback();
+ resolve(modelStore.structure);
+ }
})
}
@@ -602,8 +609,7 @@ export function useStructure() {
}
const canSaveStructure = computed(() => {
- return globalStore.session.loggedIn
- && !structureIsPristine.value
+ return !structureIsPristine.value
&& !structureHasSettingsError.value
})
diff --git a/src/interfaces.ts b/src/interfaces.ts
index 1241c5c..94c05a6 100644
--- a/src/interfaces.ts
+++ b/src/interfaces.ts
@@ -32,7 +32,7 @@ export interface IAdmin {
structure: boolean,
previewMode: 'mobile' | 'desktop' | null,
dataTab: 'data' | 'settings' | 'docs',
- editorTab: 'structure' | 'blueprints',
+ editorTab: 'structure' | 'blueprints' | 'settings' | 'integration',
}
export interface ISnack {