[+] some widgets
This commit is contained in:
parent
bd3a342c92
commit
ed163c8a1c
|
|
@ -1,5 +1,7 @@
|
|||
const CracoAlias = require("craco-alias");
|
||||
const CracoLessPlugin = require('craco-less');
|
||||
const { DefinePlugin, EnvironmentPlugin } = require("webpack");
|
||||
const pxtorem = require("./craco.postcss.pxtorem");
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
|
|
@ -35,4 +37,27 @@ module.exports = {
|
|||
},
|
||||
},
|
||||
],
|
||||
webpack: {
|
||||
plugins: [
|
||||
new DefinePlugin({
|
||||
ENABLE_INNER_HTML: true,
|
||||
ENABLE_ADJACENT_HTML: true,
|
||||
ENABLE_TEMPLATE_CONTENT: true,
|
||||
ENABLE_CLONE_NODE: true,
|
||||
ENABLE_SIZE_APIS: false
|
||||
}),
|
||||
new EnvironmentPlugin({
|
||||
TARO_ENV: 'h5',
|
||||
}),
|
||||
]
|
||||
},
|
||||
style: {
|
||||
postcss: {
|
||||
plugins: [
|
||||
pxtorem({
|
||||
h5Width: 450,
|
||||
})
|
||||
]
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,342 @@
|
|||
'use strict'
|
||||
|
||||
const postcss = require('postcss')
|
||||
const objectAssign = require('object-assign')
|
||||
const pxRegex = /"[^"]+"|'[^']+'|url\([^\)]+\)|(\d*\.?\d+)px/g
|
||||
/*eslint-disable*/
|
||||
const filterPropList = {
|
||||
exact: function (list) {
|
||||
return list.filter(function (m) {
|
||||
return m.match(/^[^\*\!]+$/)
|
||||
})
|
||||
},
|
||||
contain: function (list) {
|
||||
return list.filter(function (m) {
|
||||
return m.match(/^\*.+\*$/)
|
||||
}).map(function (m) {
|
||||
return m.substr(1, m.length - 2)
|
||||
})
|
||||
},
|
||||
endWith: function (list) {
|
||||
return list.filter(function (m) {
|
||||
return m.match(/^\*[^\*]+$/)
|
||||
}).map(function (m) {
|
||||
return m.substr(1)
|
||||
})
|
||||
},
|
||||
startWith: function (list) {
|
||||
return list.filter(function (m) {
|
||||
return m.match(/^[^\*\!]+\*$/)
|
||||
}).map(function (m) {
|
||||
return m.substr(0, m.length - 1)
|
||||
})
|
||||
},
|
||||
notExact: function (list) {
|
||||
return list.filter(function (m) {
|
||||
return m.match(/^\![^\*].*$/)
|
||||
}).map(function (m) {
|
||||
return m.substr(1)
|
||||
})
|
||||
},
|
||||
notContain: function (list) {
|
||||
return list.filter(function (m) {
|
||||
return m.match(/^\!\*.+\*$/)
|
||||
}).map(function (m) {
|
||||
return m.substr(2, m.length - 3)
|
||||
})
|
||||
},
|
||||
notEndWith: function (list) {
|
||||
return list.filter(function (m) {
|
||||
return m.match(/^\!\*[^\*]+$/)
|
||||
}).map(function (m) {
|
||||
return m.substr(2)
|
||||
})
|
||||
},
|
||||
notStartWith: function (list) {
|
||||
return list.filter(function (m) {
|
||||
return m.match(/^\![^\*]+\*$/)
|
||||
}).map(function (m) {
|
||||
return m.substr(1, m.length - 2)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const defaults = {
|
||||
rootValue: 16,
|
||||
unitPrecision: 5,
|
||||
selectorBlackList: [],
|
||||
propList: ['*'],
|
||||
replace: true,
|
||||
mediaQuery: false,
|
||||
minPixelValue: 0
|
||||
}
|
||||
|
||||
const legacyOptions = {
|
||||
root_value: 'rootValue',
|
||||
unit_precision: 'unitPrecision',
|
||||
selector_black_list: 'selectorBlackList',
|
||||
prop_white_list: 'propList',
|
||||
media_query: 'mediaQuery',
|
||||
propWhiteList: 'propList'
|
||||
}
|
||||
|
||||
const deviceRatio = {
|
||||
640: 2.34 / 2,
|
||||
750: 1,
|
||||
828: 1.81 / 2
|
||||
}
|
||||
|
||||
// transform factor for fixed-width container
|
||||
// (w / 320) * 20 * (pixels / rootValue) === (pixels / newRootValue) * 16 (default html font-size)
|
||||
// so, newRootValue = (16 * 16 / w) * rootValue
|
||||
const factor = 16 * 16
|
||||
|
||||
const baseFontSize = 40
|
||||
|
||||
const DEFAULT_WEAPP_OPTIONS = {
|
||||
platform: 'h5',
|
||||
designWidth: 750,
|
||||
deviceRatio,
|
||||
h5Width: 450,
|
||||
}
|
||||
|
||||
let targetUnit
|
||||
|
||||
module.exports = postcss.plugin('postcss-pxtransform', function (options) {
|
||||
options = Object.assign(DEFAULT_WEAPP_OPTIONS, options || {})
|
||||
|
||||
switch (options.platform) {
|
||||
case 'weapp': {
|
||||
options.rootValue = 1 / options.deviceRatio[options.designWidth]
|
||||
targetUnit = 'rpx'
|
||||
break
|
||||
}
|
||||
case 'h5': {
|
||||
options.rootValue = (baseFontSize * options.designWidth / 640) * (factor / options.h5Width)
|
||||
targetUnit = 'rem'
|
||||
break
|
||||
}
|
||||
case 'rn': {
|
||||
options.rootValue = options.deviceRatio[options.designWidth] * 2
|
||||
targetUnit = 'px'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
convertLegacyOptions(options)
|
||||
|
||||
const opts = objectAssign({}, defaults, options)
|
||||
const onePxTransform = typeof options.onePxTransform === 'undefined' ? true : options.onePxTransform
|
||||
const pxReplace = createPxReplace(opts.rootValue, opts.unitPrecision,
|
||||
opts.minPixelValue, onePxTransform)
|
||||
|
||||
const satisfyPropList = createPropListMatcher(opts.propList)
|
||||
|
||||
return function (css) {
|
||||
// only transform taroify style
|
||||
const filePath = css.source.input.file;
|
||||
if (filePath.match(/^((?!@taroify).)*$/) !== null) {
|
||||
return
|
||||
}
|
||||
|
||||
for (let i = 0; i < css.nodes.length; i++) {
|
||||
if (css.nodes[i].type === 'comment') {
|
||||
if (css.nodes[i].text === 'postcss-pxtransform disable') {
|
||||
return
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// delete code between comment in RN
|
||||
if (options.platform === 'rn') {
|
||||
css.walkComments(comment => {
|
||||
if (comment.text === 'postcss-pxtransform rn eject enable') {
|
||||
let next = comment.next()
|
||||
while (next) {
|
||||
if (next.type === 'comment' && next.text === 'postcss-pxtransform rn eject disable') {
|
||||
break
|
||||
}
|
||||
const temp = next.next()
|
||||
next.remove()
|
||||
next = temp
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* #ifdef %PLATFORM% */
|
||||
// 平台特有样式
|
||||
/* #endif */
|
||||
css.walkComments(comment => {
|
||||
const wordList = comment.text.split(' ')
|
||||
// 指定平台保留
|
||||
if (wordList.indexOf('#ifdef') > -1) {
|
||||
// 非指定平台
|
||||
if (wordList.indexOf(options.platform) === -1) {
|
||||
let next = comment.next()
|
||||
while (next) {
|
||||
if (next.type === 'comment' && next.text.trim() === '#endif') {
|
||||
break
|
||||
}
|
||||
const temp = next.next()
|
||||
next.remove()
|
||||
next = temp
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/* #ifndef %PLATFORM% */
|
||||
// 平台特有样式
|
||||
/* #endif */
|
||||
css.walkComments(comment => {
|
||||
const wordList = comment.text.split(' ')
|
||||
// 指定平台剔除
|
||||
if (wordList.indexOf('#ifndef') > -1) {
|
||||
// 指定平台
|
||||
if (wordList.indexOf(options.platform) > -1) {
|
||||
let next = comment.next()
|
||||
while (next) {
|
||||
if (next.type === 'comment' && next.text.trim() === '#endif') {
|
||||
break
|
||||
}
|
||||
const temp = next.next()
|
||||
next.remove()
|
||||
next = temp
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
css.walkDecls(function (decl, i) {
|
||||
// This should be the fastest test and will remove most declarations
|
||||
if (decl.value.indexOf('px') === -1) return
|
||||
|
||||
if (!satisfyPropList(decl.prop)) return
|
||||
|
||||
if (blacklistedSelector(opts.selectorBlackList,
|
||||
decl.parent.selector)) return
|
||||
|
||||
const value = decl.value.replace(pxRegex, pxReplace)
|
||||
|
||||
// if rem unit already exists, do not add or replace
|
||||
if (declarationExists(decl.parent, decl.prop, value)) return
|
||||
|
||||
if (opts.replace) {
|
||||
decl.value = value
|
||||
} else {
|
||||
decl.parent.insertAfter(i, decl.clone({ value: value }))
|
||||
}
|
||||
})
|
||||
|
||||
if (opts.mediaQuery) {
|
||||
css.walkAtRules('media', function (rule) {
|
||||
if (rule.params.indexOf('px') === -1) return
|
||||
rule.params = rule.params.replace(pxRegex, pxReplace)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function convertLegacyOptions (options) {
|
||||
if (typeof options !== 'object') return
|
||||
if (
|
||||
(
|
||||
(typeof options.prop_white_list !== 'undefined' &&
|
||||
options.prop_white_list.length === 0) ||
|
||||
(typeof options.propWhiteList !== 'undefined' &&
|
||||
options.propWhiteList.length === 0)
|
||||
) &&
|
||||
typeof options.propList === 'undefined'
|
||||
) {
|
||||
options.propList = ['*']
|
||||
delete options.prop_white_list
|
||||
delete options.propWhiteList
|
||||
}
|
||||
Object.keys(legacyOptions).forEach(function (key) {
|
||||
if (options.hasOwnProperty(key)) {
|
||||
options[legacyOptions[key]] = options[key]
|
||||
delete options[key]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function createPxReplace (rootValue, unitPrecision, minPixelValue, onePxTransform) {
|
||||
return function (m, $1) {
|
||||
if (!$1) return m
|
||||
if (!onePxTransform && parseInt($1, 10) === 1) {
|
||||
return m
|
||||
}
|
||||
const pixels = parseFloat($1)
|
||||
if (pixels < minPixelValue) return m
|
||||
const fixedVal = toFixed((pixels / rootValue), unitPrecision)
|
||||
return (fixedVal === 0) ? '0' : fixedVal + targetUnit
|
||||
}
|
||||
}
|
||||
|
||||
function toFixed (number, precision) {
|
||||
const multiplier = Math.pow(10, precision + 1)
|
||||
const wholeNumber = Math.floor(number * multiplier)
|
||||
return Math.round(wholeNumber / 10) * 10 / multiplier
|
||||
}
|
||||
|
||||
function declarationExists (decls, prop, value) {
|
||||
return decls.some(function (decl) {
|
||||
return (decl.prop === prop && decl.value === value)
|
||||
})
|
||||
}
|
||||
|
||||
function blacklistedSelector (blacklist, selector) {
|
||||
if (typeof selector !== 'string') return
|
||||
return blacklist.some(function (regex) {
|
||||
if (typeof regex === 'string') return selector.indexOf(regex) !== -1
|
||||
return selector.match(regex)
|
||||
})
|
||||
}
|
||||
|
||||
function createPropListMatcher (propList) {
|
||||
const hasWild = propList.indexOf('*') > -1
|
||||
const matchAll = (hasWild && propList.length === 1)
|
||||
const lists = {
|
||||
exact: filterPropList.exact(propList),
|
||||
contain: filterPropList.contain(propList),
|
||||
startWith: filterPropList.startWith(propList),
|
||||
endWith: filterPropList.endWith(propList),
|
||||
notExact: filterPropList.notExact(propList),
|
||||
notContain: filterPropList.notContain(propList),
|
||||
notStartWith: filterPropList.notStartWith(propList),
|
||||
notEndWith: filterPropList.notEndWith(propList)
|
||||
}
|
||||
return function (prop) {
|
||||
if (matchAll) return true
|
||||
return (
|
||||
(
|
||||
hasWild ||
|
||||
lists.exact.indexOf(prop) > -1 ||
|
||||
lists.contain.some(function (m) {
|
||||
return prop.indexOf(m) > -1
|
||||
}) ||
|
||||
lists.startWith.some(function (m) {
|
||||
return prop.indexOf(m) === 0
|
||||
}) ||
|
||||
lists.endWith.some(function (m) {
|
||||
return prop.indexOf(m) === prop.length - m.length
|
||||
})
|
||||
) &&
|
||||
!(
|
||||
lists.notExact.indexOf(prop) > -1 ||
|
||||
lists.notContain.some(function (m) {
|
||||
return prop.indexOf(m) > -1
|
||||
}) ||
|
||||
lists.notStartWith.some(function (m) {
|
||||
return prop.indexOf(m) === 0
|
||||
}) ||
|
||||
lists.notEndWith.some(function (m) {
|
||||
return prop.indexOf(m) === prop.length - m.length
|
||||
})
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,8 @@
|
|||
"@sentry/react": "^6.2.4",
|
||||
"@sentry/tracing": "^6.2.4",
|
||||
"@sentry/webpack-plugin": "^1.12.1",
|
||||
"@taroify/core": "^0.0.21-alpha.0",
|
||||
"@tarojs/components": "^3.3.14",
|
||||
"@types/chance": "^1.0.7",
|
||||
"@types/lodash": "^4.14.120",
|
||||
"@types/moment-timezone": "^0.5.10",
|
||||
|
|
@ -103,7 +105,7 @@
|
|||
"moment-timezone": "^0.5.27",
|
||||
"nanoid": "^2.0.4",
|
||||
"node-forge": "^0.10.0",
|
||||
"node-sass": "^6.0.1",
|
||||
"node-sass": "4.14.1",
|
||||
"normalizr": "^3.3.0",
|
||||
"path-to-regexp": "^6.2.0",
|
||||
"popper.js": "^1.15.0",
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ export interface CreateApplicationRequest {
|
|||
orgId: string;
|
||||
color?: AppColorCode;
|
||||
icon?: AppIconName;
|
||||
unpublishedAppLayout?: AppLayoutConfig;
|
||||
publishedAppLayout?: AppLayoutConfig;
|
||||
}
|
||||
|
||||
export interface SetDefaultPageRequest {
|
||||
|
|
@ -171,7 +173,13 @@ class ApplicationApi extends Api {
|
|||
return Api.post(
|
||||
ApplicationApi.baseURL +
|
||||
ApplicationApi.createApplicationPath(request.orgId),
|
||||
{ name: request.name, color: request.color, icon: request.icon },
|
||||
{
|
||||
name: request.name,
|
||||
color: request.color,
|
||||
icon: request.icon,
|
||||
unpublishedAppLayout: request.unpublishedAppLayout,
|
||||
publishedAppLayout: request.publishedAppLayout,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1639911707922" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8357" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css">@font-face { font-weight: 400; font-style: normal; font-family: Circular-Loom; src: url("https://cdn.loom.com/assets/fonts/circular/CircularXXWeb-Book-cd7d2bcec649b1243839a15d5eb8f0a3.woff2") format("woff2"); }
|
||||
@font-face { font-weight: 500; font-style: normal; font-family: Circular-Loom; src: url("https://cdn.loom.com/assets/fonts/circular/CircularXXWeb-Medium-d74eac43c78bd5852478998ce63dceb3.woff2") format("woff2"); }
|
||||
@font-face { font-weight: 700; font-style: normal; font-family: Circular-Loom; src: url("https://cdn.loom.com/assets/fonts/circular/CircularXXWeb-Bold-83b8ceaf77f49c7cffa44107561909e4.woff2") format("woff2"); }
|
||||
@font-face { font-weight: 900; font-style: normal; font-family: Circular-Loom; src: url("https://cdn.loom.com/assets/fonts/circular/CircularXXWeb-Black-bf067ecb8aa777ceb6df7d72226febca.woff2") format("woff2"); }
|
||||
</style></defs><path d="M512 170.666667a192 192 0 0 1 191.786667 182.954666l0.213333 9.045334h-42.666667a149.333333 149.333333 0 1 0-157.525333 149.12L512 512v42.666667a192 192 0 1 1 0-384z" fill="#3E3E3E" p-id="8358"></path><path d="M512 512c105.472 0 192 75.733333 192 170.666667s-86.528 170.666667-192 170.666666c-102.357333 0-186.88-71.338667-191.786667-162.346666L320 682.666667h42.666667c0 69.973333 66.261333 128 149.333333 128s149.333333-58.026667 149.333333-128c0-67.584-61.781333-123.989333-140.8-127.786667L512 554.666667v-42.666667z" fill="#3E3E3E" p-id="8359"></path><path d="M853.333333 512v42.666667H170.666667v-42.666667z" fill="#3E3E3E" p-id="8360"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
|
|
@ -13,7 +13,7 @@ const ItemWrapper = styled.div<{ selected: boolean }>`
|
|||
? props.theme.colors.propertyPane.activeButtonText
|
||||
: props.theme.colors.propertyPane.multiDropdownBoxHoverBg};
|
||||
cursor: pointer;
|
||||
&:first-of-type {
|
||||
&:not(:last-of-type) {
|
||||
margin-right: 4px;
|
||||
}
|
||||
&&& svg {
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ function ColorPickerComponent(props: ColorPickerProps) {
|
|||
)
|
||||
}
|
||||
onChange={handleChangeColor}
|
||||
placeholder="enter color name or hex"
|
||||
placeholder="输入web颜色名称,或者hex"
|
||||
value={color}
|
||||
/>
|
||||
<ColorBoard
|
||||
|
|
|
|||
|
|
@ -264,6 +264,7 @@ export type IconProps = {
|
|||
keepColors?: boolean;
|
||||
loaderWithIconWrapper?: boolean;
|
||||
clickable?: boolean;
|
||||
isMobile?: boolean;
|
||||
};
|
||||
|
||||
const Icon = forwardRef(
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ const StyledMenu = styled(Menu)`
|
|||
margin: 0px 6px;
|
||||
border-radius: ${(props) => props.theme.borderRadius};
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
line-height: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
import React from "react";
|
||||
import { Button } from "@taroify/core";
|
||||
|
||||
interface ButtonComponentProps {
|
||||
text?: string;
|
||||
color?: string;
|
||||
onClick?: any;
|
||||
rounded?: boolean;
|
||||
isDisabled?: boolean;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const ButtonComponent = ({
|
||||
text,
|
||||
color,
|
||||
onClick,
|
||||
rounded,
|
||||
isDisabled,
|
||||
isLoading,
|
||||
}: ButtonComponentProps) => {
|
||||
const style = {
|
||||
height: "100%",
|
||||
backgroundColor: color || "var(--primary-color)",
|
||||
color: "#fff",
|
||||
};
|
||||
const shape = rounded ? "round" : "square";
|
||||
return (
|
||||
<Button
|
||||
disabled={isDisabled}
|
||||
loading={!!isLoading}
|
||||
block
|
||||
style={style}
|
||||
onClick={onClick}
|
||||
shape={shape}
|
||||
>
|
||||
{text || "好的"}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default ButtonComponent;
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
import React, { useState } from "react";
|
||||
import { Text, View, ScrollView } from "@tarojs/components";
|
||||
import { Grid, Image, Button } from "@taroify/core";
|
||||
import { PhotoOutlined, ShoppingCartOutlined } from "@taroify/icons";
|
||||
import _ from "lodash";
|
||||
import styled from "styled-components";
|
||||
|
||||
export interface GridComponentProps {
|
||||
list: any[];
|
||||
gridType: "I_N" | "I_N_D" | "I_N_D_B";
|
||||
urlKey: string;
|
||||
titleKey: string;
|
||||
descriptionKey?: string;
|
||||
asPrice?: boolean;
|
||||
priceUnit?: string;
|
||||
buttonText?: string;
|
||||
height?: string;
|
||||
cols?: number;
|
||||
gutter?: string;
|
||||
bordered?: boolean;
|
||||
titleColor?: string;
|
||||
descriptionColor?: string;
|
||||
buttonColor?: string;
|
||||
}
|
||||
|
||||
const SameHeightImage = styled(Image)<{
|
||||
height?: string;
|
||||
}>`
|
||||
height: ${(props) => props.height || "auto"};
|
||||
`;
|
||||
|
||||
const Title = styled(Text)<{
|
||||
color?: string;
|
||||
}>`
|
||||
color: ${(props) => props.color || "#646566"};
|
||||
font-size: 16px;
|
||||
`;
|
||||
|
||||
const Container = styled(View)<{
|
||||
isBetween: boolean;
|
||||
}>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: ${(props) =>
|
||||
props.isBetween ? "space-between" : "space-around"};
|
||||
margin-top: 8px;
|
||||
`;
|
||||
|
||||
const Price = styled(Text)<{
|
||||
color?: string;
|
||||
}>`
|
||||
color: ${(props) => props.color || "#DD4B34"};
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
const BuyButton = styled(Button)<{
|
||||
bgColor?: string;
|
||||
}>`
|
||||
background-color: ${(props) => props.bgColor || "#03b365"};
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
padding: 0 8px;
|
||||
`;
|
||||
|
||||
const ColorGrid = styled(Grid)<{
|
||||
textColor?: string;
|
||||
}>`
|
||||
--grid-item-text-color: ${(props) => props.textColor};
|
||||
`;
|
||||
|
||||
const GridComponent = (props: GridComponentProps) => {
|
||||
const {
|
||||
list,
|
||||
gridType,
|
||||
urlKey,
|
||||
titleKey,
|
||||
descriptionKey,
|
||||
asPrice,
|
||||
priceUnit,
|
||||
buttonText,
|
||||
height,
|
||||
cols,
|
||||
gutter,
|
||||
bordered,
|
||||
titleColor,
|
||||
descriptionColor,
|
||||
buttonColor,
|
||||
} = props;
|
||||
const items = _.isArray(list) ? list : [];
|
||||
const key = urlKey + titleKey + items.length;
|
||||
const isSimple = gridType === "I_N";
|
||||
|
||||
const onClickButton = (item: any) => (e: any) => {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const onClickGridItem = (item: any) => (e: any) => {
|
||||
console.log(item);
|
||||
};
|
||||
|
||||
return (
|
||||
<ScrollView style={{ height: "100%" }} scrollY>
|
||||
<ColorGrid
|
||||
key={key}
|
||||
columns={cols}
|
||||
gutter={gutter}
|
||||
bordered={bordered}
|
||||
textColor={titleColor}
|
||||
clickable
|
||||
>
|
||||
{items.map((item, index) => {
|
||||
const url = item[urlKey];
|
||||
const title = item[titleKey] || "";
|
||||
const image = url ? (
|
||||
<SameHeightImage
|
||||
src={url}
|
||||
height={height}
|
||||
mode={isSimple ? undefined : "aspectFill"}
|
||||
/>
|
||||
) : (
|
||||
<PhotoOutlined size={height} />
|
||||
);
|
||||
if (isSimple) {
|
||||
return (
|
||||
<Grid.Item
|
||||
icon={image}
|
||||
text={title}
|
||||
key={index}
|
||||
onClick={onClickGridItem(item)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
const description = item[descriptionKey || ""] || "描述";
|
||||
const price = asPrice ? priceUnit + description : description;
|
||||
const priceView = <Price color={descriptionColor}>{price}</Price>;
|
||||
return (
|
||||
<Grid.Item key={index} onClick={onClickGridItem(item)}>
|
||||
{image}
|
||||
<View style={{ marginTop: "8px" }}>
|
||||
<Title color={titleColor}>{title}</Title>
|
||||
<Container isBetween={gridType === "I_N_D_B"}>
|
||||
{priceView}
|
||||
{gridType === "I_N_D_B" ? (
|
||||
<BuyButton
|
||||
bgColor={buttonColor}
|
||||
size="mini"
|
||||
shape="round"
|
||||
onClick={onClickButton(item)}
|
||||
>
|
||||
{buttonText || <ShoppingCartOutlined />}
|
||||
</BuyButton>
|
||||
) : null}
|
||||
</Container>
|
||||
</View>
|
||||
</Grid.Item>
|
||||
);
|
||||
})}
|
||||
</ColorGrid>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
export default GridComponent;
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import React from "react";
|
||||
import { Image } from "@taroify/core";
|
||||
|
||||
interface ImageComponentProps {
|
||||
imageUrl: string;
|
||||
mode: any;
|
||||
onClick?: any;
|
||||
isCircle?: boolean;
|
||||
radius?: string;
|
||||
}
|
||||
|
||||
const ImageComponent = ({
|
||||
imageUrl,
|
||||
mode,
|
||||
onClick,
|
||||
isCircle,
|
||||
radius,
|
||||
}: ImageComponentProps) => {
|
||||
const style = {
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
borderRadius: radius,
|
||||
};
|
||||
return (
|
||||
<Image
|
||||
src={imageUrl}
|
||||
style={style}
|
||||
mode={mode}
|
||||
onClick={onClick}
|
||||
round={isCircle}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ImageComponent;
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
import React, { useState } from "react";
|
||||
import { Text, View, ScrollView } from "@tarojs/components";
|
||||
import { Cell, Image, Button } from "@taroify/core";
|
||||
import { PhotoOutlined, ShoppingCartOutlined } from "@taroify/icons";
|
||||
import _ from "lodash";
|
||||
import styled from "styled-components";
|
||||
|
||||
export interface ListComponentProps {
|
||||
list: any[];
|
||||
contentType: "I_N_D_P_B" | "I_N_D" | "I_N_D_P";
|
||||
urlKey: string;
|
||||
titleKey: string;
|
||||
descriptionKey: string;
|
||||
priceKey?: string;
|
||||
buttonText?: string;
|
||||
inset?: boolean;
|
||||
width: string;
|
||||
height: string;
|
||||
titleColor?: string;
|
||||
descriptionColor?: string;
|
||||
priceColor?: string;
|
||||
buttonColor?: string;
|
||||
}
|
||||
|
||||
const FreeImage = styled(Image)<{
|
||||
width: string;
|
||||
height: string;
|
||||
}>`
|
||||
width: ${(props) => props.width};
|
||||
height: ${(props) => props.height};
|
||||
`;
|
||||
|
||||
const RowCenter = styled(View)`
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const Title = styled(Text)<{
|
||||
color?: string;
|
||||
}>`
|
||||
color: ${(props) => props.color || "#646566"};
|
||||
font-size: 16px;
|
||||
`;
|
||||
|
||||
const Description = styled(Text)<{
|
||||
color?: string;
|
||||
}>`
|
||||
color: ${(props) => props.color || "#646566"};
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
const Container = styled(View)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 8px;
|
||||
`;
|
||||
|
||||
const Price = styled(Text)<{
|
||||
color?: string;
|
||||
}>`
|
||||
color: ${(props) => props.color || "#DD4B34"};
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
const BuyButton = styled(Button)<{
|
||||
bgColor?: string;
|
||||
}>`
|
||||
background-color: ${(props) => props.bgColor || "#03b365"};
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
padding: 0 8px;
|
||||
`;
|
||||
|
||||
const ListComponent = (props: ListComponentProps) => {
|
||||
const {
|
||||
list,
|
||||
contentType,
|
||||
urlKey,
|
||||
titleKey,
|
||||
descriptionKey,
|
||||
priceKey,
|
||||
buttonText,
|
||||
inset,
|
||||
width,
|
||||
height,
|
||||
titleColor,
|
||||
descriptionColor,
|
||||
priceColor,
|
||||
buttonColor,
|
||||
} = props;
|
||||
const items = _.isArray(list) ? list : [];
|
||||
const noPrice = contentType === "I_N_D";
|
||||
const hasButton = contentType === "I_N_D_P_B";
|
||||
|
||||
const onClickButton = (item: any) => (e: any) => {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const onClickItem = (item: any) => (e: any) => {
|
||||
console.log(item);
|
||||
};
|
||||
|
||||
return (
|
||||
<ScrollView style={{ height: "100%" }} scrollY>
|
||||
<Cell.Group inset={inset}>
|
||||
{items.map((item, index) => {
|
||||
const url = item[urlKey];
|
||||
const title = item[titleKey] || "";
|
||||
const description = item[descriptionKey] || "描述";
|
||||
const price = `¥${item[priceKey || ""] || "168"}`;
|
||||
const image = url ? (
|
||||
<FreeImage
|
||||
src={url}
|
||||
height={height}
|
||||
width={width}
|
||||
mode="aspectFill"
|
||||
/>
|
||||
) : (
|
||||
<PhotoOutlined
|
||||
size={height > width ? height : width}
|
||||
style={{ height, width }}
|
||||
/>
|
||||
);
|
||||
const priceView = <Price color={priceColor}>{price}</Price>;
|
||||
return (
|
||||
<Cell key={index} onClick={onClickItem(item)} icon={image}>
|
||||
<RowCenter>
|
||||
<Title color={titleColor}>{title}</Title>
|
||||
<View>
|
||||
<Description color={descriptionColor}>
|
||||
{description}
|
||||
</Description>
|
||||
</View>
|
||||
{noPrice ? null : (
|
||||
<Container>
|
||||
{priceView}
|
||||
{hasButton ? (
|
||||
<BuyButton
|
||||
bgColor={buttonColor}
|
||||
size="mini"
|
||||
shape="round"
|
||||
onClick={onClickButton(item)}
|
||||
>
|
||||
{buttonText || <ShoppingCartOutlined />}
|
||||
</BuyButton>
|
||||
) : null}
|
||||
</Container>
|
||||
)}
|
||||
</RowCenter>
|
||||
</Cell>
|
||||
);
|
||||
})}
|
||||
</Cell.Group>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
export default ListComponent;
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
import React, { useState } from "react";
|
||||
import { View, Text } from "@tarojs/components";
|
||||
import VirtualList from "@tarojs/components/virtual-list";
|
||||
import Taro from "@tarojs/taro";
|
||||
import {
|
||||
Uploader,
|
||||
Cell,
|
||||
Button,
|
||||
Image,
|
||||
Toast,
|
||||
Checkbox,
|
||||
Field,
|
||||
NoticeBar,
|
||||
Flex,
|
||||
Dialog,
|
||||
} from "@taroify/core";
|
||||
import { Arrow } from "@taroify/icons";
|
||||
|
||||
interface PickerComponentProps {
|
||||
title?: string;
|
||||
onButtonClick?: (e: any) => void;
|
||||
}
|
||||
|
||||
function buildData(offset = 0) {
|
||||
return Array(100)
|
||||
.fill(0)
|
||||
.map((_, i) => i + offset);
|
||||
}
|
||||
|
||||
const Row = React.memo(({ id, index, style, data }: any) => {
|
||||
return (
|
||||
<View
|
||||
id={id}
|
||||
className={index % 2 ? "ListItemOdd" : "ListItemEven"}
|
||||
style={style}
|
||||
>
|
||||
Row {index} : {data[index]}
|
||||
</View>
|
||||
);
|
||||
});
|
||||
Row.displayName = "Row";
|
||||
|
||||
const PickerComponent = (props: PickerComponentProps) => {
|
||||
const { title, onButtonClick } = props;
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [data, setData] = useState(buildData(0));
|
||||
const listReachBottom = () => {
|
||||
// 如果 loading 与视图相关,那它就应该放在 `this.state` 里
|
||||
// 我们这里使用的是一个同步的 API 调用 loading,所以不需要
|
||||
setLoading(true);
|
||||
setTimeout(() => {
|
||||
setData(data.concat(buildData(data.length)));
|
||||
setLoading(false);
|
||||
}, 1000);
|
||||
};
|
||||
const dataLen = data.length;
|
||||
const itemSize = 100;
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [value, setValue] = useState<any>();
|
||||
const [text, setText] = useState("");
|
||||
const [idcard, setIdcard] = useState("");
|
||||
const [number, setNumber] = useState("");
|
||||
const [digit, setDigit] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
|
||||
const [file, setFile] = useState<Uploader.File>();
|
||||
|
||||
const onUpload = () => {
|
||||
Taro.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ["original", "compressed"],
|
||||
sourceType: ["album", "camera"],
|
||||
}).then(({ tempFiles }) => {
|
||||
setFile({
|
||||
url: tempFiles[0].path,
|
||||
type: tempFiles[0].type,
|
||||
name: tempFiles[0].originalFileObj?.name,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const show = () => {
|
||||
Taro.showToast({
|
||||
title: "生活愉快!",
|
||||
icon: "success",
|
||||
duration: 2000,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View>
|
||||
<Button color="primary" onClick={onButtonClick}>
|
||||
{title}
|
||||
</Button>
|
||||
<Button variant="text" color="info">
|
||||
信息按钮
|
||||
</Button>
|
||||
<Button variant="outlined" color="warning">
|
||||
警告按钮
|
||||
</Button>
|
||||
</View>
|
||||
<View>
|
||||
<Cell.Group title="分组 1">
|
||||
<Cell
|
||||
title="打开弹窗"
|
||||
rightIcon={<Arrow />}
|
||||
clickable
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
内容
|
||||
</Cell>
|
||||
</Cell.Group>
|
||||
<Cell.Group title="分组 2">
|
||||
<Cell title="单元格" brief="描述信息" rightIcon={<Arrow />} clickable>
|
||||
内容
|
||||
</Cell>
|
||||
</Cell.Group>
|
||||
</View>
|
||||
<View>
|
||||
<Flex justify="center" align="center">
|
||||
<Image
|
||||
round
|
||||
mode="aspectFill"
|
||||
style={{ width: "10rem", height: "10rem" }}
|
||||
src="https://img.yzcdn.cn/vant/cat.jpeg"
|
||||
/>
|
||||
</Flex>
|
||||
</View>
|
||||
<View>
|
||||
<Checkbox.Group
|
||||
direction="horizontal"
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
>
|
||||
<Checkbox name="a">复选框 a</Checkbox>
|
||||
<Checkbox name="b">复选框 b</Checkbox>
|
||||
</Checkbox.Group>
|
||||
</View>
|
||||
<div>
|
||||
<Uploader value={file} onUpload={onUpload} onChange={setFile} />
|
||||
</div>
|
||||
<View>
|
||||
<Cell.Group inset>
|
||||
<Field
|
||||
value={text}
|
||||
label="文本"
|
||||
placeholder="请输入文本"
|
||||
onChange={(e) => setText(e.detail.value)}
|
||||
/>
|
||||
<Field
|
||||
value={idcard}
|
||||
label="身份证号"
|
||||
type="idcard"
|
||||
placeholder="请输入手机号"
|
||||
onChange={(e) => setIdcard(e.detail.value)}
|
||||
/>
|
||||
<Field
|
||||
value={number}
|
||||
label="整数"
|
||||
type="number"
|
||||
placeholder="请输入整数"
|
||||
onChange={(e) => setNumber(e.detail.value)}
|
||||
/>
|
||||
<Field
|
||||
value={digit}
|
||||
label="数字"
|
||||
type="digit"
|
||||
placeholder="请输入数字(支持小数)"
|
||||
onChange={(e) => setDigit(e.detail.value)}
|
||||
/>
|
||||
<Field
|
||||
value={password}
|
||||
label="密码"
|
||||
type="password"
|
||||
placeholder="请输入密码"
|
||||
onChange={(e) => setPassword(e.detail.value)}
|
||||
/>
|
||||
</Cell.Group>
|
||||
</View>
|
||||
<View>
|
||||
<NoticeBar scrollable>{title}</NoticeBar>
|
||||
</View>
|
||||
<View>
|
||||
<Dialog open={open} onClose={setOpen}>
|
||||
<Dialog.Header>{title}</Dialog.Header>
|
||||
<Dialog.Content>
|
||||
代码是写出来给人看的,附带能在机器上运行
|
||||
</Dialog.Content>
|
||||
<Dialog.Actions theme="round">
|
||||
<Button onClick={() => setOpen(false)}>取消</Button>
|
||||
<Button onClick={() => setOpen(false)}>确认</Button>
|
||||
</Dialog.Actions>
|
||||
</Dialog>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default PickerComponent;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
import React, { ReactNode, useEffect } from "react";
|
||||
import styled from "styled-components";
|
||||
import { getCanvasClassName } from "utils/generators";
|
||||
import { Popup } from "@taroify/core";
|
||||
import { Cross } from "@taroify/icons";
|
||||
import { PopupProps } from "@taroify/core/popup/popup";
|
||||
|
||||
const PopupContainer = styled(Popup)<
|
||||
{
|
||||
height?: number;
|
||||
} & PopupProps
|
||||
>`
|
||||
height: ${(props) => props.height}px;
|
||||
overflow: visible;
|
||||
width: 450px;
|
||||
left: unset;
|
||||
background: #f6f6f6;
|
||||
`;
|
||||
|
||||
const Content = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
export type ModalComponentProps = {
|
||||
isOpen: boolean;
|
||||
onClose: (e: any) => void;
|
||||
onModalClose?: () => void;
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
canOutsideClickClose: boolean;
|
||||
rounded?: boolean;
|
||||
height?: number;
|
||||
};
|
||||
|
||||
/* eslint-disable react/display-name */
|
||||
export function ModalComponent(props: ModalComponentProps) {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (props.onModalClose) props.onModalClose();
|
||||
};
|
||||
}, []);
|
||||
return (
|
||||
<PopupContainer
|
||||
open={props.isOpen}
|
||||
onClose={props.onClose}
|
||||
placement="bottom"
|
||||
height={props.height}
|
||||
rounded={props.rounded}
|
||||
>
|
||||
<Popup.Backdrop
|
||||
closeable={props.canOutsideClickClose}
|
||||
style={{ left: "unset", right: "unset", width: "450px" }}
|
||||
/>
|
||||
<Popup.Close>
|
||||
<Cross size="24px" style={{ zIndex: 2 }} />
|
||||
</Popup.Close>
|
||||
<Content className={`${getCanvasClassName()} ${props.className}`}>
|
||||
{props.children}
|
||||
</Content>
|
||||
</PopupContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export default ModalComponent;
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import React, { useState } from "react";
|
||||
import { Navigator } from "@tarojs/components";
|
||||
import { Swiper, Image } from "@taroify/core";
|
||||
import _ from "lodash";
|
||||
import styled from "styled-components";
|
||||
|
||||
interface SwiperComponentProps {
|
||||
list: any[];
|
||||
urlKey: string;
|
||||
}
|
||||
|
||||
const Empty = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32px;
|
||||
color: #fff;
|
||||
background: var(--primary-color);
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const SwiperComponent = (props: SwiperComponentProps) => {
|
||||
const { list, urlKey } = props;
|
||||
const items = _.isArray(list) ? list : [];
|
||||
const key = urlKey + items.length;
|
||||
return (
|
||||
<Swiper style={{ height: "100%" }} autoplay={4000} key={key}>
|
||||
<Swiper.Indicator />
|
||||
{items.map((item, index) => {
|
||||
const url = _.isString(item) ? item : item[urlKey];
|
||||
const content = url ? (
|
||||
<Image src={url} mode="aspectFill" />
|
||||
) : (
|
||||
<Empty>{index + 1}</Empty>
|
||||
);
|
||||
return (
|
||||
<Swiper.Item key={index}>
|
||||
<Navigator>{content}</Navigator>
|
||||
</Swiper.Item>
|
||||
);
|
||||
})}
|
||||
</Swiper>
|
||||
);
|
||||
};
|
||||
|
||||
export default SwiperComponent;
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
import * as React from "react";
|
||||
import { Text, View } from "@tarojs/components";
|
||||
import styled from "styled-components";
|
||||
import { ComponentProps } from "components/designSystems/appsmith/BaseComponent";
|
||||
import { TextAlign } from "widgets/TextWidget";
|
||||
import {
|
||||
FontStyleTypes,
|
||||
TextSize,
|
||||
TEXT_SIZES,
|
||||
} from "constants/WidgetConstants";
|
||||
|
||||
export const TextContainer = styled(View)`
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const StyledText = styled(Text)<{
|
||||
scroll: boolean;
|
||||
textAlign: string;
|
||||
backgroundColor?: string;
|
||||
textColor?: string;
|
||||
fontStyle?: string;
|
||||
fontSize?: TextSize;
|
||||
}>`
|
||||
height: 100%;
|
||||
overflow-y: ${(props) => (props.scroll ? "auto" : "hidden")};
|
||||
text-overflow: ellipsis;
|
||||
text-align: ${(props) => props.textAlign.toLowerCase()};
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: ${(props) =>
|
||||
props.textAlign === "LEFT"
|
||||
? "flex-start"
|
||||
: props.textAlign === "RIGHT"
|
||||
? "flex-end"
|
||||
: "center"};
|
||||
align-items: ${(props) => (props.scroll ? "flex-start" : "center")};
|
||||
background: ${(props) => props?.backgroundColor};
|
||||
color: ${(props) => props?.textColor};
|
||||
font-style: ${(props) =>
|
||||
props?.fontStyle?.includes(FontStyleTypes.ITALIC) ? "italic" : ""};
|
||||
text-decoration: ${(props) =>
|
||||
props?.fontStyle?.includes(FontStyleTypes.LINETHROUGH)
|
||||
? "line-through"
|
||||
: ""};
|
||||
font-weight: ${(props) =>
|
||||
props?.fontStyle?.includes(FontStyleTypes.BOLD) ? "bold" : "normal"};
|
||||
font-size: ${(props) => props?.fontSize && TEXT_SIZES[props?.fontSize]};
|
||||
`;
|
||||
|
||||
export interface TextComponentProps extends ComponentProps {
|
||||
text?: string;
|
||||
textAlign: TextAlign;
|
||||
fontSize?: TextSize;
|
||||
isLoading: boolean;
|
||||
shouldScroll?: boolean;
|
||||
backgroundColor?: string;
|
||||
textColor?: string;
|
||||
fontStyle?: string;
|
||||
}
|
||||
|
||||
class TextComponent extends React.Component<TextComponentProps> {
|
||||
render() {
|
||||
const {
|
||||
backgroundColor,
|
||||
fontSize,
|
||||
fontStyle,
|
||||
text,
|
||||
textAlign,
|
||||
textColor,
|
||||
} = this.props;
|
||||
return (
|
||||
<TextContainer>
|
||||
<StyledText
|
||||
backgroundColor={backgroundColor}
|
||||
fontSize={fontSize}
|
||||
fontStyle={fontStyle}
|
||||
scroll={!!this.props.shouldScroll}
|
||||
textAlign={textAlign}
|
||||
textColor={textColor}
|
||||
>
|
||||
{text}
|
||||
</StyledText>
|
||||
</TextContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TextComponent;
|
||||
|
|
@ -63,7 +63,7 @@ const EmptyContainer = styled.div`
|
|||
width: 400px;
|
||||
height: 400px;
|
||||
margin-top: -180px;
|
||||
margin-left: -100px;
|
||||
margin-left: -70px;
|
||||
text-align: center;
|
||||
opacity: 0.5;
|
||||
|
||||
|
|
@ -74,6 +74,7 @@ const EmptyContainer = styled.div`
|
|||
|
||||
& img {
|
||||
height: 100%;
|
||||
width: 70%;
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
@ -219,12 +220,17 @@ export function DropTargetComponent(props: DropTargetComponentProps) {
|
|||
// Only show propertypane if this is a new widget.
|
||||
// If it is not a new widget, then let the DraggableComponent handle it.
|
||||
// Give evaluations a second to complete.
|
||||
const waitingTime =
|
||||
widget.type === WidgetTypes.MODAL_WIDGET ||
|
||||
widget.type === WidgetTypes.TARO_POPUP_WIDGET
|
||||
? 1000
|
||||
: 100;
|
||||
setTimeout(() => {
|
||||
if (showPropertyPane && updateWidgetParams.payload.newWidgetId) {
|
||||
showPropertyPane(updateWidgetParams.payload.newWidgetId);
|
||||
// toggleEditWidgetName(updateWidgetParams.payload.newWidgetId, true);
|
||||
}
|
||||
}, 100);
|
||||
}, waitingTime);
|
||||
|
||||
// Select the widget if it is a new widget
|
||||
selectWidget && selectWidget(widget.widgetId);
|
||||
|
|
|
|||
|
|
@ -96,6 +96,11 @@ const getStyles = (
|
|||
background: Colors.OUTER_SPACE,
|
||||
color: Colors.WHITE,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
background: Colors.OUTER_SPACE,
|
||||
color: Colors.WHITE,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,8 @@ export function WidgetNameComponent(props: WidgetNameComponentProps) {
|
|||
!!props.errorCount;
|
||||
|
||||
let currentActivity =
|
||||
props.type === WidgetTypes.MODAL_WIDGET
|
||||
props.type === WidgetTypes.MODAL_WIDGET ||
|
||||
props.type === WidgetTypes.TARO_POPUP_WIDGET
|
||||
? Activities.HOVERING
|
||||
: Activities.NONE;
|
||||
if (focusedWidget === props.widgetId) currentActivity = Activities.HOVERING;
|
||||
|
|
|
|||
|
|
@ -2596,6 +2596,10 @@ export const theme: Theme = {
|
|||
},
|
||||
};
|
||||
|
||||
export { css, createGlobalStyle, keyframes, ThemeProvider };
|
||||
const taroifyTheme = {
|
||||
primaryColor: Colors.MINT_GREEN,
|
||||
};
|
||||
|
||||
export { css, createGlobalStyle, keyframes, ThemeProvider, taroifyTheme };
|
||||
|
||||
export default styled;
|
||||
|
|
|
|||
|
|
@ -139,6 +139,58 @@ export const HelpMap = {
|
|||
path: "/widget-reference/",
|
||||
searchKey: "Formily",
|
||||
},
|
||||
TARO_PICKER_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro Picker",
|
||||
},
|
||||
TARO_SWIPER_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro Swiper",
|
||||
},
|
||||
TARO_GRID_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro Grid",
|
||||
},
|
||||
TARO_LIST_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro List",
|
||||
},
|
||||
TARO_TEXT_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro Text",
|
||||
},
|
||||
TARO_POPUP_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro Popup",
|
||||
},
|
||||
TARO_BUTTON_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro Button",
|
||||
},
|
||||
TARO_IMAGE_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro Image",
|
||||
},
|
||||
TARO_CELL_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro Cell",
|
||||
},
|
||||
TARO_HTML_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro Html",
|
||||
},
|
||||
TARO_SIMPLE_FORM_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro Simple Form",
|
||||
},
|
||||
TARO_KV_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro KV",
|
||||
},
|
||||
TARO_TABS_WIDGET: {
|
||||
path: "/widget-reference/",
|
||||
searchKey: "Taro Tabs",
|
||||
},
|
||||
};
|
||||
|
||||
export const HelpBaseURL = "https://docs.appsmith.com";
|
||||
|
|
|
|||
|
|
@ -33,6 +33,19 @@ export enum WidgetTypes {
|
|||
DIVIDER_WIDGET = "DIVIDER_WIDGET",
|
||||
MENU_BUTTON_WIDGET = "MENU_BUTTON_WIDGET",
|
||||
FORMILY_WIDGET = "FORMILY_WIDGET",
|
||||
TARO_PICKER_WIDGET = "TARO_PICKER_WIDGET",
|
||||
TARO_SWIPER_WIDGET = "TARO_SWIPER_WIDGET",
|
||||
TARO_GRID_WIDGET = "TARO_GRID_WIDGET",
|
||||
TARO_TEXT_WIDGET = "TARO_TEXT_WIDGET",
|
||||
TARO_LIST_WIDGET = "TARO_LIST_WIDGET",
|
||||
TARO_POPUP_WIDGET = "TARO_POPUP_WIDGET",
|
||||
TARO_IMAGE_WIDGET = "TARO_IMAGE_WIDGET",
|
||||
TARO_BUTTON_WIDGET = "TARO_BUTTON_WIDGET",
|
||||
TARO_CELL_WIDGET = "TARO_CELL_WIDGET",
|
||||
TARO_HTML_WIDGET = "TARO_HTML_WIDGET",
|
||||
TARO_SIMPLE_FORM_WIDGET = "TARO_SIMPLE_FORM_WIDGET",
|
||||
TARO_KV_WIDGET = "TARO_KV_WIDGET",
|
||||
TARO_TABS_WIDGET = "TARO_TABS_WIDGET",
|
||||
}
|
||||
|
||||
export type WidgetType = keyof typeof WidgetTypes;
|
||||
|
|
@ -100,6 +113,7 @@ export const layoutConfigurations: LayoutConfigurations = {
|
|||
DESKTOP: { minWidth: 1160, maxWidth: 1280 },
|
||||
TABLET: { minWidth: 650, maxWidth: 800 },
|
||||
FLUID: { minWidth: -1, maxWidth: -1 },
|
||||
MOBILE_FLUID: { minWidth: 450, maxWidth: 450 },
|
||||
};
|
||||
|
||||
export const LATEST_PAGE_VERSION = 30;
|
||||
|
|
@ -136,6 +150,7 @@ export enum FontStyleTypes {
|
|||
ITALIC = "ITALIC",
|
||||
REGULAR = "REGULAR",
|
||||
UNDERLINE = "UNDERLINE",
|
||||
LINETHROUGH = "LINETHROUGH",
|
||||
}
|
||||
|
||||
export enum TextSizes {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ export const JAVASCRIPT_KEYWORDS = {
|
|||
|
||||
export const DATA_TREE_KEYWORDS = {
|
||||
actionPaths: "actionPaths",
|
||||
appsmith: "appsmith",
|
||||
global: "global",
|
||||
pageList: "pageList",
|
||||
[EXECUTION_PARAM_KEY]: EXECUTION_PARAM_KEY,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -207,7 +207,11 @@ export const GEN_TEMPLATE_FORM_ROUTE = "/form";
|
|||
export const getGenerateTemplateURL = (
|
||||
applicationId = ":applicationId",
|
||||
pageId = ":pageId",
|
||||
): string => `${BUILDER_PAGE_URL(applicationId, pageId)}${GEN_TEMPLATE_URL}`;
|
||||
isMobile = false,
|
||||
): string =>
|
||||
`${BUILDER_PAGE_URL(applicationId, pageId)}${
|
||||
isMobile ? "" : GEN_TEMPLATE_URL
|
||||
}`;
|
||||
|
||||
export const getGenerateTemplateFormURL = (
|
||||
applicationId = ":applicationId",
|
||||
|
|
|
|||
|
|
@ -124,13 +124,13 @@ export class DataTreeFactory {
|
|||
});
|
||||
|
||||
dataTree.pageList = pageList;
|
||||
dataTree.appsmith = {
|
||||
dataTree.global = {
|
||||
...appData,
|
||||
// combine both persistent and transient state with the transient state
|
||||
// taking precedence in case the key is the same
|
||||
store: { ...appData.store.persistent, ...appData.store.transient },
|
||||
} as DataTreeAppsmith;
|
||||
(dataTree.appsmith as DataTreeAppsmith).ENTITY_TYPE = ENTITY_TYPE.APPSMITH;
|
||||
(dataTree.global as DataTreeAppsmith).ENTITY_TYPE = ENTITY_TYPE.APPSMITH;
|
||||
return dataTree;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import { ReactComponent as HideColumnIcon } from "assets/icons/control/columns-v
|
|||
import { ReactComponent as DeleteColumnIcon } from "assets/icons/control/delete-column.svg";
|
||||
import { ReactComponent as BoldFontIcon } from "assets/icons/control/bold.svg";
|
||||
import { ReactComponent as ItalicsFontIcon } from "assets/icons/control/italics.svg";
|
||||
import { ReactComponent as LineThroughFontIcon } from "assets/icons/control/line-through.svg";
|
||||
import { ReactComponent as LeftAlignIcon } from "assets/icons/control/left-align.svg";
|
||||
import { ReactComponent as CenterAlignIcon } from "assets/icons/control/center-align.svg";
|
||||
import { ReactComponent as RightAlignIcon } from "assets/icons/control/right-align.svg";
|
||||
|
|
@ -206,6 +207,11 @@ export const ControlIcons: {
|
|||
<ItalicsFontIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
LINETHROUGH_FONT: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<LineThroughFontIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
LEFT_ALIGN: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<LeftAlignIcon />
|
||||
|
|
|
|||
|
|
@ -178,6 +178,71 @@ export const WidgetIcons: {
|
|||
<FormIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_PICKER_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<MultiSelectIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_SWIPER_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<VideoIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_GRID_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<TableIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_TEXT_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<TextIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_LIST_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<ListIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_POPUP_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<ModalIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_IMAGE_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<ImageIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_BUTTON_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<ButtonIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_CELL_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<ListIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_HTML_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<RichTextEditorIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_SIMPLE_FORM_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<FormIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_KV_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<TextIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
TARO_TABS_WIDGET: (props: IconProps) => (
|
||||
<IconWrapper {...props}>
|
||||
<TabsIcon />
|
||||
</IconWrapper>
|
||||
),
|
||||
};
|
||||
|
||||
export type WidgetIcon = typeof WidgetIcons[keyof typeof WidgetIcons];
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import "./wdyr";
|
|||
import ReactDOM from "react-dom";
|
||||
import { Provider } from "react-redux";
|
||||
import "./index.less";
|
||||
import { ThemeProvider } from "constants/DefaultTheme";
|
||||
import { ThemeProvider, taroifyTheme } from "constants/DefaultTheme";
|
||||
import { appInitializer } from "utils/AppsmithUtils";
|
||||
import { Slide } from "react-toastify";
|
||||
import store from "./store";
|
||||
|
|
@ -17,6 +17,8 @@ import { setThemeMode } from "actions/themeActions";
|
|||
import { StyledToastContainer } from "components/ads/Toast";
|
||||
import localStorage from "utils/localStorage";
|
||||
import "./polyfills/corejs-add-on";
|
||||
import AppErrorBoundary from "./AppErrorBoundry";
|
||||
import GlobalStyles from "globalStyles";
|
||||
// locale
|
||||
import { ConfigProvider } from "antd";
|
||||
import zhCNAntd from "antd/lib/locale/zh_CN";
|
||||
|
|
@ -27,9 +29,20 @@ import "moment/locale/zh-cn";
|
|||
import { setAutoFreeze } from "immer";
|
||||
const shouldAutoFreeze = process.env.NODE_ENV === "development";
|
||||
setAutoFreeze(shouldAutoFreeze);
|
||||
// taro-components polyfills
|
||||
import { ConfigProvider as TaroifyTheme } from "@taroify/core";
|
||||
import {
|
||||
applyPolyfills,
|
||||
defineCustomElements,
|
||||
} from "@tarojs/components/loader";
|
||||
import "@tarojs/components/dist/taro-components/taro-components.css";
|
||||
import "@taroify/icons/index.scss";
|
||||
import "@taroify/core/index.scss";
|
||||
applyPolyfills().then(() => {
|
||||
defineCustomElements(window);
|
||||
});
|
||||
|
||||
import AppErrorBoundary from "./AppErrorBoundry";
|
||||
import GlobalStyles from "globalStyles";
|
||||
// app init
|
||||
appInitializer();
|
||||
|
||||
function App() {
|
||||
|
|
@ -68,7 +81,9 @@ class ThemedApp extends React.Component<{
|
|||
<AppErrorBoundary>
|
||||
<IntlProvider locale="zh-CN" messages={zhCN}>
|
||||
<ConfigProvider locale={zhCNAntd}>
|
||||
<AppRouter />
|
||||
<TaroifyTheme theme={taroifyTheme}>
|
||||
<AppRouter />
|
||||
</TaroifyTheme>
|
||||
</ConfigProvider>
|
||||
</IntlProvider>
|
||||
</AppErrorBoundary>
|
||||
|
|
|
|||
|
|
@ -1231,6 +1231,172 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
|
|||
showReset: true,
|
||||
resetLabel: "重置",
|
||||
},
|
||||
[WidgetTypes.TARO_PICKER_WIDGET]: {
|
||||
widgetName: "m_picker",
|
||||
rows: 2 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 4 * GRID_DENSITY_MIGRATION_V1,
|
||||
title: "喵喵",
|
||||
},
|
||||
[WidgetTypes.TARO_SWIPER_WIDGET]: {
|
||||
widgetName: "m_swiper",
|
||||
rows: 6 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 16 * GRID_DENSITY_MIGRATION_V1,
|
||||
list: [
|
||||
{ url: "https://img01.yzcdn.cn/vant/apple-1.jpg" },
|
||||
{ url: "https://img01.yzcdn.cn/vant/apple-2.jpg" },
|
||||
{ url: "https://img01.yzcdn.cn/vant/apple-3.jpg" },
|
||||
{ url: "https://img01.yzcdn.cn/vant/apple-4.jpg" },
|
||||
],
|
||||
urlKey: "url",
|
||||
},
|
||||
[WidgetTypes.TARO_GRID_WIDGET]: {
|
||||
widgetName: "m_grid",
|
||||
rows: 6 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 16 * GRID_DENSITY_MIGRATION_V1,
|
||||
list: [
|
||||
{ url: "", name: "文本" },
|
||||
{ url: "", name: "文本" },
|
||||
{ url: "", name: "文本" },
|
||||
{ url: "", name: "文本" },
|
||||
{ url: "", name: "文本" },
|
||||
{ url: "", name: "文本" },
|
||||
],
|
||||
urlKey: "url",
|
||||
titleKey: "name",
|
||||
cols: 4,
|
||||
gutter: "0",
|
||||
bordered: true,
|
||||
gridType: "I_N",
|
||||
titleColor: "#646566",
|
||||
descriptionColor: "#DD4B34",
|
||||
buttonColor: "#03b365",
|
||||
priceUnit: "¥",
|
||||
},
|
||||
[WidgetTypes.TARO_TEXT_WIDGET]: {
|
||||
widgetName: "m_text",
|
||||
text: "文本",
|
||||
fontSize: "PARAGRAPH",
|
||||
textAlign: "LEFT",
|
||||
textColor: Colors.THUNDER,
|
||||
rows: 1 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 4 * GRID_DENSITY_MIGRATION_V1,
|
||||
version: 1,
|
||||
},
|
||||
[WidgetTypes.TARO_LIST_WIDGET]: {
|
||||
widgetName: "m_list",
|
||||
rows: 6 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 16 * GRID_DENSITY_MIGRATION_V1,
|
||||
list: [
|
||||
{ url: "", name: "标题", description: "描述" },
|
||||
{ url: "", name: "标题", description: "描述" },
|
||||
{ url: "", name: "标题", description: "描述" },
|
||||
{ url: "", name: "标题", description: "描述" },
|
||||
],
|
||||
urlKey: "url",
|
||||
titleKey: "name",
|
||||
descriptionKey: "description",
|
||||
contentType: "I_N_D",
|
||||
width: "100px",
|
||||
height: "80px",
|
||||
inset: false,
|
||||
titleColor: "#646566",
|
||||
descriptionColor: "#999",
|
||||
priceColor: "#DD4B34",
|
||||
buttonColor: "#03b365",
|
||||
},
|
||||
[WidgetTypes.TARO_POPUP_WIDGET]: {
|
||||
widgetName: "m_popup",
|
||||
rows: 10 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 12 * GRID_DENSITY_MIGRATION_V1,
|
||||
// detachFromLayout is set true for widgets that are not bound to the widgets within the layout.
|
||||
// setting it to true will only render the widgets(from sidebar) on the main container without any collision check.
|
||||
detachFromLayout: true,
|
||||
canOutsideClickClose: true,
|
||||
rounded: true,
|
||||
height: 400,
|
||||
children: [],
|
||||
version: 1,
|
||||
blueprint: {
|
||||
view: [
|
||||
{
|
||||
type: "CANVAS_WIDGET",
|
||||
position: { left: 0, top: 0 },
|
||||
props: {
|
||||
detachFromLayout: true,
|
||||
canExtend: false,
|
||||
isVisible: true,
|
||||
isDisabled: false,
|
||||
shouldScrollContents: false,
|
||||
children: [],
|
||||
version: 1,
|
||||
blueprint: {
|
||||
view: [
|
||||
{
|
||||
type: "TEXT_WIDGET",
|
||||
position: { left: 1, top: 1 },
|
||||
size: {
|
||||
rows: 1 * GRID_DENSITY_MIGRATION_V1,
|
||||
cols: 10 * GRID_DENSITY_MIGRATION_V1,
|
||||
},
|
||||
props: {
|
||||
text: "Modal Title",
|
||||
fontSize: "HEADING1",
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
[WidgetTypes.TARO_IMAGE_WIDGET]: {
|
||||
widgetName: "m_image",
|
||||
rows: 6 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 8 * GRID_DENSITY_MIGRATION_V1,
|
||||
src: "https://img.yzcdn.cn/vant/cat.jpeg",
|
||||
version: 1,
|
||||
},
|
||||
[WidgetTypes.TARO_BUTTON_WIDGET]: {
|
||||
widgetName: "m_button",
|
||||
rows: 1 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 6 * GRID_DENSITY_MIGRATION_V1,
|
||||
version: 1,
|
||||
rounded: true,
|
||||
text: "好的",
|
||||
},
|
||||
[WidgetTypes.TARO_CELL_WIDGET]: {
|
||||
widgetName: "m_cell",
|
||||
rows: 1 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 4 * GRID_DENSITY_MIGRATION_V1,
|
||||
version: 1,
|
||||
},
|
||||
[WidgetTypes.TARO_HTML_WIDGET]: {
|
||||
widgetName: "m_html",
|
||||
rows: 6 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 8 * GRID_DENSITY_MIGRATION_V1,
|
||||
content: "<span style='color: red'>五彩斑斓的黑</span>",
|
||||
version: 1,
|
||||
},
|
||||
[WidgetTypes.TARO_SIMPLE_FORM_WIDGET]: {
|
||||
widgetName: "m_form",
|
||||
rows: 1 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 4 * GRID_DENSITY_MIGRATION_V1,
|
||||
version: 1,
|
||||
},
|
||||
[WidgetTypes.TARO_KV_WIDGET]: {
|
||||
widgetName: "m_kv",
|
||||
rows: 1 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 4 * GRID_DENSITY_MIGRATION_V1,
|
||||
version: 1,
|
||||
},
|
||||
[WidgetTypes.TARO_TABS_WIDGET]: {
|
||||
widgetName: "m_tabs",
|
||||
rows: 1 * GRID_DENSITY_MIGRATION_V1,
|
||||
columns: 4 * GRID_DENSITY_MIGRATION_V1,
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
configVersion: 1,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -135,6 +135,84 @@ const WidgetSidebarResponse: WidgetCardProps[] = [
|
|||
widgetCardName: "复杂表单",
|
||||
key: generateReactKey(),
|
||||
},
|
||||
// {
|
||||
// type: "TARO_PICKER_WIDGET",
|
||||
// widgetCardName: "Picker",
|
||||
// key: generateReactKey(),
|
||||
// isMobile: true,
|
||||
// },
|
||||
{
|
||||
type: "TARO_SWIPER_WIDGET",
|
||||
widgetCardName: "轮播",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
{
|
||||
type: "TARO_GRID_WIDGET",
|
||||
widgetCardName: "网格内容",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
{
|
||||
type: "TARO_TEXT_WIDGET",
|
||||
widgetCardName: "文本",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
{
|
||||
type: "TARO_LIST_WIDGET",
|
||||
widgetCardName: "列表",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
{
|
||||
type: "TARO_POPUP_WIDGET",
|
||||
widgetCardName: "底部弹窗",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
{
|
||||
type: "TARO_IMAGE_WIDGET",
|
||||
widgetCardName: "图片",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
{
|
||||
type: "TARO_BUTTON_WIDGET",
|
||||
widgetCardName: "按钮",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
{
|
||||
type: "TARO_CELL_WIDGET",
|
||||
widgetCardName: "单元格",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
{
|
||||
type: "TARO_HTML_WIDGET",
|
||||
widgetCardName: "富文本",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
{
|
||||
type: "TARO_SIMPLE_FORM_WIDGET",
|
||||
widgetCardName: "快速表单",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
{
|
||||
type: "TARO_KV_WIDGET",
|
||||
widgetCardName: "键值对",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
{
|
||||
type: "TARO_TABS_WIDGET",
|
||||
widgetCardName: "标签页",
|
||||
key: generateReactKey(),
|
||||
isMobile: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default WidgetSidebarResponse;
|
||||
|
|
|
|||
|
|
@ -255,6 +255,27 @@ const OrgShareUsers = styled.div`
|
|||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
const AddIcon = styled(Icon)`
|
||||
position: absolute;
|
||||
top: ${(props) => (props.isMobile ? "12" : "10")}px;
|
||||
left: 50%;
|
||||
margin-left: -4.5px;
|
||||
|
||||
& svg {
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
}
|
||||
`;
|
||||
const AddTypeIcon = styled(Icon)`
|
||||
& svg {
|
||||
width: 39px;
|
||||
height: 39px;
|
||||
}
|
||||
`;
|
||||
|
||||
const IconGroup = styled.div`
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
function Item(props: {
|
||||
label: string;
|
||||
|
|
@ -613,7 +634,11 @@ function ApplicationsSection(props: any) {
|
|||
);
|
||||
}
|
||||
|
||||
const createNewApplication = (applicationName: string, orgId: string) => {
|
||||
const createNewApplication = (
|
||||
applicationName: string,
|
||||
orgId: string,
|
||||
isMobile: boolean,
|
||||
) => {
|
||||
const color = getRandomPaletteColor(theme.colors.appCardColors);
|
||||
const icon =
|
||||
AppIconCollection[Math.floor(Math.random() * AppIconCollection.length)];
|
||||
|
|
@ -625,10 +650,58 @@ function ApplicationsSection(props: any) {
|
|||
orgId,
|
||||
icon,
|
||||
color,
|
||||
isMobile,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const CreateApp = ({ isMobile, orgId, applications }: any) => {
|
||||
return (
|
||||
<PaddingWrapper>
|
||||
<ApplicationAddCardWrapper
|
||||
onClick={() => {
|
||||
if (
|
||||
Object.entries(creatingApplicationMap).length === 0 ||
|
||||
(creatingApplicationMap && !creatingApplicationMap[orgId])
|
||||
) {
|
||||
createNewApplication(
|
||||
getNextEntityName(
|
||||
"未命名应用 ",
|
||||
applications.map((el: any) => el.name),
|
||||
),
|
||||
orgId,
|
||||
isMobile,
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{creatingApplicationMap && creatingApplicationMap[orgId] ? (
|
||||
<Spinner size={IconSize.XXXL} />
|
||||
) : (
|
||||
<>
|
||||
<IconGroup>
|
||||
<AddTypeIcon
|
||||
className="t--create-app-popup"
|
||||
name={isMobile ? "mobile" : "desktop"}
|
||||
size={IconSize.LARGE}
|
||||
/>
|
||||
<AddIcon
|
||||
className="t--create-app-popup"
|
||||
name={"plus"}
|
||||
size={IconSize.LARGE}
|
||||
isMobile={isMobile}
|
||||
/>
|
||||
</IconGroup>
|
||||
<CreateNewLabel className="createnew" type={TextType.H4}>
|
||||
新建{isMobile ? "移动" : "桌面"}应用
|
||||
</CreateNewLabel>
|
||||
</>
|
||||
)}
|
||||
</ApplicationAddCardWrapper>
|
||||
</PaddingWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
let updatedOrgs;
|
||||
if (!isFetchingApplications) {
|
||||
updatedOrgs = userOrgs;
|
||||
|
|
@ -820,44 +893,17 @@ function ApplicationsSection(props: any) {
|
|||
PERMISSION_TYPE.CREATE_APPLICATION,
|
||||
) &&
|
||||
!isFetchingApplications && (
|
||||
<PaddingWrapper>
|
||||
<ApplicationAddCardWrapper
|
||||
onClick={() => {
|
||||
if (
|
||||
Object.entries(creatingApplicationMap).length === 0 ||
|
||||
(creatingApplicationMap &&
|
||||
!creatingApplicationMap[organization.id])
|
||||
) {
|
||||
createNewApplication(
|
||||
getNextEntityName(
|
||||
"未命名应用 ",
|
||||
applications.map((el: any) => el.name),
|
||||
),
|
||||
organization.id,
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{creatingApplicationMap &&
|
||||
creatingApplicationMap[organization.id] ? (
|
||||
<Spinner size={IconSize.XXXL} />
|
||||
) : (
|
||||
<>
|
||||
<Icon
|
||||
className="t--create-app-popup"
|
||||
name={"plus"}
|
||||
size={IconSize.LARGE}
|
||||
/>
|
||||
<CreateNewLabel
|
||||
className="createnew"
|
||||
type={TextType.H4}
|
||||
>
|
||||
新建应用
|
||||
</CreateNewLabel>
|
||||
</>
|
||||
)}
|
||||
</ApplicationAddCardWrapper>
|
||||
</PaddingWrapper>
|
||||
<>
|
||||
<CreateApp
|
||||
orgId={organization.id}
|
||||
applications={applications}
|
||||
/>
|
||||
<CreateApp
|
||||
orgId={organization.id}
|
||||
applications={applications}
|
||||
isMobile
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{applications.map((application: any) => {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -113,7 +113,9 @@ export const WidgetEntity = memo((props: WidgetEntityProps) => {
|
|||
* so we track the immediate modal parent for the widget
|
||||
*/
|
||||
const parentModalIdForChildren = useMemo(() => {
|
||||
return widgetType === "MODAL_WIDGET" ? widgetId : parentModalId;
|
||||
return widgetType === "MODAL_WIDGET" || widgetType === "TARO_POPUP_WIDGET"
|
||||
? widgetId
|
||||
: parentModalId;
|
||||
}, [widgetType, widgetId, parentModalId]);
|
||||
|
||||
if (UNREGISTERED_WIDGETS.indexOf(props.widgetType) > -1) return null;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,10 @@ export const useNavigateToWidget = () => {
|
|||
pageId: string,
|
||||
parentModalId?: string,
|
||||
) => {
|
||||
if (widgetType === WidgetTypes.MODAL_WIDGET) {
|
||||
if (
|
||||
widgetType === WidgetTypes.MODAL_WIDGET ||
|
||||
widgetType === WidgetTypes.TARO_POPUP_WIDGET
|
||||
) {
|
||||
dispatch(showModal(widgetId));
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,11 @@ const AppsmithLayouts: AppsmithLayoutConfigOption[] = [
|
|||
type: "TABLET",
|
||||
icon: "tablet",
|
||||
},
|
||||
{
|
||||
name: "手机宽度",
|
||||
type: "MOBILE",
|
||||
icon: "mobile",
|
||||
},
|
||||
// {
|
||||
// name: "手机宽度",
|
||||
// type: "MOBILE",
|
||||
// icon: "mobile",
|
||||
// },
|
||||
{
|
||||
name: "自适应宽度",
|
||||
type: "FLUID",
|
||||
|
|
@ -71,9 +71,14 @@ const LayoutControlWrapper = styled.div`
|
|||
}
|
||||
`;
|
||||
|
||||
const EmptyBlock = styled.div`
|
||||
height: 30px;
|
||||
`;
|
||||
|
||||
export function MainContainerLayoutControl() {
|
||||
const appId = useSelector(getCurrentApplicationId);
|
||||
const appLayout = useSelector(getCurrentApplicationLayout);
|
||||
const isMobile = appLayout?.type === "MOBILE_FLUID";
|
||||
const layoutOptions = AppsmithLayouts.map((each) => {
|
||||
return {
|
||||
...each,
|
||||
|
|
@ -89,8 +94,8 @@ export function MainContainerLayoutControl() {
|
|||
const selectedLayout = appLayout
|
||||
? layoutOptions.find((each) => each.type === appLayout.type)
|
||||
: layoutOptions[0];
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const updateAppLayout = (layoutConfig: AppLayoutConfig) => {
|
||||
const { type } = layoutConfig;
|
||||
dispatch(
|
||||
|
|
@ -101,6 +106,10 @@ export function MainContainerLayoutControl() {
|
|||
}),
|
||||
);
|
||||
};
|
||||
|
||||
if (isMobile) {
|
||||
return <EmptyBlock />;
|
||||
}
|
||||
return (
|
||||
<LayoutControlWrapper>
|
||||
<div className="layout-control t--layout-control-wrapper">
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ export const excludeList = [
|
|||
WidgetTypes.TABS_WIDGET,
|
||||
WidgetTypes.FORM_WIDGET,
|
||||
WidgetTypes.MODAL_WIDGET,
|
||||
WidgetTypes.TARO_POPUP_WIDGET,
|
||||
WidgetTypes.DIVIDER_WIDGET,
|
||||
WidgetTypes.FILE_PICKER_WIDGET,
|
||||
WidgetTypes.BUTTON_WIDGET,
|
||||
|
|
|
|||
|
|
@ -146,7 +146,8 @@ export type SupportedLayouts =
|
|||
| "TABLET_LARGE"
|
||||
| "TABLET"
|
||||
| "MOBILE"
|
||||
| "FLUID";
|
||||
| "FLUID"
|
||||
| "MOBILE_FLUID";
|
||||
export interface AppLayoutConfig {
|
||||
type: SupportedLayouts;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,19 @@ import { RateWidgetProps } from "widgets/RateWidget";
|
|||
import { IframeWidgetProps } from "widgets/IframeWidget";
|
||||
import { MenuButtonWidgetProps } from "widgets/MenuButtonWidget";
|
||||
import { FormilyWidgetProps } from "widgets/FormilyWidget";
|
||||
import { PickerWidgetProps } from "widgets/taro/PickerWidget";
|
||||
import { SwiperWidgetProps } from "widgets/taro/SwiperWidget";
|
||||
import { GridWidgetProps } from "widgets/taro/GridWidget";
|
||||
import { MTextWidgetProps } from "widgets/taro/TextWidget";
|
||||
import { MListWidgetProps } from "widgets/taro/ListWidget";
|
||||
import { MPopupWidgetProps } from "widgets/taro/PopupWidget";
|
||||
import { MImageWidgetProps } from "widgets/taro/ImageWidget";
|
||||
import { MButtonWidgetProps } from "widgets/taro/ButtonWidget";
|
||||
import { MCellWidgetProps } from "widgets/taro/CellWidget";
|
||||
import { MHtmlWidgetProps } from "widgets/taro/HtmlWidget";
|
||||
import { MSimpleFormWidgetProps } from "widgets/taro/SimpleFormWidget";
|
||||
import { MKVWidgetProps } from "widgets/taro/KVWidget";
|
||||
import { MTabsWidgetProps } from "widgets/taro/TabsWidget";
|
||||
|
||||
const initialState: WidgetConfigReducerState = WidgetConfigResponse;
|
||||
|
||||
|
|
@ -94,6 +107,20 @@ export interface WidgetConfigReducerState {
|
|||
IFRAME_WIDGET: Partial<IframeWidgetProps> & WidgetConfigProps;
|
||||
MENU_BUTTON_WIDGET: Partial<MenuButtonWidgetProps> & WidgetConfigProps;
|
||||
FORMILY_WIDGET: Partial<FormilyWidgetProps> & WidgetConfigProps;
|
||||
TARO_PICKER_WIDGET: Partial<PickerWidgetProps> & WidgetConfigProps;
|
||||
TARO_SWIPER_WIDGET: Partial<SwiperWidgetProps> & WidgetConfigProps;
|
||||
TARO_GRID_WIDGET: Partial<GridWidgetProps> & WidgetConfigProps;
|
||||
TARO_TEXT_WIDGET: Partial<MTextWidgetProps> & WidgetConfigProps;
|
||||
TARO_LIST_WIDGET: Partial<MListWidgetProps> & WidgetConfigProps;
|
||||
TARO_POPUP_WIDGET: Partial<MPopupWidgetProps> & WidgetConfigProps;
|
||||
TARO_IMAGE_WIDGET: Partial<MImageWidgetProps> & WidgetConfigProps;
|
||||
TARO_BUTTON_WIDGET: Partial<MButtonWidgetProps> & WidgetConfigProps;
|
||||
TARO_CELL_WIDGET: Partial<MCellWidgetProps> & WidgetConfigProps;
|
||||
TARO_HTML_WIDGET: Partial<MHtmlWidgetProps> & WidgetConfigProps;
|
||||
TARO_SIMPLE_FORM_WIDGET: Partial<MSimpleFormWidgetProps> &
|
||||
WidgetConfigProps;
|
||||
TARO_KV_WIDGET: Partial<MKVWidgetProps> & WidgetConfigProps;
|
||||
TARO_TABS_WIDGET: Partial<MTabsWidgetProps> & WidgetConfigProps;
|
||||
};
|
||||
configVersion: number;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ import { deleteRecentAppEntities } from "utils/storage";
|
|||
import { reconnectWebsocket as reconnectWebsocketAction } from "actions/websocketActions";
|
||||
import { getCurrentOrg } from "selectors/organizationSelectors";
|
||||
import { Org } from "constants/orgConstants";
|
||||
import { AppLayoutConfig } from "reducers/entityReducers/pageListReducer";
|
||||
|
||||
const getDefaultPageId = (
|
||||
pages?: ApplicationPagePayload[],
|
||||
|
|
@ -392,12 +393,20 @@ export function* createApplicationSaga(
|
|||
applicationName: string;
|
||||
icon: AppIconName;
|
||||
color: AppColorCode;
|
||||
isMobile: boolean;
|
||||
orgId: string;
|
||||
resolve: any;
|
||||
reject: any;
|
||||
}>,
|
||||
) {
|
||||
const { applicationName, color, icon, orgId, reject } = action.payload;
|
||||
const {
|
||||
applicationName,
|
||||
color,
|
||||
icon,
|
||||
orgId,
|
||||
reject,
|
||||
isMobile,
|
||||
} = action.payload;
|
||||
try {
|
||||
const userOrgs = yield select(getUserApplicationsOrgsList);
|
||||
const existingOrgs = userOrgs.filter(
|
||||
|
|
@ -423,11 +432,16 @@ export function* createApplicationSaga(
|
|||
} else {
|
||||
yield put(resetCurrentApplication());
|
||||
|
||||
const layout: AppLayoutConfig = {
|
||||
type: isMobile ? "MOBILE_FLUID" : "DESKTOP",
|
||||
};
|
||||
const request: CreateApplicationRequest = {
|
||||
name: applicationName,
|
||||
icon: icon,
|
||||
color: color,
|
||||
orgId,
|
||||
unpublishedAppLayout: layout,
|
||||
publishedAppLayout: layout,
|
||||
};
|
||||
const response: CreateApplicationResponse = yield call(
|
||||
ApplicationApi.createApplication,
|
||||
|
|
@ -441,6 +455,7 @@ export function* createApplicationSaga(
|
|||
};
|
||||
AnalyticsUtil.logEvent("CREATE_APP", {
|
||||
appName: application.name,
|
||||
isMobile,
|
||||
});
|
||||
// This sets ui.pageWidgets = {} to ensure that
|
||||
// widgets are cleaned up from state before
|
||||
|
|
@ -458,6 +473,7 @@ export function* createApplicationSaga(
|
|||
const pageURL = getGenerateTemplateURL(
|
||||
application.id,
|
||||
application.defaultPageId,
|
||||
isMobile,
|
||||
);
|
||||
history.push(pageURL);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import {
|
|||
getWidgetsMeta,
|
||||
getWidgetIdsByType,
|
||||
getWidgetMetaProps,
|
||||
getWidgetIdsByTypes,
|
||||
} from "sagas/selectors";
|
||||
import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
|
||||
import { updateWidgetMetaProperty } from "actions/metaActions";
|
||||
|
|
@ -34,21 +35,23 @@ import { focusWidget } from "actions/widgetActions";
|
|||
import log from "loglevel";
|
||||
import { flatten } from "lodash";
|
||||
import AppsmithConsole from "utils/AppsmithConsole";
|
||||
import { isMobileLayout } from "selectors/editorSelectors";
|
||||
|
||||
export function* createModalSaga(action: ReduxAction<{ modalName: string }>) {
|
||||
try {
|
||||
const isMobile: boolean = yield select(isMobileLayout);
|
||||
const modalWidgetId = generateReactKey();
|
||||
const props: WidgetAddChild = {
|
||||
widgetId: MAIN_CONTAINER_WIDGET_ID,
|
||||
widgetName: action.payload.modalName,
|
||||
type: WidgetTypes.MODAL_WIDGET,
|
||||
type: isMobile ? WidgetTypes.TARO_POPUP_WIDGET : WidgetTypes.MODAL_WIDGET,
|
||||
newWidgetId: modalWidgetId,
|
||||
parentRowSpace: 1,
|
||||
parentRowSpace: isMobile ? 10 : 1,
|
||||
parentColumnSpace: 1,
|
||||
leftColumn: 0,
|
||||
topRow: 0,
|
||||
columns: 0,
|
||||
rows: 0,
|
||||
rows: isMobile ? 40 : 0,
|
||||
tabId: "",
|
||||
};
|
||||
yield put({
|
||||
|
|
@ -98,7 +101,10 @@ export function* showModalByNameSaga(
|
|||
export function* showIfModalSaga(
|
||||
action: ReduxAction<{ widgetId: string; type: string }>,
|
||||
) {
|
||||
if (action.payload.type === "MODAL_WIDGET") {
|
||||
if (
|
||||
action.payload.type === "MODAL_WIDGET" ||
|
||||
action.payload.type === WidgetTypes.TARO_POPUP_WIDGET
|
||||
) {
|
||||
yield put({
|
||||
type: ReduxActionTypes.SHOW_MODAL,
|
||||
payload: { modalId: action.payload.widgetId },
|
||||
|
|
@ -160,10 +166,10 @@ export function* closeModalSaga(
|
|||
const metaProps: Record<string, any> = yield select(getWidgetsMeta);
|
||||
|
||||
// Get widgetIds of all widgets of type MODAL_WIDGET
|
||||
const modalWidgetIds: string[] = yield select(
|
||||
getWidgetIdsByType,
|
||||
const modalWidgetIds: string[] = yield select(getWidgetIdsByTypes, [
|
||||
WidgetTypes.MODAL_WIDGET,
|
||||
);
|
||||
WidgetTypes.TARO_POPUP_WIDGET,
|
||||
]);
|
||||
|
||||
// Loop through all modal widgetIds
|
||||
modalWidgetIds.forEach((widgetId: string) => {
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ import {
|
|||
getCurrentLayoutId,
|
||||
getCurrentPageId,
|
||||
getCurrentPageName,
|
||||
isMobileLayout,
|
||||
} from "selectors/editorSelectors";
|
||||
import {
|
||||
fetchActionsForPage,
|
||||
|
|
@ -486,6 +487,7 @@ export function* createPageSaga(
|
|||
const request: CreatePageRequest = createPageAction.payload;
|
||||
const response: FetchPageResponse = yield call(PageApi.createPage, request);
|
||||
const isValidResponse: boolean = yield validateResponse(response);
|
||||
const isMobile: boolean = yield select(isMobileLayout);
|
||||
if (isValidResponse) {
|
||||
yield put({
|
||||
type: ReduxActionTypes.CREATE_PAGE_SUCCESS,
|
||||
|
|
@ -508,6 +510,7 @@ export function* createPageSaga(
|
|||
getGenerateTemplateURL(
|
||||
createPageAction.payload.applicationId,
|
||||
response.data.id,
|
||||
isMobile,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,12 @@ export const getWidgetIdsByType = (state: AppState, type: WidgetType) => {
|
|||
.map((widget: FlattenedWidgetProps) => widget.widgetId);
|
||||
};
|
||||
|
||||
export const getWidgetIdsByTypes = (state: AppState, types: WidgetType[]) => {
|
||||
return Object.values(state.entities.canvasWidgets)
|
||||
.filter((widget: FlattenedWidgetProps) => _.includes(types, widget.type))
|
||||
.map((widget: FlattenedWidgetProps) => widget.widgetId);
|
||||
};
|
||||
|
||||
export const getWidgetOptionsTree = createSelector(getWidgets, (widgets) =>
|
||||
Object.values(widgets)
|
||||
.filter((w) => w.type !== "CANVAS_WIDGET" && w.type !== "BUTTON_WIDGET")
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import _ from "lodash";
|
|||
import { ContainerWidgetProps } from "widgets/ContainerWidget";
|
||||
import { DataTreeWidget, ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
|
||||
import { getActions } from "selectors/entitiesSelector";
|
||||
import { AppLayoutConfig } from "reducers/entityReducers/pageListReducer";
|
||||
|
||||
import { getCanvasWidgets } from "./entitiesSelector";
|
||||
import { WidgetTypes } from "../constants/WidgetConstants";
|
||||
|
|
@ -109,6 +110,9 @@ export const getViewModePageList = createSelector(
|
|||
export const getCurrentApplicationLayout = (state: AppState) =>
|
||||
state.ui.applications.currentApplication?.appLayout;
|
||||
|
||||
export const isMobileLayout = (state: AppState) =>
|
||||
state.ui.applications.currentApplication?.appLayout?.type === "MOBILE_FLUID";
|
||||
|
||||
export const getCurrentPageName = createSelector(
|
||||
getPageListState,
|
||||
(pageList: PageListReduxState) =>
|
||||
|
|
@ -119,11 +123,15 @@ export const getCurrentPageName = createSelector(
|
|||
export const getWidgetCards = createSelector(
|
||||
getWidgetSideBar,
|
||||
getWidgetConfigs,
|
||||
isMobileLayout,
|
||||
(
|
||||
widgetCards: WidgetSidebarReduxState,
|
||||
widgetConfigs: WidgetConfigReducerState,
|
||||
isMobile: boolean,
|
||||
) => {
|
||||
const cards = widgetCards.cards;
|
||||
const cards = widgetCards.cards.filter((c) =>
|
||||
isMobile ? c.isMobile : !c.isMobile,
|
||||
);
|
||||
return cards
|
||||
.map((widget: WidgetCardProps) => {
|
||||
const {
|
||||
|
|
|
|||
|
|
@ -367,7 +367,10 @@ const getParentModalId = (widget: any, pageWidgets: Record<string, any>) => {
|
|||
let { parentId } = widget;
|
||||
let parentWidget = pageWidgets[parentId];
|
||||
while (parentId && parentId !== MAIN_CONTAINER_WIDGET_ID) {
|
||||
if (parentWidget?.type === "MODAL_WIDGET") {
|
||||
if (
|
||||
parentWidget?.type === "MODAL_WIDGET" ||
|
||||
parentWidget?.type === "TARO_POPUP_WIDGET"
|
||||
) {
|
||||
parentModalId = parentId;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReduc
|
|||
import { WidgetTypes } from "constants/WidgetConstants";
|
||||
import { getExistingWidgetNames, getWidgetNamePrefix } from "sagas/selectors";
|
||||
import { getNextEntityName } from "utils/AppsmithUtils";
|
||||
import { isMobileLayout } from "selectors/editorSelectors";
|
||||
|
||||
const getCanvasWidgets = (state: AppState) => state.entities.canvasWidgets;
|
||||
export const getModalDropdownList = createSelector(
|
||||
|
|
@ -11,7 +12,8 @@ export const getModalDropdownList = createSelector(
|
|||
(widgets) => {
|
||||
const modalWidgets = Object.values(widgets).filter(
|
||||
(widget: FlattenedWidgetProps) =>
|
||||
widget.type === WidgetTypes.MODAL_WIDGET,
|
||||
widget.type === WidgetTypes.MODAL_WIDGET ||
|
||||
widget.type === WidgetTypes.TARO_POPUP_WIDGET,
|
||||
);
|
||||
if (modalWidgets.length === 0) return undefined;
|
||||
|
||||
|
|
@ -23,8 +25,12 @@ export const getModalDropdownList = createSelector(
|
|||
},
|
||||
);
|
||||
|
||||
const getModalNamePrefix = (state: AppState) =>
|
||||
getWidgetNamePrefix(state, WidgetTypes.MODAL_WIDGET);
|
||||
const getModalNamePrefix = (state: AppState) => {
|
||||
const type = isMobileLayout(state)
|
||||
? WidgetTypes.TARO_POPUP_WIDGET
|
||||
: WidgetTypes.MODAL_WIDGET;
|
||||
return getWidgetNamePrefix(state, type);
|
||||
};
|
||||
|
||||
export const getNextModalName = createSelector(
|
||||
getExistingWidgetNames,
|
||||
|
|
|
|||
|
|
@ -1267,7 +1267,11 @@ export const generateWidgetProps = (
|
|||
|
||||
const others = {};
|
||||
const props: ContainerWidgetProps<WidgetProps> = {
|
||||
isVisible: WidgetTypes.MODAL_WIDGET === type ? undefined : true,
|
||||
isVisible:
|
||||
WidgetTypes.MODAL_WIDGET === type ||
|
||||
WidgetTypes.TARO_POPUP_WIDGET === type
|
||||
? undefined
|
||||
: true,
|
||||
...widgetConfig,
|
||||
type,
|
||||
widgetName,
|
||||
|
|
|
|||
|
|
@ -127,6 +127,58 @@ import FormilyWidget, {
|
|||
FormilyWidgetProps,
|
||||
ProfiledFormilyWidget,
|
||||
} from "widgets/FormilyWidget";
|
||||
import PickerWidget, {
|
||||
PickerWidgetProps,
|
||||
ProfiledPickerWidget,
|
||||
} from "widgets/taro/PickerWidget";
|
||||
import SwiperWidget, {
|
||||
SwiperWidgetProps,
|
||||
ProfiledSwiperWidget,
|
||||
} from "widgets/taro/SwiperWidget";
|
||||
import GridWidget, {
|
||||
GridWidgetProps,
|
||||
ProfiledGridWidget,
|
||||
} from "widgets/taro/GridWidget";
|
||||
import MTextWidget, {
|
||||
MTextWidgetProps,
|
||||
MProfiledTextWidget,
|
||||
} from "widgets/taro/TextWidget";
|
||||
import MListWidget, {
|
||||
MListWidgetProps,
|
||||
MProfiledListWidget,
|
||||
} from "widgets/taro/ListWidget";
|
||||
import MPopupWidget, {
|
||||
MPopupWidgetProps,
|
||||
MProfiledPopupWidget,
|
||||
} from "widgets/taro/PopupWidget";
|
||||
import MImageWidget, {
|
||||
MImageWidgetProps,
|
||||
MProfiledImageWidget,
|
||||
} from "widgets/taro/ImageWidget";
|
||||
import MButtonWidget, {
|
||||
MButtonWidgetProps,
|
||||
MProfiledButtonWidget,
|
||||
} from "widgets/taro/ButtonWidget";
|
||||
import MCellWidget, {
|
||||
MCellWidgetProps,
|
||||
MProfiledCellWidget,
|
||||
} from "widgets/taro/CellWidget";
|
||||
import MHtmlWidget, {
|
||||
MHtmlWidgetProps,
|
||||
MProfiledHtmlWidget,
|
||||
} from "widgets/taro/HtmlWidget";
|
||||
import MSimpleFormWidget, {
|
||||
MSimpleFormWidgetProps,
|
||||
MProfiledSimpleFormWidget,
|
||||
} from "widgets/taro/SimpleFormWidget";
|
||||
import MKVWidget, {
|
||||
MKVWidgetProps,
|
||||
MProfiledKVWidget,
|
||||
} from "widgets/taro/KVWidget";
|
||||
import MTabsWidget, {
|
||||
MTabsWidgetProps,
|
||||
MProfiledTabsWidget,
|
||||
} from "widgets/taro/TabsWidget";
|
||||
|
||||
export default class WidgetBuilderRegistry {
|
||||
static registerWidgetBuilders() {
|
||||
|
|
@ -555,5 +607,174 @@ export default class WidgetBuilderRegistry {
|
|||
FormilyWidget.getMetaPropertiesMap(),
|
||||
FormilyWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_PICKER_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: PickerWidgetProps): JSX.Element {
|
||||
return <ProfiledPickerWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
PickerWidget.getDerivedPropertiesMap(),
|
||||
PickerWidget.getDefaultPropertiesMap(),
|
||||
PickerWidget.getMetaPropertiesMap(),
|
||||
PickerWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_SWIPER_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: SwiperWidgetProps): JSX.Element {
|
||||
return <ProfiledSwiperWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
SwiperWidget.getDerivedPropertiesMap(),
|
||||
SwiperWidget.getDefaultPropertiesMap(),
|
||||
SwiperWidget.getMetaPropertiesMap(),
|
||||
SwiperWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_GRID_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: GridWidgetProps): JSX.Element {
|
||||
return <ProfiledGridWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
GridWidget.getDerivedPropertiesMap(),
|
||||
GridWidget.getDefaultPropertiesMap(),
|
||||
GridWidget.getMetaPropertiesMap(),
|
||||
GridWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_TEXT_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: MTextWidgetProps): JSX.Element {
|
||||
return <MProfiledTextWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
MTextWidget.getDerivedPropertiesMap(),
|
||||
MTextWidget.getDefaultPropertiesMap(),
|
||||
MTextWidget.getMetaPropertiesMap(),
|
||||
MTextWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_LIST_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: MListWidgetProps): JSX.Element {
|
||||
return <MProfiledListWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
MListWidget.getDerivedPropertiesMap(),
|
||||
MListWidget.getDefaultPropertiesMap(),
|
||||
MListWidget.getMetaPropertiesMap(),
|
||||
MListWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_POPUP_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: MPopupWidgetProps): JSX.Element {
|
||||
return <MProfiledPopupWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
MPopupWidget.getDerivedPropertiesMap(),
|
||||
MPopupWidget.getDefaultPropertiesMap(),
|
||||
MPopupWidget.getMetaPropertiesMap(),
|
||||
MPopupWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_IMAGE_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: MImageWidgetProps): JSX.Element {
|
||||
return <MProfiledImageWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
MImageWidget.getDerivedPropertiesMap(),
|
||||
MImageWidget.getDefaultPropertiesMap(),
|
||||
MImageWidget.getMetaPropertiesMap(),
|
||||
MImageWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_BUTTON_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: MButtonWidgetProps): JSX.Element {
|
||||
return <MProfiledButtonWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
MButtonWidget.getDerivedPropertiesMap(),
|
||||
MButtonWidget.getDefaultPropertiesMap(),
|
||||
MButtonWidget.getMetaPropertiesMap(),
|
||||
MButtonWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_CELL_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: MCellWidgetProps): JSX.Element {
|
||||
return <MProfiledCellWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
MCellWidget.getDerivedPropertiesMap(),
|
||||
MCellWidget.getDefaultPropertiesMap(),
|
||||
MCellWidget.getMetaPropertiesMap(),
|
||||
MCellWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_HTML_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: MHtmlWidgetProps): JSX.Element {
|
||||
return <MProfiledHtmlWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
MHtmlWidget.getDerivedPropertiesMap(),
|
||||
MHtmlWidget.getDefaultPropertiesMap(),
|
||||
MHtmlWidget.getMetaPropertiesMap(),
|
||||
MHtmlWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_SIMPLE_FORM_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: MSimpleFormWidgetProps): JSX.Element {
|
||||
return <MProfiledSimpleFormWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
MSimpleFormWidget.getDerivedPropertiesMap(),
|
||||
MSimpleFormWidget.getDefaultPropertiesMap(),
|
||||
MSimpleFormWidget.getMetaPropertiesMap(),
|
||||
MSimpleFormWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_KV_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: MKVWidgetProps): JSX.Element {
|
||||
return <MProfiledKVWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
MKVWidget.getDerivedPropertiesMap(),
|
||||
MKVWidget.getDefaultPropertiesMap(),
|
||||
MKVWidget.getMetaPropertiesMap(),
|
||||
MKVWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
|
||||
WidgetFactory.registerWidgetBuilder(
|
||||
WidgetTypes.TARO_TABS_WIDGET,
|
||||
{
|
||||
buildWidget(widgetData: MTabsWidgetProps): JSX.Element {
|
||||
return <MProfiledTabsWidget {...widgetData} />;
|
||||
},
|
||||
},
|
||||
MTabsWidget.getDerivedPropertiesMap(),
|
||||
MTabsWidget.getDefaultPropertiesMap(),
|
||||
MTabsWidget.getMetaPropertiesMap(),
|
||||
MTabsWidget.getPropertyPaneConfig(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -293,6 +293,59 @@ export const entityDefinitions = {
|
|||
isVisible: isVisible,
|
||||
formData: "any",
|
||||
},
|
||||
TARO_PICKER_WIDGET: {
|
||||
"!doc": "Taro 选择器",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
isVisible: isVisible,
|
||||
},
|
||||
TARO_SWIPER_WIDGET: {
|
||||
"!doc": "轮播",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
TARO_GRID_WIDGET: {
|
||||
"!doc": "网格内容",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
TARO_TEXT_WIDGET: {
|
||||
"!doc": "文本",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
TARO_LIST_WIDGET: {
|
||||
"!doc": "列表",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
TARO_POPUP_WIDGET: {
|
||||
"!doc": "底部弹窗",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
TARO_IMAGE_WIDGET: {
|
||||
"!doc": "图片",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
TARO_BUTTON_WIDGET: {
|
||||
"!doc": "按钮",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
TARO_CELL_WIDGET: {
|
||||
"!doc": "单元格",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
TARO_HTML_WIDGET: {
|
||||
"!doc": "富文本",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
TARO_SIMPLE_FORM_WIDGET: {
|
||||
"!doc": "快速表单",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
TARO_KV_WIDGET: {
|
||||
"!doc": "键值对",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
TARO_TABS_WIDGET: {
|
||||
"!doc": "标签页",
|
||||
"!url": "https://docs.appsmith.com/widget-reference/input",
|
||||
},
|
||||
};
|
||||
|
||||
export const GLOBAL_DEFS = {
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ export const dataTreeTypeDefCreator = (
|
|||
subType: "ACTION",
|
||||
});
|
||||
} else if (isAppsmithEntity(entity)) {
|
||||
def.appsmith = generateTypeDef(_.omit(entity, "ENTITY_TYPE"));
|
||||
entityMap.set("appsmith", {
|
||||
def.global = generateTypeDef(_.omit(entity, "ENTITY_TYPE"));
|
||||
entityMap.set("global", {
|
||||
type: ENTITY_TYPE.APPSMITH,
|
||||
subType: ENTITY_TYPE.APPSMITH,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -492,6 +492,7 @@ export interface WidgetCardProps {
|
|||
key?: string;
|
||||
widgetCardName: string;
|
||||
isBeta?: boolean;
|
||||
isMobile?: boolean;
|
||||
}
|
||||
|
||||
export const WidgetOperations = {
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ class FormilyWidget extends BaseWidget<FormilyWidgetProps, WidgetState> {
|
|||
};
|
||||
|
||||
getPageView() {
|
||||
console.log("----widget--props--", this.props);
|
||||
const {
|
||||
title,
|
||||
formType,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,136 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import ButtonComponent from "components/designSystems/taro/ButtonComponent";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import withMeta, { WithMeta } from "../MetaHOC";
|
||||
|
||||
class MButtonWidget extends BaseWidget<MButtonWidgetProps, ButtonWidgetState> {
|
||||
state = {
|
||||
isLoading: false,
|
||||
};
|
||||
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
propertyName: "text",
|
||||
label: "按钮文字",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "输入按钮文字",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "color",
|
||||
label: "按钮颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "rounded",
|
||||
label: "是否圆角",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
label: "是否可见",
|
||||
helpText: "控制按钮显示/隐藏",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
label: "禁用",
|
||||
controlType: "SWITCH",
|
||||
helpText: "禁止按钮交互",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "动作",
|
||||
children: [
|
||||
{
|
||||
helpText: "点击按钮时触发动作",
|
||||
propertyName: "onClick",
|
||||
label: "onClick",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
onButtonClick = () => {
|
||||
if (this.props.onClick) {
|
||||
this.setState({
|
||||
isLoading: true,
|
||||
});
|
||||
super.executeAction({
|
||||
triggerPropertyName: "onClick",
|
||||
dynamicString: this.props.onClick,
|
||||
event: {
|
||||
type: EventType.ON_CLICK,
|
||||
callback: this.handleActionComplete,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleActionComplete = () => {
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
});
|
||||
};
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<ButtonComponent
|
||||
isDisabled={this.props.isDisabled}
|
||||
isLoading={this.props.isLoading || this.state.isLoading}
|
||||
onClick={!this.props.isDisabled ? this.onButtonClick : undefined}
|
||||
text={this.props.text}
|
||||
color={this.props.color}
|
||||
rounded={this.props.rounded}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return "TARO_BUTTON_WIDGET";
|
||||
}
|
||||
}
|
||||
|
||||
export interface MButtonWidgetProps extends WidgetProps, WithMeta {
|
||||
text?: string;
|
||||
color?: string;
|
||||
onClick?: string;
|
||||
rounded?: boolean;
|
||||
isDisabled?: boolean;
|
||||
isVisible?: boolean;
|
||||
}
|
||||
|
||||
interface ButtonWidgetState extends WidgetState {
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export default MButtonWidget;
|
||||
export const MProfiledButtonWidget = withMeta(MButtonWidget);
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import ButtonComponent from "components/designSystems/taro/ButtonComponent";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import withMeta, { WithMeta } from "../MetaHOC";
|
||||
|
||||
class MCellWidget extends BaseWidget<MCellWidgetProps, CellWidgetState> {
|
||||
state = {
|
||||
isLoading: false,
|
||||
};
|
||||
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
propertyName: "text",
|
||||
label: "按钮文字",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "输入按钮文字",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "color",
|
||||
label: "按钮颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "rounded",
|
||||
label: "是否圆角",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
label: "是否可见",
|
||||
helpText: "控制按钮显示/隐藏",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
label: "禁用",
|
||||
controlType: "SWITCH",
|
||||
helpText: "禁止按钮交互",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "动作",
|
||||
children: [
|
||||
{
|
||||
helpText: "点击按钮时触发动作",
|
||||
propertyName: "onClick",
|
||||
label: "onClick",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
onButtonClick = () => {
|
||||
if (this.props.onClick) {
|
||||
this.setState({
|
||||
isLoading: true,
|
||||
});
|
||||
super.executeAction({
|
||||
triggerPropertyName: "onClick",
|
||||
dynamicString: this.props.onClick,
|
||||
event: {
|
||||
type: EventType.ON_CLICK,
|
||||
callback: this.handleActionComplete,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleActionComplete = () => {
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
});
|
||||
};
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<ButtonComponent
|
||||
isDisabled={this.props.isDisabled}
|
||||
isLoading={this.props.isLoading || this.state.isLoading}
|
||||
onClick={!this.props.isDisabled ? this.onButtonClick : undefined}
|
||||
text={this.props.text}
|
||||
color={this.props.color}
|
||||
rounded={this.props.rounded}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return "TARO_BUTTON_WIDGET";
|
||||
}
|
||||
}
|
||||
|
||||
export interface MCellWidgetProps extends WidgetProps, WithMeta {
|
||||
text?: string;
|
||||
color?: string;
|
||||
onClick?: string;
|
||||
rounded?: boolean;
|
||||
isDisabled?: boolean;
|
||||
isVisible?: boolean;
|
||||
}
|
||||
|
||||
interface CellWidgetState extends WidgetState {
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export default MCellWidget;
|
||||
export const MProfiledCellWidget = withMeta(MCellWidget);
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { WidgetType, WidgetTypes } from "constants/WidgetConstants";
|
||||
import GridComponent, {
|
||||
GridComponentProps,
|
||||
} from "components/designSystems/taro/GridComponent";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory";
|
||||
|
||||
class GridWidget extends BaseWidget<GridWidgetProps, WidgetState> {
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
helpText: "数组,通过 {{}} 进行数据绑定",
|
||||
propertyName: "list",
|
||||
label: "数据",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: '[{ "url": "", title: "" }]',
|
||||
inputType: "ARRAY",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: {
|
||||
type: ValidationTypes.OBJECT_ARRAY,
|
||||
params: {
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
evaluationSubstitutionType:
|
||||
EvaluationSubstitutionType.SMART_SUBSTITUTE,
|
||||
},
|
||||
{
|
||||
propertyName: "gridType",
|
||||
label: "内容类型",
|
||||
controlType: "DROP_DOWN",
|
||||
options: [
|
||||
{
|
||||
label: "图片+标题",
|
||||
value: "I_N",
|
||||
},
|
||||
{
|
||||
label: "图片+标题+描述",
|
||||
value: "I_N_D",
|
||||
},
|
||||
{
|
||||
label: "图片+标题+描述+按钮",
|
||||
value: "I_N_D_B",
|
||||
},
|
||||
],
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "urlKey",
|
||||
label: "图片字段",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "titleKey",
|
||||
label: "标题字段",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "descriptionKey",
|
||||
label: "描述字段",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
dependencies: ["gridType"],
|
||||
hidden: (props: GridWidgetProps) => {
|
||||
return props.gridType === "I_N";
|
||||
},
|
||||
},
|
||||
{
|
||||
propertyName: "asPrice",
|
||||
label: "描述是价格",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
dependencies: ["gridType"],
|
||||
hidden: (props: GridWidgetProps) => {
|
||||
return props.gridType === "I_N";
|
||||
},
|
||||
},
|
||||
{
|
||||
propertyName: "priceUnit",
|
||||
label: "价格单位符号",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
dependencies: ["gridType", "asPrice"],
|
||||
hidden: (props: GridWidgetProps) => {
|
||||
return props.gridType === "I_N" || !props.asPrice;
|
||||
},
|
||||
},
|
||||
{
|
||||
propertyName: "buttonText",
|
||||
label: "按钮文本",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
dependencies: ["gridType"],
|
||||
hidden: (props: GridWidgetProps) => {
|
||||
return props.gridType !== "I_N_D_B";
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "样式",
|
||||
children: [
|
||||
{
|
||||
propertyName: "height",
|
||||
label: "图片高度",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "cols",
|
||||
label: "列数",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "网格显示多少列",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: {
|
||||
type: ValidationTypes.NUMBER,
|
||||
params: { min: 2, default: 4 },
|
||||
},
|
||||
},
|
||||
{
|
||||
propertyName: "gutter",
|
||||
label: "网格间距",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "bordered",
|
||||
label: "是否显示边框",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "titleColor",
|
||||
label: "标题颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "descriptionColor",
|
||||
label: "描述颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
dependencies: ["gridType"],
|
||||
hidden: (props: GridWidgetProps) => {
|
||||
return props.gridType === "I_N";
|
||||
},
|
||||
},
|
||||
{
|
||||
propertyName: "buttonColor",
|
||||
label: "按钮颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
dependencies: ["gridType"],
|
||||
hidden: (props: GridWidgetProps) => {
|
||||
return props.gridType !== "I_N_D_B";
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
const {
|
||||
list,
|
||||
gridType,
|
||||
urlKey,
|
||||
titleKey,
|
||||
descriptionKey,
|
||||
asPrice,
|
||||
priceUnit,
|
||||
buttonText,
|
||||
height,
|
||||
cols,
|
||||
gutter,
|
||||
bordered,
|
||||
titleColor,
|
||||
descriptionColor,
|
||||
buttonColor,
|
||||
} = this.props;
|
||||
return (
|
||||
<GridComponent
|
||||
{...{
|
||||
list,
|
||||
gridType,
|
||||
urlKey,
|
||||
titleKey,
|
||||
descriptionKey,
|
||||
asPrice,
|
||||
priceUnit,
|
||||
buttonText,
|
||||
height,
|
||||
cols,
|
||||
gutter,
|
||||
bordered,
|
||||
titleColor,
|
||||
descriptionColor,
|
||||
buttonColor,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return WidgetTypes.TARO_GRID_WIDGET;
|
||||
}
|
||||
}
|
||||
|
||||
export interface GridWidgetProps extends WidgetProps, GridComponentProps {}
|
||||
|
||||
export default GridWidget;
|
||||
export const ProfiledGridWidget = GridWidget;
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { ScrollView, RichText } from "@tarojs/components";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import styled from "styled-components";
|
||||
|
||||
const Container = styled(ScrollView)`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
& img {
|
||||
width: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
class MHtmlWidget extends BaseWidget<MHtmlWidgetProps, WidgetState> {
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
propertyName: "content",
|
||||
label: "HTML内容",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "输入HTML格式内容",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
const { content } = this.props;
|
||||
return (
|
||||
<Container scrollY>
|
||||
<RichText style={{ fontSize: 0 }} nodes={content} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return "TARO_HTML_WIDGET";
|
||||
}
|
||||
}
|
||||
|
||||
export interface MHtmlWidgetProps extends WidgetProps {
|
||||
content: string;
|
||||
}
|
||||
|
||||
export default MHtmlWidget;
|
||||
export const MProfiledHtmlWidget = MHtmlWidget;
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
import * as React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { WidgetType, RenderModes } from "constants/WidgetConstants";
|
||||
import ImageComponent from "components/designSystems/taro/ImageComponent";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
|
||||
class MImageWidget extends BaseWidget<MImageWidgetProps, WidgetState> {
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
propertyName: "src",
|
||||
label: "图片地址",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "输入图片 URL",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.IMAGE_URL },
|
||||
},
|
||||
{
|
||||
helpText: "设置图片填充父容器的方式",
|
||||
propertyName: "mode",
|
||||
label: "图片填充方式",
|
||||
controlType: "DROP_DOWN",
|
||||
defaultValue: "aspectFill",
|
||||
options: [
|
||||
{
|
||||
label: "封面模式,保持原始比例",
|
||||
value: "aspectFill",
|
||||
},
|
||||
{
|
||||
label: "填充模式,不保持原始比例",
|
||||
value: "scaleToFill",
|
||||
},
|
||||
{
|
||||
label: "包含模式,保持原始比例",
|
||||
value: "aspectFit",
|
||||
},
|
||||
],
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "isCircle",
|
||||
label: "显示为圆形",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "radius",
|
||||
label: "圆角大小(默认单位 px)",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
dependencies: ["isCircle"],
|
||||
hidden: (props: MImageWidgetProps) => {
|
||||
return !!props.isCircle;
|
||||
},
|
||||
},
|
||||
{
|
||||
helpText: "控制组件显示/隐藏",
|
||||
propertyName: "isVisible",
|
||||
label: "是否可见",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "动作",
|
||||
children: [
|
||||
{
|
||||
helpText: "当用户点击图片时触发",
|
||||
propertyName: "onClick",
|
||||
label: "onClick",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
const { src, onClick, mode, isCircle, radius } = this.props;
|
||||
return (
|
||||
<ImageComponent
|
||||
imageUrl={src}
|
||||
onClick={onClick ? this.onImageClick : undefined}
|
||||
mode={mode}
|
||||
isCircle={isCircle}
|
||||
radius={radius}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
onImageClick = () => {
|
||||
if (this.props.onClick) {
|
||||
super.executeAction({
|
||||
triggerPropertyName: "onClick",
|
||||
dynamicString: this.props.onClick,
|
||||
event: {
|
||||
type: EventType.ON_CLICK,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return "TARO_IMAGE_WIDGET";
|
||||
}
|
||||
}
|
||||
|
||||
export type ImageFillMode = "aspectFill" | "scaleToFill" | "aspectFit";
|
||||
|
||||
export interface MImageWidgetProps extends WidgetProps {
|
||||
src: string;
|
||||
mode: ImageFillMode;
|
||||
isCircle?: boolean;
|
||||
radius?: string;
|
||||
onClick?: string;
|
||||
}
|
||||
|
||||
export default MImageWidget;
|
||||
export const MProfiledImageWidget = MImageWidget;
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import ButtonComponent from "components/designSystems/taro/ButtonComponent";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import withMeta, { WithMeta } from "../MetaHOC";
|
||||
|
||||
class MKVWidget extends BaseWidget<MKVWidgetProps, KVWidgetState> {
|
||||
state = {
|
||||
isLoading: false,
|
||||
};
|
||||
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
propertyName: "text",
|
||||
label: "按钮文字",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "输入按钮文字",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "color",
|
||||
label: "按钮颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "rounded",
|
||||
label: "是否圆角",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
label: "是否可见",
|
||||
helpText: "控制按钮显示/隐藏",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
label: "禁用",
|
||||
controlType: "SWITCH",
|
||||
helpText: "禁止按钮交互",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "动作",
|
||||
children: [
|
||||
{
|
||||
helpText: "点击按钮时触发动作",
|
||||
propertyName: "onClick",
|
||||
label: "onClick",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
onButtonClick = () => {
|
||||
if (this.props.onClick) {
|
||||
this.setState({
|
||||
isLoading: true,
|
||||
});
|
||||
super.executeAction({
|
||||
triggerPropertyName: "onClick",
|
||||
dynamicString: this.props.onClick,
|
||||
event: {
|
||||
type: EventType.ON_CLICK,
|
||||
callback: this.handleActionComplete,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleActionComplete = () => {
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
});
|
||||
};
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<ButtonComponent
|
||||
isDisabled={this.props.isDisabled}
|
||||
isLoading={this.props.isLoading || this.state.isLoading}
|
||||
onClick={!this.props.isDisabled ? this.onButtonClick : undefined}
|
||||
text={this.props.text}
|
||||
color={this.props.color}
|
||||
rounded={this.props.rounded}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return "TARO_BUTTON_WIDGET";
|
||||
}
|
||||
}
|
||||
|
||||
export interface MKVWidgetProps extends WidgetProps, WithMeta {
|
||||
text?: string;
|
||||
color?: string;
|
||||
onClick?: string;
|
||||
rounded?: boolean;
|
||||
isDisabled?: boolean;
|
||||
isVisible?: boolean;
|
||||
}
|
||||
|
||||
interface KVWidgetState extends WidgetState {
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export default MKVWidget;
|
||||
export const MProfiledKVWidget = withMeta(MKVWidget);
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { WidgetType, WidgetTypes } from "constants/WidgetConstants";
|
||||
import ListComponent, {
|
||||
ListComponentProps,
|
||||
} from "components/designSystems/taro/ListComponent";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory";
|
||||
|
||||
class ListWidget extends BaseWidget<MListWidgetProps, WidgetState> {
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
helpText: "数组,通过 {{}} 进行数据绑定",
|
||||
propertyName: "list",
|
||||
label: "数据",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: '[{ "url": "", name: "" }]',
|
||||
inputType: "ARRAY",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: {
|
||||
type: ValidationTypes.OBJECT_ARRAY,
|
||||
params: {
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
evaluationSubstitutionType:
|
||||
EvaluationSubstitutionType.SMART_SUBSTITUTE,
|
||||
},
|
||||
{
|
||||
propertyName: "contentType",
|
||||
label: "内容类型",
|
||||
controlType: "DROP_DOWN",
|
||||
options: [
|
||||
{
|
||||
label: "图片+标题+描述",
|
||||
value: "I_N_D",
|
||||
},
|
||||
{
|
||||
label: "图片+标题+描述+价格",
|
||||
value: "I_N_D_P",
|
||||
},
|
||||
{
|
||||
label: "图片+标题+描述+价格+按钮",
|
||||
value: "I_N_D_P_B",
|
||||
},
|
||||
],
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "urlKey",
|
||||
label: "图片字段",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "titleKey",
|
||||
label: "标题字段",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "descriptionKey",
|
||||
label: "描述字段",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "priceKey",
|
||||
label: "价格字段",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
dependencies: ["contentType"],
|
||||
hidden: (props: MListWidgetProps) => {
|
||||
return props.contentType === "I_N_D";
|
||||
},
|
||||
},
|
||||
{
|
||||
propertyName: "buttonText",
|
||||
label: "按钮文本",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
dependencies: ["contentType"],
|
||||
hidden: (props: MListWidgetProps) => {
|
||||
return props.contentType !== "I_N_D_P_B";
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "样式",
|
||||
children: [
|
||||
{
|
||||
propertyName: "inset",
|
||||
label: "圆角风格",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "width",
|
||||
label: "图片宽度",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "height",
|
||||
label: "图片高度",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "titleColor",
|
||||
label: "标题颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "descriptionColor",
|
||||
label: "描述颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "priceColor",
|
||||
label: "价格颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
dependencies: ["contentType"],
|
||||
hidden: (props: MListWidgetProps) => {
|
||||
return props.contentType === "I_N_D";
|
||||
},
|
||||
},
|
||||
{
|
||||
propertyName: "buttonColor",
|
||||
label: "按钮颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
dependencies: ["contentType"],
|
||||
hidden: (props: MListWidgetProps) => {
|
||||
return props.contentType !== "I_N_D_P_B";
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
const {
|
||||
list,
|
||||
contentType,
|
||||
urlKey,
|
||||
titleKey,
|
||||
descriptionKey,
|
||||
priceKey,
|
||||
buttonText,
|
||||
inset,
|
||||
width,
|
||||
height,
|
||||
titleColor,
|
||||
descriptionColor,
|
||||
priceColor,
|
||||
buttonColor,
|
||||
} = this.props;
|
||||
return (
|
||||
<ListComponent
|
||||
{...{
|
||||
list,
|
||||
contentType,
|
||||
urlKey,
|
||||
titleKey,
|
||||
descriptionKey,
|
||||
priceKey,
|
||||
buttonText,
|
||||
inset,
|
||||
width,
|
||||
height,
|
||||
titleColor,
|
||||
descriptionColor,
|
||||
priceColor,
|
||||
buttonColor,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return WidgetTypes.TARO_LIST_WIDGET;
|
||||
}
|
||||
}
|
||||
|
||||
export interface MListWidgetProps extends WidgetProps, ListComponentProps {}
|
||||
|
||||
export default ListWidget;
|
||||
export const MProfiledListWidget = ListWidget;
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { WidgetType, WidgetTypes } from "constants/WidgetConstants";
|
||||
import PickerComponent from "components/designSystems/taro/PickerComponent";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import withMeta, { WithMeta } from "../MetaHOC";
|
||||
|
||||
class PickerWidget extends BaseWidget<PickerWidgetProps, WidgetState> {
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
propertyName: "title",
|
||||
label: "这是什么",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "动作",
|
||||
children: [
|
||||
{
|
||||
propertyName: "onTap",
|
||||
label: "被点击后执行",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
onButtonClick = (e: any) => {
|
||||
e.stopPropagation();
|
||||
if (this.props.onTap) {
|
||||
super.executeAction({
|
||||
triggerPropertyName: "onTap",
|
||||
dynamicString: this.props.onTap,
|
||||
event: {
|
||||
type: EventType.ON_CLICK,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
static getMetaPropertiesMap(): Record<string, undefined> {
|
||||
return {};
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
const { title } = this.props;
|
||||
return (
|
||||
<PickerComponent
|
||||
onButtonClick={this.onButtonClick}
|
||||
{...{
|
||||
title,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return WidgetTypes.TARO_PICKER_WIDGET;
|
||||
}
|
||||
}
|
||||
|
||||
export interface PickerWidgetProps extends WidgetProps, WithMeta {
|
||||
title?: string;
|
||||
onTap?: string;
|
||||
}
|
||||
|
||||
export default PickerWidget;
|
||||
export const ProfiledPickerWidget = Sentry.withProfiler(withMeta(PickerWidget));
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
import React, { ReactNode } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import WidgetFactory from "utils/WidgetFactory";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import ModalComponent from "components/designSystems/taro/PopoverComponent";
|
||||
import {
|
||||
WidgetTypes,
|
||||
RenderMode,
|
||||
MAIN_CONTAINER_WIDGET_ID,
|
||||
} from "constants/WidgetConstants";
|
||||
import { generateClassName } from "utils/generators";
|
||||
import withMeta, { WithMeta } from "../MetaHOC";
|
||||
import { AppState } from "reducers";
|
||||
import { getWidget } from "sagas/selectors";
|
||||
|
||||
export class MPopupWidget extends BaseWidget<MPopupWidgetProps, WidgetState> {
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
propertyName: "height",
|
||||
label: "弹窗高度(不带单位的数字)",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: {
|
||||
type: ValidationTypes.NUMBER,
|
||||
params: { min: 200, max: 800 },
|
||||
},
|
||||
},
|
||||
{
|
||||
propertyName: "canOutsideClickClose",
|
||||
label: "点击背景关闭",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "rounded",
|
||||
label: "圆角风格",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "动作",
|
||||
children: [
|
||||
{
|
||||
helpText: "弹窗关闭后触发",
|
||||
propertyName: "onClose",
|
||||
label: "onClose",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
getModalWidth() {
|
||||
return this.props.mainContainer.rightColumn;
|
||||
}
|
||||
|
||||
renderChildWidget = (childWidgetData: WidgetProps): ReactNode => {
|
||||
childWidgetData.parentId = this.props.widgetId;
|
||||
childWidgetData.shouldScrollContents = false;
|
||||
childWidgetData.canExtend = false;
|
||||
childWidgetData.bottomRow = childWidgetData.bottomRow;
|
||||
childWidgetData.isVisible = this.props.isVisible;
|
||||
childWidgetData.containerStyle = "none";
|
||||
childWidgetData.minHeight = this.props.height;
|
||||
childWidgetData.rightColumn = this.getModalWidth();
|
||||
return WidgetFactory.createWidget(childWidgetData, this.props.renderMode);
|
||||
};
|
||||
|
||||
onModalClose = () => {
|
||||
if (this.props.onClose) {
|
||||
super.executeAction({
|
||||
triggerPropertyName: "onClose",
|
||||
dynamicString: this.props.onClose,
|
||||
event: {
|
||||
type: EventType.ON_MODAL_CLOSE,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
closeModal = () => {
|
||||
this.props.showPropertyPane(undefined);
|
||||
this.props.updateWidgetMetaProperty("isVisible", false);
|
||||
};
|
||||
|
||||
getChildren(): ReactNode {
|
||||
if (this.props.children && this.props.children.length > 0) {
|
||||
const children = this.props.children.filter(Boolean);
|
||||
return children.length > 0 && children.map(this.renderChildWidget);
|
||||
}
|
||||
}
|
||||
|
||||
makeModalComponent(content: ReactNode) {
|
||||
return (
|
||||
<ModalComponent
|
||||
canOutsideClickClose={!!this.props.canOutsideClickClose}
|
||||
className={`t--modal-widget ${generateClassName(this.props.widgetId)}`}
|
||||
height={this.props.height}
|
||||
rounded={this.props.rounded}
|
||||
isOpen={!!this.props.isVisible}
|
||||
onClose={this.closeModal}
|
||||
onModalClose={this.onModalClose}
|
||||
>
|
||||
{content}
|
||||
</ModalComponent>
|
||||
);
|
||||
}
|
||||
|
||||
getCanvasView() {
|
||||
let children = this.getChildren();
|
||||
children = this.showWidgetName(children, true);
|
||||
return this.makeModalComponent(children);
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
const children = this.getChildren();
|
||||
return this.makeModalComponent(children);
|
||||
}
|
||||
|
||||
getWidgetType() {
|
||||
return WidgetTypes.TARO_POPUP_WIDGET;
|
||||
}
|
||||
}
|
||||
|
||||
export interface MPopupWidgetProps extends WidgetProps, WithMeta {
|
||||
renderMode: RenderMode;
|
||||
children?: WidgetProps[];
|
||||
canOutsideClickClose?: boolean;
|
||||
rounded?: boolean;
|
||||
height?: number;
|
||||
showPropertyPane: (widgetId?: string) => void;
|
||||
onClose: string;
|
||||
mainContainer: WidgetProps;
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch: any) => ({
|
||||
showPropertyPane: (
|
||||
widgetId?: string,
|
||||
callForDragOrResize?: boolean,
|
||||
force = false,
|
||||
) => {
|
||||
dispatch({
|
||||
type:
|
||||
widgetId || callForDragOrResize
|
||||
? ReduxActionTypes.SHOW_PROPERTY_PANE
|
||||
: ReduxActionTypes.HIDE_PROPERTY_PANE,
|
||||
payload: { widgetId, callForDragOrResize, force },
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
const props = {
|
||||
mainContainer: getWidget(state, MAIN_CONTAINER_WIDGET_ID),
|
||||
};
|
||||
return props;
|
||||
};
|
||||
export default MPopupWidget;
|
||||
export const MProfiledPopupWidget = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
)(withMeta(MPopupWidget));
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import ButtonComponent from "components/designSystems/taro/ButtonComponent";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import withMeta, { WithMeta } from "../MetaHOC";
|
||||
|
||||
class MSimpleFormWidget extends BaseWidget<
|
||||
MSimpleFormWidgetProps,
|
||||
SimpleFormWidgetState
|
||||
> {
|
||||
state = {
|
||||
isLoading: false,
|
||||
};
|
||||
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
propertyName: "text",
|
||||
label: "按钮文字",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "输入按钮文字",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "color",
|
||||
label: "按钮颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "rounded",
|
||||
label: "是否圆角",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
label: "是否可见",
|
||||
helpText: "控制按钮显示/隐藏",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
label: "禁用",
|
||||
controlType: "SWITCH",
|
||||
helpText: "禁止按钮交互",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "动作",
|
||||
children: [
|
||||
{
|
||||
helpText: "点击按钮时触发动作",
|
||||
propertyName: "onClick",
|
||||
label: "onClick",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
onButtonClick = () => {
|
||||
if (this.props.onClick) {
|
||||
this.setState({
|
||||
isLoading: true,
|
||||
});
|
||||
super.executeAction({
|
||||
triggerPropertyName: "onClick",
|
||||
dynamicString: this.props.onClick,
|
||||
event: {
|
||||
type: EventType.ON_CLICK,
|
||||
callback: this.handleActionComplete,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleActionComplete = () => {
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
});
|
||||
};
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<ButtonComponent
|
||||
isDisabled={this.props.isDisabled}
|
||||
isLoading={this.props.isLoading || this.state.isLoading}
|
||||
onClick={!this.props.isDisabled ? this.onButtonClick : undefined}
|
||||
text={this.props.text}
|
||||
color={this.props.color}
|
||||
rounded={this.props.rounded}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return "TARO_BUTTON_WIDGET";
|
||||
}
|
||||
}
|
||||
|
||||
export interface MSimpleFormWidgetProps extends WidgetProps, WithMeta {
|
||||
text?: string;
|
||||
color?: string;
|
||||
onClick?: string;
|
||||
rounded?: boolean;
|
||||
isDisabled?: boolean;
|
||||
isVisible?: boolean;
|
||||
}
|
||||
|
||||
interface SimpleFormWidgetState extends WidgetState {
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export default MSimpleFormWidget;
|
||||
export const MProfiledSimpleFormWidget = withMeta(MSimpleFormWidget);
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { WidgetType, WidgetTypes } from "constants/WidgetConstants";
|
||||
import SwiperComponent from "components/designSystems/taro/SwiperComponent";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory";
|
||||
import _ from "lodash";
|
||||
|
||||
class SwiperWidget extends BaseWidget<SwiperWidgetProps, WidgetState> {
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
helpText: "轮播数据列表,通过 {{}} 进行数据绑定",
|
||||
propertyName: "list",
|
||||
label: "数据",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: '例如 [{ "url": "val1", link: "val2" }]',
|
||||
inputType: "ARRAY",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: {
|
||||
type: ValidationTypes.OBJECT_ARRAY,
|
||||
params: {
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
evaluationSubstitutionType: EvaluationSubstitutionType.SMART_SUBSTITUTE,
|
||||
},
|
||||
{
|
||||
propertyName: "urlKey",
|
||||
label: "图片字段",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
const { list, urlKey } = this.props;
|
||||
return (
|
||||
<SwiperComponent
|
||||
{...{
|
||||
list,
|
||||
urlKey,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return WidgetTypes.TARO_SWIPER_WIDGET;
|
||||
}
|
||||
}
|
||||
|
||||
export interface SwiperWidgetProps extends WidgetProps {
|
||||
list: any[];
|
||||
urlKey: string;
|
||||
}
|
||||
|
||||
export default SwiperWidget;
|
||||
export const ProfiledSwiperWidget = SwiperWidget;
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import ButtonComponent from "components/designSystems/taro/ButtonComponent";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import withMeta, { WithMeta } from "../MetaHOC";
|
||||
|
||||
class MTabsWidget extends BaseWidget<MTabsWidgetProps, TabsWidgetState> {
|
||||
state = {
|
||||
isLoading: false,
|
||||
};
|
||||
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
propertyName: "text",
|
||||
label: "按钮文字",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "输入按钮文字",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "color",
|
||||
label: "按钮颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "rounded",
|
||||
label: "是否圆角",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
label: "是否可见",
|
||||
helpText: "控制按钮显示/隐藏",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
{
|
||||
propertyName: "isDisabled",
|
||||
label: "禁用",
|
||||
controlType: "SWITCH",
|
||||
helpText: "禁止按钮交互",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "动作",
|
||||
children: [
|
||||
{
|
||||
helpText: "点击按钮时触发动作",
|
||||
propertyName: "onClick",
|
||||
label: "onClick",
|
||||
controlType: "ACTION_SELECTOR",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
onButtonClick = () => {
|
||||
if (this.props.onClick) {
|
||||
this.setState({
|
||||
isLoading: true,
|
||||
});
|
||||
super.executeAction({
|
||||
triggerPropertyName: "onClick",
|
||||
dynamicString: this.props.onClick,
|
||||
event: {
|
||||
type: EventType.ON_CLICK,
|
||||
callback: this.handleActionComplete,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleActionComplete = () => {
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
});
|
||||
};
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<ButtonComponent
|
||||
isDisabled={this.props.isDisabled}
|
||||
isLoading={this.props.isLoading || this.state.isLoading}
|
||||
onClick={!this.props.isDisabled ? this.onButtonClick : undefined}
|
||||
text={this.props.text}
|
||||
color={this.props.color}
|
||||
rounded={this.props.rounded}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return "TARO_BUTTON_WIDGET";
|
||||
}
|
||||
}
|
||||
|
||||
export interface MTabsWidgetProps extends WidgetProps, WithMeta {
|
||||
text?: string;
|
||||
color?: string;
|
||||
onClick?: string;
|
||||
rounded?: boolean;
|
||||
isDisabled?: boolean;
|
||||
isVisible?: boolean;
|
||||
}
|
||||
|
||||
interface TabsWidgetState extends WidgetState {
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export default MTabsWidget;
|
||||
export const MProfiledTabsWidget = withMeta(MTabsWidget);
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
import React from "react";
|
||||
import BaseWidget, { WidgetProps, WidgetState } from "../BaseWidget";
|
||||
import { WidgetType, TextSize } from "constants/WidgetConstants";
|
||||
import TextComponent from "components/designSystems/taro/TextComponent";
|
||||
import { ValidationTypes } from "constants/WidgetValidation";
|
||||
import { DerivedPropertiesMap } from "utils/WidgetFactory";
|
||||
|
||||
class TextWidget extends BaseWidget<MTextWidgetProps, WidgetState> {
|
||||
static getPropertyPaneConfig() {
|
||||
return [
|
||||
{
|
||||
sectionName: "属性",
|
||||
children: [
|
||||
{
|
||||
propertyName: "text",
|
||||
label: "文本",
|
||||
controlType: "INPUT_TEXT",
|
||||
placeholderText: "请输入文本内容",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "shouldScroll",
|
||||
label: "允许滚动",
|
||||
helpText: "内容超长时允许滚动,不然文本会被截断",
|
||||
controlType: "SWITCH",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "isVisible",
|
||||
label: "是否可见",
|
||||
controlType: "SWITCH",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.BOOLEAN },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionName: "样式",
|
||||
children: [
|
||||
{
|
||||
propertyName: "backgroundColor",
|
||||
label: "背景颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "textColor",
|
||||
label: "文本颜色",
|
||||
controlType: "COLOR_PICKER",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: {
|
||||
type: ValidationTypes.TEXT,
|
||||
params: {
|
||||
regex: /^(?![<|{{]).+/,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
propertyName: "fontSize",
|
||||
label: "字体大小",
|
||||
controlType: "DROP_DOWN",
|
||||
options: [
|
||||
{
|
||||
label: "一级标题",
|
||||
value: "HEADING1",
|
||||
subText: "24px",
|
||||
icon: "HEADING_ONE",
|
||||
},
|
||||
{
|
||||
label: "二级标题",
|
||||
value: "HEADING2",
|
||||
subText: "18px",
|
||||
icon: "HEADING_TWO",
|
||||
},
|
||||
{
|
||||
label: "三级标题",
|
||||
value: "HEADING3",
|
||||
subText: "16px",
|
||||
icon: "HEADING_THREE",
|
||||
},
|
||||
{
|
||||
label: "一级段落",
|
||||
value: "PARAGRAPH",
|
||||
subText: "14px",
|
||||
icon: "PARAGRAPH",
|
||||
},
|
||||
{
|
||||
label: "二级段落",
|
||||
value: "PARAGRAPH2",
|
||||
subText: "12px",
|
||||
icon: "PARAGRAPH_TWO",
|
||||
},
|
||||
],
|
||||
isBindProperty: false,
|
||||
isTriggerProperty: false,
|
||||
},
|
||||
{
|
||||
propertyName: "fontStyle",
|
||||
label: "字体风格",
|
||||
controlType: "BUTTON_TABS",
|
||||
options: [
|
||||
{
|
||||
icon: "BOLD_FONT",
|
||||
value: "BOLD",
|
||||
},
|
||||
{
|
||||
icon: "ITALICS_FONT",
|
||||
value: "ITALIC",
|
||||
},
|
||||
{
|
||||
icon: "LINETHROUGH_FONT",
|
||||
value: "LINETHROUGH",
|
||||
},
|
||||
],
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "textAlign",
|
||||
label: "文字对齐",
|
||||
controlType: "ICON_TABS",
|
||||
options: [
|
||||
{
|
||||
icon: "LEFT_ALIGN",
|
||||
value: "LEFT",
|
||||
},
|
||||
{
|
||||
icon: "CENTER_ALIGN",
|
||||
value: "CENTER",
|
||||
},
|
||||
{
|
||||
icon: "RIGHT_ALIGN",
|
||||
value: "RIGHT",
|
||||
},
|
||||
],
|
||||
defaultValue: "LEFT",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<TextComponent
|
||||
backgroundColor={this.props.backgroundColor}
|
||||
fontSize={this.props.fontSize}
|
||||
fontStyle={this.props.fontStyle}
|
||||
isLoading={this.props.isLoading}
|
||||
key={this.props.widgetId}
|
||||
shouldScroll={this.props.shouldScroll}
|
||||
text={this.props.text}
|
||||
textAlign={this.props.textAlign ? this.props.textAlign : "LEFT"}
|
||||
textColor={this.props.textColor}
|
||||
widgetId={this.props.widgetId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
static getDerivedPropertiesMap(): DerivedPropertiesMap {
|
||||
return {
|
||||
value: `{{ this.text }}`,
|
||||
};
|
||||
}
|
||||
|
||||
getWidgetType(): WidgetType {
|
||||
return "TARO_TEXT_WIDGET";
|
||||
}
|
||||
}
|
||||
|
||||
export type TextAlign = "LEFT" | "CENTER" | "RIGHT" | "JUSTIFY";
|
||||
|
||||
export interface TextStyles {
|
||||
backgroundColor?: string;
|
||||
textColor?: string;
|
||||
fontStyle?: string;
|
||||
fontSize?: TextSize;
|
||||
textAlign?: TextAlign;
|
||||
}
|
||||
|
||||
export interface MTextWidgetProps extends WidgetProps, TextStyles {
|
||||
text?: string;
|
||||
isLoading: boolean;
|
||||
shouldScroll: boolean;
|
||||
}
|
||||
|
||||
export default TextWidget;
|
||||
export const MProfiledTextWidget = TextWidget;
|
||||
|
|
@ -3,7 +3,9 @@
|
|||
"baseUrl": "src",
|
||||
"paths": {
|
||||
"@appsmith/*": ["enterprise/*"],
|
||||
"test/*": ["../test/*"]
|
||||
"test/*": ["../test/*"],
|
||||
"@tarojs/components$": ["../node_modules/@tarojs/components/dist-h5/react"],
|
||||
"@tarojs/taro$": ["../node_modules/@tarojs/taro-h5/dist/index.cjs.js"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -13,6 +13,9 @@ public class CloudOSConfig {
|
|||
@Value("${pageplug.cloudos.mock_baseurl}")
|
||||
String mockUrl;
|
||||
|
||||
@Value("${pageplug.cloudos.db_baseurl}")
|
||||
String dbUrl;
|
||||
|
||||
@Value("${pageplug.cloudos.in_cloudos}")
|
||||
Boolean inCloudOS;
|
||||
|
||||
|
|
|
|||
|
|
@ -56,10 +56,8 @@ public class Application extends BaseDomain {
|
|||
|
||||
String icon;
|
||||
|
||||
@JsonIgnore
|
||||
AppLayout unpublishedAppLayout;
|
||||
|
||||
@JsonIgnore
|
||||
AppLayout publishedAppLayout;
|
||||
|
||||
Boolean forkingEnabled;
|
||||
|
|
@ -118,6 +116,7 @@ public class Application extends BaseDomain {
|
|||
TABLET,
|
||||
MOBILE,
|
||||
FLUID,
|
||||
MOBILE_FLUID,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,10 +15,7 @@ import com.appsmith.server.domains.NewPage;
|
|||
import com.appsmith.server.domains.Organization;
|
||||
import com.appsmith.server.domains.Page;
|
||||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.dtos.ActionDTO;
|
||||
import com.appsmith.server.dtos.ApplicationPagesDTO;
|
||||
import com.appsmith.server.dtos.PageDTO;
|
||||
import com.appsmith.server.dtos.PageNameIdDTO;
|
||||
import com.appsmith.server.dtos.*;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import com.appsmith.server.repositories.ApplicationRepository;
|
||||
|
|
@ -255,6 +252,15 @@ public class ApplicationPageServiceImpl implements ApplicationPageService {
|
|||
|
||||
return applicationWithPoliciesMono
|
||||
.flatMap(applicationService::createDefault)
|
||||
.flatMap(savedApplication -> {
|
||||
final Application.AppLayout appLayout = savedApplication.getPublishedAppLayout();
|
||||
if (appLayout != null && appLayout.getType() == Application.AppLayout.Type.MOBILE_FLUID) {
|
||||
final ApplicationAccessDTO applicationAccessDTO = new ApplicationAccessDTO();
|
||||
applicationAccessDTO.setPublicAccess(true);
|
||||
return this.applicationService.changeViewAccess(savedApplication.getId(), applicationAccessDTO);
|
||||
}
|
||||
return Mono.just(savedApplication);
|
||||
})
|
||||
.flatMap(savedApplication -> {
|
||||
|
||||
PageDTO page = new PageDTO();
|
||||
|
|
|
|||
|
|
@ -113,8 +113,13 @@ public class CloudOSActionSolution {
|
|||
String componentId = instance.get("component_id");
|
||||
String serviceAddress = instance.get("service_address");
|
||||
String datasourceName = componentName == null ? componentId : componentName;
|
||||
String dbPrefix = cloudOSConfig.getDbUrl();
|
||||
return datasourceService.findByNameAndOrganizationId(datasourceName, application.getOrganizationId(), AclPermission.MANAGE_DATASOURCES)
|
||||
.flatMap(datasource -> {
|
||||
final String oldUrl = datasource.getDatasourceConfiguration().getUrl();
|
||||
if (oldUrl.contains(dbPrefix)) {
|
||||
return Mono.just(datasource);
|
||||
}
|
||||
final Datasource deployedDatasource = new Datasource();
|
||||
final DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
|
||||
datasourceConfiguration.setUrl(serviceAddress);
|
||||
|
|
@ -221,6 +226,14 @@ public class CloudOSActionSolution {
|
|||
final String componentId = (String) bp.get("componentId");
|
||||
final String componentDisplay = componentName == null ? componentId : componentName;
|
||||
List<Map<String, ?>> cloudOSApiList = (List<Map<String, ?>>) bp.get("apis");
|
||||
log.debug("绑定组件 " + componentName + " 的API");
|
||||
log.debug(cloudOSApiList.toString());
|
||||
Boolean isDbApi = cloudOSApiList.stream().anyMatch(ca -> {
|
||||
final String apiKey = (String) ca.get("apiKey");
|
||||
return apiKey != null;
|
||||
});
|
||||
final String apiHost = isDbApi ? cloudOSConfig.getDbUrl() : cloudOSConfig.getMockUrl() + "/" + projectId + "/" + componentId;
|
||||
log.debug("数据源地址:" + apiHost);
|
||||
|
||||
// create new datasource
|
||||
Datasource newSource = new Datasource();
|
||||
|
|
@ -229,7 +242,7 @@ public class CloudOSActionSolution {
|
|||
newSource.setName(componentDisplay);
|
||||
|
||||
DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
|
||||
datasourceConfiguration.setUrl(cloudOSConfig.getMockUrl() + "/" + projectId + "/" + componentId);
|
||||
datasourceConfiguration.setUrl(apiHost);
|
||||
ArrayList<Property> properties = new ArrayList<>();
|
||||
properties.add(new Property("isSendSessionEnabled", "N"));
|
||||
properties.add(new Property("sessionSignatureKey", ""));
|
||||
|
|
|
|||
|
|
@ -101,5 +101,6 @@ google.recaptcha.key.secret= ${APPSMITH_RECAPTCHA_SECRET_KEY:}
|
|||
# CloudOS config
|
||||
pageplug.cloudos.api_baseurl = ${CLOUDOS_API_BASE_URL:}
|
||||
pageplug.cloudos.mock_baseurl = ${CLOUDOS_MOCK_BASE_URL:}
|
||||
pageplug.cloudos.db_baseurl = ${CLOUDOS_DB_BASE_URL:}
|
||||
pageplug.cloudos.in_cloudos = ${CLOUDOS_IN_CLOUDOS:false}
|
||||
pageplug.cloudos.jwt_secret_key = ${CLOUDOS_JWT_SECRET_KET:}
|
||||
|
|
@ -13,6 +13,7 @@ APPSMITH_CODEC_SIZE=10
|
|||
|
||||
CLOUDOS_API_BASE_URL="http://10.10.11.20:8035"
|
||||
CLOUDOS_MOCK_BASE_URL="http://10.10.11.20:8899"
|
||||
CLOUDOS_DB_BASE_URL="http://db-manager.dev.staros.local/api/db-manager"
|
||||
CLOUDOS_IN_CLOUDOS=false
|
||||
CLOUDOS_JWT_SECRET_KET="jKriFBzevooCpDi"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue