Skip to content

Commit

Permalink
Fixes dot syntax path suggestion generation (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
pushchris authored Apr 17, 2024
1 parent 572d8f7 commit a68b9c5
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 6 deletions.
2 changes: 1 addition & 1 deletion apps/platform/src/rules/RuleHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { visit } from '../utilities'
export const queryValue = <T>(value: Record<string, unknown>, rule: RuleTree, cast: (item: any) => T): T[] => {
let path = rule.path
if (!value || !path) return []
if (!path.startsWith('$.')) path = '$.' + path
if (!path.startsWith('$.') && !path.startsWith('$[')) path = '$.' + path
return jsonpath.query(value, path).map(v => cast(v))
}

Expand Down
14 changes: 10 additions & 4 deletions apps/platform/src/schema/UserSchemaService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function addLeafPaths(set: Set<string>, value: any, path = '$') {
}
} else if (value && typeof value === 'object') {
for (const [key, item] of Object.entries(value)) {
addLeafPaths(set, item, path + '.' + key)
addLeafPaths(set, item, joinPath(path, key))
}
} else {
if (path !== '$') {
Expand All @@ -48,6 +48,12 @@ export function addLeafPaths(set: Set<string>, value: any, path = '$') {
}
}

const joinPath = (path: string, key: string) => {
const isValid = key.match(/^[\p{L}][\p{L}\p{N}_]*$/u)
if (isValid) return `${path}.${key}`
return `${path}['${key}']`
}

interface SyncProjectRulePathsParams {
project_id: number
updatedAfter?: Date
Expand All @@ -57,7 +63,6 @@ export async function syncUserDataPaths({
project_id,
updatedAfter,
}: SyncProjectRulePathsParams) {

await App.main.db.transaction(async trx => {

const userPaths = new Set<string>()
Expand All @@ -75,7 +80,7 @@ export async function syncUserDataPaths({
}
})
for (const path of reservedPaths.user) {
userPaths.add(`$.${path}`)
userPaths.add(joinPath('$', path))
}

const eventQuery = UserEvent.query(trx)
Expand All @@ -93,7 +98,7 @@ export async function syncUserDataPaths({
}
addLeafPaths(set, data)
for (const path of reservedPaths.event) {
set.add(`$.${path}`)
set.add(joinPath('$', path))
}
}
})
Expand Down Expand Up @@ -135,6 +140,7 @@ export async function syncUserDataPaths({
}, trx)
}
}

