huridocs/uwazi

View on GitHub
app/shared/getIXSuggestionState.ts

Summary

Maintainability
A
2 hrs
Test Coverage
A
100%
import { isSameDate } from 'shared/isSameDate';
import { PropertySchema } from 'shared/types/commonTypes';
import { IXSuggestionStateType } from './types/suggestionType';
import { setsEqual } from './data_utils/setUtils';
import {
  propertyIsMultiselect,
  propertyIsRelationship,
  propertyIsSelect,
  propertyIsSelectOrMultiSelect,
} from './propertyTypes';

const propertyIsMultiValued = (propertyType: PropertySchema['type']) =>
  propertyIsMultiselect(propertyType) || propertyIsRelationship(propertyType);

type CurrentValue = string | number | null;

type SuggestedValue = string[] | string | null;

interface SuggestionValues {
  currentValue: CurrentValue | CurrentValue[];
  labeledValue: string | null;
  suggestedValue: SuggestedValue;
  modelCreationDate: number;
  error: string;
  date: number;
  segment: string | null;
  state: string | null;
  status: string | null;
}

const sameValueSet = (first: string[], second: string[]) => setsEqual(first || [], second || []);

const EQUALITIES: Record<string, (first: any, second: any) => boolean> = {
  date: isSameDate,
  multiselect: sameValueSet,
  relationship: sameValueSet,
};

const equalsForType = (type: PropertySchema['type']) => (first: any, second: any) =>
  EQUALITIES[type] ? EQUALITIES[type](first, second) : first === second;

class IXSuggestionState implements IXSuggestionStateType {
  labeled = false;

  withValue = false;

  withSuggestion = false;

  match: boolean | undefined;

  hasContext = false;

  obsolete = false;

  processing = false;

  error = false;

  constructor(values: SuggestionValues, propertyType: PropertySchema['type']) {
    this.setLabeled(values, propertyType);
    this.setWithValue(values, propertyType);
    this.setWithSuggestion(values, propertyType);
    this.setMatch(values, propertyType);
    this.setHasContext(values, propertyType);
    this.setObsolete(values);
    this.setProcessing(values);
    this.setError(values);
  }

  setLabeled(
    { labeledValue, currentValue }: SuggestionValues,
    propertyType: PropertySchema['type']
  ) {
    if (
      labeledValue ||
      (propertyIsSelect(propertyType) && currentValue) ||
      (propertyIsMultiValued(propertyType) &&
        Array.isArray(currentValue) &&
        currentValue.length > 0)
    ) {
      this.labeled = true;
    }
  }

  setWithValue({ currentValue }: SuggestionValues, propertyType: PropertySchema['type']) {
    if (propertyIsMultiValued(propertyType) && Array.isArray(currentValue)) {
      this.withValue = currentValue?.length > 0;
    } else if (currentValue) {
      this.withValue = true;
    }
  }

  setWithSuggestion({ suggestedValue }: SuggestionValues, propertyType: PropertySchema['type']) {
    if (propertyIsMultiValued(propertyType) && Array.isArray(suggestedValue)) {
      this.withSuggestion = suggestedValue?.length > 0;
    } else if (suggestedValue) {
      this.withSuggestion = true;
    }
  }

  setMatch(
    { suggestedValue, currentValue }: SuggestionValues,
    propertyType: PropertySchema['type']
  ) {
    const equals = equalsForType(propertyType);

    this.match = false;

    if (
      suggestedValue !== '' &&
      (!Array.isArray(suggestedValue) || suggestedValue.length !== 0) &&
      equals(suggestedValue, currentValue)
    ) {
      this.match = true;
    }
  }

  setHasContext({ segment }: SuggestionValues, propertyType: PropertySchema['type']) {
    if (
      segment ||
      propertyIsSelectOrMultiSelect(propertyType) ||
      propertyIsRelationship(propertyType)
    ) {
      this.hasContext = true;
    }
  }

  setObsolete({ modelCreationDate, date }: SuggestionValues) {
    if (date < modelCreationDate) {
      this.obsolete = true;
      this.match = undefined;
    }
  }

  setProcessing({ status }: SuggestionValues) {
    if (status === 'processing') {
      this.processing = true;
      this.obsolete = true;
      this.match = undefined;
    }
  }

  setError({ error, status }: SuggestionValues) {
    if ((error && error !== '') || (status && status === 'failed')) {
      this.error = true;
      this.match = undefined;
    }
  }
}

const getSuggestionState = (
  values: SuggestionValues,
  propertyType: PropertySchema['type']
): IXSuggestionStateType => {
  const state = new IXSuggestionState(values, propertyType);

  return state;
};

export { getSuggestionState };
export type { CurrentValue, SuggestionValues };