@redocly/theme 0.58.0-next.0 → 0.58.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/lib/components/Buttons/CopyButton.d.ts +1 -0
  2. package/lib/components/Buttons/CopyButton.js +3 -3
  3. package/lib/components/Catalog/Catalog.js +14 -2
  4. package/lib/components/Catalog/CatalogEntitiesEmptyState.d.ts +2 -1
  5. package/lib/components/Catalog/CatalogEntitiesEmptyState.js +32 -11
  6. package/lib/components/Catalog/CatalogEntity/CatalogEntity.d.ts +3 -7
  7. package/lib/components/Catalog/CatalogEntity/CatalogEntity.js +13 -7
  8. package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +6 -6
  9. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityProperties.js +6 -10
  10. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/ContactProperty.js +5 -1
  11. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.d.ts +23 -0
  12. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.js +27 -0
  13. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityDefaultRelations.d.ts +3 -2
  14. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityDefaultRelations.js +2 -2
  15. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.js +11 -2
  16. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.d.ts +2 -1
  17. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.js +1 -1
  18. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTableContent.d.ts +2 -1
  19. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.js +2 -8
  20. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.d.ts +5 -2
  21. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +64 -30
  22. package/lib/components/Catalog/CatalogTableView/CatalogEntityRelationCell.d.ts +1 -1
  23. package/lib/components/Catalog/CatalogTableView/CatalogEntityRelationCell.js +2 -2
  24. package/lib/components/Catalog/variables.js +1 -1
  25. package/lib/components/Filter/FilterContent.d.ts +1 -1
  26. package/lib/core/constants/catalog.d.ts +1 -0
  27. package/lib/core/constants/catalog.js +28 -1
  28. package/lib/core/hooks/catalog/useCatalogEntitySchema.d.ts +11 -0
  29. package/lib/core/hooks/catalog/useCatalogEntitySchema.js +39 -0
  30. package/lib/core/types/catalog.d.ts +7 -0
  31. package/lib/core/types/filter.d.ts +1 -1
  32. package/lib/core/utils/change-text-casing.d.ts +1 -1
  33. package/lib/core/utils/change-text-casing.js +3 -0
  34. package/lib/ext/configure.d.ts +1 -0
  35. package/lib/ext/configure.js +4 -1
  36. package/lib/ext/useConfigureReplay.d.ts +18 -0
  37. package/lib/ext/useConfigureReplay.js +64 -0
  38. package/package.json +4 -3
  39. package/src/components/Buttons/CopyButton.tsx +4 -1
  40. package/src/components/Catalog/Catalog.tsx +15 -2
  41. package/src/components/Catalog/CatalogEntitiesEmptyState.tsx +39 -16
  42. package/src/components/Catalog/CatalogEntity/CatalogEntity.tsx +42 -14
  43. package/src/components/Catalog/CatalogEntity/CatalogEntityMetadata.tsx +8 -6
  44. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityProperties.tsx +15 -14
  45. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/ContactProperty.tsx +6 -1
  46. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.tsx +125 -0
  47. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityDefaultRelations.tsx +5 -1
  48. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.tsx +30 -3
  49. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.tsx +4 -3
  50. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTableContent.tsx +3 -1
  51. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.tsx +1 -13
  52. package/src/components/Catalog/CatalogEntity/CatalogEntitySchema.tsx +71 -23
  53. package/src/components/Catalog/CatalogTableView/CatalogEntityRelationCell.tsx +3 -3
  54. package/src/components/Catalog/variables.ts +1 -1
  55. package/src/components/Filter/FilterContent.tsx +3 -1
  56. package/src/core/constants/catalog.ts +28 -0
  57. package/src/core/hooks/catalog/useCatalogEntitySchema.ts +46 -0
  58. package/src/core/types/catalog.ts +9 -0
  59. package/src/core/types/filter.ts +3 -1
  60. package/src/core/utils/change-text-casing.ts +8 -1
  61. package/src/ext/configure.ts +5 -1
  62. package/src/ext/useConfigureReplay.ts +83 -0
  63. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/ApiDescriptionProperty.d.ts +0 -6
  64. package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/ApiDescriptionProperty.js +0 -32
  65. package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/ApiDescriptionProperty.tsx +0 -46
@@ -3,7 +3,11 @@ import styled from 'styled-components';
3
3
  import { CatalogEntityConfig, EntitiesCatalogConfig } from '@redocly/config';
4
4
  import { Route, Routes } from 'react-router-dom';
5
5
 
