Skip to content

Commit

Permalink
Predefined text fields (#4059)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaskikutis authored Feb 17, 2022
1 parent 34cc483 commit f772fd4
Show file tree
Hide file tree
Showing 30 changed files with 2,465 additions and 277 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class TestEditorComponent extends React.PureComponent<IEditorComponentProps<stri
}
}

const customField: ICustomFieldType<string> = {
const customField: ICustomFieldType<string, string> = {
id: 'test-custom-authoring-field',
label: 'Test Field',
editorComponent: TestEditorComponent,
Expand Down
4 changes: 2 additions & 2 deletions scripts/apps/fields/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {logger} from 'core/services/logger';
import {extensions} from 'appConfig';
import {ICustomFieldType} from 'superdesk-api';

type ICustomFieldTypeMap = {[id: string]: ICustomFieldType<any>};
type ICustomFieldTypeMap = {[id: string]: ICustomFieldType<any, any>};

export function getFields(): ICustomFieldTypeMap {
const fields: ICustomFieldTypeMap = {};
Expand All @@ -19,7 +19,7 @@ export function getFields(): ICustomFieldTypeMap {
return fields;
}

export function getField(customFieldTypeId: ICustomFieldType<any>['id']): ICustomFieldType<any> | null {
export function getField(customFieldTypeId: ICustomFieldType<any, any>['id']): ICustomFieldType<any, any> | null {
const fields = getFields();
const fieldType = fields[customFieldTypeId];

Expand Down
8 changes: 6 additions & 2 deletions scripts/apps/internal-destinations/InternalDestinations.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/* eslint-disable react/no-multi-comp */

import React from 'react';
import {getGenericListPageComponent, GenericListPageComponent} from 'core/ui/components/ListPage/generic-list-page';
import {
getGenericHttpEntityListPageComponent,
GenericListPageComponent,
} from 'core/ui/components/ListPage/generic-list-page';
import {ListItemColumn, ListItemActionsMenu, ListItem} from 'core/components/ListItem';
import {getFormFieldPreviewComponent} from 'core/ui/components/generic-form/form-field';
import {IInternalDestination} from 'superdesk-interfaces/InternalDestination';
Expand Down Expand Up @@ -140,14 +143,15 @@ export class InternalDestinations extends React.Component {
};

const InternalDestinationsPageComponent =
getGenericListPageComponent<IInternalDestination>('internal_destinations', formConfig);
getGenericHttpEntityListPageComponent<IInternalDestination>('internal_destinations', formConfig);

return (
<InternalDestinationsPageComponent
renderRow={renderRow}
formConfig={formConfig}
defaultSortOption={{field: 'name', direction: 'ascending'}}
fieldForSearch={getNameField()}
getId={(item) => item._id}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {gettext} from 'core/utils';
import {FormFieldType} from 'core/ui/components/generic-form/interfaces/form';
import {ListItem, ListItemActionsMenu, ListItemColumn, ListItemRow} from 'core/components/ListItem';
import {getFormFieldPreviewComponent} from 'core/ui/components/generic-form/form-field';
import {getGenericListPageComponent} from 'core/ui/components/ListPage/generic-list-page';
import {IFormField, IFormGroup, IGenericListPageComponent} from 'superdesk-api';
import {getGenericHttpEntityListPageComponent} from 'core/ui/components/ListPage/generic-list-page';
import {IFormField, IFormGroup, IGenericListPageComponent, IBaseRestApiResponse} from 'superdesk-api';
import {Label} from 'superdesk-ui-framework/react/components/Label';
import {assertNever} from 'core/helpers/typescript-helpers';
import {ISystemMessage, RESOURCE} from '..';
Expand Down Expand Up @@ -128,14 +128,15 @@ export class SystemMessagesSettingsComponent extends React.PureComponent {
</ListItem>
);

const ListComponent = getGenericListPageComponent<ISystemMessage>(RESOURCE, formConfig);
const ListComponent = getGenericHttpEntityListPageComponent<ISystemMessage>(RESOURCE, formConfig);

return (
<Page title={gettext('System Message')}>
<ListComponent
renderRow={renderRow}
formConfig={formConfig}
defaultSortOption={{field: 'message_title', direction: 'ascending'}}
getId={(item) => item._id}
/>
</Page>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import {IArticle, ICustomFieldType, IVocabulary} from 'superdesk-api';
*/
function applyMiddleware(_item: IArticle, content, vocabularies): Promise<IArticle> {
// Custom field types with `onTemplateCreate` defined. From all extensions.
const fieldTypes: {[id: string]: ICustomFieldType<any>} = {};
const fieldTypes: {[id: string]: ICustomFieldType<any, any>} = {};

Object.values(extensions).forEach((ext) => {
ext?.activationResult?.contributions?.customFieldTypes?.forEach((customField: ICustomFieldType<any>) => {
ext?.activationResult?.contributions?.customFieldTypes?.forEach((customField: ICustomFieldType<any, any>) => {
if (customField.onTemplateCreate != null) {
fieldTypes[customField.id] = customField;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ export function VocabularyEditController(
$scope.setCustomFieldConfig = (config) => {
$scope.vocabulary.custom_field_config = config;
$scope.editForm.$setDirty();
$scope.$apply();
$scope.$applyAsync();
};

let placeholderElement = null;
Expand Down
13 changes: 9 additions & 4 deletions scripts/core/get-superdesk-api-implementation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
IUser,
} from 'superdesk-api';
import {gettext, gettextPlural, stripHtmlTags} from 'core/utils';
import {getGenericListPageComponent} from './ui/components/ListPage/generic-list-page';
import {getGenericHttpEntityListPageComponent} from './ui/components/ListPage/generic-list-page';
import {ListItem, ListItemColumn, ListItemRow, ListItemActionsMenu} from './components/ListItem';
import {getFormFieldPreviewComponent} from './ui/components/generic-form/form-field';
import {
Expand All @@ -20,7 +20,7 @@ import {
} from './ui/components/generic-form/interfaces/form';
import {UserHtmlSingleLine} from './helpers/UserHtmlSingleLine';
import {Row, Item, Column} from './ui/components/List';
import {connectCrudManager, dataApi, dataApiByEntity} from './helpers/CrudManager';
import {dataApi, dataApiByEntity} from './helpers/CrudManager';
import {elasticsearchApi} from './helpers/elasticsearch';
import {generateFilterForServer} from './ui/components/generic-form/generate-filter-for-server';
import {
Expand All @@ -31,6 +31,7 @@ import {
stringToNumber,
numberToString,
notNullOrUndefined,
nameof,
} from './helpers/typescript-helpers';
import {getUrlPage, setUrlPage, urlParams} from './helpers/url';
import {downloadBlob} from './helpers/utils';
Expand Down Expand Up @@ -80,6 +81,8 @@ import {showIgnoreCancelSaveDialog} from './ui/components/IgnoreCancelSaveDialog
import {Editor3Html} from './editor3/Editor3Html';
import {arrayToTree, treeToArray} from './helpers/tree';
import {WidgetHeading} from 'apps/dashboard/widget-heading';
import {connectCrudManagerHttp} from './helpers/crud-manager-http';
import {GenericArrayListPageComponent} from './helpers/generic-array-list-page-component';

function getContentType(id): Promise<IContentProfile> {
return dataApi.findOne('content_types', id);
Expand Down Expand Up @@ -197,6 +200,7 @@ export function getSuperdeskApiImplementation(
stringToNumber,
numberToString,
notNullOrUndefined,
nameof: nameof,
},
httpRequestJsonLocal,
getExtensionConfig: () => extensions[requestingExtensionId]?.configuration ?? {},
Expand Down Expand Up @@ -314,8 +318,9 @@ export function getSuperdeskApiImplementation(
},
components: {
UserHtmlSingleLine,
getGenericListPageComponent,
connectCrudManager,
getGenericHttpEntityListPageComponent,
getGenericArrayListPageComponent: () => GenericArrayListPageComponent,
connectCrudManagerHttp: connectCrudManagerHttp,
ListItem,
ListItemColumn,
ListItemRow,
Expand Down
132 changes: 0 additions & 132 deletions scripts/core/helpers/CrudManager.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
/* eslint-disable react/display-name */
import {appConfig} from 'appConfig';
import ng from 'core/services/ng';
import {generate} from 'json-merge-patch';
import {isObject, keyBy, partition} from 'lodash';
import React from 'react';
import {
IBaseRestApiResponse,
ICrudManagerState,
ICrudManagerMethods,
ISortOption,
ICrudManagerFilters,
IRestApiResponse,
IDataApi,
IQueryElasticParameters,
IArticleQueryResult,
Expand All @@ -20,7 +15,6 @@ import {
} from 'superdesk-api';
import {DataProvider} from './data-provider';
import {httpRequestJsonLocal, httpRequestVoidLocal, httpRequestRawLocal, uploadFileWithProgress} from './network';
import {connectServices} from './ReactRenderAsync';
import {ignoreAbortError} from '../SuperdeskReactComponent';

export function queryElastic(
Expand Down Expand Up @@ -333,129 +327,3 @@ export const dataApi: IDataApi = {
createProvider: (requestFactory, responseHandler, listenTo) =>
new DataProvider(requestFactory, responseHandler, listenTo),
};

export function connectCrudManager<Props, PropsToConnect, Entity extends IBaseRestApiResponse>(
// type stoped working after react 16.8 upgrade. See if it's fixed by a future React types or TypeScript update
WrappedComponent, // : React.ComponentType<Props & PropsToConnect>
name: string,
endpoint: string,
formatFiltersForServer?: (filters: ICrudManagerFilters) => ICrudManagerFilters,
): React.ComponentType<Props> {
const component = class extends React.Component<Props, ICrudManagerState<Entity>>
implements ICrudManagerMethods<Entity> {
api: any;

constructor(props) {
super(props);

this.api = props.api(endpoint);

this.state = {
_items: null,
_meta: null,
_links: null,
activeSortOption: null,
activeFilters: {},
};

this.create = this.create.bind(this);
this.read = this.read.bind(this);
this.update = this.update.bind(this);
this.delete = this.delete.bind(this);
this.refresh = this.refresh.bind(this);
this.sort = this.sort.bind(this);
this.removeFilter = this.removeFilter.bind(this);
this.goToPage = this.goToPage.bind(this);
}

create(item: Entity): Promise<Entity> {
// creating an item impacts sorting/filtering/pagination. Data is re-fetched to correct it.
return dataApi.create<Entity>(endpoint, item).then((res) => this.refresh().then(() => res));
}

read(
page: number,
sortOption: ISortOption,
filterValues: ICrudManagerFilters = {},
): Promise<IRestApiResponse<Entity>> {
return dataApi.query(
endpoint,
page,
sortOption,
filterValues,
undefined,
formatFiltersForServer,
)
.then((res: IRestApiResponse<Entity>) => new Promise((resolve) => {
this.setState({
...res,
activeSortOption: sortOption,
activeFilters: filterValues,
}, () => {
resolve(res);
});
}));
}

update(nextItem: Entity): Promise<Entity> {
const currentItem = this.state._items.find(({_id}) => _id === nextItem._id);

// updating an item impacts sorting/filtering/pagination. Data is re-fetched to correct it.
return dataApi.patch<Entity>(endpoint, currentItem, nextItem)
.then((res) => this.refresh().then(() => res));
}

delete(item: Entity): Promise<void> {
// deleting an item impacts sorting/filtering/pagination. Data is re-fetched to correct it.
return dataApi.delete(endpoint, item).then(() => this.refresh().then(() => undefined));
}

refresh(): Promise<IRestApiResponse<Entity>> {
return this.read(this.state._meta.page, this.state.activeSortOption, this.state.activeFilters);
}

sort(sortOption: ISortOption): Promise<IRestApiResponse<Entity>> {
return this.read(1, sortOption);
}

removeFilter(fieldName: string): Promise<IRestApiResponse<Entity>> {
let nextFilters = {...this.state.activeFilters};

delete nextFilters[fieldName];

return this.read(1, this.state.activeSortOption, nextFilters);
}

goToPage(nextPage: number) {
return this.read(nextPage, this.state.activeSortOption, this.state.activeFilters);
}

render() {
// workaround for typescript bug
// https://github.com/Microsoft/TypeScript/issues/28748#issuecomment-450497274
const fixedProps = this.props as any;

return (
<WrappedComponent
{
...{
[name]: {
...this.state,
create: this.create,
read: this.read,
update: this.update,
delete: this.delete,
sort: this.sort,
removeFilter: this.removeFilter,
goToPage: this.goToPage,
},
}
}
{...fixedProps}
/>
);
}
};

return connectServices(component, ['api']);
}
Loading

0 comments on commit f772fd4

Please sign in to comment.