make right rail work with editor and details
This commit is contained in:
124
frontend-frame/src/components/RightRail.vue
Normal file
124
frontend-frame/src/components/RightRail.vue
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<template>
|
||||||
|
<div class="right-rail-container" :class="{'container-open': showContainer}">
|
||||||
|
<div class="right-rail-close-area" :class="{'visible': open, 'hidden': !open}" @click="toggleRightRail"></div>
|
||||||
|
<transition name="slidein"
|
||||||
|
v-on:before-enter="beforeEnter"
|
||||||
|
v-on:after-leave="afterLeave">
|
||||||
|
<div v-if="open" class="right-rail-rail right-rail-slidein">
|
||||||
|
<button type="button" class="close" aria-label="Close" @click="toggleRightRail">
|
||||||
|
<span aria-hidden="true">X<i class="fas fa-times"></i></span>
|
||||||
|
</button>
|
||||||
|
<slot class="rail-content"></slot>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class RightRail extends Vue {
|
||||||
|
@Prop() private open!: boolean;
|
||||||
|
|
||||||
|
private showContainer: boolean = false;
|
||||||
|
|
||||||
|
private toggleRightRail() {
|
||||||
|
this.$emit('toggle-right-rail');
|
||||||
|
}
|
||||||
|
|
||||||
|
private beforeEnter() {
|
||||||
|
this.showContainer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private afterLeave() {
|
||||||
|
this.showContainer = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="css">
|
||||||
|
.right-rail-container {
|
||||||
|
z-index: 100;
|
||||||
|
position: fixed;
|
||||||
|
right: 0px;
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-open {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-rail-close-area {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0,0,0,0.2);
|
||||||
|
/*display: none;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.visible {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity .5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
transition: visibility 0s .5s, opacity .5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-rail-rail {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 450px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-left: 1px solid rgba(0,0,0,0.2);
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
right: 0px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-rail-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: left;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slidein-enter-active {
|
||||||
|
animation: slidein .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slidein-leave-active {
|
||||||
|
animation: slidein .5s reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slidein {
|
||||||
|
from {
|
||||||
|
right: -650px;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
right: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.right-rail-container.container-open {
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.right-rail-rail {
|
||||||
|
position: absolute;
|
||||||
|
right: 0px;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-rail-close-area {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -11,7 +11,7 @@ import { {{Component}}Config } from './{{component}}Types';
|
|||||||
import { {{component}}Service } from './{{component}}Service';
|
import { {{component}}Service } from './{{component}}Service';
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export default class {{Component}}Editor extends Vue {
|
export default class {{Component}}Details extends Vue {
|
||||||
@Prop() private id!: string;
|
@Prop() private id!: string;
|
||||||
private {{component}}: {{Component}}Config = {
|
private {{component}}: {{Component}}Config = {
|
||||||
// SYSTEM-BUILDER-init-props
|
// SYSTEM-BUILDER-init-props
|
||||||
|
@ -18,10 +18,7 @@ import { {{Component}}Config } from './{{component}}Types';
|
|||||||
|
|
||||||
@Component
|
@Component
|
||||||
export default class {{Component}}Editor extends Vue {
|
export default class {{Component}}Editor extends Vue {
|
||||||
@Prop() private {{component}}_id!: string;
|
@Prop() private {{component}}!: {{Component}}Config;
|
||||||
private {{component}}: {{Component}}Config = {
|
|
||||||
// SYSTEM-BUILDER-init-props
|
|
||||||
};
|
|
||||||
private loading: boolean = false;
|
private loading: boolean = false;
|
||||||
private errorMessage: string = '';
|
private errorMessage: string = '';
|
||||||
|
|
||||||
@ -34,18 +31,18 @@ export default class {{Component}}Editor extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private mounted() {
|
private mounted() {
|
||||||
this.loadDetails();
|
// this.loadDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadDetails() {
|
// private loadDetails() {
|
||||||
this.loading = true;
|
// this.loading = true;
|
||||||
this.errorMessage = '';
|
// this.errorMessage = '';
|
||||||
{{component}}Service.get{{Component}}(this.{{component}}_id).then((res: {{Component}}Config) => {
|
// {{component}}Service.get{{Component}}(this.{{component}}_id).then((res: {{Component}}Config) => {
|
||||||
this.loading = false;
|
// this.loading = false;
|
||||||
this.errorMessage = '';
|
// this.errorMessage = '';
|
||||||
this.{{component}} = res;
|
// this.{{component}} = res;
|
||||||
}).catch(this.handleError.bind(this));
|
// }).catch(this.handleError.bind(this));
|
||||||
}
|
// }
|
||||||
|
|
||||||
private save{{Component}}() {
|
private save{{Component}}() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="{{component}}-editor">
|
<div class="{{component}}-editor">
|
||||||
|
<div class="red-text" v-if="errorMessage !== ''">{{errorMessage}}</div>
|
||||||
<div class="filter-row">
|
<div class="filter-row">
|
||||||
<!-- SYSTEM-BUILDER-filter-options -->
|
<!-- SYSTEM-BUILDER-filter-options -->
|
||||||
</div>
|
</div>
|
||||||
@ -9,7 +10,10 @@
|
|||||||
<!-- SYSTEM-BUILDER-item-props -->
|
<!-- SYSTEM-BUILDER-item-props -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="red-text" v-if="errorMessage !== ''">{{errorMessage}}</div>
|
<right-rail :open="!!selected{{Component}}.clientId" v-on:toggle-right-rail="toggleEdit{{Component}}">
|
||||||
|
<{{Component}}Details :client="selected{{Component}}" @close-{{component}}-details="toggleEdit{{Component}}"></{{Component}}Details>
|
||||||
|
</right-rail>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -26,6 +30,9 @@ export default class {{Component}}Editor extends Vue {
|
|||||||
private filterItems: {{Component}}Config = {
|
private filterItems: {{Component}}Config = {
|
||||||
// SYSTEM-BUILDER-init-props
|
// SYSTEM-BUILDER-init-props
|
||||||
};
|
};
|
||||||
|
private selected{{Component}} = {
|
||||||
|
|
||||||
|
} ;
|
||||||
// SYSTEM-BUILDER-component-variables
|
// SYSTEM-BUILDER-component-variables
|
||||||
|
|
||||||
// SYSTEM-BUILDER-component-functions
|
// SYSTEM-BUILDER-component-functions
|
||||||
@ -36,6 +43,10 @@ export default class {{Component}}Editor extends Vue {
|
|||||||
|
|
||||||
// TODO: add a search function if there is an endpoint with type 'search'
|
// TODO: add a search function if there is an endpoint with type 'search'
|
||||||
|
|
||||||
|
private toggleEdit{{Component}}() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private handleError(err: any) {
|
private handleError(err: any) {
|
||||||
// error
|
// error
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
@ -3,6 +3,10 @@ import App from './App.vue'
|
|||||||
import router from './router';
|
import router from './router';
|
||||||
import './registerServiceWorker'
|
import './registerServiceWorker'
|
||||||
|
|
||||||
|
import RightRail from './components/RightRail.vue';
|
||||||
|
|
||||||
|
Vue.component('right-rail', RightRail);
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
|
@ -11,7 +11,7 @@ import fs from "fs";
|
|||||||
import {buildServiceFunctionName, getFuncParams} from "../views/service-creator";
|
import {buildServiceFunctionName, getFuncParams} from "../views/service-creator";
|
||||||
import {METHOD, URL} from "../views/routes-creator";
|
import {METHOD, URL} from "../views/routes-creator";
|
||||||
import {buildDetailsView} from "./details-view-builder";
|
import {buildDetailsView} from "./details-view-builder";
|
||||||
import {buildListView} from "./list-view-builder";
|
import {buildListView} from "./list-view-builder-v2";
|
||||||
import {buildEditorView} from "./editor-view-builder";
|
import {buildEditorView} from "./editor-view-builder";
|
||||||
import {buildTypesView} from "./types-view-builder";
|
import {buildTypesView} from "./types-view-builder";
|
||||||
import {buildRoute} from "./route-view-builder";
|
import {buildRoute} from "./route-view-builder";
|
||||||
|
361
src/frontend-services/list-view-builder-v2.ts
Normal file
361
src/frontend-services/list-view-builder-v2.ts
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
import {ColumnDef, ColumnRef, ComponentDef, EndpointDef, Filter, SystemDef, TableDef} from "../systemGenService";
|
||||||
|
import path from "path";
|
||||||
|
import fs from "fs";
|
||||||
|
import {createDetailsInitValues, findColumn, lowercaseFirstLetter, makeSet, uppercaseFirstLetter} from "../helpers";
|
||||||
|
import pluralize from "pluralize";
|
||||||
|
import {getFuncParams} from "../views/service-creator";
|
||||||
|
|
||||||
|
const INIT_VALUE = {
|
||||||
|
"blob": "''",
|
||||||
|
"boolean": "false",
|
||||||
|
"date": "''",
|
||||||
|
"dateTIME": "''",
|
||||||
|
"number": "0",
|
||||||
|
"string": "''"
|
||||||
|
};
|
||||||
|
|
||||||
|
export function buildListView(component: ComponentDef, outDir: string, systemDef: SystemDef): Promise<void> {
|
||||||
|
let hasDeleteEndpoint = false;
|
||||||
|
let hasItemEndpoint = false;
|
||||||
|
let hasUpdateEndpoint = false;
|
||||||
|
let hasCreateEndpoint = false;
|
||||||
|
let hasSearchEndpoint = false;
|
||||||
|
let listEndpoints: EndpointDef[] = component.endpoints.filter((epd: EndpointDef) => {
|
||||||
|
if (epd.type === 'delete') {
|
||||||
|
hasDeleteEndpoint = true;
|
||||||
|
}
|
||||||
|
if (epd.type === 'create') {
|
||||||
|
hasCreateEndpoint = true;
|
||||||
|
}
|
||||||
|
if (epd.type === 'update') {
|
||||||
|
hasUpdateEndpoint = true;
|
||||||
|
}
|
||||||
|
if (epd.type === 'item') {
|
||||||
|
hasItemEndpoint = true;
|
||||||
|
}
|
||||||
|
if (epd.type === 'search') {
|
||||||
|
hasSearchEndpoint = true;
|
||||||
|
}
|
||||||
|
return epd.type === 'list' || epd.type === 'search';
|
||||||
|
});
|
||||||
|
|
||||||
|
let templateData: {[key:string]:string} = {};
|
||||||
|
templateData.component = lowercaseFirstLetter(component.component);
|
||||||
|
templateData.Component = uppercaseFirstLetter(component.component);
|
||||||
|
templateData.componentFunctions = '';
|
||||||
|
templateData.componentProps = createDetailsInitValues(listEndpoints[0], systemDef);
|
||||||
|
templateData.componentVariables = '';
|
||||||
|
templateData.rightRail = '';
|
||||||
|
templateData.moreImports = '';
|
||||||
|
templateData.componentConfig = '';
|
||||||
|
templateData.createButton = '';
|
||||||
|
|
||||||
|
let vueComponents: string[] = [];
|
||||||
|
let filterParams: Filter[] = [];
|
||||||
|
for (let i in listEndpoints) {
|
||||||
|
if (i === '0') {
|
||||||
|
templateData.filterProps = createDetailsInitValues(listEndpoints[i], systemDef);
|
||||||
|
}
|
||||||
|
if (listEndpoints[i].filters) {
|
||||||
|
filterParams = [...filterParams, ...listEndpoints[i].filters as Filter[]];
|
||||||
|
}
|
||||||
|
templateData.componentFunctions = templateData.componentFunctions + createListRequestFunc(listEndpoints[i], systemDef, hasDeleteEndpoint);
|
||||||
|
}
|
||||||
|
if (listEndpoints.length) {
|
||||||
|
templateData.itemPropsHTML = createListMarkup(listEndpoints[0], hasDeleteEndpoint, hasUpdateEndpoint);
|
||||||
|
}
|
||||||
|
if (hasDeleteEndpoint && listEndpoints.length) {
|
||||||
|
templateData.componentFunctions = templateData.componentFunctions + createFEDeleteCode(listEndpoints[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasItemEndpoint) {
|
||||||
|
// Add import for details
|
||||||
|
templateData.moreImports = templateData.moreImports + createDetailsImports(listEndpoints[0]);
|
||||||
|
// add component config
|
||||||
|
vueComponents.push(`${uppercaseFirstLetter(component.component)}Details,`);
|
||||||
|
// add details in right rail, with functions to handle opening and closing
|
||||||
|
templateData.rightRail = templateData.rightRail + createRightRailDetails(listEndpoints[0]);
|
||||||
|
|
||||||
|
templateData.componentVariables = templateData.componentVariables + detailsOpenVariables(listEndpoints[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// combine all duplicate filterParams
|
||||||
|
// @ts-ignore
|
||||||
|
let filterSet: Filter[] = makeSet<Filter>(filterParams, 'param');
|
||||||
|
// add filterParams to the markup as filter options
|
||||||
|
if (listEndpoints.length && filterSet.length) {
|
||||||
|
templateData.filterOptions = createFilterMarkup(listEndpoints[0], filterSet, hasSearchEndpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCreateEndpoint) {
|
||||||
|
// add button to open editor without a selected item
|
||||||
|
templateData.createButton = templateData.createButton + createButtonHTML(listEndpoints[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add create component to sidebar
|
||||||
|
if (hasCreateEndpoint || hasUpdateEndpoint) {
|
||||||
|
templateData.moreImports = templateData.moreImports + createEditorImports(listEndpoints[0]);
|
||||||
|
templateData.rightRail = templateData.rightRail + editRightRailHTML(listEndpoints[0]);
|
||||||
|
vueComponents.push(`${uppercaseFirstLetter(component.component)}Editor,`);
|
||||||
|
templateData.componentVariables = templateData.componentVariables + editorOpenVariables(listEndpoints[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCreateEndpoint || hasUpdateEndpoint || hasItemEndpoint) {
|
||||||
|
templateData.componentFunctions = templateData.componentFunctions + addResetSelectedFunction(listEndpoints[0], systemDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add details component to sidebar
|
||||||
|
// TODO: if delete endpoint exists add delete button next to each row
|
||||||
|
|
||||||
|
if (vueComponents.length) {
|
||||||
|
let comp = vueComponents.join(`
|
||||||
|
`);
|
||||||
|
templateData.componentConfig = `({
|
||||||
|
components: {
|
||||||
|
${comp}
|
||||||
|
},
|
||||||
|
})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let output: string = buildFile(templateData);
|
||||||
|
return writeFile(output, path.join(outDir, `${component.component}List.vue`))
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeFile(output: string, outdir: string) {
|
||||||
|
return new Promise<void>((resolve) => {
|
||||||
|
fs.writeFile(outdir, output, 'utf8', () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDetailsImports(view: EndpointDef) {
|
||||||
|
return `import ${uppercaseFirstLetter(view.component)}Details from './${lowercaseFirstLetter(view.component)}Details.vue';
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createEditorImports(view: EndpointDef) {
|
||||||
|
return `import ${uppercaseFirstLetter(view.component)}Editor from './${lowercaseFirstLetter(view.component)}Editor.vue';
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createButtonHTML(view: EndpointDef) {
|
||||||
|
let out = `<button @click="editorOpen = true">New ${uppercaseFirstLetter(view.component)}</button>
|
||||||
|
`;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createRightRailDetails(view: EndpointDef) {
|
||||||
|
let out = `<right-rail :open="detailsOpen && !!selected${uppercaseFirstLetter(view.component)}.${lowercaseFirstLetter(view.component)}_id" v-on:toggle-right-rail="detailsOpen = !detailsOpen; resetSelectedItem()">
|
||||||
|
<${lowercaseFirstLetter(view.component)}Details :id="selected${uppercaseFirstLetter(view.component)}.${lowercaseFirstLetter(view.component)}_id" @close-${lowercaseFirstLetter(view.component)}-details="detailsOpen = !detailsOpen; resetSelectedItem()"></${lowercaseFirstLetter(view.component)}Details>
|
||||||
|
</right-rail>
|
||||||
|
`;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function editRightRailHTML(view: EndpointDef) {
|
||||||
|
let out = `<right-rail :open="editorOpen" v-on:toggle-right-rail="editorOpen = !editorOpen; resetSelectedItem()">
|
||||||
|
<${lowercaseFirstLetter(view.component)}Editor :${lowercaseFirstLetter(view.component)}="selected${uppercaseFirstLetter(view.component)}.${lowercaseFirstLetter(view.component)}_id" @close-${lowercaseFirstLetter(view.component)}-editor="editorOpen = !editorOpen; resetSelectedItem()"></${lowercaseFirstLetter(view.component)}Editor>
|
||||||
|
</right-rail>
|
||||||
|
`;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function detailsOpenVariables(view: EndpointDef) {
|
||||||
|
let out = `private detailsOpen: boolean = false;
|
||||||
|
`;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function editorOpenVariables(view: EndpointDef) {
|
||||||
|
let out = `private editorOpen: boolean = false;
|
||||||
|
`;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addResetSelectedFunction(view: EndpointDef, systemDef: SystemDef) {
|
||||||
|
let out = `private resetSelectedItem() {
|
||||||
|
this.selected${uppercaseFirstLetter(view.component)} = {
|
||||||
|
${createDetailsInitValues(view, systemDef)}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
`;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFilterMarkup(view: EndpointDef, filters: Filter[], hasSearchEndpoint=false): string {
|
||||||
|
let out = ``;
|
||||||
|
let inputType: {[key: string]: string} = {
|
||||||
|
"blob": "text",
|
||||||
|
"boolean": "checkbox",
|
||||||
|
"date": "date",
|
||||||
|
"dateTIME": "datetime-local",
|
||||||
|
"number": "number",
|
||||||
|
"string": "text",
|
||||||
|
};
|
||||||
|
filters.forEach((f: Filter) => {
|
||||||
|
if (f.type) {
|
||||||
|
// base the filter markup on type
|
||||||
|
out = out + `<div>
|
||||||
|
<label>${f.param}: </label>
|
||||||
|
<input type="${inputType[f.type] || 'text'}" placeholder="${f.param}" v-model="filterItems.${f.param}"/>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
// default to a string filter
|
||||||
|
out = out + `<div>
|
||||||
|
<input type="text" placeholder="${f.param}" v-model="filterItems.${f.param}"/>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
out = out + `<div>
|
||||||
|
<button @click="${hasSearchEndpoint ? 'search' : 'get'}${uppercaseFirstLetter(pluralize(view.component))}()">Search</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createListMarkup(view: EndpointDef, hasDeleteEndpoint: boolean, hasEditEndpoint: boolean): string {
|
||||||
|
let out = ``;
|
||||||
|
|
||||||
|
view.columns.forEach((column: ColumnRef) => {
|
||||||
|
out = out + `<div class="">{{ item.${column.name} }}</div>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
out = out + `<div class="" @click="detailsOpen = true; selected${uppercaseFirstLetter(view.component)} = item">details</div>
|
||||||
|
`;
|
||||||
|
if (hasEditEndpoint) {
|
||||||
|
out = out + `<div class="" @click="editorOpen = true; selected${uppercaseFirstLetter(view.component)} = item">edit</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
if (hasDeleteEndpoint) {
|
||||||
|
out = out + `<div class="red-text" @click="deleteItem(item.${view.component}_id)">delete</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createListRequestFunc(view: EndpointDef, systemDef: SystemDef, hasDeleteEndpoint: boolean) {
|
||||||
|
let isSearch: boolean = view.type === 'search';
|
||||||
|
let params: string[] = getFuncParams(view);
|
||||||
|
params = params.map((param: string) => {
|
||||||
|
return 'this.filterItems.' + param;
|
||||||
|
});
|
||||||
|
params.push('0'); // offset
|
||||||
|
params.push('1000'); // limit
|
||||||
|
|
||||||
|
let out = `private ${isSearch ? 'search' : 'get'}${uppercaseFirstLetter(pluralize(view.component))}() {
|
||||||
|
this.loading = true;
|
||||||
|
this.errorMessage = '';
|
||||||
|
${view.component}Service.${isSearch ? 'search' : 'get'}${uppercaseFirstLetter(pluralize(view.component))}(${params.join(', ')}).then((listItems: ${uppercaseFirstLetter(view.component)}Config[]) => {
|
||||||
|
// success
|
||||||
|
this.loading = false;
|
||||||
|
this.errorMessage = '';
|
||||||
|
this.items = listItems;
|
||||||
|
}).catch(this.handleError.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
`;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFEDeleteCode(view: EndpointDef) {
|
||||||
|
let out = `private deleteItem(itemKey: string) {
|
||||||
|
this.loading = true;
|
||||||
|
this.errorMessage = '';
|
||||||
|
${view.component}Service.delete${uppercaseFirstLetter(view.component)}(itemKey).then(() => {
|
||||||
|
this.loading = false;
|
||||||
|
this.errorMessage = '';
|
||||||
|
return this.get${uppercaseFirstLetter(pluralize(view.component))}();
|
||||||
|
}).catch(this.handleError.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
`;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildFile(data: any) {
|
||||||
|
let template = `<template>
|
||||||
|
<div class="${data.component}-editor">
|
||||||
|
<div class="red-text" v-if="errorMessage !== ''">{{errorMessage}}</div>
|
||||||
|
${data.createButton}
|
||||||
|
<div class="filter-row">
|
||||||
|
${data.filterOptions}
|
||||||
|
<!-- SYSTEM-BUILDER-filter-options -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-for="item in items" :key="item.${data.component}_id" class="input-row">
|
||||||
|
<div class="">{{ item.${data.component}_id }}</div>
|
||||||
|
${data.itemPropsHTML}
|
||||||
|
<!-- SYSTEM-BUILDER-item-props -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
${data.rightRail}
|
||||||
|
<!-- <right-rail :open="!!selected{{Component}}.clientId" v-on:toggle-right-rail="toggleEdit{{Component}}">
|
||||||
|
<${data.Component}Details :client="selected${data.Component}" @close-${data.component}-details="toggleEdit${data.Component}"></${data.Component}Details>
|
||||||
|
</right-rail> -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||||
|
import { ${data.component}Service } from './${data.component}Service';
|
||||||
|
import { ${data.Component}Config } from './${data.component}Types';
|
||||||
|
${data.moreImports}
|
||||||
|
|
||||||
|
@Component${data.componentConfig}
|
||||||
|
export default class ${data.Component}List extends Vue {
|
||||||
|
private items: ${data.Component}Config[] = [];
|
||||||
|
private loading: boolean = false;
|
||||||
|
private errorMessage: string = '';
|
||||||
|
private filterItems: ${data.Component}Config = {
|
||||||
|
${data.filterProps}
|
||||||
|
// SYSTEM-BUILDER-init-props
|
||||||
|
};
|
||||||
|
private selected${data.Component}: ${data.Component}Config = {
|
||||||
|
${data.componentProps}
|
||||||
|
} ;
|
||||||
|
${data.componentVariables}
|
||||||
|
// SYSTEM-BUILDER-component-variables
|
||||||
|
|
||||||
|
${data.componentFunctions}
|
||||||
|
// SYSTEM-BUILDER-component-functions
|
||||||
|
|
||||||
|
private mounted() {
|
||||||
|
this.get${pluralize(data.Component)}();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add a search function if there is an endpoint with type 'search'
|
||||||
|
|
||||||
|
private handleError(err: any) {
|
||||||
|
// error
|
||||||
|
this.loading = false;
|
||||||
|
this.errorMessage = err.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="css">
|
||||||
|
.red-text {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
.input-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
`;
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user