diff --git a/client/components/ContentProfiles/FieldTab/FieldEditor.tsx b/client/components/ContentProfiles/FieldTab/FieldEditor.tsx index c61a88845..425963408 100644 --- a/client/components/ContentProfiles/FieldTab/FieldEditor.tsx +++ b/client/components/ContentProfiles/FieldTab/FieldEditor.tsx @@ -85,6 +85,12 @@ export class FieldEditor extends React.Component { multilingual.isEnabled(this.props.profile); const fieldProps = { + 'schema.show_in_embedded_editor': { + /** + * Coverage fields don't need this field config option, only planning and event + */ + enabled: !this.props.systemRequired && this.props.profile._id !== 'coverage', + }, 'schema.required': {enabled: !(this.props.disableRequired || this.props.systemRequired)}, 'schema.read_only': {enabled: this.props.item.name === 'related_plannings'}, 'schema.planning_auto_publish': {enabled: this.props.item.name === 'related_plannings'}, @@ -178,21 +184,22 @@ export class FieldEditor extends React.Component { 'editor', { 'schema.required': {enabled: true, index: 1}, - 'schema.read_only': {enabled: true, index: 2}, - 'schema.field_type': {enabled: true, index: 3}, - 'schema.expandable': {enabled: true, index: 4}, - 'schema.minlength': {enabled: true, index: 5}, - 'schema.maxlength': {enabled: true, index: 6}, - 'schema.format_options': {enabled: true, index: 7}, - 'schema.vocabularies': {enabled: true, index: 8}, - 'field.all_day.enabled': {enabled: true, index: 9}, - 'field.default_duration_on_change': {enabled: true, index: 10}, - 'schema.multilingual': {enabled: true, index: 11}, - 'schema.languages': {enabled: true, index: 12}, - 'schema.default_language': {enabled: true, index: 13}, - 'schema.planning_auto_publish': {enabled: true, index: 14}, - 'schema.cancel_plan_with_event': {enabled: true, index: 14}, - 'schema.default_value': {enabled: true, index: 11}, + 'schema.show_in_embedded_editor': {enabled: true, index: 2}, + 'schema.read_only': {enabled: true, index: 3}, + 'schema.field_type': {enabled: true, index: 4}, + 'schema.expandable': {enabled: true, index: 5}, + 'schema.minlength': {enabled: true, index: 6}, + 'schema.maxlength': {enabled: true, index: 7}, + 'schema.format_options': {enabled: true, index: 8}, + 'schema.vocabularies': {enabled: true, index: 9}, + 'field.all_day.enabled': {enabled: true, index: 10}, + 'field.default_duration_on_change': {enabled: true, index: 11}, + 'schema.multilingual': {enabled: true, index: 12}, + 'schema.languages': {enabled: true, index: 13}, + 'schema.default_language': {enabled: true, index: 14}, + 'schema.planning_auto_publish': {enabled: true, index: 15}, + 'schema.cancel_plan_with_event': {enabled: true, index: 16}, + 'schema.default_value': {enabled: true, index: 17}, }, { item: this.props.item, diff --git a/client/components/ContentProfiles/FieldTab/index.tsx b/client/components/ContentProfiles/FieldTab/index.tsx index 9385eedf9..6859dd63f 100644 --- a/client/components/ContentProfiles/FieldTab/index.tsx +++ b/client/components/ContentProfiles/FieldTab/index.tsx @@ -263,7 +263,15 @@ export class FieldTab extends React.Component { {this.state.selectedField == null ? null : ( { + const profileRes = cloneDeep(this.state.selectedField); + + if (profileRes.schema?.required === true) { + profileRes.schema.show_in_embedded_editor = true; + } + + return profileRes; + })()} profile={this.props.profile} isDirty={this.isEditorDirty()} disableMinMax={this.props.disableMinMaxFields?.includes(this.state.selectedField.name)} diff --git a/client/components/fields/editor/index.tsx b/client/components/fields/editor/index.tsx index 52aecf12b..7088f35dc 100644 --- a/client/components/fields/editor/index.tsx +++ b/client/components/fields/editor/index.tsx @@ -54,6 +54,10 @@ import {EditorFieldScheduledUpdates} from './ScheduledUpdates'; import {EditorFieldCustomVocabularies} from './CustomVocabularies'; import {EditorFieldAssignedCoverageComponent} from './AssignedCoverage'; +/** + * This is the single source of truth for field definitions, allows for registering + * other fields from a different place through `registerEditorField` +*/ export const FIELD_TO_EDITOR_COMPONENT = { anpa_category: EditorFieldCategories, featured: EditorFieldFeatured, diff --git a/client/components/fields/resources/profiles.ts b/client/components/fields/resources/profiles.ts index 6b12e1ee2..a496e09aa 100644 --- a/client/components/fields/resources/profiles.ts +++ b/client/components/fields/resources/profiles.ts @@ -24,6 +24,18 @@ registerEditorField( true ); +registerEditorField( + 'schema.show_in_embedded_editor', + EditorFieldCheckbox, + (props) => ({ + label: superdeskApi.localization.gettext('Show in embedded form'), + field: 'schema.show_in_embedded_editor', + disabled: props.item.schema.required, + }), + null, + true +); + registerEditorField( 'schema.read_only', EditorFieldCheckbox, diff --git a/client/components/planning-editor-standalone/field-adapters/custom-vocabularies.ts b/client/components/planning-editor-standalone/field-adapters/custom-vocabularies.ts index dd1a3f65a..7455de848 100644 --- a/client/components/planning-editor-standalone/field-adapters/custom-vocabularies.ts +++ b/client/components/planning-editor-standalone/field-adapters/custom-vocabularies.ts @@ -4,7 +4,7 @@ import {getPlanningProfileFields} from '../profile-fields'; import {IFieldDefinition} from '../field-definitions/interfaces'; export const getCustomVocabularyFields = () => { - const customVocabularyIds = getPlanningProfileFields() + const customVocabularyIds = getPlanningProfileFields({embeddedOnly: true}) .filter((x) => x.type === 'custom_vocabulary') .map(({vocabularyId}) => vocabularyId); const result: Array = []; diff --git a/client/components/planning-editor-standalone/profile-fields.ts b/client/components/planning-editor-standalone/profile-fields.ts index b1271c6a9..9fb4c2b66 100644 --- a/client/components/planning-editor-standalone/profile-fields.ts +++ b/client/components/planning-editor-standalone/profile-fields.ts @@ -23,8 +23,9 @@ const unimplementedFields = new Set([ /** * A function that handles planning profile field types so they can be used in authoring react. + * @embeddedOnly defaults to false */ -export const getPlanningProfileFields = (): Array => { +export const getPlanningProfileFields = (options: {embeddedOnly?: boolean}): Array => { const planningProfile = planningApi.contentProfiles.get('planning'); const planningGroups = getEditorFormGroupsFromProfile(planningProfile); const planningFieldIds = Object.values(planningGroups) @@ -35,6 +36,14 @@ export const getPlanningProfileFields = (): Array => { for (const fieldId of planningFieldIds) { const fieldSchema = planningProfile.schema[fieldId]; + /** + * If a field does not have show_in_embedded_editor or required toggled on + * we must not show it in the embedded editor + */ + if (options.embeddedOnly && !(fieldSchema.show_in_embedded_editor || fieldSchema.required)) { + continue; + } + if (fieldSchema?.type === 'list' && ((fieldSchema.vocabularies ?? []).length > 0)) { for (const vocabId of fieldSchema.vocabularies) { convertedFieldIds.push({ diff --git a/client/components/planning-editor-standalone/profile.ts b/client/components/planning-editor-standalone/profile.ts index c73e127c3..e15429ef5 100644 --- a/client/components/planning-editor-standalone/profile.ts +++ b/client/components/planning-editor-standalone/profile.ts @@ -5,7 +5,7 @@ import {getPlanningProfileFields} from './profile-fields'; import {getFieldDefinitions} from './field-definitions/index'; export function getProfile() { - const planningFieldIds = getPlanningProfileFields(); + const planningFieldIds = getPlanningProfileFields({embeddedOnly: true}); const skipped = new Set(); const fieldDefinitions = getFieldDefinitions(); const profileV2: IContentProfileV2 = { diff --git a/client/interfaces.ts b/client/interfaces.ts index 1544917eb..3aa16fd2f 100644 --- a/client/interfaces.ts +++ b/client/interfaces.ts @@ -1031,6 +1031,7 @@ interface IProfileEditorDatesField extends IProfileEditorField { interface IBaseProfileSchemaType { type: T; required: boolean; + show_in_embedded_editor?: boolean; validate_on_post?: boolean; minlength?: number; maxlength?: number;