6
- import type { BffCatalogEntity, BffCatalogRelatedEntityList } from '@redocly/theme/core/types';
6
+ import type {
7
+ BffCatalogEntity,
8
+ BffCatalogRelatedEntity,
9
+ BffCatalogRelatedEntityList,
10
+ } from '@redocly/theme/core/types';
7
11
 
8
12
  import { breakpoints } from '@redocly/theme/core/utils';
9
13
  import { CatalogPageDescription } from '@redocly/theme/components/Catalog/CatalogPageDescription';
@@ -18,16 +22,22 @@ import { CatalogEntityMethodAndPath } from '@redocly/theme/components/Catalog/Ca
18
22
  import { CatalogEntityRelationsGraph } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsGraph.lazy';
19
23
 
20
24
  export type CatalogEntityProps = {
25
+ RedocSchema: React.ComponentType<any>;
26
+ StoreProvider: React.ComponentType<any>;
27
+ };
28
+
29
+ type CatalogEntityPageProps = {
30
+ status: 'success';
21
31
  entity: BffCatalogEntity;
32
+ relatedEntity: BffCatalogRelatedEntity | null;
33
+ relations: BffCatalogRelatedEntityList;
22
34
  entitiesCatalogConfig: EntitiesCatalogConfig;
23
35
  catalogConfig: CatalogEntityConfig;
24
- initialRelations: BffCatalogRelatedEntityList;
36
+ sharedDataIds?: Record<string, string>;
25
37
  };
26
38
 
