mirror of
https://github.com/graphql-hive/console
synced 2026-05-24 09:38:26 +00:00
use more client preset (#2661)
This commit is contained in:
parent
32ab26c928
commit
da27a1606b
37 changed files with 392 additions and 363 deletions
2
.github/workflows/typescript-typecheck.yaml
vendored
2
.github/workflows/typescript-typecheck.yaml
vendored
|
|
@ -23,6 +23,6 @@ jobs:
|
|||
uses: SimenB/github-actions-cpu-cores@v1
|
||||
|
||||
- name: typecheck
|
||||
run: pnpm typecheck --concurrency ${{ steps.cpu-cores.outputs.count }}
|
||||
run: pnpm run --workspace-concurrency ${{ steps.cpu-cores.outputs.count }} -r typecheck
|
||||
env:
|
||||
NODE_OPTIONS: '--max-old-space-size=4096'
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
"test": "vitest",
|
||||
"test:e2e": "CYPRESS_BASE_URL=$HIVE_APP_BASE_URL cypress run",
|
||||
"test:integration": "cd integration-tests && pnpm test:integration",
|
||||
"typecheck": "pnpm turbo typecheck --color",
|
||||
"typecheck": "pnpm run -r typecheck",
|
||||
"upload-sourcemaps": "./scripts/upload-sourcemaps.sh",
|
||||
"workspace": "pnpm run --filter $1 $2"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -99,7 +99,6 @@
|
|||
"@graphql-codegen/client-preset-swc-plugin": "0.2.0",
|
||||
"@graphql-typed-document-node/core": "3.2.0",
|
||||
"@hive/emails": "workspace:*",
|
||||
"@hive/server": "workspace:*",
|
||||
"@next/bundle-analyzer": "13.4.11",
|
||||
"@storybook/addon-essentials": "7.0.23",
|
||||
"@storybook/addon-interactions": "7.0.23",
|
||||
|
|
|
|||
|
|
@ -149,13 +149,13 @@ const SchemaView_TargetFragment = graphql(`
|
|||
cleanId
|
||||
latestSchemaVersion {
|
||||
id
|
||||
valid
|
||||
schemas {
|
||||
nodes {
|
||||
__typename
|
||||
...SchemaView_SchemaFragment
|
||||
}
|
||||
}
|
||||
...MarkAsValid_SchemaVersionFragment
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
|
|
|||
|
|
@ -30,11 +30,21 @@ import {
|
|||
import { Combobox } from '@/components/v2/combobox';
|
||||
import { CreateAccessTokenModal, DeleteTargetModal } from '@/components/v2/modals';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { SetTargetValidationDocument } from '@/graphql';
|
||||
import { canAccessTarget, TargetAccessScope } from '@/lib/access/target';
|
||||
import { useRouteSelector, useToggle } from '@/lib/hooks';
|
||||
import { withSessionProtection } from '@/lib/supertokens/guard';
|
||||
|
||||
const SetTargetValidationMutation = graphql(`
|
||||
mutation Settings_SetTargetValidation($input: SetTargetValidationInput!) {
|
||||
setTargetValidation(input: $input) {
|
||||
id
|
||||
validationSettings {
|
||||
...TargetValidationSettingsFields
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const RegistryAccessTokens_MeFragment = graphql(`
|
||||
fragment RegistryAccessTokens_MeFragment on Member {
|
||||
...CanAccessTarget_MemberFragment
|
||||
|
|
@ -379,7 +389,7 @@ function floorDate(date: Date): Date {
|
|||
|
||||
const ConditionalBreakingChanges = (): ReactElement => {
|
||||
const router = useRouteSelector();
|
||||
const [targetValidation, setValidation] = useMutation(SetTargetValidationDocument);
|
||||
const [targetValidation, setValidation] = useMutation(SetTargetValidationMutation);
|
||||
const [mutation, updateValidation] = useMutation(
|
||||
TargetSettingsPage_UpdateTargetValidationSettingsMutation,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ import { Title } from '@/components/common';
|
|||
import { DataWrapper } from '@/components/v2';
|
||||
import { LAST_VISITED_ORG_KEY } from '@/constants';
|
||||
import { env } from '@/env/backend';
|
||||
import { OrganizationsDocument } from '@/graphql';
|
||||
import { graphql } from '@/gql';
|
||||
import { writeLastVisitedOrganization } from '@/lib/cookies';
|
||||
import { useRouteSelector } from '@/lib/hooks/use-route-selector';
|
||||
import { withSessionProtection } from '@/lib/supertokens/guard';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies -- TODO: should we move to "dependencies"?
|
||||
import { InternalApi } from '@hive/server';
|
||||
import { type InternalApi } from '@hive/server';
|
||||
import { createTRPCProxyClient, httpLink } from '@trpc/client';
|
||||
|
||||
async function getSuperTokensUserIdFromRequest(
|
||||
|
|
@ -67,8 +67,20 @@ export const getServerSideProps = withSessionProtection(async ({ req, res }) =>
|
|||
};
|
||||
});
|
||||
|
||||
export const OrganizationsQuery = graphql(`
|
||||
query organizations {
|
||||
organizations {
|
||||
nodes {
|
||||
...OrganizationFields
|
||||
cleanId
|
||||
}
|
||||
total
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
function Home(): ReactElement {
|
||||
const [query] = useQuery({ query: OrganizationsDocument });
|
||||
const [query] = useQuery({ query: OrganizationsQuery });
|
||||
const router = useRouteSelector();
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,3 @@
|
|||
import {
|
||||
OrganizationActivitiesQuery,
|
||||
ProjectActivitiesQuery,
|
||||
TargetActivitiesQuery,
|
||||
} from '@/graphql';
|
||||
import { OrganizationActivitiesQuery } from '@/graphql';
|
||||
|
||||
export type ActivityNode =
|
||||
| OrganizationActivitiesQuery['organizationActivities']['nodes'][0]
|
||||
| ProjectActivitiesQuery['projectActivities']['nodes'][0]
|
||||
| TargetActivitiesQuery['targetActivities']['nodes'][0];
|
||||
export type ActivityNode = OrganizationActivitiesQuery['organizationActivities']['nodes'][0];
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { ReactElement } from 'react';
|
|||
import { useQuery } from 'urql';
|
||||
import { DataWrapper, Table, TBody, Td, Th, THead, Tr } from '@/components/v2';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { UsageEstimationDocument } from '@/graphql';
|
||||
import { Scale } from '../common';
|
||||
import { calculatePeriod } from '../common/TimeFilter';
|
||||
|
||||
|
|
@ -17,6 +16,16 @@ const OrganizationUsageEstimationView_OrganizationFragment = graphql(`
|
|||
}
|
||||
`);
|
||||
|
||||
const Usage_UsageEstimationQuery = graphql(`
|
||||
query Usage_UsageEstimationQuery($range: DateRangeInput!, $organization: ID!) {
|
||||
usageEstimation(range: $range) {
|
||||
org(selector: { organization: $organization }) {
|
||||
operations
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export function OrganizationUsageEstimationView(props: {
|
||||
organization: FragmentType<typeof OrganizationUsageEstimationView_OrganizationFragment>;
|
||||
}): ReactElement {
|
||||
|
|
@ -27,7 +36,7 @@ export function OrganizationUsageEstimationView(props: {
|
|||
const period = calculatePeriod('month');
|
||||
|
||||
const [query] = useQuery({
|
||||
query: UsageEstimationDocument,
|
||||
query: Usage_UsageEstimationQuery,
|
||||
variables: {
|
||||
organization: organization.cleanId,
|
||||
range: period,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,30 @@
|
|||
import { ReactElement, useCallback } from 'react';
|
||||
import { useMutation } from 'urql';
|
||||
import { Button, Tooltip } from '@/components/v2';
|
||||
import { SchemaVersionFieldsFragment, UpdateSchemaVersionStatusDocument } from '@/graphql';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { useRouteSelector } from '@/lib/hooks';
|
||||
|
||||
export function MarkAsValid({
|
||||
version,
|
||||
}: {
|
||||
version: Pick<SchemaVersionFieldsFragment, 'id' | 'valid'>;
|
||||
const UpdateSchemaVersionStatusMutation = graphql(`
|
||||
mutation updateSchemaVersionStatus($input: SchemaVersionUpdateInput!) {
|
||||
updateSchemaVersionStatus(input: $input) {
|
||||
...SchemaVersionFields
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const MarkAsValid_SchemaVersionFragment = graphql(`
|
||||
fragment MarkAsValid_SchemaVersionFragment on SchemaVersion {
|
||||
id
|
||||
valid
|
||||
}
|
||||
`);
|
||||
|
||||
export function MarkAsValid(props: {
|
||||
version: FragmentType<typeof MarkAsValid_SchemaVersionFragment>;
|
||||
}): ReactElement | null {
|
||||
const router = useRouteSelector();
|
||||
const [mutation, mutate] = useMutation(UpdateSchemaVersionStatusDocument);
|
||||
const version = useFragment(MarkAsValid_SchemaVersionFragment, props.version);
|
||||
const [mutation, mutate] = useMutation(UpdateSchemaVersionStatusMutation);
|
||||
const markAsValid = useCallback(async () => {
|
||||
await mutate({
|
||||
input: {
|
||||
|
|
|
|||
|
|
@ -4,26 +4,43 @@ import { FixedSizeList, ListChildComponentProps } from 'react-window';
|
|||
import { useQuery } from 'urql';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import { Button, Checkbox, Drawer, Input, Spinner } from '@/components/v2';
|
||||
import { DateRangeInput, OperationsStatsDocument, OperationStatsFieldsFragment } from '@/graphql';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { DateRangeInput } from '@/graphql';
|
||||
import { useFormattedNumber, useRouteSelector, useToggle } from '@/lib/hooks';
|
||||
import { ChevronUpIcon } from '@radix-ui/react-icons';
|
||||
|
||||
const OperationsFilter_OperationStatsConnectionFragment = graphql(`
|
||||
fragment OperationsFilter_OperationStatsConnectionFragment on OperationStatsConnection {
|
||||
nodes {
|
||||
id
|
||||
operationHash
|
||||
name
|
||||
...OperationRow_OperationStatsFragment
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
function OperationsFilter({
|
||||
onClose,
|
||||
isOpen,
|
||||
onFilter,
|
||||
operations,
|
||||
operationStatsConnection,
|
||||
selected,
|
||||
}: {
|
||||
onClose(): void;
|
||||
onFilter(keys: string[]): void;
|
||||
isOpen: boolean;
|
||||
operations: readonly OperationStatsFieldsFragment[];
|
||||
operationStatsConnection: FragmentType<typeof OperationsFilter_OperationStatsConnectionFragment>;
|
||||
selected?: string[];
|
||||
}): ReactElement {
|
||||
const operations = useFragment(
|
||||
OperationsFilter_OperationStatsConnectionFragment,
|
||||
operationStatsConnection,
|
||||
);
|
||||
|
||||
function getOperationHashes() {
|
||||
const items: string[] = [];
|
||||
for (const op of operations) {
|
||||
for (const op of operations.nodes) {
|
||||
if (op.operationHash) {
|
||||
items.push(op.operationHash);
|
||||
}
|
||||
|
|
@ -51,7 +68,9 @@ function OperationsFilter({
|
|||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const debouncedFilter = useDebouncedCallback((value: string) => {
|
||||
setVisibleOperations(
|
||||
operations.filter(op => op.name.toLocaleLowerCase().includes(value.toLocaleLowerCase())),
|
||||
operations.nodes.filter(op =>
|
||||
op.name.toLocaleLowerCase().includes(value.toLocaleLowerCase()),
|
||||
),
|
||||
);
|
||||
}, 500);
|
||||
|
||||
|
|
@ -65,7 +84,7 @@ function OperationsFilter({
|
|||
[setSearchTerm, debouncedFilter],
|
||||
);
|
||||
|
||||
const [visibleOperations, setVisibleOperations] = useState(operations);
|
||||
const [visibleOperations, setVisibleOperations] = useState(operations.nodes);
|
||||
|
||||
const selectAll = useCallback(() => {
|
||||
setSelectedItems(getOperationHashes());
|
||||
|
|
@ -82,7 +101,7 @@ function OperationsFilter({
|
|||
<OperationRow
|
||||
style={style}
|
||||
key={operation.id}
|
||||
operation={operation}
|
||||
operationStats={operation}
|
||||
selected={selectedItems.includes(operation.operationHash || '')}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
|
|
@ -103,7 +122,7 @@ function OperationsFilter({
|
|||
value={searchTerm}
|
||||
onClear={() => {
|
||||
setSearchTerm('');
|
||||
setVisibleOperations(operations);
|
||||
setVisibleOperations(operations.nodes);
|
||||
}}
|
||||
/>
|
||||
<div className="flex gap-2 items-center w-full">
|
||||
|
|
@ -151,6 +170,17 @@ function OperationsFilter({
|
|||
);
|
||||
}
|
||||
|
||||
const OperationsFilterContainer_OperationStatsQuery = graphql(`
|
||||
query OperationsFilterContainer_OperationStatsQuery($selector: OperationsStatsSelectorInput!) {
|
||||
operationsStats(selector: $selector) {
|
||||
operations {
|
||||
...OperationsFilter_OperationStatsConnectionFragment
|
||||
total
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
function OperationsFilterContainer({
|
||||
period,
|
||||
isOpen,
|
||||
|
|
@ -166,7 +196,7 @@ function OperationsFilterContainer({
|
|||
}): ReactElement | null {
|
||||
const router = useRouteSelector();
|
||||
const [query] = useQuery({
|
||||
query: OperationsStatsDocument,
|
||||
query: OperationsFilterContainer_OperationStatsQuery,
|
||||
variables: {
|
||||
selector: {
|
||||
organization: router.organizationId,
|
||||
|
|
@ -186,32 +216,40 @@ function OperationsFilterContainer({
|
|||
return <Spinner />;
|
||||
}
|
||||
|
||||
const allOperations = query.data.operationsStats?.operations?.nodes ?? [];
|
||||
|
||||
return (
|
||||
<OperationsFilter
|
||||
operations={allOperations}
|
||||
operationStatsConnection={query.data.operationsStats?.operations}
|
||||
selected={selected}
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
onFilter={hashes => {
|
||||
onFilter(hashes.length === allOperations.length ? [] : hashes);
|
||||
onFilter(hashes.length === query.data?.operationsStats.operations.total ? [] : hashes);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const OperationRow_OperationStatsFragment = graphql(`
|
||||
fragment OperationRow_OperationStatsFragment on OperationStats {
|
||||
id
|
||||
name
|
||||
operationHash
|
||||
count
|
||||
}
|
||||
`);
|
||||
|
||||
function OperationRow({
|
||||
operation,
|
||||
operationStats,
|
||||
selected,
|
||||
onSelect,
|
||||
style,
|
||||
}: {
|
||||
operation: OperationStatsFieldsFragment;
|
||||
operationStats: FragmentType<typeof OperationRow_OperationStatsFragment>;
|
||||
selected: boolean;
|
||||
onSelect(id: string, selected: boolean): void;
|
||||
style: any;
|
||||
}): ReactElement {
|
||||
const operation = useFragment(OperationRow_OperationStatsFragment, operationStats);
|
||||
const requests = useFormattedNumber(operation.count);
|
||||
const hash = operation.operationHash || '';
|
||||
const change = useCallback(() => {
|
||||
|
|
@ -261,17 +299,25 @@ export function OperationsFilterTrigger({
|
|||
);
|
||||
}
|
||||
|
||||
const ClientRow_ClientStatsFragment = graphql(`
|
||||
fragment ClientRow_ClientStatsFragment on ClientStats {
|
||||
name
|
||||
count
|
||||
}
|
||||
`);
|
||||
|
||||
function ClientRow({
|
||||
client,
|
||||
selected,
|
||||
onSelect,
|
||||
style,
|
||||
...props
|
||||
}: {
|
||||
client: { name: string; count: number };
|
||||
client: FragmentType<typeof ClientRow_ClientStatsFragment>;
|
||||
selected: boolean;
|
||||
onSelect(id: string, selected: boolean): void;
|
||||
style: any;
|
||||
}): ReactElement {
|
||||
const client = useFragment(ClientRow_ClientStatsFragment, props.client);
|
||||
const requests = useFormattedNumber(client.count);
|
||||
const hash = client.name;
|
||||
const change = useCallback(() => {
|
||||
|
|
@ -294,21 +340,34 @@ function ClientRow({
|
|||
);
|
||||
}
|
||||
|
||||
const ClientsFilter_ClientStatsConnectionFragment = graphql(`
|
||||
fragment ClientsFilter_ClientStatsConnectionFragment on ClientStatsConnection {
|
||||
nodes {
|
||||
name
|
||||
...ClientRow_ClientStatsFragment
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
function ClientsFilter({
|
||||
onClose,
|
||||
isOpen,
|
||||
onFilter,
|
||||
clients,
|
||||
clientStatsConnection,
|
||||
selected,
|
||||
}: {
|
||||
onClose(): void;
|
||||
onFilter(keys: string[]): void;
|
||||
isOpen: boolean;
|
||||
clients: readonly { name: string; count: number }[];
|
||||
clientStatsConnection: FragmentType<typeof ClientsFilter_ClientStatsConnectionFragment>;
|
||||
selected?: string[];
|
||||
}): ReactElement {
|
||||
const clientConnection = useFragment(
|
||||
ClientsFilter_ClientStatsConnectionFragment,
|
||||
clientStatsConnection,
|
||||
);
|
||||
function getClientNames() {
|
||||
return clients.map(client => client.name);
|
||||
return clientConnection.nodes.map(client => client.name);
|
||||
}
|
||||
|
||||
const [selectedItems, setSelectedItems] = useState<string[]>(() =>
|
||||
|
|
@ -331,7 +390,9 @@ function ClientsFilter({
|
|||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const debouncedFilter = useDebouncedCallback((value: string) => {
|
||||
setVisibleOperations(
|
||||
clients.filter(client => client.name.toLocaleLowerCase().includes(value.toLocaleLowerCase())),
|
||||
clientConnection.nodes.filter(client =>
|
||||
client.name.toLocaleLowerCase().includes(value.toLocaleLowerCase()),
|
||||
),
|
||||
);
|
||||
}, 500);
|
||||
|
||||
|
|
@ -345,11 +406,11 @@ function ClientsFilter({
|
|||
[setSearchTerm, debouncedFilter],
|
||||
);
|
||||
|
||||
const [visibleOperations, setVisibleOperations] = useState(clients);
|
||||
const [visibleOperations, setVisibleOperations] = useState(clientConnection.nodes);
|
||||
|
||||
const selectAll = useCallback(() => {
|
||||
setSelectedItems(getClientNames());
|
||||
}, [clients]);
|
||||
}, [clientConnection.nodes]);
|
||||
const selectNone = useCallback(() => {
|
||||
setSelectedItems([]);
|
||||
}, [setSelectedItems]);
|
||||
|
|
@ -383,7 +444,7 @@ function ClientsFilter({
|
|||
value={searchTerm}
|
||||
onClear={() => {
|
||||
setSearchTerm('');
|
||||
setVisibleOperations(clients);
|
||||
setVisibleOperations(clientConnection.nodes);
|
||||
}}
|
||||
/>
|
||||
<div className="flex gap-2 items-center w-full">
|
||||
|
|
@ -431,6 +492,19 @@ function ClientsFilter({
|
|||
);
|
||||
}
|
||||
|
||||
const ClientsFilterContainer_ClientStatsQuery = graphql(`
|
||||
query ClientsFilterContainer_ClientStats($selector: OperationsStatsSelectorInput!) {
|
||||
operationsStats(selector: $selector) {
|
||||
clients {
|
||||
...ClientsFilter_ClientStatsConnectionFragment
|
||||
nodes {
|
||||
__typename
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
function ClientsFilterContainer({
|
||||
period,
|
||||
isOpen,
|
||||
|
|
@ -446,7 +520,7 @@ function ClientsFilterContainer({
|
|||
}): ReactElement | null {
|
||||
const router = useRouteSelector();
|
||||
const [query] = useQuery({
|
||||
query: OperationsStatsDocument,
|
||||
query: ClientsFilterContainer_ClientStatsQuery,
|
||||
variables: {
|
||||
selector: {
|
||||
organization: router.organizationId,
|
||||
|
|
@ -466,11 +540,11 @@ function ClientsFilterContainer({
|
|||
return <Spinner />;
|
||||
}
|
||||
|
||||
const allClients = query.data.operationsStats?.clients?.nodes ?? [];
|
||||
const allClients = query.data.operationsStats?.clients.nodes ?? [];
|
||||
|
||||
return (
|
||||
<ClientsFilter
|
||||
clients={allClients}
|
||||
clientStatsConnection={query.data.operationsStats.clients}
|
||||
selected={selected}
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ import {
|
|||
Tr,
|
||||
} from '@/components/v2';
|
||||
import { env } from '@/env/frontend';
|
||||
import { graphql } from '@/gql';
|
||||
import { DateRangeInput, OperationsStatsDocument, OperationStatsFieldsFragment } from '@/graphql';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { DateRangeInput } from '@/graphql';
|
||||
import { useDecimal, useFormattedDuration, useFormattedNumber, useToggle } from '@/lib/hooks';
|
||||
import { ChevronUpIcon, ExclamationTriangleIcon } from '@radix-ui/react-icons';
|
||||
import {
|
||||
|
|
@ -203,7 +203,7 @@ function OperationsTable({
|
|||
organization: string;
|
||||
project: string;
|
||||
target: string;
|
||||
clients: readonly { name: string }[];
|
||||
clients: readonly { name: string }[] | null;
|
||||
clientFilter: string | null;
|
||||
setClientFilter: (filter: string) => void;
|
||||
}): ReactElement {
|
||||
|
|
@ -322,53 +322,83 @@ function OperationsTable({
|
|||
);
|
||||
}
|
||||
|
||||
const OperationsTableContainer_OperationsStatsFragment = graphql(`
|
||||
fragment OperationsTableContainer_OperationsStatsFragment on OperationsStats {
|
||||
clients {
|
||||
nodes {
|
||||
name
|
||||
}
|
||||
}
|
||||
operations {
|
||||
nodes {
|
||||
id
|
||||
name
|
||||
operationHash
|
||||
kind
|
||||
duration {
|
||||
p90
|
||||
p95
|
||||
p99
|
||||
}
|
||||
countOk
|
||||
count
|
||||
percentage
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
function OperationsTableContainer({
|
||||
operations,
|
||||
operationsFilter,
|
||||
organization,
|
||||
project,
|
||||
target,
|
||||
clients,
|
||||
clientFilter,
|
||||
setClientFilter,
|
||||
className,
|
||||
...props
|
||||
}: {
|
||||
operations: readonly OperationStatsFieldsFragment[];
|
||||
operationStats: FragmentType<typeof OperationsTableContainer_OperationsStatsFragment> | null;
|
||||
operationsFilter: readonly string[];
|
||||
organization: string;
|
||||
project: string;
|
||||
target: string;
|
||||
clients: readonly { name: string }[];
|
||||
clientFilter: string | null;
|
||||
setClientFilter: (client: string) => void;
|
||||
className?: string;
|
||||
}): ReactElement {
|
||||
const operationStats = useFragment(
|
||||
OperationsTableContainer_OperationsStatsFragment,
|
||||
props.operationStats,
|
||||
);
|
||||
const data = useMemo(() => {
|
||||
const records: Operation[] = [];
|
||||
for (const op of operations) {
|
||||
if (
|
||||
operationsFilter.length > 0 &&
|
||||
op.operationHash &&
|
||||
!operationsFilter.includes(op.operationHash)
|
||||
) {
|
||||
continue;
|
||||
if (operationStats) {
|
||||
for (const op of operationStats.operations.nodes) {
|
||||
if (
|
||||
operationsFilter.length > 0 &&
|
||||
op.operationHash &&
|
||||
!operationsFilter.includes(op.operationHash)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
records.push({
|
||||
id: op.id,
|
||||
name: op.name,
|
||||
kind: op.kind,
|
||||
p90: op.duration.p90,
|
||||
p95: op.duration.p95,
|
||||
p99: op.duration.p99,
|
||||
failureRate: 1 - op.countOk / op.count,
|
||||
requests: op.count,
|
||||
percentage: op.percentage,
|
||||
hash: op.operationHash!,
|
||||
});
|
||||
}
|
||||
records.push({
|
||||
id: op.id,
|
||||
name: op.name,
|
||||
kind: op.kind,
|
||||
p90: op.duration.p90,
|
||||
p95: op.duration.p95,
|
||||
p99: op.duration.p99,
|
||||
failureRate: 1 - op.countOk / op.count,
|
||||
requests: op.count,
|
||||
percentage: op.percentage,
|
||||
hash: op.operationHash!,
|
||||
});
|
||||
}
|
||||
|
||||
return records;
|
||||
}, [operations, operationsFilter]);
|
||||
}, [operationStats?.operations.nodes, operationsFilter]);
|
||||
|
||||
const [pagination, setPagination] = useState<PaginationState>({ pageIndex: 0, pageSize: 20 });
|
||||
const [sorting, setSorting] = useState<SortingState>([]);
|
||||
|
|
@ -403,13 +433,31 @@ function OperationsTableContainer({
|
|||
organization={organization}
|
||||
project={project}
|
||||
target={target}
|
||||
clients={clients}
|
||||
clients={operationStats?.clients.nodes ?? null}
|
||||
clientFilter={clientFilter}
|
||||
setClientFilter={setClientFilter}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const OperationsList_OperationsStatsQuery = graphql(`
|
||||
query OperationsList_OperationsStats($selector: OperationsStatsSelectorInput!) {
|
||||
operationsStats(selector: $selector) {
|
||||
clients {
|
||||
nodes {
|
||||
__typename
|
||||
}
|
||||
}
|
||||
operations {
|
||||
nodes {
|
||||
__typename
|
||||
}
|
||||
}
|
||||
...OperationsTableContainer_OperationsStatsFragment
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export function OperationsList({
|
||||
className,
|
||||
organization,
|
||||
|
|
@ -429,7 +477,7 @@ export function OperationsList({
|
|||
}): ReactElement {
|
||||
const [clientFilter, setClientFilter] = useState<string | null>(null);
|
||||
const [query, refetch] = useQuery({
|
||||
query: OperationsStatsDocument,
|
||||
query: OperationsList_OperationsStatsQuery,
|
||||
variables: {
|
||||
selector: {
|
||||
organization,
|
||||
|
|
@ -441,8 +489,6 @@ export function OperationsList({
|
|||
},
|
||||
},
|
||||
});
|
||||
const operations = query.data?.operationsStats?.operations?.nodes ?? [];
|
||||
const clients = query.data?.operationsStats?.clients?.nodes ?? [];
|
||||
|
||||
return (
|
||||
<OperationsFallback
|
||||
|
|
@ -451,10 +497,9 @@ export function OperationsList({
|
|||
refetch={() => refetch({ requestPolicy: 'cache-and-network' })}
|
||||
>
|
||||
<OperationsTableContainer
|
||||
operations={operations}
|
||||
operationStats={query.data?.operationsStats ?? null}
|
||||
operationsFilter={operationsFilter}
|
||||
className={className}
|
||||
clients={clients}
|
||||
setClientFilter={setClientFilter}
|
||||
clientFilter={clientFilter}
|
||||
organization={organization}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,8 @@ import AutoSizer from 'react-virtualized-auto-sizer';
|
|||
import { useQuery } from 'urql';
|
||||
import { Section } from '@/components/common';
|
||||
import { CHART_PRIMARY_COLOR } from '@/constants';
|
||||
import {
|
||||
DateRangeInput,
|
||||
GeneralOperationsStatsDocument,
|
||||
GeneralOperationsStatsQuery,
|
||||
} from '@/graphql';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
import { DateRangeInput } from '@/graphql';
|
||||
import {
|
||||
formatDuration,
|
||||
formatNumber,
|
||||
|
|
@ -23,6 +20,28 @@ import { useChartStyles } from '@/utils';
|
|||
import { OperationsFallback } from './Fallback';
|
||||
import { createEmptySeries, fullSeries, resolutionToMilliseconds } from './utils';
|
||||
|
||||
const Stats_GeneralOperationsStatsQuery = graphql(`
|
||||
query Stats_GeneralOperationsStats($selector: OperationsStatsSelectorInput!, $resolution: Int!) {
|
||||
operationsStats(selector: $selector) {
|
||||
... on OperationsStats {
|
||||
totalRequests
|
||||
totalFailures
|
||||
totalOperations
|
||||
duration {
|
||||
p75
|
||||
p90
|
||||
p95
|
||||
p99
|
||||
}
|
||||
}
|
||||
...OverTimeStats_OperationsStatsFragment
|
||||
...RpmOverTimeStats_OperationStatsFragment
|
||||
...LatencyOverTimeStats_OperationStatsFragment
|
||||
...ClientsStats_OperationsStatsFragment
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const classes = {
|
||||
root: cn('text-center'),
|
||||
value: cn('font-normal text-3xl text-gray-900 dark:text-white'),
|
||||
|
|
@ -121,17 +140,31 @@ function FailureRateStats({
|
|||
);
|
||||
}
|
||||
|
||||
const OverTimeStats_OperationsStatsFragment = graphql(`
|
||||
fragment OverTimeStats_OperationsStatsFragment on OperationsStats {
|
||||
failuresOverTime(resolution: $resolution) {
|
||||
date
|
||||
value
|
||||
}
|
||||
requestsOverTime(resolution: $resolution) {
|
||||
date
|
||||
value
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
function OverTimeStats({
|
||||
period,
|
||||
resolution,
|
||||
requestsOverTime = [],
|
||||
failuresOverTime = [],
|
||||
operationStats,
|
||||
}: {
|
||||
period: DateRangeInput;
|
||||
resolution: number;
|
||||
requestsOverTime?: GeneralOperationsStatsQuery['operationsStats']['requestsOverTime'];
|
||||
failuresOverTime?: GeneralOperationsStatsQuery['operationsStats']['failuresOverTime'];
|
||||
operationStats: FragmentType<typeof OverTimeStats_OperationsStatsFragment> | null;
|
||||
}): ReactElement {
|
||||
const { failuresOverTime = [], requestsOverTime = [] } =
|
||||
useFragment(OverTimeStats_OperationsStatsFragment, operationStats) ?? {};
|
||||
|
||||
const styles = useChartStyles();
|
||||
const interval = resolutionToMilliseconds(resolution, period);
|
||||
const requests = useMemo(() => {
|
||||
|
|
@ -250,15 +283,34 @@ function OverTimeStats({
|
|||
);
|
||||
}
|
||||
|
||||
function ClientsStats({
|
||||
clients = [],
|
||||
}: {
|
||||
clients?: GeneralOperationsStatsQuery['operationsStats']['clients']['nodes'];
|
||||
const ClientsStats_OperationsStatsFragment = graphql(`
|
||||
fragment ClientsStats_OperationsStatsFragment on OperationsStats {
|
||||
clients {
|
||||
nodes {
|
||||
name
|
||||
count
|
||||
percentage
|
||||
versions {
|
||||
version
|
||||
count
|
||||
percentage
|
||||
}
|
||||
}
|
||||
total
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
function ClientsStats(props: {
|
||||
operationStats: FragmentType<typeof ClientsStats_OperationsStatsFragment> | null;
|
||||
}): ReactElement {
|
||||
const styles = useChartStyles();
|
||||
const operationStats = useFragment(ClientsStats_OperationsStatsFragment, props.operationStats);
|
||||
const sortedClients = useMemo(() => {
|
||||
return clients?.length ? clients.slice().sort((a, b) => b.count - a.count) : [];
|
||||
}, [clients]);
|
||||
return operationStats?.clients.nodes?.length
|
||||
? operationStats.clients.nodes.slice().sort((a, b) => b.count - a.count)
|
||||
: [];
|
||||
}, [operationStats?.clients.nodes]);
|
||||
const byClient = useMemo(() => {
|
||||
let values: string[] = [];
|
||||
const labels: string[] = [];
|
||||
|
|
@ -438,20 +490,36 @@ function ClientsStats({
|
|||
);
|
||||
}
|
||||
|
||||
const LatencyOverTimeStats_OperationStatsFragment = graphql(`
|
||||
fragment LatencyOverTimeStats_OperationStatsFragment on OperationsStats {
|
||||
durationOverTime(resolution: $resolution) {
|
||||
date
|
||||
duration {
|
||||
p75
|
||||
p90
|
||||
p95
|
||||
p99
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
function LatencyOverTimeStats({
|
||||
period,
|
||||
resolution,
|
||||
duration = [],
|
||||
operationStats,
|
||||
}: {
|
||||
period: {
|
||||
from: string;
|
||||
to: string;
|
||||
};
|
||||
resolution: number;
|
||||
duration?: GeneralOperationsStatsQuery['operationsStats']['durationOverTime'];
|
||||
operationStats?: FragmentType<typeof LatencyOverTimeStats_OperationStatsFragment> | null;
|
||||
}): ReactElement {
|
||||
const styles = useChartStyles();
|
||||
const interval = resolutionToMilliseconds(resolution, period);
|
||||
const { durationOverTime: duration = [] } =
|
||||
useFragment(LatencyOverTimeStats_OperationStatsFragment, operationStats) ?? {};
|
||||
const p75 = useMemo(() => {
|
||||
if (duration?.length) {
|
||||
return fullSeries(
|
||||
|
|
@ -576,20 +644,30 @@ function LatencyOverTimeStats({
|
|||
);
|
||||
}
|
||||
|
||||
const RpmOverTimeStats_OperationStatsFragment = graphql(`
|
||||
fragment RpmOverTimeStats_OperationStatsFragment on OperationsStats {
|
||||
requestsOverTime(resolution: $resolution) {
|
||||
date
|
||||
value
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
function RpmOverTimeStats({
|
||||
period,
|
||||
resolution,
|
||||
requestsOverTime = [],
|
||||
operationStats,
|
||||
}: {
|
||||
period: {
|
||||
from: string;
|
||||
to: string;
|
||||
};
|
||||
resolution: number;
|
||||
requestsOverTime?: GeneralOperationsStatsQuery['operationsStats']['requestsOverTime'];
|
||||
operationStats: FragmentType<typeof RpmOverTimeStats_OperationStatsFragment> | null;
|
||||
}): ReactElement {
|
||||
const styles = useChartStyles();
|
||||
const requests = requestsOverTime ?? [];
|
||||
const { requestsOverTime: requests = [] } =
|
||||
useFragment(RpmOverTimeStats_OperationStatsFragment, operationStats) ?? {};
|
||||
|
||||
const interval = resolutionToMilliseconds(resolution, period);
|
||||
const windowInM = interval / (60 * 1000);
|
||||
|
|
@ -703,7 +781,7 @@ export function OperationsStats({
|
|||
}): ReactElement {
|
||||
const resolution = 90;
|
||||
const [query, refetchQuery] = useQuery({
|
||||
query: GeneralOperationsStatsDocument,
|
||||
query: Stats_GeneralOperationsStatsQuery,
|
||||
variables: {
|
||||
selector: {
|
||||
organization,
|
||||
|
|
@ -749,15 +827,14 @@ export function OperationsStats({
|
|||
</div>
|
||||
</OperationsFallback>
|
||||
<div>
|
||||
<ClientsStats clients={operationsStats?.clients?.nodes} />
|
||||
<ClientsStats operationStats={operationsStats ?? null} />
|
||||
</div>
|
||||
<div>
|
||||
<OperationsFallback isError={isError} refetch={refetch} isFetching={isFetching}>
|
||||
<OverTimeStats
|
||||
period={period}
|
||||
resolution={resolution}
|
||||
requestsOverTime={operationsStats?.requestsOverTime}
|
||||
failuresOverTime={operationsStats?.failuresOverTime}
|
||||
operationStats={operationsStats ?? null}
|
||||
/>
|
||||
</OperationsFallback>
|
||||
</div>
|
||||
|
|
@ -766,7 +843,7 @@ export function OperationsStats({
|
|||
<RpmOverTimeStats
|
||||
period={period}
|
||||
resolution={resolution}
|
||||
requestsOverTime={operationsStats?.requestsOverTime}
|
||||
operationStats={operationsStats ?? null}
|
||||
/>
|
||||
</OperationsFallback>
|
||||
</div>
|
||||
|
|
@ -774,7 +851,7 @@ export function OperationsStats({
|
|||
<OperationsFallback isError={isError} refetch={refetch}>
|
||||
<LatencyOverTimeStats
|
||||
period={period}
|
||||
duration={operationsStats?.durationOverTime}
|
||||
operationStats={operationsStats ?? null}
|
||||
resolution={resolution}
|
||||
/>
|
||||
</OperationsFallback>
|
||||
|
|
|
|||
|
|
@ -2,10 +2,25 @@ import { ReactElement } from 'react';
|
|||
import { useRouter } from 'next/router';
|
||||
import { useMutation } from 'urql';
|
||||
import { Button, Heading, Modal } from '@/components/v2';
|
||||
import { DeleteProjectDocument } from '@/graphql';
|
||||
import { graphql } from '@/gql';
|
||||
import { useRouteSelector } from '@/lib/hooks';
|
||||
import { TrashIcon } from '@radix-ui/react-icons';
|
||||
|
||||
export const DeleteProjectMutation = graphql(`
|
||||
mutation deleteProject($selector: ProjectSelectorInput!) {
|
||||
deleteProject(selector: $selector) {
|
||||
selector {
|
||||
organization
|
||||
project
|
||||
}
|
||||
deletedProject {
|
||||
__typename
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const DeleteProjectModal = ({
|
||||
isOpen,
|
||||
toggleModalOpen,
|
||||
|
|
@ -13,7 +28,7 @@ export const DeleteProjectModal = ({
|
|||
isOpen: boolean;
|
||||
toggleModalOpen: () => void;
|
||||
}): ReactElement => {
|
||||
const [, mutate] = useMutation(DeleteProjectDocument);
|
||||
const [, mutate] = useMutation(DeleteProjectMutation);
|
||||
const router = useRouteSelector();
|
||||
const { replace } = useRouter();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,25 @@ import { ReactElement } from 'react';
|
|||
import { useRouter } from 'next/router';
|
||||
import { useMutation } from 'urql';
|
||||
import { Button, Heading, Modal } from '@/components/v2';
|
||||
import { DeleteTargetDocument } from '@/graphql';
|
||||
import { graphql } from '@/gql';
|
||||
import { TrashIcon } from '@radix-ui/react-icons';
|
||||
|
||||
export const DeleteTargetMutation = graphql(`
|
||||
mutation deleteTarget($selector: TargetSelectorInput!) {
|
||||
deleteTarget(selector: $selector) {
|
||||
selector {
|
||||
organization
|
||||
project
|
||||
target
|
||||
}
|
||||
deletedTarget {
|
||||
__typename
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const DeleteTargetModal = ({
|
||||
isOpen,
|
||||
toggleModalOpen,
|
||||
|
|
@ -18,7 +34,7 @@ export const DeleteTargetModal = ({
|
|||
projectId: string;
|
||||
targetId: string;
|
||||
}): ReactElement => {
|
||||
const [, mutate] = useMutation(DeleteTargetDocument);
|
||||
const [, mutate] = useMutation(DeleteTargetMutation);
|
||||
const { replace } = useRouter();
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import { createThirdPartyEmailPasswordNodeOktaProvider } from '@/lib/supertokens
|
|||
// eslint-disable-next-line import/no-extraneous-dependencies -- TODO: should we move to "dependencies"?
|
||||
import { EmailsApi } from '@hive/emails';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies -- TODO: should we move to "dependencies"?
|
||||
import { InternalApi } from '@hive/server';
|
||||
import { type InternalApi } from '@hive/server';
|
||||
import { createTRPCProxyClient, CreateTRPCProxyClient, httpLink } from '@trpc/client';
|
||||
import { fetch } from '@whatwg-node/fetch';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
mutation deletePersistedOperation($input: PersistedOperationSelectorInput!) {
|
||||
deletePersistedOperation(selector: $input) {
|
||||
deletedPersistedOperation {
|
||||
__typename
|
||||
id
|
||||
operationHash
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
mutation deleteProject($selector: ProjectSelectorInput!) {
|
||||
deleteProject(selector: $selector) {
|
||||
selector {
|
||||
organization
|
||||
project
|
||||
}
|
||||
deletedProject {
|
||||
__typename
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
mutation deleteTarget($selector: TargetSelectorInput!) {
|
||||
deleteTarget(selector: $selector) {
|
||||
selector {
|
||||
organization
|
||||
project
|
||||
target
|
||||
}
|
||||
deletedTarget {
|
||||
__typename
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
mutation sendFeedback($feedback: String!) {
|
||||
sendFeedback(feedback: $feedback)
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
mutation setTargetValidation($input: SetTargetValidationInput!) {
|
||||
setTargetValidation(input: $input) {
|
||||
id
|
||||
validationSettings {
|
||||
...TargetValidationSettingsFields
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
mutation updateOrganizationMemberAccess($input: OrganizationMemberAccessInput!) {
|
||||
updateOrganizationMemberAccess(input: $input) {
|
||||
selector {
|
||||
organization
|
||||
}
|
||||
organization {
|
||||
...OrganizationFields
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
mutation updateSchemaVersionStatus($input: SchemaVersionUpdateInput!) {
|
||||
updateSchemaVersionStatus(input: $input) {
|
||||
...SchemaVersionFields
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
mutation updateTargetName($input: UpdateTargetNameInput!) {
|
||||
updateTargetName(input: $input) {
|
||||
ok {
|
||||
selector {
|
||||
organization
|
||||
project
|
||||
target
|
||||
}
|
||||
updatedTarget {
|
||||
...TargetFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
query generalOperationsStats($selector: OperationsStatsSelectorInput!, $resolution: Int!) {
|
||||
operationsStats(selector: $selector) {
|
||||
... on OperationsStats {
|
||||
totalRequests
|
||||
totalFailures
|
||||
totalOperations
|
||||
duration {
|
||||
p75
|
||||
p90
|
||||
p95
|
||||
p99
|
||||
}
|
||||
}
|
||||
... on OperationsStats {
|
||||
failuresOverTime(resolution: $resolution) {
|
||||
date
|
||||
value
|
||||
}
|
||||
requestsOverTime(resolution: $resolution) {
|
||||
date
|
||||
value
|
||||
}
|
||||
durationOverTime(resolution: $resolution) {
|
||||
date
|
||||
duration {
|
||||
p75
|
||||
p90
|
||||
p95
|
||||
p99
|
||||
}
|
||||
}
|
||||
}
|
||||
... on OperationsStats {
|
||||
clients {
|
||||
nodes {
|
||||
name
|
||||
count
|
||||
percentage
|
||||
versions {
|
||||
version
|
||||
count
|
||||
percentage
|
||||
}
|
||||
}
|
||||
total
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
query hasCollectedOperations($selector: TargetSelectorInput!) {
|
||||
hasCollectedOperations(selector: $selector)
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
query operationsStats($selector: OperationsStatsSelectorInput!) {
|
||||
operationsStats(selector: $selector) {
|
||||
operations {
|
||||
nodes {
|
||||
...OperationStatsFields
|
||||
}
|
||||
total
|
||||
}
|
||||
clients {
|
||||
nodes {
|
||||
name
|
||||
count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
query usageEstimation($range: DateRangeInput!, $organization: ID!) {
|
||||
usageEstimation(range: $range) {
|
||||
org(selector: { organization: $organization }) {
|
||||
operations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
query organizations {
|
||||
organizations {
|
||||
nodes {
|
||||
...OrganizationFields
|
||||
}
|
||||
total
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
query projectActivities($selector: ProjectActivitiesSelector!) {
|
||||
projectActivities(selector: $selector) {
|
||||
nodes {
|
||||
__typename
|
||||
id
|
||||
createdAt
|
||||
...ProjectCreated
|
||||
...ProjectDeleted
|
||||
...ProjectNameUpdated
|
||||
...ProjectIdUpdated
|
||||
...TargetCreated
|
||||
...TargetDeleted
|
||||
...TargetNameUpdated
|
||||
...TargetIdUpdated
|
||||
}
|
||||
total
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
query projectsWithTargets($selector: OrganizationSelectorInput!) {
|
||||
projects(selector: $selector) {
|
||||
nodes {
|
||||
...ProjectFields
|
||||
targets {
|
||||
nodes {
|
||||
...TargetFields
|
||||
}
|
||||
total
|
||||
}
|
||||
}
|
||||
total
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
query projects($selector: OrganizationSelectorInput!) {
|
||||
projects(selector: $selector) {
|
||||
nodes {
|
||||
...ProjectFields
|
||||
}
|
||||
total
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
query targetActivities($selector: TargetActivitiesSelector!) {
|
||||
targetActivities(selector: $selector) {
|
||||
nodes {
|
||||
__typename
|
||||
id
|
||||
createdAt
|
||||
...TargetCreated
|
||||
...TargetDeleted
|
||||
...TargetNameUpdated
|
||||
...TargetIdUpdated
|
||||
}
|
||||
total
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
query targets($selector: ProjectSelectorInput!) {
|
||||
targets(selector: $selector) {
|
||||
total
|
||||
nodes {
|
||||
...TargetFields
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import { TypeInput as ThirdPartEmailPasswordTypeInput } from 'supertokens-node/r
|
|||
import zod from 'zod';
|
||||
import { env } from '@/env/backend';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies -- TODO: should we move to "dependencies"?
|
||||
import { InternalApi } from '@hive/server';
|
||||
import { type InternalApi } from '@hive/server';
|
||||
import { CreateTRPCProxyClient } from '@trpc/client';
|
||||
|
||||
const OIDCProfileInfoSchema = zod.object({
|
||||
|
|
|
|||
|
|
@ -14,20 +14,17 @@ import type { CreateOrganizationMutation } from '@/components/v2/modals/create-o
|
|||
import type { CreateProjectMutation } from '@/components/v2/modals/create-project';
|
||||
import type { CreateTarget_CreateTargetMutation } from '@/components/v2/modals/create-target';
|
||||
import type { DeleteOrganizationDocument } from '@/components/v2/modals/delete-organization';
|
||||
import { type DeleteProjectMutation } from '@/components/v2/modals/delete-project';
|
||||
import { type DeleteTargetMutation } from '@/components/v2/modals/delete-target';
|
||||
import { graphql } from '@/gql';
|
||||
import { ResultOf, VariablesOf } from '@graphql-typed-document-node/core';
|
||||
import { Cache, QueryInput, UpdateResolver } from '@urql/exchange-graphcache';
|
||||
import { OrganizationsQuery } from '../../pages';
|
||||
import { CollectionsQuery } from '../../pages/[orgId]/[projectId]/[targetId]/laboratory';
|
||||
import {
|
||||
TokensDocument,
|
||||
type DeleteTokensDocument,
|
||||
} from '../../pages/[orgId]/[projectId]/[targetId]/settings';
|
||||
import {
|
||||
DeletePersistedOperationDocument,
|
||||
DeleteProjectDocument,
|
||||
DeleteTargetDocument,
|
||||
OrganizationsDocument,
|
||||
} from '../graphql';
|
||||
|
||||
const TargetsDocument = graphql(`
|
||||
query targets($selector: ProjectSelectorInput!) {
|
||||
|
|
@ -85,7 +82,7 @@ const createOrganization: TypedDocumentNodeUpdateResolver<typeof CreateOrganizat
|
|||
updateQuery(
|
||||
cache,
|
||||
{
|
||||
query: OrganizationsDocument,
|
||||
query: OrganizationsQuery,
|
||||
},
|
||||
data => {
|
||||
if (createOrganization.ok) {
|
||||
|
|
@ -127,7 +124,7 @@ const createProject: TypedDocumentNodeUpdateResolver<typeof CreateProjectMutatio
|
|||
});
|
||||
};
|
||||
|
||||
const deleteProject: TypedDocumentNodeUpdateResolver<typeof DeleteProjectDocument> = (
|
||||
const deleteProject: TypedDocumentNodeUpdateResolver<typeof DeleteProjectMutation> = (
|
||||
{ deleteProject },
|
||||
_args,
|
||||
cache,
|
||||
|
|
@ -171,7 +168,7 @@ const createTarget: TypedDocumentNodeUpdateResolver<typeof CreateTarget_CreateTa
|
|||
);
|
||||
};
|
||||
|
||||
const deleteTarget: TypedDocumentNodeUpdateResolver<typeof DeleteTargetDocument> = (
|
||||
const deleteTarget: TypedDocumentNodeUpdateResolver<typeof DeleteTargetMutation> = (
|
||||
{ deleteTarget },
|
||||
_args,
|
||||
cache,
|
||||
|
|
@ -279,16 +276,6 @@ const addAlert: TypedDocumentNodeUpdateResolver<typeof CreateAlertModal_AddAlert
|
|||
id: updatedProject.id,
|
||||
});
|
||||
};
|
||||
const deletePersistedOperation: TypedDocumentNodeUpdateResolver<
|
||||
typeof DeletePersistedOperationDocument
|
||||
> = ({ deletePersistedOperation }, _args, cache) => {
|
||||
const operation = deletePersistedOperation.deletedPersistedOperation;
|
||||
|
||||
cache.invalidate({
|
||||
__typename: operation.__typename,
|
||||
id: operation.id,
|
||||
});
|
||||
};
|
||||
|
||||
const deleteDocumentCollection: TypedDocumentNodeUpdateResolver<DeleteCollectionMutationType> = (
|
||||
mutation,
|
||||
|
|
@ -387,7 +374,6 @@ export const Mutation = {
|
|||
addAlertChannel,
|
||||
deleteAlertChannels,
|
||||
addAlert,
|
||||
deletePersistedOperation,
|
||||
deleteDocumentCollection,
|
||||
deleteOperationInDocumentCollection,
|
||||
createOperationInDocumentCollection,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
lockfileVersion: '6.1'
|
||||
lockfileVersion: '6.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
|
|
@ -1703,9 +1703,6 @@ importers:
|
|||
'@hive/emails':
|
||||
specifier: workspace:*
|
||||
version: link:../../services/emails
|
||||
'@hive/server':
|
||||
specifier: workspace:*
|
||||
version: link:../../services/server
|
||||
'@next/bundle-analyzer':
|
||||
specifier: 13.4.11
|
||||
version: 13.4.11
|
||||
|
|
|
|||
|
|
@ -39,8 +39,9 @@
|
|||
"dependsOn": ["^build", "@graphql-hive/client#build"],
|
||||
"outputs": ["dist/**"]
|
||||
},
|
||||
"typecheck": {
|
||||
"outputs": [""]
|
||||
"@hive/server#build": {
|
||||
"dependsOn": ["^build", "@hive/app#build"],
|
||||
"outputs": ["dist/**"]
|
||||
},
|
||||
"check:build": {
|
||||
"outputs": [""]
|
||||
|
|
|
|||
Loading…
Reference in a new issue