File

packages/data/src/lib/model-config/model-config.service.ts

Description

The main class for configuring the behaviour of a model. By default, everything is auto generated from the model's schema but can be overriden via the set method.

Extends

Config

Index

Properties
Methods

Constructor

constructor(entryService: EntryService, sdk: SdkService, typeConfig: TypeConfigService, symbol: SymbolService)

Injects EntryService and SdkService.

Parameters :
Name Type Optional
entryService EntryService No
sdk SdkService No
typeConfig TypeConfigService No
symbol SymbolService No

Methods

Async generateConfig
generateConfig(model: string, customFieldConfig?: FieldConfig)

Generates a CrudConfig for the given model. Merges three configurations into one:

  • default field config, obtained by getFieldConfig
  • global model config (if any) configured via with set
  • customFieldConfig: any custom field config that is merged on top of the other two. This enables the developer to either customize at a global scale to target all lists/forms, or just specific components.
Parameters :
Name Type Optional
model string No
customFieldConfig FieldConfig Yes
get
get(property: string)

Retrieves the given model config.

Parameters :
Name Type Optional
property string No
Example :
```typescript</p>
<ul>
<li>ModelConfig.get(&#39;muffin&#39;); //returns muffin config;</li>
<li>```</li>
</ul>
getFieldConfig
getFieldConfig(model: string)

Returns the default field config for the given model. Utilizes PublicAPI#getFieldConfig + TypeConfigService#get. This config is meant to deliver the default behaviour when nothing else is configured.

Parameters :
Name Type Optional
model string No
getLightModel
getLightModel(model)

Returns light model information

Parameters :
Name Optional
model No
Returns : any
getMinLevel
getMinLevel(model: string, customFieldConfig?: FieldConfig)

Parses config for fields that require leveled entries

Parameters :
Name Type Optional
model string No
customFieldConfig FieldConfig Yes
Returns : any
getSystemFields
getSystemFields()

Returns the field config for all system fields

