@websolutespa/payload-plugin-bowl 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +722 -709
- package/dist/components/ImportExport/ImportModal.js +10 -5
- package/dist/components/ImportExport/ImportModal.js.map +1 -1
- package/dist/core/api/page.service.js +65 -28
- package/dist/core/api/page.service.js.map +1 -1
- package/dist/core/api/where.service.js +62 -40
- package/dist/core/api/where.service.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { MinimalTemplate } from '@payloadcms/next/templates';
|
|
4
|
-
import { Button, CheckboxInput,
|
|
4
|
+
import { Button, CheckboxInput, SelectInput, XIcon, toast, useAuth, useConfig, useLocale, useModal, useTranslation } from '@payloadcms/ui';
|
|
5
5
|
import { getRouteResolver } from '@websolutespa/payload-utils';
|
|
6
6
|
import * as Papa from 'papaparse';
|
|
7
7
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
@@ -354,8 +354,11 @@ export const ImportModal = ({ parser, slug })=>{
|
|
|
354
354
|
}),
|
|
355
355
|
/*#__PURE__*/ _jsx("main", {
|
|
356
356
|
className: `${baseClass}__main`,
|
|
357
|
-
children: /*#__PURE__*/ _jsxs(
|
|
358
|
-
onSubmit:
|
|
357
|
+
children: /*#__PURE__*/ _jsxs("form", {
|
|
358
|
+
onSubmit: (e)=>{
|
|
359
|
+
e.preventDefault();
|
|
360
|
+
onSubmit();
|
|
361
|
+
},
|
|
359
362
|
children: [
|
|
360
363
|
/*#__PURE__*/ _jsxs("div", {
|
|
361
364
|
className: "render-fields",
|
|
@@ -366,12 +369,14 @@ export const ImportModal = ({ parser, slug })=>{
|
|
|
366
369
|
name: "importMode",
|
|
367
370
|
path: 'importMode',
|
|
368
371
|
options: importModes,
|
|
369
|
-
onChange: onSelectDidChange
|
|
372
|
+
onChange: onSelectDidChange,
|
|
373
|
+
value: importMode
|
|
370
374
|
}),
|
|
371
375
|
typeof parser === 'function' && /*#__PURE__*/ _jsx(CheckboxInput, {
|
|
372
376
|
label: t('importExport:enableDataParsing'),
|
|
373
|
-
id: "
|
|
377
|
+
id: "dataParsing",
|
|
374
378
|
name: "dataParsing",
|
|
379
|
+
checked: dataParsing,
|
|
375
380
|
onToggle: onCheckboxkDidChange
|
|
376
381
|
})
|
|
377
382
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ImportExport/ImportModal.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { MinimalTemplate } from '@payloadcms/next/templates';\r\nimport { Button, CheckboxInput, Form, SelectInput, XIcon, toast, useAuth, useConfig, useLocale, useModal, useTranslation } from '@payloadcms/ui';\r\nimport { IEntity, IEquatable } from '@websolutespa/bom-core';\r\nimport { getRouteResolver } from '@websolutespa/payload-utils';\r\nimport * as Papa from 'papaparse';\r\nimport type { ClientField } from 'payload';\r\nimport React, { useCallback, useEffect, useState } from 'react';\r\nimport { useDropzone } from 'react-dropzone';\r\nimport { ImportLogInvalidTypes, ImportLogType, ImportMode } from '../../core/api/types';\r\nimport './ImportModal.scss';\r\nimport { IImportItem } from './types';\r\n\r\ntype Option<TValue = unknown> = {\r\n [key: string]: unknown;\r\n id?: string;\r\n value: TValue;\r\n};\r\n\r\ntype IRow = Record<string, string>;\r\n\r\ntype ImportModalProps<T = any> = {\r\n parser?: (items: IImportItem[]) => T[];\r\n slug: string;\r\n};\r\n\r\ntype ILog = {\r\n count: number;\r\n id: IEquatable;\r\n invalid?: string;\r\n key: string;\r\n message: string;\r\n type: ImportLogType;\r\n};\r\n\r\nconst INITIAL_DATA = {\r\n importMode: ImportMode.Append,\r\n dataParsing: false,\r\n};\r\n\r\nconst baseClass = 'import-modal';\r\n\r\nexport const ImportModal: React.FC<ImportModalProps> = ({\r\n parser,\r\n slug,\r\n}) => {\r\n const { closeAllModals } = useModal();\r\n const { config, getEntityConfig } = useConfig();\r\n const collectionConfig = getEntityConfig({ collectionSlug: slug });\r\n\r\n const routeResolver = getRouteResolver(config);\r\n const collectionUrl = routeResolver.api(`/${collectionConfig.slug}?pagination=false&depth=0`);\r\n\r\n // !!! check translations\r\n const { t } = useTranslation<any, any>();\r\n\r\n const format = (text: string, ...rest: unknown[]) => {\r\n return text.replace(/\\{(\\d)\\}/g, (m, g) => {\r\n const i = parseInt(g);\r\n return (i >= 0 && i < rest.length) ? String(rest[i]) : '';\r\n });\r\n };\r\n\r\n const { code: locale } = useLocale();\r\n\r\n const user = useAuth();\r\n\r\n const [dirty, setDirty] = useState<boolean>(false);\r\n const [valid, setValid] = useState<boolean>(false);\r\n const [error, setError] = useState<Error>();\r\n const [name, setName] = useState<string | null>(null);\r\n const [csv, setCSV] = useState<string | null>(null);\r\n const [keys, setKeys] = useState<string[] | null>(null);\r\n const [data, setData] = useState<IRow[] | null>(null);\r\n const [items, setItems] = useState<IImportItem[]>([]);\r\n const [logs, setLogs] = useState<ILog[]>([]);\r\n const [importMode, setImportMode] = useState<ImportMode>(INITIAL_DATA.importMode);\r\n const [dataParsing, setDataParsing] = useState<boolean>(INITIAL_DATA.dataParsing);\r\n\r\n const importModes = Object.entries(ImportMode).map(([k, v]) => ({\r\n value: v,\r\n label: t(`importExport:mode${k}`),\r\n }));\r\n\r\n const onSelectDidChange = (option: Option | Option[]) => {\r\n // console.log('onSelectDidChange', option);\r\n if (Array.isArray(option)) {\r\n return;\r\n }\r\n if (importMode !== option.value) {\r\n setValid(false);\r\n setImportMode(option.value as ImportMode);\r\n }\r\n };\r\n\r\n const onCheckboxkDidChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n // console.log('onCheckboxkDidChange', value);\r\n setValid(false);\r\n setDataParsing(!dataParsing);\r\n };\r\n\r\n const validate = useCallback(async (keys: string[], data: IRow[]) => {\r\n try {\r\n const messageByType = (key: string, type: ImportLogType) => {\r\n let message: string;\r\n switch (type) {\r\n case ImportLogType.Required:\r\n message = format(t('importExport:errorRequired'), key);\r\n break;\r\n case ImportLogType.Optional:\r\n message = format(t('importExport:errorOptional'), key);\r\n break;\r\n case ImportLogType.Invalid:\r\n message = format(t('importExport:errorInvalid'), key);\r\n break;\r\n case ImportLogType.Duplicate:\r\n message = format(t('importExport:errorDuplicate'), key);\r\n break;\r\n case ImportLogType.Unexpected:\r\n message = format(t('importExport:errorUnexpected'), key);\r\n break;\r\n }\r\n return message;\r\n };\r\n\r\n const addLog = (logs: ILog[], key: string, type: ImportLogType, invalid?: string): ILog => {\r\n const message = messageByType(key, type);\r\n const id = invalid ? `${key}-${type}-${invalid}` : `${key}-${type}`;\r\n const log = once<ILog>(logs, { id, key, type, message, invalid, count: 0 });\r\n log.count++;\r\n return log;\r\n };\r\n\r\n const itemOptionalKeys: string[] = [];\r\n const itemKeys = keys;\r\n\r\n // collecting model fields & keys\r\n const fields = collectionConfig.fields\r\n .filter(x => 'name' in x && x['name'] !== undefined && x.type !== 'ui') as (ClientField & { name: string })[];\r\n const fieldKeys = fields.map(x => x['name']);\r\n const requiredFields = fields.filter(x => {\r\n if (x['name'] === 'id' && importMode === ImportMode.Update) {\r\n return true;\r\n } else {\r\n return 'required' in x && x['required'] === true;\r\n }\r\n });\r\n const uniqueFields = fields.filter(x => x['unique'] === true);\r\n const requiredFieldKeys = requiredFields.map(x => x['name']);\r\n const optionalFieldKeys = fieldKeys.filter(x => !requiredFieldKeys.includes(x));\r\n const uniqueFieldKeys = uniqueFields.map(x => x['name']);\r\n\r\n let items: IImportItem[] = [];\r\n\r\n // parse values\r\n const valueParsers = itemKeys.map(key => {\r\n let parseValue = (item: IRow): string | number | boolean | Date | undefined => item[key];\r\n if (fieldKeys.includes(key)) {\r\n const field = collectionConfig.fields.find(x => 'name' in x && x['name'] === key);\r\n if (field) {\r\n switch (field.type) {\r\n case 'checkbox':\r\n parseValue = (item: IRow) => item[key] !== undefined ? Boolean(item[key]) : item[key];\r\n break;\r\n case 'date':\r\n parseValue = (item: IRow) => item[key] !== undefined ? new Date(item[key]) : item[key];\r\n break;\r\n case 'number':\r\n parseValue = (item: IRow) => item[key] !== undefined ? Number(item[key]) : item[key];\r\n break;\r\n }\r\n }\r\n }\r\n return parseValue;\r\n });\r\n\r\n for (const row of data) {\r\n const item = {};\r\n itemKeys.forEach((key, i) => {\r\n const parser = valueParsers[i];\r\n if (parser) {\r\n (item as any)[key] = parser(row);\r\n }\r\n });\r\n items.push(item);\r\n }\r\n\r\n if (dataParsing && typeof parser === 'function') {\r\n items = parser(items);\r\n }\r\n\r\n // console.log('data', data);\r\n // console.log('items', items);\r\n\r\n // collecting stored values\r\n const httpResponse = await fetch(collectionUrl, {\r\n method: 'GET',\r\n credentials: 'include',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n if (!httpResponse.ok) {\r\n throw httpResponse;\r\n }\r\n const storedItems = await httpResponse.json();\r\n // console.log('rows', rows, 'data', result.data);\r\n\r\n // collecting logs\r\n const logs: ILog[] = [];\r\n // required fields\r\n requiredFieldKeys.forEach(key => {\r\n if (!itemKeys.includes(key) || itemOptionalKeys.includes(key)) {\r\n addLog(logs, key, ImportLogType.Required);\r\n }\r\n });\r\n // optional fields\r\n optionalFieldKeys.forEach(key => {\r\n if (!itemKeys.includes(key)) {\r\n addLog(logs, key, ImportLogType.Optional);\r\n }\r\n });\r\n // deep check values\r\n for (const key of itemKeys) {\r\n if (fieldKeys.includes(key)) {\r\n const field = collectionConfig.fields.find(x => 'name' in x && x['name'] === key);\r\n if (field) {\r\n const validate = 'validate' in field ? field['validate'] : undefined;\r\n const values: (string | number | boolean | Date | undefined)[] = [];\r\n const storedValues = uniqueFieldKeys.includes(key) ? storedItems.map((x: any) => x[key]) : [];\r\n for (const item of items) {\r\n const value = item[key];\r\n // validate field\r\n if (typeof validate === 'function') {\r\n const validation = await validate(value, {\r\n data: item,\r\n siblingData: item,\r\n operation: 'create',\r\n user,\r\n t,\r\n });\r\n if (validation !== true) {\r\n // console.log(key, value, validation, item);\r\n if (logs.find(x =>\r\n x.key === 'key' &&\r\n x.type === ImportLogType.Invalid\r\n ) === undefined) {\r\n addLog(logs, key, ImportLogType.Invalid, validation as string);\r\n }\r\n }\r\n }\r\n // unique field\r\n if (uniqueFieldKeys.includes(key) && (\r\n values.includes(value) ||\r\n (importMode === ImportMode.Append ? storedValues.includes(value) : false)\r\n )) {\r\n addLog(logs, key, ImportLogType.Duplicate, String(value));\r\n }\r\n values.push(value);\r\n }\r\n }\r\n } else {\r\n addLog(logs, key, ImportLogType.Unexpected);\r\n }\r\n }\r\n\r\n const sortOrder = Object.values(ImportLogType);\r\n logs.sort((a, b) => {\r\n return sortOrder.indexOf(a.type) - sortOrder.indexOf(b.type);\r\n });\r\n\r\n setItems(items);\r\n setLogs(logs);\r\n\r\n const errors = logs.filter(x => ImportLogInvalidTypes.includes(x.type));\r\n if (errors.length === 0) {\r\n setValid(true);\r\n }\r\n\r\n // console.log(logs, items, itemKeys, itemOptionalKeys, fieldKeys, requiredFieldKeys, optionalFieldKeys);\r\n\r\n } catch (error) {\r\n console.log('parse error', error);\r\n setError(error as Error);\r\n }\r\n }, [collectionUrl, importMode, dataParsing, parser, collectionConfig.fields, t, user]);\r\n\r\n useEffect(() => {\r\n if (keys && data) {\r\n validate(keys, data);\r\n }\r\n }, [keys, data, importMode, validate]);\r\n\r\n const onDrop = useCallback((acceptedFiles: File[]) => {\r\n const acceptedFile = acceptedFiles.find(() => true);\r\n if (acceptedFile) {\r\n const reader = new FileReader();\r\n reader.onabort = () => console.log('file reading was aborted');\r\n reader.onerror = () => console.log('file reading has failed');\r\n reader.onload = () => {\r\n // Do whatever you want with the file contents\r\n const csv = reader.result as string;\r\n // console.log('csv', csv);\r\n // parsing csv to { data:[][] }\r\n const result = Papa.parse(csv);\r\n const resultData: string[][] = result.data as string[][];\r\n // collecting imported keys & data\r\n let keys: string[] = [];\r\n const data: IRow[] = resultData.reduce((p, c, i) => {\r\n if (i === 0) {\r\n keys = c;\r\n } else {\r\n const item: Record<string, string> = {};\r\n keys.forEach((key, k) => {\r\n if (c[k] !== undefined) {\r\n item[key] = c[k];\r\n }\r\n });\r\n p.push(item);\r\n }\r\n return p;\r\n }, [] as IRow[]);\r\n setName(acceptedFile.name);\r\n setCSV(csv);\r\n setKeys(keys);\r\n setData(data);\r\n setDirty(true);\r\n };\r\n // reader.readAsArrayBuffer(file);\r\n reader.readAsText(acceptedFile);\r\n }\r\n }, []);\r\n\r\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\r\n accept: {\r\n 'text/csv': [],\r\n },\r\n maxSize: 1048576 * 20,\r\n maxFiles: 1,\r\n onDrop,\r\n });\r\n\r\n const onSubmit = async () => {\r\n // console.log('ImportModal.onSubmit');\r\n try {\r\n const url = routeResolver.api(`/${collectionConfig.slug}/import?locale=${locale}&mode=${importMode}`);\r\n\r\n const httpResponse = await fetch(url, {\r\n method: 'POST',\r\n body: JSON.stringify({ items }),\r\n credentials: 'include',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n\r\n if (!httpResponse.ok) {\r\n throw httpResponse;\r\n }\r\n\r\n const response = await httpResponse.json();\r\n // console.log('ImportModal.onSubmit', response);\r\n toast.success(t('importExport:success'));\r\n closeAllModals();\r\n\r\n } catch (error) {\r\n console.log('ImportModal.onSubmit.error', error);\r\n toast.error(format(t('importExport:failure'), collectionConfig.slug));\r\n }\r\n };\r\n\r\n const onClose = () => {\r\n // console.log('onClose');\r\n closeAllModals();\r\n };\r\n\r\n const onClear = () => {\r\n // console.log('onClear');\r\n setValid(false);\r\n setDirty(false);\r\n setName(null);\r\n setCSV(null);\r\n setKeys(null);\r\n setData(null);\r\n setItems([]);\r\n setLogs([]);\r\n };\r\n\r\n return (\r\n <MinimalTemplate>\r\n <header className={`${baseClass}__header`}>\r\n <h3>{t('importExport:modalTitle')}</h3>\r\n <Button buttonStyle=\"none\" onClick={onClose}><XIcon /></Button>\r\n </header>\r\n <main className={`${baseClass}__main`}>\r\n <Form onSubmit={onSubmit}>\r\n <div className=\"render-fields\">\r\n <SelectInput\r\n // isClearable={viewType === 'list'}\r\n label={t('importExport:importMode')}\r\n name=\"importMode\"\r\n path={'importMode'}\r\n options={importModes}\r\n onChange={onSelectDidChange}\r\n />\r\n {typeof parser === 'function' && (\r\n <CheckboxInput\r\n label={t('importExport:enableDataParsing')}\r\n id=\"importMode\"\r\n name=\"dataParsing\"\r\n onToggle={onCheckboxkDidChange}\r\n />\r\n )}\r\n </div>\r\n {data ? (\r\n <>\r\n <div dangerouslySetInnerHTML={{ __html: format(t('importExport:records'), items.length, name) }} ></div>\r\n {logs.length > 0 && (\r\n <ul className={`${baseClass}__logs`}>\r\n {logs.map((log, i) => (\r\n <li key={`log-${i}`} className={`${baseClass}__log ${baseClass}__log--${log.type}`}>\r\n {log.count} {log.message} <i>{log.invalid}</i>\r\n </li>\r\n ))}\r\n </ul>\r\n )}\r\n </>\r\n ) : (\r\n <div className={`${baseClass}__dropzone`} {...getRootProps()}>\r\n <input className={`${baseClass}__input`} {...getInputProps()} />\r\n {isDragActive ? (\r\n <div>{t('importExport:dropTitle')}</div>\r\n ) : (\r\n <div>{t('importExport:dropAbstract')}</div>\r\n )}\r\n </div>\r\n )}\r\n {error && (\r\n <>\r\n <div>{t('importExport:parseError')}</div>\r\n {error.message && <div>{error.message}</div>}\r\n </>\r\n )}\r\n <div className={`${baseClass}__foot`}>\r\n {dirty && <Button type=\"button\" buttonStyle=\"secondary\" onClick={onClear}>\r\n {t('importExport:clear')}\r\n </Button>}\r\n <Button type=\"submit\" disabled={!valid}>\r\n {t('importExport:submit')}\r\n </Button>\r\n </div>\r\n </Form>\r\n </main>\r\n </MinimalTemplate>\r\n );\r\n};\r\n\r\nfunction once<T extends IEntity = IEntity>(items: T[], item: T): T {\r\n const exhistingItem = items.find(x => x.id === item.id);\r\n if (exhistingItem) {\r\n return exhistingItem;\r\n }\r\n items.push(item);\r\n return item;\r\n}\r\n"],"names":["MinimalTemplate","Button","CheckboxInput","Form","SelectInput","XIcon","toast","useAuth","useConfig","useLocale","useModal","useTranslation","getRouteResolver","Papa","React","useCallback","useEffect","useState","useDropzone","ImportLogInvalidTypes","ImportLogType","ImportMode","INITIAL_DATA","importMode","Append","dataParsing","baseClass","ImportModal","parser","slug","closeAllModals","config","getEntityConfig","collectionConfig","collectionSlug","routeResolver","collectionUrl","api","t","format","text","rest","replace","m","g","i","parseInt","length","String","code","locale","user","dirty","setDirty","valid","setValid","error","setError","name","setName","csv","setCSV","keys","setKeys","data","setData","items","setItems","logs","setLogs","setImportMode","setDataParsing","importModes","Object","entries","map","k","v","value","label","onSelectDidChange","option","Array","isArray","onCheckboxkDidChange","event","validate","messageByType","key","type","message","Required","Optional","Invalid","Duplicate","Unexpected","addLog","invalid","id","log","once","count","itemOptionalKeys","itemKeys","fields","filter","x","undefined","fieldKeys","requiredFields","Update","uniqueFields","requiredFieldKeys","optionalFieldKeys","includes","uniqueFieldKeys","valueParsers","parseValue","item","field","find","Boolean","Date","Number","row","forEach","push","httpResponse","fetch","method","credentials","headers","ok","storedItems","json","values","storedValues","validation","siblingData","operation","sortOrder","sort","a","b","indexOf","errors","console","onDrop","acceptedFiles","acceptedFile","reader","FileReader","onabort","onerror","onload","result","parse","resultData","reduce","p","c","readAsText","getRootProps","getInputProps","isDragActive","accept","maxSize","maxFiles","onSubmit","url","body","JSON","stringify","response","success","onClose","onClear","header","className","h3","buttonStyle","onClick","main","div","path","options","onChange","onToggle","dangerouslySetInnerHTML","__html","ul","li","input","disabled","exhistingItem"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ImportExport/ImportModal.tsx"],"sourcesContent":["'use client';\n\nimport { MinimalTemplate } from '@payloadcms/next/templates';\nimport { Button, CheckboxInput, SelectInput, XIcon, toast, useAuth, useConfig, useLocale, useModal, useTranslation } from '@payloadcms/ui';\nimport { IEntity, IEquatable } from '@websolutespa/bom-core';\nimport { getRouteResolver } from '@websolutespa/payload-utils';\nimport * as Papa from 'papaparse';\nimport type { ClientField } from 'payload';\nimport React, { useCallback, useEffect, useState } from 'react';\nimport { useDropzone } from 'react-dropzone';\nimport { ImportLogInvalidTypes, ImportLogType, ImportMode } from '../../core/api/types';\nimport './ImportModal.scss';\nimport { IImportItem } from './types';\n\ntype Option<TValue = unknown> = {\n [key: string]: unknown;\n id?: string;\n value: TValue;\n};\n\ntype IRow = Record<string, string>;\n\ntype ImportModalProps<T = any> = {\n parser?: (items: IImportItem[]) => T[];\n slug: string;\n};\n\ntype ILog = {\n count: number;\n id: IEquatable;\n invalid?: string;\n key: string;\n message: string;\n type: ImportLogType;\n};\n\nconst INITIAL_DATA = {\n importMode: ImportMode.Append,\n dataParsing: false,\n};\n\nconst baseClass = 'import-modal';\n\nexport const ImportModal: React.FC<ImportModalProps> = ({\n parser,\n slug,\n}) => {\n const { closeAllModals } = useModal();\n const { config, getEntityConfig } = useConfig();\n const collectionConfig = getEntityConfig({ collectionSlug: slug });\n\n const routeResolver = getRouteResolver(config);\n const collectionUrl = routeResolver.api(`/${collectionConfig.slug}?pagination=false&depth=0`);\n\n // !!! check translations\n const { t } = useTranslation<any, any>();\n\n const format = (text: string, ...rest: unknown[]) => {\n return text.replace(/\\{(\\d)\\}/g, (m, g) => {\n const i = parseInt(g);\n return (i >= 0 && i < rest.length) ? String(rest[i]) : '';\n });\n };\n\n const { code: locale } = useLocale();\n\n const user = useAuth();\n\n const [dirty, setDirty] = useState<boolean>(false);\n const [valid, setValid] = useState<boolean>(false);\n const [error, setError] = useState<Error>();\n const [name, setName] = useState<string | null>(null);\n const [csv, setCSV] = useState<string | null>(null);\n const [keys, setKeys] = useState<string[] | null>(null);\n const [data, setData] = useState<IRow[] | null>(null);\n const [items, setItems] = useState<IImportItem[]>([]);\n const [logs, setLogs] = useState<ILog[]>([]);\n const [importMode, setImportMode] = useState<ImportMode>(INITIAL_DATA.importMode);\n const [dataParsing, setDataParsing] = useState<boolean>(INITIAL_DATA.dataParsing);\n\n const importModes = Object.entries(ImportMode).map(([k, v]) => ({\n value: v,\n label: t(`importExport:mode${k}`),\n }));\n\n const onSelectDidChange = (option: Option | Option[]) => {\n // console.log('onSelectDidChange', option);\n if (Array.isArray(option)) {\n return;\n }\n if (importMode !== option.value) {\n setValid(false);\n setImportMode(option.value as ImportMode);\n }\n };\n\n const onCheckboxkDidChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n // console.log('onCheckboxkDidChange', value);\n setValid(false);\n setDataParsing(!dataParsing);\n };\n\n const validate = useCallback(async (keys: string[], data: IRow[]) => {\n try {\n const messageByType = (key: string, type: ImportLogType) => {\n let message: string;\n switch (type) {\n case ImportLogType.Required:\n message = format(t('importExport:errorRequired'), key);\n break;\n case ImportLogType.Optional:\n message = format(t('importExport:errorOptional'), key);\n break;\n case ImportLogType.Invalid:\n message = format(t('importExport:errorInvalid'), key);\n break;\n case ImportLogType.Duplicate:\n message = format(t('importExport:errorDuplicate'), key);\n break;\n case ImportLogType.Unexpected:\n message = format(t('importExport:errorUnexpected'), key);\n break;\n }\n return message;\n };\n\n const addLog = (logs: ILog[], key: string, type: ImportLogType, invalid?: string): ILog => {\n const message = messageByType(key, type);\n const id = invalid ? `${key}-${type}-${invalid}` : `${key}-${type}`;\n const log = once<ILog>(logs, { id, key, type, message, invalid, count: 0 });\n log.count++;\n return log;\n };\n\n const itemOptionalKeys: string[] = [];\n const itemKeys = keys;\n\n // collecting model fields & keys\n const fields = collectionConfig.fields\n .filter(x => 'name' in x && x['name'] !== undefined && x.type !== 'ui') as (ClientField & { name: string })[];\n const fieldKeys = fields.map(x => x['name']);\n const requiredFields = fields.filter(x => {\n if (x['name'] === 'id' && importMode === ImportMode.Update) {\n return true;\n } else {\n return 'required' in x && x['required'] === true;\n }\n });\n const uniqueFields = fields.filter(x => x['unique'] === true);\n const requiredFieldKeys = requiredFields.map(x => x['name']);\n const optionalFieldKeys = fieldKeys.filter(x => !requiredFieldKeys.includes(x));\n const uniqueFieldKeys = uniqueFields.map(x => x['name']);\n\n let items: IImportItem[] = [];\n\n // parse values\n const valueParsers = itemKeys.map(key => {\n let parseValue = (item: IRow): string | number | boolean | Date | undefined => item[key];\n if (fieldKeys.includes(key)) {\n const field = collectionConfig.fields.find(x => 'name' in x && x['name'] === key);\n if (field) {\n switch (field.type) {\n case 'checkbox':\n parseValue = (item: IRow) => item[key] !== undefined ? Boolean(item[key]) : item[key];\n break;\n case 'date':\n parseValue = (item: IRow) => item[key] !== undefined ? new Date(item[key]) : item[key];\n break;\n case 'number':\n parseValue = (item: IRow) => item[key] !== undefined ? Number(item[key]) : item[key];\n break;\n }\n }\n }\n return parseValue;\n });\n\n for (const row of data) {\n const item = {};\n itemKeys.forEach((key, i) => {\n const parser = valueParsers[i];\n if (parser) {\n (item as any)[key] = parser(row);\n }\n });\n items.push(item);\n }\n\n if (dataParsing && typeof parser === 'function') {\n items = parser(items);\n }\n\n // console.log('data', data);\n // console.log('items', items);\n\n // collecting stored values\n const httpResponse = await fetch(collectionUrl, {\n method: 'GET',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n if (!httpResponse.ok) {\n throw httpResponse;\n }\n const storedItems = await httpResponse.json();\n // console.log('rows', rows, 'data', result.data);\n\n // collecting logs\n const logs: ILog[] = [];\n // required fields\n requiredFieldKeys.forEach(key => {\n if (!itemKeys.includes(key) || itemOptionalKeys.includes(key)) {\n addLog(logs, key, ImportLogType.Required);\n }\n });\n // optional fields\n optionalFieldKeys.forEach(key => {\n if (!itemKeys.includes(key)) {\n addLog(logs, key, ImportLogType.Optional);\n }\n });\n // deep check values\n for (const key of itemKeys) {\n if (fieldKeys.includes(key)) {\n const field = collectionConfig.fields.find(x => 'name' in x && x['name'] === key);\n if (field) {\n const validate = 'validate' in field ? field['validate'] : undefined;\n const values: (string | number | boolean | Date | undefined)[] = [];\n const storedValues = uniqueFieldKeys.includes(key) ? storedItems.map((x: any) => x[key]) : [];\n for (const item of items) {\n const value = item[key];\n // validate field\n if (typeof validate === 'function') {\n const validation = await validate(value, {\n data: item,\n siblingData: item,\n operation: 'create',\n user,\n t,\n });\n if (validation !== true) {\n // console.log(key, value, validation, item);\n if (logs.find(x =>\n x.key === 'key' &&\n x.type === ImportLogType.Invalid\n ) === undefined) {\n addLog(logs, key, ImportLogType.Invalid, validation as string);\n }\n }\n }\n // unique field\n if (uniqueFieldKeys.includes(key) && (\n values.includes(value) ||\n (importMode === ImportMode.Append ? storedValues.includes(value) : false)\n )) {\n addLog(logs, key, ImportLogType.Duplicate, String(value));\n }\n values.push(value);\n }\n }\n } else {\n addLog(logs, key, ImportLogType.Unexpected);\n }\n }\n\n const sortOrder = Object.values(ImportLogType);\n logs.sort((a, b) => {\n return sortOrder.indexOf(a.type) - sortOrder.indexOf(b.type);\n });\n\n setItems(items);\n setLogs(logs);\n\n const errors = logs.filter(x => ImportLogInvalidTypes.includes(x.type));\n if (errors.length === 0) {\n setValid(true);\n }\n\n // console.log(logs, items, itemKeys, itemOptionalKeys, fieldKeys, requiredFieldKeys, optionalFieldKeys);\n\n } catch (error) {\n console.log('parse error', error);\n setError(error as Error);\n }\n }, [collectionUrl, importMode, dataParsing, parser, collectionConfig.fields, t, user]);\n\n useEffect(() => {\n if (keys && data) {\n validate(keys, data);\n }\n }, [keys, data, importMode, validate]);\n\n const onDrop = useCallback((acceptedFiles: File[]) => {\n const acceptedFile = acceptedFiles.find(() => true);\n if (acceptedFile) {\n const reader = new FileReader();\n reader.onabort = () => console.log('file reading was aborted');\n reader.onerror = () => console.log('file reading has failed');\n reader.onload = () => {\n // Do whatever you want with the file contents\n const csv = reader.result as string;\n // console.log('csv', csv);\n // parsing csv to { data:[][] }\n const result = Papa.parse(csv);\n const resultData: string[][] = result.data as string[][];\n // collecting imported keys & data\n let keys: string[] = [];\n const data: IRow[] = resultData.reduce((p, c, i) => {\n if (i === 0) {\n keys = c;\n } else {\n const item: Record<string, string> = {};\n keys.forEach((key, k) => {\n if (c[k] !== undefined) {\n item[key] = c[k];\n }\n });\n p.push(item);\n }\n return p;\n }, [] as IRow[]);\n setName(acceptedFile.name);\n setCSV(csv);\n setKeys(keys);\n setData(data);\n setDirty(true);\n };\n // reader.readAsArrayBuffer(file);\n reader.readAsText(acceptedFile);\n }\n }, []);\n\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\n accept: {\n 'text/csv': [],\n },\n maxSize: 1048576 * 20,\n maxFiles: 1,\n onDrop,\n });\n\n const onSubmit = async () => {\n // console.log('ImportModal.onSubmit');\n try {\n const url = routeResolver.api(`/${collectionConfig.slug}/import?locale=${locale}&mode=${importMode}`);\n\n const httpResponse = await fetch(url, {\n method: 'POST',\n body: JSON.stringify({ items }),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!httpResponse.ok) {\n throw httpResponse;\n }\n\n const response = await httpResponse.json();\n // console.log('ImportModal.onSubmit', response);\n toast.success(t('importExport:success'));\n closeAllModals();\n\n } catch (error) {\n console.log('ImportModal.onSubmit.error', error);\n toast.error(format(t('importExport:failure'), collectionConfig.slug));\n }\n };\n\n const onClose = () => {\n // console.log('onClose');\n closeAllModals();\n };\n\n const onClear = () => {\n // console.log('onClear');\n setValid(false);\n setDirty(false);\n setName(null);\n setCSV(null);\n setKeys(null);\n setData(null);\n setItems([]);\n setLogs([]);\n };\n\n return (\n <MinimalTemplate>\n <header className={`${baseClass}__header`}>\n <h3>{t('importExport:modalTitle')}</h3>\n <Button buttonStyle=\"none\" onClick={onClose}><XIcon /></Button>\n </header>\n <main className={`${baseClass}__main`}>\n <form onSubmit={(e) => { e.preventDefault(); onSubmit(); }}>\n <div className=\"render-fields\">\n <SelectInput\n // isClearable={viewType === 'list'}\n label={t('importExport:importMode')}\n name=\"importMode\"\n path={'importMode'}\n options={importModes}\n onChange={onSelectDidChange}\n value={importMode}\n />\n {typeof parser === 'function' && (\n <CheckboxInput\n label={t('importExport:enableDataParsing')}\n id=\"dataParsing\"\n name=\"dataParsing\"\n checked={dataParsing}\n onToggle={onCheckboxkDidChange}\n />\n )}\n </div>\n {data ? (\n <>\n <div dangerouslySetInnerHTML={{ __html: format(t('importExport:records'), items.length, name) }} ></div>\n {logs.length > 0 && (\n <ul className={`${baseClass}__logs`}>\n {logs.map((log, i) => (\n <li key={`log-${i}`} className={`${baseClass}__log ${baseClass}__log--${log.type}`}>\n {log.count} {log.message} <i>{log.invalid}</i>\n </li>\n ))}\n </ul>\n )}\n </>\n ) : (\n <div className={`${baseClass}__dropzone`} {...getRootProps()}>\n <input className={`${baseClass}__input`} {...getInputProps()} />\n {isDragActive ? (\n <div>{t('importExport:dropTitle')}</div>\n ) : (\n <div>{t('importExport:dropAbstract')}</div>\n )}\n </div>\n )}\n {error && (\n <>\n <div>{t('importExport:parseError')}</div>\n {error.message && <div>{error.message}</div>}\n </>\n )}\n <div className={`${baseClass}__foot`}>\n {dirty && <Button type=\"button\" buttonStyle=\"secondary\" onClick={onClear}>\n {t('importExport:clear')}\n </Button>}\n <Button type=\"submit\" disabled={!valid}>\n {t('importExport:submit')}\n </Button>\n </div>\n </form>\n </main>\n </MinimalTemplate>\n );\n};\n\nfunction once<T extends IEntity = IEntity>(items: T[], item: T): T {\n const exhistingItem = items.find(x => x.id === item.id);\n if (exhistingItem) {\n return exhistingItem;\n }\n items.push(item);\n return item;\n}\n"],"names":["MinimalTemplate","Button","CheckboxInput","SelectInput","XIcon","toast","useAuth","useConfig","useLocale","useModal","useTranslation","getRouteResolver","Papa","React","useCallback","useEffect","useState","useDropzone","ImportLogInvalidTypes","ImportLogType","ImportMode","INITIAL_DATA","importMode","Append","dataParsing","baseClass","ImportModal","parser","slug","closeAllModals","config","getEntityConfig","collectionConfig","collectionSlug","routeResolver","collectionUrl","api","t","format","text","rest","replace","m","g","i","parseInt","length","String","code","locale","user","dirty","setDirty","valid","setValid","error","setError","name","setName","csv","setCSV","keys","setKeys","data","setData","items","setItems","logs","setLogs","setImportMode","setDataParsing","importModes","Object","entries","map","k","v","value","label","onSelectDidChange","option","Array","isArray","onCheckboxkDidChange","event","validate","messageByType","key","type","message","Required","Optional","Invalid","Duplicate","Unexpected","addLog","invalid","id","log","once","count","itemOptionalKeys","itemKeys","fields","filter","x","undefined","fieldKeys","requiredFields","Update","uniqueFields","requiredFieldKeys","optionalFieldKeys","includes","uniqueFieldKeys","valueParsers","parseValue","item","field","find","Boolean","Date","Number","row","forEach","push","httpResponse","fetch","method","credentials","headers","ok","storedItems","json","values","storedValues","validation","siblingData","operation","sortOrder","sort","a","b","indexOf","errors","console","onDrop","acceptedFiles","acceptedFile","reader","FileReader","onabort","onerror","onload","result","parse","resultData","reduce","p","c","readAsText","getRootProps","getInputProps","isDragActive","accept","maxSize","maxFiles","onSubmit","url","body","JSON","stringify","response","success","onClose","onClear","header","className","h3","buttonStyle","onClick","main","form","e","preventDefault","div","path","options","onChange","checked","onToggle","dangerouslySetInnerHTML","__html","ul","li","input","disabled","exhistingItem"],"mappings":"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"}
|
|
@@ -5,8 +5,8 @@ import { findHandler } from '../utils/findHandler';
|
|
|
5
5
|
import { getCollectionItems } from './collection.service';
|
|
6
6
|
import { collectPageRedirects } from './redirect.service';
|
|
7
7
|
import { isMixerRequest } from './utils';
|
|
8
|
-
/**
|
|
9
|
-
* Rest api page collection get handler.
|
|
8
|
+
/**
|
|
9
|
+
* Rest api page collection get handler.
|
|
10
10
|
*/ export const pageIndexGet = (slug)=>({
|
|
11
11
|
path: '/',
|
|
12
12
|
method: 'get',
|
|
@@ -38,8 +38,8 @@ import { isMixerRequest } from './utils';
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
|
-
/**
|
|
42
|
-
* Rest api page collection detail get handler.
|
|
41
|
+
/**
|
|
42
|
+
* Rest api page collection detail get handler.
|
|
43
43
|
*/ export const pageDetailGet = (slug)=>({
|
|
44
44
|
path: '/:id',
|
|
45
45
|
method: 'get',
|
|
@@ -65,11 +65,11 @@ import { isMixerRequest } from './utils';
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
|
-
/**
|
|
69
|
-
* eg. PAYLOAD_PAGE_FIND = 'components'
|
|
68
|
+
/**
|
|
69
|
+
* eg. PAYLOAD_PAGE_FIND = 'components'
|
|
70
70
|
*/ const afterPageOperationFind = process.env.PAYLOAD_FILTER_FIND ? process.env.PAYLOAD_FILTER_FIND.split(',').map((x)=>x.trim()) : [];
|
|
71
|
-
/**
|
|
72
|
-
* Modify record for Mixer when queried by market and locale.
|
|
71
|
+
/**
|
|
72
|
+
* Modify record for Mixer when queried by market and locale.
|
|
73
73
|
*/ export const afterPageOperationHook = (collectionConfig)=>async ({ args, collection, req, operation, result })=>{
|
|
74
74
|
if (afterPageOperationFind.length > 0 && isMixerRequest(req) && operation === 'find' && req.pathname !== '/store' && req.query.optimize !== 'false') {
|
|
75
75
|
// console.log('withPage.afterPageOperationHook', operation, collection.slug, req.pathname);
|
|
@@ -78,8 +78,8 @@ import { isMixerRequest } from './utils';
|
|
|
78
78
|
}
|
|
79
79
|
return result;
|
|
80
80
|
};
|
|
81
|
-
/**
|
|
82
|
-
* Decorate record for Mixer when queried by market and locale.
|
|
81
|
+
/**
|
|
82
|
+
* Decorate record for Mixer when queried by market and locale.
|
|
83
83
|
*/ export const afterPageReadHook = (collectionConfig)=>async ({ doc, req, context, findMany })=>{
|
|
84
84
|
const { market, locale, routes, categories } = context;
|
|
85
85
|
// console.log('afterPageReadHook', doc.title, query, market, locale);
|
|
@@ -92,13 +92,47 @@ import { isMixerRequest } from './utils';
|
|
|
92
92
|
const withHref = await decorateHref_(withCategory, collectionConfig.slug, context);
|
|
93
93
|
const withNav = await decorateNav_(withHref, collectionConfig.slug, context);
|
|
94
94
|
return withNav;
|
|
95
|
-
/*
|
|
96
|
-
const withRichText = await decorateRichText_(withNav, collectionConfig.fields, context as Required<MixerContext>, req.payload.config);
|
|
97
|
-
return withRichText;
|
|
95
|
+
/*
|
|
96
|
+
const withRichText = await decorateRichText_(withNav, collectionConfig.fields, context as Required<MixerContext>, req.payload.config);
|
|
97
|
+
return withRichText;
|
|
98
98
|
*/ };
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
101
|
-
*/
|
|
99
|
+
/**
|
|
100
|
+
* Trigger revalidation in the Next.js Mixer app for a given page document.
|
|
101
|
+
*/ async function triggerPageRevalidation(schema, pageId) {
|
|
102
|
+
if (!schema || !pageId) return;
|
|
103
|
+
// todo: dedicated envVar for mixerUrl
|
|
104
|
+
const mixerUrl = process.env.PAYLOAD_PUBLIC_PREVIEW_URL;
|
|
105
|
+
const mixerSecret = process.env.MIXER_SECRET;
|
|
106
|
+
if (!mixerUrl || !mixerSecret) {
|
|
107
|
+
console.warn(`[revalidation] Skipping revalidation for ${schema}:${pageId}: MIXER_SECRET or PAYLOAD_PUBLIC_PREVIEW_URL is missing.`);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
// console.log(`[revalidation] Triggering revalidation for ${schema}:${pageId}`);
|
|
112
|
+
const response = await fetch(`${mixerUrl}/api/__revalidate`, {
|
|
113
|
+
method: 'POST',
|
|
114
|
+
headers: {
|
|
115
|
+
'Authorization': `Bearer ${mixerSecret}`,
|
|
116
|
+
'Content-Type': 'application/json'
|
|
117
|
+
},
|
|
118
|
+
body: JSON.stringify({
|
|
119
|
+
schema,
|
|
120
|
+
page: String(pageId)
|
|
121
|
+
})
|
|
122
|
+
});
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
const text = await response.text().catch(()=>'');
|
|
125
|
+
console.warn(`[revalidation] Failed to revalidate ${schema}:${pageId}`, response.status, text);
|
|
126
|
+
} else {
|
|
127
|
+
// console.log(`[revalidation] Successfully revalidated ${schema}:${pageId}`);
|
|
128
|
+
}
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error(`[revalidation] Error triggering revalidation for ${schema}:${pageId}`, error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Create a record of the pages collection related to the created document.
|
|
135
|
+
*/ export const afterPageChangeHook = async ({ doc, req, previousDoc, operation, collection })=>{
|
|
102
136
|
if (operation === 'update') {
|
|
103
137
|
const { query = {} } = req;
|
|
104
138
|
const { draft } = query;
|
|
@@ -108,10 +142,13 @@ import { isMixerRequest } from './utils';
|
|
|
108
142
|
// console.log('redirects', redirects);
|
|
109
143
|
}
|
|
110
144
|
}
|
|
145
|
+
if (doc._status === 'published') {
|
|
146
|
+
triggerPageRevalidation(collection?.slug, doc.id);
|
|
147
|
+
}
|
|
111
148
|
return doc;
|
|
112
149
|
};
|
|
113
|
-
/**
|
|
114
|
-
* Delete records of the pages collection related to the deleted document.
|
|
150
|
+
/**
|
|
151
|
+
* Delete records of the pages collection related to the deleted document.
|
|
115
152
|
*/ export const afterPageDeleteHook = async ({ req, id, doc })=>{
|
|
116
153
|
const { query = {} } = req;
|
|
117
154
|
const { draft } = query;
|
|
@@ -119,16 +156,16 @@ import { isMixerRequest } from './utils';
|
|
|
119
156
|
console.log('RedirectService.deletePage !!!');
|
|
120
157
|
// !!! todo find and redirect to parentCategory connected to a page
|
|
121
158
|
}
|
|
122
|
-
}; /*
|
|
123
|
-
export const beforeValidateHook: CollectionBeforeValidateHook = async ({
|
|
124
|
-
data, // incoming data to update or create with
|
|
125
|
-
req, // full express request
|
|
126
|
-
operation, // name of the operation ie. 'create', 'update'
|
|
127
|
-
originalDoc, // original document
|
|
128
|
-
}) => {
|
|
129
|
-
console.log(data, originalDoc, req.query);
|
|
130
|
-
return data; // Return data to either create or update a document with
|
|
131
|
-
};
|
|
159
|
+
}; /*
|
|
160
|
+
export const beforeValidateHook: CollectionBeforeValidateHook = async ({
|
|
161
|
+
data, // incoming data to update or create with
|
|
162
|
+
req, // full express request
|
|
163
|
+
operation, // name of the operation ie. 'create', 'update'
|
|
164
|
+
originalDoc, // original document
|
|
165
|
+
}) => {
|
|
166
|
+
console.log(data, originalDoc, req.query);
|
|
167
|
+
return data; // Return data to either create or update a document with
|
|
168
|
+
};
|
|
132
169
|
*/
|
|
133
170
|
|
|
134
171
|
//# sourceMappingURL=page.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/api/page.service.ts"],"sourcesContent":["import { ICategorized } from '@websolutespa/bom-core';\r\nimport { ResponseError, ResponseSuccess } from '@websolutespa/payload-utils/server';\r\nimport { CollectionAfterChangeHook, CollectionAfterDeleteHook, CollectionAfterOperationHook, CollectionAfterReadHook, CollectionConfig, Endpoint, PayloadRequest } from 'payload';\r\nimport { decorateCategory_, decorateComponents_, decorateHref_, decorateNav_, decorateSchema_ } from '../decorators';\r\nimport { findByIDHandler } from '../utils/findByIDHandler';\r\nimport { findHandler } from '../utils/findHandler';\r\nimport { getCollectionItems } from './collection.service';\r\nimport { collectPageRedirects } from './redirect.service';\r\nimport { MixerContext } from './types';\r\nimport { isMixerRequest } from './utils';\r\n\r\n/**\r\n * Rest api page collection get handler.\r\n */\r\nexport const pageIndexGet: ((slug: string) => Endpoint) = (slug: string) => ({\r\n path: '/',\r\n method: 'get',\r\n handler: async (req: PayloadRequest) => {\r\n try {\r\n const { query } = req;\r\n // console.log('pageIndexGet.query', ...Object.entries(query || {}));\r\n if (!query) {\r\n return findHandler(req);\r\n }\r\n const { locale, market, pagination } = query;\r\n if (typeof market === 'string' && typeof locale === 'string') {\r\n // const context = await setMixerContext(req, market, locale);\r\n // console.log('pageIndexGet.context', context.market, context.locale, context.routes.length, context.categories.length);\r\n if (pagination === 'true') {\r\n return findHandler(req);\r\n } else {\r\n const items = await getCollectionItems(req, slug);\r\n return ResponseSuccess(items);\r\n }\r\n } else if (pagination === 'false') {\r\n const items = await getCollectionItems(req, slug);\r\n return ResponseSuccess(items);\r\n }\r\n return findHandler(req);\r\n } catch (error: any) {\r\n console.error(`PageService.pageIndexGet.${slug}.error`, error);\r\n return ResponseError(error);\r\n }\r\n },\r\n});\r\n\r\n/**\r\n * Rest api page collection detail get handler.\r\n */\r\nexport const pageDetailGet: ((slug: string) => Endpoint) = (slug: string) => ({\r\n path: '/:id',\r\n method: 'get',\r\n handler: async (req: PayloadRequest) => {\r\n try {\r\n const { query } = req;\r\n // console.log('pageDetailGet.query', ...Object.entries(query || {}));\r\n if (!query) {\r\n return findByIDHandler(req);\r\n }\r\n const { market, locale } = query;\r\n // console.log('pageDetailGet', 'market', market, 'locale', locale);\r\n if (!(typeof market === 'string' && typeof locale === 'string')) {\r\n return findByIDHandler(req);\r\n }\r\n req.query.depth = req.query.depth || '3';\r\n // const context = await setMixerContext(req, market, locale);\r\n // console.log('pageDetailGet.context', context.market, context.locale, context.routes.length, context.categories.length);\r\n return findByIDHandler(req);\r\n } catch (error: any) {\r\n console.error(`PageService.pageDetailGet.${slug}.error`, error);\r\n return ResponseError(error);\r\n }\r\n },\r\n});\r\n\r\n/**\r\n * eg. PAYLOAD_PAGE_FIND = 'components'\r\n */\r\nconst afterPageOperationFind: string[] = (\r\n process.env.PAYLOAD_FILTER_FIND ?\r\n process.env.PAYLOAD_FILTER_FIND.split(',').map(x => x.trim()) :\r\n []\r\n);\r\n\r\n/**\r\n * Modify record for Mixer when queried by market and locale.\r\n */\r\nexport const afterPageOperationHook: (collectionConfig: CollectionConfig) => CollectionAfterOperationHook = (collectionConfig: CollectionConfig) => async ({\r\n args,\r\n collection,\r\n req,\r\n operation,\r\n result,\r\n}) => {\r\n if (\r\n afterPageOperationFind.length > 0 &&\r\n isMixerRequest(req) &&\r\n operation === 'find' &&\r\n req.pathname !== '/store' &&\r\n req.query.optimize !== 'false'\r\n ) {\r\n // console.log('withPage.afterPageOperationHook', operation, collection.slug, req.pathname);\r\n result.docs = result.docs.map(x => Object.fromEntries(\r\n Object.entries(x).filter(\r\n ([k, v]) => !afterPageOperationFind.includes(k)\r\n )\r\n )) as typeof result.docs;\r\n // console.log('withPage.afterPageOperationHook.done');\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Decorate record for Mixer when queried by market and locale.\r\n */\r\nexport const afterPageReadHook: (collectionConfig: CollectionConfig) => CollectionAfterReadHook = (collectionConfig: CollectionConfig) => async ({\r\n doc,\r\n req,\r\n context,\r\n findMany,\r\n}) => {\r\n const { market, locale, routes, categories } = context as MixerContext;\r\n // console.log('afterPageReadHook', doc.title, query, market, locale);\r\n if (!market || !locale || !routes || !categories) {\r\n return doc;\r\n }\r\n const withSchema = await decorateSchema_(doc, collectionConfig.slug);\r\n const withComponents = await decorateComponents_(withSchema, collectionConfig.slug, context as Required<MixerContext>);\r\n const withCategory = await decorateCategory_(withComponents, collectionConfig.slug, context as Required<MixerContext>);\r\n const withHref = await decorateHref_(withCategory, collectionConfig.slug, context as Required<MixerContext>);\r\n const withNav = await decorateNav_(withHref, collectionConfig.slug, context as Required<MixerContext>);\r\n return withNav;\r\n /*\r\n const withRichText = await decorateRichText_(withNav, collectionConfig.fields, context as Required<MixerContext>, req.payload.config);\r\n return withRichText;\r\n */\r\n};\r\n\r\n/**\r\n * Create a record of the pages collection related to the created document.\r\n */\r\nexport const afterPageChangeHook: CollectionAfterChangeHook<ICategorized> = async ({\r\n doc, // full document data\r\n req, // full express request\r\n previousDoc, // document data before updating the collection\r\n operation, // name of the operation ie. 'create', 'update'\r\n}) => {\r\n if (operation === 'update') {\r\n const { query = {} } = req;\r\n const { draft } = query;\r\n // console.log('afterPageChange', operation, draft, doc.isDefault, previousDoc.slug, doc.slug);\r\n if (!draft && doc.isDefault !== true && previousDoc.slug && doc.slug) {\r\n const redirects = await collectPageRedirects(req, previousDoc, doc);\r\n // console.log('redirects', redirects);\r\n }\r\n }\r\n return doc;\r\n};\r\n\r\n/**\r\n * Delete records of the pages collection related to the deleted document.\r\n */\r\nexport const afterPageDeleteHook: CollectionAfterDeleteHook = async ({\r\n req, // full express request\r\n id, // id of document to delete\r\n doc, // deleted document\r\n}) => {\r\n const { query = {} } = req;\r\n const { draft } = query;\r\n if (!draft && doc.isDefault !== true && doc.slug) {\r\n console.log('RedirectService.deletePage !!!');\r\n // !!! todo find and redirect to parentCategory connected to a page\r\n }\r\n};\r\n\r\n/*\r\nexport const beforeValidateHook: CollectionBeforeValidateHook = async ({\r\n data, // incoming data to update or create with\r\n req, // full express request\r\n operation, // name of the operation ie. 'create', 'update'\r\n originalDoc, // original document\r\n}) => {\r\n console.log(data, originalDoc, req.query);\r\n return data; // Return data to either create or update a document with\r\n};\r\n*/\r\n"],"names":["ResponseError","ResponseSuccess","decorateCategory_","decorateComponents_","decorateHref_","decorateNav_","decorateSchema_","findByIDHandler","findHandler","getCollectionItems","collectPageRedirects","isMixerRequest","pageIndexGet","slug","path","method","handler","req","query","locale","market","pagination","items","error","console","pageDetailGet","depth","afterPageOperationFind","process","env","PAYLOAD_FILTER_FIND","split","map","x","trim","afterPageOperationHook","collectionConfig","args","collection","operation","result","length","pathname","optimize","docs","Object","fromEntries","entries","filter","k","v","includes","afterPageReadHook","doc","context","findMany","routes","categories","withSchema","withComponents","withCategory","withHref","withNav","afterPageChangeHook","previousDoc","draft","isDefault","redirects","afterPageDeleteHook","id","log"],"mappings":"AACA,SAASA,aAAa,EAAEC,eAAe,QAAQ,qCAAqC;AAEpF,SAASC,iBAAiB,EAAEC,mBAAmB,EAAEC,aAAa,EAAEC,YAAY,EAAEC,eAAe,QAAQ,gBAAgB;AACrH,SAASC,eAAe,QAAQ,2BAA2B;AAC3D,SAASC,WAAW,QAAQ,uBAAuB;AACnD,SAASC,kBAAkB,QAAQ,uBAAuB;AAC1D,SAASC,oBAAoB,QAAQ,qBAAqB;AAE1D,SAASC,cAAc,QAAQ,UAAU;AAEzC;;CAEC,GACD,OAAO,MAAMC,eAA6C,CAACC,OAAkB,CAAA;QAC3EC,MAAM;QACNC,QAAQ;QACRC,SAAS,OAAOC;YACd,IAAI;gBACF,MAAM,EAAEC,KAAK,EAAE,GAAGD;gBAClB,qEAAqE;gBACrE,IAAI,CAACC,OAAO;oBACV,OAAOV,YAAYS;gBACrB;gBACA,MAAM,EAAEE,MAAM,EAAEC,MAAM,EAAEC,UAAU,EAAE,GAAGH;gBACvC,IAAI,OAAOE,WAAW,YAAY,OAAOD,WAAW,UAAU;oBAC5D,8DAA8D;oBAC9D,yHAAyH;oBACzH,IAAIE,eAAe,QAAQ;wBACzB,OAAOb,YAAYS;oBACrB,OAAO;wBACL,MAAMK,QAAQ,MAAMb,mBAAmBQ,KAAKJ;wBAC5C,OAAOZ,gBAAgBqB;oBACzB;gBACF,OAAO,IAAID,eAAe,SAAS;oBACjC,MAAMC,QAAQ,MAAMb,mBAAmBQ,KAAKJ;oBAC5C,OAAOZ,gBAAgBqB;gBACzB;gBACA,OAAOd,YAAYS;YACrB,EAAE,OAAOM,OAAY;gBACnBC,QAAQD,KAAK,CAAC,CAAC,yBAAyB,EAAEV,KAAK,MAAM,CAAC,EAAEU;gBACxD,OAAOvB,cAAcuB;YACvB;QACF;IACF,CAAA,EAAG;AAEH;;CAEC,GACD,OAAO,MAAME,gBAA8C,CAACZ,OAAkB,CAAA;QAC5EC,MAAM;QACNC,QAAQ;QACRC,SAAS,OAAOC;YACd,IAAI;gBACF,MAAM,EAAEC,KAAK,EAAE,GAAGD;gBAClB,sEAAsE;gBACtE,IAAI,CAACC,OAAO;oBACV,OAAOX,gBAAgBU;gBACzB;gBACA,MAAM,EAAEG,MAAM,EAAED,MAAM,EAAE,GAAGD;gBAC3B,oEAAoE;gBACpE,IAAI,CAAE,CAAA,OAAOE,WAAW,YAAY,OAAOD,WAAW,QAAO,GAAI;oBAC/D,OAAOZ,gBAAgBU;gBACzB;gBACAA,IAAIC,KAAK,CAACQ,KAAK,GAAGT,IAAIC,KAAK,CAACQ,KAAK,IAAI;gBACrC,8DAA8D;gBAC9D,0HAA0H;gBAC1H,OAAOnB,gBAAgBU;YACzB,EAAE,OAAOM,OAAY;gBACnBC,QAAQD,KAAK,CAAC,CAAC,0BAA0B,EAAEV,KAAK,MAAM,CAAC,EAAEU;gBACzD,OAAOvB,cAAcuB;YACvB;QACF;IACF,CAAA,EAAG;AAEH;;CAEC,GACD,MAAMI,yBACJC,QAAQC,GAAG,CAACC,mBAAmB,GAC7BF,QAAQC,GAAG,CAACC,mBAAmB,CAACC,KAAK,CAAC,KAAKC,GAAG,CAACC,CAAAA,IAAKA,EAAEC,IAAI,MAC1D,EAAE;AAGN;;CAEC,GACD,OAAO,MAAMC,yBAA+F,CAACC,mBAAuC,OAAO,EACzJC,IAAI,EACJC,UAAU,EACVrB,GAAG,EACHsB,SAAS,EACTC,MAAM,EACP;QACC,IACEb,uBAAuBc,MAAM,GAAG,KAChC9B,eAAeM,QACfsB,cAAc,UACdtB,IAAIyB,QAAQ,KAAK,YACjBzB,IAAIC,KAAK,CAACyB,QAAQ,KAAK,SACvB;YACA,4FAA4F;YAC5FH,OAAOI,IAAI,GAAGJ,OAAOI,IAAI,CAACZ,GAAG,CAACC,CAAAA,IAAKY,OAAOC,WAAW,CACnDD,OAAOE,OAAO,CAACd,GAAGe,MAAM,CACtB,CAAC,CAACC,GAAGC,EAAE,GAAK,CAACvB,uBAAuBwB,QAAQ,CAACF;QAGjD,uDAAuD;QACzD;QACA,OAAOT;IACT,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMY,oBAAqF,CAAChB,mBAAuC,OAAO,EAC/IiB,GAAG,EACHpC,GAAG,EACHqC,OAAO,EACPC,QAAQ,EACT;QACC,MAAM,EAAEnC,MAAM,EAAED,MAAM,EAAEqC,MAAM,EAAEC,UAAU,EAAE,GAAGH;QAC/C,sEAAsE;QACtE,IAAI,CAAClC,UAAU,CAACD,UAAU,CAACqC,UAAU,CAACC,YAAY;YAChD,OAAOJ;QACT;QACA,MAAMK,aAAa,MAAMpD,gBAAgB+C,KAAKjB,iBAAiBvB,IAAI;QACnE,MAAM8C,iBAAiB,MAAMxD,oBAAoBuD,YAAYtB,iBAAiBvB,IAAI,EAAEyC;QACpF,MAAMM,eAAe,MAAM1D,kBAAkByD,gBAAgBvB,iBAAiBvB,IAAI,EAAEyC;QACpF,MAAMO,WAAW,MAAMzD,cAAcwD,cAAcxB,iBAAiBvB,IAAI,EAAEyC;QAC1E,MAAMQ,UAAU,MAAMzD,aAAawD,UAAUzB,iBAAiBvB,IAAI,EAAEyC;QACpE,OAAOQ;IACP;;;EAGA,GACF,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMC,sBAA+D,OAAO,EACjFV,GAAG,EACHpC,GAAG,EACH+C,WAAW,EACXzB,SAAS,EACV;IACC,IAAIA,cAAc,UAAU;QAC1B,MAAM,EAAErB,QAAQ,CAAC,CAAC,EAAE,GAAGD;QACvB,MAAM,EAAEgD,KAAK,EAAE,GAAG/C;QAClB,+FAA+F;QAC/F,IAAI,CAAC+C,SAASZ,IAAIa,SAAS,KAAK,QAAQF,YAAYnD,IAAI,IAAIwC,IAAIxC,IAAI,EAAE;YACpE,MAAMsD,YAAY,MAAMzD,qBAAqBO,KAAK+C,aAAaX;QAC/D,uCAAuC;QACzC;IACF;IACA,OAAOA;AACT,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMe,sBAAiD,OAAO,EACnEnD,GAAG,EACHoD,EAAE,EACFhB,GAAG,EACJ;IACC,MAAM,EAAEnC,QAAQ,CAAC,CAAC,EAAE,GAAGD;IACvB,MAAM,EAAEgD,KAAK,EAAE,GAAG/C;IAClB,IAAI,CAAC+C,SAASZ,IAAIa,SAAS,KAAK,QAAQb,IAAIxC,IAAI,EAAE;QAChDW,QAAQ8C,GAAG,CAAC;IACZ,mEAAmE;IACrE;AACF,EAAE,CAEF;;;;;;;;;;AAUA"}
|
|
1
|
+
{"version":3,"sources":["../../../src/core/api/page.service.ts"],"sourcesContent":["import { ICategorized } from '@websolutespa/bom-core';\nimport { ResponseError, ResponseSuccess } from '@websolutespa/payload-utils/server';\nimport { CollectionAfterChangeHook, CollectionAfterDeleteHook, CollectionAfterOperationHook, CollectionAfterReadHook, CollectionConfig, Endpoint, PayloadRequest } from 'payload';\nimport { decorateCategory_, decorateComponents_, decorateHref_, decorateNav_, decorateSchema_ } from '../decorators';\nimport { findByIDHandler } from '../utils/findByIDHandler';\nimport { findHandler } from '../utils/findHandler';\nimport { getCollectionItems } from './collection.service';\nimport { collectPageRedirects } from './redirect.service';\nimport { MixerContext } from './types';\nimport { isMixerRequest } from './utils';\n\n/**\n * Rest api page collection get handler.\n */\nexport const pageIndexGet: ((slug: string) => Endpoint) = (slug: string) => ({\n path: '/',\n method: 'get',\n handler: async (req: PayloadRequest) => {\n try {\n const { query } = req;\n // console.log('pageIndexGet.query', ...Object.entries(query || {}));\n if (!query) {\n return findHandler(req);\n }\n const { locale, market, pagination } = query;\n if (typeof market === 'string' && typeof locale === 'string') {\n // const context = await setMixerContext(req, market, locale);\n // console.log('pageIndexGet.context', context.market, context.locale, context.routes.length, context.categories.length);\n if (pagination === 'true') {\n return findHandler(req);\n } else {\n const items = await getCollectionItems(req, slug);\n return ResponseSuccess(items);\n }\n } else if (pagination === 'false') {\n const items = await getCollectionItems(req, slug);\n return ResponseSuccess(items);\n }\n return findHandler(req);\n } catch (error: any) {\n console.error(`PageService.pageIndexGet.${slug}.error`, error);\n return ResponseError(error);\n }\n },\n});\n\n/**\n * Rest api page collection detail get handler.\n */\nexport const pageDetailGet: ((slug: string) => Endpoint) = (slug: string) => ({\n path: '/:id',\n method: 'get',\n handler: async (req: PayloadRequest) => {\n try {\n const { query } = req;\n // console.log('pageDetailGet.query', ...Object.entries(query || {}));\n if (!query) {\n return findByIDHandler(req);\n }\n const { market, locale } = query;\n // console.log('pageDetailGet', 'market', market, 'locale', locale);\n if (!(typeof market === 'string' && typeof locale === 'string')) {\n return findByIDHandler(req);\n }\n req.query.depth = req.query.depth || '3';\n // const context = await setMixerContext(req, market, locale);\n // console.log('pageDetailGet.context', context.market, context.locale, context.routes.length, context.categories.length);\n return findByIDHandler(req);\n } catch (error: any) {\n console.error(`PageService.pageDetailGet.${slug}.error`, error);\n return ResponseError(error);\n }\n },\n});\n\n/**\n * eg. PAYLOAD_PAGE_FIND = 'components'\n */\nconst afterPageOperationFind: string[] = (\n process.env.PAYLOAD_FILTER_FIND ?\n process.env.PAYLOAD_FILTER_FIND.split(',').map(x => x.trim()) :\n []\n);\n\n/**\n * Modify record for Mixer when queried by market and locale.\n */\nexport const afterPageOperationHook: (collectionConfig: CollectionConfig) => CollectionAfterOperationHook = (collectionConfig: CollectionConfig) => async ({\n args,\n collection,\n req,\n operation,\n result,\n}) => {\n if (\n afterPageOperationFind.length > 0 &&\n isMixerRequest(req) &&\n operation === 'find' &&\n req.pathname !== '/store' &&\n req.query.optimize !== 'false'\n ) {\n // console.log('withPage.afterPageOperationHook', operation, collection.slug, req.pathname);\n result.docs = result.docs.map(x => Object.fromEntries(\n Object.entries(x).filter(\n ([k, v]) => !afterPageOperationFind.includes(k)\n )\n )) as typeof result.docs;\n // console.log('withPage.afterPageOperationHook.done');\n }\n return result;\n};\n\n/**\n * Decorate record for Mixer when queried by market and locale.\n */\nexport const afterPageReadHook: (collectionConfig: CollectionConfig) => CollectionAfterReadHook = (collectionConfig: CollectionConfig) => async ({\n doc,\n req,\n context,\n findMany,\n}) => {\n const { market, locale, routes, categories } = context as MixerContext;\n // console.log('afterPageReadHook', doc.title, query, market, locale);\n if (!market || !locale || !routes || !categories) {\n return doc;\n }\n const withSchema = await decorateSchema_(doc, collectionConfig.slug);\n const withComponents = await decorateComponents_(withSchema, collectionConfig.slug, context as Required<MixerContext>);\n const withCategory = await decorateCategory_(withComponents, collectionConfig.slug, context as Required<MixerContext>);\n const withHref = await decorateHref_(withCategory, collectionConfig.slug, context as Required<MixerContext>);\n const withNav = await decorateNav_(withHref, collectionConfig.slug, context as Required<MixerContext>);\n return withNav;\n /*\n const withRichText = await decorateRichText_(withNav, collectionConfig.fields, context as Required<MixerContext>, req.payload.config);\n return withRichText;\n */\n};\n\n/**\n * Trigger revalidation in the Next.js Mixer app for a given page document.\n */\nasync function triggerPageRevalidation(schema?: string, pageId?: string | number) {\n if (!schema || !pageId) return;\n // todo: dedicated envVar for mixerUrl\n const mixerUrl = process.env.PAYLOAD_PUBLIC_PREVIEW_URL;\n const mixerSecret = process.env.MIXER_SECRET;\n\n if (!mixerUrl || !mixerSecret) {\n console.warn(`[revalidation] Skipping revalidation for ${schema}:${pageId}: MIXER_SECRET or PAYLOAD_PUBLIC_PREVIEW_URL is missing.`);\n return;\n }\n\n try {\n // console.log(`[revalidation] Triggering revalidation for ${schema}:${pageId}`);\n const response = await fetch(`${mixerUrl}/api/__revalidate`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${mixerSecret}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ schema, page: String(pageId) }),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n console.warn(`[revalidation] Failed to revalidate ${schema}:${pageId}`, response.status, text);\n } else {\n // console.log(`[revalidation] Successfully revalidated ${schema}:${pageId}`);\n }\n } catch (error) {\n console.error(`[revalidation] Error triggering revalidation for ${schema}:${pageId}`, error);\n }\n}\n\n/**\n * Create a record of the pages collection related to the created document.\n */\nexport const afterPageChangeHook: CollectionAfterChangeHook<ICategorized> = async ({\n doc, // full document data\n req, // full express request\n previousDoc, // document data before updating the collection\n operation, // name of the operation ie. 'create', 'update'\n collection,\n}) => {\n if (operation === 'update') {\n const { query = {} } = req;\n const { draft } = query;\n // console.log('afterPageChange', operation, draft, doc.isDefault, previousDoc.slug, doc.slug);\n if (!draft && doc.isDefault !== true && previousDoc.slug && doc.slug) {\n const redirects = await collectPageRedirects(req, previousDoc, doc);\n // console.log('redirects', redirects);\n }\n }\n\n if (doc._status === 'published') {\n triggerPageRevalidation(collection?.slug, doc.id);\n }\n\n return doc;\n};\n\n/**\n * Delete records of the pages collection related to the deleted document.\n */\nexport const afterPageDeleteHook: CollectionAfterDeleteHook = async ({\n req, // full express request\n id, // id of document to delete\n doc, // deleted document\n}) => {\n const { query = {} } = req;\n const { draft } = query;\n if (!draft && doc.isDefault !== true && doc.slug) {\n console.log('RedirectService.deletePage !!!');\n // !!! todo find and redirect to parentCategory connected to a page\n }\n};\n\n/*\nexport const beforeValidateHook: CollectionBeforeValidateHook = async ({\n data, // incoming data to update or create with\n req, // full express request\n operation, // name of the operation ie. 'create', 'update'\n originalDoc, // original document\n}) => {\n console.log(data, originalDoc, req.query);\n return data; // Return data to either create or update a document with\n};\n*/\n"],"names":["ResponseError","ResponseSuccess","decorateCategory_","decorateComponents_","decorateHref_","decorateNav_","decorateSchema_","findByIDHandler","findHandler","getCollectionItems","collectPageRedirects","isMixerRequest","pageIndexGet","slug","path","method","handler","req","query","locale","market","pagination","items","error","console","pageDetailGet","depth","afterPageOperationFind","process","env","PAYLOAD_FILTER_FIND","split","map","x","trim","afterPageOperationHook","collectionConfig","args","collection","operation","result","length","pathname","optimize","docs","Object","fromEntries","entries","filter","k","v","includes","afterPageReadHook","doc","context","findMany","routes","categories","withSchema","withComponents","withCategory","withHref","withNav","triggerPageRevalidation","schema","pageId","mixerUrl","PAYLOAD_PUBLIC_PREVIEW_URL","mixerSecret","MIXER_SECRET","warn","response","fetch","headers","body","JSON","stringify","page","String","ok","text","catch","status","afterPageChangeHook","previousDoc","draft","isDefault","redirects","_status","id","afterPageDeleteHook","log"],"mappings":"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"}
|
|
@@ -1,33 +1,55 @@
|
|
|
1
1
|
// !!! todo use json service from bom-core
|
|
2
|
+
function clauseValue(value) {
|
|
3
|
+
if (value == null) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
if (Array.isArray(value)) {
|
|
7
|
+
return value.map((x)=>clauseValue(x));
|
|
8
|
+
}
|
|
9
|
+
if (typeof value === 'string') {
|
|
10
|
+
if (String(parseInt(value)) === value) {
|
|
11
|
+
return Number(value);
|
|
12
|
+
} else if (value === 'true') {
|
|
13
|
+
return true;
|
|
14
|
+
} else if (value === 'false') {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
2
20
|
function existsClause(value, exists) {
|
|
3
|
-
// console.log('existsClause', value, exists);
|
|
4
|
-
|
|
5
|
-
|
|
21
|
+
// console.log('existsClause', value, typeof value, exists, typeof exists);
|
|
22
|
+
const clause = clauseValue(exists);
|
|
23
|
+
if (typeof clause === 'boolean') {
|
|
24
|
+
return Boolean(value) === clause;
|
|
6
25
|
}
|
|
7
26
|
return true;
|
|
8
27
|
}
|
|
9
28
|
function equalsClause(value, equals) {
|
|
10
|
-
// console.log('equalsClause', value, equals);
|
|
11
|
-
|
|
12
|
-
|
|
29
|
+
// console.log('equalsClause', value, typeof value, equals, typeof equals);
|
|
30
|
+
const clause = clauseValue(equals);
|
|
31
|
+
if (typeof clause !== 'undefined') {
|
|
32
|
+
return value === clause;
|
|
13
33
|
}
|
|
14
34
|
return true;
|
|
15
35
|
}
|
|
16
36
|
function notEqualsClause(value, not_equals) {
|
|
17
|
-
// console.log('notEqualsClause', value, not_equals);
|
|
18
|
-
|
|
19
|
-
|
|
37
|
+
// console.log('notEqualsClause', value, typeof value, not_equals, typeof not_equals);
|
|
38
|
+
const clause = clauseValue(not_equals);
|
|
39
|
+
if (typeof clause !== 'undefined') {
|
|
40
|
+
return value !== not_equals;
|
|
20
41
|
}
|
|
21
42
|
return true;
|
|
22
43
|
}
|
|
23
44
|
function containsClause(value, contains) {
|
|
24
45
|
// console.log('containsClause', value, contains);
|
|
25
|
-
|
|
26
|
-
|
|
46
|
+
const clause = clauseValue(contains);
|
|
47
|
+
if (typeof clause !== 'undefined') {
|
|
48
|
+
const query = String(clause).toLowerCase();
|
|
27
49
|
if (Array.isArray(value)) {
|
|
28
|
-
return value.reduce((p, c)=>p || String(c).toLowerCase() ===
|
|
50
|
+
return value.reduce((p, c)=>p || String(c).toLowerCase() === query, false);
|
|
29
51
|
} else if (typeof value === 'string') {
|
|
30
|
-
return value.toLowerCase().includes(
|
|
52
|
+
return value.toLowerCase().includes(query);
|
|
31
53
|
} else {
|
|
32
54
|
return false;
|
|
33
55
|
}
|
|
@@ -36,63 +58,72 @@ function containsClause(value, contains) {
|
|
|
36
58
|
}
|
|
37
59
|
function inClause(value, values) {
|
|
38
60
|
// console.log('inClause', value, values);
|
|
39
|
-
|
|
40
|
-
|
|
61
|
+
const clause = clauseValue(values);
|
|
62
|
+
if (Array.isArray(clause)) {
|
|
63
|
+
return clause.indexOf(value) !== -1;
|
|
41
64
|
}
|
|
42
65
|
return true;
|
|
43
66
|
}
|
|
44
67
|
function notInClause(value, values) {
|
|
45
68
|
// console.log('notInClause', value, values);
|
|
46
|
-
|
|
47
|
-
|
|
69
|
+
const clause = clauseValue(values);
|
|
70
|
+
if (Array.isArray(clause)) {
|
|
71
|
+
return clause.indexOf(value) === -1;
|
|
48
72
|
}
|
|
49
73
|
return true;
|
|
50
74
|
}
|
|
51
75
|
function greaterThanClause(value, greater_than) {
|
|
52
76
|
// console.log('greaterThanClause', value, greater_than);
|
|
53
|
-
|
|
54
|
-
|
|
77
|
+
const clause = clauseValue(greater_than);
|
|
78
|
+
if (typeof clause === 'number') {
|
|
79
|
+
return typeof value === 'number' && value > clause;
|
|
55
80
|
}
|
|
56
81
|
return true;
|
|
57
82
|
}
|
|
58
83
|
function greaterThanEqualClause(value, greater_than_equal) {
|
|
59
84
|
// console.log('greaterThanEqualClause', value, greater_than_equal);
|
|
60
|
-
|
|
61
|
-
|
|
85
|
+
const clause = clauseValue(greater_than_equal);
|
|
86
|
+
if (typeof clause === 'number') {
|
|
87
|
+
return typeof value === 'number' && value >= clause;
|
|
62
88
|
}
|
|
63
89
|
return true;
|
|
64
90
|
}
|
|
65
91
|
function lessThanClause(value, less_than) {
|
|
66
92
|
// console.log('lessThanClause', value, less_than);
|
|
67
|
-
|
|
68
|
-
|
|
93
|
+
const clause = clauseValue(less_than);
|
|
94
|
+
if (typeof clause === 'number') {
|
|
95
|
+
return typeof value === 'number' && value < clause;
|
|
69
96
|
}
|
|
70
97
|
return true;
|
|
71
98
|
}
|
|
72
99
|
function lessThanEqualClause(value, less_than_equal) {
|
|
73
100
|
// console.log('lessThanEqualClause', value, less_than_equal);
|
|
74
|
-
|
|
75
|
-
|
|
101
|
+
const clause = clauseValue(less_than_equal);
|
|
102
|
+
if (typeof clause === 'number') {
|
|
103
|
+
return typeof value === 'number' && value <= clause;
|
|
76
104
|
}
|
|
77
105
|
return true;
|
|
78
106
|
}
|
|
79
107
|
function likeClause(value, query) {
|
|
80
108
|
// console.log('likeClause', value, query);
|
|
81
|
-
|
|
109
|
+
const clause = clauseValue(query);
|
|
110
|
+
if (typeof clause === 'string' && clause.length > 0) {
|
|
82
111
|
return String(value).toLowerCase().indexOf(query.toLowerCase()) !== -1;
|
|
83
112
|
}
|
|
84
113
|
return true;
|
|
85
114
|
}
|
|
86
115
|
function allClause(value, values) {
|
|
87
116
|
// console.log('allClause', value, values);
|
|
88
|
-
|
|
89
|
-
|
|
117
|
+
const clause = clauseValue(values);
|
|
118
|
+
if (Array.isArray(clause) && clause.length > 0) {
|
|
119
|
+
return Array.isArray(value) ? clause.reduce((p, c)=>p && value.includes(c), true) : false;
|
|
90
120
|
}
|
|
91
121
|
return true;
|
|
92
122
|
}
|
|
93
123
|
function nearClause(value, near) {
|
|
94
124
|
// console.log('nearClause', value, near);
|
|
95
|
-
|
|
125
|
+
const clause = clauseValue(near);
|
|
126
|
+
if (Array.isArray(clause) && clause.reduce((p, c)=>p && typeof c === 'number', true)) {
|
|
96
127
|
if (!Array.isArray(value)) {
|
|
97
128
|
return false;
|
|
98
129
|
}
|
|
@@ -104,7 +135,7 @@ function nearClause(value, near) {
|
|
|
104
135
|
if (typeof itemLatitude !== 'number') {
|
|
105
136
|
return false;
|
|
106
137
|
}
|
|
107
|
-
const [longitude, latitude, maxDistance, minDistance] =
|
|
138
|
+
const [longitude, latitude, maxDistance, minDistance] = clause;
|
|
108
139
|
const distance = longitude && latitude ? calculateDistanceInMeters_(itemLongitude, itemLatitude, longitude, latitude) : 0;
|
|
109
140
|
if (typeof maxDistance === 'number' && typeof minDistance === 'number') {
|
|
110
141
|
return distance <= maxDistance && distance >= minDistance;
|
|
@@ -180,16 +211,7 @@ export async function sortCollection(items, sort) {
|
|
|
180
211
|
const aStringValue = String(aValue);
|
|
181
212
|
const bStringValue = String(bValue);
|
|
182
213
|
return aStringValue.localeCompare(bStringValue) * reverse;
|
|
183
|
-
|
|
184
|
-
const aValue = String(a[key]);
|
|
185
|
-
const bValue = String(b[key]);
|
|
186
|
-
if (aValue.localeCompare(bValue) < 0) {
|
|
187
|
-
return -1 * reverse;
|
|
188
|
-
} else if (aValue.localeCompare(bValue) > 0) {
|
|
189
|
-
return 1 * reverse;
|
|
190
|
-
}
|
|
191
|
-
return 0;
|
|
192
|
-
*/ });
|
|
214
|
+
});
|
|
193
215
|
}
|
|
194
216
|
return items;
|
|
195
217
|
}
|