27
- const renderEntityContent = (entity: BffCatalogEntity): React.ReactElement => {
39
+ const renderFirstColumnEntitySection = (entity: BffCatalogEntity): React.ReactElement => {
28
40
  switch (entity.type) {
29
- case 'data-schema':
30
- return <CatalogEntitySchema entity={entity} />;
31
41
  case 'api-operation':
32
42
  return <CatalogEntityMethodAndPath entity={entity} />;
33
43
  default:
@@ -35,14 +45,31 @@ const renderEntityContent = (entity: BffCatalogEntity): React.ReactElement => {
35
45
  }
36
46
  };
37
47
 
38
- export function CatalogEntity({
39
- entity,
40
- entitiesCatalogConfig,
41
- catalogConfig,
42
- initialRelations,
43
- }: CatalogEntityProps) {
44
- const { useTranslate, useCatalog } = useThemeHooks();
48
+ const renderDataSchemaSection = (
49
+ entity: BffCatalogEntity,
50
+ relatedEntity: BffCatalogRelatedEntity | null,
51
+ RedocSchema: React.ComponentType<any>,
52
+ StoreProvider: React.ComponentType<any>,
53
+ ): React.ReactElement | null => {
54
+ if (entity.type !== 'data-schema') {
55
+ return null;
56
+ }
57
+
58
+ return (
59
+ <CatalogEntitySchema
60
+ entity={entity}
61
+ relatedEntity={relatedEntity}
62
+ RedocSchema={RedocSchema}
63
+ StoreProvider={StoreProvider}
64
+ />
65
+ );
66
+ };
67
+
68
+ export function CatalogEntity({ RedocSchema, StoreProvider }: CatalogEntityProps) {
69
+ const { useTranslate, useCatalog, usePageProps } = useThemeHooks();
45
70
  const { translate } = useTranslate();
71
+ const { entity, relations, catalogConfig, entitiesCatalogConfig, relatedEntity } =
72
+ usePageProps<CatalogEntityPageProps>();
46
73
 
47
74
  const linkToMainCatalog = `catalogs/${catalogConfig.slug}`;
48
75
  const linkToMainCatalogLabel = translate(catalogConfig.titleTranslationKey);
@@ -71,15 +98,16 @@ export function CatalogEntity({
71
98
  tag={entity.key}
72
99
  />
73
100
  <CatalogEntityProperties entity={entity} />
101
+ {renderDataSchemaSection(entity, relatedEntity, RedocSchema, StoreProvider)}
74
102
  <CatalogTwoColumnsSection>
75
- {renderEntityContent(entity)}
103
+ {renderFirstColumnEntitySection(entity)}
76
104
  <CatalogEntityLinks entity={entity} />
77
105
  </CatalogTwoColumnsSection>
78
106
  <CatalogEntityRelations
79
107
  entity={entity}
80
108
  entitiesCatalogConfig={entitiesCatalogConfig}
81
109
  catalogConfig={catalogConfig}
82
- initialRelations={initialRelations}
110
+ initialRelations={relations}
83
111
  searchQuery={searchQuery}
84
112
  setSearchQuery={setSearchQuery}
85
113
  />
@@ -41,13 +41,15 @@ function renderMetadataValue(value: any): React.JSX.Element {
41
41
  export function CatalogEntityMetadata({ entity }: CatalogEntityMetadataProps) {
42
42
  const { useTranslate } = useThemeHooks();
43
43
  const { translate } = useTranslate();
44
- const { schema, ...metadataToShow } = entity.metadata || {};
45
- const metadata = Object.entries(metadataToShow);
44
+ const { schema, ...metadata } = entity.metadata || {};
45
+ const metadataToShow = Object.entries(metadata).filter(
46
+ ([key]) => !(entity.type === 'api-description' && key === 'descriptionFile'),
47
+ );
46
48
  const [isOn, setIsOn] = useState(false);
47
- const hasMoreItems = metadata.length > MAX_INITIAL_ITEMS;
48
- const visibleMetadata = isOn ? metadata : metadata.slice(0, MAX_INITIAL_ITEMS);
49
+ const hasMoreItems = metadataToShow.length > MAX_INITIAL_ITEMS;
50
+ const visibleMetadata = isOn ? metadataToShow : metadataToShow.slice(0, MAX_INITIAL_ITEMS);
49
51
 
50
- if (!metadata.length) {
52
+ if (!metadataToShow.length) {
51
53
  return null;
52
54
  }
53
55
 
@@ -102,7 +104,7 @@ const ArrayWrapper = styled.div`
102
104
  `;
103
105
 
104
106
  const Heading = styled.h2`
105
- margin-bottom: var(--spacing-base);
107
+ margin-bottom: var(--spacing-sm);
106
108
  margin-top: 0;
107
109
  font-size: var(--catalog-metadata-heading-size);
108
110
  `;
@@ -5,7 +5,6 @@ import { BffCatalogEntity } from '@redocly/theme/core/types';
5
5
  import { EntityTypeProperty } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityProperties/EntityTypeProperty';
6
6
  import { GitProperty } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityProperties/GitProperty';
7
7
  import { TagsProperty } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityProperties/TagsProperty';
8
- import { ApiDescriptionProperty } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityProperties/ApiDescriptionProperty';
9
8
  import { UserEmailProperty } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityProperties/UserEmailProperty';
10
9
  import { DomainsProperty } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityProperties/DomainsProperty';
11
10
  import { OwnersProperty } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityProperties/OwnersProperty';
@@ -44,11 +43,6 @@ const propertyRenderers: PropertyRenderer[] = [
44
43
  condition: (entity) => !!entity.tags?.length,
45
44
  component: TagsProperty,
46
45
  },
47
- {
48
- key: 'api-description',
49
- condition: (entity) => entity.type === 'api-description' && !!entity.metadata?.descriptionFile,
50
- component: ApiDescriptionProperty,
51
- },
52
46
  {
53
47
  key: 'user-email',
54
48
  condition: (entity) => entity.type === 'user' && !!entity.metadata?.email,
@@ -71,19 +65,26 @@ export type CatalogEntityPropertiesProps = {
71
65
  };
72
66
 
73
67
  export function CatalogEntityProperties({ entity }: CatalogEntityPropertiesProps): JSX.Element {
68
+ const renderers = propertyRenderers.filter((renderer) => renderer.condition(entity));
69
+
70
+ const gridTemplateColumns = [1, 2, 4].includes(renderers.length)
71
+ ? 'repeat(2, 1fr)'
72
+ : 'repeat(3, 1fr)';
73
+
74
74
  return (
75
- <CatalogEntityPropertiesGridWrapper data-component-name="Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityProperties">
76
- {propertyRenderers
77
- .filter((renderer) => renderer.condition(entity))
78
- .map((renderer) => (
79
- <renderer.component key={renderer.key + entity.id} entity={entity} />
80
- ))}
75
+ <CatalogEntityPropertiesGridWrapper
76
+ data-component-name="Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityProperties"
77
+ gridTemplateColumns={gridTemplateColumns}
78
+ >
79
+ {renderers.map((renderer) => (
80
+ <renderer.component key={renderer.key + entity.id} entity={entity} />
81
+ ))}
81
82
  </CatalogEntityPropertiesGridWrapper>
82
83
  );
83
84
  }
84
85
 
85
- const CatalogEntityPropertiesGridWrapper = styled.div`
86
+ const CatalogEntityPropertiesGridWrapper = styled.div<{ gridTemplateColumns: string }>`
86
87
  display: grid;
87
- grid-template-columns: repeat(auto-fill, minmax(325px, 1fr));
88
+ grid-template-columns: ${({ gridTemplateColumns }) => gridTemplateColumns};
88
89
  gap: var(--spacing-base);
89
90
  `;
@@ -27,7 +27,12 @@ export function ContactProperty({ entity }: ContactPropertyProps): JSX.Element {
27
27
  <Tag
28
28
  key={channel.name}
29
29
  textTransform="none"
30
- style={{ backgroundColor: 'var(--bg-color)' }}
30
+ style={{ backgroundColor: 'var(--bg-color)', cursor: 'pointer' }}
31
+ onClick={() => {
32
+ if (channel.url) {
33
+ window.open(channel.url, '_blank');
34
+ }
35
+ }}
31
36
  >
32
37
  {channel.name}
33
38
  </Tag>
@@ -0,0 +1,125 @@
1
+ import React, { JSX, ReactNode } from 'react';
2
+ import styled from 'styled-components';
3
+ import { CatalogEntityConfig, EntitiesCatalogConfig } from '@redocly/config';
4
+
5
+ import { Tabs, TabsSize } from '@redocly/theme/markdoc/components/Tabs/Tabs';
6
+ import { EntityTypeIcon } from '@redocly/theme/icons/EntityTypeIcon/EntityTypeIcon';
7
+ import { BffCatalogEntity, BffCatalogRelatedEntity, SortOption } from '@redocly/theme/core/types';
8
+ import { CatalogEntityDefaultRelations } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityDefaultRelations';
9
+ import { MoleculesIcon } from '@redocly/theme/icons/MoleculesIcon/MoleculesIcon';
10
+ import { NetworkIcon } from '@redocly/theme/icons/NetworkIcon/NetworkIcon';
11
+
12
+ export type CatalogEntityApiDescriptionRelationsProps = {
13
+ entity: BffCatalogEntity;
14
+ catalogConfig: CatalogEntityConfig;
15
+ entitiesCatalogConfig: EntitiesCatalogConfig;
16
+ relations: BffCatalogRelatedEntity[];
17
+ query: {
18
+ fetchNextPage: () => void;
19
+ isFetchingNextPage: boolean;
20
+ hasNextPage: boolean;
21
+ };
22
+ searchQuery: string;
23
+ setSearchQuery: (query: string) => void;
24
+ setFilter: (filter?: string) => void;
25
+ sortOption: SortOption | null;
26
+ setSortOption: (sortOption: SortOption | null) => void;
27
+ handleSortClick: (sortKey: string, direction: 'asc' | 'desc') => void;
28
+ isColumnSorted: (sortKey: string, direction: 'asc' | 'desc') => boolean;
29
+ shouldShowLoadMore: boolean;
30
+ };
31
+
32
+ export function CatalogEntityApiDescriptionRelations({
33
+ entity,
34
+ relations,
35
+ query,
36
+ searchQuery,
37
+ setSearchQuery,
38
+ setFilter,
39
+ entitiesCatalogConfig,
40
+ catalogConfig,
41
+ sortOption,
42
+ setSortOption,
43
+ handleSortClick,
44
+ isColumnSorted,
45
+ shouldShowLoadMore,
46
+ }: CatalogEntityApiDescriptionRelationsProps): JSX.Element {
47
+ return (
48
+ <div data-component-name="Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations">
49
+ <Tabs forceReady={relations.length > 0} size={TabsSize.MEDIUM}>
50
+ <TabItem
51
+ label="Operations"
52
+ icon={<MoleculesIcon />}
53
+ onClick={() => setFilter('type:api-operation')}
54
+ >
55
+ <CatalogEntityDefaultRelations
56
+ key="operations-table"
57
+ entity={entity}
58
+ relations={relations}
59
+ query={query}
60
+ searchQuery={searchQuery}
61
+ setSearchQuery={setSearchQuery}
62
+ entitiesCatalogConfig={entitiesCatalogConfig}
63
+ catalogConfig={catalogConfig}
64
+ sortOption={sortOption}
65
+ setSortOption={setSortOption}
66
+ handleSortClick={handleSortClick}
67
+ isColumnSorted={isColumnSorted}
68
+ shouldShowLoadMore={shouldShowLoadMore}
69
+ shouldShowHeading={false}
70
+ listType="api-operation"
71
+ />
72
+ </TabItem>
73
+ <TabItem
74
+ label="Schemas"
75
+ icon={<NetworkIcon />}
76
+ onClick={() => setFilter('type:data-schema')}
77
+ >
78
+ <CatalogEntityDefaultRelations
79
+ key="schemas-table"
80
+ entity={entity}
81
+ relations={relations}
82
+ query={query}
83
+ searchQuery={searchQuery}
84
+ setSearchQuery={setSearchQuery}
85
+ entitiesCatalogConfig={entitiesCatalogConfig}
86
+ catalogConfig={catalogConfig}
87
+ sortOption={sortOption}
88
+ setSortOption={setSortOption}
89
+ handleSortClick={handleSortClick}
90
+ isColumnSorted={isColumnSorted}
91
+ shouldShowLoadMore={shouldShowLoadMore}
92
+ shouldShowHeading={false}
93
+ listType="data-schema"
94
+ />
95
+ </TabItem>
96
+ <TabItem
97
+ label="Related entities"
98
+ icon={<EntityTypeIcon />}
99
+ onClick={() => setFilter('-type:api-operation,data-schema')}
100
+ >
101
+ <CatalogEntityDefaultRelations
102
+ key="related-entities-table"
103
+ entity={entity}
104
+ relations={relations}
105
+ query={query}
106
+ searchQuery={searchQuery}
107
+ setSearchQuery={setSearchQuery}
108
+ entitiesCatalogConfig={entitiesCatalogConfig}
109
+ catalogConfig={catalogConfig}
110
+ sortOption={sortOption}
111
+ setSortOption={setSortOption}
112
+ handleSortClick={handleSortClick}
113
+ isColumnSorted={isColumnSorted}
114
+ shouldShowLoadMore={shouldShowLoadMore}
115
+ shouldShowHeading={false}
116
+ />
117
+ </TabItem>
118
+ </Tabs>
119
+ </div>
120
+ );
121
+ }
122
+
123
+ const TabItem = styled.div<{ label: string; icon?: ReactNode }>`
124
+ padding: var(--spacing-sm);
125
+ `;
@@ -1,6 +1,8 @@
1
1
  import React, { JSX } from 'react';
2
2
  import { CatalogEntityConfig, EntitiesCatalogConfig } from '@redocly/config';
3
3
 
4
+ import type { ListType } from '@redocly/theme/core/types';
5
+
4
6
  import { BffCatalogEntity, BffCatalogRelatedEntity, SortOption } from '@redocly/theme/core/types';
5
7
  import { CatalogColumn } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogTableView';
6
8
  import { CatalogEntityCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogEntityCell';
@@ -49,13 +51,13 @@ export type CatalogEntityDefaultRelationsProps = {
49
51
  };
50
52
  searchQuery: string;
51
53
  setSearchQuery: (query: string) => void;
52
- setFilter: (filter: string) => void;
53
54
  sortOption: SortOption | null;
54
55
  setSortOption: (sortOption: SortOption | null) => void;
55
56
  handleSortClick: (sortKey: string, direction: 'asc' | 'desc') => void;
56
57
  isColumnSorted: (sortKey: string, direction: 'asc' | 'desc') => boolean;
57
58
  shouldShowLoadMore: boolean;
58
59
  shouldShowHeading?: boolean;
60
+ listType?: ListType;
59
61
  };
60
62
 
61
63
  export function CatalogEntityDefaultRelations({
@@ -72,6 +74,7 @@ export function CatalogEntityDefaultRelations({
72
74
  isColumnSorted,
73
75
  shouldShowLoadMore,
74
76
  shouldShowHeading = true,
77
+ listType,
75
78
  }: CatalogEntityDefaultRelationsProps): JSX.Element {
76
79
  return (
77
80
  <div data-component-name="Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityDefaultRelations">
@@ -90,6 +93,7 @@ export function CatalogEntityDefaultRelations({
90
93
  handleSortClick={handleSortClick}
91
94
  isColumnSorted={isColumnSorted}
92
95
  shouldShowLoadMore={shouldShowLoadMore}
96
+ listType={listType}
93
97
  />
94
98
  </div>
95
99
  );
@@ -1,10 +1,11 @@
1
- import React, { JSX, useState } from 'react';
1
+ import React, { JSX, useState, useEffect } from 'react';
2
2
  import { CatalogEntityConfig, EntitiesCatalogConfig } from '@redocly/config';
3
3
 
4
4
  import { BffCatalogEntity, BffCatalogRelatedEntityList } from '@redocly/theme/core/types';
5
5
  import { useThemeHooks } from '@redocly/theme/core/hooks';
6
6
  import { CatalogEntityDefaultRelations } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityDefaultRelations';
7
7
  import { CatalogEntityTeamRelations } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations';
8
+ import { CatalogEntityApiDescriptionRelations } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations';
8
9
 
9
10
  export type CatalogEntityRelationsProps = {
10
11
  entity: BffCatalogEntity;
@@ -18,6 +19,7 @@ export type CatalogEntityRelationsProps = {
18
19
  const LOAD_MORE_THRESHOLD = 10;
19
20
  const ENTITY_DEFAULT_FILTERS: Record<string, string> = {
20
21
  team: 'type:user',
22
+ 'api-description': 'type:api-operation',
21
23
  };
22
24
 
23
25
  export function CatalogEntityRelations({
@@ -30,7 +32,12 @@ export function CatalogEntityRelations({
30
32
  }: CatalogEntityRelationsProps): JSX.Element | null {
31
33
  const { useCatalogSort, useFetchCatalogEntitiesRelations } = useThemeHooks();
32
34
  const { sortOption, setSortOption, handleSortClick, isColumnSorted } = useCatalogSort();
33
- const [filter, setFilter] = useState<string>();
35
+
36
+ const [filter, setFilter] = useState<string | undefined>(ENTITY_DEFAULT_FILTERS[entity.type]);
37
+
38
+ useEffect(() => {
39
+ setFilter(ENTITY_DEFAULT_FILTERS[entity.key]);
40
+ }, [entity.key]);
34
41
 
35
42
  const { items: relations, query } = useFetchCatalogEntitiesRelations(
36
43
  {
@@ -38,6 +45,7 @@ export function CatalogEntityRelations({
38
45
  search: searchQuery,
39
46
  sort: sortOption ?? undefined,
40
47
  filter: filter ?? ENTITY_DEFAULT_FILTERS[entity.type],
48
+ limit: 10,
41
49
  },
42
50
  initialRelations,
43
51
  );
@@ -67,6 +75,26 @@ export function CatalogEntityRelations({
67
75
  />
68
76
  </div>
69
77
  );
78
+ case 'api-description':
79
+ return (
80
+ <div data-component-name="Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations/CatalogEntityApiDescriptionRelations">
81
+ <CatalogEntityApiDescriptionRelations
82
+ entity={entity}
83
+ catalogConfig={catalogConfig}
84
+ entitiesCatalogConfig={entitiesCatalogConfig}
85
+ relations={relations}
86
+ query={query}
87
+ searchQuery={searchQuery}
88
+ setSearchQuery={setSearchQuery}
89
+ setFilter={setFilter}
90
+ sortOption={sortOption}
91
+ setSortOption={setSortOption}
92
+ handleSortClick={handleSortClick}
93
+ isColumnSorted={isColumnSorted}
94
+ shouldShowLoadMore={shouldShowLoadMore}
95
+ />
96
+ </div>
97
+ );
70
98
  default:
71
99
  return (
72
100
  <div data-component-name="Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations/CatalogEntityDefaultRelations">
@@ -78,7 +106,6 @@ export function CatalogEntityRelations({
78
106
  query={query}
79
107
  searchQuery={searchQuery}
80
108
  setSearchQuery={setSearchQuery}
81
- setFilter={setFilter}
82
109
  sortOption={sortOption}
83
110
  setSortOption={setSortOption}
84
111
  handleSortClick={handleSortClick}
@@ -2,11 +2,12 @@ import React, { JSX } from 'react';
2
2
  import styled from 'styled-components';
3
3
  import { CatalogEntityConfig, EntitiesCatalogConfig } from '@redocly/config';
4
4
 
5
+ import type { ListType } from '@redocly/theme/core/types';
6
+
5
7
  import { BffCatalogEntity, BffCatalogRelatedEntity, SortOption } from '@redocly/theme/core/types';
6
8
  import { CatalogColumn } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogTableView';
7
9
  import { CatalogActionsRow } from '@redocly/theme/components/Catalog/CatalogActionsRow';
8
-
9
- import { CatalogEntityRelationsTableContent } from './CatalogEntityRelationsTableContent';
10
+ import { CatalogEntityRelationsTableContent } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTableContent';
10
11
 
11
12
  export type CatalogEntityRelationsTableProps = {
12
13
  entity: BffCatalogEntity;
@@ -26,7 +27,7 @@ export type CatalogEntityRelationsTableProps = {
26
27
  handleSortClick: (sortKey: string, direction: 'asc' | 'desc') => void;
27
28
  isColumnSorted: (sortKey: string, direction: 'asc' | 'desc') => boolean;
28
29
  shouldShowLoadMore: boolean;
29
- listType?: 'default' | 'team';
30
+ listType?: ListType;
30
31
  };
31
32
 
32
33
  export function CatalogEntityRelationsTable({
@@ -1,6 +1,8 @@
1
1
  import React, { JSX } from 'react';
2
2
  import { CatalogEntityConfig, EntitiesCatalogConfig } from '@redocly/config';
3
3
 
4
+ import type { ListType } from '@redocly/theme/core/types';
5
+
4
6
  import { ArrowDownIcon } from '@redocly/theme/icons/ArrowDownIcon/ArrowDownIcon';
5
7
  import { BffCatalogRelatedEntity, SortOption } from '@redocly/theme/core/types';
6
8
  import { LoadMore } from '@redocly/theme/components/LoadMore/LoadMore';
@@ -26,7 +28,7 @@ export type CatalogEntityRelationsTableContentProps = {
26
28
  handleSortClick: (sortKey: string, direction: 'asc' | 'desc') => void;
27
29
  isColumnSorted: (sortKey: string, direction: 'asc' | 'desc') => boolean;
28
30
  shouldShowLoadMore: boolean;
29
- listType?: 'default' | 'team';
31
+ listType?: ListType;
30
32
  };
31
33
 
32
34
  export function CatalogEntityRelationsTableContent({
@@ -11,7 +11,6 @@ import { Tag } from '@redocly/theme/components/Tag/Tag';
11
11
  import { CatalogEntityRelationsTable } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable';
12
12
  import { CatalogUserEntityCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogUserEntityCell';
13
13
  import { CatalogEntityDefaultRelations } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityDefaultRelations';
14
- import { CatalogEntityRelationCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogEntityRelationCell';
15
14
 
16
15
  const teamColumns: CatalogColumn<BffCatalogRelatedEntity>[] = [
17
16
  {
@@ -30,16 +29,6 @@ const teamColumns: CatalogColumn<BffCatalogRelatedEntity>[] = [
30
29
  render: (entity) => (entity.metadata?.role ? <Tag>{entity.metadata?.role}</Tag> : null),
31
30
  width: '2fr',
32
31
  },
33
- {
34
- key: 'relationType',
35
- title: 'Relations',
36
- render: (entity) => (
37
- <CatalogEntityRelationCell
38
- relationType={entity.relationType}
39
- relationRole={entity.relationRole}
40
- />
41
- ),
42
- },
43
32
  {
44
33
  key: 'description',
45
34
  title: 'Description',
@@ -117,7 +106,6 @@ export function CatalogEntityTeamRelations({
117
106
  query={query}
118
107
  searchQuery={searchQuery}
119
108
  setSearchQuery={setSearchQuery}
120
- setFilter={setFilter}
121
109
  entitiesCatalogConfig={entitiesCatalogConfig}
122
110
  catalogConfig={catalogConfig}
123
111
  sortOption={sortOption}
@@ -134,7 +122,7 @@ export function CatalogEntityTeamRelations({
134
122
  }
135
123
 
136
124
  const TabItem = styled.div<{ label: string; icon?: ReactNode }>`
137
- padding: 12px;
125
+ padding: var(--spacing-sm);
138
126
  `;
139
127
 
140
128
  const EntityDescription = styled.div`
@@ -1,36 +1,57 @@
1
1
  import React from 'react';
2
2
  import styled from 'styled-components';
3
+ import * as Sampler from 'openapi-sampler';
3
4
 
4
- import { BffCatalogEntity } from '@redocly/theme/core/types';
5
+ import { BffCatalogEntity, BffCatalogRelatedEntity } from '@redocly/theme/core/types';
5
6
  import { useThemeHooks } from '@redocly/theme/core/hooks';
7
+ import { useCatalogEntitySchema } from '@redocly/theme/core/hooks/catalog/useCatalogEntitySchema';
6
8
  import { JsonViewer } from '@redocly/theme/components/JsonViewer/JsonViewer';
9
+ import { CopyButton } from '@redocly/theme/components/Buttons/CopyButton';
7
10
 
8
11
  export type CatalogEntitySchemaProps = {
9
12
  entity: BffCatalogEntity;
13
+ relatedEntity: BffCatalogRelatedEntity | null;
14
+ RedocSchema: React.ComponentType<any>;
15
+ StoreProvider: React.ComponentType<any>;
10
16
  };
11
17
 
12
- export function CatalogEntitySchema({ entity }: CatalogEntitySchemaProps) {
18
+ export function CatalogEntitySchema({
19
+ entity,
20
+ relatedEntity,
21
+ RedocSchema,
22
+ StoreProvider,
23
+ }: CatalogEntitySchemaProps) {
13
24
  const { useTranslate } = useThemeHooks();
14
25
  const { translate } = useTranslate();
15
- const { schema, ...metadataToShow } = entity.metadata || {};
16
- const metadata = Object.entries(metadataToShow);
17
-
18
- if (!metadata.length) {
19
- return null;
20
- }
21
-
22
- let parsedSchema;
23
-
24
- try {
25
- parsedSchema = JSON.parse(schema);
26
- } catch (error) {
27
- return null;
28
- }
26
+ const { definition, parsedSchema, rawSchema } = useCatalogEntitySchema({ entity, relatedEntity });
29
27
 
30
28
  return (
31
29
  <MetadataWrapper data-component-name="Catalog/CatalogEntity/CatalogEntityMetadata">
32
- <Heading>{translate('catalog.entity.metadata.title')}</Heading>
33
- <JsonViewer data={parsedSchema} expandLevel={3} title="JSON" />
30
+ <HeaderWrapper>
31
+ <Heading>{translate('catalog.entity.schema.title')}</Heading>
32
+ <CopyButton
33
+ data={rawSchema}
34
+ buttonText="Copy Schema"
35
+ type="compound"
36
+ variant="secondary"
37
+ iconPosition="right"
38
+ size="medium"
39
+ ></CopyButton>
40
+ </HeaderWrapper>
41
+ <SplitViewWrapper>
42
+ <SchemaContentWrapper>
43
+ <StoreProvider definition={definition}>
44
+ <RedocSchema schema={parsedSchema} />
45
+ </StoreProvider>
46
+ </SchemaContentWrapper>
47
+ <SchemaSampleWrapper>
48
+ <JsonViewer
49
+ data={Sampler.sample({ ...parsedSchema })}
50
+ expandLevel={3}
51
+ hideHeader={false}
52
+ />
53
+ </SchemaSampleWrapper>
54
+ </SplitViewWrapper>
34
55
  </MetadataWrapper>
35
56
  );
36
57
  }
@@ -38,15 +59,42 @@ export function CatalogEntitySchema({ entity }: CatalogEntitySchemaProps) {
38
59
  const MetadataWrapper = styled.div`
39
60
  display: flex;
40
61
  flex-direction: column;
41
- gap: var(--spacing-xs);
42
62
  border-radius: var(--border-radius);
43
63
  background-color: var(--catalog-metadata-bg-color);
44
- transition: all 0.2s ease-in-out;
45
- margin: var(--spacing-lg) 0;
64
+ margin-top: var(--spacing-base);
65
+ margin-bottom: var(--spacing-xs);
66
+ `;
67
+
68
+ const SchemaContentWrapper = styled.div`
69
+ flex: 1;
70
+ & > div > div {
71
+ padding-left: 0;
72
+ padding-top: 0;
73
+ }
74
+ `;
75
+
76
+ const HeaderWrapper = styled.div`
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: space-between;
80
+ gap: var(--spacing-sm);
46
81
  `;
47
82
 
48
83
  const Heading = styled.h2`
49
- margin-bottom: var(--spacing-base);
50
- margin-top: 0;
51
84
  font-size: var(--catalog-metadata-heading-size);
52
85
  `;
86
+
87
+ const SplitViewWrapper = styled.div`
88
+ display: flex;
89
+ justify-content: space-between;
90
+ align-items: flex-start;
91
+ gap: var(--spacing-base);
92
+ `;
93
+
94
+ const SchemaSampleWrapper = styled.div`
95
+ flex: 1;
96
+ position: sticky;
97
+ top: calc(var(--navbar-height) + var(--spacing-md));
98
+ align-self: flex-start;
99
+ padding-top: var(--spacing-sm);
100
+ `;
@@ -1,6 +1,6 @@
1
1
  import type { BffCatalogRelatedEntity } from '@redocly/theme/core/types';
2
2
 
3
- import { reverseRelationMap } from '@redocly/theme/core/constants';
3
+ import { reverseRelationMap, relationTypeMap } from '@redocly/theme/core/constants';
4
4
 
5
5
  export type CatalogEntityRelationCellProps = Pick<
6
6
  BffCatalogRelatedEntity,
@@ -12,8 +12,8 @@ export function CatalogEntityRelationCell({
12
12
  relationRole,
13
13
  }: CatalogEntityRelationCellProps) {
14
14
  if (relationRole === 'source') {
15
- return reverseRelationMap[relationType];
15
+ return relationTypeMap[reverseRelationMap[relationType]];
16
16
  }
17
17
 
18
- return relationType;
18
+ return relationTypeMap[relationType];
19
19
  }