Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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 {@}\" --",
Expand Down
3 changes: 1 addition & 2 deletions src/components/Integration.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ ${prefix}JMS_ENCRYPTED_SECRET_KEY=${modelStore.structure.server_secret}`;
</script>

<template>

<v-card tile flat>
<v-card tile flat class="overflow-auto">
<v-card-text>
<h1>Integration Guide</h1>
<hr>
Expand Down
51 changes: 13 additions & 38 deletions src/components/JSONms.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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']);
Expand Down Expand Up @@ -396,33 +394,22 @@ if (globalStore.session.loggedIn) {
ref="form"
class="fill-height"
>
<v-expand-transition group>
<div v-if="globalStore.admin.structure && windowWidth > 900">
<v-tabs v-model="tab" grow>
<template v-if="!splitTabs">
<template v-if="!splitTabs">
<v-expand-transition group>
<div v-if="globalStore.admin.structure && windowWidth > 900">
<v-tabs v-model="tab" grow>
<v-tab value="data">
<v-icon icon="mdi-pencil" start />
Data
</v-tab>
</template>
<v-tab value="settings">
<v-icon start icon="mdi-cog" />
Settings
<v-icon v-if="structureHasSettingsError" color="warning" class="ml-3">
mdi-alert
</v-icon>
</v-tab>
<v-tab value="integration">
<v-icon start icon="mdi-download-circle-outline" />
Integration
</v-tab>
<v-tab value="docs">
<v-icon start icon="mdi-book" />
Docs
</v-tab>
</v-tabs>
</div>
</v-expand-transition>
<v-tab value="docs">
<v-icon start icon="mdi-book" />
Docs
</v-tab>
</v-tabs>
</div>
</v-expand-transition>
</template>
<v-tabs-window v-model="tab" class="fill-height" style="flex: 1">
<v-tabs-window-item value="data" class="fill-height">
<DataEditor
Expand All @@ -434,18 +421,6 @@ if (globalStore.session.loggedIn) {
:loading="userDataLoading"
/>
</v-tabs-window-item>
<v-tabs-window-item value="settings">
<Settings
v-model="structure"
:demo="!globalStore.session.loggedIn"
:disabled="structure.type !== 'owner'"
/>
</v-tabs-window-item>
<v-tabs-window-item value="integration">
<Integration
v-model="structure"
/>
</v-tabs-window-item>
<v-tabs-window-item value="docs">
<v-card tile flat>
<v-card-text>
Expand Down
100 changes: 90 additions & 10 deletions src/components/StructureEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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';
Expand All @@ -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;
Expand Down Expand Up @@ -398,15 +443,28 @@ watch(() => globalStore.userSettings.data, () => {
text="Access to this template has not been granted by the owner."
/>
<div v-else class="d-flex flex-column">
<v-tabs v-model="tab">
<v-tab value="structure">
<v-icon icon="mdi-invoice-text-edit-outline" start />
Structure
</v-tab>
<v-tab value="blueprints">
<v-icon icon="mdi-ruler-square" start />
Blueprints
</v-tab>
<div class="d-flex align-center pa-1">
<v-menu v-model="sectionMenu" :close-on-content-click="false">
<template #activator="{ props }">
<v-btn v-bind="props">
<v-icon :icon="selectedSection?.icon" start />
<span>{{ selectedSection?.title }}</span>
<v-icon icon="mdi-chevron-down" end />
</v-btn>
</template>
<v-list color="primary">
<v-list-item
v-for="section in sections"
:key="section.key"
:prepend-icon="section.disabled() ? 'mdi-alert' : section.icon"
:title="section.title"
:subtitle="section.disabled() ? section.disabledSubtitle : section.subtitle"
:active="selectedSection?.key === section.key"
:disabled="section.disabled()"
@click="setSection(section)"
/>
</v-list>
</v-menu>
<v-spacer />
<div class="d-flex align-center pr-1" style="gap: 0.5rem">
<div
Expand Down Expand Up @@ -438,7 +496,7 @@ watch(() => globalStore.userSettings.data, () => {
/>
</div>
</div>
</v-tabs>
</div>
<v-tabs-window v-model="tab" style="flex: 1" class="fill-height">
<v-tabs-window-item value="structure" class="fill-height">
<div class="d-flex flex-column align-center pr-1 fill-height">
Expand Down Expand Up @@ -562,6 +620,22 @@ watch(() => globalStore.userSettings.data, () => {
</div>
</div>
</v-tabs-window-item>
<v-tabs-window-item value="settings" class="fill-height">
<div class="d-flex flex-column overflow-auto h-100" style="max-height: calc(100vh - 109px)">
<Settings
v-model="structure"
:demo="!globalStore.session.loggedIn"
:disabled="structure.type !== 'owner'"
/>
</div>
</v-tabs-window-item>
<v-tabs-window-item value="integration" class="fill-height">
<div class="d-flex flex-column overflow-auto h-100" style="max-height: calc(100vh - 109px)">
<Integration
v-model="structure"
/>
</div>
</v-tabs-window-item>
</v-tabs-window>
</div>
</template>
Expand All @@ -578,3 +652,9 @@ watch(() => globalStore.userSettings.data, () => {
transition: all var(--parsing-delay) linear;
}
</style>

<style scoped lang="scss">
.v-window ::v-deep .v-window__container {
height: 100% !important;
}
</style>
4 changes: 3 additions & 1 deletion src/components/Toolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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.
<div class="text-truncate">
Free and open-source, with data securely hosted on your server.
</div>
</v-alert>
</div>

Expand Down
56 changes: 31 additions & 25 deletions src/composables/structure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string> => {
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<IStructure> => {
Expand Down Expand Up @@ -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);
}
})
}

Expand Down Expand Up @@ -602,8 +609,7 @@ export function useStructure() {
}

const canSaveStructure = computed(() => {
return globalStore.session.loggedIn
&& !structureIsPristine.value
return !structureIsPristine.value
&& !structureHasSettingsError.value
})

Expand Down
2 changes: 1 addition & 1 deletion src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down