Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle validate for choices #4793

Merged
merged 10 commits into from
Nov 13, 2024
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
### Changes

* Removes postcss plugin and webpack loader used for breakpoint preview mode. Uses instead the new `postcss-viewport-to-container-toggle` plugin in the webpack config.
* Removes error messages in server console for hidden fields. These messages should not have been printed out in the server console in the first place.
* Removes invalid error messages on select fields appearing while opening an existing valid document.

## 4.9.0 (2024-10-31)

Expand Down
46 changes: 35 additions & 11 deletions modules/@apostrophecms/schema/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -577,10 +577,21 @@ module.exports = {
// `destination` (the current level). This allows resolution of relative
// `following` paths during sanitization.

async convert(req, schema, data, destination, { fetchRelationships = true, ancestors = [] } = {}) {
async convert(
req,
schema,
data,
destination,
{
fetchRelationships = true,
ancestors = [],
isParentVisible = true
} = {}
) {
const options = {
fetchRelationships,
ancestors
ancestors,
isParentVisible
};
if (Array.isArray(req)) {
throw new Error('convert invoked without a req, do you have one in your context?');
Expand All @@ -603,6 +614,9 @@ module.exports = {

if (convert) {
try {
const isAllParentsVisible = isParentVisible === false
? false
: await self.isVisible(req, schema, destination, field.name);
const isRequired = await self.isFieldRequired(req, field, destination);
await convert(
req,
Expand All @@ -612,7 +626,10 @@ module.exports = {
},
data,
destination,
options
{
...options,
isParentVisible: isAllParentsVisible
}
);
} catch (error) {
if (Array.isArray(error)) {
Expand All @@ -635,7 +652,9 @@ module.exports = {
if (error.path) {
// `self.isVisible` will only throw for required fields that have
// an external condition containing an unknown module or method:
const isVisible = await self.isVisible(req, schema, destination, error.path);
const isVisible = isParentVisible === false
? false
: await self.isVisible(req, schema, destination, error.path);

if (!isVisible) {
// It is not reasonable to enforce required,
Expand All @@ -652,10 +671,15 @@ module.exports = {
// for a field that is not visible should be quietly discarded.
// We only worry about this if the value is not valid, as otherwise
// it's a kindness to save the work so the user can toggle back to it
destination[field.name] = klona((field.def !== undefined) ? field.def : self.fieldTypes[field.type]?.def);
destination[field.name] = klona((field.def !== undefined)
? field.def
: self.fieldTypes[field.type]?.def);
continue;
}
}
if (isParentVisible === false) {
continue;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@boutell Would like your opinion on that:
In this file just before line 672 we add default value to hidden fields.
If this is necessary, I suppose that we should do the same thing when a parent is hidden?
WDYT?

}

if (!Array.isArray(error) && typeof error !== 'string') {
Expand Down Expand Up @@ -907,7 +931,7 @@ module.exports = {
const find = manager.find;

const options = {
find: find,
find,
builders: { relationships: withRelationshipsNext[relationship._dotPath] || false }
};
const subname = relationship.name + ':' + type;
Expand Down Expand Up @@ -960,7 +984,7 @@ module.exports = {
const find = manager.find;

const options = {
find: find,
find,
builders: { relationships: withRelationshipsNext[relationship._dotPath] || false }
};

Expand Down Expand Up @@ -1195,7 +1219,7 @@ module.exports = {
const idsStorage = field.idsStorage;
const ids = await query.toDistinct(idsStorage);
const manager = self.apos.doc.getManager(field.withType);
const relationshipQuery = manager.find(query.req, { aposDocId: { $in: ids } }).project(manager.getRelationshipQueryBuilderChoicesProjection({ field: field }));
const relationshipQuery = manager.find(query.req, { aposDocId: { $in: ids } }).project(manager.getRelationshipQueryBuilderChoicesProjection({ field }));
if (field.builders) {
relationshipQuery.applyBuilders(field.builders);
}
Expand Down Expand Up @@ -1798,9 +1822,9 @@ module.exports = {
const values = await query.toDistinct(field.name);

const choices = _.map(values, function (value) {
const choice = _.find(allChoices, { value: value });
const choice = _.find(allChoices, { value });
return {
value: value,
value,
label: choice && (choice.label || value)
};
});
Expand Down Expand Up @@ -1983,7 +2007,7 @@ module.exports = {
fields[name] = component;
}
browserOptions.action = self.action;
browserOptions.components = { fields: fields };
browserOptions.components = { fields };
browserOptions.fieldMetadataComponents = self.fieldMetadataComponents;
browserOptions.customCellIndicators = self.uiManagerIndicators;
return browserOptions;
Expand Down
49 changes: 41 additions & 8 deletions modules/@apostrophecms/schema/lib/addFieldTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,17 @@ module.exports = (self) => {

self.addFieldType({
name: 'array',
async convert(req, field, data, destination, { fetchRelationships = true, ancestors = [] } = {}) {
async convert(
req,
field,
data,
destination,
{
fetchRelationships = true,
ancestors = [],
isParentVisible = true
} = {}
) {
const schema = field.schema;
data = data[field.name];
if (!Array.isArray(data)) {
Expand All @@ -779,7 +789,8 @@ module.exports = (self) => {
try {
const options = {
fetchRelationships,
ancestors: [ ...ancestors, destination ]
ancestors: [ ...ancestors, destination ],
isParentVisible
};
await self.convert(req, schema, datum, result, options);
} catch (e) {
Expand Down Expand Up @@ -861,9 +872,18 @@ module.exports = (self) => {

self.addFieldType({
name: 'object',
async convert(req, field, data, destination, {
fetchRelationships = true, ancestors = {}, doc = {}
} = {}) {
async convert(
req,
field,
data,
destination,
{
fetchRelationships = true,
ancestors = {},
isParentVisible = true,
doc = {}
} = {}
) {
data = data[field.name];
const schema = field.schema;
const errors = [];
Expand All @@ -873,7 +893,8 @@ module.exports = (self) => {
};
const options = {
fetchRelationships,
ancestors: [ ...ancestors, destination ]
ancestors: [ ...ancestors, destination ],
isParentVisible
};
if (data == null || typeof data !== 'object' || Array.isArray(data)) {
data = {};
Expand Down Expand Up @@ -963,8 +984,20 @@ module.exports = (self) => {
// properties is handled at a lower level in a beforeSave
// handler of the doc-type module.

async convert(req, field, data, destination, { fetchRelationships = true } = {}) {
const options = { fetchRelationships };
async convert(
req,
field,
data,
destination,
{
fetchRelationships = true,
isParentVisible = true
} = {}
) {
const options = {
fetchRelationships,
isParentVisible
};
const manager = self.apos.doc.getManager(field.withType);
if (!manager) {
throw Error('relationship with type ' + field.withType + ' unrecognized');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ const DEBOUNCE_TIMEOUT = 500;
export default {
data() {
return {
choices: []
choices: [],
enableValidate: false
};
},

Expand All @@ -33,6 +34,7 @@ export default {

methods: {
async getChoices() {
this.enableValidate = false;
if (typeof this.field.choices === 'string') {
const action = this.options.action;
const response = await apos.http.post(
Expand All @@ -58,10 +60,12 @@ export default {
}
},
updateChoices(choices) {
this.enableValidate = true;
this.choices = choices;
if (this.field.type === 'select') {
this.prependEmptyChoice();
}
this.validate(this.next);
},
prependEmptyChoice() {
// Using `hasOwn` here, not simply checking if `field.def` is truthy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ export default {
// You must supply the validate method. It receives the
// internal representation used for editing (a string, for instance)
validateAndEmit () {
if (this.enableValidate === false) {
return;
}
// If the field is conditional and isn't shown, disregard any errors.
const error = this.conditionMet === false ? false : this.validate(this.next);

Expand Down
Loading