mirror of
https://github.com/Redocly/redoc.git
synced 2025-08-09 22:54:51 +03:00
Commit to enable multiple contributors
This commit is contained in:
parent
c9ea62381c
commit
0a73344829
|
@ -7,6 +7,7 @@ import { MiddlePanel, Row, Section } from '../../common-elements/';
|
||||||
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
|
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
import { StyledMarkdownBlock } from '../Markdown/styled.elements';
|
import { StyledMarkdownBlock } from '../Markdown/styled.elements';
|
||||||
|
import { Contributor } from '../Contributor/Contributor'
|
||||||
import {
|
import {
|
||||||
ApiHeader,
|
ApiHeader,
|
||||||
DownloadButton,
|
DownloadButton,
|
||||||
|
@ -70,29 +71,6 @@ export class ApiInfo extends React.Component<ApiInfoProps> {
|
||||||
|
|
||||||
const version = (info.version && <span>({info.version})</span>) || null;
|
const version = (info.version && <span>({info.version})</span>) || null;
|
||||||
|
|
||||||
const contributorName = (info['x-contributorDetails'] && info['x-contributorDetails'].name && (
|
|
||||||
<InfoSpan>
|
|
||||||
Contributed by: {' '}
|
|
||||||
{info['x-contributorDetails'].name}
|
|
||||||
</InfoSpan>
|
|
||||||
)) ||
|
|
||||||
null;
|
|
||||||
|
|
||||||
const contributorEmail =
|
|
||||||
(info['x-contributorDetails'] && info['x-contributorDetails'].email && (
|
|
||||||
<InfoSpan>
|
|
||||||
<a href={'mailto:' + info['x-contributorDetails'].email}>{info['x-contributorDetails'].email}</a>
|
|
||||||
</InfoSpan>
|
|
||||||
)) ||
|
|
||||||
null;
|
|
||||||
|
|
||||||
const contributorSupportLink = (info['x-contributorDetails'] && info['x-contributorDetails'].supportlink && (
|
|
||||||
<InfoSpan>
|
|
||||||
<a href={info['x-contributorDetails'].supportlink}>Support</a>
|
|
||||||
</InfoSpan>
|
|
||||||
)) ||
|
|
||||||
null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section>
|
<Section>
|
||||||
<Row>
|
<Row>
|
||||||
|
@ -122,9 +100,7 @@ export class ApiInfo extends React.Component<ApiInfoProps> {
|
||||||
</InfoSpanBoxWrap>
|
</InfoSpanBoxWrap>
|
||||||
)) ||
|
)) ||
|
||||||
null}
|
null}
|
||||||
<InfoSpanBoxWrap><InfoSpanBox>
|
<Contributor contributor={info['x-contributorDetails']}></Contributor>
|
||||||
{contributorName} {contributorEmail} {contributorSupportLink}
|
|
||||||
</InfoSpanBox></InfoSpanBoxWrap>
|
|
||||||
</StyledMarkdownBlock>
|
</StyledMarkdownBlock>
|
||||||
<Markdown source={store.spec.info.summary} data-role="redoc-summary"/>
|
<Markdown source={store.spec.info.summary} data-role="redoc-summary"/>
|
||||||
<Markdown source={store.spec.info.description} data-role="redoc-description"/>
|
<Markdown source={store.spec.info.description} data-role="redoc-description"/>
|
||||||
|
|
52
src/components/Contributor/Contributor.tsx
Normal file
52
src/components/Contributor/Contributor.tsx
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { ContributorGroup } from './ContributorGroup';
|
||||||
|
import { mapWithLast } from '../../utils';
|
||||||
|
import { ContributorModel } from '../../services/models/Contributor';
|
||||||
|
|
||||||
|
import {
|
||||||
|
InfoSpanBox,
|
||||||
|
InfoSpanBoxWrap,
|
||||||
|
} from './../ApiInfo/styled.elements';
|
||||||
|
function safePush(obj, prop, item) {
|
||||||
|
if (!obj[prop]) {
|
||||||
|
obj[prop] = [];
|
||||||
|
}
|
||||||
|
obj[prop].push(item);
|
||||||
|
}
|
||||||
|
export interface ContributorProps {
|
||||||
|
contributor: ContributorModel[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const CONTRIBUTOR_PLACES = ['contributor'];
|
||||||
|
|
||||||
|
export class Contributor extends React.Component<ContributorProps> {
|
||||||
|
orderParams(params: ContributorModel[]): Record<string, ContributorModel[]> {
|
||||||
|
const res = {};
|
||||||
|
params.forEach(param => {
|
||||||
|
safePush(res, 'contributor', param);
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { contributor = [] } = this.props;
|
||||||
|
const paramsMap = this.orderParams(contributor);
|
||||||
|
const contributorPlaces = contributor.length > 0 ? CONTRIBUTOR_PLACES : [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
Contributed by:{' '}
|
||||||
|
<InfoSpanBoxWrap> <InfoSpanBox>
|
||||||
|
|
||||||
|
{contributorPlaces.map(place => (
|
||||||
|
mapWithLast(paramsMap[place], (contributorDetails, isLast) => (
|
||||||
|
<ContributorGroup place={place} contributors={paramsMap[place]} field = {contributorDetails} isLast = {isLast} />
|
||||||
|
))
|
||||||
|
))}
|
||||||
|
|
||||||
|
</InfoSpanBox></InfoSpanBoxWrap>
|
||||||
|
</>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
50
src/components/Contributor/ContributorGroup.tsx
Normal file
50
src/components/Contributor/ContributorGroup.tsx
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { InfoSpan } from './../ApiInfo/styled.elements';
|
||||||
|
import { ContributorModel } from '../../services/models/Contributor';
|
||||||
|
|
||||||
|
export interface ContributorGroup {
|
||||||
|
key:string;
|
||||||
|
place: string;
|
||||||
|
contributors: ContributorModel[];
|
||||||
|
field: any;
|
||||||
|
isLast: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ContributorGroup extends React.PureComponent<ContributorGroup, any> {
|
||||||
|
render() {
|
||||||
|
const { place, contributors,field,isLast } = this.props;
|
||||||
|
console.log("isLast isLast",isLast);
|
||||||
|
|
||||||
|
const contributorName = (field && field['name'] && (
|
||||||
|
<InfoSpan>
|
||||||
|
{ field['name']}
|
||||||
|
</InfoSpan>
|
||||||
|
)) ||
|
||||||
|
null;
|
||||||
|
|
||||||
|
const contributorEmail =
|
||||||
|
( field && field['email'] && (
|
||||||
|
<InfoSpan>
|
||||||
|
<a href={'mailto:' + field['email']}>{ field['email']}</a>
|
||||||
|
</InfoSpan>
|
||||||
|
)) ||
|
||||||
|
null;
|
||||||
|
|
||||||
|
const contributorSupportLink = ( field && field['supportlink'] && (
|
||||||
|
<InfoSpan>
|
||||||
|
<a href={ field['supportlink']}>Support</a>
|
||||||
|
</InfoSpan>
|
||||||
|
)) ||
|
||||||
|
null;
|
||||||
|
|
||||||
|
if (!contributors || !contributors.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={place}>
|
||||||
|
{contributorName}{contributorEmail}{contributorSupportLink}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ import { RequestSamples } from '../RequestSamples/RequestSamples';
|
||||||
import { ResponsesList } from '../Responses/ResponsesList';
|
import { ResponsesList } from '../Responses/ResponsesList';
|
||||||
import { ResponseSamples } from '../ResponseSamples/ResponseSamples';
|
import { ResponseSamples } from '../ResponseSamples/ResponseSamples';
|
||||||
import { SecurityRequirements } from '../SecurityRequirement/SecurityRequirement';
|
import { SecurityRequirements } from '../SecurityRequirement/SecurityRequirement';
|
||||||
|
import { Contributor } from '../Contributor/Contributor'
|
||||||
import {
|
import {
|
||||||
InfoSpan,
|
InfoSpan,
|
||||||
InfoSpanBox,
|
InfoSpanBox,
|
||||||
|
@ -44,28 +45,6 @@ export class Operation extends React.Component<OperationProps> {
|
||||||
const { name: summary, description, deprecated, externalDocs, isWebhook, contributorDetails} = operation;
|
const { name: summary, description, deprecated, externalDocs, isWebhook, contributorDetails} = operation;
|
||||||
const hasDescription = !!(description || externalDocs);
|
const hasDescription = !!(description || externalDocs);
|
||||||
|
|
||||||
const contributorName = (contributorDetails && contributorDetails['name'] && (
|
|
||||||
<InfoSpan>
|
|
||||||
Contributed by:{' '}
|
|
||||||
{ contributorDetails['name']}
|
|
||||||
</InfoSpan>
|
|
||||||
)) ||
|
|
||||||
null;
|
|
||||||
|
|
||||||
const contributorEmail =
|
|
||||||
( contributorDetails && contributorDetails['email'] && (
|
|
||||||
<InfoSpan>
|
|
||||||
<a href={'mailto:' + contributorDetails['email']}>{ contributorDetails['email']}</a>
|
|
||||||
</InfoSpan>
|
|
||||||
)) ||
|
|
||||||
null;
|
|
||||||
|
|
||||||
const contributorSupportLink = ( contributorDetails && contributorDetails['supportlink'] && (
|
|
||||||
<InfoSpan>
|
|
||||||
<a href={ contributorDetails['supportlink']}>Support</a>
|
|
||||||
</InfoSpan>
|
|
||||||
)) ||
|
|
||||||
null;
|
|
||||||
return (
|
return (
|
||||||
<OptionsContext.Consumer>
|
<OptionsContext.Consumer>
|
||||||
{(options) => (
|
{(options) => (
|
||||||
|
@ -76,9 +55,7 @@ export class Operation extends React.Component<OperationProps> {
|
||||||
{summary} {deprecated && <Badge type="warning"> Deprecated </Badge>}
|
{summary} {deprecated && <Badge type="warning"> Deprecated </Badge>}
|
||||||
{isWebhook && <Badge type="primary"> Webhook </Badge>}
|
{isWebhook && <Badge type="primary"> Webhook </Badge>}
|
||||||
</H2>
|
</H2>
|
||||||
<InfoSpanBoxWrap><InfoSpanBox>
|
<Contributor contributor={contributorDetails}></Contributor>
|
||||||
{contributorName}{contributorEmail}{contributorSupportLink}
|
|
||||||
</InfoSpanBox></InfoSpanBoxWrap>
|
|
||||||
{options.pathInMiddlePanel && !isWebhook && (
|
{options.pathInMiddlePanel && !isWebhook && (
|
||||||
<Endpoint operation={operation} inverted={true} />
|
<Endpoint operation={operation} inverted={true} />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -3,6 +3,7 @@ export * from './Redoc/Redoc';
|
||||||
export * from './ApiInfo/ApiInfo';
|
export * from './ApiInfo/ApiInfo';
|
||||||
export * from './ApiLogo/ApiLogo';
|
export * from './ApiLogo/ApiLogo';
|
||||||
export * from './ContentItems/ContentItems';
|
export * from './ContentItems/ContentItems';
|
||||||
|
export * from './Contributor/Contributor';
|
||||||
export { ApiContentWrap, BackgroundStub, RedocWrap } from './Redoc/styled.elements';
|
export { ApiContentWrap, BackgroundStub, RedocWrap } from './Redoc/styled.elements';
|
||||||
export * from './Schema/';
|
export * from './Schema/';
|
||||||
export * from './SearchBox/SearchBox';
|
export * from './SearchBox/SearchBox';
|
||||||
|
|
19
src/services/models/Contributor.ts
Normal file
19
src/services/models/Contributor.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { observable,} from 'mobx';
|
||||||
|
import { OpenAPIInfo } from '../../types'
|
||||||
|
|
||||||
|
export class ContributorModel {
|
||||||
|
@observable
|
||||||
|
// contributor:[
|
||||||
|
info: OpenAPIInfo;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
supportlink: string;
|
||||||
|
in: string ='contributor';
|
||||||
|
//]
|
||||||
|
|
||||||
|
constructor( ) {
|
||||||
|
console.log(this.info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ export interface OpenAPIInfo {
|
||||||
termsOfService?: string;
|
termsOfService?: string;
|
||||||
contact?: OpenAPIContact;
|
contact?: OpenAPIContact;
|
||||||
license?: OpenAPILicense;
|
license?: OpenAPILicense;
|
||||||
'x-contributorDetails'?: OpenAPIContributorDetail;
|
'x-contributorDetails'?: OpenAPIContributorDetail[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OpenAPIServer {
|
export interface OpenAPIServer {
|
||||||
|
@ -48,7 +48,7 @@ export type Referenced<T> = OpenAPIRef | T;
|
||||||
|
|
||||||
export interface OpenAPIPath {
|
export interface OpenAPIPath {
|
||||||
summary?: string;
|
summary?: string;
|
||||||
'x-contributorDetails'?: OpenAPIContributorDetail;
|
'x-contributorDetails'?: OpenAPIContributorDetail[];
|
||||||
description?: string;
|
description?: string;
|
||||||
get?: OpenAPIOperation;
|
get?: OpenAPIOperation;
|
||||||
put?: OpenAPIOperation;
|
put?: OpenAPIOperation;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user