diff --git a/.changeset/odd-plums-bake.md b/.changeset/odd-plums-bake.md
new file mode 100644
index 0000000000..427ab776b5
--- /dev/null
+++ b/.changeset/odd-plums-bake.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-adr-common': patch
+'@backstage/plugin-adr': patch
+---
+
+use path attribute to fetch files instead of name and update the UI to navigate over subdirectories
diff --git a/plugins/adr-common/src/index.ts b/plugins/adr-common/src/index.ts
index c3a048d9d1..cf71367cba 100644
--- a/plugins/adr-common/src/index.ts
+++ b/plugins/adr-common/src/index.ts
@@ -77,7 +77,7 @@ export type AdrFilePathFilterFn = (path: string) => boolean;
* @public
*/
export const madrFilePathFilter: AdrFilePathFilterFn = (path: string) =>
- /^\d{4}-.+\.md$/.test(path);
+ /^(?:.*\/)?\d{4}-.+\.md$/.test(path);
/**
* ADR indexable document interface
diff --git a/plugins/adr/package.json b/plugins/adr/package.json
index 05414dd8fb..a7763ae881 100644
--- a/plugins/adr/package.json
+++ b/plugins/adr/package.json
@@ -35,6 +35,7 @@
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.61",
"@types/react": "^16.13.1 || ^17.0.0",
+ "lodash": "^4.17.21",
"react-markdown": "^8.0.0",
"react-use": "^17.2.4",
"remark-gfm": "^3.0.1"
diff --git a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx
index eb5b4aed21..d136de4717 100644
--- a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx
+++ b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx
@@ -16,9 +16,14 @@
import React, { useEffect, useState } from 'react';
import { Link, useSearchParams } from 'react-router-dom';
+import useAsync from 'react-use/lib/useAsync';
+
+import groupBy from 'lodash/groupBy';
+
import {
Content,
ContentHeader,
+ InfoCard,
MissingAnnotationEmptyState,
Progress,
SupportButton,
@@ -35,27 +40,119 @@ import {
} from '@backstage/plugin-adr-common';
import { useEntity } from '@backstage/plugin-catalog-react';
import {
+ Box,
Chip,
+ Collapse,
Grid,
List,
ListItem,
+ ListItemIcon,
ListItemText,
makeStyles,
Theme,
Typography,
} from '@material-ui/core';
+import ExpandLess from '@material-ui/icons/ExpandLess';
+import ExpandMore from '@material-ui/icons/ExpandMore';
+import FolderIcon from '@material-ui/icons/Folder';
+import { adrApiRef, AdrFileInfo } from '../../api';
import { rootRouteRef } from '../../routes';
import { AdrContentDecorator, AdrReader } from '../AdrReader';
-import { adrApiRef } from '../../api';
-import useAsync from 'react-use/lib/useAsync';
const useStyles = makeStyles((theme: Theme) => ({
adrMenu: {
backgroundColor: theme.palette.background.paper,
},
+ adrContainerTitle: {
+ color: theme.palette.grey[700],
+ marginBottom: theme.spacing(1),
+ },
+ adrChip: {
+ position: 'absolute',
+ right: 0,
+ },
}));
+const AdrListContainer = (props: {
+ adrs: AdrFileInfo[];
+ selectedAdr: string;
+ title: string;
+}) => {
+ const { adrs, selectedAdr, title } = props;
+ const classes = useStyles();
+ const rootLink = useRouteRef(rootRouteRef);
+ const [open, setOpen] = React.useState(true);
+
+ const getChipColor = (status: string) => {
+ switch (status) {
+ case 'accepted':
+ return 'primary';
+ case 'rejected':
+ case 'deprecated':
+ return 'secondary';
+ default:
+ return 'default';
+ }
+ };
+
+ const handleClick = () => {
+ setOpen(!open);
+ };
+
+ return (
+ <>
+ {title && (
+
+
+
+
+
+ {open ? : }
+
+ )}
+
+
+ {adrs.map((adr, idx) => (
+
+
+ {adr.date}
+ {adr.status && (
+
+ )}
+
+ }
+ />
+
+ ))}
+
+
+ >
+ );
+};
+
/**
* Component for browsing ADRs on an entity page.
* @public
@@ -67,10 +164,7 @@ export const EntityAdrContent = (props: {
const { contentDecorators, filePathFilterFn } = props;
const classes = useStyles();
const { entity } = useEntity();
- const rootLink = useRouteRef(rootRouteRef);
- const [adrList, setAdrList] = useState<
- { name: string; title?: string; status?: string; date?: string }[]
- >([]);
+ const [adrList, setAdrList] = useState([]);
const [searchParams, setSearchParams] = useSearchParams();
const scmIntegrations = useApi(scmIntegrationsApiRef);
const adrApi = useApi(adrApiRef);
@@ -82,10 +176,15 @@ export const EntityAdrContent = (props: {
}, [entity, scmIntegrations]);
const selectedAdr =
- adrList.find(adr => adr.name === searchParams.get('record'))?.name ?? '';
+ adrList.find(adr => adr.path === searchParams.get('record'))?.path ?? '';
+
+ const adrSubDirectoryFunc = (adr: AdrFileInfo) => {
+ return adr.path.split('/').slice(0, -1).join('/');
+ };
+
useEffect(() => {
if (adrList.length && !selectedAdr) {
- searchParams.set('record', adrList[0].name);
+ searchParams.set('record', adrList[0].path);
setSearchParams(searchParams, { replace: true });
}
});
@@ -95,29 +194,20 @@ export const EntityAdrContent = (props: {
return;
}
- const adrs = value.data
- .filter(
- (item: { type: string; name: string }) =>
- item.type === 'file' &&
- (filePathFilterFn
- ? filePathFilterFn(item.name)
- : madrFilePathFilter(item.name)),
- )
- .map(({ name, title, status, date }) => ({ name, title, status, date }));
+ const adrs: AdrFileInfo[] = value.data.filter(
+ (item: AdrFileInfo) =>
+ item.type === 'file' &&
+ (filePathFilterFn
+ ? filePathFilterFn(item.path)
+ : madrFilePathFilter(item.path)),
+ );
setAdrList(adrs);
}, [filePathFilterFn, value]);
- const getChipColor = (status: string) => {
- switch (status) {
- case 'accepted':
- return 'primary';
- case 'rejected' || 'deprecated':
- return 'secondary';
- default:
- return 'default';
- }
- };
+ const adrListGrouped = Object.entries(
+ groupBy(adrList, adrSubDirectoryFunc),
+ ).sort();
return (
@@ -141,33 +231,18 @@ export const EntityAdrContent = (props: {
(adrList.length ? (
-
- {adrList.map((adr, idx) => (
-
-
+
+ {adrListGrouped.map(([title, adrs], idx) => (
+
- {adr.status && (
-
- )}
-
- ))}
-
+ ))}
+
+
diff --git a/yarn.lock b/yarn.lock
index 75f4a41905..367a00c90e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4356,6 +4356,7 @@ __metadata:
"@types/node": "*"
"@types/react": ^16.13.1 || ^17.0.0
cross-fetch: ^3.1.5
+ lodash: ^4.17.21
msw: ^1.0.0
react-markdown: ^8.0.0
react-use: ^17.2.4