Skip to content

Commit

Permalink
Merge pull request #1683 from ProcessMaker/feature/FOUR-18107
Browse files Browse the repository at this point in the history
Feature/FOUR-18107: STORY Collection Record Control in Form Screens.
  • Loading branch information
nolanpro authored Sep 23, 2024
2 parents a470766 + 04c9f89 commit 51af2da
Show file tree
Hide file tree
Showing 8 changed files with 424 additions and 1 deletion.
20 changes: 20 additions & 0 deletions src/DataProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,5 +286,25 @@ export default {
}
throw error;
});
},

getCollectionRecordsView(collectionId, recordId) {
return this.get(
`/collections/${collectionId}/records/${recordId}`
)
.then((response) => {
const data = response ? response.data : null;
if (!data) {
throw new Error(i18next.t("No data returned"));
}
return data;
})
.catch((error) => {
if (error.response && error.response.status === 404) {
const data = { data: [] };
return data;
}
throw error;
});
}
};
6 changes: 5 additions & 1 deletion src/components/accordions.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ export default [
'initiallyChecked',
'screen',
'multipleUpload',
'linkUrl'
'linkUrl',
'collection',
'record',
'displayMode',
'submitCollectionCheck',
],
open: true,
},
Expand Down
2 changes: 2 additions & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import accordions from "@/components/accordions";
import VariableNameGenerator from "@/components/VariableNameGenerator";
import { LinkButton } from "./renderer";
import "../assets/css/tabs.css";
import FormCollectionRecordControl from "./renderer/form-collection-record-control.vue";

