Skip to content

Commit

Permalink
Merge pull request #42 from bfritscher/enable_nested_fields
Browse files Browse the repository at this point in the history
Enable nested fields
  • Loading branch information
bfritscher authored Jan 22, 2024
2 parents a31f01c + 8e13f97 commit bf22050
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/components/NavMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@
<q-item-section> API Keys </q-item-section>
</q-item>

<q-item clickable v-ripple to="/analyticsrules" exact>
<q-item-section avatar>
<q-icon name="sym_s_query_stats" />
</q-item-section>

<q-item-section> Analytics Rules </q-item-section>
</q-item>


<q-separator spaced />

<q-item>
Expand Down
3 changes: 3 additions & 0 deletions src/components/collection/CollectionCreate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ export default defineComponent({
if (field.type !== 'float[]' || !field.num_dim) {
delete field.num_dim;
}
if (field.type.startsWith('object')) {
schema.enable_nested_fields = true;
}
}
void this.$store.dispatch('node/createCollection', schema);
},
Expand Down
2 changes: 2 additions & 0 deletions src/components/collection/CollectionUi.vue
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ export default defineComponent({
'bool[]',
'geopoint',
'geopoint[]',
'object',
'object[]',
'string*',
'auto',
],
Expand Down
235 changes: 235 additions & 0 deletions src/pages/AnalyticsRules.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
<template>
<q-page padding>
<q-expansion-item
expand-separator
icon="sym_s_add_circle"
expand-icon="sym_s_unfold_more"
expanded-icon="sym_s_unfold_less"
:label="`${isUpdate ? 'Update' : 'Add'} Analytics Rule`"
header-class="bg-primary text-white"
v-model="expanded"
>
<q-card class="bg-surface column">
<q-card-section class="row q-col-gutter-md">
<q-input
class="col-12 col-sm-6"
v-model="rule.name"
label="Rule Name"
filled
:rules="[(val) => !!val || 'Field is required']"
/>

<q-input
class="col-12 col-sm-6"
v-model="rule.type"
label="Rule Type"
filled
:rules="[(val) => !!val || 'Field is required']"
/>
</q-card-section>
<q-card-section class="row q-col-gutter-md">
<q-select
class="col-12 col-sm-6"
v-model="rule.params.source.collections"
label="Source Collection(s)"
filled
:options="collectionNames"
multiple
hint="Track searches sent to these collections"
></q-select>

<q-select
class="col-12 col-sm-6"
v-model="rule.params.destination.collection"
label="Destination Collection"
filled
:options="collectionNames"
></q-select>
</q-card-section>
<q-card-section class="row q-col-gutter-md">
<q-input
class="col-12 col-sm-6"
v-model="rule.params.limit"
label="Limit"
filled
type="number"
min="0"
/>
</q-card-section>

<q-card-actions align="right" class="bg-primary">
<q-btn
size="md"
padding="sm lg"
unelevated
color="primary"
@click="createRule()"
>{{ isUpdate ? 'Update' : 'Add' }} Rule</q-btn
>
</q-card-actions>
</q-card>
</q-expansion-item>

<q-table
class="q-mt-md"
title="Analytics Rules"
flat
bordered
:filter="filter"
:rows="$store.state.node.data.analyticsRules"
:columns="columns"
row-key="name"
:pagination="{ rowsPerPage: 50, sortBy: 'name' }"
>
<template v-slot:top-left>
<div class="text-h6">
<q-icon size="md" name="sym_s_query_stats" /> Analytics Rules
</div>
</template>
<template v-slot:top-right>
<q-input
borderless
dense
debounce="300"
v-model="filter"
placeholder="Search"
>
<template v-slot:append>
<q-icon name="sym_s_search" />
</template>
</q-input>
</template>
<template v-slot:body-cell-actions="props">
<q-td class="text-right">
<q-btn
flat
color="primary"
@click="editRule(props.row)"
icon="sym_s_edit"
title="Edit"
></q-btn>
<q-btn
flat
color="negative"
@click="deleteRule(props.row.name)"
icon="sym_s_delete_forever"
title="Delete"
></q-btn>
</q-td>
</template>
</q-table>
</q-page>
</template>

<script lang="ts">
import { AnalyticsRuleSchema } from 'typesense/lib/Typesense/AnalyticsRule';
import { defineComponent } from 'vue';
function initialData(): AnalyticsRuleSchema {
return {
name: '',
type: 'popular_queries',
params: {
source: {
collections: [],
},
destination: {
collection: '',
},
limit: 100,
},
};
}
export default defineComponent({
name: 'AnalyticsRules',
data() {
return {
rule: initialData(),
expanded: this.$store.state.node.data.aliases.length === 0,
filter: '',
columns: [
{
label: 'Rule Name',
name: 'name',
field: 'name',
align: 'left',
sortable: true,
},
{
label: 'Rule Type',
name: 'type',
field: 'type',
align: 'left',
sortable: true,
},
{
label: 'Source Collection(s)',
name: 'source',
field: (r: AnalyticsRuleSchema) =>
r.params.source.collections.join(', '),
align: 'left',
sortable: true,
},
{
label: 'Destination Collection',
name: 'destination',
field: (r: AnalyticsRuleSchema) => r.params.destination.collection,
align: 'left',
sortable: true,
},
{
label: 'Limit',
name: 'limit',
field: (r: AnalyticsRuleSchema) => r.params.limit,
align: 'right',
sortable: true,
},
{
label: 'Actions',
name: 'actions',
align: 'right',
},
],
};
},
mounted() {
void this.$store.dispatch('node/getAnalyticsRules');
},
computed: {
collectionNames() {
return this.$store.state.node.data.collections.map(
(collection) => collection.name
);
},
isUpdate(): boolean {
return this.$store.state.node.data.analyticsRules
.map((a) => a.name)
.includes(this.rule.name);
},
},
methods: {
async createRule() {
await this.$store.dispatch('node/createAnalyticsRule', this.rule);
this.expanded = false;
this.rule = initialData();
},
editRule(rule: AnalyticsRuleSchema) {
this.rule = JSON.parse(JSON.stringify(rule));
this.expanded = true;
},
deleteRule(name: string) {
this.$q
.dialog({
title: 'Confirm',
message: `Delete analytics rule ${name}?`,
cancel: true,
persistent: true,
})
.onOk(() => {
void this.$store.dispatch('node/deleteAnalyticsRule', name);
});
},
},
});
</script>
1 change: 1 addition & 0 deletions src/router/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const routes: RouteRecordRaw[] = [
{ path: '', component: () => import('pages/ServerStatus.vue') },
{ path: 'aliases', component: () => import('pages/Aliases.vue') },
{ path: 'apikeys', component: () => import('pages/ApiKeys.vue') },
{ path: 'analyticsrules', component: () => import('pages/AnalyticsRules.vue') },
{ path: 'collections', component: () => import('pages/Collections.vue') },
{ path: 'collection/:name/document', component: () => import('pages/Document.vue') },
{ path: 'collection/:name/search', component: () => import('pages/Search.vue') },
Expand Down
14 changes: 14 additions & 0 deletions src/shared/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { SearchParams } from 'typesense/lib/Typesense/Documents';
import { KeyCreateSchema } from 'typesense/lib/Typesense/Key';
import { OverrideSchema } from 'typesense/lib/Typesense/Override';
import { SynonymSchema } from 'typesense/lib/Typesense/Synonym';
import AnalyticsRule, { AnalyticsRuleCreateSchema } from 'typesense/lib/Typesense/AnalyticsRule';
import AnalyticsRules from 'typesense/lib/Typesense/AnalyticsRules';

export class Api {
public axiosClient?: AxiosInstance;
Expand Down Expand Up @@ -78,6 +80,18 @@ export class Api {
}
}

public getAnalyticsRules() {
return this.typesenseClient?.analytics.rules().retrieve();
}

public upsertAnalyticsRule(name: string, rule: AnalyticsRuleCreateSchema) {
return (this.typesenseClient?.analytics.rules() as AnalyticsRules).upsert(name, rule);
}

public deleteAnalyticsRule(name: string) {
return (this.typesenseClient?.analytics.rules(name) as AnalyticsRule).delete();
}

public getSynonyms(collectionName: string) {
return this.typesenseClient?.collections(collectionName)
.synonyms()
Expand Down
27 changes: 27 additions & 0 deletions src/store/node/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { OverrideCreateSchema } from 'typesense/lib/Typesense/Overrides';
import { SearchParams } from 'typesense/lib/Typesense/Documents';
import { Api } from 'src/shared/api';
import { DebugResponseSchema } from 'typesense/lib/Typesense/Debug';
import { AnalyticsRuleSchema } from 'typesense/lib/Typesense/AnalyticsRule';

const actions: ActionTree<NodeStateInterface, StateInterface> = {
connectionCheck(context) {
Expand Down Expand Up @@ -120,6 +121,32 @@ const actions: ActionTree<NodeStateInterface, StateInterface> = {
void context.dispatch('connectionCheck');
});
},
async getAnalyticsRules(context) {
await context.getters.api
.getAnalyticsRules()
.then((response: { rules: AnalyticsRuleSchema[] }) => {
context.commit('setData', {
analyticsRules: response.rules,
});
})
.catch((err: Error) => {
console.log(err);
void context.dispatch('connectionCheck');
});
},
async deleteAnalyticsRule(context, name: string) {
await context.getters.api.deleteAnalyticsRule(name);
void context.dispatch('getAnalyticsRules');
},
async createAnalyticsRule(context, rule: AnalyticsRuleSchema) {
try {
context.commit('setError', null);
await context.getters.api.upsertAnalyticsRule(rule.name, rule);
void context.dispatch('getAnalyticsRules');
} catch (error) {
context.commit('setError', (error as Error).message);
}
},
getSynonyms(context, collectionName: string) {
context.getters.api
.getSynonyms(collectionName)
Expand Down
3 changes: 3 additions & 0 deletions src/store/node/state.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { LocalStorage } from 'quasar';
import { CollectionAliasSchema } from 'typesense/lib/Typesense/Aliases';
import { AnalyticsRuleSchema } from 'typesense/lib/Typesense/AnalyticsRule';
import { CollectionSchema } from 'typesense/lib/Typesense/Collection';
import { NodeConfiguration } from 'typesense/lib/Typesense/Configuration';
import { KeySchema } from 'typesense/lib/Typesense/Key';
Expand All @@ -17,6 +18,7 @@ export interface NodeDataInterface {
collections: CollectionSchema[];
aliases: CollectionAliasSchema[];
apiKeys: KeySchema[];
analyticsRules: AnalyticsRuleSchema[];
overrides: OverrideSchema[];
synonyms: SynonymSchema[];
}
Expand Down Expand Up @@ -67,6 +69,7 @@ function state(): NodeStateInterface {
collections: [],
aliases: [],
apiKeys: [],
analyticsRules: [],
overrides: [],
synonyms: [],
},
Expand Down

0 comments on commit bf22050

Please sign in to comment.