asyncapi-react icon indicating copy to clipboard operation
asyncapi-react copied to clipboard

React Components for extensions Catalog

Open sambhavgupta0705 opened this issue 2 years ago • 21 comments

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).

sambhavgupta0705 avatar Oct 18 '23 04:10 sambhavgupta0705

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.

github-actions[bot] avatar Oct 18 '23 04:10 github-actions[bot]

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 add extensions property on the config to the AsyncAPIComponent. It should be simple JS object.

  • inside Extensions component 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 Extensions component

  • 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

magicmatatjahu avatar Nov 30 '23 16:11 magicmatatjahu

sounds good to me, @sambhavgupta0705 feel free to ask more followup questions

derberg avatar Nov 30 '23 17:11 derberg

@magicmatatjahu is there any previous work or PR from which I can better understand about this

sambhavgupta0705 avatar Dec 02 '23 03:12 sambhavgupta0705

just a friendly reminder @magicmatatjahu

sambhavgupta0705 avatar Dec 08 '23 10:12 sambhavgupta0705

@sambhavgupta0705 Nope, maybe there was but I wasn't involved.

magicmatatjahu avatar Dec 08 '23 11:12 magicmatatjahu

@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 avatar Dec 15 '23 06:12 sambhavgupta0705

@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?

magicmatatjahu avatar Dec 15 '23 12:12 magicmatatjahu

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?

image

sambhavgupta0705 avatar Dec 19 '23 11:12 sambhavgupta0705

@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 avatar Dec 21 '23 14:12 derberg

@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>
    )
  );
};

magicmatatjahu avatar Dec 22 '23 09:12 magicmatatjahu

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 a good first issue. example: /gfi js or /good-first-issue ci-cd

asyncapi-bot avatar Dec 22 '23 09:12 asyncapi-bot

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:

github-actions[bot] avatar Apr 21 '24 00:04 github-actions[bot]

still relevant I won't be working on this

sambhavgupta0705 avatar Apr 21 '24 17:04 sambhavgupta0705

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:

github-actions[bot] avatar Aug 21 '24 00:08 github-actions[bot]

Still relevant

sambhavgupta0705 avatar Aug 28 '24 12:08 sambhavgupta0705