Merged PR 760152: Add schema validation tools
Add schema validation tools
This commit is contained in:
Родитель
a467738bdf
Коммит
6c16a697dc
|
@ -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],
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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],
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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 !== ''));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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}`);
|
||||
}
|
||||
}
|
|
@ -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'];
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 !== ''));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
} }));
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 })
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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],
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче