React Components for extensions Catalog
Description As part of the "MVP integration of extensions catalog with AsyncAPI tools to make extension catalog useful" mentorhsip program, detailed here https://github.com/asyncapi/extensions-catalog/issues/78. We would like to add react component to visualize the extensions catalog.
Reasons
Extensions are part of the spec. So we need to create react component to compile theses extensions as a part of the AsyncAPI spec. So basically, this functionnality allow us to have suggestions on the existed extensions and to be able to add them when we are writing our code.
We would like to know how and where in the code would be the best way to provide extensions-related components. Now we are working on the twitter extension, we want to expose at the first time this one, you can check it here : https://github.com/asyncapi/extensions-catalog/pull/112 ( we are still working on their format).
Welcome to AsyncAPI. Thanks a lot for reporting your first issue. Please check out our contributors guide and the instructions about a basic recommended setup useful for opening a pull request.
Keep in mind there are also other channels you can use to interact with AsyncAPI community. For more details check out this issue.
The best place to write components will be there https://github.com/asyncapi/asyncapi-react/blob/master/library/src/components/Extensions.tsx However props to the component (root component, not mentioned in link) should have also option to pass custom components to render another extensions, written by user of component.
My idea:
-
component has registry of extension components, like
TwitterExtension- we can addextensionsproperty on the config to theAsyncAPIComponent. It should be simple JS object. -
inside
Extensionscomponent we try to retrieve the proper component for given extension:const { extensions } = useConfig() const ExtensionComponent = extensions[extension]of course we need to change the logic in the current
Extensionscomponent -
pass to the custom component, the extension value, asyncapi document, maybe also config passed to the root component and parent model (where extensions are defined) from parser-js
-
when registry won't have custom component, we should render extension as normal JSON Schema - like here https://github.com/asyncapi/asyncapi-react/blob/master/library/src/components/Extensions.tsx#L25
cc @derberg @Min2who @sambhavgupta0705
sounds good to me, @sambhavgupta0705 feel free to ask more followup questions
@magicmatatjahu is there any previous work or PR from which I can better understand about this
just a friendly reminder @magicmatatjahu
@sambhavgupta0705 Nope, maybe there was but I wasn't involved.
@magicmatatjahu need more clarification on these two points
- component has registry of extension components, like TwitterExtension - we can add extensions property on the config to the AsyncAPIComponent. It should be simple JS object.
- pass to the custom component, the extension value, asyncapi document, maybe also config passed to the root component and parent model (where extensions are defined) from parser-js
@sambhavgupta0705
component has registry of extension components, like TwitterExtension - we can add extensions property on the config to the AsyncAPIComponent. It should be simple JS object.
To the AsyncAPIComponent you can pass config property, we need to extend shape (interface) of that property with extensions field so https://github.com/asyncapi/asyncapi-react/blob/master/library/src/config/config.ts#L1 should has additional field:
extensions: Record<string, React.ComponentType<ExtensionComponentProps>>;
Have in mind that types can be wrong, however I hope you will understand idea.
pass to the custom component, the extension value, asyncapi document, maybe also config passed to the root component and parent model (where extensions are defined) from parser-js
To the React components you can pass properties, we need to define ExtensionComponentProps interface with shape:
interface ExtensionComponentProps {
key: string; // extension key
value: any; // extension value
document: AsyncAPIDocument // value from `useSpec()` hook
config: ConfigInterface // config from `useConfig()` hook
parent: any // parent model
}
so every extension component will have that values, passed from https://github.com/asyncapi/asyncapi-react/blob/master/library/src/components/Extensions.tsx component perspective.
Any additional questions?
To the AsyncAPIComponent you can pass config property, we need to extend shape (interface) of that property with extensions field so https://github.com/asyncapi/asyncapi-react/blob/master/library/src/config/config.ts#L1 should has additional field:
for this I added extensions in configInterface is that correct?
@magicmatatjahu for MVP wouldn't it be better if by config, people just pass an array of extension names, and we internally handle it, understand and apply certain component? So MVP would be without enabling to pass a custom component to AsyncAPIComponent?
@derberg @sambhavgupta0705
for MVP wouldn't it be better if by config, people just pass an array of extension names, and we internally handle it, understand and apply certain component? So MVP would be without enabling to pass a custom component to AsyncAPIComponent?
I would prefer to avoid this situation, because passing a map is as simple and uncomplicated as an array.
for this I added extensions in configInterface is that correct?
No, I added you good type:
extensions: Record<string, React.ComponentType<ExtensionComponentProps>>
then you should define type for properties for custom component (which is used above):
import type { AsyncAPIDocumentInterface, BaseModel } from "@asyncapi/parser"
import type { ConfigInterface } from "../config"
export interface ExtensionComponentProps<V = any> {
key: string; // extension key
value: V; // extension value
document: AsyncAPIDocumentInterface // parsed spec
config: ConfigInterface // config from `useConfig()` hook
parent: BaseModel // parent model
}
define that type inside https://github.com/asyncapi/asyncapi-react/blob/master/library/src/components/Extensions.tsx file
Then you should write simple logic to retrieve given custom component for extension (inside https://github.com/asyncapi/asyncapi-react/blob/master/library/src/components/Extensions.tsx component). I added comments in places where you should write logic):
import React from 'react';
import { Schema } from './Schema';
import { SchemaHelpers } from '../helpers';
import { useConfig, useSpec } from '../contexts';
interface ExtensionsProps {
name?: string;
item: any;
}
export const Extensions: React.FunctionComponent<ExtensionsProps> = ({
name = 'Extensions',
item,
}) => {
const config = useSpec();
const document = useConfig();
const extensionsValues = SchemaHelpers.getCustomExtensions(item);
if (!extensionsValues || !Object.keys(extensionsValues).length) {
return null;
}
const extensions = config.extensions;
// you have config, document, parent model ("item" property).
// you should make for loop to read all keys from "extensionsValues" and create ReactNode based on the key (the
// component you should read from "extensions" dictionary). If you will have "undefined" for component
// (component won't exist), then you should use "Schema" component (used below) as the fallback
// change return logic to render proper components
const schema = SchemaHelpers.jsonToSchema(extensions);
return (
schema && (
<div className="mt-2">
<Schema schemaName={name} schema={schema} onlyTitle={true} />
</div>
)
);
};
Hello, @magicmatatjahu! 👋🏼
I'm 🧞🧞🧞 Genie 🧞🧞🧞 from the magic lamp. Looks like somebody needs a hand!
At the moment the following comments are supported in issues:
/good-first-issue {js | ts | java | go | docs | design | ci-cd}or/gfi {js | ts | java | go | docs | design | ci-cd}- label an issue as agood first issue. example:/gfi jsor/good-first-issue ci-cd
This issue has been automatically marked as stale because it has not had recent activity :sleeping:
It will be closed in 120 days if no further activity occurs. To unstale this issue, add a comment with a detailed explanation.
There can be many reasons why some specific issue has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under open governance model.
Let us figure out together how to push this issue forward. Connect with us through one of many communication channels we established here.
Thank you for your patience :heart:
still relevant I won't be working on this
This issue has been automatically marked as stale because it has not had recent activity :sleeping:
It will be closed in 120 days if no further activity occurs. To unstale this issue, add a comment with a detailed explanation.
There can be many reasons why some specific issue has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under open governance model.
Let us figure out together how to push this issue forward. Connect with us through one of many communication channels we established here.
Thank you for your patience :heart:
Still relevant