import { IframeType, IWidget } from 'dot-utils'; import { action, Action, computed, Computed, Dispatch, Store } from 'easy-peasy'; import { WordpressTaxonomy } from '../models/wp'; import { path, prop, propEq, symmetricDifference, uniqBy } from 'ramda'; import { Alignment, InsertionPoint, Placement, PlacementTabKey } from './placements.models'; import { IStore } from '../store/store'; import { ajaxAction } from '../ajax/ajax.utils'; type SelectedTaxonomyType = 'category' | 'post_tag'; export interface ICreatePlacementModel { selectedWidget: IWidget; currentPlacementId: string | number; currentStep: string; selectedTaxonomyType: SelectedTaxonomyType; selectedTaxonomies: WordpressTaxonomy[]; selectedInsertionPoint: InsertionPoint; selectedInsertionNumber: number; selectedAlignment: Alignment; selectedFormat: IframeType[]; } export interface IPlacementsModel extends ICreatePlacementModel { data: { categories: WordpressTaxonomy[]; tags: WordpressTaxonomy[]; }; savedPlacements: Placement[]; } export interface IPlacementsStore extends IPlacementsModel { setData: Action; taxonomyById: Computed< IPlacementsStore, (type: 'categories' | 'tags', id: number) => WordpressTaxonomy | undefined >; updatePlacements: Action; setSelectedWidget: Action; setStep: Action; setSelectedTaxonomies: Action; toggleTaxonomy: Action; setInsertionPoint: Action; setInsertionNumber: Action; setAlignment: Action; toggleFormat: Action; resetPlacementSelect: Action; updatePlacementSelect: Action< IPlacementsStore, { selectedWidget: IWidget; currentPlacementId: string | number; selectedTaxonomyType: SelectedTaxonomyType; selectedTaxonomies: WordpressTaxonomy[]; selectedInsertionPoint: InsertionPoint; selectedInsertionNumber: number; selectedAlignment: Alignment; selectedFormat: IframeType[]; } >; } function initialPlacementSelectData(): ICreatePlacementModel { return { // @ts-ignore selectedWidget: null, currentPlacementId: '', currentStep: PlacementTabKey.SelectWidget, selectedTaxonomyType: 'category', selectedTaxonomies: [], selectedInsertionPoint: InsertionPoint.AfterParagraph, selectedInsertionNumber: 1, selectedAlignment: Alignment.Center, selectedFormat: [], }; } const placementsStore: IPlacementsStore = { data: null as any, setData: action((state, payload) => ({ ...state, data: payload, })), taxonomyById: computed((state) => (type, id) => { return state.data[type].find(propEq('term_id', id as any)); }), savedPlacements: [], updatePlacements: action((state, payload) => ({ ...state, savedPlacements: uniqBy(prop('ID'), payload), })), ...initialPlacementSelectData(), setSelectedWidget: action((state, payload) => ({ ...state, selectedWidget: payload, })), currentPlacementId: '', currentStep: PlacementTabKey.SelectWidget, setStep: action((state, payload) => ({ ...state, currentStep: payload, })), selectedTaxonomyType: 'category', selectedTaxonomies: [], setSelectedTaxonomies: action((state, payload) => ({ ...state, selectedTaxonomies: payload, })), toggleTaxonomy: action((state, payload) => { const currentType = path([0, 'taxonomy'], state.selectedTaxonomies); // todo: confirm this is the desired behaviour, may want to allow both categories and tags const taxonomies = (currentType === payload.taxonomy && state.selectedTaxonomies) || []; return { ...state, selectedTaxonomyType: payload.taxonomy as any, selectedTaxonomies: symmetricDifference([payload], taxonomies), }; }), selectedInsertionPoint: InsertionPoint.AfterParagraph, setInsertionPoint: action((state, payload) => ({ ...state, selectedInsertionPoint: payload, })), selectedInsertionNumber: 1, setInsertionNumber: action((state, payload) => ({ ...state, selectedInsertionNumber: payload, })), selectedAlignment: Alignment.Center, setAlignment: action((state, payload) => ({ ...state, selectedAlignment: payload, })), selectedFormat: [], toggleFormat: action((state, payload) => ({ ...state, selectedFormat: symmetricDifference([payload], state.selectedFormat), })), resetPlacementSelect: action((state) => ({ ...state, ...initialPlacementSelectData(), })), updatePlacementSelect: action((state, payload) => { return { ...state, ...payload, currentStep: PlacementTabKey.SelectPlacement, }; }), }; export async function loadPlacementStore(store: Store) { const state = store.getState(); if (!state.placements.data) { const data = await ajaxAction({ action: 'dot_press_get_placements_admin_data', method: 'get', }); store.dispatch.placements.setData(data); } } export default placementsStore;