mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
prettier v3 and apply fixes to existing files (#3279)
This commit is contained in:
parent
383bb7473f
commit
72f59267a1
143 changed files with 863 additions and 915 deletions
|
|
@ -7,7 +7,6 @@ __generated__/
|
|||
/.husky/_/
|
||||
/.turbo/
|
||||
/integration-tests/testkit/gql/
|
||||
/packages/services/storage/src/db/types.ts
|
||||
/packages/libraries/cli/src/sdk.ts
|
||||
/packages/libraries/cli/src/gql/
|
||||
/packages/web/app/src/gql/**
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@ export type ObservabilityConfig = {
|
|||
};
|
||||
};
|
||||
export class Observability {
|
||||
constructor(private envName: string, private config: ObservabilityConfig) {}
|
||||
constructor(
|
||||
private envName: string,
|
||||
private config: ObservabilityConfig,
|
||||
) {}
|
||||
|
||||
deploy() {
|
||||
const ns = new k8s.core.v1.Namespace('observability', {
|
||||
|
|
|
|||
|
|
@ -43,28 +43,24 @@ test.concurrent('can check a schema with target:registry:read access', async ()
|
|||
|
||||
// Check schema with no read and write rights
|
||||
const checkResultErrors = await noAccessToken
|
||||
.checkSchema(
|
||||
/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
foo: String
|
||||
}
|
||||
`,
|
||||
)
|
||||
.checkSchema(/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
foo: String
|
||||
}
|
||||
`)
|
||||
.then(r => r.expectGraphQLErrors());
|
||||
expect(checkResultErrors).toHaveLength(1);
|
||||
expect(checkResultErrors[0].message).toMatch('target:registry:read');
|
||||
|
||||
// Check schema with read rights
|
||||
const checkResultValid = await readToken
|
||||
.checkSchema(
|
||||
/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
foo: String
|
||||
}
|
||||
`,
|
||||
)
|
||||
.checkSchema(/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
foo: String
|
||||
}
|
||||
`)
|
||||
.then(r => r.expectNoGraphQLErrors());
|
||||
expect(checkResultValid.schemaCheck.__typename).toBe('SchemaCheckSuccess');
|
||||
});
|
||||
|
|
@ -107,18 +103,16 @@ test.concurrent('should match indentation of previous description', async () =>
|
|||
|
||||
// Check schema with read rights
|
||||
const checkResult = await readToken
|
||||
.checkSchema(
|
||||
/* GraphQL */ `
|
||||
type Query {
|
||||
"""
|
||||
ping-ping
|
||||
"""
|
||||
ping: String
|
||||
" pong-pong "
|
||||
pong: String
|
||||
}
|
||||
`,
|
||||
)
|
||||
.checkSchema(/* GraphQL */ `
|
||||
type Query {
|
||||
"""
|
||||
ping-ping
|
||||
"""
|
||||
ping: String
|
||||
" pong-pong "
|
||||
pong: String
|
||||
}
|
||||
`)
|
||||
.then(r => r.expectNoGraphQLErrors());
|
||||
const check = checkResult.schemaCheck;
|
||||
|
||||
|
|
@ -272,14 +266,12 @@ test.concurrent('successful check without previously published schema is persist
|
|||
|
||||
// Check schema with read rights
|
||||
const checkResult = await readToken
|
||||
.checkSchema(
|
||||
/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
pong: String
|
||||
}
|
||||
`,
|
||||
)
|
||||
.checkSchema(/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
pong: String
|
||||
}
|
||||
`)
|
||||
.then(r => r.expectNoGraphQLErrors());
|
||||
const check = checkResult.schemaCheck;
|
||||
|
||||
|
|
@ -358,14 +350,12 @@ test.concurrent('successful check with previously published schema is persisted'
|
|||
|
||||
// Check schema with read rights
|
||||
const checkResult = await readToken
|
||||
.checkSchema(
|
||||
/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
pong: String
|
||||
}
|
||||
`,
|
||||
)
|
||||
.checkSchema(/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
pong: String
|
||||
}
|
||||
`)
|
||||
.then(r => r.expectNoGraphQLErrors());
|
||||
const check = checkResult.schemaCheck;
|
||||
|
||||
|
|
@ -421,13 +411,11 @@ test.concurrent('failed check due to graphql validation is persisted', async ()
|
|||
|
||||
// Check schema with read rights
|
||||
const checkResult = await readToken
|
||||
.checkSchema(
|
||||
/* GraphQL */ `
|
||||
type Query {
|
||||
ping: Str
|
||||
}
|
||||
`,
|
||||
)
|
||||
.checkSchema(/* GraphQL */ `
|
||||
type Query {
|
||||
ping: Str
|
||||
}
|
||||
`)
|
||||
.then(r => r.expectNoGraphQLErrors());
|
||||
const check = checkResult.schemaCheck;
|
||||
|
||||
|
|
@ -512,13 +500,11 @@ test.concurrent('failed check due to breaking change is persisted', async () =>
|
|||
|
||||
// Check schema with read rights
|
||||
const checkResult = await readToken
|
||||
.checkSchema(
|
||||
/* GraphQL */ `
|
||||
type Query {
|
||||
ping: Float
|
||||
}
|
||||
`,
|
||||
)
|
||||
.checkSchema(/* GraphQL */ `
|
||||
type Query {
|
||||
ping: Float
|
||||
}
|
||||
`)
|
||||
.then(r => r.expectNoGraphQLErrors());
|
||||
const check = checkResult.schemaCheck;
|
||||
|
||||
|
|
@ -610,14 +596,12 @@ test.concurrent('failed check due to policy error is persisted', async () => {
|
|||
|
||||
// Check schema with read rights
|
||||
const checkResult = await readToken
|
||||
.checkSchema(
|
||||
/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
foo: String
|
||||
}
|
||||
`,
|
||||
)
|
||||
.checkSchema(/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
foo: String
|
||||
}
|
||||
`)
|
||||
.then(r => r.expectNoGraphQLErrors());
|
||||
const check = checkResult.schemaCheck;
|
||||
|
||||
|
|
@ -661,13 +645,13 @@ test.concurrent('failed check due to policy error is persisted', async () => {
|
|||
{
|
||||
node: {
|
||||
end: {
|
||||
column: 19,
|
||||
column: 17,
|
||||
line: 2,
|
||||
},
|
||||
message: 'Description is required for type "Query"',
|
||||
ruleId: 'require-description',
|
||||
start: {
|
||||
column: 14,
|
||||
column: 12,
|
||||
line: 2,
|
||||
},
|
||||
},
|
||||
|
|
@ -721,14 +705,12 @@ test.concurrent('successful check with warnings and safe changes is persisted',
|
|||
|
||||
// Check schema with read rights
|
||||
const checkResult = await readToken
|
||||
.checkSchema(
|
||||
/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
foo: String
|
||||
}
|
||||
`,
|
||||
)
|
||||
.checkSchema(/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
foo: String
|
||||
}
|
||||
`)
|
||||
.then(r => r.expectNoGraphQLErrors());
|
||||
const check = checkResult.schemaCheck;
|
||||
|
||||
|
|
@ -770,13 +752,13 @@ test.concurrent('successful check with warnings and safe changes is persisted',
|
|||
{
|
||||
node: {
|
||||
end: {
|
||||
column: 19,
|
||||
column: 17,
|
||||
line: 2,
|
||||
},
|
||||
message: 'Description is required for type "Query"',
|
||||
ruleId: 'require-description',
|
||||
start: {
|
||||
column: 14,
|
||||
column: 12,
|
||||
line: 2,
|
||||
},
|
||||
},
|
||||
|
|
@ -810,14 +792,12 @@ test.concurrent(
|
|||
|
||||
// Check schema with read rights
|
||||
const checkResult = await readToken
|
||||
.checkSchema(
|
||||
/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
foo: String
|
||||
}
|
||||
`,
|
||||
)
|
||||
.checkSchema(/* GraphQL */ `
|
||||
type Query {
|
||||
ping: String
|
||||
foo: String
|
||||
}
|
||||
`)
|
||||
.then(r => r.expectNoGraphQLErrors());
|
||||
const check = checkResult.schemaCheck;
|
||||
|
||||
|
|
@ -937,13 +917,11 @@ test('approve failed schema check that has breaking changes succeeds', async ()
|
|||
|
||||
// Check schema with read rights
|
||||
const checkResult = await readToken
|
||||
.checkSchema(
|
||||
/* GraphQL */ `
|
||||
type Query {
|
||||
ping: Float
|
||||
}
|
||||
`,
|
||||
)
|
||||
.checkSchema(/* GraphQL */ `
|
||||
type Query {
|
||||
ping: Float
|
||||
}
|
||||
`)
|
||||
.then(r => r.expectNoGraphQLErrors());
|
||||
const check = checkResult.schemaCheck;
|
||||
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@
|
|||
"@next/eslint-plugin-next": "13.5.6",
|
||||
"@sentry/cli": "2.21.2",
|
||||
"@swc/core": "1.3.96",
|
||||
"@theguild/eslint-config": "0.11.0",
|
||||
"@theguild/prettier-config": "1.2.0",
|
||||
"@theguild/eslint-config": "0.11.1",
|
||||
"@theguild/prettier-config": "2.0.2",
|
||||
"@types/node": "18.18.8",
|
||||
"bob-the-bundler": "7.0.1",
|
||||
"cypress": "13.4.0",
|
||||
|
|
@ -84,9 +84,9 @@
|
|||
"jest-snapshot-serializer-raw": "2.0.0",
|
||||
"lint-staged": "15.0.2",
|
||||
"pg": "8.11.3",
|
||||
"prettier": "2.8.8",
|
||||
"prettier": "3.0.3",
|
||||
"prettier-plugin-sql": "0.15.1",
|
||||
"prettier-plugin-tailwindcss": "0.4.1",
|
||||
"prettier-plugin-tailwindcss": "0.5.6",
|
||||
"pretty-quick": "3.1.3",
|
||||
"rimraf": "4.4.1",
|
||||
"ts-node": "10.9.1",
|
||||
|
|
|
|||
|
|
@ -30,14 +30,17 @@ export default class Introspect extends Command {
|
|||
|
||||
async run() {
|
||||
const { flags, args } = await this.parse(Introspect);
|
||||
const headers = flags.header?.reduce((acc, header) => {
|
||||
const [key, ...values] = header.split(':');
|
||||
const headers = flags.header?.reduce(
|
||||
(acc, header) => {
|
||||
const [key, ...values] = header.split(':');
|
||||
|
||||
return {
|
||||
...acc,
|
||||
[key]: values.join(':'),
|
||||
};
|
||||
}, {} as Record<string, string>);
|
||||
return {
|
||||
...acc,
|
||||
[key]: values.join(':'),
|
||||
};
|
||||
},
|
||||
{} as Record<string, string>,
|
||||
);
|
||||
|
||||
const schema = await loadSchema(args.location, {
|
||||
headers,
|
||||
|
|
|
|||
|
|
@ -10,11 +10,10 @@ export async function loadOperations(
|
|||
file: string,
|
||||
options?: {
|
||||
normalize?: boolean;
|
||||
pluckModules?:
|
||||
| {
|
||||
name: string;
|
||||
identifier?: string;
|
||||
}[];
|
||||
pluckModules?: {
|
||||
name: string;
|
||||
identifier?: string;
|
||||
}[];
|
||||
pluckGlobalGqlIdentifierName?: string[];
|
||||
},
|
||||
): Promise<
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ export interface RegistryContext {
|
|||
|
||||
declare global {
|
||||
namespace GraphQLModules {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
interface GlobalContext extends RegistryContext {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,11 @@ interface PaginationSelector {
|
|||
export class ActivityManager {
|
||||
private logger: Logger;
|
||||
|
||||
constructor(logger: Logger, private authManager: AuthManager, private storage: Storage) {
|
||||
constructor(
|
||||
logger: Logger,
|
||||
private authManager: AuthManager,
|
||||
private storage: Storage,
|
||||
) {
|
||||
this.logger = logger.child({
|
||||
source: 'ActivityManager',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@ import {
|
|||
export class SlackCommunicationAdapter implements CommunicationAdapter {
|
||||
private logger: Logger;
|
||||
|
||||
constructor(logger: Logger, @Inject(WEB_APP_URL) private appBaseUrl: string) {
|
||||
constructor(
|
||||
logger: Logger,
|
||||
@Inject(WEB_APP_URL) private appBaseUrl: string,
|
||||
) {
|
||||
this.logger = logger.child({ service: 'SlackCommunicationAdapter' });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,10 @@ export class ProjectAccess {
|
|||
private tokenAccess: Dataloader<ProjectTokenAccessSelector, boolean, string>;
|
||||
private scopes: Dataloader<ProjectUserScopesSelector, readonly ProjectAccessScope[], string>;
|
||||
|
||||
constructor(logger: Logger, private organizationAccess: OrganizationAccess) {
|
||||
constructor(
|
||||
logger: Logger,
|
||||
private organizationAccess: OrganizationAccess,
|
||||
) {
|
||||
this.logger = logger.child({
|
||||
source: 'ProjectAccess',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -43,7 +43,10 @@ export class TargetAccess {
|
|||
private tokenAccess: Dataloader<TargetTokenAccessSelector, boolean, string>;
|
||||
private scopes: Dataloader<TargetUserScopesSelector, readonly TargetAccessScope[], string>;
|
||||
|
||||
constructor(logger: Logger, private organizationAccess: OrganizationAccess) {
|
||||
constructor(
|
||||
logger: Logger,
|
||||
private organizationAccess: OrganizationAccess,
|
||||
) {
|
||||
this.logger = logger.child({
|
||||
source: 'TargetAccess',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -22,7 +22,10 @@ export const fullNameLengthBoundaries = {
|
|||
export class UserManager {
|
||||
private logger: Logger;
|
||||
|
||||
constructor(logger: Logger, private storage: Storage) {
|
||||
constructor(
|
||||
logger: Logger,
|
||||
private storage: Storage,
|
||||
) {
|
||||
this.logger = logger.child({
|
||||
source: 'UserManager',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,7 +11,11 @@ import type { CollectionModule } from './../__generated__/types';
|
|||
export class CollectionProvider {
|
||||
private logger: Logger;
|
||||
|
||||
constructor(logger: Logger, private storage: Storage, private authManager: AuthManager) {
|
||||
constructor(
|
||||
logger: Logger,
|
||||
private storage: Storage,
|
||||
private authManager: AuthManager,
|
||||
) {
|
||||
this.logger = logger.child({ source: 'CollectionProvider' });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,10 @@ function ensureNumber(value: number | string): number {
|
|||
global: true,
|
||||
})
|
||||
export class OperationsReader {
|
||||
constructor(private clickHouse: ClickHouse, private logger: Logger) {}
|
||||
constructor(
|
||||
private clickHouse: ClickHouse,
|
||||
private logger: Logger,
|
||||
) {}
|
||||
|
||||
private pickQueryByPeriod(
|
||||
queryMap: {
|
||||
|
|
|
|||
|
|
@ -1735,7 +1735,7 @@ export const resolvers: SchemaModule.Resolvers = {
|
|||
organization: usage.organization,
|
||||
project: usage.project,
|
||||
target: usage.target,
|
||||
} as const);
|
||||
}) as const;
|
||||
|
||||
for (const typeDefinition of sdl.definitions) {
|
||||
if (typeDefinition.kind === Kind.OBJECT_TYPE_DEFINITION) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export const createTaskRunner = (args: {
|
|||
logger: args.logger,
|
||||
name: 'schema-purge',
|
||||
});
|
||||
task.done.finally(() => {
|
||||
void task.done.finally(() => {
|
||||
if (!isStopped) {
|
||||
loop();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,10 @@ import { REDIS_INSTANCE } from '../../shared/providers/redis';
|
|||
})
|
||||
export class DistributedCache {
|
||||
private logger: Logger;
|
||||
constructor(logger: Logger, @Inject(REDIS_INSTANCE) private redis: Redis) {
|
||||
constructor(
|
||||
logger: Logger,
|
||||
@Inject(REDIS_INSTANCE) private redis: Redis,
|
||||
) {
|
||||
this.logger = logger.child({ service: 'DistributedCache' });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,10 @@ import { Storage } from './storage';
|
|||
})
|
||||
export class IdTranslator {
|
||||
private logger: Logger;
|
||||
constructor(private storage: Storage, logger: Logger) {
|
||||
constructor(
|
||||
private storage: Storage,
|
||||
logger: Logger,
|
||||
) {
|
||||
this.logger = logger.child({ service: 'IdTranslator' });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ export interface TargetSelector extends ProjectSelector {
|
|||
target: string;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
||||
export interface Storage {
|
||||
destroy(): Promise<void>;
|
||||
isReady(): Promise<boolean>;
|
||||
|
|
@ -744,4 +745,5 @@ export interface Storage {
|
|||
}
|
||||
|
||||
@Injectable()
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
||||
export class Storage implements Storage {}
|
||||
|
|
|
|||
|
|
@ -68,15 +68,15 @@ export function createEmailScheduler(config?: { endpoint: string }) {
|
|||
input.organization.name
|
||||
}</strong> has reached over 100% of the operations limit quota.
|
||||
Used ${numberFormatter.format(input.usage.current)} of ${numberFormatter.format(
|
||||
input.usage.quota,
|
||||
)}.
|
||||
input.usage.quota,
|
||||
)}.
|
||||
</mj-text>.
|
||||
<mj-text>
|
||||
We recommend to increase the limit.
|
||||
</mj-text>
|
||||
<mj-button href="${env.hiveServices.webAppUrl}/${
|
||||
input.organization.cleanId
|
||||
}/view/subscription">
|
||||
input.organization.cleanId
|
||||
}/view/subscription">
|
||||
Manage your subscription
|
||||
</mj-button>
|
||||
</mj-column>
|
||||
|
|
@ -132,15 +132,15 @@ export function createEmailScheduler(config?: { endpoint: string }) {
|
|||
input.organization.name
|
||||
}</strong> is approaching its operations limit quota.
|
||||
Used ${numberFormatter.format(input.usage.current)} of ${numberFormatter.format(
|
||||
input.usage.quota,
|
||||
)}.
|
||||
input.usage.quota,
|
||||
)}.
|
||||
</mj-text>.
|
||||
<mj-text>
|
||||
We recommend to increase the limit.
|
||||
</mj-text>
|
||||
<mj-button href="${env.hiveServices.webAppUrl}/${
|
||||
input.organization.cleanId
|
||||
}/view/subscription">
|
||||
input.organization.cleanId
|
||||
}/view/subscription">
|
||||
Manage your subscription
|
||||
</mj-button>
|
||||
</mj-column>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"build": "tsx ../../../scripts/runify.ts",
|
||||
"db:generate": "schemats generate --config schemats.cjs -o src/db/types.ts"
|
||||
"db:generate": "schemats generate --config schemats.cjs -o src/db/types.ts && prettier --write src/db/types.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sentry/node": "7.77.0",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ const cn = require('../../migrations/tools/db-connection-string.cjs');
|
|||
|
||||
module.exports = {
|
||||
conn: cn('registry'),
|
||||
prettier: true,
|
||||
// Prettier v3 is not supported here yet, but we don't really need it.
|
||||
prettier: false,
|
||||
skipPrefix: ['supertokens_'],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
export type alert_channel_type = "SLACK" | "WEBHOOK";
|
||||
export type alert_type = "SCHEMA_CHANGE_NOTIFICATIONS";
|
||||
export type schema_policy_resource = "ORGANIZATION" | "PROJECT";
|
||||
export type user_role = "ADMIN" | "MEMBER";
|
||||
export type alert_channel_type = 'SLACK' | 'WEBHOOK';
|
||||
export type alert_type = 'SCHEMA_CHANGE_NOTIFICATIONS';
|
||||
export type schema_policy_resource = 'ORGANIZATION' | 'PROJECT';
|
||||
export type user_role = 'ADMIN' | 'MEMBER';
|
||||
|
||||
export interface activities {
|
||||
activity_metadata: any;
|
||||
|
|
|
|||
|
|
@ -1604,9 +1604,9 @@ export async function createStorage(connection: string, maximumPoolSize: number)
|
|||
return trx.one(sql`
|
||||
UPDATE public.targets as t
|
||||
SET validation_percentage = ${percentage}, validation_period = ${period}, validation_excluded_clients = ${sql.array(
|
||||
excludedClients,
|
||||
'text',
|
||||
)}
|
||||
excludedClients,
|
||||
'text',
|
||||
)}
|
||||
FROM (
|
||||
SELECT
|
||||
it.id,
|
||||
|
|
@ -1745,8 +1745,8 @@ export async function createStorage(connection: string, maximumPoolSize: number)
|
|||
LEFT JOIN public.targets as t ON (t.id = sv.target_id)
|
||||
LEFT JOIN public.schema_log as sl ON (sl.id = sv.action_id)
|
||||
WHERE t.id = ${target} AND t.project_id = ${project} AND ${
|
||||
onlyComposable ? sql`sv.is_composable IS TRUE` : true
|
||||
}
|
||||
onlyComposable ? sql`sv.is_composable IS TRUE` : true
|
||||
}
|
||||
ORDER BY sv.created_at DESC
|
||||
LIMIT 1
|
||||
`);
|
||||
|
|
@ -1829,8 +1829,8 @@ export async function createStorage(connection: string, maximumPoolSize: number)
|
|||
SELECT sv.id FROM public.schema_versions as sv WHERE sv.created_at < (
|
||||
SELECT svi.created_at FROM public.schema_versions as svi WHERE svi.id = ${version}
|
||||
) AND sv.target_id = ${target} AND ${
|
||||
onlyComposable ? sql`sv.is_composable IS TRUE` : true
|
||||
} ORDER BY sv.created_at DESC LIMIT 1
|
||||
onlyComposable ? sql`sv.is_composable IS TRUE` : true
|
||||
} ORDER BY sv.created_at DESC LIMIT 1
|
||||
) AND sl.action = 'PUSH'
|
||||
ORDER BY sl.created_at DESC
|
||||
`,
|
||||
|
|
@ -2333,8 +2333,8 @@ export async function createStorage(connection: string, maximumPoolSize: number)
|
|||
("name", "type", "project_id", "slack_channel", "webhook_endpoint")
|
||||
VALUES
|
||||
(${name}, ${type}, ${project}, ${slack?.channel ?? null}, ${
|
||||
webhook?.endpoint ?? null
|
||||
})
|
||||
webhook?.endpoint ?? null
|
||||
})
|
||||
RETURNING *
|
||||
`,
|
||||
),
|
||||
|
|
@ -2930,8 +2930,8 @@ export async function createStorage(connection: string, maximumPoolSize: number)
|
|||
INSERT INTO "public"."schema_policy_config"
|
||||
("resource_type", "resource_id", "config", "allow_overriding")
|
||||
VALUES ('ORGANIZATION', ${input.organizationId}, ${sql.jsonb(input.policy)}, ${
|
||||
input.allowOverrides
|
||||
})
|
||||
input.allowOverrides
|
||||
})
|
||||
ON CONFLICT
|
||||
(resource_type, resource_id)
|
||||
DO UPDATE
|
||||
|
|
|
|||
|
|
@ -64,9 +64,9 @@ export async function createTokenStorage(connection: string, maximumPoolSize: nu
|
|||
(name, token, token_alias, target_id, project_id, organization_id, scopes)
|
||||
VALUES
|
||||
(${name}, ${token}, ${tokenAlias}, ${target}, ${project}, ${organization}, ${sql.array(
|
||||
scopes,
|
||||
'text',
|
||||
)})
|
||||
scopes,
|
||||
'text',
|
||||
)})
|
||||
RETURNING *
|
||||
`,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@ const NotFoundPage = () => {
|
|||
|
||||
<style jsx global>{`
|
||||
html {
|
||||
background: url(/images/bg-top-shine.svg) no-repeat left top,
|
||||
url(/images/bg-bottom-shine.svg) no-repeat right bottom, #0b0d11;
|
||||
background:
|
||||
url(/images/bg-top-shine.svg) no-repeat left top,
|
||||
url(/images/bg-bottom-shine.svg) no-repeat right bottom,
|
||||
#0b0d11;
|
||||
}
|
||||
|
||||
body {
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ const Navigation = (props: {
|
|||
}}
|
||||
scroll={false} // disable the scroll to top on page
|
||||
>
|
||||
<h3 className="truncate font-semibold text-sm">
|
||||
<h3 className="truncate text-sm font-semibold">
|
||||
{edge.node.meta?.commit ?? edge.node.id}
|
||||
</h3>
|
||||
{edge.node.meta?.author ? (
|
||||
|
|
@ -129,7 +129,7 @@ const Navigation = (props: {
|
|||
<span className="overflow-hidden truncate">{edge.node.meta.author}</span>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="mt-2.5 mb-1.5 flex align-middle text-xs font-medium text-[#c4c4c4]">
|
||||
<div className="mb-1.5 mt-2.5 flex align-middle text-xs font-medium text-[#c4c4c4]">
|
||||
<div
|
||||
className={cn(
|
||||
edge.node.__typename === 'FailedSchemaCheck' ? 'text-red-500' : null,
|
||||
|
|
@ -148,7 +148,7 @@ const Navigation = (props: {
|
|||
</NextLink>
|
||||
{edge.node.githubRepository && edge.node.meta ? (
|
||||
<a
|
||||
className="text-xs font-medium text-gray-500 hover:text-gray-400 ml-[-1px]"
|
||||
className="ml-[-1px] text-xs font-medium text-gray-500 hover:text-gray-400"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={`https://github.com/${edge.node.githubRepository}/commit/${edge.node.meta.commit}`}
|
||||
|
|
@ -476,16 +476,16 @@ const ActiveSchemaCheck = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="flex grow flex-col h-full">
|
||||
<div className="flex h-full grow flex-col">
|
||||
<div className="py-6">
|
||||
<Title>Check {schemaCheck.id}</Title>
|
||||
<Subtitle>Detailed view of the schema check</Subtitle>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex flex-row justify-between items-center font-medium gap-x-4 p-4 text-gray-400 rounded-md border-gray-800 border">
|
||||
<div className="flex flex-row items-center justify-between gap-x-4 rounded-md border border-gray-800 p-4 font-medium text-gray-400">
|
||||
<div>
|
||||
<div className="text-xs">Status</div>
|
||||
<div className="text-white text-sm font-semibold">
|
||||
<div className="text-sm font-semibold text-white">
|
||||
{schemaCheck.__typename === 'FailedSchemaCheck' ? <>Failed</> : <>Success</>}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -493,7 +493,7 @@ const ActiveSchemaCheck = ({
|
|||
<div className="ml-4">
|
||||
<div className="text-xs">Service</div>
|
||||
<div>
|
||||
<div className="text-white text-sm font-semibold">{schemaCheck.serviceName}</div>
|
||||
<div className="text-sm font-semibold text-white">{schemaCheck.serviceName}</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
@ -501,20 +501,20 @@ const ActiveSchemaCheck = ({
|
|||
<div className="text-xs">
|
||||
Triggered <TimeAgo date={schemaCheck.createdAt} />
|
||||
</div>
|
||||
<div className="text-white text-sm truncate">
|
||||
<div className="truncate text-sm text-white">
|
||||
by {schemaCheck.meta ? <>{schemaCheck.meta.author}</> : 'unknown'}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs">Commit</div>
|
||||
<div>
|
||||
<div className="text-white text-sm font-semibold truncate">
|
||||
<div className="truncate text-sm font-semibold text-white">
|
||||
{schemaCheck.meta?.commit ?? 'unknown'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{schemaCheck.__typename === 'FailedSchemaCheck' && schemaCheck.canBeApproved ? (
|
||||
<div className="mr-0 ml-auto pl-4">
|
||||
<div className="ml-auto mr-0 pl-4">
|
||||
{schemaCheck.canBeApprovedByViewer ? (
|
||||
<Button danger onClick={() => setIsApproveFailedSchemaCheckModalOpen(true)}>
|
||||
Approve
|
||||
|
|
@ -530,7 +530,7 @@ const ActiveSchemaCheck = ({
|
|||
<div className="ml-4">
|
||||
<div className="text-xs">Approved by</div>
|
||||
<div>
|
||||
<div className="text-white text-sm font-bold">
|
||||
<div className="text-sm font-bold text-white">
|
||||
{schemaCheck.approvedBy?.displayName ?? 'unknown'}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -539,7 +539,7 @@ const ActiveSchemaCheck = ({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pt-6 pb-1">
|
||||
<div className="pb-1 pt-6">
|
||||
<ToggleGroup.Root
|
||||
className="flex space-x-1 rounded-md bg-gray-900/50 text-gray-500"
|
||||
type="single"
|
||||
|
|
@ -552,7 +552,7 @@ const ActiveSchemaCheck = ({
|
|||
key={item.value}
|
||||
value={item.value}
|
||||
className={cn(
|
||||
'flex items-center rounded-md py-[0.4375rem] px-2 text-xs font-semibold hover:text-white',
|
||||
'flex items-center rounded-md px-2 py-[0.4375rem] text-xs font-semibold hover:text-white',
|
||||
view === item.value && 'bg-gray-800 text-white',
|
||||
)}
|
||||
title={item.tooltip}
|
||||
|
|
@ -824,7 +824,7 @@ function ChecksPageContent() {
|
|||
>
|
||||
<div
|
||||
className={cn(
|
||||
'flex w-full h-full',
|
||||
'flex h-full w-full',
|
||||
hasSchemaChecks || hasActiveSchemaCheck ? 'flex-row gap-x-6' : '',
|
||||
)}
|
||||
>
|
||||
|
|
@ -836,10 +836,10 @@ function ChecksPageContent() {
|
|||
{query.fetching || query.stale ? null : hasSchemaChecks ? (
|
||||
<div className="flex flex-col gap-5">
|
||||
<div>
|
||||
<div className="flex flex-row items-center justify-between h-9">
|
||||
<div className="flex h-9 flex-row items-center justify-between">
|
||||
<Label
|
||||
htmlFor="filter-toggle-has-changes"
|
||||
className="text-sm text-gray-100 font-normal"
|
||||
className="text-sm font-normal text-gray-100"
|
||||
>
|
||||
Show only changed schemas
|
||||
</Label>
|
||||
|
|
@ -854,10 +854,10 @@ function ChecksPageContent() {
|
|||
id="filter-toggle-has-changes"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-row items-center justify-between h-9">
|
||||
<div className="flex h-9 flex-row items-center justify-between">
|
||||
<Label
|
||||
htmlFor="filter-toggle-status-failed"
|
||||
className="text-sm text-gray-100 font-normal"
|
||||
className="text-sm font-normal text-gray-100"
|
||||
>
|
||||
Show only failed checks
|
||||
</Label>
|
||||
|
|
@ -888,14 +888,14 @@ function ChecksPageContent() {
|
|||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-sm cursor-default">
|
||||
<div className="cursor-default text-sm">
|
||||
No schema checks found with the current filters
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<div className="text-sm cursor-default">
|
||||
<div className="cursor-default text-sm">
|
||||
{hasActiveSchemaCheck ? 'List is empty' : 'Your schema check list is empty'}
|
||||
</div>
|
||||
<DocsLink href="/features/schema-registry#check-a-schema">
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ function ExplorerPageContent() {
|
|||
organizations={organizationConnection ?? null}
|
||||
isCDNEnabled={isCDNEnabled ?? null}
|
||||
>
|
||||
<div className="py-6 flex flex-row items-center justify-between">
|
||||
<div className="flex flex-row items-center justify-between py-6">
|
||||
<div>
|
||||
<Title>Explore</Title>
|
||||
<Subtitle>Insights from the latest version.</Subtitle>
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ function TypeExplorerPageContent({ typename }: { typename: string }) {
|
|||
organizations={organizationConnection ?? null}
|
||||
isCDNEnabled={isCDNEnabled ?? null}
|
||||
>
|
||||
<div className="py-6 flex flex-row items-center justify-between">
|
||||
<div className="flex flex-row items-center justify-between py-6">
|
||||
<div>
|
||||
<Title>Explore</Title>
|
||||
<Subtitle>Insights from the latest version.</Subtitle>
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ const UnusedSchemaView = memo(function _UnusedSchemaView(props: {
|
|||
'rounded-none px-2 py-1',
|
||||
letter === selectedLetter
|
||||
? 'text-orange-500'
|
||||
: 'hover:text-orange-500 text-gray-500',
|
||||
: 'text-gray-500 hover:text-orange-500',
|
||||
)}
|
||||
key={letter}
|
||||
>
|
||||
|
|
@ -210,7 +210,7 @@ function UnusedSchemaExplorer(props: {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="py-6 flex flex-row items-center justify-between">
|
||||
<div className="flex flex-row items-center justify-between py-6">
|
||||
<div>
|
||||
<Title>Unused Schema</Title>
|
||||
<Subtitle>
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ function ListPage({
|
|||
}}
|
||||
scroll={false} // disable the scroll to top on page
|
||||
>
|
||||
<h3 className="truncate font-semibold text-sm">
|
||||
<h3 className="truncate text-sm font-semibold">
|
||||
{'commit' in version.log
|
||||
? version.log.commit
|
||||
: `Deleted ${version.log.deletedService}`}
|
||||
|
|
@ -118,7 +118,7 @@ function ListPage({
|
|||
<span className="overflow-hidden truncate">{version.log.author}</span>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="mt-2.5 mb-1.5 flex align-middle text-xs font-medium text-[#c4c4c4]">
|
||||
<div className="mb-1.5 mt-2.5 flex align-middle text-xs font-medium text-[#c4c4c4]">
|
||||
<div className={cn(!version.valid && 'text-red-500')}>
|
||||
<Badge color={version.valid ? 'green' : 'red'} /> Published{' '}
|
||||
<TimeAgo date={version.date} />
|
||||
|
|
@ -133,7 +133,7 @@ function ListPage({
|
|||
</NextLink>
|
||||
{version.githubMetadata ? (
|
||||
<a
|
||||
className="text-xs font-medium text-gray-500 hover:text-gray-400 ml-[-1px]"
|
||||
className="ml-[-1px] text-xs font-medium text-gray-500 hover:text-gray-400"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={`https://github.com/${version.githubMetadata.repository}/commit/${version.githubMetadata.commit}`}
|
||||
|
|
@ -233,7 +233,7 @@ function ComparisonView({ versionId }: { versionId: string }) {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="flex flex-row items-center justify-between">
|
||||
<div className="py-6">
|
||||
<Title>Details</Title>
|
||||
<Subtitle>Explore details of the selected version</Subtitle>
|
||||
|
|
@ -241,7 +241,7 @@ function ComparisonView({ versionId }: { versionId: string }) {
|
|||
{availableViews.length ? (
|
||||
<div className="flex items-center justify-between">
|
||||
<ToggleGroup.Root
|
||||
className="flex space-x-1 rounded-md bg-gray-900/50 text-gray-500 p-0.5"
|
||||
className="flex space-x-1 rounded-md bg-gray-900/50 p-0.5 text-gray-500"
|
||||
type="single"
|
||||
defaultValue={availableViews[0]?.value}
|
||||
onValueChange={onViewChange}
|
||||
|
|
@ -252,7 +252,7 @@ function ComparisonView({ versionId }: { versionId: string }) {
|
|||
key={value}
|
||||
value={value}
|
||||
className={cn(
|
||||
'flex items-center rounded-md py-[0.4375rem] px-2 text-xs font-semibold hover:text-white',
|
||||
'flex items-center rounded-md px-2 py-[0.4375rem] text-xs font-semibold hover:text-white',
|
||||
view === value && 'bg-gray-800 text-white',
|
||||
)}
|
||||
title={tooltip}
|
||||
|
|
@ -266,9 +266,9 @@ function ComparisonView({ versionId }: { versionId: string }) {
|
|||
) : null}
|
||||
</div>
|
||||
<div className="flex h-full">
|
||||
<div className="grow rounded-md overflow-y-auto">
|
||||
<div className="grow overflow-y-auto rounded-md">
|
||||
{isLoading ? (
|
||||
<div className="flex w-full h-full justify-center items-center">
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : error ? (
|
||||
|
|
@ -328,7 +328,7 @@ function ComparisonView({ versionId }: { versionId: string }) {
|
|||
<CheckCircledIcon className="h-4 w-auto text-emerald-500" />
|
||||
<h2 className="text-base font-medium text-white">First composable version</h2>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Congratulations! This is the first version of the schema that is composable.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -403,7 +403,7 @@ function HistoryPageContent() {
|
|||
isCDNEnabled={isCDNEnabled ?? null}
|
||||
>
|
||||
{versionId ? (
|
||||
<div className="flex w-full h-full flex-row gap-x-6">
|
||||
<div className="flex h-full w-full flex-row gap-x-6">
|
||||
<div>
|
||||
<div className="py-6">
|
||||
<Title>Versions</Title>
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ function TargetSchemaPage() {
|
|||
organizations={organizationConnection ?? null}
|
||||
isCDNEnabled={isCDNEnabled ?? null}
|
||||
>
|
||||
<div className="py-6 flex flex-row items-center justify-between">
|
||||
<div className="flex flex-row items-center justify-between py-6">
|
||||
<div>
|
||||
<Title>Schema</Title>
|
||||
<Subtitle>The latest published schema.</Subtitle>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ function OperationsView({
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="py-6 flex flex-row items-center justify-between">
|
||||
<div className="flex flex-row items-center justify-between py-6">
|
||||
<div>
|
||||
<Title>Insights</Title>
|
||||
<Subtitle>Observe GraphQL requests and see how the API is consumed.</Subtitle>
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ function OperationView({
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="py-6 flex flex-row items-center justify-between">
|
||||
<div className="flex flex-row items-center justify-between py-6">
|
||||
<div>
|
||||
<Title>{operationName}</Title>
|
||||
<Subtitle>Insights of individual GraphQL operation</Subtitle>
|
||||
|
|
@ -127,7 +127,7 @@ function OperationView({
|
|||
resolution={resolution}
|
||||
mode="operation-page"
|
||||
/>
|
||||
<div className="w-full rounded-md bg-gray-900/50 p-5 border border-gray-800 mt-12">
|
||||
<div className="mt-12 w-full rounded-md border border-gray-800 bg-gray-900/50 p-5">
|
||||
<Section.Title>Operation body</Section.Title>
|
||||
<GraphQLOperationBody
|
||||
organization={organizationCleanId}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ function ClientView(props: {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="py-6 flex flex-row items-center justify-between">
|
||||
<div className="flex flex-row items-center justify-between py-6">
|
||||
<div>
|
||||
<Title>{props.clientName}</Title>
|
||||
<Subtitle>GraphQL API consumer insights</Subtitle>
|
||||
|
|
@ -135,13 +135,13 @@ function ClientView(props: {
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total calls</CardTitle>
|
||||
<GlobeIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<GlobeIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">
|
||||
{isLoading ? '-' : formatNumber(totalRequests)}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Requests in {displayDateRangeLabel(dateRangeKey).toLowerCase()}
|
||||
</p>
|
||||
</CardContent>
|
||||
|
|
@ -149,7 +149,7 @@ function ClientView(props: {
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Requests per minute</CardTitle>
|
||||
<ActivityIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<ActivityIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">
|
||||
|
|
@ -163,7 +163,7 @@ function ClientView(props: {
|
|||
),
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
RPM in {displayDateRangeLabel(dateRangeKey).toLowerCase()}
|
||||
</p>
|
||||
</CardContent>
|
||||
|
|
@ -171,11 +171,11 @@ function ClientView(props: {
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Operations</CardTitle>
|
||||
<BookIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<BookIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{isLoading ? '-' : totalOperations}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Documents requested by selected client
|
||||
</p>
|
||||
</CardContent>
|
||||
|
|
@ -183,11 +183,11 @@ function ClientView(props: {
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Versions</CardTitle>
|
||||
<HistoryIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<HistoryIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{isLoading ? '-' : totalVersions}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Versions in {displayDateRangeLabel(dateRangeKey).toLowerCase()}
|
||||
</p>
|
||||
</CardContent>
|
||||
|
|
@ -195,14 +195,14 @@ function ClientView(props: {
|
|||
</div>
|
||||
</div>
|
||||
<div className="col-span-4">
|
||||
<Card className="bg-gray-900/50 flex flex-col h-full">
|
||||
<Card className="flex h-full flex-col bg-gray-900/50">
|
||||
<CardHeader>
|
||||
<CardTitle>Activity</CardTitle>
|
||||
<CardDescription>
|
||||
GraphQL requests from {props.clientName} over time
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="basis-0 grow min-h-[150px]">
|
||||
<CardContent className="min-h-[150px] grow basis-0">
|
||||
<AutoSizer>
|
||||
{size => (
|
||||
<ReactECharts
|
||||
|
|
@ -269,7 +269,7 @@ function ClientView(props: {
|
|||
</div>
|
||||
</div>
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-7">
|
||||
<Card className="col-span-4 bg-gray-900/50 flex flex-col h-full">
|
||||
<Card className="col-span-4 flex h-full flex-col bg-gray-900/50">
|
||||
<CardHeader>
|
||||
<CardTitle>Operations</CardTitle>
|
||||
<CardDescription>
|
||||
|
|
@ -278,15 +278,15 @@ function ClientView(props: {
|
|||
{displayDateRangeLabel(dateRangeKey).toLowerCase()}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="basis-0 grow overflow-y-auto min-h-[120px]">
|
||||
<CardContent className="min-h-[120px] grow basis-0 overflow-y-auto">
|
||||
<div className="space-y-2">
|
||||
{isLoading
|
||||
? null
|
||||
: query.data?.clientStats.operations.nodes.map(operation => (
|
||||
<div key={operation.id} className="flex items-center">
|
||||
<p className="text-sm font-medium truncate">
|
||||
<p className="truncate text-sm font-medium">
|
||||
<Link
|
||||
className="text-orange-500 hover:underline hover:underline-offset-2 hover:text-orange-500"
|
||||
className="text-orange-500 hover:text-orange-500 hover:underline hover:underline-offset-2"
|
||||
href={{
|
||||
pathname:
|
||||
'/[organizationId]/[projectId]/[targetId]/insights/[operationName]/[operationHash]',
|
||||
|
|
@ -302,7 +302,7 @@ function ClientView(props: {
|
|||
{operation.name}
|
||||
</Link>
|
||||
</p>
|
||||
<div className="ml-auto font-light flex flex-row justify-end items-center text-sm min-w-[150px]">
|
||||
<div className="ml-auto flex min-w-[150px] flex-row items-center justify-end text-sm font-light">
|
||||
<div>{formatNumber(operation.count)}</div>{' '}
|
||||
<div className="min-w-[70px] text-right">
|
||||
{toDecimal((operation.count * 100) / totalRequests)}%
|
||||
|
|
@ -314,7 +314,7 @@ function ClientView(props: {
|
|||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="col-span-3 bg-gray-900/50 flex flex-col h-full">
|
||||
<Card className="col-span-3 flex h-full flex-col bg-gray-900/50">
|
||||
<CardHeader>
|
||||
<CardTitle>Versions</CardTitle>
|
||||
<CardDescription>
|
||||
|
|
@ -326,14 +326,14 @@ function ClientView(props: {
|
|||
: null}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="basis-0 grow overflow-y-auto min-h-[170px]">
|
||||
<CardContent className="min-h-[170px] grow basis-0 overflow-y-auto">
|
||||
<div className="space-y-2">
|
||||
{isLoading
|
||||
? null
|
||||
: query.data?.clientStats.versions.map(version => (
|
||||
<div key={version.version} className="flex items-center">
|
||||
<p className="text-sm font-medium truncate">{version.version}</p>
|
||||
<div className="ml-auto font-light flex flex-row justify-end items-center text-sm min-w-[150px]">
|
||||
<p className="truncate text-sm font-medium">{version.version}</p>
|
||||
<div className="ml-auto flex min-w-[150px] flex-row items-center justify-end text-sm font-light">
|
||||
<div>{formatNumber(version.count)}</div>
|
||||
<div className="min-w-[70px] text-right">
|
||||
{toDecimal((version.count * 100) / totalRequests)}%
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ function SchemaCoordinateView(props: {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="py-6 flex flex-row items-center justify-between">
|
||||
<div className="flex flex-row items-center justify-between py-6">
|
||||
<div>
|
||||
<Title>{props.coordinate}</Title>
|
||||
<Subtitle>Schema coordinate insights</Subtitle>
|
||||
|
|
@ -139,13 +139,13 @@ function SchemaCoordinateView(props: {
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Total calls</CardTitle>
|
||||
<GlobeIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<GlobeIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">
|
||||
{isLoading ? '-' : formatNumber(totalRequests)}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Requests in {displayDateRangeLabel(dateRangeKey).toLowerCase()}
|
||||
</p>
|
||||
</CardContent>
|
||||
|
|
@ -153,7 +153,7 @@ function SchemaCoordinateView(props: {
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Requests per minute</CardTitle>
|
||||
<ActivityIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<ActivityIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">
|
||||
|
|
@ -167,7 +167,7 @@ function SchemaCoordinateView(props: {
|
|||
),
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
RPM in {displayDateRangeLabel(dateRangeKey).toLowerCase()}
|
||||
</p>
|
||||
</CardContent>
|
||||
|
|
@ -175,11 +175,11 @@ function SchemaCoordinateView(props: {
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Operations</CardTitle>
|
||||
<BookIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<BookIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{isLoading ? '-' : totalOperations}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
GraphQL documents with selected coordinate
|
||||
</p>
|
||||
</CardContent>
|
||||
|
|
@ -187,11 +187,11 @@ function SchemaCoordinateView(props: {
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Consumers</CardTitle>
|
||||
<TabletSmartphoneIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<TabletSmartphoneIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{isLoading ? '-' : totalClients}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
GraphQL clients in {displayDateRangeLabel(dateRangeKey).toLowerCase()}
|
||||
</p>
|
||||
</CardContent>
|
||||
|
|
@ -199,14 +199,14 @@ function SchemaCoordinateView(props: {
|
|||
</div>
|
||||
</div>
|
||||
<div className="col-span-4">
|
||||
<Card className="bg-gray-900/50 flex flex-col h-full">
|
||||
<Card className="flex h-full flex-col bg-gray-900/50">
|
||||
<CardHeader>
|
||||
<CardTitle>Activity</CardTitle>
|
||||
<CardDescription>
|
||||
GraphQL requests with {props.coordinate} over time
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="basis-0 grow min-h-[150px]">
|
||||
<CardContent className="min-h-[150px] grow basis-0">
|
||||
<AutoSizer>
|
||||
{size => (
|
||||
<ReactECharts
|
||||
|
|
@ -273,7 +273,7 @@ function SchemaCoordinateView(props: {
|
|||
</div>
|
||||
</div>
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-7">
|
||||
<Card className="col-span-4 bg-gray-900/50 flex flex-col h-full">
|
||||
<Card className="col-span-4 flex h-full flex-col bg-gray-900/50">
|
||||
<CardHeader>
|
||||
<CardTitle>Operations</CardTitle>
|
||||
<CardDescription>
|
||||
|
|
@ -282,15 +282,15 @@ function SchemaCoordinateView(props: {
|
|||
{displayDateRangeLabel(dateRangeKey).toLowerCase()}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="basis-0 grow overflow-y-auto min-h-[120px]">
|
||||
<CardContent className="min-h-[120px] grow basis-0 overflow-y-auto">
|
||||
<div className="space-y-2">
|
||||
{isLoading
|
||||
? null
|
||||
: query.data?.schemaCoordinateStats.operations.nodes.map(operation => (
|
||||
<div key={operation.id} className="flex items-center">
|
||||
<p className="text-sm font-medium truncate">
|
||||
<p className="truncate text-sm font-medium">
|
||||
<Link
|
||||
className="text-orange-500 hover:underline hover:underline-offset-2 hover:text-orange-500"
|
||||
className="text-orange-500 hover:text-orange-500 hover:underline hover:underline-offset-2"
|
||||
href={{
|
||||
pathname:
|
||||
'/[organizationId]/[projectId]/[targetId]/insights/[operationName]/[operationHash]',
|
||||
|
|
@ -306,7 +306,7 @@ function SchemaCoordinateView(props: {
|
|||
{operation.name}
|
||||
</Link>
|
||||
</p>
|
||||
<div className="ml-auto font-light flex flex-row justify-end items-center text-sm min-w-[150px]">
|
||||
<div className="ml-auto flex min-w-[150px] flex-row items-center justify-end text-sm font-light">
|
||||
<div>{formatNumber(operation.count)}</div>{' '}
|
||||
<div className="min-w-[70px] text-right">
|
||||
{toDecimal((operation.count * 100) / totalRequests)}%
|
||||
|
|
@ -318,7 +318,7 @@ function SchemaCoordinateView(props: {
|
|||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="col-span-3 bg-gray-900/50 flex flex-col h-full">
|
||||
<Card className="col-span-3 flex h-full flex-col bg-gray-900/50">
|
||||
<CardHeader>
|
||||
<CardTitle>Clients</CardTitle>
|
||||
<CardDescription>
|
||||
|
|
@ -327,15 +327,15 @@ function SchemaCoordinateView(props: {
|
|||
{displayDateRangeLabel(dateRangeKey).toLowerCase()}.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="basis-0 grow overflow-y-auto min-h-[170px]">
|
||||
<CardContent className="min-h-[170px] grow basis-0 overflow-y-auto">
|
||||
<div className="space-y-2">
|
||||
{isLoading
|
||||
? null
|
||||
: query.data?.schemaCoordinateStats.clients.nodes.map(client => (
|
||||
<div key={client.name} className="flex items-center">
|
||||
<p className="text-sm font-medium truncate">
|
||||
<p className="truncate text-sm font-medium">
|
||||
<Link
|
||||
className="text-orange-500 hover:underline hover:underline-offset-2 hover:text-orange-500"
|
||||
className="text-orange-500 hover:text-orange-500 hover:underline hover:underline-offset-2"
|
||||
href={{
|
||||
pathname:
|
||||
'/[organizationId]/[projectId]/[targetId]/insights/client/[name]',
|
||||
|
|
@ -350,7 +350,7 @@ function SchemaCoordinateView(props: {
|
|||
{client.name}
|
||||
</Link>
|
||||
</p>
|
||||
<div className="ml-auto font-light flex flex-row justify-end items-center text-sm min-w-[150px]">
|
||||
<div className="ml-auto flex min-w-[150px] flex-row items-center justify-end text-sm font-light">
|
||||
<div>{formatNumber(client.count)}</div>
|
||||
<div className="min-w-[70px] text-right">
|
||||
{toDecimal((client.count * 100) / totalRequests)}%
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ const CollectionItem = (props: {
|
|||
const copyToClipboard = useClipboard();
|
||||
|
||||
return (
|
||||
<div key={props.node.id} className="flex justify-between items-center">
|
||||
<div key={props.node.id} className="flex items-center justify-between">
|
||||
<Link
|
||||
href={{
|
||||
pathname: '/[organizationId]/[projectId]/[targetId]/laboratory/[operationId]',
|
||||
|
|
@ -166,7 +166,7 @@ const CollectionItem = (props: {
|
|||
},
|
||||
}}
|
||||
className={cn(
|
||||
'hover:bg-gray-100/10 w-full rounded p-2 !text-gray-300',
|
||||
'w-full rounded p-2 !text-gray-300 hover:bg-gray-100/10',
|
||||
router.query.operation === props.node.id && 'bg-gray-100/10 text-white',
|
||||
)}
|
||||
onClick={ev => {
|
||||
|
|
@ -195,7 +195,7 @@ const CollectionItem = (props: {
|
|||
modal={false}
|
||||
>
|
||||
<GraphiQLDropdownMenu.Button
|
||||
className="graphiql-toolbar-button opacity-0 [div:hover>&]:opacity-100 transition [div:hover>&]:bg-transparent"
|
||||
className="graphiql-toolbar-button opacity-0 transition [div:hover>&]:bg-transparent [div:hover>&]:opacity-100"
|
||||
aria-label="More"
|
||||
data-cy="operation-3-dots"
|
||||
>
|
||||
|
|
@ -245,7 +245,7 @@ const AddCollectionItemButton = (props: { collectionId: string }): ReactElement
|
|||
return (
|
||||
<Button
|
||||
variant="link"
|
||||
className="py-0 px-2 text-gray-500 hover:text-white hover:no-underline"
|
||||
className="px-2 py-0 text-gray-500 hover:text-white hover:no-underline"
|
||||
onClick={async () => {
|
||||
const result = await createOperation({
|
||||
input: {
|
||||
|
|
@ -403,15 +403,15 @@ function useOperationCollectionsPlugin({
|
|||
)?.id;
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col">
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="flex justify-between">
|
||||
<Title>Collections</Title>
|
||||
</div>
|
||||
{loading ? (
|
||||
<div className="flex justify-center h-fit flex-1 items-center">
|
||||
<div className="flex items-center flex-col">
|
||||
<div className="flex h-fit flex-1 items-center justify-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<Spinner />
|
||||
<div className="text-xs mt-2">Loading collections</div>
|
||||
<div className="mt-2 text-xs">Loading collections</div>
|
||||
</div>
|
||||
</div>
|
||||
) : collections?.length ? (
|
||||
|
|
@ -480,10 +480,10 @@ function useOperationCollectionsPlugin({
|
|||
))}
|
||||
</Accordion>
|
||||
) : (
|
||||
<div className="flex justify-center h-fit flex-1 items-center">
|
||||
<div className="flex items-center flex-col">
|
||||
<div className="flex h-fit flex-1 items-center justify-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<BookmarkIcon width={30} height={30} />
|
||||
<div className="text-xs mt-2">There are no collections available.</div>
|
||||
<div className="mt-2 text-xs">There are no collections available.</div>
|
||||
{canEdit ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
|
|
@ -584,7 +584,7 @@ function Save(): ReactElement {
|
|||
<GraphiQLDropdownMenu.Content>
|
||||
<GraphiQLDropdownMenu.Item
|
||||
disabled={isSame}
|
||||
className={cx(isSame && 'cursor-default hover:bg-transparent text-gray-400')}
|
||||
className={cx(isSame && 'cursor-default text-gray-400 hover:bg-transparent')}
|
||||
onClick={async () => {
|
||||
if (!currentOperation || isSame) {
|
||||
return;
|
||||
|
|
@ -760,7 +760,7 @@ function LaboratoryPageContent() {
|
|||
organizations={organizationConnection ?? null}
|
||||
isCDNEnabled={isCDNEnabled ?? null}
|
||||
>
|
||||
<div className="py-6 flex">
|
||||
<div className="flex py-6">
|
||||
<div className="flex-1">
|
||||
<Title>Laboratory</Title>
|
||||
<Subtitle>Explore your GraphQL schema and run queries against your GraphQL API.</Subtitle>
|
||||
|
|
@ -793,7 +793,7 @@ function LaboratoryPageContent() {
|
|||
</Button>
|
||||
</div>
|
||||
<div className="self-end pt-2">
|
||||
<span className="text-xs font-bold mr-2">Query</span>
|
||||
<span className="mr-2 text-xs font-bold">Query</span>
|
||||
<ToggleGroup
|
||||
defaultValue="list"
|
||||
onValueChange={newValue => {
|
||||
|
|
@ -808,7 +808,7 @@ function LaboratoryPageContent() {
|
|||
value="mockApi"
|
||||
title="Use Mock Schema"
|
||||
className={clsx(
|
||||
'hover:text-white text-xs',
|
||||
'text-xs hover:text-white',
|
||||
!query.fetching &&
|
||||
actualSelectedApiEndpoint === 'mockApi' &&
|
||||
'bg-gray-800 text-white',
|
||||
|
|
@ -822,7 +822,7 @@ function LaboratoryPageContent() {
|
|||
value="linkedApi"
|
||||
title="Use API endpoint"
|
||||
className={clsx(
|
||||
'hover:text-white text-xs',
|
||||
'text-xs hover:text-white',
|
||||
!query.fetching &&
|
||||
actualSelectedApiEndpoint === 'linkedApi' &&
|
||||
'bg-gray-800 text-white',
|
||||
|
|
@ -888,7 +888,7 @@ function LaboratoryPageContent() {
|
|||
)
|
||||
}
|
||||
>
|
||||
<span className="text-xs font-normal pr-2 cursor-help">
|
||||
<span className="cursor-help pr-2 text-xs font-normal">
|
||||
{actualSelectedApiEndpoint === 'linkedApi'
|
||||
? 'Querying GraphQL API'
|
||||
: 'Querying Mock API'}
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ const ExtendBaseSchema = (props: { baseSchema: string }): ReactElement => {
|
|||
>
|
||||
Reset
|
||||
</Button>
|
||||
{isUnsaved && <span className="text-green-500 text-sm">Unsaved changes!</span>}
|
||||
{isUnsaved && <span className="text-sm text-green-500">Unsaved changes!</span>}
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -627,7 +627,7 @@ const ConditionalBreakingChanges = (): ReactElement => {
|
|||
{touched.targets && errors.targets && (
|
||||
<div className="text-red-500">{errors.targets}</div>
|
||||
)}
|
||||
<div className="mt-5 pl-5 py-2 space-y-2 border-l-2 border-l-gray-800 bg-gray-600/10 rounded text-gray-400">
|
||||
<div className="mt-5 space-y-2 rounded border-l-2 border-l-gray-800 bg-gray-600/10 py-2 pl-5 text-gray-400">
|
||||
<div>
|
||||
<div className="font-semibold">Example settings</div>
|
||||
<div className="text-sm">Removal of a field is considered breaking if</div>
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ const TargetCard = (props: {
|
|||
<Card
|
||||
as={NextLink}
|
||||
href={href}
|
||||
className="h-full pt-4 px-0 self-start hover:bg-gray-800/40 hover:shadow-md hover:shadow-gray-800/50 bg-gray-900/50"
|
||||
className="h-full self-start bg-gray-900/50 px-0 pt-4 hover:bg-gray-800/40 hover:shadow-md hover:shadow-gray-800/50"
|
||||
>
|
||||
<TooltipProvider>
|
||||
<div className="flex items-start gap-x-2">
|
||||
|
|
@ -153,12 +153,12 @@ const TargetCard = (props: {
|
|||
)}
|
||||
</AutoSizer>
|
||||
</div>
|
||||
<div className="flex flex-row gap-y-3 px-4 pt-4 justify-between items-center">
|
||||
<div className="flex flex-row items-center justify-between gap-y-3 px-4 pt-4">
|
||||
<div>
|
||||
{target ? (
|
||||
<h4 className="line-clamp-2 text-lg font-bold">{target.name}</h4>
|
||||
) : (
|
||||
<div className="w-48 h-4 py-2 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="h-4 w-48 animate-pulse rounded-full bg-gray-800 py-2" />
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col gap-y-2 py-1">
|
||||
|
|
@ -166,8 +166,8 @@ const TargetCard = (props: {
|
|||
<>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="flex flex-row gap-x-2 items-center">
|
||||
<Globe className="w-4 h-4 text-gray-500" />
|
||||
<div className="flex flex-row items-center gap-x-2">
|
||||
<Globe className="h-4 w-4 text-gray-500" />
|
||||
<div className="text-xs">
|
||||
{requestsInDateRange}{' '}
|
||||
{pluralize(totalNumberOfRequests, 'request', 'requests')}
|
||||
|
|
@ -180,8 +180,8 @@ const TargetCard = (props: {
|
|||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="flex flex-row gap-x-2 items-center">
|
||||
<History className="w-4 h-4 text-gray-500" />
|
||||
<div className="flex flex-row items-center gap-x-2">
|
||||
<History className="h-4 w-4 text-gray-500" />
|
||||
<div className="text-xs">
|
||||
{schemaVersionsInDateRange}{' '}
|
||||
{pluralize(totalNumberOfVersions, 'commit', 'commits')}
|
||||
|
|
@ -195,8 +195,8 @@ const TargetCard = (props: {
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className="w-16 h-2 my-1 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="w-16 h-2 my-1 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="my-1 h-2 w-16 animate-pulse rounded-full bg-gray-800" />
|
||||
<div className="my-1 h-2 w-16 animate-pulse rounded-full bg-gray-800" />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -275,7 +275,7 @@ const ProjectsPageContent = () => {
|
|||
<div
|
||||
className={cn(
|
||||
'grow',
|
||||
targets?.length === 0 ? '' : 'grid grid-cols-2 gap-5 items-stretch',
|
||||
targets?.length === 0 ? '' : 'grid grid-cols-2 items-stretch gap-5',
|
||||
)}
|
||||
>
|
||||
{targets ? (
|
||||
|
|
|
|||
|
|
@ -183,8 +183,8 @@ function ProjectPolicyContent() {
|
|||
currentState={currentProject.schemaPolicy}
|
||||
/>
|
||||
) : (
|
||||
<div className="text-gray-400 pl-1 text-sm font-bold">
|
||||
<p className="text-orange-500 inline-block mr-4">!</p>
|
||||
<div className="pl-1 text-sm font-bold text-gray-400">
|
||||
<p className="mr-4 inline-block text-orange-500">!</p>
|
||||
Organization settings does not allow projects to override policy. Please consult
|
||||
your organization administrator.
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -99,14 +99,14 @@ function GitHubIntegration(props: {
|
|||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex flex-row justify-between items-center rounded-sm mb-4 gap-x-4 text-sm text-muted-foreground">
|
||||
<div className="text-muted-foreground mb-4 flex flex-row items-center justify-between gap-x-4 rounded-sm text-sm">
|
||||
<div className="space-y-2">
|
||||
<div>
|
||||
<div className="mb-4">Here's how it will look like in your CI pipeline.</div>
|
||||
<div className="flex items-center gap-x-2 pl-1">
|
||||
<CheckIcon className="w-4 h-4 text-emerald-500" />
|
||||
<div className="bg-white w-6 h-6 flex items-center justify-center rounded-sm">
|
||||
<HiveLogo className="w-[80%] h-[80%]" />
|
||||
<CheckIcon className="h-4 w-4 text-emerald-500" />
|
||||
<div className="flex h-6 w-6 items-center justify-center rounded-sm bg-white">
|
||||
<HiveLogo className="h-[80%] w-[80%]" />
|
||||
</div>
|
||||
|
||||
<div className="font-semibold text-[#adbac7]">
|
||||
|
|
@ -116,13 +116,13 @@ function GitHubIntegration(props: {
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<ArrowBigDownDashIcon className="w-6 h-6" />
|
||||
<ArrowBigDownDashIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-x-2 pl-1">
|
||||
<CheckIcon className="w-4 h-4 text-emerald-500" />
|
||||
<div className="bg-white w-6 h-6 flex items-center justify-center rounded-sm">
|
||||
<HiveLogo className="w-[80%] h-[80%]" />
|
||||
<CheckIcon className="h-4 w-4 text-emerald-500" />
|
||||
<div className="flex h-6 w-6 items-center justify-center rounded-sm bg-white">
|
||||
<HiveLogo className="h-[80%] w-[80%]" />
|
||||
</div>
|
||||
|
||||
<div className="font-semibold text-[#adbac7]">
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ const ProjectCard = (props: {
|
|||
}
|
||||
: '#'
|
||||
}
|
||||
className="h-full pt-4 px-0 self-start hover:bg-gray-800/40 hover:shadow-md hover:shadow-gray-800/50 bg-gray-900/50"
|
||||
className="h-full self-start bg-gray-900/50 px-0 pt-4 hover:bg-gray-800/40 hover:shadow-md hover:shadow-gray-800/50"
|
||||
>
|
||||
<TooltipProvider>
|
||||
<div className="flex items-start gap-x-2">
|
||||
|
|
@ -174,16 +174,16 @@ const ProjectCard = (props: {
|
|||
)}
|
||||
</AutoSizer>
|
||||
</div>
|
||||
<div className="flex flex-row gap-y-3 px-4 pt-4 justify-between items-center">
|
||||
<div className="flex flex-row items-center justify-between gap-y-3 px-4 pt-4">
|
||||
{project ? (
|
||||
<div>
|
||||
<h4 className="line-clamp-2 text-lg font-bold">{project.name}</h4>
|
||||
<p className="text-gray-300 text-xs">{projectTypeFullNames[project.type]}</p>
|
||||
<p className="text-xs text-gray-300">{projectTypeFullNames[project.type]}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<div className="w-48 h-4 mb-4 py-2 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="w-24 h-2 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="mb-4 h-4 w-48 animate-pulse rounded-full bg-gray-800 py-2" />
|
||||
<div className="h-2 w-24 animate-pulse rounded-full bg-gray-800" />
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col gap-y-2 py-1">
|
||||
|
|
@ -191,8 +191,8 @@ const ProjectCard = (props: {
|
|||
<>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="flex flex-row gap-x-2 items-center">
|
||||
<Globe className="w-4 h-4 text-gray-500" />
|
||||
<div className="flex flex-row items-center gap-x-2">
|
||||
<Globe className="h-4 w-4 text-gray-500" />
|
||||
<div className="text-xs">
|
||||
{requestsInDateRange}{' '}
|
||||
{pluralize(totalNumberOfRequests, 'request', 'requests')}
|
||||
|
|
@ -205,8 +205,8 @@ const ProjectCard = (props: {
|
|||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="flex flex-row gap-x-2 items-center">
|
||||
<History className="w-4 h-4 text-gray-500" />
|
||||
<div className="flex flex-row items-center gap-x-2">
|
||||
<History className="h-4 w-4 text-gray-500" />
|
||||
<div className="text-xs">
|
||||
{schemaVersionsInDateRange}{' '}
|
||||
{pluralize(totalNumberOfVersions, 'commit', 'commits')}
|
||||
|
|
@ -220,8 +220,8 @@ const ProjectCard = (props: {
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className="w-16 h-2 my-1 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="w-16 h-2 my-1 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="my-1 h-2 w-16 animate-pulse rounded-full bg-gray-800" />
|
||||
<div className="my-1 h-2 w-16 animate-pulse rounded-full bg-gray-800" />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -341,7 +341,7 @@ function OrganizationPageContent() {
|
|||
docsUrl="/management/projects#create-a-new-project"
|
||||
/>
|
||||
) : (
|
||||
<div className="grid grid-cols-2 gap-5 items-stretch">
|
||||
<div className="grid grid-cols-2 items-stretch gap-5">
|
||||
{projects.nodes
|
||||
.sort((a, b) => {
|
||||
const diffOperations = b.totalRequests - a.totalRequests;
|
||||
|
|
@ -371,7 +371,7 @@ function OrganizationPageContent() {
|
|||
</div>
|
||||
)
|
||||
) : (
|
||||
<div className="grid grid-cols-2 gap-5 items-stretch">
|
||||
<div className="grid grid-cols-2 items-stretch gap-5">
|
||||
{Array.from({ length: 4 }).map((_, index) => (
|
||||
<ProjectCard
|
||||
key={index}
|
||||
|
|
|
|||
|
|
@ -478,7 +478,7 @@ function ManageSubscriptionPageContent() {
|
|||
me={me}
|
||||
>
|
||||
<div className="grow">
|
||||
<div className="py-6 flex flex-row justify-between items-center">
|
||||
<div className="flex flex-row items-center justify-between py-6">
|
||||
<div>
|
||||
<Title>Manage subscription</Title>
|
||||
<Subtitle>Manage your current plan and invoices.</Subtitle>
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ const MemberInvitationForm = ({
|
|||
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={handleSubmit} className="flex flex-row gap-2 items-center">
|
||||
<form onSubmit={handleSubmit} className="flex flex-row items-center gap-2">
|
||||
<Input
|
||||
style={{
|
||||
minWidth: '200px',
|
||||
|
|
@ -344,7 +344,7 @@ function PageContent(props: {
|
|||
disabled={checked.length === 0}
|
||||
>
|
||||
Delete {checked.length || ''}
|
||||
<TrashIcon className="ml-2 w-4 h-4" />
|
||||
<TrashIcon className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
{members?.map(node => {
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ function PolicyPageContent() {
|
|||
</>
|
||||
))}
|
||||
</p>
|
||||
<p className="py-2 text-muted-foreground font-semibold underline">
|
||||
<p className="text-muted-foreground py-2 font-semibold underline">
|
||||
Policy feature is only available for projects that are using the new registry
|
||||
model.
|
||||
</p>
|
||||
|
|
@ -184,7 +184,7 @@ function PolicyPageContent() {
|
|||
/>
|
||||
<label
|
||||
htmlFor="allowOverrides"
|
||||
className="inline-block ml-2 text-sm text-gray-300"
|
||||
className="ml-2 inline-block text-sm text-gray-300"
|
||||
>
|
||||
Allow projects to override or disable rules
|
||||
</label>
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ function SubscriptionPageContent() {
|
|||
me={me}
|
||||
>
|
||||
<div className="grow">
|
||||
<div className="py-6 flex flex-row justify-between items-center">
|
||||
<div className="flex flex-row items-center justify-between py-6">
|
||||
<div>
|
||||
<Title>Your subscription</Title>
|
||||
<Subtitle>Explore your current plan and usage.</Subtitle>
|
||||
|
|
|
|||
|
|
@ -142,10 +142,10 @@ function NewTicketForm(props: {
|
|||
}
|
||||
}}
|
||||
>
|
||||
<SheetContent className="h-full flex grow flex-col w-1/3 sm:w-1/2 md:w-1/3 max-w-none sm:max-w-none md:max-w-[500px]">
|
||||
<SheetContent className="flex h-full w-1/3 max-w-none grow flex-col sm:w-1/2 sm:max-w-none md:w-1/3 md:max-w-[500px]">
|
||||
<Form {...form}>
|
||||
<form
|
||||
className="h-full flex justify-between grow flex-col gap-y-4"
|
||||
className="flex h-full grow flex-col justify-between gap-y-4"
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
>
|
||||
<SheetHeader>
|
||||
|
|
@ -156,7 +156,7 @@ function NewTicketForm(props: {
|
|||
</SheetHeader>
|
||||
|
||||
<div className="flex flex-1">
|
||||
<div className="overflow-y-auto text-sm text-ellipsis w-full px-2 space-y-6">
|
||||
<div className="w-full space-y-6 overflow-y-auto text-ellipsis px-2 text-sm">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="priority"
|
||||
|
|
@ -235,7 +235,7 @@ function NewTicketForm(props: {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<SheetFooter className="flex flex-col sm:flex-col gap-y-2">
|
||||
<SheetFooter className="flex flex-col gap-y-2 sm:flex-col">
|
||||
<Button type="submit">Submit</Button>
|
||||
</SheetFooter>
|
||||
</form>
|
||||
|
|
@ -268,7 +268,7 @@ function SupportTicketRow(props: {
|
|||
<TableCell>
|
||||
<Button
|
||||
variant="link"
|
||||
className={cn(isSolved ? 'text-gray-500' : '', 'p-0 h-auto text-left')}
|
||||
className={cn(isSolved ? 'text-gray-500' : '', 'h-auto p-0 text-left')}
|
||||
asChild
|
||||
>
|
||||
<NextLink
|
||||
|
|
@ -290,7 +290,7 @@ function SupportTicketRow(props: {
|
|||
<TableCell className="w-[150px] text-center">
|
||||
<Priority level={ticket.priority} />
|
||||
</TableCell>
|
||||
<TableCell className="text-right w-[200px] text-xs">
|
||||
<TableCell className="w-[200px] text-right text-xs">
|
||||
<TimeAgo date={ticket.updatedAt} className="text-gray-500" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
|
@ -347,14 +347,14 @@ function Support(props: {
|
|||
return (
|
||||
<TooltipProvider>
|
||||
<div>
|
||||
<div className="py-6 flex flex-row justify-between items-center">
|
||||
<div className="flex flex-row items-center justify-between py-6">
|
||||
<div>
|
||||
<Title>Support</Title>
|
||||
<Subtitle>A list of support requests</Subtitle>
|
||||
</div>
|
||||
<div>
|
||||
<Button variant="outline" onClick={toggle}>
|
||||
<PencilIcon className="w-4 h-4 mr-2" />
|
||||
<PencilIcon className="mr-2 h-4 w-4" />
|
||||
New ticket
|
||||
</Button>
|
||||
<NewTicketForm
|
||||
|
|
|
|||
|
|
@ -128,16 +128,16 @@ function Comment({ node }: { node: FragmentType<typeof Comment_SupportTicketComm
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-row items-end space-x-2 w-full',
|
||||
'flex w-full flex-row items-end space-x-2',
|
||||
isSupport ? 'justify-end' : 'justify-start',
|
||||
)}
|
||||
>
|
||||
{isSupport ? null : <UserIcon className="w-6 h-6 text-orange-500" />}
|
||||
{isSupport ? null : <UserIcon className="h-6 w-6 text-orange-500" />}
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div
|
||||
className={cn(
|
||||
'p-2 rounded-lg inline-block bg-gray-800 text-foreground text-left max-w-[70%]',
|
||||
'text-foreground inline-block max-w-[70%] rounded-lg bg-gray-800 p-2 text-left',
|
||||
isSupport ? 'rounded-br-none' : 'rounded-bl-none',
|
||||
)}
|
||||
>
|
||||
|
|
@ -149,7 +149,7 @@ function Comment({ node }: { node: FragmentType<typeof Comment_SupportTicketComm
|
|||
</TooltipContent>
|
||||
</Tooltip>
|
||||
{isSupport ? (
|
||||
<img className="block w-6 h-6" src="/just-logo.svg" alt="GraphQL Hive logo" />
|
||||
<img className="block h-6 w-6" src="/just-logo.svg" alt="GraphQL Hive logo" />
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -199,12 +199,12 @@ function SupportTicket(props: {
|
|||
return (
|
||||
<TooltipProvider>
|
||||
<div className="py-6">
|
||||
<div className="flex flex-row justify-between items-start gap-x-6">
|
||||
<div className="flex flex-row items-start justify-between gap-x-6">
|
||||
<div className="flex-1 border-r border-gray-800 pr-6">
|
||||
<Title className="flex flex-row gap-x-2 items-center">
|
||||
<Title className="flex flex-row items-center gap-x-2">
|
||||
<Button
|
||||
variant="link"
|
||||
className="p-0 h-auto text-lg font-semibold tracking-tight"
|
||||
className="h-auto p-0 text-lg font-semibold tracking-tight"
|
||||
asChild
|
||||
>
|
||||
<NextLink
|
||||
|
|
@ -219,12 +219,12 @@ function SupportTicket(props: {
|
|||
</NextLink>
|
||||
</Button>
|
||||
<span className="text-lg font-semibold tracking-tight text-gray-500">
|
||||
<ChevronRightIcon className="w-4 h-4" />
|
||||
<ChevronRightIcon className="h-4 w-4" />
|
||||
</span>
|
||||
<span>{ticket.subject}</span>
|
||||
</Title>
|
||||
<Subtitle>Support ticket detailed view</Subtitle>
|
||||
<div className="py-12 space-y-6">
|
||||
<div className="space-y-6 py-12">
|
||||
{comments.map(comment => (
|
||||
<Comment key={comment.node.id} node={comment.node} />
|
||||
))}
|
||||
|
|
@ -238,28 +238,28 @@ function SupportTicket(props: {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm shrink-0 w-1/3">
|
||||
<div className="w-1/3 shrink-0 text-sm">
|
||||
<div className="flex flex-col gap-y-6 text-left">
|
||||
<div className="space-y-0">
|
||||
<div className="text-white font-semibold">Support Ticket ID</div>
|
||||
<div className="font-semibold text-white">Support Ticket ID</div>
|
||||
<div className="text-muted-foreground">{ticket.id}</div>
|
||||
</div>
|
||||
<div className="space-y-0">
|
||||
<div className="text-white font-semibold">Status</div>
|
||||
<div className="font-semibold text-white">Status</div>
|
||||
<div className="text-muted-foreground">
|
||||
{ticket.status}
|
||||
<div className="text-xs">{statusDescription[ticket.status]}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-0">
|
||||
<div className="text-white font-semibold">Priority</div>
|
||||
<div className="font-semibold text-white">Priority</div>
|
||||
<div className="text-muted-foreground">
|
||||
{ticket.priority}
|
||||
<div className="text-xs">{priorityDescription[ticket.priority]}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-0">
|
||||
<div className="text-white font-semibold">Last updated</div>
|
||||
<div className="font-semibold text-white">Last updated</div>
|
||||
<div>
|
||||
<TimeAgo date={ticket.updatedAt} className="text-xs text-gray-500" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import '@/config/frontend-env';
|
|||
export default class MyDocument extends Document<{
|
||||
ids: Array<string>;
|
||||
css: string;
|
||||
frontendEnv: typeof import('@/config/frontend-env')['env'];
|
||||
frontendEnv: (typeof import('@/config/frontend-env'))['env'];
|
||||
}> {
|
||||
static async getInitialProps(ctx: DocumentContext) {
|
||||
if (globalThis.process.env.BUILD !== '1') {
|
||||
|
|
|
|||
|
|
@ -15,21 +15,21 @@ const IndexPage = (): ReactElement => {
|
|||
flex h-screen
|
||||
w-1/3
|
||||
flex-col
|
||||
bg-gray-800/10 pt-[30px] pl-[30px] pb-[50px] pr-[50px]
|
||||
bg-gray-800/10 pb-[50px] pl-[30px] pr-[50px] pt-[30px]
|
||||
"
|
||||
>
|
||||
<GuildLink textClassName="flex-col" />
|
||||
<div className="mt-[50px] grow rounded-[30px] bg-gray-800/30" />
|
||||
<Heading size="2xl" className="mt-[22px] mb-[5px]">
|
||||
<Heading size="2xl" className="mb-[5px] mt-[22px]">
|
||||
Hive
|
||||
</Heading>
|
||||
<p className="font-light text-gray-500">Open GraphQL Platform</p>
|
||||
</div>
|
||||
|
||||
<div className="grow px-9 pt-11 pb-9">
|
||||
<div className="grow px-9 pb-9 pt-11">
|
||||
<div className="mx-auto flex w-[500px] flex-col">
|
||||
<HiveLink />
|
||||
<h2 className="mt-20 mb-1 text-2xl font-light text-white">
|
||||
<h2 className="mb-1 mt-20 text-2xl font-light text-white">
|
||||
{isLoginPage ? 'Log In' : 'Create an account'}
|
||||
</h2>
|
||||
<p className="font-light text-[#9b9b9b]">
|
||||
|
|
@ -60,18 +60,18 @@ const IndexPage = (): ReactElement => {
|
|||
<hr className="grow border-gray-800" />
|
||||
</div>
|
||||
<Input placeholder="Email" />
|
||||
<Input placeholder="Password" type="password" className="mt-7 mb-1" />
|
||||
<Input placeholder="Password" type="password" className="mb-1 mt-7" />
|
||||
<Link
|
||||
variant="primary"
|
||||
href="#"
|
||||
className={clsx('ml-auto mb-11', !isLoginPage && 'invisible')}
|
||||
className={clsx('mb-11 ml-auto', !isLoginPage && 'invisible')}
|
||||
>
|
||||
Forgot password?
|
||||
</Link>
|
||||
<Button size="large" variant="primary" block>
|
||||
{isLoginPage ? 'Log In' : 'Create Account'}
|
||||
</Button>
|
||||
<GuildLink className="mx-auto mt-20 mb-6 opacity-10 transition hover:opacity-100" />
|
||||
<GuildLink className="mx-auto mb-6 mt-20 opacity-10 transition hover:opacity-100" />
|
||||
<p className={clsx('mb-4 text-xs text-[#9b9b9b]', isLoginPage && 'invisible')}>
|
||||
Creating an account means you're okay with our{' '}
|
||||
<Link variant="primary" href="#">
|
||||
|
|
|
|||
|
|
@ -103,8 +103,8 @@ function OrganizationTransferPage() {
|
|||
<Title title="Organization Transfer" />
|
||||
<DataWrapper query={query}>
|
||||
{({ data }) => (
|
||||
<div className="w-full h-full flex flex-row items-center justify-center">
|
||||
<div className="flex flex-col text-center md:w-2/3 w-full">
|
||||
<div className="flex h-full w-full flex-row items-center justify-center">
|
||||
<div className="flex w-full flex-col text-center md:w-2/3">
|
||||
{data.organizationTransferRequest == null ? (
|
||||
<>
|
||||
<h1 className={classes.title}>Organization Transfer Error</h1>
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ export default function Auth(props: { oidcProviderId: string | null }): ReactEle
|
|||
color={{ main: '#fff', sub: '#fff' }}
|
||||
/>
|
||||
{props.oidcProviderId ? (
|
||||
<div className=" p-5 bg-white rounded-md max-w-md mx-auto text-center">
|
||||
<div className=" mx-auto max-w-md rounded-md bg-white p-5 text-center">
|
||||
{error ? (
|
||||
<>
|
||||
<div className="text-red-500">{error}</div>
|
||||
|
|
@ -124,7 +124,7 @@ export default function Auth(props: { oidcProviderId: string | null }): ReactEle
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<Spinner className="w-20 h-20 mx-auto" />
|
||||
<Spinner className="mx-auto h-20 w-20" />
|
||||
<div className="mt-3">Starting OIDC Login Flow.</div>
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ function JoinOrganizationPage() {
|
|||
const invitation = data.organizationByInviteCode;
|
||||
|
||||
return (
|
||||
<div className="w-full h-full flex flex-row items-center justify-center">
|
||||
<div className="flex flex-col text-center md:w-2/3 w-full">
|
||||
<div className="flex h-full w-full flex-row items-center justify-center">
|
||||
<div className="flex w-full flex-col text-center md:w-2/3">
|
||||
{invitation.__typename === 'OrganizationInvitationError' ? (
|
||||
<>
|
||||
<h1 className={classes.title}>Invitation Error</h1>
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ function CreateOrgPage(): ReactElement {
|
|||
return (
|
||||
<>
|
||||
<MetaTitle title="Create Organization" />
|
||||
<div className="h-full grow flex items-center">
|
||||
<div className="flex h-full grow items-center">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => router.push('/logout')}
|
||||
className="absolute top-6 right-6"
|
||||
className="absolute right-6 top-6"
|
||||
>
|
||||
<LogOutIcon className="mr-2 h-4 w-4" /> Sign out
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -81,7 +81,9 @@
|
|||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
font-feature-settings: 'rlig' 1, 'calt' 1;
|
||||
font-feature-settings:
|
||||
'rlig' 1,
|
||||
'calt' 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +116,9 @@
|
|||
input:-webkit-autofill:hover,
|
||||
input:-webkit-autofill:focus,
|
||||
input:-webkit-autofill:active {
|
||||
-webkit-transition: color 9999s ease-out, background-color 9999s ease-out;
|
||||
-webkit-transition:
|
||||
color 9999s ease-out,
|
||||
background-color 9999s ease-out;
|
||||
-webkit-transition-delay: 9999s;
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +157,9 @@
|
|||
|
||||
.hive-modal {
|
||||
transform: translate(-50%, -50%);
|
||||
box-shadow: hsl(206 22% 7% / 35%) 0 10px 38px -10px, hsl(206 22% 7% / 20%) 0 10px 20px -15px;
|
||||
box-shadow:
|
||||
hsl(206 22% 7% / 35%) 0 10px 38px -10px,
|
||||
hsl(206 22% 7% / 20%) 0 10px 20px -15px;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ function OrganizationTable({ data }: { data: Organization[] }) {
|
|||
</TBody>
|
||||
</Table>
|
||||
|
||||
<div className="py-3 flex flex-row items-center justify-center gap-4">
|
||||
<div className="flex flex-row items-center justify-center gap-4 py-3">
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={firstPage}
|
||||
|
|
@ -362,9 +362,9 @@ function OrganizationTable({ data }: { data: Organization[] }) {
|
|||
onClick={tableInstance.previousPage}
|
||||
disabled={!tableInstance.getCanPreviousPage()}
|
||||
>
|
||||
<ChevronUpIcon className="-rotate-90 h-5 w-auto" />
|
||||
<ChevronUpIcon className="h-5 w-auto -rotate-90" />
|
||||
</Button>
|
||||
<span className="font-bold whitespace-nowrap text-sm">
|
||||
<span className="whitespace-nowrap text-sm font-bold">
|
||||
{tableInstance.getState().pagination.pageIndex + 1} / {tableInstance.getPageCount()}
|
||||
</span>
|
||||
<Button
|
||||
|
|
@ -373,7 +373,7 @@ function OrganizationTable({ data }: { data: Organization[] }) {
|
|||
onClick={tableInstance.nextPage}
|
||||
disabled={!tableInstance.getCanNextPage()}
|
||||
>
|
||||
<ChevronUpIcon className="rotate-90 h-5 w-auto" />
|
||||
<ChevronUpIcon className="h-5 w-auto rotate-90" />
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={lastPage} disabled={!tableInstance.getCanNextPage()}>
|
||||
Last
|
||||
|
|
@ -444,7 +444,7 @@ export function AdminStats({
|
|||
<DataWrapper query={query}>
|
||||
{({ data }) => (
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="flex rounded-md p-5 border border-gray-800 bg-gray-900/50 justify-between">
|
||||
<div className="flex justify-between rounded-md border border-gray-800 bg-gray-900/50 p-5">
|
||||
<OverallStat label="Users" value={overall.users} />
|
||||
<OverallStat label="Organizations" value={overall.organizations} />
|
||||
<OverallStat label="Projects" value={overall.projects} />
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@ export const LoadingAPIIndicator = memo(() => {
|
|||
|
||||
if (!isFetching) return null;
|
||||
|
||||
return <div className="hive-loading-indicator w-1/2 fixed h-1.5 will-change-transform" />;
|
||||
return <div className="hive-loading-indicator fixed h-1.5 w-1/2 will-change-transform" />;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@ export function Label({ className, children, ...props }: ComponentProps<'span'>)
|
|||
className={clsx(
|
||||
`
|
||||
inline-block
|
||||
py-1 px-2
|
||||
rounded
|
||||
bg-yellow-50 dark:bg-white/10
|
||||
text-yellow-600 dark:text-yellow-300
|
||||
text-xs font-medium tracking-widest`,
|
||||
rounded bg-yellow-50
|
||||
px-2
|
||||
py-1 text-xs
|
||||
font-medium tracking-widest
|
||||
text-yellow-600 dark:bg-white/10 dark:text-yellow-300`,
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -47,11 +47,11 @@ export const Page = ({
|
|||
className?: string;
|
||||
}): ReactElement => {
|
||||
return (
|
||||
<div className={clsx('flex flex-col relative h-full', className)}>
|
||||
<div className="p-4 shrink-0 flex flex-row justify-between items-center">
|
||||
<div className={clsx('relative flex h-full flex-col', className)}>
|
||||
<div className="flex shrink-0 flex-row items-center justify-between p-4">
|
||||
<div>
|
||||
<h2 className="text-xl text-black dark:text-white font-bold">{title}</h2>
|
||||
<span className="text-sm text-gray-600 dark:text-gray-300 mt-2">{subtitle}</span>
|
||||
<h2 className="text-xl font-bold text-black dark:text-white">{title}</h2>
|
||||
<span className="mt-2 text-sm text-gray-600 dark:text-gray-300">{subtitle}</span>
|
||||
</div>
|
||||
<div className="flex flex-row items-center space-x-2">{actions}</div>
|
||||
</div>
|
||||
|
|
@ -73,12 +73,12 @@ export const Page = ({
|
|||
|
||||
export const Section = {
|
||||
Title: ({ className, children, ...props }: ComponentProps<'h3'>): ReactElement => (
|
||||
<h3 className={clsx('text-base text-black dark:text-white font-bold', className)} {...props}>
|
||||
<h3 className={clsx('text-base font-bold text-black dark:text-white', className)} {...props}>
|
||||
{children}
|
||||
</h3>
|
||||
),
|
||||
BigTitle: ({ className, children, ...props }: ComponentProps<'h2'>): ReactElement => (
|
||||
<h2 className={clsx('text-base text-black dark:text-white font-bold', className)} {...props}>
|
||||
<h2 className={clsx('text-base font-bold text-black dark:text-white', className)} {...props}>
|
||||
{children}
|
||||
</h2>
|
||||
),
|
||||
|
|
@ -101,11 +101,11 @@ export function Scale({
|
|||
className?: string;
|
||||
}): ReactElement {
|
||||
return (
|
||||
<div className={clsx('flex flex-row space-x-1 grow-0', className)}>
|
||||
<div className={clsx('flex grow-0 flex-row space-x-1', className)}>
|
||||
{new Array(size).fill(null).map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={clsx('w-1 h-4', value >= i * (max / size) ? 'bg-emerald-400' : 'bg-gray-200')}
|
||||
className={clsx('h-4 w-1', value >= i * (max / size) ? 'bg-emerald-400' : 'bg-gray-200')}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ export function GetStartedProgress(props: {
|
|||
{remaining} remaining task{remaining > 1 ? 's' : ''}
|
||||
</div>
|
||||
<div>
|
||||
<div className="relative mt-1 w-full overflow-hidden rounded bg-gray-800 h-[5px]">
|
||||
<div className="relative mt-1 h-[5px] w-full overflow-hidden rounded bg-gray-800">
|
||||
<div
|
||||
className="h-full bg-orange-500"
|
||||
style={{ width: `${(completed / total) * 100}%` }}
|
||||
|
|
@ -136,7 +136,7 @@ function Task({
|
|||
className={clsx('h-5 w-auto', completed ? 'text-green-500' : 'text-gray-500')}
|
||||
/>
|
||||
|
||||
<span className={completed ? 'opacity-50 line-through' : 'hover:opacity-80'}>{children}</span>
|
||||
<span className={completed ? 'line-through opacity-50' : 'hover:opacity-80'}>{children}</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ export function OrganizationLayout({
|
|||
<header>
|
||||
<div className="container flex h-[84px] items-center justify-between">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<HiveLink className="w-8 h-8" />
|
||||
<HiveLink className="h-8 w-8" />
|
||||
{currentOrganization && organizations ? (
|
||||
<Select
|
||||
defaultValue={currentOrganization.cleanId}
|
||||
|
|
@ -123,7 +123,7 @@ export function OrganizationLayout({
|
|||
</SelectContent>
|
||||
</Select>
|
||||
) : (
|
||||
<div className="w-48 h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="h-5 w-48 animate-pulse rounded-full bg-gray-800" />
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -136,7 +136,7 @@ export function OrganizationLayout({
|
|||
</div>
|
||||
</header>
|
||||
<div className="relative border-b border-gray-800">
|
||||
<div className="container flex justify-between items-center">
|
||||
<div className="container flex items-center justify-between">
|
||||
{currentOrganization && meInCurrentOrg ? (
|
||||
<Tabs value={page}>
|
||||
<Tabs.List>
|
||||
|
|
@ -230,10 +230,10 @@ export function OrganizationLayout({
|
|||
</Tabs.List>
|
||||
</Tabs>
|
||||
) : (
|
||||
<div className="flex flex-row gap-x-8 px-4 py-3 border-b-[2px] border-b-transparent">
|
||||
<div className="w-12 h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="w-12 h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="w-12 h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="flex flex-row gap-x-8 border-b-[2px] border-b-transparent px-4 py-3">
|
||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
</div>
|
||||
)}
|
||||
{currentOrganization ? (
|
||||
|
|
|
|||
|
|
@ -117,23 +117,23 @@ export function ProjectLayout({
|
|||
<header>
|
||||
<div className="container flex h-[84px] items-center justify-between">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<HiveLink className="w-8 h-8" />
|
||||
<HiveLink className="h-8 w-8" />
|
||||
{currentOrganization ? (
|
||||
<NextLink
|
||||
href={{
|
||||
pathname: '/[organizationId]',
|
||||
query: { organizationId: currentOrganization.cleanId },
|
||||
}}
|
||||
className="shrink-0 font-medium truncate max-w-[200px]"
|
||||
className="max-w-[200px] shrink-0 truncate font-medium"
|
||||
>
|
||||
{currentOrganization.name}
|
||||
</NextLink>
|
||||
) : (
|
||||
<div className="w-48 max-w-[200px] h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="h-5 w-48 max-w-[200px] animate-pulse rounded-full bg-gray-800" />
|
||||
)}
|
||||
{projects?.length && currentProject ? (
|
||||
<>
|
||||
<div className="text-gray-500 italic">/</div>
|
||||
<div className="italic text-gray-500">/</div>
|
||||
<Select
|
||||
defaultValue={currentProject.cleanId}
|
||||
onValueChange={id => {
|
||||
|
|
@ -156,7 +156,7 @@ export function ProjectLayout({
|
|||
</Select>
|
||||
</>
|
||||
) : (
|
||||
<div className="w-48 h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="h-5 w-48 animate-pulse rounded-full bg-gray-800" />
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -174,7 +174,7 @@ export function ProjectLayout({
|
|||
)}
|
||||
|
||||
<div className="relative border-b border-gray-800">
|
||||
<div className="container flex justify-between items-center">
|
||||
<div className="container flex items-center justify-between">
|
||||
{currentOrganization && currentProject ? (
|
||||
<Tabs value={page}>
|
||||
<Tabs.List>
|
||||
|
|
@ -242,10 +242,10 @@ export function ProjectLayout({
|
|||
</Tabs.List>
|
||||
</Tabs>
|
||||
) : (
|
||||
<div className="flex flex-row gap-x-8 px-4 py-3 border-b-[2px] border-b-transparent">
|
||||
<div className="w-12 h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="w-12 h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="w-12 h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="flex flex-row gap-x-8 border-b-[2px] border-b-transparent px-4 py-3">
|
||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
</div>
|
||||
)}
|
||||
{currentProject ? (
|
||||
|
|
@ -257,7 +257,7 @@ export function ProjectLayout({
|
|||
<CreateTargetModal isOpen={isModalOpen} toggleModalOpen={toggleModalOpen} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="container pb-7 h-full">
|
||||
<div className="container h-full pb-7">
|
||||
<div className={className}>{children}</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ export const TargetLayout = ({
|
|||
<header>
|
||||
<div className="container flex h-[84px] items-center justify-between">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<HiveLink className="w-8 h-8" />
|
||||
<HiveLink className="h-8 w-8" />
|
||||
{currentOrganization ? (
|
||||
<NextLink
|
||||
href={{
|
||||
|
|
@ -154,14 +154,14 @@ export const TargetLayout = ({
|
|||
organizationId: currentOrganization.cleanId,
|
||||
},
|
||||
}}
|
||||
className="shrink-0 font-medium truncate max-w-[200px]"
|
||||
className="max-w-[200px] shrink-0 truncate font-medium"
|
||||
>
|
||||
{currentOrganization.name}
|
||||
</NextLink>
|
||||
) : (
|
||||
<div className="w-48 max-w-[200px] h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="h-5 w-48 max-w-[200px] animate-pulse rounded-full bg-gray-800" />
|
||||
)}
|
||||
<div className="text-gray-500 italic">/</div>
|
||||
<div className="italic text-gray-500">/</div>
|
||||
{currentOrganization && currentProject ? (
|
||||
<NextLink
|
||||
href={{
|
||||
|
|
@ -171,14 +171,14 @@ export const TargetLayout = ({
|
|||
projectId: currentProject.cleanId,
|
||||
},
|
||||
}}
|
||||
className="shrink-0 font-medium truncate max-w-[200px]"
|
||||
className="max-w-[200px] shrink-0 truncate font-medium"
|
||||
>
|
||||
{currentProject.name}
|
||||
</NextLink>
|
||||
) : (
|
||||
<div className="w-48 max-w-[200px] h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="h-5 w-48 max-w-[200px] animate-pulse rounded-full bg-gray-800" />
|
||||
)}
|
||||
<div className="text-gray-500 italic">/</div>
|
||||
<div className="italic text-gray-500">/</div>
|
||||
{targets?.length && currentOrganization && currentProject && currentTarget ? (
|
||||
<>
|
||||
<Select
|
||||
|
|
@ -204,7 +204,7 @@ export const TargetLayout = ({
|
|||
</Select>
|
||||
</>
|
||||
) : (
|
||||
<div className="w-48 max-w-[200px] h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="h-5 w-48 max-w-[200px] animate-pulse rounded-full bg-gray-800" />
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -222,7 +222,7 @@ export const TargetLayout = ({
|
|||
) : null}
|
||||
|
||||
<div className="relative border-b border-gray-800">
|
||||
<div className="container flex justify-between items-center">
|
||||
<div className="container flex items-center justify-between">
|
||||
{currentOrganization && currentProject && currentTarget ? (
|
||||
<Tabs className="flex h-full grow flex-col" value={page}>
|
||||
<Tabs.List>
|
||||
|
|
@ -333,10 +333,10 @@ export const TargetLayout = ({
|
|||
</Tabs.List>
|
||||
</Tabs>
|
||||
) : (
|
||||
<div className="flex flex-row gap-x-8 px-4 py-3 border-b-[2px] border-b-transparent">
|
||||
<div className="w-12 h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="w-12 h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="w-12 h-5 bg-gray-800 rounded-full animate-pulse" />
|
||||
<div className="flex flex-row gap-x-8 border-b-[2px] border-b-transparent px-4 py-3">
|
||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
<div className="h-5 w-12 animate-pulse rounded-full bg-gray-800" />
|
||||
</div>
|
||||
)}
|
||||
{currentTarget ? (
|
||||
|
|
@ -355,9 +355,9 @@ export const TargetLayout = ({
|
|||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="container pb-7 h-full">
|
||||
<div className={cn('flex justify-between gap-12 h-full', className)}>
|
||||
<div className="grow flex flex-col">{children}</div>
|
||||
<div className="container h-full pb-7">
|
||||
<div className={cn('flex h-full justify-between gap-12', className)}>
|
||||
<div className="flex grow flex-col">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ export const PermissionScopeItem = <
|
|||
<div
|
||||
key={props.scope.name}
|
||||
className={clsx(
|
||||
'py-2 flex flex-row justify-between items-center',
|
||||
'flex flex-row items-center justify-between py-2',
|
||||
props.canManageScope === false ? 'opacity-50' : null,
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export function OrganizationUsageEstimationView(props: {
|
|||
});
|
||||
|
||||
return (
|
||||
<div className="top-7 right-4">
|
||||
<div className="right-4 top-7">
|
||||
<DataWrapper query={query}>
|
||||
{result => (
|
||||
<Table>
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ function Plan(plan: {
|
|||
{plan.features.map((feature, i) => (
|
||||
<div key={i}>
|
||||
<Section.Subtitle className="flex items-center gap-1">
|
||||
<CheckIcon className="text-gray-500 h-5 w-auto" />
|
||||
<CheckIcon className="h-5 w-auto text-gray-500" />
|
||||
{feature}
|
||||
</Section.Subtitle>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export function ProPlanBilling(props: {
|
|||
const organization = useFragment(ProPlanBilling_OrganizationFragment, props.organization);
|
||||
if (organization?.billingConfiguration?.hasPaymentIssues) {
|
||||
return (
|
||||
<Callout type="warning" className="w-full mb-2">
|
||||
<Callout type="warning" className="mb-2 w-full">
|
||||
<b>Your organization has a rejected payment!</b>
|
||||
<br />
|
||||
Please review your recent invoices and update your payment method.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export function RateLimitWarn(props: {
|
|||
|
||||
if (organization.plan === BillingPlanType.Enterprise) {
|
||||
return (
|
||||
<Callout type="warning" className="w-full mb-2">
|
||||
<Callout type="warning" className="mb-2 w-full">
|
||||
<b>Your organization has reached it's contract limit.</b>
|
||||
<br />
|
||||
The data under your organization is still being processed and no data will be lost.
|
||||
|
|
@ -34,7 +34,7 @@ export function RateLimitWarn(props: {
|
|||
}
|
||||
|
||||
return (
|
||||
<Callout type="warning" className="w-full mb-2">
|
||||
<Callout type="warning" className="mb-2 w-full">
|
||||
<b>Your organization is being rate-limited for operations.</b>
|
||||
<br />
|
||||
Since you have reached your organization rate-limit and data ingestion limitation, your
|
||||
|
|
|
|||
|
|
@ -606,7 +606,7 @@ function RemoveOIDCIntegrationModal(props: {
|
|||
</>
|
||||
) : (
|
||||
<>
|
||||
<Tag color="yellow" className="py-2.5 px-4">
|
||||
<Tag color="yellow" className="px-4 py-2.5">
|
||||
<AlertTriangleIcon className="h-5 w-5" />
|
||||
<p className="ml-3">
|
||||
This action is not reversible and <b>deletes all users</b> that have signed in with
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@ export function PolicyConfigBox(props: Props) {
|
|||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'px-4 items-center font-mono pb-2',
|
||||
'items-center px-4 pb-2 font-mono',
|
||||
'title' in props ? undefined : 'flex',
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
{'title' in props ? (
|
||||
<>
|
||||
<div className="text-xs pb-1 text-gray-600">{props.title}</div>
|
||||
<div className="pb-1 text-xs text-gray-600">{props.title}</div>
|
||||
<div>{props.children}</div>
|
||||
</>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ export function PolicyListItem(props: {
|
|||
|
||||
return (
|
||||
<Tooltip.Provider delayDuration={100}>
|
||||
<div className="py-4 px-1">
|
||||
<div className="px-1 py-4">
|
||||
<div className="flex gap-4">
|
||||
<div>
|
||||
<Checkbox
|
||||
|
|
@ -84,7 +84,7 @@ export function PolicyListItem(props: {
|
|||
<div>
|
||||
<SeverityLevelToggle canTurnOff={props.overridingParentRule} rule={ruleInfo.id} />
|
||||
</div>
|
||||
<div className="grow grid grid-cols-4 [&>*]:border-l-gray-800 [&>*]:border-l-[1px] align-middle [&>*]:min-h-[40px]">
|
||||
<div className="grid grow grid-cols-4 align-middle [&>*]:min-h-[40px] [&>*]:border-l-[1px] [&>*]:border-l-gray-800">
|
||||
{shouldShowRuleConfig && (
|
||||
<PolicyRuleConfig
|
||||
rule={ruleInfo.id}
|
||||
|
|
@ -96,8 +96,8 @@ export function PolicyListItem(props: {
|
|||
</div>
|
||||
) : null}
|
||||
{props.overridingParentRule && enabled ? (
|
||||
<div className="text-xs font-medium mt-4 text-gray-400">
|
||||
<p className="text-orange-500 text-sm font-medium inline-block mr-2">!</p>
|
||||
<div className="mt-4 text-xs font-medium text-gray-400">
|
||||
<p className="mr-2 inline-block text-sm font-medium text-orange-500">!</p>
|
||||
You are {severity === RuleInstanceSeverityLevel.Off ? 'disabling' : 'overriding'} a
|
||||
rule configured at the organization level
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -81,16 +81,19 @@ function PolicySettingsListForm({
|
|||
return {
|
||||
allowOverrides: currentState?.allowOverrides ?? true,
|
||||
rules:
|
||||
currentState?.rules.reduce((acc, ruleInstance) => {
|
||||
return {
|
||||
...acc,
|
||||
[ruleInstance.rule.id]: {
|
||||
enabled: true,
|
||||
severity: ruleInstance.severity,
|
||||
config: ruleInstance.configuration,
|
||||
},
|
||||
};
|
||||
}, {} as PolicyFormValues['rules']) ?? {},
|
||||
currentState?.rules.reduce(
|
||||
(acc, ruleInstance) => {
|
||||
return {
|
||||
...acc,
|
||||
[ruleInstance.rule.id]: {
|
||||
enabled: true,
|
||||
severity: ruleInstance.severity,
|
||||
config: ruleInstance.configuration,
|
||||
},
|
||||
};
|
||||
},
|
||||
{} as PolicyFormValues['rules'],
|
||||
) ?? {},
|
||||
};
|
||||
}, [currentState]);
|
||||
|
||||
|
|
@ -104,7 +107,7 @@ function PolicySettingsListForm({
|
|||
{props => (
|
||||
<>
|
||||
{children ? children(props) : null}
|
||||
<div className="justify-end flex items-center">
|
||||
<div className="flex items-center justify-end">
|
||||
{props.dirty ? <p className="pr-2 text-sm text-gray-500">Unsaved changes</p> : null}
|
||||
<Button
|
||||
disabled={!props.dirty || saving}
|
||||
|
|
@ -116,7 +119,7 @@ function PolicySettingsListForm({
|
|||
</Button>
|
||||
</div>
|
||||
{error ? (
|
||||
<Callout type="error" className="w-2/3 mx-auto">
|
||||
<Callout type="error" className="mx-auto w-2/3">
|
||||
<b>Oops, something went wrong.</b>
|
||||
<br />
|
||||
{error}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export const PolicyBooleanToggle = (props: {
|
|||
|
||||
const label = (
|
||||
<label
|
||||
className="text-xs pb-1 text-gray-500 pl-2 font-mono"
|
||||
className="pb-1 pl-2 font-mono text-xs text-gray-500"
|
||||
htmlFor={`${props.rule}_${props.propertyName}`}
|
||||
>
|
||||
{props.title}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export const PolicyEnumSelect = (props: {
|
|||
return (
|
||||
<PolicyConfigBox
|
||||
title={
|
||||
<div className="items-center flex">
|
||||
<div className="flex items-center">
|
||||
<div>{props.title}</div>
|
||||
{props.tooltip ? (
|
||||
<Tooltip content={props.tooltip}>
|
||||
|
|
@ -55,7 +55,7 @@ export const PolicyEnumSelect = (props: {
|
|||
value={option.value}
|
||||
title={option.label}
|
||||
className={clsx(
|
||||
'hover:text-white text-xs',
|
||||
'text-xs hover:text-white',
|
||||
currentValue === option.value && 'bg-gray-800 text-white',
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export const PolicyMultiSelect = (props: {
|
|||
const currentValues = getConfigValue<string[]>(props.propertyName);
|
||||
|
||||
useEffect(() => {
|
||||
if (!config && typeof props.defaultValues !== undefined) {
|
||||
if (!config && typeof props.defaultValues !== 'undefined') {
|
||||
setConfig(props.propertyName, props.defaultValues);
|
||||
}
|
||||
}, []);
|
||||
|
|
@ -29,7 +29,7 @@ export const PolicyMultiSelect = (props: {
|
|||
return (
|
||||
<PolicyConfigBox
|
||||
title={
|
||||
<div className="items-center flex">
|
||||
<div className="flex items-center">
|
||||
<div>{props.title}</div>
|
||||
{props.tooltip ? (
|
||||
<Tooltip content={props.tooltip}>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export const SeverityLevelToggle = (props: { rule: string; canTurnOff: boolean }
|
|||
}
|
||||
|
||||
return (
|
||||
<PolicyConfigBox title="severity" className="first:pl-0 row-start-1 row-end-6">
|
||||
<PolicyConfigBox title="severity" className="row-start-1 row-end-6 first:pl-0">
|
||||
<ToggleGroup
|
||||
defaultValue="list"
|
||||
onValueChange={newValue => {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export const PolicyStringInputConfig = (props: {
|
|||
return (
|
||||
<PolicyConfigBox
|
||||
title={
|
||||
<div className="items-center flex">
|
||||
<div className="flex items-center">
|
||||
<div>{props.title}</div>
|
||||
{props.tooltip ? (
|
||||
<Tooltip content={props.tooltip}>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export function ChannelsTable(props: {
|
|||
/>
|
||||
</Td>
|
||||
<Td>{channel.name}</Td>
|
||||
<Td className="text-xs truncate text-gray-400">
|
||||
<Td className="truncate text-xs text-gray-400">
|
||||
{channel.__typename === 'AlertSlackChannel'
|
||||
? channel.channel
|
||||
: channel.__typename === 'AlertWebhookChannel'
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@ import { Button } from '@/components/v2';
|
|||
|
||||
export function ProjectMigrationToast({ projectId, orgId }: { projectId: string; orgId: string }) {
|
||||
return (
|
||||
<div className="fixed right-24 bottom-6 p-4 rounded-md bg-gray-900 flex flex-row justify-center gap-6 z-10">
|
||||
<div className="fixed bottom-6 right-24 z-10 flex flex-row justify-center gap-6 rounded-md bg-gray-900 p-4">
|
||||
<div>
|
||||
<div className="font-medium text-sm text-white mb-2">
|
||||
<div className="mb-2 text-sm font-medium text-white">
|
||||
This project utilizes the outdated model of the registry
|
||||
</div>
|
||||
<p className="text-gray-400 text-xs">
|
||||
<p className="text-xs text-gray-400">
|
||||
For an optimized workflow, kindly switch to the modern model.
|
||||
</p>
|
||||
<p className="text-gray-400 text-xs">
|
||||
<p className="text-xs text-gray-400">
|
||||
The legacy model will cease to be accessible in a few months' time.
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ const ExternalCompositionStatus = ({
|
|||
<Tooltip.Provider delayDuration={100}>
|
||||
{query.fetching ? (
|
||||
<Tooltip content="Connecting..." contentProps={{ side: 'right' }}>
|
||||
<UpdateIcon className="animate-spin h-5 w-5 text-gray-500" />
|
||||
<UpdateIcon className="h-5 w-5 animate-spin text-gray-500" />
|
||||
</Tooltip>
|
||||
) : null}
|
||||
{error ? (
|
||||
|
|
@ -158,7 +158,7 @@ const ExternalCompositionForm = ({
|
|||
<div>
|
||||
<span>HTTP endpoint</span>
|
||||
<p className="pb-2 text-xs text-gray-300">A POST request will be sent to that endpoint</p>
|
||||
<div className="flex gap-2 items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
placeholder="Endpoint"
|
||||
name="endpoint"
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ import { RegistryModel } from '@/graphql';
|
|||
import { useNotifications, useRouteSelector } from '@/lib/hooks';
|
||||
import { CheckIcon, Cross2Icon, QuestionMarkCircledIcon } from '@radix-ui/react-icons';
|
||||
|
||||
const divider = <div className="border-b border-gray-900 mt-4" />;
|
||||
const divider = <div className="mt-4 border-b border-gray-900" />;
|
||||
|
||||
function Flag(props: { children: ReactNode }): ReactElement {
|
||||
return <span className="rounded px-1 py-0.5 bg-gray-900/50 text-gray-300">{props.children}</span>;
|
||||
return <span className="rounded bg-gray-900/50 px-1 py-0.5 text-gray-300">{props.children}</span>;
|
||||
}
|
||||
|
||||
const noFlag = <span className="text-gray-300">(defaults)</span>;
|
||||
|
|
@ -23,12 +23,12 @@ function Row(props: {
|
|||
}) {
|
||||
return (
|
||||
<div className="flex">
|
||||
<div className="p-2 grow shrink basis-0">{props.action ?? null}</div>
|
||||
<div className="p-2 grow shrink basis-0 flex items-center text-xs">{props.flag ?? null}</div>
|
||||
<div className="p-2 grow-0 shrink-0 w-40 flex items-center gap-2 justify-center">
|
||||
<div className="shrink grow basis-0 p-2">{props.action ?? null}</div>
|
||||
<div className="flex shrink grow basis-0 items-center p-2 text-xs">{props.flag ?? null}</div>
|
||||
<div className="flex w-40 shrink-0 grow-0 items-center justify-center gap-2 p-2">
|
||||
{props.legacy ?? null}
|
||||
</div>
|
||||
<div className="p-2 grow-0 shrink-0 w-40 flex items-center gap-2 justify-center">
|
||||
<div className="flex w-40 shrink-0 grow-0 items-center justify-center gap-2 p-2">
|
||||
{props.modern ?? null}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -167,7 +167,7 @@ export function ModelMigrationSettings(props: {
|
|||
|
||||
return (
|
||||
<Card>
|
||||
<div className="flex gap-12 items-center">
|
||||
<div className="flex items-center gap-12">
|
||||
<div>
|
||||
<Heading className="mb-2 flex items-center justify-between gap-5">
|
||||
<span className="shrink-0">Upgrade Project</span>
|
||||
|
|
@ -201,12 +201,12 @@ export function ModelMigrationSettings(props: {
|
|||
</div>
|
||||
</div>
|
||||
<Tooltip.Provider delayDuration={200}>
|
||||
<div className="text-sm pt-4">
|
||||
<div className="pt-4 text-sm">
|
||||
<div className="flex border-b-2 border-gray-900 text-gray-500">
|
||||
<div className="p-2 grow shrink basis-0">Action</div>
|
||||
<div className="p-2 grow shrink basis-0">CLI Flag</div>
|
||||
<div className="p-2 grow-0 shrink-0 w-40 text-center">Legacy</div>
|
||||
<div className="p-2 grow-0 shrink-0 w-40 text-center">New</div>
|
||||
<div className="shrink grow basis-0 p-2">Action</div>
|
||||
<div className="shrink grow basis-0 p-2">CLI Flag</div>
|
||||
<div className="w-40 shrink-0 grow-0 p-2 text-center">Legacy</div>
|
||||
<div className="w-40 shrink-0 grow-0 p-2 text-center">New</div>
|
||||
</div>
|
||||
{isComposite ? (
|
||||
<>
|
||||
|
|
@ -321,9 +321,9 @@ export function ModelMigrationSettings(props: {
|
|||
</div>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<div className="flex items-center gap-4 bg-gray-900/50 p-4 rounded border-2 border-gray-900">
|
||||
<div className="flex items-center gap-4 rounded border-2 border-gray-900 bg-gray-900/50 p-4">
|
||||
<QuestionMarkCircledIcon className="h-5 w-auto" />
|
||||
<div className="font-light text-gray-300 text-sm">
|
||||
<div className="text-sm font-light text-gray-300">
|
||||
If you're having difficulty comprehending the changes,{' '}
|
||||
<Button
|
||||
variant="link"
|
||||
|
|
|
|||
|
|
@ -72,23 +72,23 @@ export function SchemaExplorerUsageStats(props: {
|
|||
|
||||
return (
|
||||
<TooltipProvider delayDuration={0}>
|
||||
<div className="flex flex-row items-center gap-2 text-xs ml-3">
|
||||
<div className="ml-3 flex flex-row items-center gap-2 text-xs">
|
||||
<div className="grow">
|
||||
<div className="text-center" title={`${usage.total} requests`}>
|
||||
{formatNumber(usage.total)}
|
||||
</div>
|
||||
<div
|
||||
title={`${toDecimal(percentage)}% of all requests`}
|
||||
className="relative mt-1 w-full overflow-hidden rounded z-0 bg-orange-500/20 min-w-[25px]"
|
||||
className="relative z-0 mt-1 w-full min-w-[25px] overflow-hidden rounded bg-orange-500/20"
|
||||
style={{ width: 50, height: 5 }}
|
||||
>
|
||||
<div className="h-full bg-orange-500 z-0" style={{ width: `${percentage}%` }} />
|
||||
<div className="z-0 h-full bg-orange-500" style={{ width: `${percentage}%` }} />
|
||||
</div>
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipContent>
|
||||
<div className="z-10">
|
||||
<div className="font-bold mb-1 text-lg">Field Usage</div>
|
||||
<div className="mb-1 text-lg font-bold">Field Usage</div>
|
||||
{usage.isUsed === false ? (
|
||||
<div>This field is currently not in use.</div>
|
||||
) : (
|
||||
|
|
@ -108,17 +108,17 @@ export function SchemaExplorerUsageStats(props: {
|
|||
<table className="mt-4 table-auto">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-left p-2 pl-0">Top 5 Operations</th>
|
||||
<th className="text-center p-2">Reqs</th>
|
||||
<th className="text-center p-2">Of total</th>
|
||||
<th className="p-2 pl-0 text-left">Top 5 Operations</th>
|
||||
<th className="p-2 text-center">Reqs</th>
|
||||
<th className="p-2 text-center">Of total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{usage.topOperations.map(op => (
|
||||
<tr key={op.hash}>
|
||||
<td className="text-left px-2 pl-0">
|
||||
<td className="px-2 pl-0 text-left">
|
||||
<NextLink
|
||||
className="text-orange-500 hover:underline hover:underline-offset-2 hover:text-orange-500"
|
||||
className="text-orange-500 hover:text-orange-500 hover:underline hover:underline-offset-2"
|
||||
href={{
|
||||
pathname:
|
||||
'/[organizationId]/[projectId]/[targetId]/insights/[operationName]/[operationHash]',
|
||||
|
|
@ -134,10 +134,10 @@ export function SchemaExplorerUsageStats(props: {
|
|||
{op.hash.substring(0, 4)}_{op.name}
|
||||
</NextLink>
|
||||
</td>
|
||||
<td className="font-bold text-center px-2">
|
||||
<td className="px-2 text-center font-bold">
|
||||
{formatNumber(op.count)}
|
||||
</td>
|
||||
<td className="font-bold text-center px-2">
|
||||
<td className="px-2 text-center font-bold">
|
||||
{toDecimal((op.count / props.totalRequests) * 100)}%
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -151,7 +151,7 @@ export function SchemaExplorerUsageStats(props: {
|
|||
</div>
|
||||
</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<div className="text-xl cursor-help">
|
||||
<div className="cursor-help text-xl">
|
||||
<PulseIcon className="h-6 w-auto" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
|
|
@ -160,7 +160,7 @@ export function SchemaExplorerUsageStats(props: {
|
|||
<Tooltip>
|
||||
<TooltipContent>
|
||||
<>
|
||||
<div className="font-bold mb-1 text-lg">Client Usage</div>
|
||||
<div className="mb-1 text-lg font-bold">Client Usage</div>
|
||||
|
||||
{Array.isArray(usage.usedByClients) ? (
|
||||
<>
|
||||
|
|
@ -169,7 +169,7 @@ export function SchemaExplorerUsageStats(props: {
|
|||
{usage.usedByClients.map(clientName => (
|
||||
<li key={clientName} className="font-bold">
|
||||
<NextLink
|
||||
className="text-orange-500 hover:underline hover:underline-offset-2 hover:text-orange-500"
|
||||
className="text-orange-500 hover:text-orange-500 hover:underline hover:underline-offset-2"
|
||||
href={{
|
||||
pathname:
|
||||
'/[organizationId]/[projectId]/[targetId]/insights/client/[name]',
|
||||
|
|
@ -193,7 +193,7 @@ export function SchemaExplorerUsageStats(props: {
|
|||
</>
|
||||
</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<div className="text-xl p-1 cursor-help">
|
||||
<div className="cursor-help p-1 text-xl">
|
||||
<UsersIcon size={16} className="h-6 w-auto" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
|
|
@ -438,7 +438,7 @@ export function GraphQLFields(props: {
|
|||
<GraphQLArguments parentCoordinate={coordinate} args={field.args} />
|
||||
) : null}
|
||||
<span className="mr-1">:</span>
|
||||
<GraphQLTypeAsLink className="text-gray-400 font-semibold" type={field.type} />
|
||||
<GraphQLTypeAsLink className="font-semibold text-gray-400" type={field.type} />
|
||||
</div>
|
||||
<div className="flex flex-row items-center">
|
||||
{field.supergraphMetadata ? (
|
||||
|
|
@ -490,7 +490,7 @@ export function GraphQLInputFields(props: {
|
|||
return (
|
||||
<GraphQLTypeCardListItem key={field.name} index={i}>
|
||||
<div className="text-gray-400">
|
||||
<LinkToCoordinatePage coordinate={coordinate} className="text-white font-semibold">
|
||||
<LinkToCoordinatePage coordinate={coordinate} className="font-semibold text-white">
|
||||
{field.name}
|
||||
</LinkToCoordinatePage>
|
||||
<span className="mr-1">:</span>
|
||||
|
|
@ -518,14 +518,14 @@ function GraphQLTypeAsLink(props: { type: string; className?: string }): ReactEl
|
|||
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger className={cn('hover:underline-offset-4 hover:underline', props.className)}>
|
||||
<PopoverTrigger className={cn('hover:underline hover:underline-offset-4', props.className)}>
|
||||
{props.type}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent side="right">
|
||||
<div className="flex flex-col gap-y-2">
|
||||
<p>
|
||||
<NextLink
|
||||
className="hover:underline hover:underline-offset-2 font-normal text-sm"
|
||||
className="text-sm font-normal hover:underline hover:underline-offset-2"
|
||||
href={{
|
||||
pathname: '/[organizationId]/[projectId]/[targetId]/explorer/[typename]',
|
||||
query: {
|
||||
|
|
@ -539,11 +539,11 @@ function GraphQLTypeAsLink(props: { type: string; className?: string }): ReactEl
|
|||
>
|
||||
Visit in <span className="font-bold">Explorer</span>
|
||||
</NextLink>
|
||||
<span className="text-gray-500 text-xs"> - displays a full type</span>
|
||||
<span className="text-xs text-gray-500"> - displays a full type</span>
|
||||
</p>
|
||||
<p>
|
||||
<NextLink
|
||||
className="hover:underline hover:underline-offset-2 font-normal text-sm"
|
||||
className="text-sm font-normal hover:underline hover:underline-offset-2"
|
||||
href={{
|
||||
pathname:
|
||||
'/[organizationId]/[projectId]/[targetId]/insights/schema-coordinate/[typename]',
|
||||
|
|
@ -558,7 +558,7 @@ function GraphQLTypeAsLink(props: { type: string; className?: string }): ReactEl
|
|||
>
|
||||
Visit in <span className="font-bold">Insights</span>
|
||||
</NextLink>
|
||||
<span className="text-gray-500 text-xs"> - usage insights</span>
|
||||
<span className="text-xs text-gray-500"> - usage insights</span>
|
||||
</p>
|
||||
</div>
|
||||
<PopoverArrow />
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export function SchemaExplorerFilter({
|
|||
return (
|
||||
<div className="flex flex-row items-center gap-x-4">
|
||||
<Autocomplete
|
||||
className="grow min-w-[250px] cursor-text"
|
||||
className="min-w-[250px] grow cursor-text"
|
||||
placeholder="Search for a type"
|
||||
defaultValue={typename ? { value: typename, label: typename } : null}
|
||||
options={types}
|
||||
|
|
@ -134,7 +134,7 @@ export function SchemaExplorerFilter({
|
|||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="flex flex-row items-center gap-x-4 rounded-md border px-3 h-[40px] bg-secondary">
|
||||
<div className="bg-secondary flex h-[40px] flex-row items-center gap-x-4 rounded-md border px-3">
|
||||
<div>
|
||||
<Label htmlFor="filter-toggle-arguments" className="text-sm font-normal">
|
||||
Display all arguments
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@ function SubgraphChip(props: { text: string; tooltip: boolean }): React.ReactEle
|
|||
hash: `service-${props.text}`,
|
||||
}}
|
||||
style={{ backgroundColor: stringToHslColor(props.text) }}
|
||||
className="drop-shadow-md my-[2px] ml-[6px] h-[22px] cursor-pointer items-center justify-between rounded-[16px] pr-[6px] pl-[8px] py-0 text-[10px] font-normal normal-case leading-loose text-[#4f4f4f] inline-block max-w-[100px] truncate"
|
||||
className="my-[2px] ml-[6px] inline-block h-[22px] max-w-[100px] cursor-pointer items-center justify-between truncate rounded-[16px] py-0 pl-[8px] pr-[6px] text-[10px] font-normal normal-case leading-loose text-[#4f4f4f] drop-shadow-md"
|
||||
>
|
||||
{props.text}
|
||||
<PackageIcon size={10} className="inline-block ml-1" />
|
||||
<PackageIcon size={10} className="ml-1 inline-block" />
|
||||
</Link>
|
||||
);
|
||||
|
||||
|
|
@ -106,19 +106,19 @@ export function SupergraphMetadataList(props: {
|
|||
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<div className="w-full flex justify-end">
|
||||
<div className="flex w-full justify-end">
|
||||
{previewItems}{' '}
|
||||
{allItems ? (
|
||||
<Tooltip
|
||||
content={
|
||||
<>
|
||||
<div className="font-bold mb-2">All Subgraphs</div>
|
||||
<div className="relative w-[250px] h-[250px]">
|
||||
<div className="inset-0 absolute w-[250px] h-[250px] overflow-y-scroll py-2">
|
||||
<div className="mb-2 font-bold">All Subgraphs</div>
|
||||
<div className="relative h-[250px] w-[250px]">
|
||||
<div className="absolute inset-0 h-[250px] w-[250px] overflow-y-scroll py-2">
|
||||
{allItems}
|
||||
</div>
|
||||
<div
|
||||
className="inset-0 absolute pointer-events-none"
|
||||
className="pointer-events-none absolute inset-0"
|
||||
style={{
|
||||
boxShadow: `inset 0px 11px 8px -10px ${tooltipColor}, inset 0px -11px 8px -10px ${tooltipColor}`,
|
||||
}}
|
||||
|
|
@ -128,7 +128,7 @@ export function SupergraphMetadataList(props: {
|
|||
}
|
||||
contentProps={{ className: 'z-10' }}
|
||||
>
|
||||
<span className="pl-1 font-bold text-xs flex items-center cursor-pointer text-white ">
|
||||
<span className="flex cursor-pointer items-center pl-1 text-xs font-bold text-white ">
|
||||
+ {allItems.length - previewItems.length} more
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ function ErrorsBlock({ title, errors }: { errors: string[]; title: React.ReactNo
|
|||
<h2 className="mb-2 text-sm font-medium text-gray-900 dark:text-white">{title}</h2>
|
||||
<ul className="list-inside list-disc pl-3 text-sm leading-relaxed">
|
||||
{errors.map((error, key) => (
|
||||
<li key={key} className="text-red-400 my-1">
|
||||
<li key={key} className="my-1 text-red-400">
|
||||
<span className="text-gray-600 dark:text-white">{labelize(error)}</span>
|
||||
</li>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ function OperationsFilter({
|
|||
<Drawer open={isOpen} onOpenChange={onClose} width={500}>
|
||||
<Drawer.Title>Filter by operation</Drawer.Title>
|
||||
|
||||
<div className="flex flex-col h-full space-y-3">
|
||||
<div className="flex h-full flex-col space-y-3">
|
||||
<Input
|
||||
size="medium"
|
||||
placeholder="Search for operation..."
|
||||
|
|
@ -128,7 +128,7 @@ function OperationsFilter({
|
|||
setVisibleOperations(operations.nodes);
|
||||
}}
|
||||
/>
|
||||
<div className="flex gap-2 items-center w-full">
|
||||
<div className="flex w-full items-center gap-2">
|
||||
<LegacyButton variant="link" onClick={selectAll}>
|
||||
All
|
||||
</LegacyButton>
|
||||
|
|
@ -149,7 +149,7 @@ function OperationsFilter({
|
|||
Save
|
||||
</LegacyButton>
|
||||
</div>
|
||||
<div className="pl-1 grow">
|
||||
<div className="grow pl-1">
|
||||
<AutoSizer>
|
||||
{({ height, width }) =>
|
||||
!height || !width ? (
|
||||
|
|
@ -266,9 +266,9 @@ function OperationRow({
|
|||
<Checkbox checked={selected} onCheckedChange={change} id={hash} />
|
||||
<label
|
||||
htmlFor={hash}
|
||||
className="flex items-center justify-between overflow-hidden gap-4 w-full cursor-pointer"
|
||||
className="flex w-full cursor-pointer items-center justify-between gap-4 overflow-hidden"
|
||||
>
|
||||
<span className="grow text-ellipsis overflow-hidden">{operation.name}</span>
|
||||
<span className="grow overflow-hidden text-ellipsis">{operation.name}</span>
|
||||
<div className="shrink-0 text-right text-gray-500">{requests}</div>
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -290,7 +290,7 @@ export function OperationsFilterTrigger({
|
|||
<>
|
||||
<Button variant="outline" className="bg-accent" onClick={toggle}>
|
||||
<span>Operations ({selected?.length || 'all'})</span>
|
||||
<FilterIcon className="ml-2 w-4 h-4" />
|
||||
<FilterIcon className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
<OperationsFilterContainer
|
||||
isOpen={isOpen}
|
||||
|
|
@ -335,9 +335,9 @@ function ClientRow({
|
|||
<Checkbox checked={selected} onCheckedChange={change} id={hash} />
|
||||
<label
|
||||
htmlFor={hash}
|
||||
className="flex items-center justify-between overflow-hidden gap-4 w-full cursor-pointer"
|
||||
className="flex w-full cursor-pointer items-center justify-between gap-4 overflow-hidden"
|
||||
>
|
||||
<span className="grow text-ellipsis overflow-hidden">{client.name}</span>
|
||||
<span className="grow overflow-hidden text-ellipsis">{client.name}</span>
|
||||
<div className="shrink-0 text-right text-gray-500">{requests}</div>
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -440,7 +440,7 @@ function ClientsFilter({
|
|||
<Drawer open={isOpen} onOpenChange={onClose} width={500}>
|
||||
<Drawer.Title>Filter by client</Drawer.Title>
|
||||
|
||||
<div className="flex flex-col h-full space-y-3">
|
||||
<div className="flex h-full flex-col space-y-3">
|
||||
<Input
|
||||
size="medium"
|
||||
placeholder="Search for operation..."
|
||||
|
|
@ -451,7 +451,7 @@ function ClientsFilter({
|
|||
setVisibleOperations(clientConnection.nodes);
|
||||
}}
|
||||
/>
|
||||
<div className="flex gap-2 items-center w-full">
|
||||
<div className="flex w-full items-center gap-2">
|
||||
<LegacyButton variant="link" onClick={selectAll}>
|
||||
All
|
||||
</LegacyButton>
|
||||
|
|
@ -472,7 +472,7 @@ function ClientsFilter({
|
|||
Save
|
||||
</LegacyButton>
|
||||
</div>
|
||||
<div className="pl-1 grow">
|
||||
<div className="grow pl-1">
|
||||
<AutoSizer>
|
||||
{({ height, width }) =>
|
||||
!height || !width ? (
|
||||
|
|
@ -574,7 +574,7 @@ export function ClientsFilterTrigger({
|
|||
<>
|
||||
<Button variant="outline" className="bg-accent" onClick={toggle}>
|
||||
<span>Clients ({selected?.length || 'all'})</span>
|
||||
<FilterIcon className="ml-2 w-4 h-4" />
|
||||
<FilterIcon className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
<ClientsFilterContainer
|
||||
isOpen={isOpen}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ function OperationRow({
|
|||
<>
|
||||
<Tr>
|
||||
<Td className="font-medium">
|
||||
<div className="flex gap-2 items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<Link
|
||||
href={{
|
||||
pathname:
|
||||
|
|
@ -87,7 +87,7 @@ function OperationRow({
|
|||
}}
|
||||
passHref
|
||||
>
|
||||
<OldButton variant="link" as="a" className="block truncate max-w-[300px]">
|
||||
<OldButton variant="link" as="a" className="block max-w-[300px] truncate">
|
||||
{operation.name}
|
||||
</OldButton>
|
||||
</Link>
|
||||
|
|
@ -233,7 +233,7 @@ function OperationsTable({
|
|||
const { headers } = tableInstance.getHeaderGroups()[0];
|
||||
|
||||
return (
|
||||
<div className={clsx('rounded-md p-5 border border-gray-800 bg-gray-900/50', className)}>
|
||||
<div className={clsx('rounded-md border border-gray-800 bg-gray-900/50 p-5', className)}>
|
||||
<Section.Title>Operations</Section.Title>
|
||||
<Section.Subtitle>List of all operations with their statistics</Section.Subtitle>
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ function OperationsTable({
|
|||
)}
|
||||
</TBody>
|
||||
</Table>
|
||||
<div className="flex items-center gap-2 mt-6">
|
||||
<div className="mt-6 flex items-center gap-2">
|
||||
<Button
|
||||
onClick={firstPage}
|
||||
variant="outline"
|
||||
|
|
@ -294,9 +294,9 @@ function OperationsTable({
|
|||
onClick={tableInstance.previousPage}
|
||||
disabled={!tableInstance.getCanPreviousPage()}
|
||||
>
|
||||
<ChevronUpIcon className="-rotate-90 h-5 w-auto" />
|
||||
<ChevronUpIcon className="h-5 w-auto -rotate-90" />
|
||||
</Button>
|
||||
<span className="font-bold whitespace-nowrap text-sm">
|
||||
<span className="whitespace-nowrap text-sm font-bold">
|
||||
{tableInstance.getState().pagination.pageIndex + 1} / {tableInstance.getPageCount()}
|
||||
</span>
|
||||
<Button
|
||||
|
|
@ -305,7 +305,7 @@ function OperationsTable({
|
|||
onClick={tableInstance.nextPage}
|
||||
disabled={!tableInstance.getCanNextPage()}
|
||||
>
|
||||
<ChevronUpIcon className="rotate-90 h-5 w-auto" />
|
||||
<ChevronUpIcon className="h-5 w-auto rotate-90" />
|
||||
</Button>
|
||||
<Button variant="outline" onClick={lastPage} disabled={!tableInstance.getCanNextPage()}>
|
||||
Last
|
||||
|
|
|
|||
|
|
@ -74,11 +74,11 @@ function RequestsStats({
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Requests</CardTitle>
|
||||
<GlobeIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<GlobeIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{value}</div>
|
||||
<p className="text-xs text-muted-foreground">Total requests served</p>
|
||||
<p className="text-muted-foreground text-xs">Total requests served</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -97,11 +97,11 @@ function UniqueOperationsStats({
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Operations</CardTitle>
|
||||
<BookIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<BookIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{value}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Distinct GraphQL operations in {dateRangeText}
|
||||
</p>
|
||||
</CardContent>
|
||||
|
|
@ -125,11 +125,11 @@ function OperationRelativeFrequency({
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Relative Request Frequency</CardTitle>
|
||||
<PercentIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<PercentIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{rate}</div>
|
||||
<p className="text-xs text-muted-foreground">The impact on the overall API traffic</p>
|
||||
<p className="text-muted-foreground text-xs">The impact on the overall API traffic</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -150,11 +150,11 @@ function PercentileStats({
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">p{percentile}</CardTitle>
|
||||
<GaugeIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<GaugeIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{formatted}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Latency p{percentile} in {dateRangeText}
|
||||
</p>
|
||||
</CardContent>
|
||||
|
|
@ -183,11 +183,11 @@ function RPM({
|
|||
<Card className="bg-gray-900/50">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Requests per minute</CardTitle>
|
||||
<ActivityIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<ActivityIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{throughput}</div>
|
||||
<p className="text-xs text-muted-foreground">Throughput in {dateRangeText}</p>
|
||||
<p className="text-muted-foreground text-xs">Throughput in {dateRangeText}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -213,11 +213,11 @@ function SuccessRateStats({
|
|||
<CardTitle className="text-sm font-medium text-emerald-500 dark:text-emerald-500">
|
||||
Success rate
|
||||
</CardTitle>
|
||||
<SmileIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<SmileIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{rate}</div>
|
||||
<p className="text-xs text-muted-foreground">Successful requests in {dateRangeText}</p>
|
||||
<p className="text-muted-foreground text-xs">Successful requests in {dateRangeText}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -240,11 +240,11 @@ function FailureRateStats({
|
|||
<CardTitle className="text-sm font-medium text-red-500 dark:text-red-500">
|
||||
Failure rate
|
||||
</CardTitle>
|
||||
<FrownIcon className="h-4 w-4 text-muted-foreground" />
|
||||
<FrownIcon className="text-muted-foreground h-4 w-4" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{rate}</div>
|
||||
<p className="text-xs text-muted-foreground">Failed requests in {dateRangeText}</p>
|
||||
<p className="text-muted-foreground text-xs">Failed requests in {dateRangeText}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -294,7 +294,7 @@ function OverTimeStats({
|
|||
}, [failuresOverTime, interval, period]);
|
||||
|
||||
return (
|
||||
<div className="rounded-md bg-gray-900/50 p-5 border border-gray-800">
|
||||
<div className="rounded-md border border-gray-800 bg-gray-900/50 p-5">
|
||||
<Section.Title>Operations over time</Section.Title>
|
||||
<Section.Subtitle>Timeline of GraphQL requests and failures</Section.Subtitle>
|
||||
<AutoSizer disableHeight>
|
||||
|
|
@ -577,10 +577,10 @@ function ClientsStats(props: {
|
|||
);
|
||||
|
||||
return (
|
||||
<div className="w-full rounded-md bg-gray-900/50 p-5 border border-gray-800">
|
||||
<div className="w-full rounded-md border border-gray-800 bg-gray-900/50 p-5">
|
||||
<Section.Title>Clients</Section.Title>
|
||||
<Section.Subtitle>Top 5 - GraphQL API consumers</Section.Subtitle>
|
||||
<AutoSizer disableHeight className="mt-5 w-full flex flex-row gap-x-4">
|
||||
<AutoSizer disableHeight className="mt-5 flex w-full flex-row gap-x-4">
|
||||
{size => {
|
||||
if (!size.width) {
|
||||
return <></>;
|
||||
|
|
@ -748,7 +748,7 @@ function ClientsStats(props: {
|
|||
}}
|
||||
</AutoSizer>
|
||||
) : null}
|
||||
<div className="w-full mt-5 text-center">
|
||||
<div className="mt-5 w-full text-center">
|
||||
<Button variant="outline" onClick={() => setIsOpen(value => !value)}>
|
||||
{isOpen ? (
|
||||
<>
|
||||
|
|
@ -843,7 +843,7 @@ function LatencyOverTimeStats({
|
|||
];
|
||||
|
||||
return (
|
||||
<div className="rounded-md bg-gray-900/50 p-5 border border-gray-800">
|
||||
<div className="rounded-md border border-gray-800 bg-gray-900/50 p-5">
|
||||
<Section.Title>Latency over time</Section.Title>
|
||||
<Section.Subtitle>Timeline of latency of GraphQL requests</Section.Subtitle>
|
||||
<AutoSizer disableHeight>
|
||||
|
|
@ -940,7 +940,7 @@ function RpmOverTimeStats({
|
|||
}, [requests, interval, period, windowInM]);
|
||||
|
||||
return (
|
||||
<div className="rounded-md bg-gray-900/50 p-5 border border-gray-800">
|
||||
<div className="rounded-md border border-gray-800 bg-gray-900/50 p-5">
|
||||
<Section.Title>RPM over time</Section.Title>
|
||||
<Section.Subtitle>Requests per minute</Section.Subtitle>
|
||||
<AutoSizer disableHeight>
|
||||
|
|
@ -1073,7 +1073,7 @@ export function OperationsStats({
|
|||
dateRangeText = dateRangeText.toLowerCase();
|
||||
|
||||
return (
|
||||
<section className="text-gray-600 dark:text-gray-400 space-y-12 transition-opacity ease-in-out duration-700">
|
||||
<section className="space-y-12 text-gray-600 transition-opacity duration-700 ease-in-out dark:text-gray-400">
|
||||
<OperationsFallback isError={isError} refetch={refetch} isFetching={isFetching}>
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<RequestsStats requests={operationsStats?.totalRequests} dateRangeText={dateRangeText} />
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ export const EditOperationModal = (props: {
|
|||
return (
|
||||
<Modal open onOpenChange={props.close} className="flex flex-col items-center gap-5">
|
||||
{!updateOperationNameState.fetching && (
|
||||
<form className="flex flex-col gap-8 w-full" onSubmit={handleSubmit}>
|
||||
<form className="flex w-full flex-col gap-8" onSubmit={handleSubmit}>
|
||||
<Heading className="text-center">Edit Operation</Heading>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ function CreateCDNAccessTokenModal(props: {
|
|||
|
||||
<p>The CDN Access Token was successfully created.</p>
|
||||
|
||||
<div className="flex items-center gap-2 rounded-sm p-4 bg-yellow-500/10 text-yellow-500">
|
||||
<div className="flex items-center gap-2 rounded-sm bg-yellow-500/10 p-4 text-yellow-500">
|
||||
<AlertTriangleIcon className="h-5 w-5" />
|
||||
<span>
|
||||
Please store this access token securely. You will not be able to see it again.
|
||||
|
|
@ -157,7 +157,7 @@ function CreateCDNAccessTokenModal(props: {
|
|||
|
||||
<p>Something went wrong.</p>
|
||||
|
||||
<Tag color="yellow" className="py-2.5 px-4">
|
||||
<Tag color="yellow" className="px-4 py-2.5">
|
||||
<AlertTriangleIcon className="h-5 w-5" />
|
||||
{createCdnAccessToken.data?.createCdnAccessToken.error.message}
|
||||
</Tag>
|
||||
|
|
@ -212,7 +212,7 @@ function DeleteCDNAccessTokenModal(props: {
|
|||
<div className="flex flex-col gap-5">
|
||||
<Heading className="text-center">Delete CDN Access Tokens</Heading>
|
||||
</div>
|
||||
<Tag color="yellow" className="py-2.5 px-4">
|
||||
<Tag color="yellow" className="px-4 py-2.5">
|
||||
<AlertTriangleIcon className="h-5 w-5" />
|
||||
Deleting an CDN access token can not be undone. After deleting the access token it might
|
||||
take up to 5 minutes before the changes are propagated across the CDN.
|
||||
|
|
@ -254,7 +254,7 @@ function DeleteCDNAccessTokenModal(props: {
|
|||
|
||||
<p>The CDN Access Token was successfully deleted.</p>
|
||||
|
||||
<Tag color="yellow" className="py-2.5 px-4">
|
||||
<Tag color="yellow" className="px-4 py-2.5">
|
||||
<AlertTriangleIcon className="h-5 w-5" />
|
||||
It can take up to 5 minutes before the changes are propagated across the CDN.
|
||||
</Tag>
|
||||
|
|
@ -274,7 +274,7 @@ function DeleteCDNAccessTokenModal(props: {
|
|||
|
||||
<p>Something went wrong.</p>
|
||||
|
||||
<Tag color="yellow" className="py-2.5 px-4">
|
||||
<Tag color="yellow" className="px-4 py-2.5">
|
||||
<AlertTriangleIcon className="h-5 w-5" />
|
||||
{deleteCdnAccessToken.data?.deleteCdnAccessToken.error.message}
|
||||
</Tag>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElemen
|
|||
({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn('rounded-lg border text-card-foreground shadow-sm bg-gray-900/50', className)}
|
||||
className={cn('text-card-foreground rounded-lg border bg-gray-900/50 shadow-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
|
|
@ -16,7 +16,7 @@ const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDiv
|
|||
({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn('flex flex-col space-y-1.5 p-6 cursor-default', className)}
|
||||
className={cn('flex cursor-default flex-col space-y-1.5 p-6', className)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
|
|
@ -28,7 +28,7 @@ const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HT
|
|||
// eslint-disable-next-line jsx-a11y/heading-has-content
|
||||
<h3
|
||||
ref={ref}
|
||||
className={cn('text-lg font-semibold leading-none tracking-tight cursor-default', className)}
|
||||
className={cn('cursor-default text-lg font-semibold leading-none tracking-tight', className)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
|
|
@ -41,7 +41,7 @@ const CardDescription = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<p
|
||||
ref={ref}
|
||||
className={cn('text-sm text-muted-foreground cursor-default', className)}
|
||||
className={cn('text-muted-foreground cursor-default text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const Checkbox = React.forwardRef<
|
|||
<CheckboxPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
|
||||
'border-primary ring-offset-background focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground peer h-4 w-4 shrink-0 rounded-sm border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
|
|||
<DropdownMenuPrimitive.SubTrigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',
|
||||
'focus:bg-accent data-[state=open]:bg-accent flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
|
||||
inset && 'pl-8',
|
||||
className,
|
||||
)}
|
||||
|
|
@ -39,7 +39,7 @@ const DropdownMenuSubContent = React.forwardRef<
|
|||
<DropdownMenuPrimitive.SubContent
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1',
|
||||
'bg-popover text-popover-foreground animate-in data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-md',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -56,7 +56,7 @@ const DropdownMenuContent = React.forwardRef<
|
|||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-2 text-popover-foreground shadow-md animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||
'bg-popover text-popover-foreground animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-2 shadow-md',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -75,7 +75,7 @@ const DropdownMenuItem = React.forwardRef<
|
|||
<DropdownMenuPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'relative flex cursor-pointer select-none items-center rounded-sm px-2 py-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
'focus:bg-accent focus:text-accent-foreground relative flex cursor-pointer select-none items-center rounded-sm px-2 py-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
inset && 'pl-8',
|
||||
active && 'bg-accent text-orange-500',
|
||||
className,
|
||||
|
|
@ -92,7 +92,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
|
|||
<DropdownMenuPrimitive.CheckboxItem
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
'focus:bg-accent focus:text-accent-foreground relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
className,
|
||||
)}
|
||||
checked={checked}
|
||||
|
|
@ -115,7 +115,7 @@ const DropdownMenuRadioItem = React.forwardRef<
|
|||
<DropdownMenuPrimitive.RadioItem
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
'focus:bg-accent focus:text-accent-foreground relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -150,7 +150,7 @@ const DropdownMenuSeparator = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn('-mx-1 my-1 h-px bg-muted', className)}
|
||||
className={cn('bg-muted -mx-1 my-1 h-px', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ const FormDescription = React.forwardRef<
|
|||
<p
|
||||
ref={ref}
|
||||
id={formDescriptionId}
|
||||
className={cn('text-sm text-muted-foreground', className)}
|
||||
className={cn('text-muted-foreground text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
|
@ -145,7 +145,7 @@ const FormMessage = React.forwardRef<
|
|||
<p
|
||||
ref={ref}
|
||||
id={formMessageId}
|
||||
className={cn('text-sm font-medium text-destructive', className)}
|
||||
className={cn('text-destructive text-sm font-medium', className)}
|
||||
{...props}
|
||||
>
|
||||
{body}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
'border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export const NotFound = ({
|
|||
}) => {
|
||||
return (
|
||||
<Card
|
||||
className={cn('flex grow flex-col items-center gap-y-2 cursor-default', className)}
|
||||
className={cn('flex grow cursor-default flex-col items-center gap-y-2', className)}
|
||||
data-cy="empty-list"
|
||||
>
|
||||
<Image src={ghost} alt="Ghost illustration" width="200" height="200" className="drag-none" />
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ import { cn } from '@/lib/utils';
|
|||
|
||||
export function Title({ children, className }: { children: ReactNode; className?: string }) {
|
||||
return (
|
||||
<h3 className={cn('text-lg font-semibold tracking-tight cursor-default', className)}>
|
||||
<h3 className={cn('cursor-default text-lg font-semibold tracking-tight', className)}>
|
||||
{children}
|
||||
</h3>
|
||||
);
|
||||
}
|
||||
|
||||
export function Subtitle({ children, className }: { children: ReactNode; className?: string }) {
|
||||
return <p className={cn('text-sm text-gray-400 cursor-default', className)}>{children}</p>;
|
||||
return <p className={cn('cursor-default text-sm text-gray-400', className)}>{children}</p>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const PopoverContent = React.forwardRef<
|
|||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-none',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@ export function QueryError({
|
|||
const requestId =
|
||||
error &&
|
||||
'response' in error &&
|
||||
error?.response?.headers &&
|
||||
error.response.headers.get('x-request-id')?.split(',')[0].trim();
|
||||
error?.response?.headers?.get('x-request-id')?.split(',')[0].trim();
|
||||
|
||||
cookies.remove(LAST_VISITED_ORG_KEY);
|
||||
|
||||
|
|
@ -31,19 +30,19 @@ export function QueryError({
|
|||
typeof router.query.organizationId === 'string' ? router.query.organizationId : null;
|
||||
|
||||
return (
|
||||
<div className="h-full w-full flex items-center justify-center">
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => router.push('/logout')}
|
||||
className="absolute top-6 right-6"
|
||||
className="absolute right-6 top-6"
|
||||
>
|
||||
<LogOutIcon className="mr-2 h-4 w-4" /> Sign out
|
||||
</Button>
|
||||
<div className="flex sm:flex-row flex-col items-center gap-x-6 max-w-[960px]">
|
||||
<div className="flex max-w-[960px] flex-col items-center gap-x-6 sm:flex-row">
|
||||
<img
|
||||
src="/images/figures/connection.svg"
|
||||
alt="Ghost"
|
||||
className="block w-[200px] h-[200px]"
|
||||
className="block h-[200px] w-[200px]"
|
||||
/>
|
||||
<div className="grow text-center sm:text-left">
|
||||
<h1 className="text-xl font-semibold">Oops, something went wrong.</h1>
|
||||
|
|
@ -79,8 +78,8 @@ export function QueryError({
|
|||
{requestId ? (
|
||||
<div className="mt-6 text-xs">
|
||||
<div className="inline-flex items-center text-gray-300">
|
||||
<div className="p-2 bg-yellow-500/10 rounded-l-sm">Error ID</div>
|
||||
<div className="p-2 bg-yellow-500/5 rounded-r-sm">{requestId}</div>
|
||||
<div className="rounded-l-sm bg-yellow-500/10 p-2">Error ID</div>
|
||||
<div className="rounded-r-sm bg-yellow-500/5 p-2">{requestId}</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const RadioGroupItem = React.forwardRef<
|
|||
<RadioGroupPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
'border-primary text-primary ring-offset-background focus-visible:ring-ring aspect-square h-4 w-4 rounded-full border focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ const SelectContent = React.forwardRef<
|
|||
<SelectPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md animate-in fade-in-80 cursor-pointer',
|
||||
'bg-popover text-popover-foreground animate-in fade-in-80 relative z-50 min-w-[8rem] cursor-pointer overflow-hidden rounded-md border shadow-md',
|
||||
position === 'popper' && 'translate-y-1',
|
||||
className,
|
||||
)}
|
||||
|
|
@ -96,7 +96,7 @@ const SelectItem = React.forwardRef<
|
|||
<SelectPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'relative flex w-full select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 cursor-pointer',
|
||||
'focus:bg-accent focus:text-accent-foreground relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -118,7 +118,7 @@ const SelectSeparator = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn('-mx-1 my-1 h-px bg-muted', className)}
|
||||
className={cn('bg-muted -mx-1 my-1 h-px', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue