Merged PR 760152: Add schema validation tools

Add schema validation tools
This commit is contained in:
Dongyu Zhao 2018-09-06 13:43:59 +00:00
Родитель a467738bdf
Коммит 6c16a697dc
259 изменённых файлов: 6055 добавлений и 807 удалений

2
dist/Components/Basic/Banner.js поставляемый
Просмотреть файл

@ -34,6 +34,6 @@ export class Banner extends React.Component {
}
}
get color() {
return StyleManager.getBackgroundColor(this.props.theme);
return StyleManager.getColor('light', this.props.theme, false);
}
}

15
dist/Components/Basic/ImageBackground.js поставляемый
Просмотреть файл

@ -1,6 +1,19 @@
import React from 'react';
import { Image, StyleSheet, View, } from 'react-native';
export class ImageBackground extends React.PureComponent {
constructor() {
super(...arguments);
this.onLoad = (data) => {
if (this.props.onLoad) {
this.props.onLoad(data);
}
};
this.onError = (error) => {
if (this.props.onError) {
this.props.onError(error);
}
};
}
render() {
return (React.createElement(View, { style: [{
flex: this.props.flex,
@ -17,7 +30,7 @@ export class ImageBackground extends React.PureComponent {
React.createElement(Image, { source: { uri: this.props.url }, style: [
StyleSheet.absoluteFill,
this.props.imageStyle
] }),
], onLoad: this.onLoad, onError: this.onError }),
this.props.children));
}
}

11
dist/Components/Basic/ImageBlock.js поставляемый
Просмотреть файл

@ -10,8 +10,17 @@ export class ImageBlock extends React.Component {
console.log(err);
this.setState({
loaded: false
}, () => {
if (this.props.onError) {
this.props.onError(err);
}
});
};
this.onLoad = (data) => {
if (this.props.onLoad) {
this.props.onLoad(data);
}
};
this.state = {
loaded: true,
};
@ -104,7 +113,7 @@ export class ImageBlock extends React.Component {
},
this.borderRadius,
this.props.style
], resizeMethod: 'resize', resizeMode: 'contain', onError: this.onError }));
], resizeMethod: 'resize', resizeMode: 'contain', onLoad: this.onLoad, onError: this.onError }));
}
}
get borderRadius() {

2
dist/Components/Basic/SeparateLine.js поставляемый
Просмотреть файл

@ -7,9 +7,7 @@ export class SeparateLine extends React.PureComponent {
backgroundColor: StyleManager.separatorColor,
height: StyleManager.separatorThickness,
marginTop: StyleManager.separatorSpacing,
marginRight: StyleManager.separatorSpacing,
marginBottom: StyleManager.separatorSpacing,
marginLeft: StyleManager.separatorSpacing
} }));
}
}

2
dist/Components/Containers/Card.js поставляемый
Просмотреть файл

@ -16,7 +16,7 @@ const styles = StyleSheet.create({
elevation: 2,
},
web: {
borderWidth: 0.4,
borderWidth: 0.5,
borderColor: 'rgba(0, 0, 0, .1)',
shadowColor: '#000',
shadowOffset: { width: 0, height: 0 },

4
dist/Config/default.json поставляемый
Просмотреть файл

@ -21,7 +21,7 @@
"default": 14,
"medium": 17,
"large": 21,
"extraLarge": 26
"extraLarge": 44
},
"fontWeights": {
"lighter": 200,
@ -156,4 +156,4 @@
"focusBorderColor": "#006ae2"
}
}
}
}

3
dist/Contexts/CardContext.js поставляемый
Просмотреть файл

@ -1,15 +1,18 @@
import { TreeNode } from '../Shared/Types';
import { FormStore } from './FormStore';
import { SchemaStore } from './SchemaStore';
export class CardContext extends TreeNode {
constructor(parent) {
super(parent);
this.children = [];
if (parent) {
this.form = parent.form;
this.schemas = parent.schemas;
parent.children.push(this);
}
else {
this.form = FormStore.createInstance();
this.schemas = SchemaStore.createInstance();
}
}
static createInstance(parent) {

52
dist/Contexts/SchemaStore.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,52 @@
import { CallbackActionSchema } from '../Schemas/Actions/CallbackAction';
import { OpenUrlActionSchema } from '../Schemas/Actions/OpenUrlAction';
import { SelectActionSchema } from '../Schemas/Actions/SelectAction';
import { ShowCardActionSchema } from '../Schemas/Actions/ShowCardAction';
import { SubmitActionSchema } from '../Schemas/Actions/SubmitAction';
import { BackgroundImageSchema } from '../Schemas/CardElements/BackgroundImage';
import { ImageSchema } from '../Schemas/CardElements/Image';
import { TextBlockSchema } from '../Schemas/CardElements/TextBlock';
import { CardSchema } from '../Schemas/Cards/AdaptiveCard';
import { ColumnSchema } from '../Schemas/Containers/Column';
import { ColumnSetSchema } from '../Schemas/Containers/ColumnSet';
import { ContainerSchema } from '../Schemas/Containers/Container';
import { FactSchema } from '../Schemas/Containers/Fact';
import { FactSetSchema } from '../Schemas/Containers/FactSet';
import { ImageSetSchema } from '../Schemas/Containers/ImageSet';
import { DateInputSchema } from '../Schemas/Inputs/DateInput';
import { NumberInputSchema } from '../Schemas/Inputs/NumberInput';
import { PeoplePickerSchema } from '../Schemas/Inputs/PeoplePicker';
import { TextInputSchema } from '../Schemas/Inputs/TextInput';
import { TimeInputSchema } from '../Schemas/Inputs/TimeInput';
import { ActionType, ContentType } from '../Shared/Types';
export class SchemaStore {
constructor() {
this.schemas = {};
this.schemas[ActionType.OpenUrl] = new OpenUrlActionSchema();
this.schemas[ActionType.Submit] = new SubmitActionSchema();
this.schemas[ActionType.ShowCard] = new ShowCardActionSchema();
this.schemas[ActionType.Callback] = new CallbackActionSchema();
this.schemas[ActionType.Select] = new SelectActionSchema();
this.schemas[ContentType.TextBlock] = new TextBlockSchema();
this.schemas[ContentType.Image] = new ImageSchema();
this.schemas['BackgroundImage'] = new BackgroundImageSchema();
this.schemas[ContentType.AdaptiveCard] = new CardSchema();
this.schemas[ContentType.Container] = new ContainerSchema();
this.schemas[ContentType.ColumnSet] = new ColumnSetSchema();
this.schemas[ContentType.Column] = new ColumnSchema();
this.schemas[ContentType.FactSet] = new FactSetSchema();
this.schemas['Fact'] = new FactSchema();
this.schemas[ContentType.ImageSet] = new ImageSetSchema();
this.schemas[ContentType.TextInput] = new TextInputSchema();
this.schemas[ContentType.NumberInput] = new NumberInputSchema();
this.schemas[ContentType.DateInput] = new DateInputSchema();
this.schemas[ContentType.TimeInput] = new TimeInputSchema();
this.schemas[ContentType.PeoplePicker] = new PeoplePickerSchema();
}
static createInstance() {
return new SchemaStore();
}
read(type) {
return this.schemas[type];
}
}

58
dist/Models/Abstract/AbstractModel.js поставляемый
Просмотреть файл

@ -1,12 +1,68 @@
import { SchemaMessage, SchemaResult, SchemaValidator } from '../../Schemas/SchemaValidator';
import { TreeNode } from '../../Shared/Types';
export class AbstractModel extends TreeNode {
constructor(json, parent, context) {
super(parent);
this.context = context;
this.type = json.type;
this.type = json.type || this.type;
this.schemaCheckResult = this.shallowCheckSchema(json);
if (this.context) {
this.context.fit = 'content';
}
this.outputSchemaMessage();
}
outputSchemaMessage() {
if (this.context) {
let infoHandler = this.context.infoHandler;
let warningHandler = this.context.warningHandler;
let errorHandler = this.context.errorHandler;
if (this.schemaCheckResult && this.schemaCheckResult.messages) {
this.schemaCheckResult.messages.forEach((message) => {
switch (message.level) {
case 'Info':
if (infoHandler) {
infoHandler(`AdaptiveCard >> Schema >> ${this.type} >> ${message.message}`);
}
break;
case 'Warning':
if (warningHandler) {
warningHandler(`AdaptiveCard >> Schema >> ${this.type} >> ${message.message}`);
}
break;
case 'Error':
if (errorHandler) {
errorHandler(`AdaptiveCard >> Schema >> ${this.type} >> ${message.message}`);
}
break;
default:
break;
}
});
}
}
}
shallowCheckSchema(json) {
if (this.context && this.context.schemas) {
if (this.type) {
let schema = this.context.schemas.read(this.type);
return SchemaValidator.shallowCheckElements(json, schema);
}
return new SchemaResult(false, new SchemaMessage('Error', 'Property type is required.'));
}
return new SchemaResult(true);
}
deepCheckSchema() {
if (this.context && this.context.schemas) {
if (this.type) {
let schema = this.context.schemas.read(this.type);
return SchemaValidator.deepCheckElement(this, schema);
}
return new SchemaResult(false, new SchemaMessage('Error', 'Property type is required.'));
}
return new SchemaResult(true);
}
get isSchemaCheckPassed() {
return this.schemaCheckResult.isValid;
}
get children() {
return [];

9
dist/Models/Abstract/ScopeModel.js поставляемый
Просмотреть файл

@ -4,14 +4,5 @@ export class ScopeModel extends ContentModel {
constructor(json, parent, context) {
super(json, parent, context);
this.selectAction = ActionModelFactory.create(json.selectAction, this, this.context);
if (json.backgroundImage) {
if (typeof json.backgroundImage === 'string') {
this.backgroundImage = json.backgroundImage;
}
else {
this.backgroundImage = json.backgroundImage.url;
}
this.context.fit = 'background';
}
}
}

11
dist/Models/CardElements/BackgroundImage.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
import { AbstractModel } from '../Abstract/AbstractModel';
export class BackgroundImageModel extends AbstractModel {
constructor(json, parent, context) {
json.type = 'BackgroundImage';
super(json, parent, context);
this.url = json.url;
this.mode = json.mode;
this.horizontalAlignment = json.horizontalAlignment;
this.verticalAlignment = json.verticalAlignment;
}
}

7
dist/Models/Containers/Column.js поставляемый
Просмотреть файл

@ -1,4 +1,5 @@
import { ScopeModel } from '../Abstract/ScopeModel';
import { BackgroundImageModel } from '../CardElements/BackgroundImage';
import { ContentModelFactory } from '../Factories/ContentModelFactory';
export class ColumnModel extends ScopeModel {
constructor(json, parent, context) {
@ -20,10 +21,14 @@ export class ColumnModel extends ScopeModel {
this.width = columnWidth;
}
}
if (json.backgroundImage) {
this.backgroundImage = new BackgroundImageModel(json.backgroundImage, this, this.context);
this.context.fit = 'background';
}
}
get children() {
if (this.selectAction) {
return [...this.items, this.selectAction];
return [...this.items, this.selectAction, this.backgroundImage];
}
return this.items;
}

7
dist/Models/Containers/Container.js поставляемый
Просмотреть файл

@ -1,4 +1,5 @@
import { ScopeModel } from '../Abstract/ScopeModel';
import { BackgroundImageModel } from '../CardElements/BackgroundImage';
import { ContentModelFactory } from '../Factories/ContentModelFactory';
export class ContainerModel extends ScopeModel {
constructor(json, parent, context) {
@ -8,10 +9,14 @@ export class ContainerModel extends ScopeModel {
this.items = ContentModelFactory.createSet(json.items, this, this.context);
this.height = json.height;
this.verticalContentAlignment = json.verticalContentAlignment;
if (json.backgroundImage) {
this.backgroundImage = new BackgroundImageModel(json.backgroundImage, this, this.context);
this.context.fit = 'background';
}
}
get children() {
if (this.selectAction) {
return [...this.items, this.selectAction];
return [...this.items, this.selectAction, this.backgroundImage];
}
return this.items;
}

3
dist/Models/Containers/Fact.js поставляемый
Просмотреть файл

@ -1,7 +1,8 @@
import { AbstractModel } from '../Abstract/AbstractModel';
export class FactModel extends AbstractModel {
constructor(json, parent, context) {
super(json, parent, context);
json.type = 'Fact',
super(json, parent, context);
this.title = json.title;
this.value = json.value;
}

1
dist/Models/Inputs/DateInput.js поставляемый
Просмотреть файл

@ -38,6 +38,7 @@ export class DateInputModel extends InputModel {
this.min = json.min;
if (this.context.form) {
this.context.form.registerListener(this.id, this.storeListener);
this.onInput(this.value);
}
}
}

1
dist/Models/Inputs/NumberInput.js поставляемый
Просмотреть файл

@ -36,6 +36,7 @@ export class NumberInputModel extends InputModel {
this.min = json.min;
if (this.context.form) {
this.context.form.registerListener(this.id, this.storeListener);
this.onInput(this.value);
}
}
}

1
dist/Models/Inputs/TextInput.js поставляемый
Просмотреть файл

@ -36,6 +36,7 @@ export class TextInputModel extends InputModel {
this.style = json.style;
if (this.context.form) {
this.context.form.registerListener(this.id, this.storeListener);
this.onInput(this.value);
}
}
}

1
dist/Models/Inputs/TimeInput.js поставляемый
Просмотреть файл

@ -39,6 +39,7 @@ export class TimeInputModel extends InputModel {
this.placeholder = json.placeholder;
if (this.context.form) {
this.context.form.registerListener(this.id, this.storeListener);
this.onInput(this.value);
}
}
}

22
dist/Schemas/Actions/CallbackAction.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
import { SchemaElement } from '../SchemaValidator';
export class CallbackActionSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Action.Callback'],
},
'url': {
name: 'url',
isRequired: true,
},
'parameters': {
name: 'parameters',
isRequired: false,
}
};
}
}

22
dist/Schemas/Actions/OpenUrlAction.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
import { SchemaElement } from '../SchemaValidator';
export class OpenUrlActionSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Action.OpenUrl'],
},
'title': {
name: 'title',
isRequired: true,
},
'url': {
name: 'url',
isRequired: true,
},
};
}
}

26
dist/Schemas/Actions/SelectAction.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,26 @@
import { SchemaElement } from '../SchemaValidator';
export class SelectActionSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Action.Select'],
},
'selectedTextTitle': {
name: 'selectedTextTitle',
isRequired: true,
},
'selectedTextSubTitle': {
name: 'selectedTextSubTitle',
isRequired: true,
},
'data': {
name: 'data',
isRequired: false,
},
};
}
}

22
dist/Schemas/Actions/ShowCardAction.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
import { SchemaElement } from '../SchemaValidator';
export class ShowCardActionSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Action.ShowCard'],
},
'title': {
name: 'title',
isRequired: true,
},
'card': {
name: 'card',
isRequired: true,
},
};
}
}

22
dist/Schemas/Actions/SubmitAction.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
import { SchemaElement } from '../SchemaValidator';
export class SubmitActionSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Action.Submit'],
},
'title': {
name: 'title',
isRequired: true,
},
'data': {
name: 'data',
isRequired: false,
},
};
}
}

33
dist/Schemas/CardElements/BackgroundImage.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,33 @@
import { SchemaElement } from '../SchemaValidator';
export class BackgroundImageSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'horizontalAlignment': {
name: 'horizontalAlignment',
isRequired: false,
accepts: ['left', 'center', 'right']
},
'verticalAlignment': {
name: 'verticalAlignment',
isRequired: false,
accepts: ['top', 'center', 'bottom'],
},
'mode': {
name: 'mode',
isRequired: false,
accepts: ['stretch', 'repeatHorizontally', 'repeatVertically', 'repeat'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['BackgroundImage'],
},
'url': {
name: 'url',
isRequired: true,
},
};
}
}

63
dist/Schemas/CardElements/Image.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,63 @@
import { ActionType } from '../../Shared/Types';
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class ImageSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.selectAction && model.selectAction.type !== ActionType.OpenUrl && model.selectAction.type !== ActionType.Submit) {
return new SchemaResult(false, new SchemaMessage('Error', `Only ${ActionType.OpenUrl} and ${ActionType.Submit} accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'altText': {
name: 'altText',
isRequired: false,
},
'horizontalAlignment': {
name: 'horizontalAlignment',
isRequired: false,
accepts: ['left', 'center', 'right']
},
'selectAction': {
name: 'selectAction',
isRequired: false,
},
'size': {
name: 'size',
isRequired: false,
accepts: ['auto', 'stretch', 'small', 'medium', 'large'],
},
'style': {
name: 'style',
isRequired: false,
accepts: ['default', 'person'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Image'],
},
'url': {
name: 'url',
isRequired: true,
},
'id': {
name: 'id',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

73
dist/Schemas/CardElements/TextBlock.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,73 @@
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class TextBlockSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.maxLines && typeof (model.maxLines) !== 'number') {
return new SchemaResult(false, new SchemaMessage('Error', `Only number accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'color': {
name: 'color',
isRequired: false,
accepts: ['default', 'dark', 'light', 'accent', 'good', 'warning', 'attention']
},
'horizontalAlignment': {
name: 'horizontalAlignment',
isRequired: false,
accepts: ['left', 'center', 'right']
},
'isSubtle': {
name: 'isSubtle',
isRequired: false,
accepts: [true, false],
},
'maxLines': {
name: 'maxLines',
isRequired: false,
},
'size': {
name: 'size',
isRequired: false,
accepts: ['small', 'default', 'medium', 'large', 'extraLarge'],
},
'text': {
name: 'text',
isRequired: true,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['TextBlock'],
},
'weight': {
name: 'weight',
isRequired: false,
accepts: ['lighter', 'default', 'bolder'],
},
'wrap': {
name: 'wrap',
isRequired: false,
accepts: [true, false],
},
'id': {
name: 'id',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

44
dist/Schemas/Cards/AdaptiveCard.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,44 @@
import { Language } from '../../Shared/Lang';
import { SchemaElement } from '../SchemaValidator';
export class CardSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['AdaptiveCard']
},
'actions': {
name: 'actions',
isRequired: false,
},
'body': {
name: 'body',
isRequired: false,
},
'version': {
name: 'version',
isRequired: true,
},
'fallbackText': {
name: 'fallbackText',
isRequired: false,
},
'backgroundImage': {
name: 'backgroundImage',
isRequired: false,
},
'speak': {
name: 'speak',
isRequired: false,
},
'lang': {
name: 'lang',
isRequired: false,
accepts: Language.codes,
},
};
}
}