Returns : { id: { label: any; create: boolean; view: string; filterView: string; filterable: boolean; filte...
set
set(property: string, config: CrudConfig)

Sets the given model config.

Parameters :
Name Type Optional
property string No
config CrudConfig<EntryResource> No
Example :
```typescript</p>
<ul>
<li>ModelConfig.set(&#39;muffin&#39;, {</li>
<li>fields: {</li>
<li>title: {</li>
<li>label: &#39;Muffin Titel&#39;</li>
<li>}</li>
<li>});</li>
<li>```</li>
</ul>
Public Optional configure
configure(key: string, property: string, config?: Object)
Inherited from Config
Defined in Config:13

This method is a getter and setter for configurations. The key stands for the config (e.g. model). The property is a sub property if the config (e.g. fields => model.fields). If no config is given, the method just returns the configuration for the given property. If a config is given, the property config is merged via Object.assign.

Parameters :
Name Type Optional
key string No
property string No
config Object Yes
Returns : any

Properties

omittedFields
Type : Array<string>
Default value : ['id', 'private', 'created', 'creator', 'modified']

Array of property names that are omitted by default.

Private config
Type : literal type
Default value : {}
Inherited from Config
Defined in Config:5

The config object.

import { Injectable } from '@angular/core';
import { Config, FieldConfig, Item } from '@ec.components/core';
import { SymbolService, DefaultInputComponent } from '@ec.components/ui';
import { fields } from 'ec.sdk/lib/PublicAPI';
import EntryResource from 'ec.sdk/lib/resources/publicAPI/EntryResource';
import { CrudConfig } from '../crud/crud-config.interface';
import { EntryService } from '../entry/entry.service';
import { SdkService } from '../sdk/sdk.service';
import { TypeConfigService } from './type-config.service';
import { AdminEntryInputComponent } from '../entry-form/admin-entry-input.component';
import { DefaultEntryOutputComponent } from '../entry-form/default-entry-output.component';

/** The main class for configuring the behaviour of a model.
 * By default, everything is auto generated from the model's schema but can be overriden via the
 * set method. */
@Injectable()
export class ModelConfigService extends Config {
  /** Array of property names that are omitted by default. */
  omittedFields: Array<string> = ['id', 'private', 'created', 'creator', 'modified'];

  /** Injects EntryService and SdkService. */
  constructor(
    private entryService: EntryService,
    private sdk: SdkService,
    private typeConfig: TypeConfigService,
    private symbol: SymbolService,
  ) {
    super();
  }

  /** Retrieves the given model config.
   * @example
   * ```typescript
   * ModelConfig.get('muffin'); //returns muffin config;
   * ```
   * */
  get(property: string): CrudConfig<EntryResource> {
    return this.configure('model', property);
  }

  /** Sets the given model config.
   * @example
   * ```typescript
   * ModelConfig.set('muffin', {
   *  fields: {
   *    title: {
   *      label: 'Muffin Titel'
   *    }
   *  });
   * ```
   * */
  set(property: string, config: CrudConfig<EntryResource>): CrudConfig<EntryResource> {
    return this.configure('model', property, config);
  }

  /** Returns the field config for all system fields */
  getSystemFields() {
    return {
      id: {
        label: this.symbol.resolve('field.label.id'),
        create: false,
        view: 'copy',
        filterView: 'string',
        filterable: true,
        filterOperator: 'exact',
        form: true,
        immutable: true,
        disabled: true,
        hideInList: true,
        columns: 3,
      },
      _created: {
        label: this.symbol.resolve('field.label.created'),
        display: this.typeConfig.displayDate(),
        group: this.typeConfig.groupDate(),
        copy: this.typeConfig.isoDate(),
        create: false,
        form: true,
        columns: 3,
        view: 'copy',
        immutable: true,
        disabled: true,
        sortable: true,
        hideInList: true,
        rawFilter: true,
      },
      _modified: {
        label: this.symbol.resolve('field.label.modified'),
        display: this.typeConfig.displayDate(),
        group: this.typeConfig.groupDate(),
        copy: this.typeConfig.isoDate(),
        create: false,
        form: true,
        columns: 3,
        view: 'copy',
        immutable: true,
        disabled: true,
        sortable: true,
        hideInList: false,
        rawFilter: true,
      },
      _creator: {
        label: this.symbol.resolve('field.label.creator'),
        display: this.typeConfig.displayAccount(),
        copy: this.typeConfig.displayAccount(),
        create: false,
        type: 'account',
        view: 'copy',
        columns: 3,
        form: true,
        immutable: true,
        disabled: true,
        hideInList: true,
        filterable: true,
        filterComponent: AdminEntryInputComponent,
        formComponent: DefaultInputComponent,
        output: DefaultEntryOutputComponent,
        readOnly: true,
        filterOperator: 'exact',
      },
    };
  }

  /** Parses config for fields that require leveled entries */
  getMinLevel(model: string, customFieldConfig?: FieldConfig) {
    return this.generateConfig(model, customFieldConfig).then((modelConfig) => {
      const fieldConfig = modelConfig.fields;
      return Object.keys(fieldConfig)
        .filter((field) => !!fieldConfig[field].type)
        .map((field) => {
          const inputView = fieldConfig[field].inputView;
          const views = this.typeConfig.get(fieldConfig[field].type).inputViews || [];
          if (!inputView || !views) {
            return 1;
          }
          const match = views.find((v) => v.name === inputView);
          return match ? match.levels || 1 : 1;
        })
        .reduce((max, lvl) => Math.max(max, lvl), 1);
    });
  }

  /** Returns the default field config for the given model.
   * Utilizes PublicAPI#getFieldConfig + TypeConfigService#get.
   * This config is meant to deliver the default behaviour when nothing else is configured. */
  getFieldConfig(model: string): Promise<FieldConfig> {
    return this.sdk.api.getFieldConfig(model).then((fieldConfig: fields) => {
      const merged = {};
      Object.assign(merged, this.getSystemFields());
      Object.keys(fieldConfig)
        .map((property) => fieldConfig[property])
        .forEach(
          ({ config, type, title, unique, mutable, readOnly, required, validation, description, localizable }) => {
            /* type = type as string; */
            config = config || {};
            if (type.includes('asset')) {
              type = type.replace('a', 'dmA');
            }
            // parse field config
            const {
              hideInList,
              hideInForm,
              hideOnCreate,
              hideOnEdit,
              placeholder,
              inputView,
              outputView,
              label,
              classes,
              disabled,
              columns = 12,
            } = config;
            const typeConfig = this.typeConfig.get(type);
            // assign default values + merge customFieldConfig if given
            merged[title] = Object.assign(
              {
                property: title,
                label: label || title + (type === 'datetime' ? ` ${this.symbol.resolve('datetime.local')}` : ''),
                placeholder,
                description,
                validation,
                relation: validation,
                immutable: !mutable,
                disabled,
                readOnly,
                hideInList,
                hideInForm,
                create: !hideOnCreate,
                edit: !hideOnEdit,
                classes,
                unique,
                required,
                columns,
                /* display: ((value) => value), */
                localizable,
              },
              typeConfig,
              {
                placeholder: placeholder || typeConfig.placeholder,
                inputView: inputView || typeConfig.inputView,
                outputView: outputView || typeConfig.outputView,
              },
            );
          },
        );
      return merged;
    });
  }

  /** Generates a CrudConfig for the given model.
   * Merges three configurations into one:
   * - default field config, obtained by getFieldConfig
   * - global model config (if any) configured via with set
   * - customFieldConfig: any custom field config that is merged on top of the other two.
   * This enables the developer to either customize at a global scale to target all lists/forms,
   * or just specific components. */
  async generateConfig(model: string, customFieldConfig?: FieldConfig): Promise<CrudConfig<EntryResource>> {
    const lightModel = await this.getLightModel(model);
    const { singularLabel } = lightModel.config;
    // first step: merge global model config with default entry config
    const modelConfig = Object.assign(this.get(model) || {}, {
      singularLabel,
      identifier: 'id',
      identifierPattern: /^[0-9A-Za-z-_]{7,14}$/, // shortID pattern
      label: '_entryTitle',
      defaultFilter: lightModel.titleField,
      onSave: (item: Item<EntryResource>, value) => this.entryService.save(model, item, value),
    });
    return this.getFieldConfig(model).then((fieldConfig: FieldConfig) => {
      const modelConfigFields = modelConfig.fields || {};
      const relevantKeys = Object.keys(customFieldConfig || modelConfigFields);
      const mergedFields = {};
      if (!relevantKeys.length) {
        modelConfig.fields = fieldConfig;
      } else {
        relevantKeys.forEach((key) => {
          mergedFields[key] = Object.assign(
            {},
            fieldConfig[key] || {},
            modelConfigFields[key] || {},
            (customFieldConfig || {})[key],
          );
        });
        modelConfig.fields = mergedFields;
      }
      return modelConfig;
    });
  }
  /** Returns light model information */
  getLightModel(model) {
    return this.sdk.ready.then(() => this.sdk.api.modelList()).then((models) => models[model]);
  }
}

result-matching ""

    No results matching ""