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 2, 2024
1 parent 6cf3826 commit 57264d9
Show file tree
Hide file tree
Showing 113 changed files with 7,957 additions and 783 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
35 changes: 29 additions & 6 deletions modules/admin/app/assets/css/admin/_admin.scss
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,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 +318,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 +445,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
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 57264d9

Please sign in to comment.