fix all
This commit is contained in:
parent
77f5e9f965
commit
9d6581ad57
@ -74,8 +74,10 @@ export class ProxyController {
|
||||
return (Object.keys(queryTTL) as Array<keyof typeof queryTTL>).reduce(
|
||||
(acc, queryName) => {
|
||||
const queries = list.filter((x) => x.split(' ').at(0) === queryName);
|
||||
const ttl = queryTTL[queryName];
|
||||
acc[queryName] = { queries, ttl };
|
||||
if (queries.length) {
|
||||
const ttl = queryTTL[queryName];
|
||||
acc[queryName] = { queries, ttl };
|
||||
}
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
.collapse {
|
||||
flex-grow: 1;
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
import style from './Admin.module.css';
|
||||
import { getQueryValue } from '@/api/cache/query';
|
||||
import type { ResponseQueries } from '@/api/cache/types';
|
||||
import type { CollapseProps } from 'antd';
|
||||
import { Button, Collapse } from 'antd';
|
||||
import { useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
type IProps = {
|
||||
readonly data: string;
|
||||
readonly index: number;
|
||||
readonly name: string;
|
||||
readonly onClick: (name: string, key: string) => void;
|
||||
};
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
`;
|
||||
|
||||
export function AdminRow(props: IProps) {
|
||||
const { data, index, name, onClick } = props;
|
||||
const defaultItems: CollapseProps['items'] = [
|
||||
{
|
||||
children: <p>{data}</p>,
|
||||
key: index.toString(),
|
||||
label: data,
|
||||
},
|
||||
];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [queryText, setQueryText] = useState<ResponseQueries>({});
|
||||
const [items, setItems] = useState<CollapseProps['items']>(defaultItems);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [key, setKey] = useState(data);
|
||||
|
||||
const handleClick = () => {
|
||||
onClick(name, key);
|
||||
};
|
||||
|
||||
const handleChange = async () => {
|
||||
const query = await getQueryValue(key);
|
||||
setQueryText(query);
|
||||
setItems(
|
||||
[...items].map((obj) => ({
|
||||
...obj,
|
||||
children: <p>{JSON.stringify(query)}</p>,
|
||||
}))
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Collapse className={style.collapse} onChange={handleChange} items={items} />
|
||||
<Button onClick={handleClick}>Удалить</Button>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
import { AdminRow } from './AdminRow';
|
||||
import type { CollapseProps } from 'antd';
|
||||
import { Collapse } from 'ui/elements';
|
||||
|
||||
export function AdminRows({
|
||||
index,
|
||||
name,
|
||||
onClick,
|
||||
queries,
|
||||
}: {
|
||||
readonly index: number;
|
||||
readonly name: string;
|
||||
readonly onClick: (name: string, key: string) => void;
|
||||
readonly queries: string[];
|
||||
}) {
|
||||
if (queries.length === 0) {
|
||||
const items: CollapseProps['items'] = [
|
||||
{
|
||||
children: null,
|
||||
key: index.toString(),
|
||||
label: name,
|
||||
},
|
||||
];
|
||||
|
||||
return <Collapse items={items} />;
|
||||
}
|
||||
|
||||
const rows: CollapseProps['items'] = [
|
||||
{
|
||||
children: queries.map((x, ind) => (
|
||||
<AdminRow key={x} data={x} index={ind} name={name} onClick={onClick} />
|
||||
)),
|
||||
key: index.toString(),
|
||||
label: name,
|
||||
},
|
||||
];
|
||||
|
||||
return <Collapse items={rows} />;
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
import { AdminRows } from './AdminRows';
|
||||
import { deleleteQueriesByKey, deleteQuery, getQueries } from '@/api/cache/query';
|
||||
import type { ResponseQueries } from '@/api/cache/types';
|
||||
import { useEffect, useState } from 'react';
|
||||
import type { QueryItem } from 'shared/types/cache';
|
||||
import styled from 'styled-components';
|
||||
import { Button } from 'ui/elements';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
> * {
|
||||
&:first-child {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export function AdminTable() {
|
||||
const [data, setData] = useState<ResponseQueries>({});
|
||||
|
||||
const handleClick = async (name: string, key: string) => {
|
||||
await deleteQuery(key);
|
||||
|
||||
const index = data[name].queries.indexOf(key);
|
||||
const updatedQuery: QueryItem = { ...data[name] };
|
||||
|
||||
if (index >= 0 && updatedQuery.queries.length > 1) {
|
||||
setData({ ...data, [name]: { ...data[name], queries: data[name].queries.splice(index, 1) } });
|
||||
} else if (index === 0) {
|
||||
setData({ ...data, [name]: { ...data[name], queries: [] } });
|
||||
}
|
||||
};
|
||||
|
||||
const handleClickQueriesGroup = async (name: string) => {
|
||||
await deleleteQueriesByKey(name);
|
||||
if (data[name].queries.length > 0) {
|
||||
const updatedQuery = { ...data[name], queries: [] };
|
||||
setData({ ...data, [name]: updatedQuery });
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const getRows = async () => {
|
||||
const queryList = await getQueries();
|
||||
|
||||
setData(queryList);
|
||||
};
|
||||
|
||||
getRows();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{Object.keys(data).map((key, index) => (
|
||||
<Wrapper key={key}>
|
||||
<AdminRows
|
||||
key={key}
|
||||
queries={data[key].queries}
|
||||
name={key}
|
||||
index={index}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
<Button onClick={() => handleClickQueriesGroup(key)}>Удалить все</Button>
|
||||
</Wrapper>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
130
apps/web/Components/Admin/Cache.tsx
Normal file
130
apps/web/Components/Admin/Cache.tsx
Normal file
@ -0,0 +1,130 @@
|
||||
// import { AdminRows } from './AdminRows';
|
||||
import Background from '../Layout/Background';
|
||||
import * as cacheApi from '@/api/cache/query';
|
||||
import { min } from '@/styles/mq';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { memo, useMemo, useState } from 'react';
|
||||
import type { QueryItem } from 'shared/types/cache';
|
||||
import styled from 'styled-components';
|
||||
import { Button, Collapse, Divider } from 'ui/elements';
|
||||
import { Flex } from 'ui/grid';
|
||||
|
||||
type QueryProps = {
|
||||
readonly handleDeleteQuery: () => void;
|
||||
readonly queryKey: string;
|
||||
};
|
||||
|
||||
const StyledPre = styled.pre`
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
`;
|
||||
|
||||
const Query = memo(({ handleDeleteQuery, queryKey }: QueryProps) => {
|
||||
const { data, refetch } = useQuery({
|
||||
enabled: false,
|
||||
queryFn: ({ signal }) => signal && cacheApi.getQueryValue(queryKey, { signal }),
|
||||
queryKey: ['admin', 'cache', 'query', queryKey],
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
|
||||
const [activeKey, setActiveKey] = useState<string | undefined>(undefined);
|
||||
|
||||
const content = (
|
||||
<>
|
||||
<StyledPre>{JSON.stringify(data, null, 2)}</StyledPre>
|
||||
<Flex justifyContent="flex-end">
|
||||
<Button type="primary" danger onClick={handleDeleteQuery}>
|
||||
Удалить
|
||||
</Button>
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<Collapse
|
||||
bordered={false}
|
||||
activeKey={activeKey}
|
||||
items={[
|
||||
{
|
||||
children: data ? content : 'Загрузка...',
|
||||
key: queryKey,
|
||||
label: queryKey,
|
||||
},
|
||||
]}
|
||||
onChange={() => {
|
||||
if (activeKey) {
|
||||
setActiveKey(undefined);
|
||||
} else {
|
||||
setActiveKey(queryKey);
|
||||
|
||||
refetch();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
type QueryListProps = QueryItem;
|
||||
|
||||
const QueryList = memo(({ queries }: QueryListProps) => {
|
||||
const [deletedQueries, setDeletedQueries] = useState<QueryItem['queries']>([]);
|
||||
|
||||
const activeQueries = useMemo(
|
||||
() => queries.filter((queryKey) => !deletedQueries.includes(queryKey)),
|
||||
[deletedQueries, queries]
|
||||
);
|
||||
|
||||
function deleteQuery(queryName: string) {
|
||||
cacheApi.deleteQuery(queryName).then(() => setDeletedQueries([...deletedQueries, queryName]));
|
||||
}
|
||||
|
||||
return activeQueries.map((queryKey) => (
|
||||
<Query
|
||||
key={queryKey}
|
||||
queryKey={queryKey}
|
||||
handleDeleteQuery={() => {
|
||||
deleteQuery(queryKey);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
});
|
||||
|
||||
const Wrapper = styled(Background)`
|
||||
padding: 4px 6px;
|
||||
width: 100%;
|
||||
|
||||
${min('tablet')} {
|
||||
min-height: 790px;
|
||||
}
|
||||
|
||||
${min('laptop')} {
|
||||
padding: 4px 6px 10px;
|
||||
width: 1024px;
|
||||
}
|
||||
`;
|
||||
|
||||
export function CacheQueries() {
|
||||
const { data: queries } = useQuery({
|
||||
queryFn: ({ signal }) => signal && cacheApi.getQueries({ signal }),
|
||||
queryKey: ['admin', 'cache', 'queries'],
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
|
||||
if (!queries) {
|
||||
return <div>Загрузка...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Divider>Управление кэшем</Divider>
|
||||
<Collapse
|
||||
accordion
|
||||
items={Object.keys(queries).map((queryGroupName) => ({
|
||||
children: <QueryList {...queries[queryGroupName]} />,
|
||||
key: queryGroupName,
|
||||
label: queryGroupName,
|
||||
}))}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
export * from './AdminRow';
|
||||
export * from './AdminRows';
|
||||
export * from './AdminTable';
|
||||
9
apps/web/Components/Admin/index.tsx
Normal file
9
apps/web/Components/Admin/index.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import { CacheQueries } from './Cache';
|
||||
|
||||
export function AdminPanel() {
|
||||
return (
|
||||
<div>
|
||||
<CacheQueries />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -22,3 +22,18 @@ export const Grid = styled(Box)`
|
||||
margin: 8px 10% !important;
|
||||
}
|
||||
`;
|
||||
|
||||
export const AdminGrid = styled(Box)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
${min('laptop')} {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
${min('desktop-xl')} {
|
||||
margin: 8px 10% !important;
|
||||
}
|
||||
`;
|
||||
|
||||
11
apps/web/api/cache/query.ts
vendored
11
apps/web/api/cache/query.ts
vendored
@ -11,8 +11,8 @@ const {
|
||||
URL_CACHE_GET_QUERY_VALUE,
|
||||
} = getUrls();
|
||||
|
||||
export function getQueries() {
|
||||
return withHandleError(axios.get<ResponseQueries>(URL_CACHE_GET_QUERIES)).then(
|
||||
export function getQueries({ signal }: { signal: AbortSignal }) {
|
||||
return withHandleError(axios.get<ResponseQueries>(URL_CACHE_GET_QUERIES, { signal })).then(
|
||||
({ data }) => data
|
||||
);
|
||||
}
|
||||
@ -31,7 +31,7 @@ export function reset() {
|
||||
return withHandleError(axios.delete(URL_CACHE_RESET_QUERIES)).then(({ data }) => data);
|
||||
}
|
||||
|
||||
export function deleleteQueriesByKey(queriesGroup: string) {
|
||||
export function deleteQueriesByKey(queriesGroup: string) {
|
||||
return withHandleError(
|
||||
axios.delete(URL_CACHE_DELETE_QUERIES_BY_KEY, {
|
||||
params: {
|
||||
@ -41,12 +41,13 @@ export function deleleteQueriesByKey(queriesGroup: string) {
|
||||
).then(({ data }) => data);
|
||||
}
|
||||
|
||||
export function getQueryValue(queryKey: string) {
|
||||
export function getQueryValue(queryKey: string, { signal }: { signal: AbortSignal }) {
|
||||
return withHandleError(
|
||||
axios.get<ResponseQueries>(URL_CACHE_GET_QUERY_VALUE, {
|
||||
axios.get<object>(URL_CACHE_GET_QUERY_VALUE, {
|
||||
params: {
|
||||
queryKey,
|
||||
},
|
||||
signal,
|
||||
})
|
||||
).then(({ data }) => data);
|
||||
}
|
||||
|
||||
@ -1,47 +1,23 @@
|
||||
import { makeGetServerSideProps } from '.';
|
||||
import { AdminTable } from '@/Components/Admin';
|
||||
import { getQueries } from '@/api/cache/query';
|
||||
import { getUser } from '@/api/user/query';
|
||||
import initializeApollo from '@/apollo/client';
|
||||
import { AdminPanel } from '@/Components/Admin';
|
||||
import { Error } from '@/Components/Common/Error';
|
||||
import Background from '@/Components/Layout/Background';
|
||||
import { Grid } from '@/Components/Layout/Page';
|
||||
import { AdminGrid } from '@/Components/Layout/Page';
|
||||
import { unlimitedRoles } from '@/config/users';
|
||||
import * as hooks from '@/process/hooks';
|
||||
import { useStore } from '@/stores/hooks';
|
||||
import { min } from '@/styles/mq';
|
||||
import * as CRMTypes from '@/graphql/crm.types';
|
||||
import { dehydrate, QueryClient } from '@tanstack/react-query';
|
||||
import Head from 'next/head';
|
||||
import styled from 'styled-components';
|
||||
|
||||
function Content() {
|
||||
const store = useStore();
|
||||
store.$process.add('Unlimited');
|
||||
|
||||
hooks.useSentryScope();
|
||||
hooks.useMainData();
|
||||
hooks.useGetUsers();
|
||||
hooks.useInsuranceData();
|
||||
hooks.useReactions();
|
||||
|
||||
const Wrapper = styled(Background)`
|
||||
padding: 4px 6px;
|
||||
|
||||
${min('tablet')} {
|
||||
min-height: 790px;
|
||||
}
|
||||
|
||||
${min('laptop')} {
|
||||
padding: 4px 6px 10px;
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<Grid>
|
||||
<AdminGrid>
|
||||
<Head>
|
||||
<title>Админка</title>
|
||||
<title>Панель управления</title>
|
||||
<meta name="description" content="Админка" />
|
||||
</Head>
|
||||
<Wrapper>
|
||||
<AdminTable />
|
||||
</Wrapper>
|
||||
</Grid>
|
||||
<AdminPanel />
|
||||
</AdminGrid>
|
||||
);
|
||||
}
|
||||
|
||||
@ -51,6 +27,62 @@ export default function Admin(props) {
|
||||
return <Content />;
|
||||
}
|
||||
|
||||
export const getServerSideProps = makeGetServerSideProps({
|
||||
roles: unlimitedRoles,
|
||||
});
|
||||
/** @type {import('next').GetServerSideProps} */
|
||||
export async function getServerSideProps({ req }) {
|
||||
const { cookie = '' } = req.headers;
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
const user = await queryClient.fetchQuery(['user'], ({ signal }) =>
|
||||
getUser({
|
||||
headers: {
|
||||
cookie,
|
||||
},
|
||||
signal,
|
||||
})
|
||||
);
|
||||
|
||||
const apolloClient = initializeApollo();
|
||||
|
||||
try {
|
||||
const {
|
||||
data: { systemuser },
|
||||
} = await apolloClient.query({
|
||||
fetchPolicy: 'network-only',
|
||||
query: CRMTypes.GetSystemUserDocument,
|
||||
variables: {
|
||||
domainname: user.domainName,
|
||||
},
|
||||
});
|
||||
|
||||
if (!systemuser?.roles?.some((x) => x?.name && unlimitedRoles.includes(x.name))) {
|
||||
return {
|
||||
props: {
|
||||
initialQueryState: dehydrate(queryClient),
|
||||
statusCode: 403,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
await queryClient.prefetchQuery(['admin', 'cache', 'queries'], ({ signal }) =>
|
||||
getQueries({ signal })
|
||||
);
|
||||
|
||||
return {
|
||||
props: {
|
||||
calculation: {},
|
||||
initialApolloState: apolloClient.cache.extract(),
|
||||
initialQueryState: dehydrate(queryClient),
|
||||
statusCode: 200,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
props: {
|
||||
error: JSON.stringify(error),
|
||||
initialQueryState: dehydrate(queryClient),
|
||||
statusCode: 500,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user