-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
430 additions
and
313 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import { Error, Feedback, Warning } from '@mui/icons-material'; | ||
import { Stack, Typography } from '@mui/material'; | ||
import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; | ||
import { TreeItem2 as TreeItem } from '@mui/x-tree-view/TreeItem2'; | ||
import { groupToMapBy } from '@seedcompany/common'; | ||
import Markdown, { MarkdownToJSX } from 'markdown-to-jsx'; | ||
import { memo } from 'react'; | ||
import { PnpProblemSeverity as Severity } from '~/api/schema.graphql'; | ||
import { InlineCode } from '../Debug'; | ||
import { FormattedNumber } from '../Formatters'; | ||
import { Link } from '../Routing'; | ||
import { PnpProblemFragment as Problem } from './pnpExtractionResult.graphql'; | ||
|
||
export interface ProblemTreeProps { | ||
problems: readonly Problem[]; | ||
} | ||
export const ProblemTree = memo(function ProblemTree({ | ||
problems, | ||
}: ProblemTreeProps) { | ||
return ( | ||
<SimpleTreeView itemChildrenIndentation={6 * 8}> | ||
<ProblemList groupIndex={1} problems={problems} /> | ||
</SimpleTreeView> | ||
); | ||
}); | ||
|
||
export const ProblemList = memo(function ProblemList({ | ||
problems, | ||
groupIndex, | ||
}: ProblemTreeProps & { | ||
groupIndex: number; | ||
}) { | ||
return [...groupToMapBy(problems, (p) => p.groups[groupIndex])].map( | ||
([group, problems]) => { | ||
const { severity } = problems[0]; | ||
if (group && (groupIndex === 1 || problems.length > 1)) { | ||
const currentNode = | ||
groupIndex === 1 ? ( | ||
<Stack direction="row" gap={1} alignItems="center"> | ||
<SeverityIcon severity={severity} /> | ||
<div> | ||
(<FormattedNumber value={problems.length} />){' '} | ||
<Markdown options={mdOptions}>{group}</Markdown> | ||
<Doc problem={problems[0]} /> | ||
</div> | ||
</Stack> | ||
) : ( | ||
<Markdown options={mdOptions}>{group}</Markdown> | ||
); | ||
|
||
return ( | ||
<TreeItem key={group} itemId={group} label={currentNode}> | ||
<ProblemList problems={problems} groupIndex={groupIndex + 1} /> | ||
</TreeItem> | ||
); | ||
} else { | ||
return problems.map((problem) => ( | ||
<TreeItem | ||
key={problem.id} | ||
itemId={problem.id} | ||
label={ | ||
<Stack direction="row" gap={1} alignItems="center"> | ||
{groupIndex === 1 && <SeverityIcon severity={severity} />} | ||
<div> | ||
<Markdown options={mdOptions}>{problem.message}</Markdown> | ||
{groupIndex === 1 && <Doc problem={problem} />} | ||
</div> | ||
</Stack> | ||
} | ||
/> | ||
)); | ||
} | ||
} | ||
); | ||
}); | ||
|
||
const mdOptions: MarkdownToJSX.Options = { | ||
forceInline: true, | ||
overrides: { | ||
code: InlineCode, | ||
}, | ||
}; | ||
|
||
function Doc({ problem }: { problem: Problem }) { | ||
if (!problem.documentation) { | ||
return null; | ||
} | ||
return ( | ||
<Typography color="text.secondary" sx={{ mt: 1 }}> | ||
For more information see the PnP Troubleshooting{' '} | ||
<Link external to={problem.documentation} target="_blank"> | ||
Guide | ||
</Link> | ||
</Typography> | ||
); | ||
} | ||
|
||
const SeverityIcon = ({ severity }: { severity: Severity }) => { | ||
if (severity === 'Error') { | ||
return <Error color="error" />; | ||
} | ||
if (severity === 'Warning') { | ||
return <Warning color="warning" />; | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition | ||
if (severity === 'Notice') { | ||
return <Feedback color="info" />; | ||
} | ||
|
||
return null; | ||
}; |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { DialogContent, IconButtonProps } from '@mui/material'; | ||
import { cmpBy } from '@seedcompany/common'; | ||
import { ComponentType, useMemo } from 'react'; | ||
import { PnpProblemSeverity as Severity } from '~/api/schema.graphql'; | ||
import { ChildrenProp } from '../../common'; | ||
import { useDialog } from '../Dialog'; | ||
import { ProblemTree, ProblemTreeProps } from './PnPExtractionProblems'; | ||
import { | ||
PnpExtractionResultFragment, | ||
PnpExtractionResultFragment as Result, | ||
} from './pnpExtractionResult.graphql'; | ||
import { PnPExtractionResultDialog } from './PnpExtractionResultDialog'; | ||
import { PnPValidationIcon } from './PnpValidationIcon'; | ||
|
||
export const PnPValidation = ({ | ||
result, | ||
slots, | ||
}: { | ||
result: PnpExtractionResultFragment; | ||
slots?: { | ||
dialogContent?: ComponentType<ChildrenProp>; | ||
problems?: ComponentType<ProblemTreeProps>; | ||
}; | ||
} & Pick<IconButtonProps, 'size'>) => { | ||
const [dialog, open] = useDialog(); | ||
|
||
const problems = useMemo(() => problemsToShow(result), [result]); | ||
|
||
const Content = slots?.dialogContent ?? DialogContent; | ||
const ProblemList = slots?.problems ?? ProblemTree; | ||
|
||
return ( | ||
<> | ||
<PnPValidationIcon problems={problems} size="small" onClick={open} /> | ||
<PnPExtractionResultDialog fullWidth {...dialog}> | ||
<Content> | ||
<ProblemList problems={problems} /> | ||
</Content> | ||
</PnPExtractionResultDialog> | ||
</> | ||
); | ||
}; | ||
|
||
const problemsToShow = (result: Result) => { | ||
// Temporarily filter out problems with "Notice" severity | ||
const filteredProblems = result.problems.filter( | ||
(problem) => problem.severity !== 'Notice' | ||
); | ||
|
||
return filteredProblems.toSorted( | ||
cmpBy((problem) => priority.indexOf(problem.severity)) | ||
); | ||
}; | ||
|
||
const priority = ['Error', 'Warning', 'Notice'] satisfies Severity[]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { Check, Error, Warning } from '@mui/icons-material'; | ||
import { Badge, IconButton, IconButtonProps, Tooltip } from '@mui/material'; | ||
import { groupToMapBy } from '@seedcompany/common'; | ||
import { PnpProblemSeverity as Severity } from '~/api/schema.graphql'; | ||
import { useNumberFormatter } from '../Formatters'; | ||
import { PnpProblemFragment as Problem } from './pnpExtractionResult.graphql'; | ||
|
||
export const PnPValidationIcon = ({ | ||
problems, | ||
...props | ||
}: { | ||
problems: readonly Problem[]; | ||
} & IconButtonProps) => { | ||
const bySev = groupToMapBy(problems, (p) => p.severity); | ||
|
||
const formatNumber = useNumberFormatter(); | ||
const count = (sev: Severity) => formatNumber(bySev.get(sev)!.length); | ||
|
||
const { Icon, color, badge, title } = bySev.has('Error') | ||
? { | ||
Icon: Error, | ||
color: 'error' as const, | ||
badge: count('Error'), | ||
title: `${count('Error')} error(s)`, | ||
} | ||
: bySev.has('Warning') | ||
? { | ||
Icon: Warning, | ||
color: 'warning' as const, | ||
badge: count('Warning'), | ||
title: `${count('Warning')} warning(s)`, | ||
} | ||
: { | ||
Icon: Check, | ||
color: 'success' as const, | ||
badge: undefined, | ||
title: 'Validation Passed!', | ||
}; | ||
|
||
return ( | ||
<Tooltip title={title}> | ||
<Badge badgeContent={badge} max={Infinity}> | ||
<IconButton color={color} {...props}> | ||
<Icon /> | ||
</IconButton> | ||
</Badge> | ||
</Tooltip> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { TabContext, TabList, TabPanel } from '@mui/lab'; | ||
import { Box, Tab } from '@mui/material'; | ||
import { groupToMapBy } from '@seedcompany/common'; | ||
import { memo, ReactNode, useState } from 'react'; | ||
import { ProblemTreeProps } from './PnPExtractionProblems'; | ||
|
||
export const ProblemsWithSheetsAsTabs = memo(function ProblemsWithSheetsAsTabs({ | ||
problems, | ||
children, | ||
}: ProblemTreeProps & { | ||
children: (props: ProblemTreeProps & { sheet: string }) => ReactNode; | ||
}) { | ||
const bySheet = groupToMapBy(problems, (p) => p.groups[0]!); | ||
const [tab, setTab] = useState(bySheet.keys().next().value); | ||
|
||
return ( | ||
<TabContext value={tab}> | ||
<Box sx={{ pl: 1, borderBottom: 1, borderColor: 'divider' }}> | ||
<TabList onChange={(_, next) => setTab(next)}> | ||
{[...bySheet.keys()].toSorted().map((sheet) => ( | ||
<Tab key={sheet} value={sheet} label={sheet} /> | ||
))} | ||
</TabList> | ||
</Box> | ||
{[...bySheet].map(([sheet, problems]) => ( | ||
<TabPanel key={sheet} value={sheet} sx={{ p: 1 }}> | ||
{children({ sheet, problems })} | ||
</TabPanel> | ||
))} | ||
</TabContext> | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,5 @@ fragment pnpProblem on PnpProblem { | |
severity | ||
message | ||
groups | ||
documentation | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Preview as PreviewIcon } from '@mui/icons-material'; | ||
import { IconButton, Tooltip } from '@mui/material'; | ||
import { NonDirectoryActionItem as File, useFileActions } from '../FileActions'; | ||
|
||
export const PreviewIconButton = ({ file }: { file: File }) => { | ||
const { openFilePreview } = useFileActions(); | ||
return ( | ||
<Tooltip title="Preview"> | ||
<IconButton onClick={() => openFilePreview(file)} size="small"> | ||
<PreviewIcon /> | ||
</IconButton> | ||
</Tooltip> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.