Use framework logo on console & trust
Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
import { availableFrameworks } from "@probo/helpers";
|
||||
import { Avatar } from "@probo/ui";
|
||||
|
||||
const availableLogos = new Map(
|
||||
availableFrameworks.map((framework) => [framework.name, framework.logo])
|
||||
);
|
||||
|
||||
export function FrameworkLogo({ name }: { name: string }) {
|
||||
const logo = availableLogos.get(name);
|
||||
return logo ? (
|
||||
<img src={logo} alt="" className="h-12" />
|
||||
) : (
|
||||
<Avatar name={name} size="l" className="size-12" />
|
||||
);
|
||||
}
|
||||
@@ -36,6 +36,8 @@ export const auditNodeQuery = graphql`
|
||||
framework {
|
||||
id
|
||||
name
|
||||
lightLogoURL
|
||||
darkLogoURL
|
||||
}
|
||||
organization {
|
||||
id
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<fc4103e0e8b03c1b6b8ea07c4adcf095>>
|
||||
* @generated SignedSource<<c802dc4c6e5b63e48b0050dfcf13b4b4>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -17,7 +17,9 @@ export type AuditGraphNodeQuery$data = {
|
||||
readonly node: {
|
||||
readonly createdAt?: any;
|
||||
readonly framework?: {
|
||||
readonly darkLogoURL: string | null | undefined;
|
||||
readonly id: string;
|
||||
readonly lightLogoURL: string | null | undefined;
|
||||
readonly name: string;
|
||||
};
|
||||
readonly id?: string;
|
||||
@@ -151,31 +153,47 @@ v9 = {
|
||||
"name": "state",
|
||||
"storageKey": null
|
||||
},
|
||||
v10 = [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/)
|
||||
],
|
||||
v11 = {
|
||||
v10 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Framework",
|
||||
"kind": "LinkedField",
|
||||
"name": "framework",
|
||||
"plural": false,
|
||||
"selections": (v10/*: any*/),
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "lightLogoURL",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "darkLogoURL",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
v12 = {
|
||||
v11 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Organization",
|
||||
"kind": "LinkedField",
|
||||
"name": "organization",
|
||||
"plural": false,
|
||||
"selections": (v10/*: any*/),
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
v13 = {
|
||||
v12 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
@@ -207,10 +225,10 @@ return {
|
||||
(v7/*: any*/),
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/),
|
||||
(v12/*: any*/),
|
||||
(v6/*: any*/),
|
||||
(v13/*: any*/)
|
||||
(v12/*: any*/)
|
||||
],
|
||||
"type": "Audit",
|
||||
"abstractKey": null
|
||||
@@ -253,10 +271,10 @@ return {
|
||||
(v7/*: any*/),
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/),
|
||||
(v12/*: any*/),
|
||||
(v6/*: any*/),
|
||||
(v13/*: any*/)
|
||||
(v12/*: any*/)
|
||||
],
|
||||
"type": "Audit",
|
||||
"abstractKey": null
|
||||
@@ -267,16 +285,16 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "eede00ab53ccd396e92b7fe6c1f1c2a2",
|
||||
"cacheID": "af5fde4e1522c98b908630fdf1451ae9",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "AuditGraphNodeQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query AuditGraphNodeQuery(\n $auditId: ID!\n) {\n node(id: $auditId) {\n __typename\n ... on Audit {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n mimeType\n size\n downloadUrl\n createdAt\n }\n reportUrl\n state\n framework {\n id\n name\n }\n organization {\n id\n name\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n"
|
||||
"text": "query AuditGraphNodeQuery(\n $auditId: ID!\n) {\n node(id: $auditId) {\n __typename\n ... on Audit {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n mimeType\n size\n downloadUrl\n createdAt\n }\n reportUrl\n state\n framework {\n id\n name\n lightLogoURL\n darkLogoURL\n }\n organization {\n id\n name\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "c07896ae39a7d16b42c7ee4216dc28fa";
|
||||
(node as any).hash = "db92119c6d6f000963a0ff3d0fb74dfd";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<a67eb2a88e39d7eaf96910e0318dd1bc>>
|
||||
* @generated SignedSource<<7aaf0b32e40fe8c723a28ab9590b62b5>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -243,6 +243,20 @@ return {
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "lightLogoURL",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "darkLogoURL",
|
||||
"storageKey": null
|
||||
},
|
||||
(v3/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
@@ -275,7 +289,7 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "b31afd68395ae800a18885bca3abfa1c",
|
||||
"cacheID": "90e970007a500be89809ac0f2a77bccd",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
@@ -292,7 +306,7 @@ return {
|
||||
},
|
||||
"name": "FrameworkGraphListQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query FrameworkGraphListQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n frameworks(first: 100) {\n edges {\n node {\n id\n ...FrameworksPageCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n}\n"
|
||||
"text": "query FrameworkGraphListQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n frameworks(first: 100) {\n edges {\n node {\n id\n ...FrameworksPageCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n lightLogoURL\n darkLogoURL\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<8901b5c750861080551542d26c2681d6>>
|
||||
* @generated SignedSource<<6fcc115e1ab6df38ede8756968ae7a6a>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -123,6 +123,20 @@ return {
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "lightLogoURL",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "darkLogoURL",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -228,12 +242,12 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "29d6f638feb1bb633169abcfe083f5d2",
|
||||
"cacheID": "68c09567aff1176075300c645f5d117d",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "FrameworkGraphNodeQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query FrameworkGraphNodeQuery(\n $frameworkId: ID!\n) {\n node(id: $frameworkId) {\n __typename\n ... on Framework {\n id\n name\n ...FrameworkDetailPageFragment\n }\n id\n }\n}\n\nfragment FrameworkDetailPageFragment on Framework {\n id\n name\n description\n organization {\n name\n id\n }\n controls(first: 250, orderBy: {field: SECTION_TITLE, direction: ASC}) {\n edges {\n node {\n id\n sectionTitle\n name\n status\n exclusionJustification\n }\n }\n }\n}\n"
|
||||
"text": "query FrameworkGraphNodeQuery(\n $frameworkId: ID!\n) {\n node(id: $frameworkId) {\n __typename\n ... on Framework {\n id\n name\n ...FrameworkDetailPageFragment\n }\n id\n }\n}\n\nfragment FrameworkDetailPageFragment on Framework {\n id\n name\n description\n lightLogoURL\n darkLogoURL\n organization {\n name\n id\n }\n controls(first: 250, orderBy: {field: SECTION_TITLE, direction: ASC}) {\n edges {\n node {\n id\n sectionTitle\n name\n status\n exclusionJustification\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -25,14 +25,24 @@ import {
|
||||
IconArrowInbox,
|
||||
useConfirm,
|
||||
useToast,
|
||||
FrameworkLogo,
|
||||
} from "@probo/ui";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
import { FrameworkLogo } from "/components/FrameworkLogo";
|
||||
import { ControlledField } from "/components/form/ControlledField";
|
||||
import { useFormWithSchema } from "/hooks/useFormWithSchema";
|
||||
import z from "zod";
|
||||
import { getAuditStateLabel, getAuditStateVariant, auditStates, fileSize, sprintf, formatDatetime, formatError, formatDate, type GraphQLError } from "@probo/helpers";
|
||||
import {
|
||||
getAuditStateLabel,
|
||||
getAuditStateVariant,
|
||||
auditStates,
|
||||
fileSize,
|
||||
sprintf,
|
||||
formatDatetime,
|
||||
formatError,
|
||||
formatDate,
|
||||
type GraphQLError,
|
||||
} from "@probo/helpers";
|
||||
import type { AuditGraphNodeQuery } from "/hooks/graph/__generated__/AuditGraphNodeQuery.graphql";
|
||||
import { use } from "react";
|
||||
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||
@@ -42,7 +52,13 @@ const updateAuditSchema = z.object({
|
||||
name: z.string().nullable().optional(),
|
||||
validFrom: z.string().optional(),
|
||||
validUntil: z.string().optional(),
|
||||
state: z.enum(["NOT_STARTED", "IN_PROGRESS", "COMPLETED", "REJECTED", "OUTDATED"]),
|
||||
state: z.enum([
|
||||
"NOT_STARTED",
|
||||
"IN_PROGRESS",
|
||||
"COMPLETED",
|
||||
"REJECTED",
|
||||
"OUTDATED",
|
||||
]),
|
||||
});
|
||||
|
||||
type Props = {
|
||||
@@ -50,7 +66,10 @@ type Props = {
|
||||
};
|
||||
|
||||
export default function AuditDetailsPage(props: Props) {
|
||||
const audit = usePreloadedQuery<AuditGraphNodeQuery>(auditNodeQuery, props.queryRef);
|
||||
const audit = usePreloadedQuery<AuditGraphNodeQuery>(
|
||||
auditNodeQuery,
|
||||
props.queryRef
|
||||
);
|
||||
const auditEntry = audit.node;
|
||||
const { __ } = useTranslate();
|
||||
const organizationId = useOrganizationId();
|
||||
@@ -58,19 +77,20 @@ export default function AuditDetailsPage(props: Props) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const deleteAudit = useDeleteAudit(
|
||||
{ id: auditEntry.id!, framework: { name: auditEntry.framework!.name} },
|
||||
{ id: auditEntry.id!, framework: { name: auditEntry.framework!.name } },
|
||||
ConnectionHandler.getConnectionID(organizationId, "AuditsPage_audits"),
|
||||
() => navigate(`/organizations/${organizationId}/audits`)
|
||||
);
|
||||
|
||||
const { control, formState, handleSubmit, register, reset } = useFormWithSchema(updateAuditSchema, {
|
||||
defaultValues: {
|
||||
name: auditEntry.name || null,
|
||||
validFrom: auditEntry.validFrom?.split('T')[0] || "",
|
||||
validUntil: auditEntry.validUntil?.split('T')[0] || "",
|
||||
state: auditEntry.state || "NOT_STARTED",
|
||||
},
|
||||
});
|
||||
const { control, formState, handleSubmit, register, reset } =
|
||||
useFormWithSchema(updateAuditSchema, {
|
||||
defaultValues: {
|
||||
name: auditEntry.name || null,
|
||||
validFrom: auditEntry.validFrom?.split("T")[0] || "",
|
||||
validUntil: auditEntry.validUntil?.split("T")[0] || "",
|
||||
state: auditEntry.state || "NOT_STARTED",
|
||||
},
|
||||
});
|
||||
|
||||
const updateAudit = useUpdateAudit();
|
||||
const [uploadAuditReport, isUploading] = useUploadAuditReport();
|
||||
@@ -98,7 +118,10 @@ export default function AuditDetailsPage(props: Props) {
|
||||
} catch (error) {
|
||||
toast({
|
||||
title: __("Error"),
|
||||
description: formatError(__("Failed to update audit"), error as GraphQLError),
|
||||
description: formatError(
|
||||
__("Failed to update audit"),
|
||||
error as GraphQLError
|
||||
),
|
||||
variant: "error",
|
||||
});
|
||||
}
|
||||
@@ -131,7 +154,9 @@ export default function AuditDetailsPage(props: Props) {
|
||||
to: `/organizations/${organizationId}/audits`,
|
||||
},
|
||||
{
|
||||
label: (auditEntry.name || auditEntry.framework?.name) ?? __("Unknown Audit"),
|
||||
label:
|
||||
(auditEntry.name || auditEntry.framework?.name) ??
|
||||
__("Unknown Audit"),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
@@ -139,10 +164,16 @@ export default function AuditDetailsPage(props: Props) {
|
||||
<div className="flex justify-between items-start">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<FrameworkLogo name={auditEntry.framework?.name || ""} />
|
||||
<FrameworkLogo
|
||||
name={auditEntry.framework?.name || ""}
|
||||
lightLogoURL={auditEntry.framework?.lightLogoURL}
|
||||
darkLogoURL={auditEntry.framework?.darkLogoURL}
|
||||
/>
|
||||
<div className="text-2xl">{auditEntry.framework?.name}</div>
|
||||
</div>
|
||||
<Badge variant={getAuditStateVariant(auditEntry.state || "NOT_STARTED")}>
|
||||
<Badge
|
||||
variant={getAuditStateVariant(auditEntry.state || "NOT_STARTED")}
|
||||
>
|
||||
{getAuditStateLabel(__, auditEntry.state || "NOT_STARTED")}
|
||||
</Badge>
|
||||
</div>
|
||||
@@ -187,12 +218,10 @@ export default function AuditDetailsPage(props: Props) {
|
||||
</Field>
|
||||
|
||||
<div className="flex justify-end">
|
||||
{formState.isDirty && (
|
||||
isAuthorized("Audit", "updateAudit") && (
|
||||
<Button type="submit" disabled={formState.isSubmitting}>
|
||||
{formState.isSubmitting ? __("Updating...") : __("Update")}
|
||||
</Button>
|
||||
)
|
||||
{formState.isDirty && isAuthorized("Audit", "updateAudit") && (
|
||||
<Button type="submit" disabled={formState.isSubmitting}>
|
||||
{formState.isSubmitting ? __("Updating...") : __("Update")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
@@ -201,7 +230,7 @@ export default function AuditDetailsPage(props: Props) {
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-lg font-medium">{__("Audit Report")}</h3>
|
||||
|
||||
{auditEntry.report ? (
|
||||
{auditEntry.report ? (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between p-4 bg-success-50 border border-success-200 rounded-lg">
|
||||
<div className="flex items-center gap-3">
|
||||
@@ -211,11 +240,10 @@ export default function AuditDetailsPage(props: Props) {
|
||||
{auditEntry.report.filename}
|
||||
</p>
|
||||
<div className="flex items-center gap-4 text-sm text-success-700">
|
||||
<span>{fileSize(__, auditEntry.report.size)}</span>
|
||||
<span>
|
||||
{fileSize(__, auditEntry.report.size)}
|
||||
</span>
|
||||
<span>
|
||||
{__("Uploaded")} {formatDate(auditEntry.report.createdAt)}
|
||||
{__("Uploaded")}{" "}
|
||||
{formatDate(auditEntry.report.createdAt)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -224,7 +252,7 @@ export default function AuditDetailsPage(props: Props) {
|
||||
<DropdownItem
|
||||
onClick={() => {
|
||||
if (auditEntry.report?.downloadUrl) {
|
||||
window.open(auditEntry.report.downloadUrl, '_blank');
|
||||
window.open(auditEntry.report.downloadUrl, "_blank");
|
||||
}
|
||||
}}
|
||||
icon={IconArrowInbox}
|
||||
@@ -244,10 +272,14 @@ export default function AuditDetailsPage(props: Props) {
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
<p className="text-neutral-600">
|
||||
{__("Upload the final audit report document (PDF recommended)")}
|
||||
{__(
|
||||
"Upload the final audit report document (PDF recommended)"
|
||||
)}
|
||||
</p>
|
||||
<Dropzone
|
||||
description={__("Only PDF, DOCX files up to 25MB are allowed")}
|
||||
description={__(
|
||||
"Only PDF, DOCX files up to 25MB are allowed"
|
||||
)}
|
||||
isUploading={isUploading}
|
||||
onDrop={async (files) => {
|
||||
if (files.length > 0 && auditEntry.id) {
|
||||
|
||||
@@ -10,12 +10,12 @@ import {
|
||||
Button,
|
||||
ControlItem,
|
||||
DropdownItem,
|
||||
FrameworkLogo,
|
||||
IconPencil,
|
||||
IconPlusLarge,
|
||||
IconTrashCan,
|
||||
PageHeader,
|
||||
} from "@probo/ui";
|
||||
import { FrameworkLogo } from "/components/FrameworkLogo";
|
||||
import {
|
||||
connectionListKey,
|
||||
frameworkNodeQuery,
|
||||
@@ -39,6 +39,8 @@ const frameworkDetailFragment = graphql`
|
||||
id
|
||||
name
|
||||
description
|
||||
lightLogoURL
|
||||
darkLogoURL
|
||||
organization {
|
||||
name
|
||||
}
|
||||
@@ -70,12 +72,8 @@ const generateFrameworkStateOfApplicabilityMutation = graphql`
|
||||
`;
|
||||
|
||||
const exportFrameworkMutation = graphql`
|
||||
mutation FrameworkDetailPageExportFrameworkMutation(
|
||||
$frameworkId: ID!
|
||||
) {
|
||||
exportFramework(
|
||||
input: { frameworkId: $frameworkId }
|
||||
) {
|
||||
mutation FrameworkDetailPageExportFrameworkMutation($frameworkId: ID!) {
|
||||
exportFramework(input: { frameworkId: $frameworkId }) {
|
||||
exportJobId
|
||||
}
|
||||
}
|
||||
@@ -120,7 +118,8 @@ export default function FrameworkDetailPage(props: Props) {
|
||||
exportFrameworkMutation,
|
||||
{
|
||||
errorMessage: "Failed to export framework",
|
||||
successMessage: "Framework export started successfully. You will receive an email when the export is ready.",
|
||||
successMessage:
|
||||
"Framework export started successfully. You will receive an email when the export is ready.",
|
||||
}
|
||||
);
|
||||
|
||||
@@ -193,7 +192,11 @@ export default function FrameworkDetailPage(props: Props) {
|
||||
{__("Export Framework")}
|
||||
</DropdownItem>
|
||||
{isAuthorized("Framework", "deleteFramework") && (
|
||||
<DropdownItem icon={IconTrashCan} variant="danger" onClick={onDelete}>
|
||||
<DropdownItem
|
||||
icon={IconTrashCan}
|
||||
variant="danger"
|
||||
onClick={onDelete}
|
||||
>
|
||||
{__("Delete")}
|
||||
</DropdownItem>
|
||||
)}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
Card,
|
||||
DropdownItem,
|
||||
FileButton,
|
||||
FrameworkLogo,
|
||||
FrameworkSelector,
|
||||
IconFolderUpload,
|
||||
IconPencil,
|
||||
@@ -27,7 +28,6 @@ import { Link } from "react-router";
|
||||
import type { FrameworksPageCardFragment$key } from "./__generated__/FrameworksPageCardFragment.graphql";
|
||||
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
|
||||
import { useState, type ChangeEventHandler, use } from "react";
|
||||
import { FrameworkLogo } from "/components/FrameworkLogo";
|
||||
import { FrameworkFormDialog } from "./dialogs/FrameworkFormDialog";
|
||||
import { PermissionsContext } from "/providers/PermissionsContext";
|
||||
|
||||
@@ -120,7 +120,8 @@ export default function FrameworksPage(props: Props) {
|
||||
|
||||
const isLoading = isUploading || isImporting;
|
||||
|
||||
const hasAnyAction = isAuthorized("Framework", "updateFramework") ||
|
||||
const hasAnyAction =
|
||||
isAuthorized("Framework", "updateFramework") ||
|
||||
isAuthorized("Framework", "deleteFramework");
|
||||
|
||||
return (
|
||||
@@ -172,6 +173,8 @@ const frameworkCardFragment = graphql`
|
||||
id
|
||||
name
|
||||
description
|
||||
lightLogoURL
|
||||
darkLogoURL
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -200,7 +203,11 @@ function FrameworkCard(props: FrameworkCardProps) {
|
||||
framework={framework}
|
||||
/>
|
||||
<div className="flex justify-between mb-3">
|
||||
<FrameworkLogo {...framework} />
|
||||
<FrameworkLogo
|
||||
name={framework.name}
|
||||
lightLogoURL={framework.lightLogoURL}
|
||||
darkLogoURL={framework.darkLogoURL}
|
||||
/>
|
||||
{props.hasAnyAction && (
|
||||
<ActionDropdown className="z-10 relative">
|
||||
{isAuthorized("Framework", "updateFramework") && (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<daf4012a65afffdedc10e4f5c7e2bc3c>>
|
||||
* @generated SignedSource<<1da75e11f49e841800329ded9f67a1d4>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -24,8 +24,10 @@ export type FrameworkDetailPageFragment$data = {
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly darkLogoURL: string | null | undefined;
|
||||
readonly description: string | null | undefined;
|
||||
readonly id: string;
|
||||
readonly lightLogoURL: string | null | undefined;
|
||||
readonly name: string;
|
||||
readonly organization: {
|
||||
readonly name: string;
|
||||
@@ -67,6 +69,20 @@ return {
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "lightLogoURL",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "darkLogoURL",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -167,6 +183,6 @@ return {
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "c31fd5c0f675d2524f736d69c4ebebe3";
|
||||
(node as any).hash = "34a82531b8812ee16e75eb035bc739e8";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<9fdc712e118402371c9951169aac320a>>
|
||||
* @generated SignedSource<<412cc494e90709fca575c68f6deef112>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,8 +11,10 @@
|
||||
import { ReaderFragment } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type FrameworksPageCardFragment$data = {
|
||||
readonly darkLogoURL: string | null | undefined;
|
||||
readonly description: string | null | undefined;
|
||||
readonly id: string;
|
||||
readonly lightLogoURL: string | null | undefined;
|
||||
readonly name: string;
|
||||
readonly " $fragmentType": "FrameworksPageCardFragment";
|
||||
};
|
||||
@@ -47,12 +49,26 @@ const node: ReaderFragment = {
|
||||
"kind": "ScalarField",
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "lightLogoURL",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "darkLogoURL",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Framework",
|
||||
"abstractKey": null
|
||||
};
|
||||
|
||||
(node as any).hash = "4481f380673963e72f88071031e37d14";
|
||||
(node as any).hash = "fe86a14971741a77f587ae015ebf0a22";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<9436ef052ea63a9785d82ec810e810f1>>
|
||||
* @generated SignedSource<<2256362d89b6b5c2f5c707acb44d283e>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -158,6 +158,20 @@ return {
|
||||
"kind": "ScalarField",
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "lightLogoURL",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "darkLogoURL",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
@@ -187,12 +201,12 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "87a38788cb2e060657b552af69acb707",
|
||||
"cacheID": "5584472f1e68fac3d766662c6d5dab90",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "FrameworksPageImportMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation FrameworksPageImportMutation(\n $input: ImportFrameworkInput!\n) {\n importFramework(input: $input) {\n frameworkEdge {\n node {\n id\n ...FrameworksPageCardFragment\n }\n }\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n}\n"
|
||||
"text": "mutation FrameworksPageImportMutation(\n $input: ImportFrameworkInput!\n) {\n importFramework(input: $input) {\n frameworkEdge {\n node {\n id\n ...FrameworksPageCardFragment\n }\n }\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n lightLogoURL\n darkLogoURL\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<b8d5c939f1b3a4337be9a4ecc2e8fd98>>
|
||||
* @generated SignedSource<<af136d6db1a014d6241ad2c9c6dd5f55>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -159,6 +159,20 @@ return {
|
||||
"kind": "ScalarField",
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "lightLogoURL",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "darkLogoURL",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
@@ -188,12 +202,12 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "931895b4bbb7caacd8ee0ee69de76cd6",
|
||||
"cacheID": "c66177d87b59d87fdf7cbc9268af431a",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "FrameworkFormDialogMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation FrameworkFormDialogMutation(\n $input: CreateFrameworkInput!\n) {\n createFramework(input: $input) {\n frameworkEdge {\n node {\n id\n ...FrameworksPageCardFragment\n }\n }\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n}\n"
|
||||
"text": "mutation FrameworkFormDialogMutation(\n $input: CreateFrameworkInput!\n) {\n createFramework(input: $input) {\n frameworkEdge {\n node {\n id\n ...FrameworksPageCardFragment\n }\n }\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n lightLogoURL\n darkLogoURL\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user