diff --git a/admin/src/components/SchemaMapper/index.js b/admin/src/components/SchemaMapper/index.js
index ee348e3..ed05266 100644
--- a/admin/src/components/SchemaMapper/index.js
+++ b/admin/src/components/SchemaMapper/index.js
@@ -1,97 +1,20 @@
-import React from "react"
-import {
- Box,
- Checkbox,
- Flex,
- Switch,
- Table,
- Thead,
- Tbody,
- Tr,
- Th,
- Td,
- Tooltip,
- Typography,
- Status
-} from "@strapi/design-system"
-import WarningIcon from "../WarningIcon"
-import { getSelectedPropsFromObj, getSelectedAttributesFromSchema } from "../../../../utils/schema"
-
-const isCollection = (value) => Array.isArray(value) && value.length > 0 && typeof value[0] === "object"
-
-const handleObjectField = (acc, fieldKey, fieldValue, relations) => {
- if (relations.includes(fieldKey)) {
- Object.keys(fieldValue).forEach((key) => acc.push(`${fieldKey}.${key}`))
- }
-}
-
-const handleCollectionField = (acc, fieldKey, fieldValue, relations) => {
- if (relations.includes(fieldKey)) {
- acc.push(fieldKey)
- }
-}
+import React from 'react'
+import { Box, Checkbox, Flex, Switch, Table, Thead, Tbody, Tr, Th, Td, Typography } from '@strapi/design-system'
+import { getSelectedPropsFromObj, getSelectedAttributesFromSchema } from '../../../../utils'
const generateSelectableAttributesFromSchema = ({ schema, relations }) => {
- const handlers = {
- object: handleObjectField,
- collection: handleCollectionField
- }
-
return Object.entries(schema).reduce((acc, [fieldKey, fieldValue]) => {
- const fieldType = fieldValue === "collection" ? "collection" : typeof fieldValue
-
- if (fieldType in handlers) {
- handlers[fieldType](acc, fieldKey, fieldValue, relations)
- } else if (!isCollection(fieldValue)) {
+ if (typeof fieldValue === 'object') {
+ if (relations.includes(fieldKey)) {
+ Object.keys(fieldValue).forEach((key) => acc.push(`${fieldKey}.${key}`))
+ }
+ } else {
acc.push(fieldKey)
}
-
return acc
}, [])
}
-const AttributeRow = ({ contentTypeSchema, field, isChecked, onCheck, isSearchableSelected, onSearchableSwitch, needsTransformation }) => (
-
-
- onCheck(field)} />
- |
- onCheck(field)}
- style={{ cursor: "pointer", display: "flex", alignItems: "center" }}
- >
- {field}
- {contentTypeSchema[field] === "collection" && needsTransformation && (
- <>
-
-
-
-
- Action required
-
-
-
- >
- )}
- |
-
-
- onSearchableSwitch(field)} />
-
- |
-
-)
-
const SchemaMapper = ({ collection, contentTypeSchema, onSchemaChange }) => {
const [selectedAttributes, setSelectedAttributes] = React.useState(
getSelectedAttributesFromSchema({
@@ -154,12 +77,10 @@ const SchemaMapper = ({ collection, contentTypeSchema, onSchemaChange }) => {
}
}
- const collectionDocumentsTransformers = collection?.documentsTransformers || {}
-
return (
- Attributes Mapping *
+ Attributes Mapping*
@@ -167,7 +88,13 @@ const SchemaMapper = ({ collection, contentTypeSchema, onSchemaChange }) => {
-
+ {/*TODO: style this*/}
+ {collection.hasSettings && (
+
+ The schema is handled by the Orama Cloud plugin settings.
+
+ )}
+ {!collection.hasSettings && (
@@ -177,15 +104,15 @@ const SchemaMapper = ({ collection, contentTypeSchema, onSchemaChange }) => {
onChange={() => selectAllAttributes()}
/>
|
-
+ |
Attribute
|
Searchable
@@ -194,22 +121,23 @@ const SchemaMapper = ({ collection, contentTypeSchema, onSchemaChange }) => {
|
- {schemaAttributes.map(
- (field) => (
-
- )
- )}
+ {schemaAttributes.map((field) => (
+
+
+ handleCheck(field)} />
+ |
+ handleCheck(field)} style={{ cursor: 'pointer' }}>
+ {field}
+ |
+
+
+ handleSearchable(field)} />
+
+ |
+
+ ))}
-
+
)}
)
diff --git a/server/content-types/collection/index.js b/server/content-types/collection/index.js
index a9c84db..71781e4 100644
--- a/server/content-types/collection/index.js
+++ b/server/content-types/collection/index.js
@@ -1,7 +1,7 @@
// @ts-nocheck
'use strict'
-const schema = require('./schema')
+const schema = require('./schema.json')
const lifecycles = require('./lifecycles')
module.exports = {
diff --git a/server/services/collections.js b/server/services/collections.js
index 7d15e1d..f9b7263 100644
--- a/server/services/collections.js
+++ b/server/services/collections.js
@@ -12,26 +12,25 @@ module.exports = ({ strapi }) => {
async find() {
const collections = await strapi.entityService.findMany(ENTITY_NAME)
- const result = collectionSettings ? collections.map(collection => {
+ return collectionSettings ? collections.reduce((acc, collection) => {
const settings = collectionSettings[collection.indexId]
- const hasTransformers = !!settings?.documentsTransformer
-
- if (hasTransformers) {
- const documentsTransformers = Object.keys(settings.documentsTransformer).reduce((acc, key) => {
- acc[key] = true
- return acc
- }, {})
-
- return {
- ...collection,
- documentsTransformers,
+ const hasValidSettings = settings?.schema && settings?.transformer
+
+ if (settings) {
+ if (hasValidSettings) {
+ acc.push({
+ ...collection,
+ hasSettings: true,
+ })
+ } else {
+ strapi.log.warn(`Collection with indexId ${collection.indexId} has settings but no schema or transformer`)
}
+ } else {
+ acc.push(collection)
}
- return collection
- }) : collections
-
- return result
+ return acc
+ }, []) : collections
},
/**
diff --git a/server/services/orama-manager.js b/server/services/orama-manager.js
index 6183f65..d5aafd4 100644
--- a/server/services/orama-manager.js
+++ b/server/services/orama-manager.js
@@ -1,7 +1,7 @@
'use strict'
const { CloudManager } = require('@oramacloud/client')
-const { getSchemaFromEntryStructure, getSelectedPropsFromObj } = require('../../utils/schema')
+const { getSelectedPropsFromObj } = require('../../utils')
class OramaManager {
constructor({ strapi }) {
@@ -26,6 +26,8 @@ class OramaManager {
* @param {Object} collection - Collection object
* */
validate(collection) {
+ const collectionSettings = this.collectionSettings?.[collection.indexId]
+
if (!collection) {
this.strapi.log.error(`Collection not found`)
return false
@@ -50,6 +52,13 @@ class OramaManager {
return false
}
+ if ((collectionSettings.schema && !collectionSettings.transformer) || (!collectionSettings.schema && collectionSettings.transformer)) {
+ this.strapi.log.error(
+ `ERROR: Both schema and transformer are required in the collection settings`
+ )
+ return false
+ }
+
return true
}
@@ -61,19 +70,13 @@ class OramaManager {
* @param {Array} entries - Array of entries
* */
documentsTransformer(indexId, entries) {
- const transformerFnMap = this.collectionSettings?.[indexId]?.documentsTransformer
+ const transformer = this.collectionSettings?.[indexId]?.transformer
- if (!transformerFnMap) {
+ if (!transformer) {
return entries
}
- return entries.map((entry) => {
- return Object.entries(entry)
- .map(([key, value]) => ({
- [key]: transformerFnMap[key]?.(value) ?? value
- }))
- .reduce((acc, curr) => ({ ...acc, ...curr }), {})
- })
+ return entries.map(transformer)
}
/*
@@ -148,19 +151,6 @@ class OramaManager {
})
if (entries.length > 0) {
- if (offset === 0) {
- const transformedEntries = this.documentsTransformer(collection.indexId, entries)
- const filteredEntry = getSelectedPropsFromObj({
- props: collection.searchableAttributes,
- obj: transformedEntries[0]
- })
-
- await this.oramaUpdateSchema({
- indexId: collection.indexId,
- schema: getSchemaFromEntryStructure(filteredEntry)
- })
- }
-
await this.oramaInsert({
indexId: collection.indexId,
entries
@@ -190,16 +180,16 @@ class OramaManager {
* */
async oramaInsert({ indexId, entries }) {
const index = this.oramaCloudManager.index(indexId)
- const formattedData = this.documentsTransformer(indexId, entries)
+ const transformedData = this.documentsTransformer(indexId, entries)
- if (!formattedData) {
+ if (!transformedData) {
this.strapi.log.error(`ERROR: documentsTransformer needs a return value`)
return false
}
- const result = await index.insert(formattedData)
+ const result = await index.insert(transformedData)
- this.strapi.log.info(`INSERT: documents with id ${formattedData.map(({ id }) => id)} into index ${indexId}`)
+ this.strapi.log.info(`INSERT: documents with id ${transformedData.map(({ id }) => id)} into index ${indexId}`)
return result
}
@@ -212,16 +202,16 @@ class OramaManager {
* */
async oramaUpdate({ indexId, entries }) {
const index = this.oramaCloudManager.index(indexId)
- const formattedData = this.documentsTransformer(entries) || entries
+ const transformedData = this.documentsTransformer(indexId, entries)
- if (!formattedData) {
+ if (!transformedData) {
this.strapi.log.error(`ERROR: documentsTransformer needs a return value`)
return false
}
- const result = await index.update(formattedData)
+ const result = await index.update(transformedData)
- this.strapi.log.info(`UPDATE: document with id ${formattedData.map(({ id }) => id)} into index ${indexId}`)
+ this.strapi.log.info(`UPDATE: document with id ${transformedData.map(({ id }) => id)} into index ${indexId}`)
return result
}
@@ -269,13 +259,27 @@ class OramaManager {
return
}
+ const customSchema = this.collectionSettings?.[collection.indexId]?.schema
+
+ const oramaSchema = customSchema ?? getSelectedPropsFromObj({
+ props: collection.searchableAttributes,
+ obj: collection.schema
+ })
+
await this.updatingStarted(collection)
await this.resetIndex(collection)
+ await this.oramaUpdateSchema({
+ indexId: collection.indexId,
+ schema: oramaSchema
+ })
+
const { documents_count } = await this.bulkInsert(collection)
- await this.oramaDeployIndex(collection)
+ if (documents_count > 0) {
+ await this.oramaDeployIndex(collection)
+ }
await this.updatingCompleted(collection, documents_count)
}
diff --git a/utils/schema.js b/utils/index.js
similarity index 95%
rename from utils/schema.js
rename to utils/index.js
index 6704ba4..349eee7 100644
--- a/utils/schema.js
+++ b/utils/index.js
@@ -1,3 +1,4 @@
+const { collection } = require("../server/content-types")
const getSelectedPropsFromObj = ({ props, obj }) => {
return props.reduce((acc, field) => {
if (field.includes('.')) {
diff --git a/utils/schema.test.js b/utils/index.test.js
similarity index 97%
rename from utils/schema.test.js
rename to utils/index.test.js
index 1d36d91..6b19eb7 100644
--- a/utils/schema.test.js
+++ b/utils/index.test.js
@@ -1,4 +1,4 @@
-const { getSelectedPropsFromObj, getSelectedAttributesFromSchema, getSchemaFromEntryStructure } = require('./schema')
+const { getSelectedPropsFromObj, getSelectedAttributesFromSchema, getSchemaFromEntryStructure } = require('./index')
describe('Schema Utils', () => {
describe('getSelectedPropsFromObj', () => {