67
dist/Schemas/Containers/Column.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,67 @@
import { ActionType } from '../../Shared/Types';
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class ColumnSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.selectAction && model.selectAction.type !== ActionType.OpenUrl && model.selectAction.type !== ActionType.Submit) {
return new SchemaResult(false, new SchemaMessage('Error', `Only ${ActionType.OpenUrl} and ${ActionType.Submit} accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'items': {
name: 'items',
isRequired: true,
},
'selectAction': {
name: 'selectAction',
isRequired: false,
},
'style': {
name: 'style',
isRequired: false,
accepts: ['default', 'emphasis'],
},
'width': {
name: 'width',
isRequired: false,
},
'height': {
name: 'height',
isRequired: false,
accepts: ['auto', 'stretch'],
},
'verticalContentAlignment': {
name: 'verticalContentAlignment',
isRequired: false,
accepts: ['top', 'center', 'bottom'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Column'],
},
'id': {
name: 'id',
isRequired: false,
},
'backgroundImage': {
name: 'backgroundImage',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

49
dist/Schemas/Containers/ColumnSet.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,49 @@
import { ActionType } from '../../Shared/Types';
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class ColumnSetSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.selectAction && model.selectAction.type !== ActionType.OpenUrl && model.selectAction.type !== ActionType.Submit) {
return new SchemaResult(false, new SchemaMessage('Error', `Only ${ActionType.OpenUrl} and ${ActionType.Submit} accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'columns': {
name: 'columns',
isRequired: true,
},
'selectAction': {
name: 'selectAction',
isRequired: false,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['ColumnSet'],
},
'height': {
name: 'height',
isRequired: false,
accepts: ['auto', 'stretch'],
},
'id': {
name: 'id',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

63
dist/Schemas/Containers/Container.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,63 @@
import { ActionType } from '../../Shared/Types';
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class ContainerSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.selectAction && model.selectAction.type !== ActionType.OpenUrl && model.selectAction.type !== ActionType.Submit) {
return new SchemaResult(false, new SchemaMessage('Error', `Only ${ActionType.OpenUrl} and ${ActionType.Submit} accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'items': {
name: 'items',
isRequired: true,
},
'selectAction': {
name: 'selectAction',
isRequired: false,
},
'style': {
name: 'style',
isRequired: false,
accepts: ['default', 'emphasis'],
},
'height': {
name: 'height',
isRequired: false,
accepts: ['auto', 'stretch'],
},
'verticalContentAlignment': {
name: 'verticalContentAlignment',
isRequired: false,
accepts: ['top', 'center', 'bottom'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Container'],
},
'id': {
name: 'id',
isRequired: false,
},
'backgroundImage': {
name: 'backgroundImage',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

22
dist/Schemas/Containers/Fact.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
import { SchemaElement } from '../SchemaValidator';
export class FactSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Fact'],
},
'title': {
name: 'title',
isRequired: true,
},
'value': {
name: 'value',
isRequired: true,
},
};
}
}

32
dist/Schemas/Containers/FactSet.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,32 @@
import { SchemaElement } from '../SchemaValidator';
export class FactSetSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'facts': {
name: 'facts',
isRequired: true,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['FactSet'],
},
'id': {
name: 'id',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

37
dist/Schemas/Containers/ImageSet.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,37 @@
import { SchemaElement } from '../SchemaValidator';
export class ImageSetSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'images': {
name: 'images',
isRequired: true,
},
'imageSize': {
name: 'imageSize',
isRequired: false,
accepts: ['auto', 'stretch', 'small', 'medium', 'large'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['ImageSet'],
},
'id': {
name: 'id',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

44
dist/Schemas/Inputs/DateInput.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,44 @@
import { SchemaElement } from '../SchemaValidator';
export class DateInputSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'id': {
name: 'id',
isRequired: true,
},
'max': {
name: 'max',
isRequired: false,
},
'min': {
name: 'min',
isRequired: false,
},
'placeholder': {
name: 'placeholder',
isRequired: false,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Input.Date'],
},
'value': {
name: 'value',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

44
dist/Schemas/Inputs/NumberInput.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,44 @@
import { SchemaElement } from '../SchemaValidator';
export class NumberInputSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'id': {
name: 'id',
isRequired: true,
},
'max': {
name: 'max',
isRequired: false,
},
'min': {
name: 'min',
isRequired: false,
},
'placeholder': {
name: 'placeholder',
isRequired: false,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Input.Number'],
},
'value': {
name: 'value',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

48
dist/Schemas/Inputs/PeoplePicker.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,48 @@
import { ActionType } from '../../Shared/Types';
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class PeoplePickerSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.callback && model.callback.type !== ActionType.Callback) {
return new SchemaResult(false, new SchemaMessage('Error', `Only ${ActionType.Callback} accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'id': {
name: 'id',
isRequired: true,
},
'placeholder': {
name: 'placeholder',
isRequired: false,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Input.PeoplePicker'],
},
'value': {
name: 'value',
isRequired: false,
},
'callback': {
name: 'callback',
isRequired: true,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

46
dist/Schemas/Inputs/TextInput.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,46 @@
import { SchemaElement } from '../SchemaValidator';
export class TextInputSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'id': {
name: 'id',
isRequired: true,
},
'isMultiline': {
name: 'isMultiline',
isRequired: false,
accepts: [true, false]
},
'placeholder': {
name: 'placeholder',
isRequired: false,
},
'style': {
name: 'style',
isRequired: false,
accepts: ['text', 'url', 'tel', 'email'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Input.Text'],
},
'value': {
name: 'value',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

44
dist/Schemas/Inputs/TimeInput.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,44 @@
import { SchemaElement } from '../SchemaValidator';
export class TimeInputSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'id': {
name: 'id',
isRequired: true,
},
'max': {
name: 'max',
isRequired: false,
},
'min': {
name: 'min',
isRequired: false,
},
'placeholder': {
name: 'placeholder',
isRequired: false,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Input.Time'],
},
'value': {
name: 'value',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

130
dist/Schemas/SchemaValidator.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,130 @@
export class SchemaElement {
get requiredProps() {
if (this.propsSchemas) {
return Object.values(this.propsSchemas).reduce((prev, current) => {
if (current && current.isRequired) {
prev.push(current);
}
return prev;
}, []);
}
return [];
}
get props() {
if (this.propsSchemas) {
return Object.values(this.propsSchemas).reduce((prev, current) => {
if (current) {
prev.push(current);
}
return prev;
}, []);
}
return [];
}
}
export class SchemaMessage {
constructor(level, message) {
this.level = level;
this.message = message;
}
}
export class SchemaResult {
constructor(isValid, ...messages) {
this.messages = [];
this.combine = (current) => {
if (current) {
this.isValid = this.isValid && current.isValid;
if (this.messages) {
this.messages = this.messages.concat(current.messages);
}
else {
this.messages = current.messages;
}
}
return this;
};
this.isValid = isValid;
this.messages = messages;
}
}
export class SchemaValidator {
static shallowCheckElements(json, schema) {
if (schema) {
let props = Object.keys(json);
let result = schema.props.reduce((prev, current) => {
if (current) {
prev = prev.combine(SchemaValidator.checkProp(json[current.name], current));
let index = props.indexOf(current.name);
if (index > -1) {
props.splice(index, 1);
}
}
return prev;
}, new SchemaResult(true));
result = result.combine(props.reduce((prev, current) => {
if (current) {
prev = prev.combine(new SchemaResult(true, new SchemaMessage('Warning', `Unknown property ${current}`)));
}
return prev;
}, new SchemaResult(true)));
return result;
}
return new SchemaResult(true, new SchemaMessage('Warning', `No Schema available for ${JSON.stringify(json)}`));
}
static deepCheckElement(model, schema) {
if (schema) {
let result = new SchemaResult(true);
if (schema.rules) {
result = schema.rules.reduce((prev, current) => {
if (current) {
let ruleResult = current(model);
if (ruleResult) {
prev.combine(ruleResult);
}
}
return prev;
}, result);
}
return result;
}
return new SchemaResult(true, new SchemaMessage('Warning', `No Schema available for ${JSON.stringify(model)}`));
}
static checkProp(value, schema) {
if (schema) {
let result = new SchemaResult(true);
if (schema.isRequired) {
if (!SchemaValidator.isValuePresent(value)) {
result = result.combine(new SchemaResult(false, new SchemaMessage('Error', `Required property ${schema.name} is null or undefined`)));
}
}
if (schema.accepts && schema.accepts.length > 0) {
if (value !== undefined && schema.accepts.indexOf(value) < 0) {
result = result.combine(new SchemaResult(false, new SchemaMessage('Error', `Value of ${schema.name} is not acceptable.`)));
}
}
if (schema.rules && schema.rules.length > 0) {
result = result.combine(this.checkRules(value, schema.rules));
}
return result;
}
return new SchemaResult(true, new SchemaMessage('Warning', `No Schema available for ${JSON.stringify(value)}`));
}
static checkRules(json, rules) {
let result = new SchemaResult(true);
if (rules) {
result = rules.reduce((prev, current) => {
if (current) {
let ruleResult = current(json);
if (ruleResult) {
prev.combine(ruleResult);
}
}
return prev;
}, result);
}
return result;
}
static isValuePresent(value) {
return !(value === undefined || value === null || (typeof value === 'string' && !value && value !== ''));
}
}

191
dist/Shared/Lang.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,191 @@
const lang = [
{ code: 'ab', name: 'Abkhazian' },
{ code: 'aa', name: 'Afar' },
{ code: 'af', name: 'Afrikaans' },
{ code: 'ak', name: 'Akan' },
{ code: 'sq', name: 'Albanian' },
{ code: 'am', name: 'Amharic' },
{ code: 'ar', name: 'Arabic' },
{ code: 'an', name: 'Aragonese' },
{ code: 'hy', name: 'Armenian' },
{ code: 'as', name: 'Assamese' },
{ code: 'av', name: 'Avaric' },
{ code: 'ae', name: 'Avestan' },
{ code: 'ay', name: 'Aymara' },
{ code: 'az', name: 'Azerbaijani' },
{ code: 'bm', name: 'Bambara' },
{ code: 'ba', name: 'Bashkir' },
{ code: 'eu', name: 'Basque' },
{ code: 'be', name: 'Belarusian' },
{ code: 'bn', name: 'Bengali' },
{ code: 'bh', name: 'Bihari languages' },
{ code: 'bi', name: 'Bislama' },
{ code: 'bs', name: 'Bosnian' },
{ code: 'br', name: 'Breton' },
{ code: 'bg', name: 'Bulgarian' },
{ code: 'my', name: 'Burmese' },
{ code: 'ca', name: 'Catalan, Valencian' },
{ code: 'km', name: 'Central Khmer' },
{ code: 'ch', name: 'Chamorro' },
{ code: 'ce', name: 'Chechen' },
{ code: 'ny', name: 'Chichewa, Chewa, Nyanja' },
{ code: 'zh', name: 'Chinese' },
{ code: 'cu', name: 'Church Slavonic, Old Bulgarian, Old Church Slavonic' },
{ code: 'cv', name: 'Chuvash' },
{ code: 'kw', name: 'Cornish' },
{ code: 'co', name: 'Corsican' },
{ code: 'cr', name: 'Cree' },
{ code: 'hr', name: 'Croatian' },
{ code: 'cs', name: 'Czech' },
{ code: 'da', name: 'Danish' },
{ code: 'dv', name: 'Divehi, Dhivehi, Maldivian' },
{ code: 'nl', name: 'Dutch, Flemish' },
{ code: 'dz', name: 'Dzongkha' },
{ code: 'en', name: 'English' },
{ code: 'eo', name: 'Esperanto' },
{ code: 'et', name: 'Estonian' },
{ code: 'ee', name: 'Ewe' },
{ code: 'fo', name: 'Faroese' },
{ code: 'fj', name: 'Fijian' },
{ code: 'fi', name: 'Finnish' },
{ code: 'fr', name: 'French' },
{ code: 'ff', name: 'Fulah' },
{ code: 'gd', name: 'Gaelic, Scottish Gaelic' },
{ code: 'gl', name: 'Galician' },
{ code: 'lg', name: 'Ganda' },
{ code: 'ka', name: 'Georgian' },
{ code: 'de', name: 'German' },
{ code: 'ki', name: 'Gikuyu, Kikuyu' },
{ code: 'el', name: 'Greek (Modern)' },
{ code: 'kl', name: 'Greenlandic, Kalaallisut' },
{ code: 'gn', name: 'Guarani' },
{ code: 'gu', name: 'Gujarati' },
{ code: 'ht', name: 'Haitian, Haitian Creole' },
{ code: 'ha', name: 'Hausa' },
{ code: 'he', name: 'Hebrew' },
{ code: 'hz', name: 'Herero' },
{ code: 'hi', name: 'Hindi' },
{ code: 'ho', name: 'Hiri Motu' },
{ code: 'hu', name: 'Hungarian' },
{ code: 'is', name: 'Icelandic' },
{ code: 'io', name: 'Ido' },
{ code: 'ig', name: 'Igbo' },
{ code: 'id', name: 'Indonesian' },
{ code: 'ia', name: 'Interlingua (International Auxiliary Language Association)' },
{ code: 'ie', name: 'Interlingue' },
{ code: 'iu', name: 'Inuktitut' },
{ code: 'ik', name: 'Inupiaq' },
{ code: 'ga', name: 'Irish' },
{ code: 'it', name: 'Italian' },
{ code: 'ja', name: 'Japanese' },
{ code: 'jv', name: 'Javanese' },
{ code: 'kn', name: 'Kannada' },
{ code: 'kr', name: 'Kanuri' },
{ code: 'ks', name: 'Kashmiri' },
{ code: 'kk', name: 'Kazakh' },
{ code: 'rw', name: 'Kinyarwanda' },
{ code: 'kv', name: 'Komi' },
{ code: 'kg', name: 'Kongo' },
{ code: 'ko', name: 'Korean' },
{ code: 'kj', name: 'Kwanyama, Kuanyama' },
{ code: 'ku', name: 'Kurdish' },
{ code: 'ky', name: 'Kyrgyz' },
{ code: 'lo', name: 'Lao' },
{ code: 'la', name: 'Latin' },
{ code: 'lv', name: 'Latvian' },
{ code: 'lb', name: 'Letzeburgesch, Luxembourgish' },
{ code: 'li', name: 'Limburgish, Limburgan, Limburger' },
{ code: 'ln', name: 'Lingala' },
{ code: 'lt', name: 'Lithuanian' },
{ code: 'lu', name: 'Luba-Katanga' },
{ code: 'mk', name: 'Macedonian' },
{ code: 'mg', name: 'Malagasy' },
{ code: 'ms', name: 'Malay' },
{ code: 'ml', name: 'Malayalam' },
{ code: 'mt', name: 'Maltese' },
{ code: 'gv', name: 'Manx' },
{ code: 'mi', name: 'Maori' },
{ code: 'mr', name: 'Marathi' },
{ code: 'mh', name: 'Marshallese' },
{ code: 'ro', name: 'Moldovan, Moldavian, Romanian' },
{ code: 'mn', name: 'Mongolian' },
{ code: 'na', name: 'Nauru' },
{ code: 'nv', name: 'Navajo, Navaho' },
{ code: 'nd', name: 'Northern Ndebele' },
{ code: 'ng', name: 'Ndonga' },
{ code: 'ne', name: 'Nepali' },
{ code: 'se', name: 'Northern Sami' },
{ code: 'no', name: 'Norwegian' },
{ code: 'nb', name: 'Norwegian Bokmål' },
{ code: 'nn', name: 'Norwegian Nynorsk' },
{ code: 'ii', name: 'Nuosu, Sichuan Yi' },
{ code: 'oc', name: 'Occitan (post 1500)' },
{ code: 'oj', name: 'Ojibwa' },
{ code: 'or', name: 'Oriya' },
{ code: 'om', name: 'Oromo' },
{ code: 'os', name: 'Ossetian, Ossetic' },
{ code: 'pi', name: 'Pali' },
{ code: 'pa', name: 'Panjabi, Punjabi' },
{ code: 'ps', name: 'Pashto, Pushto' },
{ code: 'fa', name: 'Persian' },
{ code: 'pl', name: 'Polish' },
{ code: 'pt', name: 'Portuguese' },
{ code: 'qu', name: 'Quechua' },
{ code: 'rm', name: 'Romansh' },
{ code: 'rn', name: 'Rundi' },
{ code: 'ru', name: 'Russian' },
{ code: 'sm', name: 'Samoan' },
{ code: 'sg', name: 'Sango' },
{ code: 'sa', name: 'Sanskrit' },
{ code: 'sc', name: 'Sardinian' },
{ code: 'sr', name: 'Serbian' },
{ code: 'sn', name: 'Shona' },
{ code: 'sd', name: 'Sindhi' },
{ code: 'si', name: 'Sinhala, Sinhalese' },
{ code: 'sk', name: 'Slovak' },
{ code: 'sl', name: 'Slovenian' },
{ code: 'so', name: 'Somali' },
{ code: 'st', name: 'Sotho, Southern' },
{ code: 'nr', name: 'South Ndebele' },
{ code: 'es', name: 'Spanish, Castilian' },
{ code: 'su', name: 'Sundanese' },
{ code: 'sw', name: 'Swahili' },
{ code: 'ss', name: 'Swati' },
{ code: 'sv', name: 'Swedish' },
{ code: 'tl', name: 'Tagalog' },
{ code: 'ty', name: 'Tahitian' },
{ code: 'tg', name: 'Tajik' },
{ code: 'ta', name: 'Tamil' },
{ code: 'tt', name: 'Tatar' },
{ code: 'te', name: 'Telugu' },
{ code: 'th', name: 'Thai' },
{ code: 'bo', name: 'Tibetan' },
{ code: 'ti', name: 'Tigrinya' },
{ code: 'to', name: 'Tonga (Tonga Islands)' },
{ code: 'ts', name: 'Tsonga' },
{ code: 'tn', name: 'Tswana' },
{ code: 'tr', name: 'Turkish' },
{ code: 'tk', name: 'Turkmen' },
{ code: 'tw', name: 'Twi' },
{ code: 'ug', name: 'Uighur, Uyghur' },
{ code: 'uk', name: 'Ukrainian' },
{ code: 'ur', name: 'Urdu' },
{ code: 'uz', name: 'Uzbek' },
{ code: 've', name: 'Venda' },
{ code: 'vi', name: 'Vietnamese' },
{ code: 'vo', name: 'Volap_k' },
{ code: 'wa', name: 'Walloon' },
{ code: 'cy', name: 'Welsh' },
{ code: 'fy', name: 'Western Frisian' },
{ code: 'wo', name: 'Wolof' },
{ code: 'xh', name: 'Xhosa' },
{ code: 'yi', name: 'Yiddish' },
{ code: 'yo', name: 'Yoruba' },
{ code: 'za', name: 'Zhuang, Chuang' },
{ code: 'zu', name: 'Zulu' }
];
export class Language {
static get codes() {
return lang.map(langCode => langCode.code);
}
}

11
dist/Utils/ConsoleUtils.js поставляемый
Просмотреть файл

@ -1,11 +0,0 @@
export class ConsoleUtils {
static log(type, message) {
console.log(`${type}: ${message}`);
}
static warning(type, message) {
console.warn(`${type}: ${message}`);
}
static error(type, message) {
console.error(`${type}: ${message}`);
}
}

14
dist/Utils/ElementUtils.js поставляемый
Просмотреть файл

@ -1,14 +0,0 @@
export class ElementUtils {
static isInput(type) {
return ElementUtils.inputTypes.indexOf(type) >= 0;
}
static isValue(type) {
return ElementUtils.valueTypes.indexOf(type) >= 0;
}
static isSelectActionTarget(type) {
return ElementUtils.selectActionTargetTypes.indexOf(type) >= 0;
}
}
ElementUtils.inputTypes = ['Input.Text', 'Input.Number', 'Input.Date', 'Input.Time', 'Input.Toggle', 'Input.ChoiceSet'];
ElementUtils.valueTypes = ['Fact', 'Input.Choice'];
ElementUtils.selectActionTargetTypes = ['Input.PeoplePicker'];

35
dist/Utils/EnumUtils.js поставляемый
Просмотреть файл

@ -1,35 +0,0 @@
export class EnumUtils {
static getEnumValueOrDefault(targetEnum, name, defaultValue) {
if (!name) {
return defaultValue;
}
for (const key in targetEnum) {
if (targetEnum.hasOwnProperty(key)) {
let isValueProperty = parseInt(key, 10) >= 0;
if (isValueProperty) {
let value = targetEnum[key];
if (value && typeof value === 'string') {
if (value.toLowerCase() === name.toLowerCase()) {
return parseInt(key, 10);
}
}
}
}
}
return defaultValue;
}
static getStringEnumValueOrDefault(targetEnum, name, defaultValue) {
if (!name) {
return defaultValue;
}
for (const key in targetEnum) {
if (targetEnum.hasOwnProperty(key)) {
let value = targetEnum[key];
if (value.toLowerCase() === name.toLowerCase()) {
return value;
}
}
}
return defaultValue;
}
}

33
dist/Utils/JsonUtils.js поставляемый
Просмотреть файл

@ -1,33 +0,0 @@
export class JsonUtils {
static isValidateJson(json, requiredProperties) {
if (!json) {
return {
isValid: false,
message: 'data not found',
};
}
if (requiredProperties) {
return requiredProperties.reduce((prev, current) => {
if (prev.isValid) {
prev.isValid = JsonUtils.isValidValue(json[current]);
if (!prev.isValid) {
if (current === 'title') {
prev.isValid = true;
}
prev.message = `${current} is required`;
}
}
return prev;
}, { isValid: true, message: '', });
}
return {
isValid: true,
message: ''
};
}
static isValidValue(value) {
return !(value === undefined ||
value === null ||
(typeof value === 'string' && !value && value !== ''));
}
}

8
dist/Utils/StyleUtils.js поставляемый
Просмотреть файл

@ -1,8 +0,0 @@
export class StyleUtils {
static isFlexWidth(flex) {
return flex && flex > 0;
}
static isFixedSize(width, height) {
return width && width > 0 && height && height > 0;
}
}

3
dist/Utils/TimeUtils.js поставляемый
Просмотреть файл

@ -1,5 +1,8 @@
import { StringUtils } from './StringUtils';
export class TimeUtils {
static getFileTime() {
return (new Date()).getTime();
}
static isDate(value) {
return /^\d{4}(\-\d{2}){2}$/.test(value);
}

6
dist/Views/Actions/Action.js поставляемый
Просмотреть файл

@ -1,6 +1,7 @@
import * as React from 'react';
import { Button } from '../../Components/Inputs/Button';
import { StyleManager } from '../../Styles/StyleManager';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class ActionView extends React.Component {
constructor() {
super(...arguments);
@ -16,7 +17,10 @@ export class ActionView extends React.Component {
};
}
render() {
const { theme } = this.props;
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.title + ' is not valid', theme, 'error');
}
return (React.createElement(Button, { flex: 1, title: this.title, color: StyleManager.getColor('accent', theme, false), fontSize: StyleManager.getFontSize('default'), fontWeight: StyleManager.getFontWeight('bolder'), backgroundColor: StyleManager.getBackgroundColor(theme), textHorizontalAlign: 'center', textVerticalAlign: 'center', paddingTop: 6, paddingBottom: 6, paddingLeft: 16, paddingRight: 16, onPress: this.onPress, marginTop: StyleManager.actionDirection === 'vertically' ? this.spacing : 0, marginLeft: StyleManager.actionDirection === 'horizontal' ? this.spacing : 0, style: {
borderLeftWidth: this.leftBorderWidth,
borderLeftColor: StyleManager.separatorColor,

44
dist/Views/CardElements/BackgroundImage.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,44 @@
import * as React from 'react';
import { ImageBackground } from '../../Components/Basic/ImageBackground';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class BackgroundImageView extends React.Component {
constructor() {
super(...arguments);
this.onImageLoad = (data) => {
const { model } = this.props;
if (model && model.context) {
let handler = model.context.infoHandler;
if (handler) {
handler(data);
}
}
};
this.onError = (error) => {
const { model } = this.props;
if (model && model.context) {
let handler = model.context.errorHandler;
if (handler) {
handler(error);
}
}
};
}
componentDidMount() {
const { model, } = this.props;
if (model) {
if (model.context) {
let handler = model.context.infoHandler;
if (handler) {
handler(`AdaptiveCard >> Start load background img >> ${model.url}`);
}
}
}
}
render() {
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.url + ' is not valid', theme, 'error');
}
return (React.createElement(ImageBackground, { url: model.url, flex: 1, onLoad: this.onImageLoad, onError: this.onError }, this.props.children));
}
}

38
dist/Views/CardElements/Image.js поставляемый
Просмотреть файл

@ -2,6 +2,7 @@ import * as React from 'react';
import { ImageBlock } from '../../Components/Basic/ImageBlock';
import { StyleManager } from '../../Styles/StyleManager';
import { ImageUtils } from '../../Utils/ImageUtils';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class ImageView extends React.Component {
constructor(props) {
super(props);
@ -25,10 +26,32 @@ export class ImageView extends React.Component {
});
}
};
this.onImageLoad = (data) => {
const { model } = this.props;
if (model && model.context) {
let handler = model.context.infoHandler;
if (handler) {
handler(data);
}
}
};
this.onImageError = (error) => {
this.handleError(error);
};
this.onImageSizeError = (error) => {
console.log(error);
this.handleError(error);
};
this.handleError = (error) => {
this.setState({
loaded: false,
}, () => {
const { model } = this.props;
if (model && model.context) {
let handler = model.context.errorHandler;
if (handler) {
handler(error);
}
}
});
};
this.onImageSize = (size) => {
@ -49,13 +72,22 @@ export class ImageView extends React.Component {
componentDidMount() {
const { model, size, maxWidth, maxHeight } = this.props;
if (model) {
if (model.context) {
let handler = model.context.infoHandler;
if (handler) {
handler(`AdaptiveCard >> Start load img >> ${model.url}`);
}
}
ImageUtils.fetchSize(model.url, size || model.size, { width: maxWidth, height: maxHeight }, this.onImageSize, this.onImageSizeError);
}
}
render() {
const { model, spacing } = this.props;
const { model, spacing, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.url + ' is not valid', theme, 'error');
}
if (this.state.loaded) {
return (React.createElement(ImageBlock, { url: model.url, alt: model.alt, flex: this.flex, alignSelf: StyleManager.getHorizontalAlign(model.horizontalAlignment), width: this.state.width, height: this.state.height, onPress: model.selectAction ? this.onPress : undefined, onLayout: this.onLayout, marginTop: this.spacing, marginLeft: spacing, mode: model.style === 'person' ? 'avatar' : 'default' }));
return (React.createElement(ImageBlock, { url: model.url, alt: model.alt, flex: this.flex, alignSelf: StyleManager.getHorizontalAlign(model.horizontalAlignment), width: this.state.width, height: this.state.height, onPress: model.selectAction ? this.onPress : undefined, onLayout: this.onLayout, onLoad: this.onImageLoad, onError: this.onImageError, marginTop: this.spacing, marginLeft: spacing, mode: model.style === 'person' ? 'avatar' : 'default' }));
}
return null;
}

6
dist/Views/CardElements/TextBlock.js поставляемый
Просмотреть файл

@ -1,9 +1,13 @@
import * as React from 'react';
import { Text } from 'react-native';
import { StyleManager } from '../../Styles/StyleManager';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class TextBlockView extends React.Component {
render() {
const { model } = this.props;
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.text + ' is not valid', theme, 'error');
}
return (React.createElement(Text, { accessible: true, style: {
color: StyleManager.getColor(model.color, this.props.theme, model.isSubtle),
fontSize: StyleManager.getFontSize(model.size),

6
dist/Views/Cards/AdaptiveCard.js поставляемый
Просмотреть файл

@ -5,6 +5,7 @@ import { Card } from '../../Components/Containers/Card';
import { StyleManager } from '../../Styles/StyleManager';
import { ActionFactory } from '../Factories/ActionFactory';
import { ContentFactory } from '../Factories/ContentFactory';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class AdaptiveCardView extends React.Component {
constructor(props) {
super(props);
@ -29,7 +30,10 @@ export class AdaptiveCardView extends React.Component {
this.props.model.context.registerShowCardActionHandler(this.showSubCard);
}
render() {
const { model } = this.props;
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.id + ' is not valid', theme, 'error');
}
return (React.createElement(Card, { flex: 1, fit: 'container', backgroundImageUrl: model.backgroundImage, onLayout: this.onLayout, style: [
{
minHeight: this.minHeight,

13
dist/Views/Containers/Column.js поставляемый
Просмотреть файл

@ -2,7 +2,9 @@ import * as React from 'react';
import { View } from 'react-native';
import { Touchable } from '../../Components/Basic/Touchable';
import { StyleManager } from '../../Styles/StyleManager';
import { BackgroundImageView } from '../CardElements/BackgroundImage';
import { ContentFactory } from '../Factories/ContentFactory';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class ColumnView extends React.Component {
constructor() {
super(...arguments);
@ -27,13 +29,13 @@ export class ColumnView extends React.Component {
} }, this.renderContent()));
};
this.renderContent = () => {
const { model } = this.props;
const { model, theme } = this.props;
if (!model) {
return undefined;
}
const background = model.backgroundImage;
if (background) {
return ContentFactory.createBackgroundImageView(this.renderItems(), background);
if (background && background.url) {
return (React.createElement(BackgroundImageView, { model: background, theme: theme }, this.renderItems()));
}
return this.renderItems();
};
@ -59,7 +61,10 @@ export class ColumnView extends React.Component {
};
}
render() {
const { model } = this.props;
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.id + ' is not valid', theme, 'error');
}
let backgroundColor = StyleManager.getBackgroundColor(model.style);
if (model.selectAction) {
return this.renderTouchableBlock(backgroundColor);

11
dist/Views/Containers/ColumnSet.js поставляемый
Просмотреть файл

@ -2,7 +2,7 @@ import * as React from 'react';
import { View } from 'react-native';
import { Touchable } from '../../Components/Basic/Touchable';
import { StyleManager } from '../../Styles/StyleManager';
import { ContentFactory } from '../Factories/ContentFactory';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
import { ColumnView } from './Column';
export class ColumnSetView extends React.Component {
constructor() {
@ -30,10 +30,6 @@ export class ColumnSetView extends React.Component {
if (!model) {
return undefined;
}
const background = model.backgroundImage;
if (background) {
return ContentFactory.createBackgroundImageView(this.renderColumns(), background);
}
return this.renderColumns();
};
this.renderColumns = () => {
@ -55,7 +51,10 @@ export class ColumnSetView extends React.Component {
};
}
render() {
const { model } = this.props;
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.id + ' is not valid', theme, 'error');
}
if (model.selectAction) {
return this.renderTouchableBlock();
}

13
dist/Views/Containers/Container.js поставляемый
Просмотреть файл

@ -2,7 +2,9 @@ import * as React from 'react';
import { View } from 'react-native';
import { Touchable } from '../../Components/Basic/Touchable';
import { StyleManager } from '../../Styles/StyleManager';
import { BackgroundImageView } from '../CardElements/BackgroundImage';
import { ContentFactory } from '../Factories/ContentFactory';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class ContainerView extends React.Component {
constructor() {
super(...arguments);
@ -25,13 +27,13 @@ export class ContainerView extends React.Component {
} }, this.renderContent()));
};
this.renderContent = () => {
const { model } = this.props;
const { model, theme } = this.props;
if (!model) {
return undefined;
}
const background = model.backgroundImage;
if (background) {
return ContentFactory.createBackgroundImageView(this.renderItems(), background);
if (background && background.url) {
return (React.createElement(BackgroundImageView, { model: background, theme: theme }, this.renderItems()));
}
return this.renderItems();
};
@ -57,7 +59,10 @@ export class ContainerView extends React.Component {
};
}
render() {
const { model } = this.props;
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.id + ' is not valid', theme, 'error');
}
let backgroundColor = StyleManager.getBackgroundColor(model.style);
if (model.selectAction) {
return this.renderTouchableBlock(backgroundColor);

4
dist/Views/Containers/Fact.js поставляемый
Просмотреть файл

@ -1,9 +1,13 @@
import * as React from 'react';
import { Text, View } from 'react-native';
import { StyleManager } from '../../Styles/StyleManager';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class FactView extends React.Component {
render() {
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.title + ' is not valid', theme, 'error');
}
return (React.createElement(View, { style: {
flexDirection: 'row',
alignSelf: 'stretch'

5
dist/Views/Containers/FactSet.js поставляемый
Просмотреть файл

@ -1,6 +1,7 @@
import * as React from 'react';
import { View } from 'react-native';
import { StyleManager } from '../../Styles/StyleManager';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
import { FactView } from './Fact';
export class FactSetView extends React.Component {
constructor() {
@ -14,6 +15,10 @@ export class FactSetView extends React.Component {
};
}
render() {
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.id + ' is not valid', theme, 'error');
}
return (React.createElement(View, { style: {
flexDirection: 'column',
marginTop: this.spacing,

6
dist/Views/Containers/ImageSet.js поставляемый
Просмотреть файл

@ -2,6 +2,7 @@ import * as React from 'react';
import { FlatList } from 'react-native';
import { StyleManager } from '../../Styles/StyleManager';
import { ImageView } from '../CardElements/Image';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class ImageSetView extends React.Component {
constructor() {
super(...arguments);
@ -17,7 +18,10 @@ export class ImageSetView extends React.Component {
};
}
render() {
const { model } = this.props;
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.id + ' is not valid', theme, 'error');
}
return (React.createElement(FlatList, { data: model.images, renderItem: this.renderImage, keyExtractor: this.keyExtractor, horizontal: true, style: {
marginTop: this.spacing
} }));

10
dist/Views/Factories/ContentFactory.js поставляемый
Просмотреть файл

@ -1,5 +1,4 @@
import * as React from 'react';
import { ImageBackground } from '../../Components/Basic/ImageBackground';
import { SeparateLine } from '../../Components/Basic/SeparateLine';
import { ContentType } from '../../Shared/Types';
import { ImageView } from '../CardElements/Image';
@ -28,15 +27,6 @@ export class ContentFactory {
}
return null;
}
static createBackgroundImageView(node, background) {
console.log(background);
if (background) {
return (React.createElement(ImageBackground, { url: background, flex: 1 }, node));
}
else {
return null;
}
}
static createElement(model, index, theme) {
if (model) {
switch (model.type) {

8
dist/Views/Inputs/DateInput.js поставляемый
Просмотреть файл

@ -2,6 +2,7 @@ import * as React from 'react';
import { Button } from '../../Components/Inputs/Button';
import { DatePanel } from '../../Components/Inputs/DatePanel';
import { StyleManager } from '../../Styles/StyleManager';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class DateInputView extends React.Component {
constructor(props) {
super(props);
@ -51,7 +52,7 @@ export class DateInputView extends React.Component {
}
}
});
console.log('on press');
console.log('DateInput onPress');
};
this.onStoreUpdate = (value) => {
this.setState({
@ -81,7 +82,10 @@ export class DateInputView extends React.Component {
}
}
render() {
const { index } = this.props;
const { model, index, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.id + ' is not valid', theme, 'error');
}
return ([
React.createElement(Button, { key: 'DateInputButton' + index, title: this.state.value, color: this.color, backgroundColor: this.backgroundColor, borderColor: this.borderColor, borderRadius: 4, borderWidth: 1, height: this.height, fontSize: this.fontSize, fontWeight: this.fontWeight, textHorizontalAlign: 'center', textVerticalAlign: 'center', marginTop: this.spacing, paddingLeft: this.paddingHorizontal, paddingRight: this.paddingHorizontal, paddingTop: this.paddingVertical, paddingBottom: this.paddingVertical, onPress: this.onPress }),
React.createElement(DatePanel, { key: 'DatePanel' + index, value: this.state.value, show: this.state.focused, onValueChange: this.onValueChange, onSave: this.onSave, onCancel: this.onCancel })

4
dist/Views/Inputs/NumberInput.js поставляемый
Просмотреть файл

@ -2,6 +2,7 @@ import * as React from 'react';
import { InputBox } from '../../Components/Inputs/InputBox';
import { StyleManager } from '../../Styles/StyleManager';
import { NumberUtils } from '../../Utils/NumberUtils';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class NumberInputView extends React.Component {
constructor(props) {
super(props);
@ -65,6 +66,9 @@ export class NumberInputView extends React.Component {
}
render() {
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.id + ' is not valid', theme, 'error');
}
return (React.createElement(InputBox, { placeholder: model.placeholder, value: this.state.value, onValueChange: this.onValueChange, onBlur: this.onBlur, onFocus: this.onFocus, theme: theme, marginTop: this.spacing }));
}
get spacing() {

4
dist/Views/Inputs/PeoplePicker.js поставляемый
Просмотреть файл

@ -1,6 +1,7 @@
import * as React from 'react';
import { LabelInput } from '../../Components/Inputs/LabelInput';
import { ContentFactory } from '../Factories/ContentFactory';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class PeoplePickerView extends React.Component {
constructor(props) {
super(props);
@ -76,6 +77,9 @@ export class PeoplePickerView extends React.Component {
}
render() {
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.id + ' is not valid', theme, 'error');
}
return (React.createElement(LabelInput, { placeholder: model.placeholder, value: this.state.value, focused: this.state.inputFocused, labels: this.labels, suggestionView: ContentFactory.createElement(this.state.suggestionCard, 0, theme), onRequestSuggestion: this.onRequestSuggestion, onFocus: this.onFocus, onBlur: this.onBlur }));
}
get labels() {

4
dist/Views/Inputs/TextInput.js поставляемый
Просмотреть файл

@ -1,6 +1,7 @@
import * as React from 'react';
import { InputBox } from '../../Components/Inputs/InputBox';
import { StyleManager } from '../../Styles/StyleManager';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class TextInputView extends React.Component {
constructor(props) {
super(props);
@ -62,6 +63,9 @@ export class TextInputView extends React.Component {
}
render() {
const { model, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.id + ' is not valid', theme, 'error');
}
return (React.createElement(InputBox, { numberOfLines: this.numberOfLine, placeholder: model.placeholder, value: this.state.value, onValueChange: this.onValueChange, onFocus: this.onFocus, onBlur: this.onBlur, theme: theme, marginTop: this.spacing }));
}
get numberOfLine() {

8
dist/Views/Inputs/TimeInput.js поставляемый
Просмотреть файл

@ -2,6 +2,7 @@ import * as React from 'react';
import { Button } from '../../Components/Inputs/Button';
import { TimePanel } from '../../Components/Inputs/TimePanel';
import { StyleManager } from '../../Styles/StyleManager';
import { DebugOutputFactory } from '../Factories/DebugOutputFactory';
export class TimeInputView extends React.Component {
constructor(props) {
super(props);
@ -51,7 +52,7 @@ export class TimeInputView extends React.Component {
}
}
});
console.log('on press');
console.log('TimeInput onPress');
};
this.onStoreUpdate = (value) => {
this.setState({
@ -80,7 +81,10 @@ export class TimeInputView extends React.Component {
}
}
render() {
const { index } = this.props;
const { model, index, theme } = this.props;
if (!model || !model.isSchemaCheckPassed) {
return DebugOutputFactory.createDebugOutputBanner(model.type + '>>' + model.id + ' is not valid', theme, 'error');
}
return ([
React.createElement(Button, { key: 'TimeInputButton' + index, title: this.state.value, color: this.color, backgroundColor: this.backgroundColor, borderColor: this.borderColor, borderRadius: 4, borderWidth: 1, height: this.height, fontSize: this.fontSize, fontWeight: this.fontWeight, textHorizontalAlign: 'center', textVerticalAlign: 'center', marginTop: this.spacing, paddingLeft: this.paddingHorizontal, paddingRight: this.paddingHorizontal, paddingTop: this.paddingVertical, paddingBottom: this.paddingVertical, onPress: this.onPress }),
React.createElement(TimePanel, { key: 'TimePanel' + index, value: this.state.value, show: this.state.focused, onValueChange: this.onValueChange, onSave: this.onSave, onCancel: this.onCancel })

Просмотреть файл

@ -34,6 +34,6 @@ export class Banner extends React.Component {
}
}
get color() {
return StyleManager.getBackgroundColor(this.props.theme);
return StyleManager.getColor('light', this.props.theme, false);
}
}

Просмотреть файл

@ -1,6 +1,19 @@
import React from 'react';
import { Image, StyleSheet, View, } from 'react-native';
export class ImageBackground extends React.PureComponent {
constructor() {
super(...arguments);
this.onLoad = (data) => {
if (this.props.onLoad) {
this.props.onLoad(data);
}
};
this.onError = (error) => {
if (this.props.onError) {
this.props.onError(error);
}
};
}
render() {
return (React.createElement(View, { style: [{
flex: this.props.flex,
@ -17,7 +30,7 @@ export class ImageBackground extends React.PureComponent {
React.createElement(Image, { source: { uri: this.props.url }, style: [
StyleSheet.absoluteFill,
this.props.imageStyle
] }),
], onLoad: this.onLoad, onError: this.onError }),
this.props.children));
}
}

Просмотреть файл

@ -10,8 +10,17 @@ export class ImageBlock extends React.Component {
console.log(err);
this.setState({
loaded: false
}, () => {
if (this.props.onError) {
this.props.onError(err);
}
});
};
this.onLoad = (data) => {
if (this.props.onLoad) {
this.props.onLoad(data);
}
};
this.state = {
loaded: true,
};
@ -104,7 +113,7 @@ export class ImageBlock extends React.Component {
},
this.borderRadius,
this.props.style
], resizeMethod: 'resize', resizeMode: 'contain', onError: this.onError }));
], resizeMethod: 'resize', resizeMode: 'contain', onLoad: this.onLoad, onError: this.onError }));
}
}
get borderRadius() {

Просмотреть файл

@ -7,9 +7,7 @@ export class SeparateLine extends React.PureComponent {
backgroundColor: StyleManager.separatorColor,
height: StyleManager.separatorThickness,
marginTop: StyleManager.separatorSpacing,
marginRight: StyleManager.separatorSpacing,
marginBottom: StyleManager.separatorSpacing,
marginLeft: StyleManager.separatorSpacing
} }));
}
}

Просмотреть файл

@ -16,7 +16,7 @@ const styles = StyleSheet.create({
elevation: 2,
},
web: {
borderWidth: 0.4,
borderWidth: 0.5,
borderColor: 'rgba(0, 0, 0, .1)',
shadowColor: '#000',
shadowOffset: { width: 0, height: 0 },

Просмотреть файл

@ -21,7 +21,7 @@
"default": 14,
"medium": 17,
"large": 21,
"extraLarge": 26
"extraLarge": 44
},
"fontWeights": {
"lighter": 200,
@ -156,4 +156,4 @@
"focusBorderColor": "#006ae2"
}
}
}
}

Просмотреть файл

@ -1,15 +1,18 @@
import { TreeNode } from '../Shared/Types';
import { FormStore } from './FormStore';
import { SchemaStore } from './SchemaStore';
export class CardContext extends TreeNode {
constructor(parent) {
super(parent);
this.children = [];
if (parent) {
this.form = parent.form;
this.schemas = parent.schemas;
parent.children.push(this);
}
else {
this.form = FormStore.createInstance();
this.schemas = SchemaStore.createInstance();
}
}
static createInstance(parent) {

Просмотреть файл

@ -0,0 +1,52 @@
import { CallbackActionSchema } from '../Schemas/Actions/CallbackAction';
import { OpenUrlActionSchema } from '../Schemas/Actions/OpenUrlAction';
import { SelectActionSchema } from '../Schemas/Actions/SelectAction';
import { ShowCardActionSchema } from '../Schemas/Actions/ShowCardAction';
import { SubmitActionSchema } from '../Schemas/Actions/SubmitAction';
import { BackgroundImageSchema } from '../Schemas/CardElements/BackgroundImage';
import { ImageSchema } from '../Schemas/CardElements/Image';
import { TextBlockSchema } from '../Schemas/CardElements/TextBlock';
import { CardSchema } from '../Schemas/Cards/AdaptiveCard';
import { ColumnSchema } from '../Schemas/Containers/Column';
import { ColumnSetSchema } from '../Schemas/Containers/ColumnSet';
import { ContainerSchema } from '../Schemas/Containers/Container';
import { FactSchema } from '../Schemas/Containers/Fact';
import { FactSetSchema } from '../Schemas/Containers/FactSet';
import { ImageSetSchema } from '../Schemas/Containers/ImageSet';
import { DateInputSchema } from '../Schemas/Inputs/DateInput';
import { NumberInputSchema } from '../Schemas/Inputs/NumberInput';
import { PeoplePickerSchema } from '../Schemas/Inputs/PeoplePicker';
import { TextInputSchema } from '../Schemas/Inputs/TextInput';
import { TimeInputSchema } from '../Schemas/Inputs/TimeInput';
import { ActionType, ContentType } from '../Shared/Types';
export class SchemaStore {
constructor() {
this.schemas = {};
this.schemas[ActionType.OpenUrl] = new OpenUrlActionSchema();
this.schemas[ActionType.Submit] = new SubmitActionSchema();
this.schemas[ActionType.ShowCard] = new ShowCardActionSchema();
this.schemas[ActionType.Callback] = new CallbackActionSchema();
this.schemas[ActionType.Select] = new SelectActionSchema();
this.schemas[ContentType.TextBlock] = new TextBlockSchema();
this.schemas[ContentType.Image] = new ImageSchema();
this.schemas['BackgroundImage'] = new BackgroundImageSchema();
this.schemas[ContentType.AdaptiveCard] = new CardSchema();
this.schemas[ContentType.Container] = new ContainerSchema();
this.schemas[ContentType.ColumnSet] = new ColumnSetSchema();
this.schemas[ContentType.Column] = new ColumnSchema();
this.schemas[ContentType.FactSet] = new FactSetSchema();
this.schemas['Fact'] = new FactSchema();
this.schemas[ContentType.ImageSet] = new ImageSetSchema();
this.schemas[ContentType.TextInput] = new TextInputSchema();
this.schemas[ContentType.NumberInput] = new NumberInputSchema();
this.schemas[ContentType.DateInput] = new DateInputSchema();
this.schemas[ContentType.TimeInput] = new TimeInputSchema();
this.schemas[ContentType.PeoplePicker] = new PeoplePickerSchema();
}
static createInstance() {
return new SchemaStore();
}
read(type) {
return this.schemas[type];
}
}

Просмотреть файл

@ -1,12 +1,68 @@
import { SchemaMessage, SchemaResult, SchemaValidator } from '../../Schemas/SchemaValidator';
import { TreeNode } from '../../Shared/Types';
export class AbstractModel extends TreeNode {
constructor(json, parent, context) {
super(parent);
this.context = context;
this.type = json.type;
this.type = json.type || this.type;
this.schemaCheckResult = this.shallowCheckSchema(json);
if (this.context) {
this.context.fit = 'content';
}
this.outputSchemaMessage();
}
outputSchemaMessage() {
if (this.context) {
let infoHandler = this.context.infoHandler;
let warningHandler = this.context.warningHandler;
let errorHandler = this.context.errorHandler;
if (this.schemaCheckResult && this.schemaCheckResult.messages) {
this.schemaCheckResult.messages.forEach((message) => {
switch (message.level) {
case 'Info':
if (infoHandler) {
infoHandler(`AdaptiveCard >> Schema >> ${this.type} >> ${message.message}`);
}
break;
case 'Warning':
if (warningHandler) {
warningHandler(`AdaptiveCard >> Schema >> ${this.type} >> ${message.message}`);
}
break;
case 'Error':
if (errorHandler) {
errorHandler(`AdaptiveCard >> Schema >> ${this.type} >> ${message.message}`);
}
break;
default:
break;
}
});
}
}
}
shallowCheckSchema(json) {
if (this.context && this.context.schemas) {
if (this.type) {
let schema = this.context.schemas.read(this.type);
return SchemaValidator.shallowCheckElements(json, schema);
}
return new SchemaResult(false, new SchemaMessage('Error', 'Property type is required.'));
}
return new SchemaResult(true);
}
deepCheckSchema() {
if (this.context && this.context.schemas) {
if (this.type) {
let schema = this.context.schemas.read(this.type);
return SchemaValidator.deepCheckElement(this, schema);
}
return new SchemaResult(false, new SchemaMessage('Error', 'Property type is required.'));
}
return new SchemaResult(true);
}
get isSchemaCheckPassed() {
return this.schemaCheckResult.isValid;
}
get children() {
return [];

Просмотреть файл

@ -4,14 +4,5 @@ export class ScopeModel extends ContentModel {
constructor(json, parent, context) {
super(json, parent, context);
this.selectAction = ActionModelFactory.create(json.selectAction, this, this.context);
if (json.backgroundImage) {
if (typeof json.backgroundImage === 'string') {
this.backgroundImage = json.backgroundImage;
}
else {
this.backgroundImage = json.backgroundImage.url;
}
this.context.fit = 'background';
}
}
}

Просмотреть файл

@ -0,0 +1,11 @@
import { AbstractModel } from '../Abstract/AbstractModel';
export class BackgroundImageModel extends AbstractModel {
constructor(json, parent, context) {
json.type = 'BackgroundImage';
super(json, parent, context);
this.url = json.url;
this.mode = json.mode;
this.horizontalAlignment = json.horizontalAlignment;
this.verticalAlignment = json.verticalAlignment;
}
}

Просмотреть файл

@ -1,4 +1,5 @@
import { ScopeModel } from '../Abstract/ScopeModel';
import { BackgroundImageModel } from '../CardElements/BackgroundImage';
import { ContentModelFactory } from '../Factories/ContentModelFactory';
export class ColumnModel extends ScopeModel {
constructor(json, parent, context) {
@ -20,10 +21,14 @@ export class ColumnModel extends ScopeModel {
this.width = columnWidth;
}
}
if (json.backgroundImage) {
this.backgroundImage = new BackgroundImageModel(json.backgroundImage, this, this.context);
this.context.fit = 'background';
}
}
get children() {
if (this.selectAction) {
return [...this.items, this.selectAction];
return [...this.items, this.selectAction, this.backgroundImage];
}
return this.items;
}

Просмотреть файл

@ -1,4 +1,5 @@
import { ScopeModel } from '../Abstract/ScopeModel';
import { BackgroundImageModel } from '../CardElements/BackgroundImage';
import { ContentModelFactory } from '../Factories/ContentModelFactory';
export class ContainerModel extends ScopeModel {
constructor(json, parent, context) {
@ -8,10 +9,14 @@ export class ContainerModel extends ScopeModel {
this.items = ContentModelFactory.createSet(json.items, this, this.context);
this.height = json.height;
this.verticalContentAlignment = json.verticalContentAlignment;
if (json.backgroundImage) {
this.backgroundImage = new BackgroundImageModel(json.backgroundImage, this, this.context);
this.context.fit = 'background';
}
}
get children() {
if (this.selectAction) {
return [...this.items, this.selectAction];
return [...this.items, this.selectAction, this.backgroundImage];
}
return this.items;
}

Просмотреть файл

@ -1,7 +1,8 @@
import { AbstractModel } from '../Abstract/AbstractModel';
export class FactModel extends AbstractModel {
constructor(json, parent, context) {
super(json, parent, context);
json.type = 'Fact',
super(json, parent, context);
this.title = json.title;
this.value = json.value;
}

Просмотреть файл

@ -38,6 +38,7 @@ export class DateInputModel extends InputModel {
this.min = json.min;
if (this.context.form) {
this.context.form.registerListener(this.id, this.storeListener);
this.onInput(this.value);
}
}
}

Просмотреть файл

@ -36,6 +36,7 @@ export class NumberInputModel extends InputModel {
this.min = json.min;
if (this.context.form) {
this.context.form.registerListener(this.id, this.storeListener);
this.onInput(this.value);
}
}
}

Просмотреть файл

@ -36,6 +36,7 @@ export class TextInputModel extends InputModel {
this.style = json.style;
if (this.context.form) {
this.context.form.registerListener(this.id, this.storeListener);
this.onInput(this.value);
}
}
}

Просмотреть файл

@ -39,6 +39,7 @@ export class TimeInputModel extends InputModel {
this.placeholder = json.placeholder;
if (this.context.form) {
this.context.form.registerListener(this.id, this.storeListener);
this.onInput(this.value);
}
}
}

Просмотреть файл

@ -0,0 +1,22 @@
import { SchemaElement } from '../SchemaValidator';
export class CallbackActionSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Action.Callback'],
},
'url': {
name: 'url',
isRequired: true,
},
'parameters': {
name: 'parameters',
isRequired: false,
}
};
}
}

Просмотреть файл

@ -0,0 +1,22 @@
import { SchemaElement } from '../SchemaValidator';
export class OpenUrlActionSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Action.OpenUrl'],
},
'title': {
name: 'title',
isRequired: true,
},
'url': {
name: 'url',
isRequired: true,
},
};
}
}

Просмотреть файл

@ -0,0 +1,26 @@
import { SchemaElement } from '../SchemaValidator';
export class SelectActionSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Action.Select'],
},
'selectedTextTitle': {
name: 'selectedTextTitle',
isRequired: true,
},
'selectedTextSubTitle': {
name: 'selectedTextSubTitle',
isRequired: true,
},
'data': {
name: 'data',
isRequired: false,
},
};
}
}

Просмотреть файл

@ -0,0 +1,22 @@
import { SchemaElement } from '../SchemaValidator';
export class ShowCardActionSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Action.ShowCard'],
},
'title': {
name: 'title',
isRequired: true,
},
'card': {
name: 'card',
isRequired: true,
},
};
}
}

Просмотреть файл

@ -0,0 +1,22 @@
import { SchemaElement } from '../SchemaValidator';
export class SubmitActionSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Action.Submit'],
},
'title': {
name: 'title',
isRequired: true,
},
'data': {
name: 'data',
isRequired: false,
},
};
}
}

Просмотреть файл

@ -0,0 +1,33 @@
import { SchemaElement } from '../SchemaValidator';
export class BackgroundImageSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'horizontalAlignment': {
name: 'horizontalAlignment',
isRequired: false,
accepts: ['left', 'center', 'right']
},
'verticalAlignment': {
name: 'verticalAlignment',
isRequired: false,
accepts: ['top', 'center', 'bottom'],
},
'mode': {
name: 'mode',
isRequired: false,
accepts: ['stretch', 'repeatHorizontally', 'repeatVertically', 'repeat'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['BackgroundImage'],
},
'url': {
name: 'url',
isRequired: true,
},
};
}
}

Просмотреть файл

@ -0,0 +1,63 @@
import { ActionType } from '../../Shared/Types';
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class ImageSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.selectAction && model.selectAction.type !== ActionType.OpenUrl && model.selectAction.type !== ActionType.Submit) {
return new SchemaResult(false, new SchemaMessage('Error', `Only ${ActionType.OpenUrl} and ${ActionType.Submit} accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'altText': {
name: 'altText',
isRequired: false,
},
'horizontalAlignment': {
name: 'horizontalAlignment',
isRequired: false,
accepts: ['left', 'center', 'right']
},
'selectAction': {
name: 'selectAction',
isRequired: false,
},
'size': {
name: 'size',
isRequired: false,
accepts: ['auto', 'stretch', 'small', 'medium', 'large'],
},
'style': {
name: 'style',
isRequired: false,
accepts: ['default', 'person'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Image'],
},
'url': {
name: 'url',
isRequired: true,
},
'id': {
name: 'id',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

Просмотреть файл

@ -0,0 +1,73 @@
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class TextBlockSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.maxLines && typeof (model.maxLines) !== 'number') {
return new SchemaResult(false, new SchemaMessage('Error', `Only number accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'color': {
name: 'color',
isRequired: false,
accepts: ['default', 'dark', 'light', 'accent', 'good', 'warning', 'attention']
},
'horizontalAlignment': {
name: 'horizontalAlignment',
isRequired: false,
accepts: ['left', 'center', 'right']
},
'isSubtle': {
name: 'isSubtle',
isRequired: false,
accepts: [true, false],
},
'maxLines': {
name: 'maxLines',
isRequired: false,
},
'size': {
name: 'size',
isRequired: false,
accepts: ['small', 'default', 'medium', 'large', 'extraLarge'],
},
'text': {
name: 'text',
isRequired: true,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['TextBlock'],
},
'weight': {
name: 'weight',
isRequired: false,
accepts: ['lighter', 'default', 'bolder'],
},
'wrap': {
name: 'wrap',
isRequired: false,
accepts: [true, false],
},
'id': {
name: 'id',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

Просмотреть файл

@ -0,0 +1,44 @@
import { Language } from '../../Shared/Lang';
import { SchemaElement } from '../SchemaValidator';
export class CardSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['AdaptiveCard']
},
'actions': {
name: 'actions',
isRequired: false,
},
'body': {
name: 'body',
isRequired: false,
},
'version': {
name: 'version',
isRequired: true,
},
'fallbackText': {
name: 'fallbackText',
isRequired: false,
},
'backgroundImage': {
name: 'backgroundImage',
isRequired: false,
},
'speak': {
name: 'speak',
isRequired: false,
},
'lang': {
name: 'lang',
isRequired: false,
accepts: Language.codes,
},
};
}
}

Просмотреть файл

@ -0,0 +1,67 @@
import { ActionType } from '../../Shared/Types';
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class ColumnSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.selectAction && model.selectAction.type !== ActionType.OpenUrl && model.selectAction.type !== ActionType.Submit) {
return new SchemaResult(false, new SchemaMessage('Error', `Only ${ActionType.OpenUrl} and ${ActionType.Submit} accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'items': {
name: 'items',
isRequired: true,
},
'selectAction': {
name: 'selectAction',
isRequired: false,
},
'style': {
name: 'style',
isRequired: false,
accepts: ['default', 'emphasis'],
},
'width': {
name: 'width',
isRequired: false,
},
'height': {
name: 'height',
isRequired: false,
accepts: ['auto', 'stretch'],
},
'verticalContentAlignment': {
name: 'verticalContentAlignment',
isRequired: false,
accepts: ['top', 'center', 'bottom'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Column'],
},
'id': {
name: 'id',
isRequired: false,
},
'backgroundImage': {
name: 'backgroundImage',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

Просмотреть файл

@ -0,0 +1,49 @@
import { ActionType } from '../../Shared/Types';
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class ColumnSetSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.selectAction && model.selectAction.type !== ActionType.OpenUrl && model.selectAction.type !== ActionType.Submit) {
return new SchemaResult(false, new SchemaMessage('Error', `Only ${ActionType.OpenUrl} and ${ActionType.Submit} accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'columns': {
name: 'columns',
isRequired: true,
},
'selectAction': {
name: 'selectAction',
isRequired: false,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['ColumnSet'],
},
'height': {
name: 'height',
isRequired: false,
accepts: ['auto', 'stretch'],
},
'id': {
name: 'id',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

Просмотреть файл

@ -0,0 +1,63 @@
import { ActionType } from '../../Shared/Types';
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class ContainerSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.selectAction && model.selectAction.type !== ActionType.OpenUrl && model.selectAction.type !== ActionType.Submit) {
return new SchemaResult(false, new SchemaMessage('Error', `Only ${ActionType.OpenUrl} and ${ActionType.Submit} accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'items': {
name: 'items',
isRequired: true,
},
'selectAction': {
name: 'selectAction',
isRequired: false,
},
'style': {
name: 'style',
isRequired: false,
accepts: ['default', 'emphasis'],
},
'height': {
name: 'height',
isRequired: false,
accepts: ['auto', 'stretch'],
},
'verticalContentAlignment': {
name: 'verticalContentAlignment',
isRequired: false,
accepts: ['top', 'center', 'bottom'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Container'],
},
'id': {
name: 'id',
isRequired: false,
},
'backgroundImage': {
name: 'backgroundImage',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

Просмотреть файл

@ -0,0 +1,22 @@
import { SchemaElement } from '../SchemaValidator';
export class FactSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'type': {
name: 'type',
isRequired: true,
accepts: ['Fact'],
},
'title': {
name: 'title',
isRequired: true,
},
'value': {
name: 'value',
isRequired: true,
},
};
}
}

Просмотреть файл

@ -0,0 +1,32 @@
import { SchemaElement } from '../SchemaValidator';
export class FactSetSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'facts': {
name: 'facts',
isRequired: true,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['FactSet'],
},
'id': {
name: 'id',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

Просмотреть файл

@ -0,0 +1,37 @@
import { SchemaElement } from '../SchemaValidator';
export class ImageSetSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'images': {
name: 'images',
isRequired: true,
},
'imageSize': {
name: 'imageSize',
isRequired: false,
accepts: ['auto', 'stretch', 'small', 'medium', 'large'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['ImageSet'],
},
'id': {
name: 'id',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

Просмотреть файл

@ -0,0 +1,44 @@
import { SchemaElement } from '../SchemaValidator';
export class DateInputSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'id': {
name: 'id',
isRequired: true,
},
'max': {
name: 'max',
isRequired: false,
},
'min': {
name: 'min',
isRequired: false,
},
'placeholder': {
name: 'placeholder',
isRequired: false,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Input.Date'],
},
'value': {
name: 'value',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

Просмотреть файл

@ -0,0 +1,44 @@
import { SchemaElement } from '../SchemaValidator';
export class NumberInputSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'id': {
name: 'id',
isRequired: true,
},
'max': {
name: 'max',
isRequired: false,
},
'min': {
name: 'min',
isRequired: false,
},
'placeholder': {
name: 'placeholder',
isRequired: false,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Input.Number'],
},
'value': {
name: 'value',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

Просмотреть файл

@ -0,0 +1,48 @@
import { ActionType } from '../../Shared/Types';
import { SchemaElement, SchemaMessage, SchemaResult } from '../SchemaValidator';
export class PeoplePickerSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [
(model) => {
if (model.callback && model.callback.type !== ActionType.Callback) {
return new SchemaResult(false, new SchemaMessage('Error', `Only ${ActionType.Callback} accepted.`));
}
return new SchemaResult(true);
}
];
this.propsSchemas = {
'id': {
name: 'id',
isRequired: true,
},
'placeholder': {
name: 'placeholder',
isRequired: false,
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Input.PeoplePicker'],
},
'value': {
name: 'value',
isRequired: false,
},
'callback': {
name: 'callback',
isRequired: true,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

Просмотреть файл

@ -0,0 +1,46 @@
import { SchemaElement } from '../SchemaValidator';
export class TextInputSchema extends SchemaElement {
constructor() {
super(...arguments);
this.rules = [];
this.propsSchemas = {
'id': {
name: 'id',
isRequired: true,
},
'isMultiline': {
name: 'isMultiline',
isRequired: false,
accepts: [true, false]
},
'placeholder': {
name: 'placeholder',
isRequired: false,
},
'style': {
name: 'style',
isRequired: false,
accepts: ['text', 'url', 'tel', 'email'],
},
'type': {
name: 'type',
isRequired: true,
accepts: ['Input.Text'],
},
'value': {
name: 'value',
isRequired: false,
},
'spacing': {
name: 'spacing',
isRequired: false,
accepts: ['none', 'small', 'default', 'medium', 'large', 'extraLarge', 'padding'],
},
'separator': {
name: 'separator',
isRequired: false,
accepts: [true, false],
},
};
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше