Skip to content

Commit

Permalink
Planning authoring-react fields (#2147)
Browse files Browse the repository at this point in the history
  • Loading branch information
thecalcc authored Dec 12, 2024
1 parent 5b5a3d4 commit d0cd58a
Show file tree
Hide file tree
Showing 10 changed files with 321 additions and 154 deletions.
13 changes: 8 additions & 5 deletions client/components/fields/editor/CustomVocabularies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import {getVocabularyItemFieldTranslated} from '../../../utils/vocabularies';
import {arrayToTree} from 'superdesk-core/scripts/core/helpers/tree';
import {TreeSelect} from 'superdesk-ui-framework/react';

interface IProps extends IEditorFieldProps {
export interface ICustomVocabulariesProps extends IEditorFieldProps {
schema?: IProfileSchemaTypeList;
}

interface IReduxStateProps {
vocabularies: Array<IVocabulary>;
popupContainer?(): HTMLElement;
onPopupOpen?(): void;
onPopupClose?(): void;
}

type IProps = ICustomVocabulariesProps & IReduxStateProps;

const mapStateToProps = (state) => ({
vocabularies: state.customVocabularies,
});
Expand Down Expand Up @@ -93,4 +95,5 @@ class CustomVocabulariesComponent extends React.PureComponent<IProps> {
}
}

export const EditorFieldCustomVocabularies = connect(mapStateToProps)(CustomVocabulariesComponent);
export const EditorFieldCustomVocabularies =
connect<IReduxStateProps, {}, ICustomVocabulariesProps>(mapStateToProps)(CustomVocabulariesComponent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import {IDropdownConfigVocabulary, IAuthoringFieldV2, ISubject, IVocabularyItem} from 'superdesk-api';
import {superdeskApi} from '../../../superdeskApi';
import {IFieldDefinition} from '../profile';
import {getPlanningProfileFields} from '../profile-fields';

export const getCustomVocabularyFields = () => {
const customVocabularyIds = getPlanningProfileFields()
.filter((x) => x.type === 'custom_vocabulary')
.map(({vocabularyId}) => vocabularyId);
const result: Array<IFieldDefinition> = [];

if ((customVocabularyIds?.length ?? 0) > 0) {
const allVocabularies = superdeskApi.entities.vocabulary.getAll();

for (const id of customVocabularyIds) {
const vocabulary = allVocabularies.get(id);

result.push({
fieldId: id,
getField: ({required, id: _id}) => {
const fieldConfig: IDropdownConfigVocabulary = {
source: 'vocabulary',
vocabularyId: id,
multiple: true,
required: required,
};

const field: IAuthoringFieldV2 = {
id: _id,
name: vocabulary.display_name,
fieldType: 'dropdown',
fieldConfig: fieldConfig,
};

return field;
},
storageAdapter: {
storeValue: (item, operationalValue: IVocabularyItem['qcode']) => {
const vocabulary = allVocabularies.get(id);
const vocabItems = vocabulary.items.filter((x) => operationalValue.includes(x.qcode));

// Subfield values
const itemsToSubject: Array<ISubject> = vocabItems.map((x) => ({
name: x.name,
qcode: x.qcode,
scheme: vocabulary._id,
}));

// Remove values that don't match the "subfield" ID, so there's no item duplication
const restOfValues = (item.subject ?? []).filter((x) => x.scheme !== id);

return {
...item,
subject: [
...itemsToSubject,
...restOfValues,
],
};
},
retrieveStoredValue: (item) => {
return (item.subject ?? []).filter((x) => x.scheme === id).map((x) => x.qcode);
},
}
});
}
}

return result;
};
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ export class PlanningEditorStandaloneComponent extends React.PureComponent<IProp
// PR-TODO: add a close button that will collapse the accordion
return {readOnly: false, actions: [saveButton]};
}}
getAuthoringPrimaryToolbarWidgets={() => []}
secondaryToolbarWidgets={[]}
getSidebarWidgetsCount={() => 0}
getSidebar={() => null}
sideWidget={null}
Expand All @@ -124,4 +122,4 @@ function mapStateToProps(state: IPlanningAppState): IReduxProps {
};
}

export const PlanningEditorStandalone = connect(mapStateToProps)(PlanningEditorStandaloneComponent);
export const PlanningEditorStandalone = connect(mapStateToProps)(PlanningEditorStandaloneComponent);
48 changes: 48 additions & 0 deletions client/components/planning-editor-standalone/profile-fields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {flatMap} from 'lodash';
import {planningApi} from '../../superdeskApi';
import {getEditorFormGroupsFromProfile} from '../../utils/contentProfiles';

interface IBaseField<T> {
type: T;
fieldId: string;
required: boolean;
}

interface ICustomVocabularyField extends IBaseField<'custom_vocabulary'> {
vocabularyId: string;
}

type IFieldConverted = IBaseField<'normal'> | ICustomVocabularyField;

/**
* A function that handles planning profile field types so they can be used in authoring react.
*/
export const getPlanningProfileFields = (): Array<IFieldConverted> => {
const planningProfile = planningApi.contentProfiles.get('planning');
const planningGroups = getEditorFormGroupsFromProfile(planningProfile);
const planningFieldIds = Object.values(planningGroups).flatMap((x) => x.fields);
const convertedFieldIds: Array<IFieldConverted> = [];

for (const fieldId of planningFieldIds) {
const fieldSchema = planningProfile.schema[fieldId];

if (fieldSchema?.type === 'list' && ((fieldSchema.vocabularies ?? []).length > 0)) {
for (const vocabId of fieldSchema.vocabularies) {
convertedFieldIds.push({
type: 'custom_vocabulary',
fieldId: vocabId,
required: fieldSchema.required ?? false,
vocabularyId: vocabId,
});
}
} else {
convertedFieldIds.push({
type: 'normal',
fieldId: fieldId,
required: fieldSchema.required ?? false,
});
}
}

return convertedFieldIds;
};
Loading

0 comments on commit d0cd58a

Please sign in to comment.