const rendererComponents = {
...renderer,
Expand Down Expand Up @@ -163,6 +164,7 @@ export default {
Vue.use(Vuex);
Vue.component("FormListTable", FormListTable);
Vue.component("LinkButton", LinkButton);
Vue.component("FormCollectionRecordControl", FormCollectionRecordControl);
const store = new Vuex.Store({
modules: {
globalErrorsModule,
Expand Down
132 changes: 132 additions & 0 deletions src/components/inspector/collection-records-list.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<template>
<div>
<div>
<label for="collection">{{ $t("Collection") }}</label>
<b-form-select
id="collection"
v-model="collectionId"
:options="collections"
data-cy="inspector-collection"
@change="resetFields"
/>
</div>
</div>
</template>

<script>
import { debounce } from "lodash";
import MustacheHelper from "./mustache-helper.vue";
import ScreenVariableSelector from "../screen-variable-selector.vue";
const CONFIG_FIELDS = [
"collectionId",
"labelField",
"valueField",
"pmql",
"unique"
];
export default {
components: {
MustacheHelper,
ScreenVariableSelector
},
props: ["value"],
data() {
return {
collections: [],
fields: [],
collectionId: null,
labelField: null,
valueField: null,
pmql: "",
unique: false
};
},
computed: {
options() {
return Object.fromEntries(
CONFIG_FIELDS.map((field) => [field, this[field]])
);
}
},
watch: {
value: {
handler(value) {
if (!value) {
return;
}
CONFIG_FIELDS.forEach((field) => (this[field] = value[field]));
},
immediate: true
},
collectionId: {
handler() {
this.getFields();
}
},
options: {
handler() {
this.$emit("input", this.options);
},
deep: true
}
},
created() {
this.onDebouncedPmqlChange = debounce((pmql) => {
this.onPmqlChange(pmql);
}, 1000);
},
mounted() {
this.getCollections();
if (this.collectionId) {
this.getFields();
}
},
methods: {
resetFields() {
this.labelField = null;
this.valueField = null;
},
getCollections() {
this.$dataProvider.getCollections().then((response) => {
this.collections = [
{ value: null, text: this.$t("Select a collection") },
...response.data.data.map((collection) => {
return {
text: collection.name,
value: collection.id
};
})
];
});
},
getFields() {
if (!this.collectionId) {
return;
}
this.$dataProvider
.getCollectionFields(this.collectionId)
.then((response) => {
this.fields = [
{ value: null, text: this.$t("Select a field") },
{ value: "id", text: this.$t("Collection Record ID") },
...response.data.data.map((field) => {
return {
text: field.label,
value: field.field
};
})
];
});
},
onNLQConversion(pmql) {
this.pmql = pmql;
},
onPmqlChange(pmql) {
this.pmql = pmql;
}
}
};
</script>
1 change: 1 addition & 0 deletions src/components/inspector/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { default as CollectionSelectList } from "./collection-select-list.vue";
export { default as CollectionRecordsList } from "./collection-records-list.vue";
export { default as ColorSelect } from "./color-select.vue";
export { default as ColumnSetup } from "./column-setup.vue";
export { default as ContainerColumns } from "./container-columns.vue";
Expand Down
203 changes: 203 additions & 0 deletions src/components/renderer/form-collection-record-control.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
<template>
<vue-form-renderer
ref="collectionRecordControl"
class="form-collection-record-control"
:placeholder="placeholder"
v-model="data"
mode="preview"
:config="validatedConfig"
:computed="computed"
:custom-css="customCss"
:watchers="watchers"
:_parent="_parent"
/>
</template>

<script>
import VueFormRenderer from "../vue-form-renderer.vue";
import CollectionRecordsList from "../inspector/collection-records-list.vue";
const globalObject = typeof window === "undefined" ? global : window;
const defaultConfig = [
{
name: "empty",
items: []
}
];
export default {
components: {
VueFormRenderer,
CollectionRecordsList
},
props: {
name: String,
validationData: null,
_parent: null,
record: null,
displayMode: {
type: String,
default: "Edit"
},
collection: {
type: Object
},
},
data() {
return {
localData: {},
config: defaultConfig,
computed: [],
customCSS: null,
watchers: [],
screenTitle: null,
collectionMode: "Edit",
selCollectionId: Number,
selRecordId: Number,
screenCollectionId: null,
placeholder: "Select a collection"
};
},
computed: {
validatedConfig() {
return this.config && this.config[0] ? this.config : defaultConfig;
},
data: {
get() {
return this.localData;
},
set(data) {
Object.keys(data).forEach((variable) => {
this.validationData && this.$set(this.validationData, variable, data[variable]);
});
},
},
},
methods: {
isSubmitButton(item) {
return (
item.config &&
item.component === "FormButton" &&
item.config.event === "submit"
);
},
hideSubmitButtons(config) {
config.forEach((item) => {
//If the element has containers
if (Array.isArray(item)) {
this.hideSubmitButtons(item);
}
//If the element has items
if (item.items) {
this.hideSubmitButtons(item.items);
}
//hidden buttons
if (this.isSubmitButton(item)) {
item.config.hidden = true;
}
});
},
disableForm(config) {
config.forEach((item) => {
//If the element has containers
if (Array.isArray(item)) {
this.disableForm(item);
}
//If the element has items
if (item.items) {
this.disableForm(item.items);
}
//Disable element
if (item && item.config) {
item.config.disabled = true;
item.config.readonly = true;
item.config.editable = false;
}
});
},
loadScreen(id) {
this.config = defaultConfig;
this.computed = [];
this.customCSS = null;
this.watchers = [];
this.screenTitle = null;
if (id) {
this.$dataProvider.getScreen(id).then((response) => {
this.config = response.data.config;
this.hideSubmitButtons(this.config);
this.computed = response.data.computed;
this.customCSS = response.data.custom_css;
this.watchers = response.data.watchers;
this.screenTitle = response.data.title;
if (this.$attrs["disabled"]) {
this.disableForm(this.config);
}
});
}
},
errors() {
this.$refs.nestedScreen.isValid();
return this.$refs.nestedScreen.errors;
},
loadRecordCollection(collectionId, recordId) {
this.selCollectionId = collectionId;
this.selRecordId = recordId;
this.$dataProvider
.getCollectionRecordsView(collectionId, recordId)
.then((response) => {
this.placeholder = "";
const respData = response.data;
//ld = {};
const viewScreen = response.collection.read_screen_id;
const editScreen = response.collection.update_screen_id;
this.screenCollectionId =
this.displayMode === "View" ? viewScreen : editScreen;
this.loadScreen(this.screenCollectionId);
this.localData = respData;
})
.catch(() => {
this.localData = {};
globalObject.ProcessMaker.alert(this.$t('This content does not exist. We could not locate indicated data'), "danger");
});;
},
},
watch: {
collection(collection) {
if(collection) {
this.selCollectionId = collection.collectionId;
}
},
record(record) {
if (record && !isNaN(record) && record > 0 && this.collection) {
this.selRecordId = record;
this.loadRecordCollection(this.selCollectionId, record);
} else {
this.localData = {};
}
},
displayMode(val) {
this.loadRecordCollection(this.selCollectionId, this.selRecordId);
},
},
mounted() {
if (this.collection && this.record) {
this.loadRecordCollection(this.collection.collectionId, this.record);
}
},
};
</script>

<style lang="scss">
.prevent-interaction.form-collection-record-control::after {
content: attr(placeholder);
}
</style>
Loading

0 comments on commit 51af2da

Please sign in to comment.