Skip to content

Commit

Permalink
feat: select instance & index based on dynamic url param.
Browse files Browse the repository at this point in the history
  • Loading branch information
riccox committed May 12, 2023
1 parent 08e7030 commit 8908329
Show file tree
Hide file tree
Showing 15 changed files with 177 additions and 111 deletions.
43 changes: 26 additions & 17 deletions src/components/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
import { Link } from 'react-router-dom';
import { FC, useCallback, useMemo, useState } from 'react';
import { useClipboard } from '@mantine/hooks';
import { useAppStore } from '@/src/store';
import { MeiliSearch, Version } from 'meilisearch';
import { useQuery } from '@tanstack/react-query';
import { useInstanceStats } from '@/src/hooks/useInstanceStats';
Expand All @@ -24,53 +23,54 @@ import { getTimeText, showTaskSubmitNotification } from '@/src/utils/text';
import { validateKeysRouteAvailable } from '@/src/utils/conn';
import { useNavigatePreCheck } from '@/src/hooks/useRoutePreCheck';
import { toast } from '@/src/utils/toast';
import { useCurrentInstance } from '@/src/hooks/useCurrentInstance';

interface Props {
client: MeiliSearch;
}

export const Header: FC<Props> = ({ client }) => {
const currentInstance = useCurrentInstance();
const navigate = useNavigatePreCheck(([to], opt) => {
// check before keys page (no masterKey will cause error)
if (to === '/keys') {
if (typeof to === 'string' && /\/keys$/.test(to)) {
// check before keys page (no masterKey will cause error)
return validateKeysRouteAvailable(opt?.currentInstance?.apiKey);
}
return null;
});
const store = useAppStore();
const clipboard = useClipboard({ timeout: 500 });

const stats = useInstanceStats(client);
const [version, setVersion] = useState<Version>();
const [health, setHealth] = useState<boolean>(true);

useQuery(
['version', store.currentInstance?.host],
['version', currentInstance?.host],
async () => {
return await client.getVersion();
},
{ refetchOnMount: 'always', refetchInterval: 60000, onSuccess: (res) => setVersion(res) }
);
useQuery(
['health', store.currentInstance?.host],
['health', currentInstance?.host],
async () => {
return (await client.health()).status === 'available';
},
{ refetchOnMount: 'always', refetchInterval: 5000, onSuccess: (res) => setHealth(res) }
);

const onClickHost = useCallback(() => {
clipboard.copy(store.currentInstance?.host);
clipboard.copy(currentInstance?.host);
toast('Server Host Copied ✍', {
type: 'success',
});
}, [clipboard, store.currentInstance?.host]);
}, [clipboard, currentInstance?.host]);

const onClickDump = useCallback(() => {
openConfirmModal({
title: 'Create a new dump',
centered: true,
children: <p>Are you sure you want to start a new dump?</p>,
children: <p>Are you sure you want to start a new dump for instance {currentInstance.name}?</p>,
labels: { confirm: 'Start', cancel: 'Cancel' },
confirmProps: { color: 'orange' },
onConfirm: () => {
Expand All @@ -79,7 +79,7 @@ export const Header: FC<Props> = ({ client }) => {
});
},
});
}, [client]);
}, [client, currentInstance.name]);

