Skip to content

Commit 10032df

Browse files
committed
Allow triggers to be scoped to development or user #89
1 parent 91eb485 commit 10032df

10 files changed

Lines changed: 87 additions & 17 deletions

File tree

docs/structure.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,9 @@ triggers:
447447
448448
# URL called when the trigger is executed
449449
url: https://json.ms/?action=build
450+
451+
# Location of the trigger button (structure, toolbar, data)
452+
location: editor
450453
451454
# HTTP method used for the request
452455
method: POST

src/assets/example-structure.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ triggers:
2222
label: Build
2323
icon: mdi-play
2424
url: [BUILD_URL]/build
25+
location: structure
2526
method: POST
2627
headers:
2728
Content-Type: application/json

src/components/ActionBar.vue

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ import {useGlobalStore} from '@/stores/global';
66
import {computed} from "vue";
77
import {useTypings} from "@/composables/typings";
88
import {useModelStore} from "@/stores/model";
9+
import TriggerMenu from "@/components/TriggerMenu.vue";
10+
import type {IStructure, IStructureData} from "@/interfaces";
11+
12+
const structure = defineModel<IStructure>({ required: true });
13+
const { structureData, userData } = defineProps<{
14+
structureData: IStructureData,
15+
userData: any,
16+
}>();
917
1018
const globalStore = useGlobalStore();
1119
const modelStore = useModelStore();
@@ -56,6 +64,12 @@ const reset = () => {
5664
</script>
5765

5866
<template>
67+
<TriggerMenu
68+
:model-value="structureData"
69+
:structure="structure"
70+
:user-data="userData"
71+
location="data"
72+
/>
5973
<div
6074
v-if="globalStore.session.loggedIn"
6175
class="w-100 pr-3"

src/components/JSONms.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ if (globalStore.session.loggedIn) {
323323
:structures="structures"
324324
:structure-data="structureParsedData"
325325
:default-locale="getAvailableLocale()"
326+
:user-data="modelStore.userData"
326327
@refresh="onRefreshPreview"
327328
@create="onCreateStructure"
328329
@save="onSaveStructure"
@@ -442,7 +443,11 @@ if (globalStore.session.loggedIn) {
442443
<template #append>
443444
<v-divider />
444445
<div class="d-flex align-center justify-space-between pl-3" style="height: 4rem">
445-
<ActionBar />
446+
<ActionBar
447+
:model-value="structure"
448+
:structure-data="structureParsedData"
449+
:user-data="modelStore.userData"
450+
/>
446451
</div>
447452
</template>
448453

@@ -466,7 +471,11 @@ if (globalStore.session.loggedIn) {
466471
class="pl-3"
467472
>
468473
<div class="w-100 d-flex align-center justify-space-between">
469-
<ActionBar />
474+
<ActionBar
475+
:model-value="structure"
476+
:structure-data="structureParsedData"
477+
:user-data="modelStore.userData"
478+
/>
470479
</div>
471480
</v-app-bar>
472481
</v-expand-transition>

src/components/SitePreview.vue

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const loaded = ref(false);
2424
const loading = ref(false);
2525
const killIframe = ref(false);
2626
const siteNotCompatibleSnack = ref(false);
27-
const hoveringEditor = ref(false);
27+
const expanded = ref(false);
2828
const { layoutSize, windowHeight, layoutPx } = useLayout();
2929
const { reloading, siteCompatible, sendMessageToIframe, getPathsFromSectionKey, listenIframeMessage, sendUserDataToIframe } = useIframe();
3030
const { userDataLoading } = useUserData();
@@ -33,7 +33,7 @@ const iframeErrorMsg = ref('This site is not JSONms compatible');
3333
const editorHeight = computed((): number => {
3434
const padding = (globalStore.userSettings.data.layoutSitePreviewPadding ? 96 : 63);
3535
const result = windowHeight.value - padding;
36-
if (hoveringEditor.value) {
36+
if (expanded.value) {
3737
return result + 32;
3838
}
3939
return result - layoutSize.value.preview.height;
@@ -153,6 +153,7 @@ defineExpose({
153153
:width="layoutSize.preview.width"
154154
:location="globalStore.userSettings.data.layoutSitePreviewLocation"
155155
scrim
156+
class="site-preview-drawer"
156157
color="transparent"
157158
border="0"
158159
permanent
@@ -228,8 +229,6 @@ defineExpose({
228229
flat
229230
class="editor-card"
230231
theme="dark"
231-
@mouseover="hoveringEditor = true"
232-
@mouseleave="hoveringEditor = false"
233232
>
234233
<StructureEditor
235234
ref="structureEditor"
@@ -241,7 +240,19 @@ defineExpose({
241240
@save="onSaveStructureContent"
242241
@create="onCreateStructure"
243242
@change="onStructureContentChange"
244-
/>
243+
>
244+
<template #header.end>
245+
<v-btn
246+
size="small"
247+
@click="expanded = !expanded"
248+
>
249+
<span v-if="expanded">Collapse</span>
250+
<span v-else>Expand</span>
251+
<v-icon v-if="expanded" icon="mdi-unfold-less-horizontal" end />
252+
<v-icon v-else icon="mdi-unfold-more-horizontal" end />
253+
</v-btn>
254+
</template>
255+
</StructureEditor>
245256
</v-card>
246257
</div>
247258
</v-expand-transition>
@@ -259,4 +270,7 @@ defineExpose({
259270
.editor-card {
260271
transition: height 300ms ease;
261272
}
273+
.site-preview-drawer ::v-deep .v-navigation-drawer__content {
274+
overflow: hidden !important;
275+
}
262276
</style>

src/components/StructureEditor.vue

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {useTypings} from "@/composables/typings";
1313
import {useModelStore} from "@/stores/model";
1414
// import yaml from 'js-yaml';
1515
16-
const emit = defineEmits(['save', 'create', 'change'])
16+
const emit = defineEmits(['save', 'create', 'change', 'focus', 'blur']);
1717
const structure = defineModel<IStructure>({ required: true });
1818
const { columns = false, userData } = defineProps<{
1919
columns?: boolean,
@@ -155,6 +155,16 @@ const findNeedleInString = (haystack: string, needle: string) => {
155155
return -1
156156
}
157157
158+
159+
const onFocus = () => {
160+
setTimeout(() => {
161+
emit('focus');
162+
}, 100);
163+
}
164+
const onBlur = () => {
165+
emit('blur');
166+
}
167+
158168
const scrollToSection = (section: string) => {
159169
const instance = structureEditor.value?.getAceInstance();
160170
if (instance) {
@@ -443,8 +453,8 @@ watch(() => globalStore.userSettings.data, () => {
443453
text="Access to this template has not been granted by the owner."
444454
/>
445455
<div v-else class="d-flex flex-column">
446-
<div class="d-flex align-center pa-1">
447-
<v-menu v-model="sectionMenu" :close-on-content-click="false">
456+
<div class="d-flex align-center pa-1" style="gap: 1rem">
457+
<v-menu v-model="sectionMenu" contained :close-on-content-click="false">
448458
<template #activator="{ props }">
449459
<v-btn v-bind="props">
450460
<v-icon :icon="selectedSection?.icon" start />
@@ -466,6 +476,7 @@ watch(() => globalStore.userSettings.data, () => {
466476
</v-list>
467477
</v-menu>
468478
<v-spacer />
479+
<slot name="header.end"></slot>
469480
<div class="d-flex align-center pr-1" style="gap: 0.5rem">
470481
<div
471482
v-if="!globalStore.userSettings.data.editorLiveUpdate"
@@ -514,6 +525,8 @@ watch(() => globalStore.userSettings.data, () => {
514525
theme="github_dark"
515526
class="fill-height"
516527
@change="onChange"
528+
@focus="onFocus"
529+
@blur="onBlur"
517530
/>
518531
</div>
519532
<div class="pa-2 d-flex w-100" style="flex: 0; gap: 0.5rem">
@@ -553,6 +566,8 @@ watch(() => globalStore.userSettings.data, () => {
553566
:model-value="structureData"
554567
:structure="structure"
555568
:user-data="userData"
569+
location="structure"
570+
size="small"
556571
/>
557572
<v-tooltip
558573
v-if="isFolderSynced(modelStore.structure, 'typescript')"

src/components/Toolbar.vue

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ import {useLayout} from '@/composables/layout';
1616
import {useIframe} from '@/composables/iframe';
1717
import {useModelStore} from "@/stores/model";
1818
import {useMigration} from "@/composables/migration";
19+
import TriggerMenu from "@/components/TriggerMenu.vue";
1920
2021
const structure = defineModel<IStructure>({ required: true });
21-
const { structureData, structures = [], defaultLocale = 'en-US' } = defineProps<{
22+
const { structureData, structures = [], defaultLocale = 'en-US', userData } = defineProps<{
2223
structureData: IStructureData,
24+
userData: any,
2325
structures: IStructure[],
2426
defaultLocale?: string,
2527
}>();
@@ -224,6 +226,13 @@ watch(() => currentRoute.params.locale, () => {
224226
</v-tooltip>
225227
</v-btn-toggle>
226228

229+
<TriggerMenu
230+
:model-value="structureData"
231+
:structure="structure"
232+
:user-data="userData"
233+
location="toolbar"
234+
/>
235+
227236
<v-alert
228237
v-if="!globalStore.session.loggedIn && windowWidth > 1700"
229238
density="comfortable"

src/components/TriggerMenu.vue

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import {Services} from "@/services";
55
import {useGlobalStore} from "@/stores/global";
66
77
const structureData = defineModel<IStructureData>({ required: true });
8-
const { structure, userData } = defineProps<{
8+
const { structure, userData, location = 'structure', size } = defineProps<{
99
structure: IStructure,
1010
userData: IStructure,
11+
location?: 'structure' | 'toolbar' | 'data'
12+
size?: string
1113
}>();
1214
1315
const globalStore = useGlobalStore();
@@ -24,7 +26,7 @@ const triggers = computed((): ITrigger[] => {
2426
...structureData.value.triggers[key],
2527
})
2628
}
27-
return triggers;
29+
return triggers.filter(item => item.location === location || (!item.location && location === 'editor'));
2830
})
2931
const hasManyItems = computed((): boolean => {
3032
return triggers.value.length > 1;
@@ -33,10 +35,12 @@ const otherTriggers = computed((): ITrigger[] => {
3335
return triggers.value.filter((item: ITrigger) => item !== firstTrigger.value && item.key !== lastTrigger.value?.key);
3436
})
3537
const firstTrigger = computed((): ITrigger => {
36-
return lastTrigger.value || triggers.value[0] || {
38+
return Object.assign({
39+
icon: 'mdi-wrench'
40+
}, lastTrigger.value || triggers.value[0] || {
3741
label: '',
3842
url: '',
39-
}
43+
});
4044
})
4145
4246
const run = (trigger: ITrigger): Promise<any> => {
@@ -60,7 +64,7 @@ const run = (trigger: ITrigger): Promise<any> => {
6064
<div class="position-relative" style="flex: 1">
6165
<v-btn
6266
variant="outlined"
63-
size="small"
67+
:size="size"
6468
:disabled="running"
6569
:text="firstTrigger.label"
6670
:class="hasManyItems ? ['w-100 pr-12'] : []"

src/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ export interface ITrigger {
190190
headers?: {[key: string]: string}
191191
method?: string
192192
url: string
193+
location: 'editor' | 'toolbar'
193194
}
194195

195196
export interface IStructureData {

src/stores/global.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export const useGlobalStore = defineStore('global', {
8888
layoutAutoSplit: true,
8989
blueprintsIncludeTypings: true,
9090
blueprintsReadFromData: true,
91-
blueprintsReadFromStructure: false,
91+
blueprintsReadFromStructure: true,
9292
blueprintsWriteToData: true,
9393
blueprintsWriteToDefault: true,
9494
blueprintsWriteToIndex: true,

0 commit comments

Comments
 (0)