mirror of
https://github.com/Redocly/redoc.git
synced 2025-08-09 22:54:51 +03:00
Extended search
This commit is contained in:
parent
ffacdc09be
commit
9e6005ff72
|
@ -36,6 +36,8 @@ export class ContentItem extends React.Component<ContentItemProps> {
|
||||||
case 'group':
|
case 'group':
|
||||||
content = null;
|
content = null;
|
||||||
break;
|
break;
|
||||||
|
case 'field':
|
||||||
|
return null;
|
||||||
case 'tag':
|
case 'tag':
|
||||||
case 'section':
|
case 'section':
|
||||||
content = <SectionItem {...this.props} />;
|
content = <SectionItem {...this.props} />;
|
||||||
|
|
|
@ -61,7 +61,7 @@ export class Field extends React.Component<FieldProps> {
|
||||||
<>
|
<>
|
||||||
<tr className={isLast ? 'last ' + className : className}>
|
<tr className={isLast ? 'last ' + className : className}>
|
||||||
{paramName}
|
{paramName}
|
||||||
<PropertyDetailsCell>
|
<PropertyDetailsCell data-section-id={this.props.field.id}>
|
||||||
<FieldDetails {...this.props} />
|
<FieldDetails {...this.props} />
|
||||||
</PropertyDetailsCell>
|
</PropertyDetailsCell>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -42,6 +42,9 @@ export class MenuItem extends React.Component<MenuItemProps> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { item, withoutChildren } = this.props;
|
const { item, withoutChildren } = this.props;
|
||||||
|
if (item.type === 'field' && this.props['data-role'] !== 'search:result') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<MenuItemLi
|
<MenuItemLi
|
||||||
onClick={this.activate}
|
onClick={this.activate}
|
||||||
|
|
|
@ -6,14 +6,17 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
||||||
<Field
|
<Field
|
||||||
field={
|
field={
|
||||||
FieldModel {
|
FieldModel {
|
||||||
|
"active": false,
|
||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
"description": "",
|
"description": "",
|
||||||
"example": undefined,
|
"example": undefined,
|
||||||
"expanded": false,
|
"expanded": false,
|
||||||
"explode": false,
|
"explode": false,
|
||||||
"in": undefined,
|
"in": undefined,
|
||||||
|
"items": Array [],
|
||||||
"kind": "field",
|
"kind": "field",
|
||||||
"name": "packSize",
|
"name": "packSize",
|
||||||
|
"ready": true,
|
||||||
"required": false,
|
"required": false,
|
||||||
"schema": SchemaModel {
|
"schema": SchemaModel {
|
||||||
"activeOneOf": 0,
|
"activeOneOf": 0,
|
||||||
|
@ -47,6 +50,7 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
||||||
"typePrefix": "",
|
"typePrefix": "",
|
||||||
"writeOnly": false,
|
"writeOnly": false,
|
||||||
},
|
},
|
||||||
|
"type": "field",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isLast={false}
|
isLast={false}
|
||||||
|
@ -56,14 +60,17 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
||||||
<Field
|
<Field
|
||||||
field={
|
field={
|
||||||
FieldModel {
|
FieldModel {
|
||||||
|
"active": false,
|
||||||
"deprecated": false,
|
"deprecated": false,
|
||||||
"description": "",
|
"description": "",
|
||||||
"example": undefined,
|
"example": undefined,
|
||||||
"expanded": false,
|
"expanded": false,
|
||||||
"explode": false,
|
"explode": false,
|
||||||
"in": undefined,
|
"in": undefined,
|
||||||
|
"items": Array [],
|
||||||
"kind": "field",
|
"kind": "field",
|
||||||
"name": "type",
|
"name": "type",
|
||||||
|
"ready": true,
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": SchemaModel {
|
"schema": SchemaModel {
|
||||||
"activeOneOf": 0,
|
"activeOneOf": 0,
|
||||||
|
@ -97,6 +104,7 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
||||||
"typePrefix": "",
|
"typePrefix": "",
|
||||||
"writeOnly": false,
|
"writeOnly": false,
|
||||||
},
|
},
|
||||||
|
"type": "field",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isLast={true}
|
isLast={true}
|
||||||
|
|
|
@ -84,7 +84,7 @@ export class AppStore {
|
||||||
if (!this.options.disableSearch) {
|
if (!this.options.disableSearch) {
|
||||||
this.search = new SearchStore();
|
this.search = new SearchStore();
|
||||||
if (createSearchIndex) {
|
if (createSearchIndex) {
|
||||||
this.search.indexItems(this.menu.items);
|
this.search.indexItems(this.menu.flatItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.disposer = observe(this.menu, 'activeItemIdx', change => {
|
this.disposer = observe(this.menu, 'activeItemIdx', change => {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { OpenAPIOperation, OpenAPIParameter, OpenAPISpec, OpenAPITag, Referenced } from '../types';
|
import { OpenAPIOperation, OpenAPIParameter, OpenAPISpec, OpenAPITag, Referenced } from '../types';
|
||||||
import {
|
import {
|
||||||
isOperationName,
|
isOperationName, safeSlugify,
|
||||||
SECURITY_DEFINITIONS_COMPONENT_NAME,
|
SECURITY_DEFINITIONS_COMPONENT_NAME,
|
||||||
setSecuritySchemePrefix,
|
setSecuritySchemePrefix,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { MarkdownRenderer } from './MarkdownRenderer';
|
import { MarkdownRenderer } from './MarkdownRenderer';
|
||||||
import { GroupModel, OperationModel } from './models';
|
import { FieldModel, GroupModel, OperationModel } from './models';
|
||||||
import { OpenAPIParser } from './OpenAPIParser';
|
import { OpenAPIParser } from './OpenAPIParser';
|
||||||
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
||||||
|
|
||||||
|
@ -28,12 +28,13 @@ export interface TagGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GROUP_DEPTH = 0;
|
export const GROUP_DEPTH = 0;
|
||||||
export type ContentItemModel = GroupModel | OperationModel;
|
export type ContentItemModel = GroupModel | OperationModel | FieldModel;
|
||||||
|
|
||||||
export class MenuBuilder {
|
export class MenuBuilder {
|
||||||
/**
|
/**
|
||||||
* Builds page content structure based on tags
|
* Builds page content structure based on tags
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static buildStructure(
|
static buildStructure(
|
||||||
parser: OpenAPIParser,
|
parser: OpenAPIParser,
|
||||||
options: RedocNormalizedOptions,
|
options: RedocNormalizedOptions,
|
||||||
|
@ -139,7 +140,7 @@ export class MenuBuilder {
|
||||||
return tagsMap[tagName];
|
return tagsMap[tagName];
|
||||||
});
|
});
|
||||||
|
|
||||||
const res: Array<GroupModel | OperationModel> = [];
|
const res: Array<GroupModel | OperationModel | FieldModel> = [];
|
||||||
for (const tag of tags) {
|
for (const tag of tags) {
|
||||||
if (!tag) {
|
if (!tag) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -179,20 +180,144 @@ export class MenuBuilder {
|
||||||
tag: TagInfo,
|
tag: TagInfo,
|
||||||
depth: number,
|
depth: number,
|
||||||
options: RedocNormalizedOptions,
|
options: RedocNormalizedOptions,
|
||||||
): OperationModel[] {
|
): ContentItemModel[] {
|
||||||
if (tag.operations.length === 0) {
|
if (tag.operations.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const res: OperationModel[] = [];
|
const res: ContentItemModel[] = [];
|
||||||
for (const operationInfo of tag.operations) {
|
for (const operationInfo of tag.operations) {
|
||||||
const operation = new OperationModel(parser, operationInfo, parent, options);
|
const operation = new OperationModel(parser, operationInfo, parent, options);
|
||||||
operation.depth = depth;
|
operation.depth = depth;
|
||||||
res.push(operation);
|
res.push(operation);
|
||||||
|
res.push(...this.getOperationFields(operation, depth + 1));
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getOperationFields(
|
||||||
|
parent: OperationModel,
|
||||||
|
depth: number,
|
||||||
|
): FieldModel[] {
|
||||||
|
|
||||||
|
const fields: FieldModel[] = [];
|
||||||
|
|
||||||
|
if (parent.parameters !== undefined) {
|
||||||
|
const parameters = parent.parameters;
|
||||||
|
fields.push(...this.getFields(parameters, parent, 'parameters', depth));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent.requestBody !== undefined) {
|
||||||
|
const body = parent.requestBody;
|
||||||
|
const bodyFields: FieldModel[] = [];
|
||||||
|
|
||||||
|
if (body.content) {
|
||||||
|
const mediaTypes = body.content.mediaTypes;
|
||||||
|
mediaTypes.forEach(mediaType => {
|
||||||
|
const type = mediaType.name.split('/')[1];
|
||||||
|
const schema = mediaType.schema;
|
||||||
|
if (schema && schema.oneOf) { // One of
|
||||||
|
let active = 0;
|
||||||
|
schema.oneOf.forEach(s => {
|
||||||
|
bodyFields.push(...this.getFields(s.fields, parent, 'body/' + type + '/' + s.title, depth).map(f => {
|
||||||
|
f.containerContentModel = body.content;
|
||||||
|
f.activeContentModel = mediaTypes.indexOf(mediaType);
|
||||||
|
f.containerOneOf = schema;
|
||||||
|
f.activeOneOf = active;
|
||||||
|
return f;
|
||||||
|
}));
|
||||||
|
active++;
|
||||||
|
});
|
||||||
|
} else if (schema && schema.fields) {
|
||||||
|
bodyFields.push(...this.getFields(schema.fields, parent, 'body/' + type, depth).map(f => {
|
||||||
|
f.containerContentModel = body.content;
|
||||||
|
f.activeContentModel = mediaTypes.indexOf(mediaType);
|
||||||
|
return f;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fields.push(...bodyFields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent.responses !== undefined) {
|
||||||
|
const responses = parent.responses;
|
||||||
|
const responseFields: FieldModel[] = [];
|
||||||
|
|
||||||
|
responses.forEach(response => {
|
||||||
|
responseFields.push(...this.getFields(response.headers, parent, 'responses/' + response.code + '/headers', depth).map(r => {
|
||||||
|
r.responseContainer = response;
|
||||||
|
return r;
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (response.content) {
|
||||||
|
const mediaTypes = response.content.mediaTypes;
|
||||||
|
mediaTypes.forEach(mediaType => {
|
||||||
|
const type = mediaType.name.split('/')[1];
|
||||||
|
const schema = mediaType.schema;
|
||||||
|
if (schema && schema.oneOf) { // One of
|
||||||
|
let active = 0;
|
||||||
|
schema.oneOf.forEach(s => {
|
||||||
|
responseFields.push(...this.getFields(s.fields, parent, 'responses/' + response.code + '/' + type + '/' + s.title, depth).map(f => {
|
||||||
|
f.responseContainer = response;
|
||||||
|
f.containerContentModel = response.content;
|
||||||
|
f.activeContentModel = mediaTypes.indexOf(mediaType);
|
||||||
|
f.containerOneOf = schema;
|
||||||
|
f.activeOneOf = active;
|
||||||
|
return f;
|
||||||
|
}));
|
||||||
|
active++;
|
||||||
|
});
|
||||||
|
} else if (schema && schema.fields) {
|
||||||
|
responseFields.push(...this.getFields(schema.fields, parent, 'responses/' + response.code + '/' + type, depth).map(f => {
|
||||||
|
f.responseContainer = response;
|
||||||
|
f.containerContentModel = response.content;
|
||||||
|
f.activeContentModel = mediaTypes.indexOf(mediaType);
|
||||||
|
return f;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fields.push(...responseFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getFields(fields, parent, section, depth): FieldModel[] {
|
||||||
|
const temp: FieldModel[] = [];
|
||||||
|
fields.forEach(field => {
|
||||||
|
temp.push(...this.getDeepFields(field, parent, section, depth));
|
||||||
|
});
|
||||||
|
return temp.filter((field, index, self) => {
|
||||||
|
return index === self.findIndex(f => {
|
||||||
|
return f.id === field.id;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDeepFields(field: FieldModel, parent: ContentItemModel, section: string, depth: number): FieldModel[] {
|
||||||
|
const temp: FieldModel[] = [];
|
||||||
|
|
||||||
|
field.id = parent.id.includes(section) ? parent.id + '/' + safeSlugify(field.name) : parent.id + '/' + section + '/' + safeSlugify(field.name);
|
||||||
|
field.parent = parent;
|
||||||
|
temp.push(field);
|
||||||
|
|
||||||
|
if (field.schema.fields !== undefined) {
|
||||||
|
field.schema.fields.forEach(fieldInner => {
|
||||||
|
temp.push(...this.getDeepFields(fieldInner, field, section, depth + 1));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (field.schema.items !== undefined && field.schema.items.fields !== undefined) {
|
||||||
|
field.schema.items.fields.forEach(fieldInner => {
|
||||||
|
temp.push(...this.getDeepFields(fieldInner, field, section, depth + 1));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* collects tags and maps each tag to list of operations belonging to this tag
|
* collects tags and maps each tag to list of operations belonging to this tag
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { action, observable } from 'mobx';
|
import { action, observable } from 'mobx';
|
||||||
import { querySelector } from '../utils/dom';
|
import { querySelector } from '../utils/dom';
|
||||||
import { SpecStore } from './models';
|
import { FieldModel, SpecStore } from './models';
|
||||||
|
|
||||||
import { history as historyInst, HistoryService } from './HistoryService';
|
import { history as historyInst, HistoryService } from './HistoryService';
|
||||||
import { ScrollService } from './ScrollService';
|
import { ScrollService } from './ScrollService';
|
||||||
|
@ -9,7 +9,7 @@ import { flattenByProp, SECURITY_SCHEMES_SECTION_PREFIX } from '../utils';
|
||||||
import { GROUP_DEPTH } from './MenuBuilder';
|
import { GROUP_DEPTH } from './MenuBuilder';
|
||||||
|
|
||||||
export type MenuItemGroupType = 'group' | 'tag' | 'section';
|
export type MenuItemGroupType = 'group' | 'tag' | 'section';
|
||||||
export type MenuItemType = MenuItemGroupType | 'operation';
|
export type MenuItemType = MenuItemGroupType | 'operation' | 'field';
|
||||||
|
|
||||||
/** Generic interface for MenuItems */
|
/** Generic interface for MenuItems */
|
||||||
export interface IMenuItem {
|
export interface IMenuItem {
|
||||||
|
@ -64,6 +64,8 @@ export class MenuStore {
|
||||||
items: IMenuItem[];
|
items: IMenuItem[];
|
||||||
flatItems: IMenuItem[];
|
flatItems: IMenuItem[];
|
||||||
|
|
||||||
|
imagesLoaded: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cached flattened menu items to support absolute indexing
|
* cached flattened menu items to support absolute indexing
|
||||||
*/
|
*/
|
||||||
|
@ -129,7 +131,16 @@ export class MenuStore {
|
||||||
itemIdx += step;
|
itemIdx += step;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.activate(this.flatItems[itemIdx], true, true);
|
let item: FieldModel | undefined = this.flatItems[itemIdx] as FieldModel;
|
||||||
|
while (item && item.type === 'field' && item.parent && item.parent.type === 'field' && !item.parent.expanded ||
|
||||||
|
item && item.containerContentModel !== undefined && item.containerContentModel.activeMimeIdx !== item.activeContentModel ||
|
||||||
|
item && item.responseContainer && !item.responseContainer.expanded ||
|
||||||
|
item && item.containerOneOf !== undefined && item.containerOneOf.activeOneOf !== item.activeOneOf) {
|
||||||
|
itemIdx += step;
|
||||||
|
item = this.flatItems[itemIdx] as FieldModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.activate(item, true, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -142,6 +153,12 @@ export class MenuStore {
|
||||||
}
|
}
|
||||||
let item: IMenuItem | undefined;
|
let item: IMenuItem | undefined;
|
||||||
|
|
||||||
|
// Make jumps possible even if last char in URL is '/'
|
||||||
|
if (id[id.length - 1] === '/') {
|
||||||
|
id = id.slice(0, -1);
|
||||||
|
this.history.replace(id, false);
|
||||||
|
}
|
||||||
|
|
||||||
item = this.flatItems.find(i => i.id === id);
|
item = this.flatItems.find(i => i.id === id);
|
||||||
if (item) {
|
if (item) {
|
||||||
this.activateAndScroll(item, false);
|
this.activateAndScroll(item, false);
|
||||||
|
@ -178,7 +195,7 @@ export class MenuStore {
|
||||||
* activate menu item
|
* activate menu item
|
||||||
* @param item item to activate
|
* @param item item to activate
|
||||||
* @param updateLocation [true] whether to update location
|
* @param updateLocation [true] whether to update location
|
||||||
* @param rewriteHistory [false] whether to rewrite browser history (do not create new enrty)
|
* @param rewriteHistory [false] whether to rewrite browser history (do not create new entry)
|
||||||
*/
|
*/
|
||||||
@action
|
@action
|
||||||
activate(
|
activate(
|
||||||
|
@ -220,7 +237,9 @@ export class MenuStore {
|
||||||
}
|
}
|
||||||
item.deactivate();
|
item.deactivate();
|
||||||
while (item !== undefined) {
|
while (item !== undefined) {
|
||||||
item.collapse();
|
if (item.type !== 'field') {
|
||||||
|
item.collapse();
|
||||||
|
}
|
||||||
item = item.parent;
|
item = item.parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,7 +267,17 @@ export class MenuStore {
|
||||||
* scrolls to active section
|
* scrolls to active section
|
||||||
*/
|
*/
|
||||||
scrollToActive(): void {
|
scrollToActive(): void {
|
||||||
this.scroll.scrollIntoView(this.getElementAt(this.activeItemIdx));
|
const active = this.activeItemIdx;
|
||||||
|
const element = this.getElementAt(active);
|
||||||
|
if (element === null || !this.imagesLoaded) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.activeItemIdx = active;
|
||||||
|
this.scrollToActive();
|
||||||
|
this.imagesLoaded = true;
|
||||||
|
}, this.imagesLoaded ? 500 : 100);
|
||||||
|
} else {
|
||||||
|
this.scroll.scrollIntoView(element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
|
|
|
@ -21,16 +21,13 @@ export class SearchStore<T> {
|
||||||
searchWorker = new worker();
|
searchWorker = new worker();
|
||||||
|
|
||||||
indexItems(groups: Array<IMenuItem | OperationModel>) {
|
indexItems(groups: Array<IMenuItem | OperationModel>) {
|
||||||
const recurse = items => {
|
groups.forEach(group => {
|
||||||
items.forEach(group => {
|
if (group.type !== 'group') {
|
||||||
if (group.type !== 'group') {
|
// @ts-ignore
|
||||||
this.add(group.name, group.description || '', group.id);
|
this.add(group.name, group.description || '', group.id);
|
||||||
}
|
}
|
||||||
recurse(group.items);
|
});
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
recurse(groups);
|
|
||||||
this.searchWorker.done();
|
this.searchWorker.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,13 @@ import {
|
||||||
OpenAPIParameterStyle,
|
OpenAPIParameterStyle,
|
||||||
Referenced,
|
Referenced,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
import { IMenuItem } from '../MenuStore';
|
||||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
|
|
||||||
import { extractExtensions } from '../../utils/openapi';
|
import { extractExtensions } from '../../utils/openapi';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
import { MediaContentModel } from './MediaContent';
|
||||||
|
import { ResponseModel } from './Response';
|
||||||
import { SchemaModel } from './Schema';
|
import { SchemaModel } from './Schema';
|
||||||
|
|
||||||
function getDefaultStyleValue(parameterLocation: OpenAPIParameterLocation): OpenAPIParameterStyle {
|
function getDefaultStyleValue(parameterLocation: OpenAPIParameterLocation): OpenAPIParameterStyle {
|
||||||
|
@ -28,10 +31,28 @@ function getDefaultStyleValue(parameterLocation: OpenAPIParameterLocation): Open
|
||||||
/**
|
/**
|
||||||
* Field or Parameter model ready to be used by components
|
* Field or Parameter model ready to be used by components
|
||||||
*/
|
*/
|
||||||
export class FieldModel {
|
export class FieldModel implements IMenuItem {
|
||||||
@observable
|
@observable
|
||||||
expanded: boolean = false;
|
expanded: boolean = false;
|
||||||
|
|
||||||
|
depth: number;
|
||||||
|
items = [];
|
||||||
|
|
||||||
|
ready?: boolean = true;
|
||||||
|
active: boolean = false;
|
||||||
|
|
||||||
|
id: string;
|
||||||
|
absoluteIdx?: number;
|
||||||
|
parent?: IMenuItem;
|
||||||
|
|
||||||
|
containerContentModel?: MediaContentModel;
|
||||||
|
containerOneOf?: SchemaModel;
|
||||||
|
activeContentModel?: number;
|
||||||
|
activeOneOf?: number;
|
||||||
|
responseContainer?: ResponseModel;
|
||||||
|
|
||||||
|
type = 'field' as 'field';
|
||||||
|
|
||||||
schema: SchemaModel;
|
schema: SchemaModel;
|
||||||
name: string;
|
name: string;
|
||||||
required: boolean;
|
required: boolean;
|
||||||
|
@ -92,4 +113,41 @@ export class FieldModel {
|
||||||
toggle() {
|
toggle() {
|
||||||
this.expanded = !this.expanded;
|
this.expanded = !this.expanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
activate() {
|
||||||
|
if (this.parent) {
|
||||||
|
this.parent.activate();
|
||||||
|
if (this.responseContainer !== undefined) {
|
||||||
|
this.responseContainer.expand();
|
||||||
|
}
|
||||||
|
if (this.containerContentModel !== undefined && this.activeContentModel !== undefined) {
|
||||||
|
this.containerContentModel.activate(this.activeContentModel);
|
||||||
|
}
|
||||||
|
if (this.containerOneOf !== undefined && this.activeOneOf !== undefined) {
|
||||||
|
this.containerOneOf.activateOneOf(this.activeOneOf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
deactivate() {
|
||||||
|
if (this.parent) {
|
||||||
|
this.parent.deactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
expand() {
|
||||||
|
if (this.parent) {
|
||||||
|
if (this.parent.type === 'field') {
|
||||||
|
this.parent.expanded = true;
|
||||||
|
}
|
||||||
|
this.parent.expand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
collapse() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,7 @@ export class OperationModel implements IMenuItem {
|
||||||
this.active = false;
|
this.active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
expand() {
|
expand() {
|
||||||
if (this.parent) {
|
if (this.parent) {
|
||||||
this.parent.expand();
|
this.parent.expand();
|
||||||
|
|
|
@ -58,4 +58,8 @@ export class ResponseModel {
|
||||||
toggle() {
|
toggle() {
|
||||||
this.expanded = !this.expanded;
|
this.expanded = !this.expanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expand() {
|
||||||
|
this.expanded = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user