From 6a6fc7e13ab2e4ccf51f045f6088f092a9d4056f Mon Sep 17 00:00:00 2001 From: Shams mosowi Date: Mon, 12 Apr 2021 23:59:36 +1000 Subject: [PATCH] algolia connectTable personal search keys --- .../functions/src/algoliaSearchKey.ts | 2 +- .../functions/src/functionConfig.ts | 3 + cloud_functions/functions/src/index.ts | 47 +++++++------- www/package.json | 2 +- .../ConnectTable/ConnectTableSelect.tsx | 62 ++++++++++++++----- www/src/firebase/callables.ts | 4 ++ www/yarn.lock | 8 +-- 7 files changed, 85 insertions(+), 43 deletions(-) diff --git a/cloud_functions/functions/src/algoliaSearchKey.ts b/cloud_functions/functions/src/algoliaSearchKey.ts index f3e5f7c8..a518774c 100644 --- a/cloud_functions/functions/src/algoliaSearchKey.ts +++ b/cloud_functions/functions/src/algoliaSearchKey.ts @@ -19,7 +19,7 @@ export const getAlgoliaSearchKey = functions.https.onCall(async ( } const userRoles = context.auth.token.roles if (userRoles.some(role=> allIndicesRoles.includes(role)||rolesIndicesAccess[role].includes(requestedIndex))){ - const validUntil = Math.floor(Date.now() / 1000) + 36000; + const validUntil = Math.floor(Date.now() / 1000) + 3600; const key = algoliaClient.generateSecuredApiKey( env.algolia.search, { diff --git a/cloud_functions/functions/src/functionConfig.ts b/cloud_functions/functions/src/functionConfig.ts index e69de29b..f412540a 100644 --- a/cloud_functions/functions/src/functionConfig.ts +++ b/cloud_functions/functions/src/functionConfig.ts @@ -0,0 +1,3 @@ +export const collectionPath = '' +export const functionName = '' +export default {} \ No newline at end of file diff --git a/cloud_functions/functions/src/index.ts b/cloud_functions/functions/src/index.ts index 72528f91..f5ad6d59 100644 --- a/cloud_functions/functions/src/index.ts +++ b/cloud_functions/functions/src/index.ts @@ -1,32 +1,33 @@ -export { triggerCloudBuild, cloudBuildUpdates } from "./buildTriggers"; // a callable used for triggering cloudbuild to build and deploy configurable cloud functions -export { - scheduledFirestoreBackup, // callableFirestoreBackup -} from "./backup"; -import * as callableFns from "./callable"; +// export { triggerCloudBuild, cloudBuildUpdates } from "./buildTriggers"; // a callable used for triggering cloudbuild to build and deploy configurable cloud functions +// export { +// scheduledFirestoreBackup, // callableFirestoreBackup +// } from "./backup"; +// import * as callableFns from "./callable"; -export const callable = callableFns; +// export const callable = callableFns; -// all the cloud functions bellow are deployed using the triggerCloudBuild callable function -// these functions are designed to be built and deployed based on the configuration passed through the callable +// // all the cloud functions bellow are deployed using the triggerCloudBuild callable function +// // these functions are designed to be built and deployed based on the configuration passed through the callable -export { FT_aggregates } from "./aggregates"; -export { FT_subTableStats } from "./subTableStats"; +// export { FT_aggregates } from "./aggregates"; +// export { FT_subTableStats } from "./subTableStats"; -export { actionScript } from "./actionScript"; +// export { actionScript } from "./actionScript"; -export { webhook } from "./webhooks"; +// export { webhook } from "./webhooks"; -export { FT_snapshotSync } from "./snapshotSync"; +// export { FT_snapshotSync } from "./snapshotSync"; -export { FT_compressedThumbnail } from "./compressedThumbnail"; +// export { FT_compressedThumbnail } from "./compressedThumbnail"; -export { slackBotMessageOnCreate } from "./slackOnTrigger/trigger"; +export {getAlgoliaSearchKey} from './algoliaSearchKey' -//deprecated, moved to FT_functions folder and used within sparks table functions -export { FT_derivatives } from "./derivatives"; -export { FT_algolia } from "./algolia"; -export { FT_email } from "./emailOnTrigger"; -export { FT_slack } from "./slackOnTrigger"; -export { FT_sync } from "./collectionSync"; -export { FT_spark } from "./sparks"; -export { FT_history } from "./history"; +//deprecated, updated implementation moved to FT_build folder and used within sparks table functions +// export { FT_derivatives } from "./derivatives"; +// export { FT_algolia } from "./algolia"; +// export { FT_email } from "./emailOnTrigger"; +// export { FT_slack } from "./slackOnTrigger"; +// export { FT_sync } from "./collectionSync"; +// export { FT_spark } from "./sparks"; +// export { FT_history } from "./history"; +// export { slackBotMessageOnCreate } from "./slackOnTrigger/trigger"; \ No newline at end of file diff --git a/www/package.json b/www/package.json index 950d98b8..646d9772 100644 --- a/www/package.json +++ b/www/package.json @@ -52,7 +52,7 @@ "typescript": "^3.7.2", "use-algolia": "^1.4.1", "use-debounce": "^3.3.0", - "use-persisted-state": "^0.3.0", + "use-persisted-state": "^0.3.3", "yarn": "^1.22.10", "yup": "^0.32.9" }, diff --git a/www/src/components/fields/ConnectTable/ConnectTableSelect.tsx b/www/src/components/fields/ConnectTable/ConnectTableSelect.tsx index 32a6e7b1..fbb3c7a3 100644 --- a/www/src/components/fields/ConnectTable/ConnectTableSelect.tsx +++ b/www/src/components/fields/ConnectTable/ConnectTableSelect.tsx @@ -6,6 +6,9 @@ import _get from "lodash/get"; import MultiSelect, { MultiSelectProps } from "@antlerengineering/multiselect"; import Loading from "components/Loading"; +import { getAlgoliaSearchKey } from '../../../firebase/callables' +import createPersistedState from 'use-persisted-state'; +const useAlgoliaSearchKeys = createPersistedState('algolia-search'); export type ConnectTableValue = { docPath: string; @@ -33,7 +36,7 @@ export interface IConnectTableSelectProps { disabled?: boolean; /** Optional style overrides for root MUI `TextField` component */ className?: string; - row:any; + row: any; /** Override any props of the root MUI `TextField` component */ TextFieldProps?: MultiSelectProps["TextFieldProps"]; onClose?: MultiSelectProps["onClose"]; @@ -49,7 +52,6 @@ export default function ConnectTableSelect({ config, disabled, className, - TextFieldProps = {}, onClose, loadBeforeOpen, @@ -59,18 +61,48 @@ export default function ConnectTableSelect({ const [localValue, setLocalValue] = useState( Array.isArray(value) ? value : [] ); - const filters = config.filters? config.filters.replace( + const filters = config.filters ? config.filters.replace( /\{\{(.*?)\}\}/g, replacer(row) - ):'' + ) : '' const algoliaIndex = config.index; + + const [algoliaSearchKeys, setAlgoliaSearchKeys] = useAlgoliaSearchKeys({}); const [algoliaState, requestDispatch, , setAlgoliaConfig] = useAlgolia( process.env.REACT_APP_ALGOLIA_APP_ID!, - process.env.REACT_APP_ALGOLIA_SEARCH_API_KEY!, + process.env.REACT_APP_ALGOLIA_SEARCH_API_KEY??'', // Don’t choose the index until the user opens the dropdown if !loadBeforeOpen loadBeforeOpen ? algoliaIndex : "", - { filters} + { filters } ); + + const setAlgoliaSearchKey = async (algoliaIndex: string) => { + const requestedAt = Date.now() / 1000 + if (algoliaSearchKeys&&(algoliaSearchKeys?.[algoliaIndex] as any)?.key + && requestedAt < ((algoliaSearchKeys?.[algoliaIndex] as any).requestedAt) + 3600 + ) { + console.log('use existing key') + setAlgoliaConfig({ indexName: algoliaIndex, searchKey: (algoliaSearchKeys?.[algoliaIndex] as any).key }) + } else { + console.log('get new key') + const resp = await getAlgoliaSearchKey(algoliaIndex) + const key = resp.data.data?.key + if (key) { + const newKey = { + key, + requestedAt + } + setAlgoliaSearchKeys(algoliaSearchKeys ? { ...algoliaSearchKeys, [algoliaIndex]: newKey } : { [algoliaIndex]: newKey }) + setAlgoliaConfig({ indexName: algoliaIndex, searchKey: key }) + } + } + } + + useEffect(() => { + if (!process.env.REACT_APP_ALGOLIA_SEARCH_API_KEY)setAlgoliaSearchKey(algoliaIndex) + }, [algoliaIndex]) + + const options = algoliaState.hits.map((hit) => ({ label: config.primaryKeys?.map((key: string) => hit[key]).join(" "), value: hit.objectID, @@ -86,8 +118,8 @@ export default function ConnectTableSelect({ const newValue = Array.isArray(_newValue) ? _newValue : _newValue !== null - ? [_newValue] - : []; + ? [_newValue] + : []; // Calculate new value const newLocalValue = newValue.map((objectID) => { @@ -134,9 +166,11 @@ export default function ConnectTableSelect({ value={config.multiple === false ? sanitisedValue[0] : sanitisedValue} onChange={handleChange} onOpen={() => { - setAlgoliaConfig({ indexName: algoliaIndex }) - requestDispatch({ filters}); - }} + setAlgoliaConfig({ + indexName: algoliaIndex + }) + requestDispatch({ filters }); + }} onClose={handleSave} options={options} TextFieldProps={{ @@ -156,10 +190,10 @@ export default function ConnectTableSelect({ }, filterOptions: () => options, }} - countText={`${localValue.length} of ${ - algoliaState.response?.nbHits ?? "?" - }`} + countText={`${localValue.length} of ${algoliaState.response?.nbHits ?? "?" + }`} disabled={disabled} + /> ); } diff --git a/www/src/firebase/callables.ts b/www/src/firebase/callables.ts index a7c36f0d..9ac7ff71 100644 --- a/www/src/firebase/callables.ts +++ b/www/src/firebase/callables.ts @@ -2,6 +2,7 @@ import { functions } from "./index"; export enum CLOUD_FUNCTIONS { ImpersonatorAuth = "callable-ImpersonatorAuth", + getAlgoliaSearchKey = 'getAlgoliaSearchKey' } export const cloudFunction = ( @@ -27,3 +28,6 @@ export const cloudFunction = ( export const ImpersonatorAuth = (email: string) => functions.httpsCallable(CLOUD_FUNCTIONS.ImpersonatorAuth)({ email }); + + export const getAlgoliaSearchKey = (index: string) => + functions.httpsCallable(CLOUD_FUNCTIONS.getAlgoliaSearchKey)({ index }); \ No newline at end of file diff --git a/www/yarn.lock b/www/yarn.lock index 3cb596d6..41491c57 100644 --- a/www/yarn.lock +++ b/www/yarn.lock @@ -14868,10 +14868,10 @@ use-memo-one@^1.1.1: resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.1.tgz#39e6f08fe27e422a7d7b234b5f9056af313bd22c" integrity sha512-oFfsyun+bP7RX8X2AskHNTxu+R3QdE/RC5IefMbqptmACAA/gfol1KDD5KRzPsGMa62sWxGZw+Ui43u6x4ddoQ== -use-persisted-state@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/use-persisted-state/-/use-persisted-state-0.3.0.tgz#f8e3d2fd8eee67e0c86fd596c3ea3e8121c07402" - integrity sha512-UlWEq0JYg7NbvcRBZ1g6Bwe4SEbYfr1wr/D5mrmfCzSxXSwsPRYygGLlsxHcW58Rf7gGwRPBT23sNVvyVn4WYg== +use-persisted-state@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/use-persisted-state/-/use-persisted-state-0.3.3.tgz#5e0f2236967cec7c34de33abc07ae6818e7c7451" + integrity sha512-pCNlvYC8+XjRxwnIut4teGC9f2p9aD88R8OGseQGZa2dvqG/h1vEGk1vRE1IZG0Vf161UDpn+NlW4+UGubQflQ== dependencies: "@use-it/event-listener" "^0.1.2"