Skip to content

Commit

Permalink
Rework various forms and integrate type metadata into forms
Browse files Browse the repository at this point in the history
This is done by extending the existing form config system, now
called field hints, which is integrated into various action builders
for editing and saving forms.
  • Loading branch information
mikesname committed Aug 7, 2024
1 parent 6cf3826 commit 5444ffc
Show file tree
Hide file tree
Showing 141 changed files with 8,155 additions and 951 deletions.
9 changes: 9 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,15 @@ module.exports = function (grunt) {
],
dest: paths.adminJsLib
},
{
expand: true,
cwd: 'node_modules/vue-i18n/dist',
src: [
// not using runtime 'cos we need the messages compiler
'vue-i18n.global.js'
],
dest: paths.adminJsLib
},
],
},
},
Expand Down
61 changes: 51 additions & 10 deletions modules/admin/app/assets/css/admin/_admin.scss
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,36 @@ body > .admin-content > .flash {
background-color: $gray-100;
}
}
}

.markdown-helper {
font-style: italic;
cursor: help;
}
.markdown-helper {
font-style: italic;
cursor: pointer;
}

.inline-remove > a:hover {
text-decoration: none;
cursor: pointer;
}

.form-legend {
font-size: $font-size-base;

dl {
display: flex;
flex-wrap: wrap;

dt {
@include make-col(3);
font-weight: bold;
}

dd {
@include make-col(9);
}
}
}

