This commit is contained in:
liaoxuezhi 2020-07-03 22:36:13 +08:00
commit d63e0511cd
21 changed files with 415 additions and 302 deletions

View File

@ -132,13 +132,11 @@ module.exports = function (ret, pack, settings, opt) {
} catch (e) {
d = (/((?:https?|file)\:.*)$/.test(e.stack) && RegExp.$1).replace(/\\/[^\\/]*$/, '');
}
${contents.replace(/\"url\"\s*\:\s*('|")(\.\/.*)\1/g, function (
_,
quote,
value
) {
return `"url": d + ${quote}${value.substring(1)}${quote}`;
})}
${contents
.replace(/\"url\"\s*\:\s*('|")(\.\/.*)\1/g, function (_, quote, value) {
return `"url": d + ${quote}${value.substring(1)}${quote}`;
})
.replace(/require\.resourceMap/, 'amis.require.resourceMap')}
})()`;
}

View File

@ -178,7 +178,7 @@ amis 是一个前端低代码框架,它使用 JSON 配置来生成页面,可
## amis 的其它亮点
- **提供完整的界面解决方案**,其它 UI 框架必须使用 JavaScript 来组装业务逻辑,而 amis 只需 JSON 配置就能完完整功能开发,包括数据获取、表单提交及验证等功能。
- **提供完整的界面解决方案**,其它 UI 框架必须使用 JavaScript 来组装业务逻辑,而 amis 只需 JSON 配置就能完完整功能开发,包括数据获取、表单提交及验证等功能。
- 内置 **92** 种 UI 组件,包括其它 UI 框架都会不提供的富文本编辑器、代码编辑器等,能满足各种页面组件展现的需求,而且对于特殊的展现形式还可以通过[自定义组件](./custom.md)来扩充。
- 容器组件支持**无限层级嵌套**,可以通过组合来满足各种布局需求。
- 经历了长时间的实战考验amis 在百度内部得到了广泛使用,在 4 年多的时间里创建了 3w 多页面从内容审核到机器管理从数据分析到模型训练amis 满足了各种各样的页面需求。

View File

@ -24,7 +24,7 @@ export default {
{
type: 'iframe',
className: 'b-a',
src: 'https://www.baidu.com/s?wd=${keywords|url_encode}',
src: 'https://www.baidu.com/s?wd=${keywords|raw}',
height: 500
}
]

View File

@ -30,7 +30,7 @@ function amisRequire(...args: Array<any>) {
let id = args.shift();
id = Array.isArray(id) ? id.map(id => mapping[id] || id) : mapping[id] || id;
args.unshift(id);
return require.apply(this, args);
return amis.require.apply(this, args);
}
(window as any).amisRequire = amisRequire;

View File

@ -1,292 +1,265 @@
/**
* @file: mod.js
* @author fis
* ver: 1.0.13
* update: 2016/01/27
* https://github.com/fex-team/mod
* @file mod-sandbox.js.
*/
var require;
/* eslint-disable no-unused-vars */
var define;
/* eslint-disable */
(function (global) {
var require, define;
var amis = window.amis || {};
var amis = window.amis || {};
// 避免重复加载而导致已定义模块丢失
if (require) {
return;
// 避免重复加载而导致已定义模块丢失
if (amis.require) {
return;
}
var head = document.getElementsByTagName('head')[0];
var loadingMap = {};
var factoryMap = {};
var modulesMap = {};
var scriptsMap = {};
var resMap = {};
var pkgMap = {};
var createScripts = function (queues, onerror) {
var docFrag = document.createDocumentFragment();
for (var i = 0, len = queues.length; i < len; i++) {
var id = queues[i].id;
var url = queues[i].url;
if (url in scriptsMap) {
continue;
}
scriptsMap[url] = true;
var script = document.createElement('script');
if (onerror) {
(function (script, id) {
var tid = setTimeout(function () {
onerror(id);
}, require.timeout);
script.onerror = function () {
clearTimeout(tid);
onerror(id);
};
var onload = function () {
clearTimeout(tid);
};
if ('onload' in script) {
script.onload = onload;
} else {
script.onreadystatechange = function () {
if (
this.readyState === 'loaded' ||
this.readyState === 'complete'
) {
onload();
}
};
}
})(script, id);
}
script.type = 'text/javascript';
script.src = url;
docFrag.appendChild(script);
}
var head = document.getElementsByTagName('head')[0];
var loadingMap = {};
var factoryMap = {};
var modulesMap = {};
var scriptsMap = {};
var resMap = {};
var pkgMap = {};
head.appendChild(docFrag);
};
var createScripts = function (queues, onerror) {
var loadScripts = function (ids, callback, onerror) {
var queues = [];
for (var i = 0, len = ids.length; i < len; i++) {
var id = ids[i];
var queue = loadingMap[id] || (loadingMap[id] = []);
queue.push(callback);
var docFrag = document.createDocumentFragment();
//
// resource map query
//
var res = resMap[id] || resMap[id + '.js'] || {};
var pkg = res.pkg;
var url;
for (var i = 0, len = queues.length; i < len; i++) {
var id = queues[i].id;
var url = queues[i].url;
if (pkg) {
url = pkgMap[pkg].url || pkgMap[pkg].uri;
} else {
url = res.url || res.uri || id;
}
if (url in scriptsMap) {
continue;
}
queues.push({
id: id,
url: url
});
}
scriptsMap[url] = true;
createScripts(queues, onerror);
};
var script = document.createElement('script');
if (onerror) {
(function (script, id) {
var tid = setTimeout(function () {
onerror(id);
}, require.timeout);
define = function (id, factory) {
id = id.replace(/\.js$/i, '');
factoryMap[id] = factory;
script.onerror = function () {
clearTimeout(tid);
onerror(id);
};
var queue = loadingMap[id];
if (queue) {
for (var i = 0, n = queue.length; i < n; i++) {
queue[i]();
}
delete loadingMap[id];
}
};
var onload = function () {
clearTimeout(tid);
};
require = function (id) {
// compatible with require([dep, dep2...]) syntax.
if (id && id.splice) {
return require.async.apply(this, arguments);
}
if ('onload' in script) {
script.onload = onload;
}
else {
script.onreadystatechange = function () {
if (this.readyState === 'loaded' || this.readyState === 'complete') {
onload();
}
};
}
})(script, id);
}
script.type = 'text/javascript';
script.src = url;
id = require.alias(id);
docFrag.appendChild(script);
}
var mod = modulesMap[id];
if (mod) {
return mod.exports;
}
head.appendChild(docFrag);
//
// init module
//
var factory = factoryMap[id];
if (!factory) {
throw '[ModJS] Cannot find module `' + id + '`';
}
mod = modulesMap[id] = {
exports: {}
};
var loadScripts = function (ids, callback, onerror) {
var queues = [];
for (var i = 0, len = ids.length; i < len; i++) {
var id = ids[i];
var queue = loadingMap[id] || (loadingMap[id] = []);
queue.push(callback);
//
// factory: function OR value
//
var ret =
typeof factory === 'function'
? factory.apply(mod, [require, mod.exports, mod])
: factory;
//
// resource map query
//
var res = resMap[id] || resMap[id + '.js'] || {};
var pkg = res.pkg;
var url;
if (ret) {
mod.exports = ret;
}
if (pkg) {
url = pkgMap[pkg].url || pkgMap[pkg].uri;
}
else {
url = res.url || res.uri || id;
}
return mod.exports;
};
queues.push({
id: id,
url: url
});
}
require.async = function (names, onload, onerror) {
if (typeof names === 'string') {
names = [names];
}
createScripts(queues, onerror);
};
var needMap = {};
var needNum = 0;
var needLoad = [];
define = function (id, factory) {
id = id.replace(/\.js$/i, '');
factoryMap[id] = factory;
var queue = loadingMap[id];
if (queue) {
for (var i = 0, n = queue.length; i < n; i++) {
queue[i]();
}
delete loadingMap[id];
}
};
require = function (id) {
// compatible with require([dep, dep2...]) syntax.
if (id && id.splice) {
return require.async.apply(this, arguments);
}
id = require.alias(id);
var mod = modulesMap[id];
if (mod) {
return mod.exports;
}
function findNeed(depArr) {
var child;
for (var i = 0, n = depArr.length; i < n; i++) {
//
// init module
// skip loading or loaded
//
var factory = factoryMap[id];
if (!factory) {
throw '[ModJS] Cannot find module `' + id + '`';
var dep = require.alias(depArr[i]);
if (dep in needMap) {
continue;
}
mod = modulesMap[id] = {
exports: {}
};
needMap[dep] = true;
//
// factory: function OR value
//
var ret = (typeof factory === 'function') ? factory.apply(mod, [require, mod.exports, mod]) : factory;
if (ret) {
mod.exports = ret;
if (dep in factoryMap) {
// check whether loaded resource's deps is loaded or not
child = resMap[dep] || resMap[dep + '.js'];
if (child && 'deps' in child) {
findNeed(child.deps);
}
continue;
}
return mod.exports;
};
needLoad.push(dep);
needNum++;
require.async = function (names, onload, onerror) {
if (typeof names === 'string') {
names = [names];
child = resMap[dep] || resMap[dep + '.js'];
if (child && 'deps' in child) {
findNeed(child.deps);
}
}
}
function updateNeed() {
if (0 === needNum--) {
var args = [];
for (var i = 0, n = names.length; i < n; i++) {
args[i] = require(names[i]);
}
var needMap = {};
var needNum = 0;
var needLoad = [];
onload && onload.apply(global, args);
}
}
function findNeed(depArr) {
var child;
findNeed(names);
loadScripts(needLoad, updateNeed, onerror);
updateNeed();
};
for (var i = 0, n = depArr.length; i < n; i++) {
//
// skip loading or loaded
//
var dep = require.alias(depArr[i]);
require.ensure = function (names, callback) {
require.async(names, function () {
callback && callback.call(this, require);
});
};
if (dep in needMap) {
continue;
}
require.resourceMap = function (obj) {
var k;
var col;
needMap[dep] = true;
// merge `res` & `pkg` fields
col = obj.res;
for (k in col) {
if (col.hasOwnProperty(k)) {
resMap[k] = col[k];
}
}
if (dep in factoryMap) {
// check whether loaded resource's deps is loaded or not
child = resMap[dep] || resMap[dep + '.js'];
if (child && 'deps' in child) {
findNeed(child.deps);
}
continue;
}
col = obj.pkg;
for (k in col) {
if (col.hasOwnProperty(k)) {
pkgMap[k] = col[k];
}
}
};
needLoad.push(dep);
needNum++;
require.loadJs = function (url) {
if (url in scriptsMap) {
return;
}
child = resMap[dep] || resMap[dep + '.js'];
if (child && 'deps' in child) {
findNeed(child.deps);
}
}
}
scriptsMap[url] = true;
function updateNeed() {
if (0 === needNum--) {
var args = [];
for (var i = 0, n = names.length; i < n; i++) {
args[i] = require(names[i]);
}
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
head.appendChild(script);
};
onload && onload.apply(global, args);
}
}
require.alias = function (id) {
return id.replace(/\.js$/i, '');
};
findNeed(names);
loadScripts(needLoad, updateNeed, onerror);
updateNeed();
};
require.ensure = function (names, callback) {
require.async(names, function () {
callback && callback.call(this, require);
});
};
require.resourceMap = function (obj) {
var k;
var col;
// merge `res` & `pkg` fields
col = obj.res;
for (k in col) {
if (col.hasOwnProperty(k)) {
resMap[k] = col[k];
}
}
col = obj.pkg;
for (k in col) {
if (col.hasOwnProperty(k)) {
pkgMap[k] = col[k];
}
}
};
require.loadJs = function (url) {
if (url in scriptsMap) {
return;
}
scriptsMap[url] = true;
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
head.appendChild(script);
};
require.loadCss = function (cfg) {
if (cfg.content) {
var sty = document.createElement('style');
sty.type = 'text/css';
if (sty.styleSheet) { // IE
sty.styleSheet.cssText = cfg.content;
}
else {
sty.innerHTML = cfg.content;
}
head.appendChild(sty);
}
else if (cfg.url) {
var link = document.createElement('link');
link.href = cfg.url;
link.rel = 'stylesheet';
link.type = 'text/css';
head.appendChild(link);
}
};
require.alias = function (id) {
return id.replace(/\.js$/i, '');
};
require.timeout = 5000;
amis.require = require;
amis.define = define;
window.amis = amis;
require.timeout = 5000;
amis.require = require;
amis.define = define;
window.amis = amis;
// window.require = window.require || require;
})(this);

View File

@ -512,6 +512,7 @@ $Card-actions-borderColor: lighten($Card-borderColor, 5%) !default;
$Card-actions-onHover-bg: darken($white, 5%) !default;
$Card-actions-onHover-color: darken($text-color, 5%) !default;
$Card-actions-onChecked-onHover-bg: darken(#d9f3fb, 5%) !default;
$Card-actions-fontSize: $fontSizeBase !default;
$Card-onChecked-bg: #d9f3fb !default;
$Card-onChecked-borderColor: darken($Table-onChecked-bg, 10%) !default;

View File

@ -144,7 +144,7 @@
color: $text-color;
text-align: center;
line-height: px2rem(40px);
// font-size: $fontSizeBase;
font-size: $Card-actions-fontSize;
&:not(.is-disabled) {
cursor: pointer;

View File

@ -78,7 +78,7 @@
&-placeholder {
color: $text--muted-color;
text-align: center;
height: $List-placeholder-height;
min-height: $List-placeholder-height;
line-height: $List-placeholder-height;
}
}

View File

@ -10,7 +10,9 @@
background-color: $Form-input-onError-bg;
}
&.is-focused {
&.is-focused,
&:focus {
outline: none;
border-color: $Form-input-onFocused-borderColor;
box-shadow: $Form-input-boxShadow;

View File

@ -454,6 +454,9 @@ $Card-actions-onHover-bg: white;
$Card-actions-onHover-color: $primary;
$Card-actions-onChecked-onHover-bg: $white;
$Card-actions-borderColor: lighten($borderColor, 2.5%);
$Card-actions-fontSize: px2rem(12px);
// Combo
$Combo--horizontal-dragger-top: px2rem(5px);

View File

@ -168,16 +168,17 @@ function createScopedTools(
*
* @param target name
*/
close(target: string) {
close(target: string | boolean) {
const scoped = this;
let targets =
typeof target === 'string' ? target.split(/\s*,\s*/) : target;
// 过滤已经关掉的,当用户 close 配置多个弹框 name 时会出现这种情况
targets
.map(name => scoped.getComponentByName(name))
.filter(component => component && component.props.show)
.forEach(closeDialog);
if (typeof target === 'string') {
// 过滤已经关掉的,当用户 close 配置多个弹框 name 时会出现这种情况
target
.split(/\s*,\s*/)
.map(name => scoped.getComponentByName(name))
.filter(component => component && component.props.show)
.forEach(closeDialog);
}
}
};
}

View File

@ -9,6 +9,9 @@ import Modal from './Modal';
import Button from './Button';
import {ClassNamesFn, themeable, ThemeProps} from '../theme';
import {LocaleProps, localeable} from '../locale';
import Html from './Html';
import {PlainObject} from '../types';
import {render as renderSchema} from '../factory';
export interface AlertProps extends ThemeProps, LocaleProps {
container?: any;
@ -24,6 +27,9 @@ export interface AlertState {
title?: string;
content: string;
confirm: boolean;
prompt?: boolean;
controls?: any;
value?: any;
confirmText?: string;
}
@ -57,7 +63,8 @@ export class Alert extends React.Component<AlertProps, AlertState> {
this.handleConfirm = this.handleConfirm.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.modalRef = this.modalRef.bind(this);
this.bodyRef = this.bodyRef.bind(this);
this.handleFormSubmit = this.handleFormSubmit.bind(this);
this.scopeRef = this.scopeRef.bind(this);
}
static defaultProps = {
@ -86,8 +93,19 @@ export class Alert extends React.Component<AlertProps, AlertState> {
Alert.instance = null;
}
schemaSope: any;
scopeRef(schemaSope: any) {
this.schemaSope = schemaSope;
}
handleConfirm() {
this.close(true);
const form = this.schemaSope?.getComponentByName('form');
if (form) {
form.doAction({type: 'submit'});
} else {
this.close(true);
}
}
handleCancel() {
@ -95,7 +113,7 @@ export class Alert extends React.Component<AlertProps, AlertState> {
}
close(confirmed: boolean) {
const isConfirm = this.state.confirm;
const isConfirm = this.state.confirm || this.state.prompt;
this.setState(
{
@ -128,13 +146,51 @@ export class Alert extends React.Component<AlertProps, AlertState> {
});
}
prompt(
controls: any,
defaultValue?: any,
title: string = '请输入',
confirmText: string = '确认'
) {
if (typeof controls === 'string') {
// 兼容浏览器标准用法。
controls = [
{
name: 'text',
label: controls,
type: 'text'
}
];
if (typeof defaultValue === 'string') {
defaultValue = {
text: defaultValue
};
}
} else if (!Array.isArray(controls)) {
controls = [controls];
}
this.setState({
title,
controls,
show: true,
prompt: true,
value: defaultValue,
confirmText
});
return new Promise(resolve => {
this._resolve = resolve;
});
}
modalRef(ref: any) {
this._modal = ref;
}
bodyRef(ref: any) {
this._body = ref;
this._body && (this._body.innerHTML = this.state.content);
handleFormSubmit(values: any) {
this.close(values);
}
render() {
@ -146,9 +202,11 @@ export class Alert extends React.Component<AlertProps, AlertState> {
confirmBtnLevel,
alertBtnLevel,
classnames: cx,
classPrefix
theme
} = this.props;
const __ = this.props.translate;
const finalTitle = __(this.state.title ?? title);
const finalConfirmText = __(this.state.confirmText ?? confirmText);
return (
<Modal
@ -156,31 +214,75 @@ export class Alert extends React.Component<AlertProps, AlertState> {
onHide={this.handleCancel}
container={container}
ref={this.modalRef}
closeOnEsc
>
<div className={cx('Modal-header')}>
<div className={cx('Modal-title')}>
{__(this.state.title || title)}
{finalTitle ? (
<div className={cx('Modal-header')}>
<div className={cx('Modal-title')}>{finalTitle}</div>
</div>
</div>
) : null}
<div className={cx('Modal-body')}>
<div ref={this.bodyRef} />
</div>
<div className={cx('Modal-footer')}>
{this.state.confirm ? (
<Button onClick={this.handleCancel}>{__(cancelText)}</Button>
) : null}
<Button
level={this.state.confirm ? confirmBtnLevel : alertBtnLevel}
onClick={this.handleConfirm}
>
{__(this.state.confirmText || confirmText)}
</Button>
{this.state.prompt ? (
renderForm(
this.state.controls,
this.state.value,
this.handleFormSubmit,
this.scopeRef,
theme
)
) : (
<Html html={this.state.content} />
)}
</div>
{finalConfirmText ? (
<div className={cx('Modal-footer')}>
{this.state.confirm || this.state.prompt ? (
<Button onClick={this.handleCancel}>{__(cancelText)}</Button>
) : null}
<Button
level={
this.state.confirm || this.state.prompt
? confirmBtnLevel
: alertBtnLevel
}
onClick={this.handleConfirm}
>
{finalConfirmText}
</Button>
</div>
) : null}
</Modal>
);
}
}
function renderForm(
controls: Array<any>,
value: PlainObject = {},
callback?: (values: PlainObject) => void,
scopeRef?: (value: any) => void,
theme?: string
) {
return renderSchema(
{
name: 'form',
type: 'form',
wrapWithPanel: false,
mode: 'horizontal',
controls
},
{
data: value,
onFinished: callback,
scopeRef,
theme
},
{
session: 'prompt'
}
);
}
export const alert: (content: string, title?: string) => void = (
content,
title
@ -191,5 +293,12 @@ export const confirm: (
confirmText?: string
) => Promise<any> = (content, title, confirmText) =>
Alert.getInstance().confirm(content, title, confirmText);
export const prompt: (
controls: any,
defaultvalue?: any,
title?: string,
confirmText?: string
) => Promise<any> = (controls, defaultvalue, title, confirmText) =>
Alert.getInstance().prompt(controls, defaultvalue, title, confirmText);
export const FinnalAlert = themeable(localeable(Alert));
export default FinnalAlert;

View File

@ -5,7 +5,7 @@
*/
import NotFound from './404';
import {default as Alert, alert, confirm} from './Alert';
import {default as Alert, alert, confirm, prompt} from './Alert';
import {default as ContextMenu, openContextMenus} from './ContextMenu';
import AsideNav from './AsideNav';
import Button from './Button';
@ -57,10 +57,11 @@ export {
NotFound,
Alert as AlertComponent,
alert,
confirm,
prompt,
ContextMenu,
openContextMenus,
Alert2,
confirm,
AsideNav,
Button,
Checkbox,

View File

@ -443,7 +443,7 @@ export default class CRUD extends React.Component<CRUDProps, any> {
action.reload
? this.reloadTarget(action.reload, data)
: this.search({[pageField || 'page']: 1}, undefined, true);
: this.search({[pageField || 'page']: 1}, undefined, true, true);
action.close && this.closeTarget(action.close);
const redirect = action.redirect && filter(action.redirect, data);

View File

@ -460,6 +460,18 @@ export default class Form extends React.Component<FormProps, object> {
return store.clearErrors();
}
getValues() {
const {store} = this.props;
this.flush();
return store.data;
}
setValues(value: any) {
const {store} = this.props;
this.flush();
store.setValues(value);
}
submit(fn?: (values: object) => Promise<any>): Promise<any> {
const {store, messages, translate: __} = this.props;
this.flush();
@ -1219,7 +1231,11 @@ export class FormRenderer extends Form {
super.componentWillUnmount();
}
doAction(action: Action, data: object, throwErrors: boolean = false) {
doAction(
action: Action,
data: object = this.props.store.data,
throwErrors: boolean = false
) {
return this.handleAction(undefined, action, data, throwErrors);
}

View File

@ -789,7 +789,9 @@ export default class List extends React.Component<ListProps, object> {
)}
</div>
) : (
<div className={cx('List-placeholder')}>{__(placeholder)}</div>
<div className={cx('List-placeholder')}>
{render('placeholder', __(placeholder))}
</div>
)}
{this.renderFooter()}

View File

@ -72,6 +72,7 @@ export class StatusField extends React.Component<StatusProps, object> {
<Icon
icon={svgIcon}
className={cx('Status-icon icon', itemClassName)}
key="icon"
/>
);
} else if (itemClassName) {

View File

@ -120,10 +120,11 @@ export interface ThemeProps {
className?: string;
classPrefix: string;
classnames: ClassNamesFn;
theme?: string;
}
export const ThemeContext = React.createContext('theme');
export let defaultTheme: string = 'default';
export const ThemeContext = React.createContext('');
export function themeable<
T extends React.ComponentType<React.ComponentProps<T> & ThemeProps> & {
@ -156,9 +157,11 @@ export function themeable<
const injectedProps: {
classPrefix: string;
classnames: ClassNamesFn;
theme: string;
} = {
classPrefix: config.classPrefix as string,
classnames: config.classnames
classnames: config.classnames,
theme
};
return (

View File

@ -7,7 +7,7 @@ export interface ApiObject {
withCredentials?: boolean;
cancelExecutor?: (cancel: Function) => void;
};
autoRefresh: boolean; // 是否自动刷新,当 url 中的取值结果变化时,自动刷新数据。
autoRefresh?: boolean; // 是否自动刷新,当 url 中的取值结果变化时,自动刷新数据。
reload?: string;
sendOn?: string;
adaptor?: (payload: object, response: fetcherResult, api: ApiObject) => any;

View File

@ -253,7 +253,10 @@ export function isApiOutdated(
}
export function isValidApi(api: string) {
return api && /^(?:https?:\/\/[^\/]+)?(\/[^\s\/\?]*){1,}(\?.*)?$/.test(api);
return (
api &&
/^(?:(https?|wss?|taf):\/\/[^\/]+)?(\/[^\s\/\?]*){1,}(\?.*)?$/.test(api)
);
}
export function isEffectiveApi(

View File

@ -42,7 +42,7 @@ const entityMap: {
'/': '&#x2F;'
};
export const escapeHtml = (str: string) =>
String(str).replace(/[&<>"'\/]/g, function(s) {
String(str).replace(/[&<>"'\/]/g, function (s) {
return entityMap[s];
});
@ -218,13 +218,13 @@ export const filters: {
Array.isArray(input)
? input.map(item => resolveVariable(path, item) || item)
: resolveVariable(path, input) || input,
str2date: function(input, inputFormat = 'X', outputFormat = 'X') {
str2date: function (input, inputFormat = 'X', outputFormat = 'X') {
return input
? filterDate(input, this, inputFormat).format(outputFormat)
: '';
},
asArray: input => (Array.isArray(input) ? input : input ? [input] : input),
filter: function(input, keys, expOrDirective, arg1) {
filter: function (input, keys, expOrDirective, arg1) {
if (!Array.isArray(input) || !keys || !expOrDirective) {
return input;
}
@ -243,7 +243,7 @@ export const filters: {
fn = value => arg1 == value;
} else if (directive === 'isIn') {
let list: Array<any> = arg1 ? getStrOrVariable(arg1, this) : [];
list = Array.isArray(list) ? list : [];
list = Array.isArray(list) ? list : [list];
fn = value => !!~list.indexOf(value);
} else if (directive === 'notIn') {
let list: Array<any> = arg1 ? getStrOrVariable(arg1, this) : [];
@ -284,7 +284,7 @@ export const filters: {
return decodeURIComponent(
atob(str)
.split('')
.map(function(c) {
.map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
})
.join('')