Skip to content

Commit

Permalink
Load schema on demand (fixes #203)
Browse files Browse the repository at this point in the history
  • Loading branch information
TeodoraPavlova committed Apr 30, 2024
1 parent df11fa3 commit a7af940
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 243 deletions.
1 change: 0 additions & 1 deletion frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ export default {
},
provide() {
return {
activeSchema: computed(() => this.activeSchema),
availableSchemas: computed(() => this.$refs.schemalist.schemas),
updatePendingRequests: this.onPendingReviews,
apiInfo: computed(() => this.apiInfo)
Expand Down
194 changes: 98 additions & 96 deletions frontend/src/components/Entity.vue
Original file line number Diff line number Diff line change
@@ -1,113 +1,115 @@
<template>
<BaseLayout>
<template v-slot:additional_breadcrumbs>
<li class="breadcrumb-item">
<router-link :to="{name: 'schema-view', params: {schemaSlug: activeSchema?.slug || 'n-a'}}">
{{ activeSchema?.name || 'n/a' }}
</router-link>
</li>
<li class="breadcrumb-item active">{{ title }}</li>
<Placeholder :big="true" :loading="loading">
<template v-slot:content>
<BaseLayout>
<template v-slot:additional_breadcrumbs>
<li class="breadcrumb-item">
<router-link :to="{name: 'schema-view', params: {schemaSlug: activeSchema?.slug || 'n-a'}}">
{{ activeSchema?.name || 'n/a' }}
</router-link>
</li>
<li class="breadcrumb-item active">{{ title }}</li>
</template>
<template v-slot:actions>
<div v-if="entity?.deleted" class="alert alert-danger p-2">
<i class="eos-icons me-2">delete</i>
This entity is deleted.
</div>
</template>
</BaseLayout>
<Tabbing :bind-args="bindArgs" :tabs="tabs" :tabEvents="{update: onUpdate}"/>
</template>
<template v-slot:actions>
<div v-if="entity?.deleted" class="alert alert-danger p-2">
<i class="eos-icons me-2">delete</i>
This entity is deleted.
</div>
</template>
</BaseLayout>
<Tabbing :bind-args="bindArgs" :tabs="tabs" ref="entitytabbing"
:tabEvents="{update: onUpdate}"/>
</Placeholder>
</template>
<script>
import { markRaw } from "vue";
<script setup>
import {markRaw, ref, computed, watch} from "vue";
import BaseLayout from "@/components/layout/BaseLayout";
import EntityForm from "@/components/inputs/EntityForm";
import Changes from "@/components/change_review/Changes";
import Tabbing from "@/components/layout/Tabbing";
import PermissionList from "@/components/auth/PermissionList";
import EntityBulkAdd from "@/components/EntityBulkAdd";
import Placeholder from "@/components/layout/Placeholder";
import {useSchema} from "@/store/schema";
import {useRoute} from "vue-router";
import {api} from "@/composables/api";
export default {
name: "Entity",
components: {BaseLayout, Tabbing},
inject: ["activeSchema"],
emits: ["pending-reviews"],
data() {
return {
entity: null,
tabs: [
{
name: 'Show/Edit',
component: markRaw(EntityForm),
icon: "mode_edit",
tooltip: "Edit/show entity details"
},
{
name: "Bulk Add (copy Attributes)",
component: markRaw(EntityBulkAdd),
icon: "add_circle",
tooltip: "Copy over entity attributes to new entities"
},
{
name: "Permissions",
component: markRaw(PermissionList),
icon: "security",
tooltip: "Manage permissions on the entity"
},
{
name: "History",
component: markRaw(Changes),
icon: "history",
tooltip: 'Change history of entity'
}
]
};
},
computed: {
title() {
return this.entity?.name || this.$route.params.entitySlug || '-';
},
bindArgs() {
return [
{ schema: this.activeSchema, entity: this.entity },
{ schema: this.activeSchema, entity: this.entity },
{ objectType: "Entity", objectId: this.entity?.id },
{ schema: this.activeSchema, entitySlug: this.$route.params.entitySlug },
]
},
const {getSchema, activeSchema} = useSchema();
const route = useRoute();
const entity = ref(null);
const loading = ref(true);
const tabs = ref([
{
name: 'Show/Edit',
component: markRaw(EntityForm),
icon: "mode_edit",
tooltip: "Edit/show entity details"
},
methods: {
async getEntity() {
if (this.$route.params.entitySlug && this.$route.params.schemaSlug) {
const params = {
schemaSlug: this.$route.params.schemaSlug,
entityIdOrSlug: this.$route.params.entitySlug
};
this.entity = await this.$api.getEntity(params);
} else {
this.entity = null;
}
},
async onUpdate(entity) {
if (entity) {
this.entity = entity;
}
}
{
name: "Bulk Add (copy Attributes)",
component: markRaw(EntityBulkAdd),
icon: "add_circle",
tooltip: "Copy over entity attributes to new entities"
},
async activated() {
await this.getEntity();
{
name: "Permissions",
component: markRaw(PermissionList),
icon: "security",
tooltip: "Manage permissions on the entity"
},
watch: {
entity(newValue) {
if (newValue?.name) {
document.title = newValue.name;
}
{
name: "History",
component: markRaw(Changes),
icon: "history",
tooltip: 'Change history of entity'
}
]);
const title = computed(() => {
return entity.value?.name || route.params.entitySlug || '-';
});
const bindArgs = computed(() => {
return [
{schema: activeSchema.value, entity: entity.value},
{schema: activeSchema.value, entity: entity.value},
{objectType: "Entity", objectId: entity.value?.id},
{schema: activeSchema.value, entitySlug: route.params.entitySlug},
]
});
async function getEntity() {
if (route.params.entitySlug && route.params.schemaSlug) {
const params = {
schemaSlug: route.params.schemaSlug,
entityIdOrSlug: route.params.entitySlug
};
entity.value = await api.getEntity(params);
} else {
entity.value = null;
}
}
async function onUpdate(entity) {
if (entity) {
entity.value = entity;
}
}
watch(entity, (newValue) => {
if (newValue?.name) {
document.title = newValue.name;
}
});
watch(
route,
() => {
loading.value = true;
Promise.all([getSchema(), getEntity()])
.then(() => loading.value = false);
},
$route: {
handler: "getEntity",
{
immediate: true
},
}
};
}
);
</script>
134 changes: 66 additions & 68 deletions frontend/src/components/EntityBulkEdit.vue
Original file line number Diff line number Diff line change
@@ -1,87 +1,85 @@
<template>
<BaseLayout>
<template v-slot:additional_breadcrumbs>
<li class="breadcrumb-item active">
<router-link :to="{name: 'schema-view', params: {schemaSlug: activeSchema?.slug || 'n-a'}}">
{{ activeSchema?.name || 'n/a' }}
</router-link>
</li>
<li class="breadcrumb-item active">Bulk Editor</li>
</template>
</BaseLayout>
<Placeholder :big="true" :loading="loading">
<template v-slot:content>
<BaseLayout>
<template v-slot:additional_breadcrumbs>
<li class="breadcrumb-item active">
<router-link :to="{name: 'schema-view', params: {schemaSlug: activeSchema?.slug || 'n-a'}}">
{{ activeSchema?.name || 'n/a' }}
</router-link>
</li>
<li class="breadcrumb-item active">Bulk Editor</li>
</template>
</BaseLayout>
<div v-for="e of entities" :key="e.id" class="border mb-3 p-2">
<EntityForm :entity="e" :schema="activeSchema"
:batch-mode="true" :ref="`e_form_${e.id}`" v-on:save-all="saveAll" />
:batch-mode="true" :ref="el => { entityFormRefs[`e_form_${e.id}`] = el }"
v-on:save-all="saveAll"/>
</div>
</template>
</Placeholder>
</template>
<script>
<script setup>
import BaseLayout from "@/components/layout/BaseLayout";
import EntityForm from "@/components/inputs/EntityForm";
import Placeholder from "@/components/layout/Placeholder.vue";
import Placeholder from "@/components/layout/Placeholder";
import {ref, computed, watch} from "vue";
import {useSchema} from "@/store/schema";
import {useRoute} from "vue-router";
import {api} from "@/composables/api";
import {alertStore} from "@/composables/alert";
export default {
name: "EntityBulkEdit",
components: {BaseLayout, EntityForm, Placeholder},
inject: ['activeSchema'],
data() {
return {
entities: [],
loading: true
}
},
computed: {
entityIds() {
return this.entities.map(x => x.id);
const {getSchema, activeSchema} = useSchema();
const route = useRoute();
const entities = ref([]);
const loading = ref(true);
const entityFormRefs = ref([]);
const entityIds = computed(() => {
return entities.value.map(x => x.id);
});
async function getEntityData() {
const schemaSlug = route.params.schemaSlug;
if (!schemaSlug) {
return
}
const queryIds = (route.query?.entity || []);
entities.value = entities.value.filter(x => queryIds.includes(x.id));
const promises = queryIds
.map(x => parseInt(x))
.filter(x => !entityIds.value.includes(x))
.map(x => api.getEntity({schemaSlug: schemaSlug, entityIdOrSlug: x}));
Promise.all(promises).then(x => {
entities.value = entities.value.concat(x);
});
}
async function saveAll() {
const promises = Object.entries(entityFormRefs.value)
.map(x => x[1].updateEntity());
Promise.all(promises).then(x => {
if (x.every(y => y === null)) {
alertStore.push(
"warning",
"None of the entities were changed. Therefore no changes were sent to server."
);
}
},
methods: {
async getEntityData() {
const schemaSlug = this.$route.params.schemaSlug;
if (!schemaSlug) {
return
}
});
}
const queryIds = (this.$route.query?.entity || []);
this.entities = this.entities.filter(x => queryIds.includes(x.id));
this.loading = true;
const promises = queryIds
.map(x => parseInt(x))
.filter(x => !this.entityIds.includes(x))
.map(x => this.$api.getEntity({schemaSlug: schemaSlug, entityIdOrSlug: x}));
Promise.all(promises).then(x => {
this.entities = this.entities.concat(x);
this.loading = false;
})
watch(
route,
() => {
loading.value = true;
Promise.all([getSchema(), getEntityData()])
.then(() => loading.value = false);
},
async saveAll() {
const promises = Object.entries(this.$refs)
.filter(x => x[0].startsWith("e_form_"))
.map(x => x[1][0].updateEntity());
Promise.all(promises).then(x => {
if (x.every(y => y === null)) {
this.$alerts.push(
"warning",
"None of the entities were changed. Therefore no changes were sent to server."
);
}
});
}
},
watch: {
$route: {
handler: "getEntityData",
{
immediate: true,
deep: true
},
}
}
}
);
</script>
<style scoped>
</style>
Loading

0 comments on commit a7af940

Please sign in to comment.