return useMemo(
() => (
Expand All @@ -90,14 +90,15 @@ export const Header: FC<Props> = ({ client }) => {
>
<button
className="btn primary solid flex items-center gap-2"
onClick={() => navigate(['/'], { currentInstance: store.currentInstance })}
onClick={() => navigate(['/'], { currentInstance })}
>
<IconHomeBolt size={26} />
<p>Home</p>
</button>
<p className={`text-2xl font-bold`}>{_.truncate(store.currentInstance?.name, { length: 20 })}</p>
<p className={`text-2xl font-bold`}>{_.truncate(currentInstance?.name, { length: 20 })}</p>
<p className={`text-2xl font-bold text-bw-800/50`}>#{currentInstance.id}</p>
<span className={`!cursor-pointer hover:underline badge outline lg success`} onClick={onClickHost}>
Host: {_.truncate(store.currentInstance?.host, { length: 40 })}
Host: {_.truncate(currentInstance?.host, { length: 40 })}
</span>
<p className={`font-bold `}>Last Updated: {getTimeText(stats?.lastUpdate)}</p>
<span className={`badge outline lg primary`}>
Expand All @@ -123,21 +124,29 @@ export const Header: FC<Props> = ({ client }) => {
</ActionIcon>
<div className="menu bottom-left">
<p className="subtitle">Instance</p>
<Link to={'/index'} className="item text-sm flex items-center gap-2 " tabIndex={-1}>
<Link
to={`/ins/${currentInstance.id}/index`}
className="item text-sm flex items-center gap-2 "
tabIndex={-1}
>
<IconBooks size={14} />
<p>Index</p>
</Link>
<div
onClick={() => {
navigate(['/keys'], { currentInstance: store.currentInstance });
navigate([`/ins/${currentInstance.id}/keys`], { currentInstance });
}}
className="item text-sm flex items-center gap-2 hover:underline"
tabIndex={-1}
>
<IconKey size={14} />
<p>Keys</p>
</div>
<Link to={'/tasks'} className="item text-sm flex items-center gap-2" tabIndex={-1}>
<Link
to={`/ins/${currentInstance.id}/tasks`}
className="item text-sm flex items-center gap-2"
tabIndex={-1}
>
<IconListCheck size={14} />
<p>Tasks</p>
</Link>
Expand Down Expand Up @@ -185,13 +194,13 @@ export const Header: FC<Props> = ({ client }) => {
</div>
),
[
currentInstance,
health,
navigate,
onClickDump,
onClickHost,
stats?.databaseSize,
stats?.lastUpdate,
store.currentInstance,
version?.commitDate,
version?.commitSha,
version?.pkgVersion,
Expand Down
4 changes: 3 additions & 1 deletion src/components/Settings/dangerZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { hiddenRequestLoader, showRequestLoader } from '@/src/utils/loader';
import { showTaskSubmitNotification } from '@/src/utils/text';
import { openConfirmModal } from '@mantine/modals';
import { IndexSettingComponentProps } from '.';
import { useCurrentInstance } from '@/src/hooks/useCurrentInstance';

export const DangerZone: FC<
IndexSettingComponentProps & {
Expand All @@ -14,6 +15,7 @@ export const DangerZone: FC<
> = ({ refreshIndexes, host, client }) => {
const navigate = useNavigate();

const currentInstance = useCurrentInstance();
const delIndexMutation = useMutation(
['delIndex', host, client.uid],
async () => {
Expand All @@ -24,7 +26,7 @@ export const DangerZone: FC<
onSuccess: (t) => {
showTaskSubmitNotification(t);
refreshIndexes();
navigate('/index');
navigate(`/ins/${currentInstance.id}/index`);
},
onSettled: () => {
hiddenRequestLoader();
Expand Down
20 changes: 20 additions & 0 deletions src/hooks/useCurrentInstance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Instance, useAppStore } from '@/src/store';
import _ from 'lodash';
import { toast } from '../utils/toast';
import { useParams } from 'react-router-dom';

export const useCurrentInstance = () => {
let { insId } = useParams();
const currentInstance = useAppStore((state) => state.instances.find((i) => i.id === parseInt(insId || '0')));

if (currentInstance && _.isEmpty(currentInstance)) {
toast('Instance not found 🤥', {
type: 'warning',
});
console.debug('useCurrentInstance', 'Instance lost');
// do not use useNavigate, because maybe in first render
window.location.assign(import.meta.env.BASE_URL);
}

return currentInstance as Instance;
};
5 changes: 3 additions & 2 deletions src/hooks/useIndexes.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Index, MeiliSearch } from 'meilisearch';
import { useState } from 'react';
import { useAppStore } from '@/src/store';
import { useQuery, UseQueryResult } from '@tanstack/react-query';
import { IndexesQuery } from 'meilisearch/src/types';
import { useCurrentInstance } from './useCurrentInstance';

export const useIndexes = (client: MeiliSearch, params?: IndexesQuery): [Index[], UseQueryResult] => {
const host = useAppStore((state) => state.currentInstance?.host);
const currentInstance = useCurrentInstance();
const host = currentInstance?.host;

const [indexes, setIndexes] = useState<Index[]>([]);

Expand Down
6 changes: 3 additions & 3 deletions src/hooks/useInstanceStats.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { MeiliSearch, Stats } from 'meilisearch';
import { useState } from 'react';
import { useAppStore } from '@/src/store';
import { useQuery } from '@tanstack/react-query';
import { useCurrentInstance } from './useCurrentInstance';

export const useInstanceStats = (client: MeiliSearch) => {
const host = useAppStore((state) => state.currentInstance?.host);

const currentInstance = useCurrentInstance();
const host = currentInstance?.host;
const [stats, setStats] = useState<Stats>();

useQuery(
Expand Down
8 changes: 4 additions & 4 deletions src/hooks/useMeiliClient.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { MeiliSearch } from 'meilisearch';
import { useCallback, useEffect, useState } from 'react';
import { defaultInstance, useAppStore } from '@/src/store';
import _ from 'lodash';
import { toast } from '../utils/toast';
import { useCurrentInstance } from './useCurrentInstance';

export const useMeiliClient = () => {
const currentInstance = useAppStore((state) => state.currentInstance ?? defaultInstance);
const currentInstance = useCurrentInstance();

const [client, setClient] = useState<MeiliSearch>(
new MeiliSearch({
Expand All @@ -21,7 +21,7 @@ export const useMeiliClient = () => {
});
console.debug('useMeilisearchClient', 'connection config lost');
// do not use useNavigate, because maybe in first render
window.location.assign('/');
window.location.assign(import.meta.env.BASE_URL);
return;
}
const conn = new MeiliSearch({ ...currentInstance });
Expand All @@ -35,7 +35,7 @@ export const useMeiliClient = () => {
type: 'warning',
});
// do not use useNavigate, because maybe in first render
window.location.assign('/');
window.location.assign(import.meta.env.BASE_URL);
}
}, [currentInstance]);

Expand Down
1 change: 1 addition & 0 deletions src/hooks/useRoutePreCheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useCallback } from 'react';

export type NavigateFuncParams = [To, NavigateOptions?] | [number];
export type NavigateFunc = (params: [To, NavigateOptions?] | [number], opt?: any) => void;

export const useNavigatePreCheck = (
pre: (params: NavigateFuncParams, opt?: any) => null | WarningPageData
): NavigateFunc => {
Expand Down
Loading

0 comments on commit 8908329

Please sign in to comment.