for (const [name, paths] of eventPaths.entries()) {
for (const path of paths) {
if (!existing.find(e => e.type === 'event' && e.path === path && e.name === name)) {
Expand Down
6 changes: 6 additions & 0 deletions apps/ui/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"add_translation": "Add Translation",
"admin": "Admin",
"admins": "Admins",
"advanced": "Advanced",
"api_keys": "API Keys",
"api_triggered": "API Triggered",
"archive": "Archive",
Expand Down Expand Up @@ -164,6 +165,7 @@
"list_generation_dialog_description": "List generation will happen in the background. Please reload the page to see the latest status.",
"list_name": "List Name",
"list_save": "Save List",
"list": "List",
"lists": "Lists",
"load_user": "Load User",
"loading": "Loading",
Expand Down Expand Up @@ -212,6 +214,10 @@
"rate_limit": "Rate Limit",
"raw_json": "Raw JSON",
"ready": "Ready",
"rebuild": "Rebuild",
"rebuild_path_suggestions": "Rebuild Path Suggestions",
"rebuild_path_suggestions_desc": "Would you like to recreate all of the event and user data autocomplete paths used for creating rules?",
"rebuild_path_suggestions_success": "Path suggestions are rebuilding. This might take a few minutes depending on how many users and events you have.",
"remove": "Remove",
"remove_locale_warning": "Are you sure you want to delete this locale? The template cannot be recovered.",
"reply_to": "Reply To",
Expand Down
8 changes: 7 additions & 1 deletion apps/ui/public/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"add_translation": "Añadir traducción",
"admin": "Admin",
"admins": "Administradores",
"advanced": "Avanzado",
"api_keys": "Claves API",
"api_triggered": "Activado por API",
"archive": "Archivar",
Expand All @@ -24,6 +25,7 @@
"blast": "Volumen (Lista)",
"body": "Cuerpo",
"bounced": "Rebotado",
"campaign": "Campaña",
"campaign_alert_pending": "¡Esta campaña aún no ha sido enviada! Una vez que la campaña esté activa o programada, esta pestaña mostrará el progreso y los resultados.",
"campaign_alert_scheduled": "Esta campaña está pendiente de entrega. Comenzará a desplegarse a",
"campaign_delivery_trigger_description": "",
Expand All @@ -35,7 +37,6 @@
"campaign_list_generating": "Esta lista aún se está generando. Enviar antes de que se haya completado podría provocar que esta campaña no se envíe a todos los usuarios que entrarán en la lista. ¿Está seguro de que desea continuar?",
"campaign_name": "Nombre de la campaña",
"campaigns": "Campañas",
"campaign": "Campaña",
"cancel": "Cancelar",
"cc": "CC",
"change_schedule": "Cambiar horario",
Expand Down Expand Up @@ -161,6 +162,7 @@
"link_empty": "Enviar usuarios a",
"link_wrapping": "Ajuste de enlaces",
"link_wrapping_subtitle": "Habilite el ajuste de enlaces para todos los enlaces de los mensajes.",
"list": "Lista",
"list_generation_dialog_description": "La lista se generará en segundo plano. Vuelva a cargar la página para ver el estado más reciente.",
"list_name": "Nombre de la lista",
"list_save": "Guardar Lista",
Expand Down Expand Up @@ -212,6 +214,10 @@
"rate_limit": "Límite de Velocidad",
"raw_json": "JSON Sin Procesar",
"ready": "Listo",
"rebuild": "Reconstruir",
"rebuild_path_suggestions": "Reconstruir las Sugerencias de Ruta",
"rebuild_path_suggestions_desc": "¿Le gustaría recrear todas las rutas de autocompletado de datos de eventos y usuarios utilizadas para crear reglas?",
"rebuild_path_suggestions_success": "Las sugerencias de ruta se están reconstruyendo. Esto puede tardar unos minutos dependiendo de cuántos usuarios y eventos tengas.",
"remove": "Eliminar",
"remove_locale_warning": "¿Está seguro de que desea eliminar esta configuración regional? La plantilla no se puede recuperar.",
"reply_to": "Responder a",
Expand Down
3 changes: 3 additions & 0 deletions apps/ui/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ const api = {
pathSuggestions: async (projectId: number | string) => await client
.get<RuleSuggestions>(`${projectUrl(projectId)}/data/paths`)
.then(r => r.data),
rebuildPathSuggestions: async (projectId: number | string) => await client
.post(`${projectUrl(projectId)}/data/paths/sync`)
.then(r => r.data),
},

apiKeys: createProjectEntityPath<ProjectApiKey, ProjectApiKeyParams, Omit<ProjectApiKeyParams, 'scope'>>('keys'),
Expand Down
15 changes: 15 additions & 0 deletions apps/ui/src/views/settings/ProjectSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ import Heading from '../../ui/Heading'
import { toast } from 'react-hot-toast/headless'
import ProjectForm from '../project/ProjectForm'
import { useTranslation } from 'react-i18next'
import { Button } from '../../ui'
import api from '../../api'

export default function ProjectSettings() {
const { t } = useTranslation()
const [project, setProject] = useContext(ProjectContext)

const handleRebuildAttributeSchema = async () => {
await api.projects.rebuildPathSuggestions(project.id)
toast.success(t('rebuild_path_suggestions_success'))
}

return (
<>
<Heading size="h3" title={t('general')} />
Expand All @@ -17,6 +24,14 @@ export default function ProjectSettings() {
setProject(project)
toast.success(t('project_settings_saved'))
}} />

<br />
<Heading size="h3" title={t('advanced')} />
<label>
<span>{t('rebuild_path_suggestions')}</span>
<span className="label-subtitle">{t('rebuild_path_suggestions_desc')}</span>
<Button variant="secondary" style={{ marginTop: '10px' }} onClick={async () => await handleRebuildAttributeSchema()}>{t('rebuild')}</Button>
</label>
</>
)
}

0 comments on commit a68b9c5

Please sign in to comment.