.address-form,
.concept-description-form {
background-color: $gray-100;
Expand Down Expand Up @@ -127,8 +145,11 @@ body > .admin-content > .flash {
padding-top: $margin-md;
}

.add-address {
.add-address,
.add-concept
{
float: right;
margin-bottom: $margin-md;
}

.admin-help-notice {
Expand Down Expand Up @@ -315,12 +336,18 @@ pre.code-format {
margin-bottom: $margin-md;
}

.add-description {
margin-bottom: $margin-md;
@include clearfix();
a {
float: right;
.control-elements {
.add-inline-element:not(.btn) {
display: block;
background-color: $gray-100;
border-bottom: 1px solid darken($gray-100, 5%);
padding: 0 $margin-xs;
color: $gray-700;
}
.add-inline-element:hover:not(.btn) {
background-color: darken($gray-100, 5%);
}

}

.inline-element-block-controls {
Expand Down Expand Up @@ -436,6 +463,20 @@ pre.code-format {
}
}

// Metadata validation
.metadata-validation {
summary {
font-size: $font-size-lg;
@extend .alert, .alert-warning;
}
.validation-errors {
@extend .alert, .alert-danger;
}
.validation-warnings {
@extend .alert, .alert-warning;
}
}

// Vue Single-page applications
%expanding-row {
display: flex;
Expand Down
27 changes: 27 additions & 0 deletions modules/admin/app/assets/css/dmeditor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,30 @@ $active-table-row: #e7f1ff;
overflow: auto;
flex-basis: 0;
}

.section {
background-color: $gray-100;
font-weight: bold;
}

.fm-list td.fm-actions {
width: 5rem;
}

.fm-see-also a + a {
display: inline-block;
}

.fm-usage {
white-space: nowrap;

}

.fm-list td:last-child a {
margin-left: $margin-xs;
}

#delete-metadata {
margin-right: auto;
}

6 changes: 5 additions & 1 deletion modules/admin/app/assets/js/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ jQuery(function ($) {
event.preventDefault();

var container = $(event.target).closest(".inline-formset");
var set = container.children(".inline-element-list");
var set = container.children(".control-elements").children(".inline-element-list").first();
var prefix = container.data("prefix");
if (!prefix) {
throw "No prefix found for formset";
Expand All @@ -212,6 +212,10 @@ jQuery(function ($) {

// And a help popover
addPopover($elem.find("textarea,input"));

// Focus the first input
$elem.find("input,textarea").first().focus();

}).on("click", ".remove-inline-element", function (event) {
event.preventDefault();
$(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import _takeWhile from 'lodash/takeWhile';
import _find from 'lodash/find';
import {DataTransformation} from "../types";
let initialConvertState = function (config) {
return {
ingesting: {},
Expand Down
26 changes: 14 additions & 12 deletions modules/admin/app/assets/js/dmeditor/__mocks__/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
EntityType,
EntityTypeMetadata,
EntityTypeMetadataInfo,
FieldMetadata,
Expand All @@ -17,9 +18,9 @@ export default class EntityTypeMetadataApi {
this.etData = {
Country: {
entityType: "Country",
name: "Country",
description: "Country description",
created: "2021-06-01"
name: "Country",
description: "Country description",
created: "2021-06-01"
}
};

Expand All @@ -31,6 +32,7 @@ export default class EntityTypeMetadataApi {
name: "History",
description: "Test",
usage: "mandatory",
defaultVal: null,
seeAlso: ["seeAlso"],
created: "2021-06-01"
}
Expand All @@ -39,42 +41,42 @@ export default class EntityTypeMetadataApi {

}

list(): Promise<Record<string, EntityTypeMetadata>> {
list(): Promise<Record<EntityType, EntityTypeMetadata>> {
return Promise.resolve(this.etData);
}

get(entityType: string): Promise<EntityTypeMetadata | null> {
get(entityType: EntityType): Promise<EntityTypeMetadata | null> {
return Promise.resolve(this.etData[entityType] || null);
}

save(entityType: string, data: EntityTypeMetadataInfo): Promise<EntityTypeMetadata> {
save(entityType: EntityType, data: EntityTypeMetadataInfo): Promise<EntityTypeMetadata> {
return Promise.resolve({
entityType,
...data
} as EntityTypeMetadata);
}

delete(entityType: string): Promise<boolean> {
delete(entityType: EntityType): Promise<boolean> {
return Promise.resolve(true);
}

listFields(entityType?: string): Promise<Record<string, FieldMetadata[]>> {
listFields(entityType?: EntityType): Promise<Record<EntityType, FieldMetadata[]>> {
return Promise.resolve(this.fData);
}

getField(entityType: string, id: string): Promise<FieldMetadata | null> {
getField(entityType: EntityType, id: string): Promise<FieldMetadata | null> {
return Promise.resolve(this.fData[entityType].find(f => f.id === id) || null);
}

saveField(entityType: string, id: string, data: FieldMetadataInfo): Promise<FieldMetadata> {
saveField(entityType: EntityType, id: string, data: FieldMetadataInfo): Promise<FieldMetadata> {
return Promise.resolve({
entityType,
id,
...data
} as FieldMetadata);
}

deleteField(entityType: string, id: string): Promise<boolean> {
deleteField(entityType: EntityType, id: string): Promise<boolean> {
// remove the item from fData:
this.fData[entityType] = this.fData[entityType].filter(f => f.id !== id);
return Promise.resolve(true);
Expand All @@ -83,7 +85,7 @@ export default class EntityTypeMetadataApi {
templates(): Promise<FieldMetadataTemplates> {
return Promise.resolve({
Country: {
"" : ["history"]
"_" : ["history"]
}
} as FieldMetadataTemplates);
}
Expand Down
23 changes: 12 additions & 11 deletions modules/admin/app/assets/js/dmeditor/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import axios from "axios";
import {
EntityType,
EntityTypeMetadata, EntityTypeMetadataInfo,
FieldMetadata,
FieldMetadataInfo, FieldMetadataTemplates,
Expand Down Expand Up @@ -30,36 +31,36 @@ export default class EntityTypeMetadataApi {
withCredentials: true,
}).then(r => r.data);
}
list(): Promise<Record<string, EntityTypeMetadata>> {
return EntityTypeMetadataApi.call<Record<string, EntityTypeMetadata>>(this.service.list(), {});
list(): Promise<Record<EntityType, EntityTypeMetadata>> {
return EntityTypeMetadataApi.call<Record<EntityType, EntityTypeMetadata>>(this.service.list(), {});
}

get(entityType: string): Promise<Record<string, EntityTypeMetadata>> {
return EntityTypeMetadataApi.call<Record<string, EntityTypeMetadata>>(this.service.list(), {}, {entityType});
get(entityType: EntityType): Promise<Record<EntityType, EntityTypeMetadata>> {
return EntityTypeMetadataApi.call<Record<EntityType, EntityTypeMetadata>>(this.service.list(), {}, {entityType});
}

save(entityType: string, data: EntityTypeMetadataInfo): Promise<EntityTypeMetadata> {
save(entityType: EntityType, data: EntityTypeMetadataInfo): Promise<EntityTypeMetadata> {
return EntityTypeMetadataApi.call<EntityTypeMetadata>(this.service.save(entityType), data);
}

delete(entityType: string): Promise<boolean> {
delete(entityType: EntityType): Promise<boolean> {
return EntityTypeMetadataApi.call<boolean>(this.service.delete(entityType));
}

listFields(entityType?: string): Promise<Record<string, FieldMetadata[]>> {
listFields(entityType?: EntityType): Promise<Record<EntityType, FieldMetadata[]>> {
let params = entityType ? {entityType} : {};
return EntityTypeMetadataApi.call<Record<string, FieldMetadata[]>>(this.service.listFields(), {}, params)
return EntityTypeMetadataApi.call<Record<EntityType, FieldMetadata[]>>(this.service.listFields(), {}, params)
}

getField(entityType: string, id: string): Promise<FieldMetadata | null> {
getField(entityType: EntityType, id: string): Promise<FieldMetadata | null> {
return EntityTypeMetadataApi.call<FieldMetadata>(this.service.getField(entityType, id));
}

saveField(entityType: string, id: string, data: FieldMetadataInfo): Promise<FieldMetadata> {
saveField(entityType: EntityType, id: string, data: FieldMetadataInfo): Promise<FieldMetadata> {
return EntityTypeMetadataApi.call<FieldMetadata>(this.service.saveField(entityType, id), data);
}

deleteField(entityType: string, id: string): Promise<boolean> {
deleteField(entityType: EntityType, id: string): Promise<boolean> {
return EntityTypeMetadataApi.call<boolean>(this.service.deleteField(entityType, id));
}

Expand Down
10 changes: 8 additions & 2 deletions modules/admin/app/assets/js/dmeditor/app.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import {mount, flushPromises} from '@vue/test-utils';
import {mount, flushPromises,config} from '@vue/test-utils';
import App from './app.vue';
import ListEt from './components/_list-et.vue';
import EntityTypeMetadataApi from "./api";

jest.mock('./api');

config.global.mocks = {
'$t': (msg) => msg, // return i18n key
}

const defaultInit = {
props: {
service: {},
Expand Down Expand Up @@ -55,7 +59,9 @@ test('deleting a field', async () => {
expect(wrapper.find(".fm-list").exists()).toBe(true);
expect(wrapper.find("#fm-Country-history").exists()).toBe(true);

await wrapper.find("#fm-Country-history .fm-delete").trigger("click");
await wrapper.find("#fm-Country-history .fm-edit").trigger("click");
expect(wrapper.find("#delete-metadata").exists()).toBe(true);
await wrapper.find("#delete-metadata").trigger("click");
expect(wrapper.find(".confirm-delete-field-metadata").exists()).toBe(true);
await wrapper.find(".confirm-delete-field-metadata button.accept").trigger("click");
await flushPromises();
Expand Down
3 changes: 3 additions & 0 deletions modules/admin/app/assets/js/dmeditor/app.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<script lang="ts">
import ListEt from "./components/_list-et";
import EntityTypeMetadataApi from "./api";
import {VueI18n} from "vue-i18n";
import Vue from "vue";
export default {
components: {ListEt},
Expand Down
Loading

0 comments on commit 5444ffc

Please sign in to comment.