diff --git a/packages/api-explorer/src/components/DocReferences/DocReferences.spec.tsx b/packages/api-explorer/src/components/DocReferences/DocReferences.spec.tsx index 7533e849d..b11a3a605 100644 --- a/packages/api-explorer/src/components/DocReferences/DocReferences.spec.tsx +++ b/packages/api-explorer/src/components/DocReferences/DocReferences.spec.tsx @@ -33,34 +33,42 @@ import { DocReferences } from './DocReferences' describe('DocReferences', () => { test('it renders method and type references', () => { - const seeTypes = typeRefs(api, api.types.Dashboard.customTypes) - const seeMethods = methodRefs(api, api.types.Dashboard.methodRefs) + const typesUsed = typeRefs(api, api.types.DashboardElement.customTypes) + const typesUsedBy = typeRefs(api, api.types.DashboardElement.parentTypes) + const methodsUsedBy = methodRefs(api, api.types.DashboardElement.methodRefs) renderWithSearchAndRouter( ) expect(screen.getAllByRole('link')).toHaveLength( - seeTypes.length + seeMethods.length + typesUsed.length + typesUsedBy.length + methodsUsedBy.length ) - expect(screen.getByText(seeTypes[0].name).closest('a')).toHaveAttribute( + expect(screen.getByText(typesUsed[0].name).closest('a')).toHaveAttribute( 'href', - `/3.1/types/${seeTypes[0].name}` + `/3.1/types/${typesUsed[0].name}` ) - expect(screen.getByText(seeMethods[0].name).closest('a')).toHaveAttribute( + + expect(typesUsedBy).toHaveLength(1) + expect(typesUsedBy[0].name).toEqual('Dashboard') + expect(screen.getByText(typesUsedBy[0].name).closest('a')).toHaveAttribute( 'href', - `/3.1/methods/Dashboard/${seeMethods[0].name}` + `/3.1/types/${typesUsedBy[0].name}` ) + expect( + screen.getByText(methodsUsedBy[0].name).closest('a') + ).toHaveAttribute('href', `/3.1/methods/Dashboard/${methodsUsedBy[0].name}`) }) test('it highlights text matching search pattern', () => { const highlightPattern = 'dash' renderWithSearchAndRouter( , diff --git a/packages/api-explorer/src/components/DocReferences/DocReferences.tsx b/packages/api-explorer/src/components/DocReferences/DocReferences.tsx index b6cfa07b4..edd18d659 100644 --- a/packages/api-explorer/src/components/DocReferences/DocReferences.tsx +++ b/packages/api-explorer/src/components/DocReferences/DocReferences.tsx @@ -33,8 +33,9 @@ import { CollapserCard } from '../Collapser' import { DocReferenceItems } from './utils' interface DocReferencesProps { - seeTypes: IType[] - seeMethods?: IMethod[] + typesUsed: IType[] + methodsUsedBy?: IMethod[] + typesUsedBy?: IType[] specKey: string api: ApiModel } @@ -43,16 +44,22 @@ interface DocReferencesProps { * It renders links to the given types and/or methods references */ export const DocReferences: FC = ({ - seeTypes, + typesUsed, specKey, api, - seeMethods = [], + methodsUsedBy = [], + typesUsedBy = [], }) => { const { searchSettings: { pattern }, } = useContext(SearchContext) - if (seeTypes.length === 0 && seeMethods.length === 0) return <> + if ( + typesUsed.length === 0 && + methodsUsedBy.length === 0 && + typesUsedBy.length === 0 + ) + return <> return ( @@ -60,14 +67,21 @@ export const DocReferences: FC = ({ <> {DocReferenceItems( 'Referenced Types:', - seeTypes, + typesUsed, + api, + specKey, + pattern + )} + {DocReferenceItems( + 'Used by types:', + typesUsedBy, api, specKey, pattern )} {DocReferenceItems( 'Used by methods:', - seeMethods, + methodsUsedBy, api, specKey, pattern diff --git a/packages/api-explorer/src/scenes/MethodScene/MethodScene.tsx b/packages/api-explorer/src/scenes/MethodScene/MethodScene.tsx index 9cb5cc7ba..74b7eeafe 100644 --- a/packages/api-explorer/src/scenes/MethodScene/MethodScene.tsx +++ b/packages/api-explorer/src/scenes/MethodScene/MethodScene.tsx @@ -111,7 +111,7 @@ export const MethodScene: FC = ({ api }) => { - + {sdk && value && ( diff --git a/packages/api-explorer/src/scenes/TypeScene/TypeScene.tsx b/packages/api-explorer/src/scenes/TypeScene/TypeScene.tsx index b26752982..cf4e9811c 100644 --- a/packages/api-explorer/src/scenes/TypeScene/TypeScene.tsx +++ b/packages/api-explorer/src/scenes/TypeScene/TypeScene.tsx @@ -50,8 +50,9 @@ interface DocTypeParams { export const TypeScene: FC = ({ api }) => { const { specKey, typeName } = useParams() const type = api.types[typeName] - const seeTypes = typeRefs(api, type.customTypes) - const seeMethods = methodRefs(api, type.methodRefs) + const typesUsed = typeRefs(api, type.customTypes) + const methodsUsedBy = methodRefs(api, type.methodRefs) + const typesUsedBy = typeRefs(api, type.parentTypes) return ( @@ -61,8 +62,9 @@ export const TypeScene: FC = ({ api }) => { diff --git a/packages/sdk-codegen/src/sdkModels.spec.ts b/packages/sdk-codegen/src/sdkModels.spec.ts index 3879b8172..f3a9506ec 100644 --- a/packages/sdk-codegen/src/sdkModels.spec.ts +++ b/packages/sdk-codegen/src/sdkModels.spec.ts @@ -732,6 +732,25 @@ describe('sdkModels', () => { describe('method and type xrefs', () => { describe('custom types', () => { + it('determines parent type of array types', () => { + const arrayType = apiTestModel.types.DashboardElement + const parents = arrayType.parentTypes + expect(parents).toEqual(new Set(['DashboardElement[]', 'Dashboard'])) + }) + + it('determines parent type of enum types', () => { + const enumType = apiTestModel.types.LinkedContentType + const parents = enumType.parentTypes + expect(parents).toEqual(new Set(['Command'])) + }) + + it('determines parent type of complex hash types', () => { + const hashProp = apiTestModel.types.ComplexHashProp + expect(hashProp.parentTypes).toEqual( + new Set(['Hash[ComplexHashProp]', 'ComplexHash']) + ) + }) + it('intrinsic types have undefined custom types', () => { const actual = new IntrinsicType('integer') expect(actual.customType).toEqual('') diff --git a/packages/sdk-codegen/src/sdkModels.ts b/packages/sdk-codegen/src/sdkModels.ts index e19c06e62..1ff4c3c6f 100644 --- a/packages/sdk-codegen/src/sdkModels.ts +++ b/packages/sdk-codegen/src/sdkModels.ts @@ -1541,10 +1541,12 @@ export class Type implements IType { // Track the "parent" reference for this type from the property reference propType.parentTypes.add(this.name) if ( - propType.instanceOf('ArrayType') && - propType.elementType?.instanceOf('EnumType') + propType.instanceOf('ArrayType') || + propType.instanceOf('HashType') ) { - propType.elementType.parentTypes.add(propType.name) + propType.elementType?.parentTypes.add(propType.name) + propType.elementType?.parentTypes.add(this.name) + propType.parentTypes.add(this.name) } this.types.add(propType.name) const customType = propType.customType diff --git a/test/openApiRef.json b/test/openApiRef.json index f66cfbb80..383443ed1 100644 --- a/test/openApiRef.json +++ b/test/openApiRef.json @@ -35124,6 +35124,27 @@ } }, "x-looker-status": "beta" + }, + "ComplexHash": { + "properties": { + "complex_prop": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ComplexHashProp" + }, + "description": "A complex hash prop ", + "nullable": false + } + } + }, + "ComplexHashProp": { + "properties": { + "id": { + "type": "string", + "description": "A simple string used to annotate a property in a complex hash", + "nullable": false + } + } } } }