[+] add taro project
This commit is contained in:
parent
0a456e4877
commit
ea05f91d8a
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
|
|
@ -41,7 +41,6 @@ applyPolyfills().then(() => {
|
|||
defineCustomElements(window);
|
||||
});
|
||||
// create taro runtime in React
|
||||
import { createRouter } from "@tarojs/taro";
|
||||
import { createReactApp } from "@tarojs/runtime";
|
||||
class Empty extends React.Component {
|
||||
render() {
|
||||
|
|
@ -49,18 +48,7 @@ class Empty extends React.Component {
|
|||
}
|
||||
}
|
||||
const inst = createReactApp(Empty, React, ReactDOM, {});
|
||||
// createRouter(
|
||||
// inst,
|
||||
// {
|
||||
// routes: [],
|
||||
// router: {
|
||||
// mode: "browser",
|
||||
// basename: "",
|
||||
// pathname: "",
|
||||
// },
|
||||
// },
|
||||
// "react",
|
||||
// );
|
||||
|
||||
// add touch emulator
|
||||
import "@vant/touch-emulator";
|
||||
import "react-sortable-tree-patch-react-17/style.css";
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
APPSMITH_MONGODB_URI="mongodb://10.10.13.50:27017/appsmith"
|
||||
|
||||
APPSMITH_REDIS_URL="redis://10.10.13.50:63799"
|
||||
|
||||
CLOUDOS_WECHAT_APPID="wx414ad0dbeda1a70b"
|
||||
CLOUDOS_WECHAT_SECRET="d5289fd08b1fb31290f66ea2ce5ec7dc"
|
||||
|
||||
APPSMITH_MAIL_ENABLED=false
|
||||
|
||||
APPSMITH_ENCRYPTION_PASSWORD=abcd
|
||||
APPSMITH_ENCRYPTION_SALT=abcd
|
||||
|
||||
APPSMITH_CODEC_SIZE=10
|
||||
|
||||
#APPSMITH_CLOUD_SERVICES_BASE_URL="https://release-cs.appsmith.com"
|
||||
|
||||
#APPSMITH_OAUTH2_GOOGLE_CLIENT_ID=""
|
||||
#APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET=""
|
||||
|
||||
#APPSMITH_OAUTH2_GITHUB_CLIENT_ID=""
|
||||
#APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET=""
|
||||
|
||||
#APPSMITH_SENTRY_DSN=
|
||||
#APPSMITH_SENTRY_ENVIRONMENT=
|
||||
|
||||
#APPSMITH_RECAPTCHA_SITE_KEY=""
|
||||
#APPSMITH_RECAPTCHA_SECRET_KEY=""
|
||||
|
|
@ -12,5 +12,5 @@ node_modules
|
|||
**/.project
|
||||
**/.factorypath
|
||||
container-volumes
|
||||
!.env
|
||||
*.env
|
||||
dependency-reduced-pom.xml
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
module.exports = {
|
||||
"extends": ["taro/react"],
|
||||
"rules": {
|
||||
"react/jsx-uses-react": "off",
|
||||
"react/react-in-jsx-scope": "off"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
dist/
|
||||
deploy_versions/
|
||||
.temp/
|
||||
.rn_temp/
|
||||
node_modules/
|
||||
.DS_Store
|
||||
.linaria-cache/
|
||||
|
|
@ -0,0 +1 @@
|
|||
# taro viewer for PagePlug 💖
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// babel-preset-taro 更多选项和默认值:
|
||||
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
|
||||
module.exports = {
|
||||
presets: [
|
||||
['taro', {
|
||||
framework: 'react',
|
||||
ts: true
|
||||
}],
|
||||
'linaria/babel'
|
||||
],
|
||||
plugins: [
|
||||
[
|
||||
"import",
|
||||
{
|
||||
libraryName: "@taroify/core",
|
||||
libraryDirectory: "",
|
||||
style: true,
|
||||
},
|
||||
"@taroify/core",
|
||||
],
|
||||
[
|
||||
"import",
|
||||
{
|
||||
libraryName: "@taroify/icons",
|
||||
libraryDirectory: "",
|
||||
camel2DashComponentName: false,
|
||||
style: () => "@taroify/icons/style",
|
||||
},
|
||||
"@taroify/icons",
|
||||
],
|
||||
],
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
// eslint-disable-next-line import/no-commonjs
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
const pxtransform = require("./postcss.pxtransform");
|
||||
|
||||
const transformEditorSize = (rule) => {
|
||||
rule.oneOf('0').use('2').tap(options => ({
|
||||
...options,
|
||||
postcssOptions: {
|
||||
plugins: [
|
||||
// transform PagePlug component px(based on 450) to weapp unit rpx(based on 750)
|
||||
pxtransform(),
|
||||
...options.postcssOptions.plugins,
|
||||
]
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
env: {
|
||||
NODE_ENV: '"development"',
|
||||
REACT_APP_CLIENT_LOG_LEVEL: '"error"', // debug or error
|
||||
},
|
||||
defineConstants: {
|
||||
// PagePlug 接口地址
|
||||
API_BASE_URL: '""',
|
||||
// 默认应用ID
|
||||
DEFAULT_APP: '""',
|
||||
},
|
||||
mini: {
|
||||
webpackChain(chain, webpack) {
|
||||
// add postcss plugin
|
||||
transformEditorSize(chain.module.rule("less"));
|
||||
transformEditorSize(chain.module.rule("nomorlCss"));
|
||||
|
||||
// lodash bundle reduction
|
||||
// `shorthands`, `coercions`, `paths` are necessary to avoid some weird things
|
||||
chain.plugin("lodash-webpack-plugin").use(require("lodash-webpack-plugin"), [
|
||||
{
|
||||
shorthands: true,
|
||||
cloning: true,
|
||||
caching: true,
|
||||
collections: true,
|
||||
exotics: true,
|
||||
guards: true,
|
||||
memoizing: true,
|
||||
coercions: true,
|
||||
flattening: true,
|
||||
paths: true,
|
||||
},
|
||||
])
|
||||
|
||||
chain.merge({
|
||||
resolve: {
|
||||
modules: [
|
||||
'./src',
|
||||
],
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
// `all` or `initial`, `all` will have the smallest overall size, refer to
|
||||
// https://stackoverflow.com/questions/50127185/webpack-what-is-the-difference-between-all-and-initial-options-in-optimizat
|
||||
chunks: "all",
|
||||
cacheGroups: {
|
||||
lodash: {
|
||||
name: "lodash",
|
||||
priority: 100,
|
||||
test(module) {
|
||||
return /node_modules[\\/]lodash/.test(module.context)
|
||||
},
|
||||
},
|
||||
taroify: {
|
||||
name: "taroify",
|
||||
test(module) {
|
||||
if (/package[\\/](core|icons|hooks)/.test(module.resource)) {
|
||||
return true
|
||||
}
|
||||
if (/bundles[\\/](core|icons|hooks)/.test(module.resource)) {
|
||||
return true
|
||||
}
|
||||
return /node_modules[\\/]@taroify/.test(module.resource)
|
||||
},
|
||||
//
|
||||
// test: /node_modules[\\/]@taroify/,
|
||||
// just higher than 10 will be fine, refer to
|
||||
// https://github.com/NervJS/taro/blob/bc6af68bda2cbc9163fbda36c15878fc96aec8f1/packages/taro-mini-runner/src/webpack/build.conf.ts#L220-L254
|
||||
priority: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
// turn on below `minimize`, `minimizer` settings if bundle size is way too large
|
||||
// to do remote debug in wechatdevtools
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
// add those `bundle`s your want to do size reduction
|
||||
// refer to https://webpack.js.org/plugins/terser-webpack-plugin/#test
|
||||
test: ["common.js", "taro.js", "vendors.js", "lodash.js", "taroify.js", "app.js", "pages/index/index.js"],
|
||||
parallel: true,
|
||||
// minify: TerserPlugin.swcMinify,
|
||||
cache: true,
|
||||
// remove comments
|
||||
terserOptions: {
|
||||
output: {
|
||||
comments: false,
|
||||
},
|
||||
},
|
||||
extractComments: false,
|
||||
// should work with `mini.sourceMapType='source-map'`
|
||||
// refer to https://webpack.js.org/plugins/terser-webpack-plugin/#note-about-source-maps
|
||||
sourceMap: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
})
|
||||
// enable webpack-bundle-analyzer
|
||||
// if you would like to do some bundle reduction stuff
|
||||
// chain.plugin("analyzer")
|
||||
// .use(require("webpack-bundle-analyzer").BundleAnalyzerPlugin, [{
|
||||
// analyzerPort: "auto",
|
||||
// generateStatsFile: true,
|
||||
// }])
|
||||
|
||||
chain.module
|
||||
.rule('script')
|
||||
.use('linariaLoader')
|
||||
.loader('linaria/loader')
|
||||
.options({
|
||||
sourceMap: true,
|
||||
});
|
||||
},
|
||||
commonChunks(commonChunks) {
|
||||
commonChunks.push("lodash")
|
||||
commonChunks.push("taroify")
|
||||
return commonChunks
|
||||
},
|
||||
// turn to source-map if TerserPlugin is on
|
||||
// refer to http://taro-docs.jd.com/taro/docs/config-detail/#minisourcemaptype
|
||||
sourceMapType: "source-map",
|
||||
},
|
||||
h5: {}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
const pxtransform = require("./postcss.pxtransform");
|
||||
|
||||
const transformEditorSize = (rule) => {
|
||||
rule.oneOf('0').use('2').tap(options => ({
|
||||
...options,
|
||||
postcssOptions: {
|
||||
plugins: [
|
||||
// transform PagePlug component px(based on 450) to weapp unit rpx(based on 750)
|
||||
pxtransform(),
|
||||
...options.postcssOptions.plugins,
|
||||
]
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
const config = {
|
||||
projectName: 'b_d_m',
|
||||
date: '2021-11-8',
|
||||
designWidth: 750,
|
||||
deviceRatio: {
|
||||
640: 2.34 / 2,
|
||||
750: 1,
|
||||
828: 1.81 / 2
|
||||
},
|
||||
sourceRoot: 'src',
|
||||
outputRoot: 'dist',
|
||||
plugins: [
|
||||
'@tarojs/plugin-html',
|
||||
'@tarojs/plugin-sass',
|
||||
],
|
||||
defineConstants: {
|
||||
// PagePlug 接口地址
|
||||
API_BASE_URL: '""',
|
||||
// 默认应用ID
|
||||
DEFAULT_APP: '""',
|
||||
// 默认空内容图片地址
|
||||
EMPTY_IMAGE_URL: '"https://img.icons8.com/stickers/344/aquarium.png"',
|
||||
},
|
||||
copy: {
|
||||
patterns: [
|
||||
{ from: 'src/worker/', to: 'dist/worker/' },
|
||||
],
|
||||
options: {
|
||||
}
|
||||
},
|
||||
framework: 'react',
|
||||
mini: {
|
||||
postcss: {
|
||||
pxtransform: {
|
||||
enable: true,
|
||||
config: {},
|
||||
},
|
||||
url: {
|
||||
enable: true,
|
||||
config: {
|
||||
limit: 1024 // 设定转换尺寸上限
|
||||
}
|
||||
},
|
||||
cssModules: {
|
||||
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
|
||||
config: {
|
||||
namingPattern: 'module', // 转换模式,取值为 global/module
|
||||
generateScopedName: '[name]__[local]___[hash:base64:5]'
|
||||
}
|
||||
}
|
||||
},
|
||||
webpackChain(chain, webpack) {
|
||||
// add postcss plugin
|
||||
transformEditorSize(chain.module.rule("less"));
|
||||
transformEditorSize(chain.module.rule("nomorlCss"));
|
||||
chain.merge({
|
||||
resolve: {
|
||||
modules: [
|
||||
'./src',
|
||||
],
|
||||
}
|
||||
});
|
||||
chain.module
|
||||
.rule('script')
|
||||
.use('linariaLoader')
|
||||
.loader('linaria/loader')
|
||||
.options({
|
||||
sourceMap: process.env.NODE_ENV !== 'production',
|
||||
});
|
||||
}
|
||||
},
|
||||
h5: {
|
||||
publicPath: '/',
|
||||
staticDirectory: 'static',
|
||||
postcss: {
|
||||
autoprefixer: {
|
||||
enable: true,
|
||||
config: {
|
||||
}
|
||||
},
|
||||
cssModules: {
|
||||
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
|
||||
config: {
|
||||
namingPattern: 'module', // 转换模式,取值为 global/module
|
||||
generateScopedName: '[name]__[local]___[hash:base64:5]'
|
||||
}
|
||||
}
|
||||
},
|
||||
webpackChain(chain, webpack) {
|
||||
chain.merge({
|
||||
resolve: {
|
||||
modules: [
|
||||
'./src',
|
||||
],
|
||||
}
|
||||
});
|
||||
chain.module
|
||||
.rule('script')
|
||||
.use('linariaLoader')
|
||||
.loader('linaria/loader')
|
||||
.options({
|
||||
sourceMap: process.env.NODE_ENV !== 'production',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function (merge) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
return merge({}, config, require('./dev'))
|
||||
}
|
||||
return merge({}, config, require('./prod'))
|
||||
}
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
'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: 'weapp',
|
||||
designWidth: 750,
|
||||
deviceRatio,
|
||||
h5Width: 450,
|
||||
}
|
||||
|
||||
let targetUnit
|
||||
|
||||
module.exports = postcss.plugin('postcss-editorto', function (options) {
|
||||
options = Object.assign(DEFAULT_WEAPP_OPTIONS, options || {})
|
||||
|
||||
switch (options.platform) {
|
||||
case 'weapp': {
|
||||
// pc editor px (450 based) => weapp rpx (750 based)
|
||||
options.rootValue = (options.h5Width / options.designWidth) * (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) {
|
||||
const filePath = css.source.input.file;
|
||||
|
||||
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
|
||||
})
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
NODE_ENV: '"production"',
|
||||
},
|
||||
defineConstants: {
|
||||
// PagePlug 接口地址
|
||||
API_BASE_URL: '""',
|
||||
// 默认应用ID
|
||||
DEFAULT_APP: '""',
|
||||
},
|
||||
mini: {},
|
||||
h5: {
|
||||
/**
|
||||
* 如果h5端编译后体积过大,可以使用webpack-bundle-analyzer插件对打包体积进行分析。
|
||||
* 参考代码如下:
|
||||
* webpackChain (chain) {
|
||||
* chain.plugin('analyzer')
|
||||
* .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
|
||||
* }
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
declare module "*.png";
|
||||
declare module "*.gif";
|
||||
declare module "*.jpg";
|
||||
declare module "*.jpeg";
|
||||
declare module "*.svg";
|
||||
declare module "*.css";
|
||||
declare module "*.less";
|
||||
declare module "*.scss";
|
||||
declare module "*.sass";
|
||||
declare module "*.styl";
|
||||
|
||||
// @ts-ignore
|
||||
declare const process: {
|
||||
env: {
|
||||
TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq' | 'jd';
|
||||
[key: string]: any;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// linaria 配置详见 https://github.com/callstack/linaria/blob/master/docs/CONFIGURATION.md#options
|
||||
module.exports = {
|
||||
rules: [
|
||||
{
|
||||
action: require("linaria/evaluators").shaker,
|
||||
},
|
||||
{
|
||||
test: /node_modules[\/\\](?!@tarojs|@taroify)/,
|
||||
action: "ignore"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
{
|
||||
"name": "b_d_m",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "PagePlug 跨端展示",
|
||||
"templateInfo": {
|
||||
"name": "redux",
|
||||
"typescript": true,
|
||||
"css": "less"
|
||||
},
|
||||
"scripts": {
|
||||
"build:weapp": "taro build --type weapp",
|
||||
"build:swan": "taro build --type swan",
|
||||
"build:alipay": "taro build --type alipay",
|
||||
"build:tt": "taro build --type tt",
|
||||
"build:h5": "taro build --type h5",
|
||||
"build:rn": "taro build --type rn",
|
||||
"build:qq": "taro build --type qq",
|
||||
"build:jd": "taro build --type jd",
|
||||
"build:quickapp": "taro build --type quickapp",
|
||||
"dev:weapp": "npm run build:weapp -- --watch",
|
||||
"dev:swan": "npm run build:swan -- --watch",
|
||||
"dev:alipay": "npm run build:alipay -- --watch",
|
||||
"dev:tt": "npm run build:tt -- --watch",
|
||||
"dev:h5": "npm run build:h5 -- --watch",
|
||||
"dev:rn": "npm run build:rn -- --watch",
|
||||
"dev:qq": "npm run build:qq -- --watch",
|
||||
"dev:jd": "npm run build:jd -- --watch",
|
||||
"dev:quickapp": "npm run build:quickapp -- --watch"
|
||||
},
|
||||
"browserslist": [
|
||||
"last 3 versions",
|
||||
"Android >= 4.1",
|
||||
"ios >= 8"
|
||||
],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@manaflair/redux-batch": "^1.0.0",
|
||||
"@taroify/core": "0.0.28-alpha.1",
|
||||
"@tarojs/components": "3.3.12",
|
||||
"@tarojs/plugin-html": "3.3.12",
|
||||
"@tarojs/react": "3.3.12",
|
||||
"@tarojs/runtime": "3.3.12",
|
||||
"@tarojs/taro": "3.3.12",
|
||||
"@types/deep-diff": "^1.0.1",
|
||||
"@types/downloadjs": "^1.4.2",
|
||||
"@types/jshint": "^2.12.1",
|
||||
"@types/nanoid": "^3.0.0",
|
||||
"@types/toposort": "^2.0.3",
|
||||
"astring": "^1.7.5",
|
||||
"clsx": "^1.1.1",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"dayjs": "^1.10.7",
|
||||
"deep-diff": "^1.0.2",
|
||||
"downloadjs": "^1.4.7",
|
||||
"eval5": "^1.4.7",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-xml-parser": "^3.21.1",
|
||||
"fuse.js": "^6.4.6",
|
||||
"immer": "^9.0.6",
|
||||
"jshint": "^2.13.1",
|
||||
"linaria": "^3.0.0-beta.17",
|
||||
"lodash": "^4.17.21",
|
||||
"loglevel": "^1.7.1",
|
||||
"nanoid": "^3.1.30",
|
||||
"node-forge": "^0.10.0",
|
||||
"normalizr": "^3.6.1",
|
||||
"path-to-regexp": "^6.2.0",
|
||||
"react": "^17.0.0",
|
||||
"react-dom": "^17.0.0",
|
||||
"react-redux": "^7.2.0",
|
||||
"redux": "^4.0.0",
|
||||
"redux-form": "^8.3.7",
|
||||
"redux-logger": "^3.0.6",
|
||||
"redux-saga": "^1.1.3",
|
||||
"reselect": "^4.1.2",
|
||||
"shallowequal": "^1.1.0",
|
||||
"taro-axios": "^1.1.1",
|
||||
"tinycolor2": "^1.4.2",
|
||||
"toposort": "^2.0.2",
|
||||
"unescape-js": "^1.1.4",
|
||||
"url-search-params-polyfill": "^8.1.1",
|
||||
"worker-loader": "^3.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.8.0",
|
||||
"@tarojs/mini-runner": "3.3.12",
|
||||
"@tarojs/plugin-sass": "^2.2.10",
|
||||
"@tarojs/webpack-runner": "3.3.12",
|
||||
"@types/react": "^17.0.2",
|
||||
"@types/webpack-env": "^1.13.6",
|
||||
"@typescript-eslint/eslint-plugin": "^4.15.1",
|
||||
"@typescript-eslint/parser": "^4.15.1",
|
||||
"babel-plugin-import": "^1.13.3",
|
||||
"babel-preset-taro": "3.3.12",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-taro": "3.3.12",
|
||||
"eslint-plugin-import": "^2.12.0",
|
||||
"eslint-plugin-react": "^7.8.2",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"lodash-webpack-plugin": "^0.11.6",
|
||||
"redux-devtools-extension": "^2.13.9",
|
||||
"stylelint": "9.3.0",
|
||||
"terser-webpack-plugin": "4",
|
||||
"typescript": "^4.1.0",
|
||||
"webpack-bundle-analyzer": "^4.5.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"miniprogramRoot": "dist/",
|
||||
"projectname": "b_d_m",
|
||||
"description": "PagePlug 跨端展示",
|
||||
"appid": "",
|
||||
"setting": {
|
||||
"urlCheck": false,
|
||||
"es6": false,
|
||||
"enhance": false,
|
||||
"postcss": false,
|
||||
"preloadBackgroundData": false,
|
||||
"minified": true,
|
||||
"newFeature": false,
|
||||
"coverView": true,
|
||||
"nodeModules": false,
|
||||
"autoAudits": false,
|
||||
"showShadowRootInWxmlPanel": true,
|
||||
"scopeDataCheck": false,
|
||||
"uglifyFileName": false,
|
||||
"checkInvalidKey": true,
|
||||
"checkSiteMap": true,
|
||||
"uploadWithSourceMap": true,
|
||||
"compileHotReLoad": false,
|
||||
"lazyloadPlaceholderEnable": false,
|
||||
"useMultiFrameRuntime": true,
|
||||
"useApiHook": true,
|
||||
"useApiHostProcess": true,
|
||||
"babelSetting": {
|
||||
"ignore": [],
|
||||
"disablePlugins": [],
|
||||
"outputPath": ""
|
||||
},
|
||||
"useIsolateContext": true,
|
||||
"userConfirmedBundleSwitch": false,
|
||||
"packNpmManually": false,
|
||||
"packNpmRelationList": [],
|
||||
"minifyWXSS": true,
|
||||
"disableUseStrict": false,
|
||||
"minifyWXML": true,
|
||||
"showES6CompileOption": false,
|
||||
"useCompilerPlugins": false,
|
||||
"ignoreUploadUnusedFiles": true
|
||||
},
|
||||
"compileType": "miniprogram",
|
||||
"libVersion": "2.21.0",
|
||||
"condition": {}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"setting": {},
|
||||
"condition": {
|
||||
"plugin": {
|
||||
"list": []
|
||||
},
|
||||
"game": {
|
||||
"list": []
|
||||
},
|
||||
"gamePlugin": {
|
||||
"list": []
|
||||
},
|
||||
"miniprogram": {
|
||||
"list": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"miniprogramRoot": "./",
|
||||
"projectname": "b_d_m",
|
||||
"description": "PagePlug 跨端展示",
|
||||
"appid": "touristappid",
|
||||
"setting": {
|
||||
"urlCheck": true,
|
||||
"es6": false,
|
||||
"postcss": false,
|
||||
"minified": false
|
||||
},
|
||||
"compileType": "miniprogram"
|
||||
}
|
||||
|
|
@ -0,0 +1,300 @@
|
|||
import { PaginationField, ActionResponse } from "api/ActionAPI";
|
||||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxAction,
|
||||
ReduxActionErrorTypes,
|
||||
EvaluationReduxAction,
|
||||
ReduxActionWithoutPayload,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { Action } from "entities/Action";
|
||||
import { batchAction } from "actions/batchActions";
|
||||
|
||||
export const createActionRequest = (payload: Partial<Action>) => {
|
||||
return {
|
||||
type: ReduxActionTypes.CREATE_ACTION_INIT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const createActionSuccess = (payload: Action) => {
|
||||
return {
|
||||
type: ReduxActionTypes.CREATE_ACTION_SUCCESS,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export type FetchActionsPayload = {
|
||||
applicationId: string;
|
||||
};
|
||||
|
||||
export const fetchActions = (
|
||||
applicationId: string,
|
||||
postEvalActions: Array<ReduxAction<unknown> | ReduxActionWithoutPayload>,
|
||||
): EvaluationReduxAction<unknown> => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_ACTIONS_INIT,
|
||||
payload: { applicationId },
|
||||
postEvalActions,
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchActionsForView = (
|
||||
applicationId: string,
|
||||
): ReduxAction<FetchActionsPayload> => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_ACTIONS_VIEW_MODE_INIT,
|
||||
payload: { applicationId },
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchActionsForPage = (
|
||||
pageId: string,
|
||||
postEvalActions: Array<ReduxAction<unknown> | ReduxActionWithoutPayload> = [],
|
||||
): EvaluationReduxAction<unknown> => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_ACTIONS_FOR_PAGE_INIT,
|
||||
payload: { pageId },
|
||||
postEvalActions,
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchActionsForPageSuccess = (
|
||||
actions: Action[],
|
||||
postEvalActions?: Array<ReduxAction<unknown> | ReduxActionWithoutPayload>,
|
||||
): EvaluationReduxAction<unknown> => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_ACTIONS_FOR_PAGE_SUCCESS,
|
||||
payload: actions,
|
||||
postEvalActions,
|
||||
};
|
||||
};
|
||||
|
||||
export const setActionTabsInitialIndex = (index: number) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_ACTION_TABS_INITIAL_INDEX,
|
||||
payload: index,
|
||||
};
|
||||
};
|
||||
|
||||
export const runActionViaShortcut = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.RUN_ACTION_SHORTCUT_REQUEST,
|
||||
};
|
||||
};
|
||||
|
||||
export const runAction = (id: string, paginationField?: PaginationField) => {
|
||||
return {
|
||||
type: ReduxActionTypes.RUN_ACTION_REQUEST,
|
||||
payload: {
|
||||
id,
|
||||
paginationField,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const runActionInit = (
|
||||
id: string,
|
||||
paginationField?: PaginationField,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.RUN_ACTION_INIT,
|
||||
payload: {
|
||||
id,
|
||||
paginationField,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const showRunActionConfirmModal = (show: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SHOW_RUN_ACTION_CONFIRM_MODAL,
|
||||
payload: show,
|
||||
};
|
||||
};
|
||||
|
||||
export const cancelRunActionConfirmModal = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.CANCEL_RUN_ACTION_CONFIRM_MODAL,
|
||||
};
|
||||
};
|
||||
|
||||
export const acceptRunActionConfirmModal = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.ACCEPT_RUN_ACTION_CONFIRM_MODAL,
|
||||
};
|
||||
};
|
||||
|
||||
export const updateAction = (payload: { id: string }) => {
|
||||
return batchAction({
|
||||
type: ReduxActionTypes.UPDATE_ACTION_INIT,
|
||||
payload,
|
||||
});
|
||||
};
|
||||
|
||||
export const updateActionSuccess = (payload: { data: Action }) => {
|
||||
return {
|
||||
type: ReduxActionTypes.UPDATE_ACTION_SUCCESS,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const deleteAction = (payload: {
|
||||
id: string;
|
||||
name: string;
|
||||
onSuccess?: () => void;
|
||||
}) => {
|
||||
return {
|
||||
type: ReduxActionTypes.DELETE_ACTION_INIT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const deleteActionSuccess = (payload: { id: string }) => {
|
||||
return {
|
||||
type: ReduxActionTypes.DELETE_ACTION_SUCCESS,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const moveActionRequest = (payload: {
|
||||
id: string;
|
||||
destinationPageId: string;
|
||||
originalPageId: string;
|
||||
name: string;
|
||||
}) => {
|
||||
return {
|
||||
type: ReduxActionTypes.MOVE_ACTION_INIT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const moveActionSuccess = (payload: Action) => {
|
||||
return {
|
||||
type: ReduxActionTypes.MOVE_ACTION_SUCCESS,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const moveActionError = (payload: {
|
||||
id: string;
|
||||
originalPageId: string;
|
||||
}) => {
|
||||
return {
|
||||
type: ReduxActionErrorTypes.MOVE_ACTION_ERROR,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const copyActionRequest = (payload: {
|
||||
id: string;
|
||||
destinationPageId: string;
|
||||
name: string;
|
||||
}) => {
|
||||
return {
|
||||
type: ReduxActionTypes.COPY_ACTION_INIT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const copyActionSuccess = (payload: Action) => {
|
||||
return {
|
||||
type: ReduxActionTypes.COPY_ACTION_SUCCESS,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const copyActionError = (payload: {
|
||||
id: string;
|
||||
destinationPageId: string;
|
||||
}) => {
|
||||
return {
|
||||
type: ReduxActionErrorTypes.COPY_ACTION_ERROR,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const executeApiActionRequest = (payload: { id: string }) => ({
|
||||
type: ReduxActionTypes.EXECUTE_API_ACTION_REQUEST,
|
||||
payload: payload,
|
||||
});
|
||||
|
||||
export const executeApiActionSuccess = (payload: {
|
||||
id: string;
|
||||
response: ActionResponse;
|
||||
isPageLoad?: boolean;
|
||||
}) => ({
|
||||
type: ReduxActionTypes.EXECUTE_API_ACTION_SUCCESS,
|
||||
payload: payload,
|
||||
});
|
||||
|
||||
export const saveActionName = (payload: { id: string; name: string }) => ({
|
||||
type: ReduxActionTypes.SAVE_ACTION_NAME_INIT,
|
||||
payload: payload,
|
||||
});
|
||||
|
||||
export type SetActionPropertyPayload = {
|
||||
actionId: string;
|
||||
propertyName: string;
|
||||
value: any;
|
||||
};
|
||||
|
||||
export const setActionProperty = (payload: SetActionPropertyPayload) => ({
|
||||
type: ReduxActionTypes.SET_ACTION_PROPERTY,
|
||||
payload,
|
||||
});
|
||||
|
||||
export type UpdateActionPropertyActionPayload = {
|
||||
id: string;
|
||||
field: string;
|
||||
value: any;
|
||||
};
|
||||
|
||||
export const updateActionProperty = (
|
||||
payload: UpdateActionPropertyActionPayload,
|
||||
) => {
|
||||
return batchAction({
|
||||
type: ReduxActionTypes.UPDATE_ACTION_PROPERTY,
|
||||
payload,
|
||||
});
|
||||
};
|
||||
|
||||
export const executePageLoadActionsComplete = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.EXECUTE_PAGE_LOAD_ACTIONS_COMPLETE,
|
||||
};
|
||||
};
|
||||
|
||||
export const setActionsToExecuteOnPageLoad = (
|
||||
actions: Array<{
|
||||
executeOnLoad: boolean;
|
||||
id: string;
|
||||
name: string;
|
||||
}>,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_ACTION_TO_EXECUTE_ON_PAGELOAD,
|
||||
payload: actions,
|
||||
};
|
||||
};
|
||||
|
||||
export const bindDataOnCanvas = (payload: {
|
||||
queryId: string;
|
||||
applicationId: string;
|
||||
pageId: string;
|
||||
}) => {
|
||||
return {
|
||||
type: ReduxActionTypes.BIND_DATA_ON_CANVAS,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export default {
|
||||
createAction: createActionRequest,
|
||||
fetchActions,
|
||||
runAction: runAction,
|
||||
deleteAction,
|
||||
deleteActionSuccess,
|
||||
updateAction,
|
||||
updateActionSuccess,
|
||||
bindDataOnCanvas,
|
||||
};
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
import { ReduxAction, ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { EventLocation } from "utils/AnalyticsUtil";
|
||||
import { ApiContentTypes } from "constants/ApiEditorConstants";
|
||||
|
||||
export const changeApi = (
|
||||
id: string,
|
||||
isSaas: boolean,
|
||||
newApi?: boolean,
|
||||
): ReduxAction<{ id: string; isSaas: boolean; newApi?: boolean }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.API_PANE_CHANGE_API,
|
||||
payload: { id, isSaas, newApi },
|
||||
};
|
||||
};
|
||||
|
||||
export const initApiPane = (urlId?: string): ReduxAction<{ id?: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.INIT_API_PANE,
|
||||
payload: { id: urlId },
|
||||
};
|
||||
};
|
||||
|
||||
export const setCurrentCategory = (
|
||||
category: string,
|
||||
): ReduxAction<{ category: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_CURRENT_CATEGORY,
|
||||
payload: { category },
|
||||
};
|
||||
};
|
||||
|
||||
export const setLastUsedEditorPage = (
|
||||
path: string,
|
||||
): ReduxAction<{ path: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_LAST_USED_EDITOR_PAGE,
|
||||
payload: { path },
|
||||
};
|
||||
};
|
||||
|
||||
export const setLastSelectedPage = (
|
||||
selectedPageId: string,
|
||||
): ReduxAction<{ selectedPageId: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_LAST_SELECTED_PAGE_PAGE,
|
||||
payload: { selectedPageId },
|
||||
};
|
||||
};
|
||||
|
||||
export const createNewApiAction = (
|
||||
pageId: string,
|
||||
from: EventLocation,
|
||||
): ReduxAction<{ pageId: string; from: EventLocation }> => ({
|
||||
type: ReduxActionTypes.CREATE_NEW_API_ACTION,
|
||||
payload: { pageId, from },
|
||||
});
|
||||
|
||||
export const createNewQueryAction = (
|
||||
pageId: string,
|
||||
from: EventLocation,
|
||||
): ReduxAction<{ pageId: string; from: EventLocation }> => ({
|
||||
type: ReduxActionTypes.CREATE_NEW_QUERY_ACTION,
|
||||
payload: { pageId, from },
|
||||
});
|
||||
|
||||
export const updateBodyContentType = (
|
||||
title: ApiContentTypes,
|
||||
apiId: string,
|
||||
): ReduxAction<{ title: ApiContentTypes; apiId: string }> => ({
|
||||
type: ReduxActionTypes.UPDATE_API_ACTION_BODY_CONTENT_TYPE,
|
||||
payload: { title, apiId },
|
||||
});
|
||||
|
||||
export const redirectToNewIntegrations = (
|
||||
applicationId: string,
|
||||
pageId: string,
|
||||
params?: any,
|
||||
): ReduxAction<{ applicationId: string; pageId: string; params: any }> => ({
|
||||
type: ReduxActionTypes.REDIRECT_TO_NEW_INTEGRATIONS,
|
||||
payload: { applicationId, pageId, params },
|
||||
});
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
import { ReduxAction, ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { APP_MODE } from "entities/App";
|
||||
import {
|
||||
UpdateApplicationPayload,
|
||||
ImportApplicationRequest,
|
||||
} from "api/ApplicationApi";
|
||||
|
||||
export const setDefaultApplicationPageSuccess = (
|
||||
pageId: string,
|
||||
applicationId: string,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_DEFAULT_APPLICATION_PAGE_SUCCESS,
|
||||
payload: {
|
||||
pageId,
|
||||
applicationId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export interface FetchApplicationPayload {
|
||||
applicationId: string;
|
||||
mode: APP_MODE;
|
||||
}
|
||||
|
||||
export const fetchApplication = (
|
||||
applicationId: string,
|
||||
mode: APP_MODE,
|
||||
): ReduxAction<FetchApplicationPayload> => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_APPLICATION_INIT,
|
||||
payload: {
|
||||
applicationId,
|
||||
mode,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const updateApplicationLayout = (
|
||||
id: string,
|
||||
data: UpdateApplicationPayload,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.UPDATE_APP_LAYOUT,
|
||||
payload: {
|
||||
id,
|
||||
...data,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const updateApplication = (
|
||||
id: string,
|
||||
data: UpdateApplicationPayload,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.UPDATE_APPLICATION,
|
||||
payload: {
|
||||
id,
|
||||
...data,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const publishApplication = (applicationId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.PUBLISH_APPLICATION_INIT,
|
||||
payload: {
|
||||
applicationId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const duplicateApplication = (applicationId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.DUPLICATE_APPLICATION_INIT,
|
||||
payload: {
|
||||
applicationId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const importApplication = (appDetails: ImportApplicationRequest) => {
|
||||
return {
|
||||
type: ReduxActionTypes.IMPORT_APPLICATION_INIT,
|
||||
payload: appDetails,
|
||||
};
|
||||
};
|
||||
|
||||
export const getAllApplications = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.GET_ALL_APPLICATION_INIT,
|
||||
};
|
||||
};
|
||||
|
||||
export const resetCurrentApplication = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.RESET_CURRENT_APPLICATION,
|
||||
};
|
||||
};
|
||||
|
||||
export const setShowAppInviteUsersDialog = (payload: boolean) => ({
|
||||
type: ReduxActionTypes.SET_SHOW_APP_INVITE_USERS_MODAL,
|
||||
payload,
|
||||
});
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
|
||||
export const getCurrentUser = () => ({
|
||||
type: ReduxActionTypes.FETCH_USER_INIT,
|
||||
});
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { ReduxAction, ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
|
||||
export const batchAction = (action: ReduxAction<any>) => ({
|
||||
type: ReduxActionTypes.BATCHED_UPDATE,
|
||||
payload: action,
|
||||
});
|
||||
|
||||
export type BatchAction<T> = ReduxAction<ReduxAction<T>>;
|
||||
|
||||
export const batchActionSuccess = (actions: ReduxAction<any>[]) => ({
|
||||
type: ReduxActionTypes.BATCH_UPDATES_SUCCESS,
|
||||
payload: actions,
|
||||
});
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
|
||||
export const fetchImportedCollections = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_IMPORTED_COLLECTIONS_INIT,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
import { ReduxActionTypes, ReduxAction } from "constants/ReduxActionConstants";
|
||||
import { RenderMode } from "constants/WidgetConstants";
|
||||
import { DynamicPath } from "utils/DynamicBindingUtils";
|
||||
|
||||
export const updateWidgetPropertyRequest = (
|
||||
widgetId: string,
|
||||
propertyPath: string,
|
||||
propertyValue: any,
|
||||
renderMode: RenderMode,
|
||||
): ReduxAction<UpdateWidgetPropertyRequestPayload> => {
|
||||
return {
|
||||
type: ReduxActionTypes.UPDATE_WIDGET_PROPERTY_REQUEST,
|
||||
payload: {
|
||||
widgetId,
|
||||
propertyPath,
|
||||
propertyValue,
|
||||
renderMode,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export interface BatchPropertyUpdatePayload {
|
||||
modify?: Record<string, unknown>; //Key value pairs of paths and values to update
|
||||
remove?: string[]; //Array of paths to delete
|
||||
triggerPaths?: string[]; // Array of paths in the modify and remove list which are trigger paths
|
||||
}
|
||||
|
||||
export const batchUpdateWidgetProperty = (
|
||||
widgetId: string,
|
||||
updates: BatchPropertyUpdatePayload,
|
||||
): ReduxAction<UpdateWidgetPropertyPayload> => ({
|
||||
type: ReduxActionTypes.BATCH_UPDATE_WIDGET_PROPERTY,
|
||||
payload: {
|
||||
widgetId,
|
||||
updates,
|
||||
},
|
||||
});
|
||||
|
||||
export const deleteWidgetProperty = (
|
||||
widgetId: string,
|
||||
propertyPaths: string[],
|
||||
): ReduxAction<DeleteWidgetPropertyPayload> => ({
|
||||
type: ReduxActionTypes.DELETE_WIDGET_PROPERTY,
|
||||
payload: {
|
||||
widgetId,
|
||||
propertyPaths,
|
||||
},
|
||||
});
|
||||
|
||||
export const setWidgetDynamicProperty = (
|
||||
widgetId: string,
|
||||
propertyPath: string,
|
||||
isDynamic: boolean,
|
||||
): ReduxAction<SetWidgetDynamicPropertyPayload> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_WIDGET_DYNAMIC_PROPERTY,
|
||||
payload: {
|
||||
widgetId,
|
||||
propertyPath,
|
||||
isDynamic,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export interface UpdateWidgetPropertyRequestPayload {
|
||||
widgetId: string;
|
||||
propertyPath: string;
|
||||
propertyValue: any;
|
||||
renderMode: RenderMode;
|
||||
}
|
||||
|
||||
export interface UpdateWidgetPropertyPayload {
|
||||
widgetId: string;
|
||||
updates: BatchPropertyUpdatePayload;
|
||||
dynamicUpdates?: {
|
||||
dynamicBindingPathList: DynamicPath[];
|
||||
dynamicTriggerPathList: DynamicPath[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface UpdateCanvasLayout {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface SetWidgetDynamicPropertyPayload {
|
||||
widgetId: string;
|
||||
propertyPath: string;
|
||||
isDynamic: boolean;
|
||||
}
|
||||
|
||||
export interface DeleteWidgetPropertyPayload {
|
||||
widgetId: string;
|
||||
propertyPaths: string[];
|
||||
}
|
||||
|
|
@ -0,0 +1,239 @@
|
|||
import {
|
||||
ReduxAction,
|
||||
ReduxActionTypes,
|
||||
ReduxActionWithCallbacks,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { CreateDatasourceConfig } from "api/DatasourcesApi";
|
||||
import { Datasource } from "entities/Datasource";
|
||||
import { PluginType } from "entities/Action";
|
||||
import { executeDatasourceQueryRequest } from "../api/DatasourcesApi";
|
||||
import { ResponseMeta } from "../api/ApiResponses";
|
||||
|
||||
export const createDatasourceFromForm = (payload: CreateDatasourceConfig) => {
|
||||
return {
|
||||
type: ReduxActionTypes.CREATE_DATASOURCE_FROM_FORM_INIT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const updateDatasource = (
|
||||
payload: Datasource,
|
||||
onSuccess?: ReduxAction<unknown>,
|
||||
onError?: ReduxAction<unknown>,
|
||||
): ReduxActionWithCallbacks<Datasource, unknown, unknown> => {
|
||||
return {
|
||||
type: ReduxActionTypes.UPDATE_DATASOURCE_INIT,
|
||||
payload,
|
||||
onSuccess,
|
||||
onError,
|
||||
};
|
||||
};
|
||||
|
||||
export type UpdateDatasourceSuccessAction = {
|
||||
type: string;
|
||||
payload: Datasource;
|
||||
redirect: boolean;
|
||||
queryParams?: Record<string, string>;
|
||||
};
|
||||
|
||||
export const updateDatasourceSuccess = (
|
||||
payload: Datasource,
|
||||
redirect = true,
|
||||
queryParams = {},
|
||||
): UpdateDatasourceSuccessAction => ({
|
||||
type: ReduxActionTypes.UPDATE_DATASOURCE_SUCCESS,
|
||||
payload,
|
||||
redirect,
|
||||
queryParams,
|
||||
});
|
||||
|
||||
export const redirectAuthorizationCode = (
|
||||
pageId: string,
|
||||
datasourceId: string,
|
||||
pluginType: PluginType,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.REDIRECT_AUTHORIZATION_CODE,
|
||||
payload: {
|
||||
pageId,
|
||||
datasourceId,
|
||||
pluginType,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchDatasourceStructure = (id: string, ignoreCache?: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_DATASOURCE_STRUCTURE_INIT,
|
||||
payload: {
|
||||
id,
|
||||
ignoreCache,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const expandDatasourceEntity = (id: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.EXPAND_DATASOURCE_ENTITY,
|
||||
payload: id,
|
||||
};
|
||||
};
|
||||
|
||||
export const refreshDatasourceStructure = (id: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.REFRESH_DATASOURCE_STRUCTURE_INIT,
|
||||
payload: {
|
||||
id,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const saveDatasourceName = (payload: { id: string; name: string }) => ({
|
||||
type: ReduxActionTypes.SAVE_DATASOURCE_NAME,
|
||||
payload: payload,
|
||||
});
|
||||
|
||||
export const changeDatasource = (payload: Datasource) => {
|
||||
return {
|
||||
type: ReduxActionTypes.CHANGE_DATASOURCE,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const switchDatasource = (id: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SWITCH_DATASOURCE,
|
||||
payload: { datasourceId: id },
|
||||
};
|
||||
};
|
||||
|
||||
export const testDatasource = (payload: Partial<Datasource>) => {
|
||||
return {
|
||||
type: ReduxActionTypes.TEST_DATASOURCE_INIT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const deleteDatasource = (
|
||||
payload: Partial<Datasource>,
|
||||
onSuccess?: ReduxAction<unknown>,
|
||||
onError?: ReduxAction<unknown>,
|
||||
onSuccessCallback?: () => void,
|
||||
): ReduxActionWithCallbacks<Partial<Datasource>, unknown, unknown> => {
|
||||
return {
|
||||
type: ReduxActionTypes.DELETE_DATASOURCE_INIT,
|
||||
payload,
|
||||
onSuccess,
|
||||
onError,
|
||||
onSuccessCallback,
|
||||
};
|
||||
};
|
||||
|
||||
export const setDatsourceEditorMode = (payload: {
|
||||
id: string;
|
||||
viewMode: boolean;
|
||||
}) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_DATASOURCE_EDITOR_MODE,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchDatasources = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_DATASOURCES_INIT,
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchMockDatasources = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_MOCK_DATASOURCES_INIT,
|
||||
};
|
||||
};
|
||||
|
||||
export interface addMockRequest
|
||||
extends ReduxAction<{
|
||||
name: string;
|
||||
organizationId: string;
|
||||
pluginId: string;
|
||||
packageName: string;
|
||||
isGeneratePageMode?: string;
|
||||
}> {
|
||||
extraParams?: any;
|
||||
}
|
||||
|
||||
export const addMockDatasourceToOrg = (
|
||||
name: string,
|
||||
organizationId: string,
|
||||
pluginId: string,
|
||||
packageName: string,
|
||||
isGeneratePageMode?: string,
|
||||
): addMockRequest => {
|
||||
return {
|
||||
type: ReduxActionTypes.ADD_MOCK_DATASOURCES_INIT,
|
||||
payload: { name, packageName, pluginId, organizationId },
|
||||
extraParams: { isGeneratePageMode },
|
||||
};
|
||||
};
|
||||
|
||||
export const initDatasourcePane = (
|
||||
pluginType: string,
|
||||
urlId?: string,
|
||||
): ReduxAction<{ pluginType: string; id?: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.INIT_DATASOURCE_PANE,
|
||||
payload: { id: urlId, pluginType },
|
||||
};
|
||||
};
|
||||
|
||||
export const storeAsDatasource = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.STORE_AS_DATASOURCE_INIT,
|
||||
};
|
||||
};
|
||||
|
||||
export const getOAuthAccessToken = (datasourceId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SAAS_GET_OAUTH_ACCESS_TOKEN,
|
||||
payload: { datasourceId },
|
||||
};
|
||||
};
|
||||
|
||||
export type executeDatasourceQuerySuccessPayload = {
|
||||
responseMeta: ResponseMeta;
|
||||
data: {
|
||||
body: Array<{ id: string; name: string }>;
|
||||
headers: Record<string, string[]>;
|
||||
statusCode: string;
|
||||
isExecutionSuccess: boolean;
|
||||
};
|
||||
};
|
||||
type errorPayload = unknown;
|
||||
|
||||
export type executeDatasourceQueryReduxAction = ReduxActionWithCallbacks<
|
||||
executeDatasourceQueryRequest,
|
||||
executeDatasourceQuerySuccessPayload,
|
||||
errorPayload
|
||||
>;
|
||||
|
||||
export const executeDatasourceQuery = ({
|
||||
onErrorCallback,
|
||||
onSuccessCallback,
|
||||
payload,
|
||||
}: {
|
||||
onErrorCallback?: (payload: errorPayload) => void;
|
||||
onSuccessCallback?: (payload: executeDatasourceQuerySuccessPayload) => void;
|
||||
payload: executeDatasourceQueryRequest;
|
||||
}): executeDatasourceQueryReduxAction => {
|
||||
return {
|
||||
type: ReduxActionTypes.EXECUTE_DATASOURCE_QUERY_INIT,
|
||||
payload,
|
||||
onErrorCallback,
|
||||
onSuccessCallback,
|
||||
};
|
||||
};
|
||||
|
||||
export default {
|
||||
fetchDatasources,
|
||||
initDatasourcePane,
|
||||
};
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { Message, ENTITY_TYPE } from "entities/AppsmithConsole";
|
||||
import { EventName } from "utils/AnalyticsUtil";
|
||||
|
||||
export interface LogDebuggerErrorAnalyticsPayload {
|
||||
entityName: string;
|
||||
entityId: string;
|
||||
entityType: ENTITY_TYPE;
|
||||
eventName: EventName;
|
||||
propertyPath: string;
|
||||
errorMessages: { message: string }[];
|
||||
}
|
||||
|
||||
export const debuggerLogInit = (payload: Message) => ({
|
||||
type: ReduxActionTypes.DEBUGGER_LOG_INIT,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const debuggerLog = (payload: Message) => ({
|
||||
type: ReduxActionTypes.DEBUGGER_LOG,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const clearLogs = () => ({
|
||||
type: ReduxActionTypes.CLEAR_DEBUGGER_LOGS,
|
||||
});
|
||||
|
||||
export const showDebugger = (payload?: boolean) => ({
|
||||
type: ReduxActionTypes.SHOW_DEBUGGER,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const errorLog = (payload: Message) => ({
|
||||
type: ReduxActionTypes.DEBUGGER_ERROR_LOG,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const updateErrorLog = (payload: Message) => ({
|
||||
type: ReduxActionTypes.DEBUGGER_UPDATE_ERROR_LOG,
|
||||
payload,
|
||||
});
|
||||
|
||||
// Only used for analytics
|
||||
export const logDebuggerErrorAnalytics = (
|
||||
payload: LogDebuggerErrorAnalyticsPayload,
|
||||
) => ({
|
||||
type: ReduxActionTypes.DEBUGGER_ERROR_ANALYTICS,
|
||||
payload,
|
||||
});
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
|
||||
export const flushErrors = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.FLUSH_ERRORS,
|
||||
};
|
||||
};
|
||||
|
||||
export const flushErrorsAndRedirect = (url: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.FLUSH_AND_REDIRECT,
|
||||
payload: {
|
||||
url,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
import {
|
||||
ReduxAction,
|
||||
ReduxActionErrorTypes,
|
||||
ReduxActionTypes,
|
||||
} from "../constants/ReduxActionConstants";
|
||||
import _ from "lodash";
|
||||
import { DataTree } from "../entities/DataTree/dataTreeFactory";
|
||||
import { DependencyMap } from "../utils/DynamicBindingUtils";
|
||||
import { Diff } from "deep-diff";
|
||||
|
||||
export const FIRST_EVAL_REDUX_ACTIONS = [
|
||||
// Pages
|
||||
ReduxActionTypes.FETCH_PAGE_SUCCESS,
|
||||
ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS,
|
||||
];
|
||||
export const EVALUATE_REDUX_ACTIONS = [
|
||||
...FIRST_EVAL_REDUX_ACTIONS,
|
||||
// Actions
|
||||
ReduxActionTypes.FETCH_ACTIONS_SUCCESS,
|
||||
ReduxActionTypes.FETCH_PLUGIN_FORM_CONFIGS_SUCCESS,
|
||||
ReduxActionTypes.FETCH_ACTIONS_VIEW_MODE_SUCCESS,
|
||||
ReduxActionErrorTypes.FETCH_ACTIONS_ERROR,
|
||||
ReduxActionErrorTypes.FETCH_ACTIONS_VIEW_MODE_ERROR,
|
||||
ReduxActionTypes.FETCH_ACTIONS_FOR_PAGE_SUCCESS,
|
||||
ReduxActionTypes.SUBMIT_CURL_FORM_SUCCESS,
|
||||
ReduxActionTypes.CREATE_ACTION_SUCCESS,
|
||||
ReduxActionTypes.UPDATE_ACTION_PROPERTY,
|
||||
ReduxActionTypes.DELETE_ACTION_SUCCESS,
|
||||
ReduxActionTypes.COPY_ACTION_SUCCESS,
|
||||
ReduxActionTypes.MOVE_ACTION_SUCCESS,
|
||||
ReduxActionTypes.RUN_ACTION_SUCCESS,
|
||||
ReduxActionErrorTypes.RUN_ACTION_ERROR,
|
||||
ReduxActionTypes.EXECUTE_API_ACTION_SUCCESS,
|
||||
ReduxActionErrorTypes.EXECUTE_ACTION_ERROR,
|
||||
// App Data
|
||||
ReduxActionTypes.SET_APP_MODE,
|
||||
ReduxActionTypes.FETCH_USER_DETAILS_SUCCESS,
|
||||
ReduxActionTypes.UPDATE_APP_PERSISTENT_STORE,
|
||||
ReduxActionTypes.UPDATE_APP_TRANSIENT_STORE,
|
||||
// Widgets
|
||||
ReduxActionTypes.UPDATE_LAYOUT,
|
||||
ReduxActionTypes.UPDATE_WIDGET_PROPERTY,
|
||||
ReduxActionTypes.UPDATE_WIDGET_NAME_SUCCESS,
|
||||
// Widget Meta
|
||||
ReduxActionTypes.SET_META_PROP,
|
||||
ReduxActionTypes.RESET_WIDGET_META,
|
||||
// Batches
|
||||
ReduxActionTypes.BATCH_UPDATES_SUCCESS,
|
||||
];
|
||||
export const shouldProcessBatchedAction = (action: ReduxAction<unknown>) => {
|
||||
if (
|
||||
action.type === ReduxActionTypes.BATCH_UPDATES_SUCCESS &&
|
||||
Array.isArray(action.payload)
|
||||
) {
|
||||
const batchedActionTypes = action.payload.map(
|
||||
(batchedAction) => batchedAction.type,
|
||||
);
|
||||
return (
|
||||
_.intersection(EVALUATE_REDUX_ACTIONS, batchedActionTypes).length > 0
|
||||
);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
export const setEvaluatedTree = (
|
||||
dataTree: DataTree,
|
||||
updates: Diff<DataTree, DataTree>[],
|
||||
): ReduxAction<{ dataTree: DataTree; updates: Diff<DataTree, DataTree>[] }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_EVALUATED_TREE,
|
||||
payload: { dataTree, updates },
|
||||
};
|
||||
};
|
||||
|
||||
export const setDependencyMap = (
|
||||
inverseDependencyMap: DependencyMap,
|
||||
): ReduxAction<{ inverseDependencyMap: DependencyMap }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_EVALUATION_INVERSE_DEPENDENCY_MAP,
|
||||
payload: { inverseDependencyMap },
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
|
||||
export const initExplorerEntityNameEdit = (actionId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.INIT_EXPLORER_ENTITY_NAME_EDIT,
|
||||
payload: {
|
||||
id: actionId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
|
||||
export const setHelpDefaultRefinement = (payload: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_DEFAULT_REFINEMENT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
export const setHelpModalVisibility = (payload: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_HELP_MODAL_OPEN,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxAction,
|
||||
InitializeEditorPayload,
|
||||
} from "constants/ReduxActionConstants";
|
||||
|
||||
export const initEditor = (
|
||||
applicationId: string,
|
||||
pageId: string,
|
||||
queryParams: any,
|
||||
): ReduxAction<InitializeEditorPayload> => ({
|
||||
type: ReduxActionTypes.INITIALIZE_EDITOR,
|
||||
payload: {
|
||||
applicationId,
|
||||
pageId,
|
||||
queryParams,
|
||||
},
|
||||
});
|
||||
|
||||
export const resetEditorRequest = () => ({
|
||||
type: ReduxActionTypes.RESET_EDITOR_REQUEST,
|
||||
});
|
||||
|
||||
export const resetEditorSuccess = () => ({
|
||||
type: ReduxActionTypes.RESET_EDITOR_SUCCESS,
|
||||
});
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import { ReduxActionTypes, ReduxAction } from "constants/ReduxActionConstants";
|
||||
import { BatchAction, batchAction } from "actions/batchActions";
|
||||
|
||||
export interface UpdateWidgetMetaPropertyPayload {
|
||||
widgetId: string;
|
||||
propertyName: string;
|
||||
propertyValue: any;
|
||||
}
|
||||
export const updateWidgetMetaProperty = (
|
||||
widgetId: string,
|
||||
propertyName: string,
|
||||
propertyValue: any,
|
||||
): BatchAction<UpdateWidgetMetaPropertyPayload> => {
|
||||
return batchAction({
|
||||
type: ReduxActionTypes.SET_META_PROP,
|
||||
payload: {
|
||||
widgetId,
|
||||
propertyName,
|
||||
propertyValue,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const resetWidgetMetaProperty = (
|
||||
widgetId: string,
|
||||
): BatchAction<{ widgetId: string }> => {
|
||||
return batchAction({
|
||||
type: ReduxActionTypes.RESET_WIDGET_META,
|
||||
payload: {
|
||||
widgetId,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const resetChildrenMetaProperty = (
|
||||
widgetId: string,
|
||||
): ReduxAction<{ widgetId: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.RESET_CHILDREN_WIDGET_META,
|
||||
payload: {
|
||||
widgetId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { AppsmithNotification } from "entities/Notification";
|
||||
|
||||
export const fetchNotificationsRequest = (beforeTime?: string) => ({
|
||||
type: ReduxActionTypes.FETCH_NOTIFICATIONS_REQUEST,
|
||||
payload: beforeTime,
|
||||
});
|
||||
|
||||
export const fetchNotificationsSuccess = (payload: {
|
||||
notifications: Array<AppsmithNotification>;
|
||||
}) => ({
|
||||
type: ReduxActionTypes.FETCH_NOTIFICATIONS_SUCCESS,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const newNotificationEvent = (payload: Notification) => ({
|
||||
type: ReduxActionTypes.NEW_NOTIFICATION_EVENT,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const setIsNotificationsListVisible = (payload: boolean) => ({
|
||||
type: ReduxActionTypes.SET_IS_NOTIFICATIONS_LIST_VISIBLE,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const markAllNotificationsAsReadRequest = () => ({
|
||||
type: ReduxActionTypes.MARK_ALL_NOTIFICATIONS_AS_READ_REQUEST,
|
||||
});
|
||||
|
||||
export const markAllNotificationsAsReadSuccess = () => ({
|
||||
type: ReduxActionTypes.MARK_ALL_NOTIFICATIONS_AS_READ_SUCCESS,
|
||||
});
|
||||
|
||||
export const resetNotifications = (payload: {
|
||||
notifications: Array<AppsmithNotification>;
|
||||
}) => ({
|
||||
type: ReduxActionTypes.RESET_NOTIFICATIONS,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const fetchUnreadNotificationsCountRequest = () => ({
|
||||
type: ReduxActionTypes.FETCH_UNREAD_NOTIFICATIONS_COUNT_REQUEST,
|
||||
});
|
||||
|
||||
export const fetchUnreadNotificationsCountSuccess = (payload: number) => ({
|
||||
type: ReduxActionTypes.FETCH_UNREAD_NOTIFICATIONS_COUNT_SUCCESS,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const markNotificationAsReadRequest = (payload: string) => ({
|
||||
type: ReduxActionTypes.MARK_NOTIFICATION_AS_READ_REQUEST,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const markNotificationAsReadSuccess = (payload: string) => ({
|
||||
type: ReduxActionTypes.MARK_NOTIFICATION_AS_READ_SUCCESS,
|
||||
payload,
|
||||
});
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
import {
|
||||
OnboardingHelperConfig,
|
||||
OnboardingStep,
|
||||
} from "constants/OnboardingConstants";
|
||||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
|
||||
export const showIndicator = (payload: OnboardingStep) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SHOW_ONBOARDING_INDICATOR,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const endOnboarding = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.END_ONBOARDING,
|
||||
};
|
||||
};
|
||||
|
||||
export const setCurrentStep = (payload: number) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_CURRENT_STEP,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const setOnboardingState = (payload: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_ONBOARDING_STATE,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const showOnboardingHelper = (payload: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SHOW_ONBOARDING_HELPER,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const setHelperConfig = (payload: OnboardingHelperConfig) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_HELPER_CONFIG,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const setCurrentSubstep = (payload: number) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_ONBOARDING_SUBSTEP,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const showWelcomeHelper = (payload: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SHOW_ONBOARDING_WELCOME_HELPER,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const showOnboardingLoader = (payload: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SHOW_ONBOARDING_LOADER,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const showEndOnboardingHelper = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.SHOW_END_ONBOARDING_HELPER,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { SaveOrgLogo, SaveOrgRequest } from "api/OrgApi";
|
||||
|
||||
export const fetchOrg = (orgId: string, skipValidation?: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_CURRENT_ORG,
|
||||
payload: {
|
||||
orgId,
|
||||
skipValidation,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const changeOrgUserRole = (
|
||||
orgId: string,
|
||||
role: string,
|
||||
username: string,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.CHANGE_ORG_USER_ROLE_INIT,
|
||||
payload: {
|
||||
orgId,
|
||||
role,
|
||||
username,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const deleteOrgUser = (orgId: string, username: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.DELETE_ORG_USER_INIT,
|
||||
payload: {
|
||||
orgId,
|
||||
username,
|
||||
},
|
||||
};
|
||||
};
|
||||
export const fetchUsersForOrg = (orgId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_ALL_USERS_INIT,
|
||||
payload: {
|
||||
orgId,
|
||||
},
|
||||
};
|
||||
};
|
||||
export const fetchRolesForOrg = (orgId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_ALL_ROLES_INIT,
|
||||
payload: {
|
||||
orgId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const saveOrg = (orgSettings: SaveOrgRequest) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SAVE_ORG_INIT,
|
||||
payload: orgSettings,
|
||||
};
|
||||
};
|
||||
|
||||
export const uploadOrgLogo = (orgLogo: SaveOrgLogo) => {
|
||||
return {
|
||||
type: ReduxActionTypes.UPLOAD_ORG_LOGO,
|
||||
payload: orgLogo,
|
||||
};
|
||||
};
|
||||
|
||||
export const deleteOrgLogo = (id: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.REMOVE_ORG_LOGO,
|
||||
payload: {
|
||||
id: id,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,366 @@
|
|||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import {
|
||||
EvaluationReduxAction,
|
||||
ReduxAction,
|
||||
ReduxActionTypes,
|
||||
ReduxActionWithoutPayload,
|
||||
UpdateCanvasPayload,
|
||||
ReduxActionErrorTypes,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { WidgetOperation } from "widgets/BaseWidget";
|
||||
import { FetchPageRequest, PageLayout, SavePageResponse } from "api/PageApi";
|
||||
import { UrlDataState } from "reducers/entityReducers/appReducer";
|
||||
import { APP_MODE } from "entities/App";
|
||||
import { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
|
||||
import { GenerateTemplatePageRequest } from "../api/PageApi";
|
||||
import { WidgetReduxActionTypes } from "../constants/ReduxActionConstants";
|
||||
|
||||
export interface FetchPageListPayload {
|
||||
applicationId: string;
|
||||
mode: APP_MODE;
|
||||
}
|
||||
|
||||
export const fetchPageList = (
|
||||
applicationId: string,
|
||||
mode: APP_MODE
|
||||
): ReduxAction<FetchPageListPayload> => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_PAGE_LIST_INIT,
|
||||
payload: {
|
||||
applicationId,
|
||||
mode,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchPage = (
|
||||
pageId: string,
|
||||
isFirstLoad = false
|
||||
): ReduxAction<FetchPageRequest> => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_PAGE_INIT,
|
||||
payload: {
|
||||
id: pageId,
|
||||
isFirstLoad,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchPublishedPage = (
|
||||
pageId: string,
|
||||
bustCache = false,
|
||||
urlData?: UrlDataState
|
||||
) => ({
|
||||
type: ReduxActionTypes.FETCH_PUBLISHED_PAGE_INIT,
|
||||
payload: {
|
||||
pageId,
|
||||
bustCache,
|
||||
urlData,
|
||||
},
|
||||
});
|
||||
|
||||
export const fetchPageSuccess = (
|
||||
postEvalActions: Array<ReduxAction<unknown> | ReduxActionWithoutPayload>
|
||||
): EvaluationReduxAction<undefined> => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_PAGE_SUCCESS,
|
||||
postEvalActions,
|
||||
payload: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchPublishedPageSuccess = (
|
||||
postEvalActions: Array<ReduxAction<unknown> | ReduxActionWithoutPayload>
|
||||
): EvaluationReduxAction<undefined> => ({
|
||||
type: ReduxActionTypes.FETCH_PUBLISHED_PAGE_SUCCESS,
|
||||
postEvalActions,
|
||||
payload: undefined,
|
||||
});
|
||||
|
||||
export const updateCurrentPage = (id: string) => ({
|
||||
type: ReduxActionTypes.SWITCH_CURRENT_PAGE_ID,
|
||||
payload: { id },
|
||||
});
|
||||
|
||||
export const initCanvasLayout = (
|
||||
payload: UpdateCanvasPayload
|
||||
): ReduxAction<UpdateCanvasPayload> => {
|
||||
return {
|
||||
type: ReduxActionTypes.INIT_CANVAS_LAYOUT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const setLastUpdatedTime = (payload: number): ReduxAction<number> => ({
|
||||
type: ReduxActionTypes.SET_LAST_UPDATED_TIME,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const savePageSuccess = (payload: SavePageResponse) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SAVE_PAGE_SUCCESS,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const updateWidgetNameSuccess = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.UPDATE_WIDGET_NAME_SUCCESS,
|
||||
};
|
||||
};
|
||||
|
||||
export const deletePageSuccess = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.DELETE_PAGE_SUCCESS,
|
||||
};
|
||||
};
|
||||
|
||||
export const updateAndSaveLayout = (
|
||||
widgets: CanvasWidgetsReduxState,
|
||||
isRetry?: boolean
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.UPDATE_LAYOUT,
|
||||
payload: { widgets, isRetry },
|
||||
};
|
||||
};
|
||||
|
||||
export const saveLayout = (isRetry?: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SAVE_PAGE_INIT,
|
||||
payload: { isRetry },
|
||||
};
|
||||
};
|
||||
|
||||
export const createPage = (
|
||||
applicationId: string,
|
||||
pageName: string,
|
||||
layouts: Partial<PageLayout>[]
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.CREATE_PAGE_INIT,
|
||||
payload: {
|
||||
applicationId,
|
||||
name: pageName,
|
||||
layouts,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const clonePageInit = (pageId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.CLONE_PAGE_INIT,
|
||||
payload: {
|
||||
id: pageId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const clonePageSuccess = (
|
||||
pageId: string,
|
||||
pageName: string,
|
||||
layoutId: string
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.CLONE_PAGE_SUCCESS,
|
||||
payload: {
|
||||
pageId,
|
||||
pageName,
|
||||
layoutId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const updatePage = (id: string, name: string, isHidden: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.UPDATE_PAGE_INIT,
|
||||
payload: {
|
||||
id,
|
||||
name,
|
||||
isHidden,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export type WidgetAddChild = {
|
||||
widgetId: string;
|
||||
widgetName?: string;
|
||||
type: WidgetType;
|
||||
leftColumn: number;
|
||||
topRow: number;
|
||||
columns: number;
|
||||
rows: number;
|
||||
parentRowSpace: number;
|
||||
parentColumnSpace: number;
|
||||
newWidgetId: string;
|
||||
tabId: string;
|
||||
props?: Record<string, any>;
|
||||
};
|
||||
|
||||
export type WidgetMove = {
|
||||
widgetId: string;
|
||||
leftColumn: number;
|
||||
topRow: number;
|
||||
parentId: string;
|
||||
/*
|
||||
If newParentId is different from what we have in redux store,
|
||||
then we have to delete this,
|
||||
as it has been dropped in another container somewhere.
|
||||
*/
|
||||
newParentId: string;
|
||||
};
|
||||
|
||||
export type WidgetRemoveChild = {
|
||||
widgetId: string;
|
||||
childWidgetId: string;
|
||||
};
|
||||
|
||||
export type WidgetDelete = {
|
||||
widgetId?: string;
|
||||
parentId?: string;
|
||||
disallowUndo?: boolean;
|
||||
isShortcut?: boolean;
|
||||
};
|
||||
|
||||
export type MultipleWidgetDeletePayload = {
|
||||
widgetIds: string[];
|
||||
disallowUndo?: boolean;
|
||||
isShortcut?: boolean;
|
||||
};
|
||||
|
||||
export type WidgetResize = {
|
||||
widgetId: string;
|
||||
leftColumn: number;
|
||||
rightColumn: number;
|
||||
topRow: number;
|
||||
bottomRow: number;
|
||||
};
|
||||
|
||||
export type WidgetAddChildren = {
|
||||
widgetId: string;
|
||||
children: Array<{
|
||||
type: WidgetType;
|
||||
widgetId: string;
|
||||
parentId: string;
|
||||
parentRowSpace: number;
|
||||
parentColumnSpace: number;
|
||||
leftColumn: number;
|
||||
rightColumn: number;
|
||||
topRow: number;
|
||||
bottomRow: number;
|
||||
isLoading: boolean;
|
||||
}>;
|
||||
};
|
||||
|
||||
export type WidgetUpdateProperty = {
|
||||
widgetId: string;
|
||||
propertyPath: string;
|
||||
propertyValue: any;
|
||||
};
|
||||
|
||||
export const updateWidget = (
|
||||
operation: WidgetOperation,
|
||||
widgetId: string,
|
||||
payload: any
|
||||
): ReduxAction<
|
||||
| WidgetAddChild
|
||||
| WidgetMove
|
||||
| WidgetResize
|
||||
| WidgetDelete
|
||||
| WidgetAddChildren
|
||||
| WidgetUpdateProperty
|
||||
> => {
|
||||
return {
|
||||
type: WidgetReduxActionTypes["WIDGET_" + operation],
|
||||
payload: { widgetId, ...payload },
|
||||
};
|
||||
};
|
||||
|
||||
export const setUrlData = (
|
||||
payload: UrlDataState
|
||||
): ReduxAction<UrlDataState> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_URL_DATA,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const setAppMode = (payload: APP_MODE): ReduxAction<APP_MODE> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_APP_MODE,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const updateAppTransientStore = (
|
||||
payload: Record<string, unknown>
|
||||
): ReduxAction<Record<string, unknown>> => ({
|
||||
type: ReduxActionTypes.UPDATE_APP_TRANSIENT_STORE,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const updateAppPersistentStore = (
|
||||
payload: Record<string, unknown>
|
||||
): ReduxAction<Record<string, unknown>> => {
|
||||
return {
|
||||
type: ReduxActionTypes.UPDATE_APP_PERSISTENT_STORE,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export interface ReduxActionWithExtraParams<T> extends ReduxAction<T> {
|
||||
extraParams: Record<any, any>;
|
||||
}
|
||||
|
||||
export const generateTemplateSuccess = ({
|
||||
isNewPage,
|
||||
layoutId,
|
||||
pageId,
|
||||
pageName,
|
||||
}: {
|
||||
layoutId: string;
|
||||
pageId: string;
|
||||
pageName: string;
|
||||
isNewPage: boolean;
|
||||
}) => {
|
||||
return {
|
||||
type: ReduxActionTypes.GENERATE_TEMPLATE_PAGE_SUCCESS,
|
||||
payload: {
|
||||
layoutId,
|
||||
pageId,
|
||||
pageName,
|
||||
isNewPage,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const generateTemplateError = () => {
|
||||
return {
|
||||
type: ReduxActionErrorTypes.GENERATE_TEMPLATE_PAGE_ERROR,
|
||||
};
|
||||
};
|
||||
|
||||
export const generateTemplateToUpdatePage = ({
|
||||
applicationId,
|
||||
columns,
|
||||
datasourceId,
|
||||
mode,
|
||||
pageId,
|
||||
searchColumn,
|
||||
tableName,
|
||||
}: GenerateTemplatePageRequest): ReduxActionWithExtraParams<GenerateTemplatePageRequest> => {
|
||||
return {
|
||||
type: ReduxActionTypes.GENERATE_TEMPLATE_PAGE_INIT,
|
||||
payload: {
|
||||
pageId,
|
||||
tableName,
|
||||
datasourceId,
|
||||
applicationId,
|
||||
columns,
|
||||
searchColumn,
|
||||
},
|
||||
extraParams: {
|
||||
mode,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
import {
|
||||
ReduxAction,
|
||||
ReduxActionTypes,
|
||||
ReduxActionErrorTypes,
|
||||
ReduxActionWithoutPayload,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { PluginFormPayload } from "api/PluginApi";
|
||||
import { DependencyMap } from "utils/DynamicBindingUtils";
|
||||
|
||||
export const fetchPlugins = (): ReduxActionWithoutPayload => ({
|
||||
type: ReduxActionTypes.FETCH_PLUGINS_REQUEST,
|
||||
});
|
||||
|
||||
export const fetchPluginFormConfigs = (): ReduxActionWithoutPayload => ({
|
||||
type: ReduxActionTypes.FETCH_PLUGIN_FORM_CONFIGS_REQUEST,
|
||||
});
|
||||
|
||||
export type PluginFormsPayload = {
|
||||
formConfigs: Record<string, any[]>;
|
||||
editorConfigs: Record<string, any[]>;
|
||||
settingConfigs: Record<string, any[]>;
|
||||
dependencies: Record<string, DependencyMap>;
|
||||
};
|
||||
|
||||
export const fetchPluginFormConfigsSuccess = (
|
||||
payload: PluginFormsPayload,
|
||||
): ReduxAction<PluginFormsPayload> => ({
|
||||
type: ReduxActionTypes.FETCH_PLUGIN_FORM_CONFIGS_SUCCESS,
|
||||
payload,
|
||||
});
|
||||
|
||||
export interface PluginFormPayloadWithId extends PluginFormPayload {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export const fetchPluginFormConfigSuccess = (
|
||||
payload: PluginFormPayloadWithId,
|
||||
): ReduxAction<PluginFormPayloadWithId> => ({
|
||||
type: ReduxActionTypes.FETCH_PLUGIN_FORM_SUCCESS,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const fetchPluginFormConfigError = (
|
||||
payload: GetPluginFormConfigRequest,
|
||||
): ReduxAction<GetPluginFormConfigRequest> => ({
|
||||
type: ReduxActionErrorTypes.FETCH_PLUGIN_FORM_ERROR,
|
||||
payload,
|
||||
});
|
||||
|
||||
export interface GetPluginFormConfigRequest {
|
||||
id: string;
|
||||
}
|
||||
|
||||
// To fetch plugin form config for individual plugin
|
||||
export const fetchPluginFormConfig = ({
|
||||
pluginId: id,
|
||||
}: {
|
||||
pluginId: GetPluginFormConfigRequest;
|
||||
}) => ({
|
||||
type: ReduxActionTypes.GET_PLUGIN_FORM_CONFIG_INIT,
|
||||
payload: id,
|
||||
});
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
export const updateWidgetName = (widgetId: string, newName: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.UPDATE_WIDGET_NAME_INIT,
|
||||
payload: {
|
||||
id: widgetId,
|
||||
newName,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const hidePropertyPane = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.HIDE_PROPERTY_PANE,
|
||||
};
|
||||
};
|
||||
|
||||
export const bindDataToWidget = (payload: { widgetId: string }) => {
|
||||
return {
|
||||
type: ReduxActionTypes.BIND_DATA_TO_WIDGET,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const setSnipingMode = (payload: boolean) => ({
|
||||
type: ReduxActionTypes.SET_SNIPING_MODE,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const resetSnipingMode = () => ({
|
||||
type: ReduxActionTypes.RESET_SNIPING_MODE,
|
||||
});
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
|
||||
import {
|
||||
AddApiToPageRequest,
|
||||
FetchProviderWithCategoryRequest,
|
||||
SearchApiOrProviderRequest,
|
||||
} from "api/ProvidersApi";
|
||||
|
||||
export const fetchProviders = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_PROVIDERS_INIT,
|
||||
};
|
||||
};
|
||||
|
||||
export const searchApiOrProvider = (payload: SearchApiOrProviderRequest) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SEARCH_APIORPROVIDERS_INIT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchProviderCategories = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_PROVIDERS_CATEGORIES_INIT,
|
||||
};
|
||||
};
|
||||
|
||||
export const getProviderDetailsByProviderId = (providerId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_PROVIDER_DETAILS_BY_PROVIDER_ID_INIT,
|
||||
payload: { providerId },
|
||||
};
|
||||
};
|
||||
export const fetchProviderTemplates = (providerId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_PROVIDER_TEMPLATES_INIT,
|
||||
payload: { providerId },
|
||||
};
|
||||
};
|
||||
|
||||
export const addApiToPage = (payload: AddApiToPageRequest) => {
|
||||
return {
|
||||
type: ReduxActionTypes.ADD_API_TO_PAGE_INIT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchProvidersWithCategory = (
|
||||
payload: FetchProviderWithCategoryRequest,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_PROVIDERS_WITH_CATEGORY_INIT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const clearProviders = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.CLEAR_PROVIDERS,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
import { ReduxActionTypes, ReduxAction } from "constants/ReduxActionConstants";
|
||||
import { Action } from "entities/Action";
|
||||
|
||||
export const createQueryRequest = (payload: Partial<Action>) => {
|
||||
return {
|
||||
type: ReduxActionTypes.CREATE_QUERY_INIT,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const initQueryPane = (
|
||||
pluginType: string,
|
||||
urlId?: string,
|
||||
): ReduxAction<{ pluginType: string; id?: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.INIT_QUERY_PANE,
|
||||
payload: { id: urlId, pluginType },
|
||||
};
|
||||
};
|
||||
|
||||
export const changeQuery = (
|
||||
id: string,
|
||||
newQuery?: boolean,
|
||||
): ReduxAction<{ id: string; newQuery?: boolean }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.QUERY_PANE_CHANGE,
|
||||
payload: { id, newQuery },
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
|
||||
export const handlePathUpdated = (location: typeof window.location) => ({
|
||||
type: ReduxActionTypes.HANDLE_PATH_UPDATED,
|
||||
payload: { location },
|
||||
});
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
|
||||
export const resetReleasesCount = () => ({
|
||||
type: ReduxActionTypes.RESET_UNREAD_RELEASES_COUNT,
|
||||
});
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { ThemeMode } from "../selectors/themeSelectors";
|
||||
|
||||
export const setThemeMode = (mode: ThemeMode) => ({
|
||||
type: ReduxActionTypes.SET_THEME,
|
||||
payload: mode,
|
||||
});
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { TourType } from "entities/Tour";
|
||||
|
||||
export const setActiveTour = (tourType: TourType) => ({
|
||||
type: ReduxActionTypes.SET_ACTIVE_TOUR,
|
||||
payload: tourType,
|
||||
});
|
||||
|
||||
export const resetActiveTour = () => ({
|
||||
type: ReduxActionTypes.RESET_ACTIVE_TOUR,
|
||||
payload: undefined,
|
||||
});
|
||||
|
||||
export const setActiveTourIndex = (index: number) => ({
|
||||
type: ReduxActionTypes.SET_ACTIVE_TOUR_INDEX,
|
||||
payload: index,
|
||||
});
|
||||
|
||||
export const proceedToNextTourStep = () => ({
|
||||
type: ReduxActionTypes.PROCEED_TO_NEXT_TOUR_STEP,
|
||||
payload: undefined,
|
||||
});
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
import {
|
||||
ReduxActionErrorTypes,
|
||||
ReduxActionTypes,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { CurrentUserDetailsRequestPayload } from "constants/userConstants";
|
||||
import {
|
||||
TokenPasswordUpdateRequest,
|
||||
UpdateUserRequest,
|
||||
VerifyTokenRequest,
|
||||
} from "api/UserApi";
|
||||
|
||||
export const logoutUser = (payload?: { redirectURL: string }) => ({
|
||||
type: ReduxActionTypes.LOGOUT_USER_INIT,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const logoutUserSuccess = () => ({
|
||||
type: ReduxActionTypes.LOGOUT_USER_SUCCESS,
|
||||
});
|
||||
|
||||
export const logoutUserError = (error: any) => ({
|
||||
type: ReduxActionErrorTypes.LOGOUT_USER_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
},
|
||||
});
|
||||
export const setCurrentUserDetails = () => ({
|
||||
type: ReduxActionTypes.SET_CURRENT_USER_INIT,
|
||||
payload: CurrentUserDetailsRequestPayload,
|
||||
});
|
||||
|
||||
export const verifyInviteSuccess = () => ({
|
||||
type: ReduxActionTypes.VERIFY_INVITE_SUCCESS,
|
||||
});
|
||||
|
||||
export const verifyInvite = (payload: VerifyTokenRequest) => ({
|
||||
type: ReduxActionTypes.VERIFY_INVITE_INIT,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const verifyInviteError = (error: any) => ({
|
||||
type: ReduxActionErrorTypes.VERIFY_INVITE_ERROR,
|
||||
payload: { error },
|
||||
});
|
||||
|
||||
export const invitedUserSignup = (
|
||||
payload: TokenPasswordUpdateRequest & { resolve: any; reject: any },
|
||||
) => ({
|
||||
type: ReduxActionTypes.INVITED_USER_SIGNUP_INIT,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const invitedUserSignupSuccess = () => ({
|
||||
type: ReduxActionTypes.INVITED_USER_SIGNUP_SUCCESS,
|
||||
});
|
||||
|
||||
export const invitedUserSignupError = (error: any) => ({
|
||||
type: ReduxActionErrorTypes.INVITED_USER_SIGNUP_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
},
|
||||
});
|
||||
|
||||
export const updateUserDetails = (payload: UpdateUserRequest) => ({
|
||||
type: ReduxActionTypes.UPDATE_USER_DETAILS_INIT,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const updatePhoto = (payload: {
|
||||
file: File;
|
||||
callback?: () => void;
|
||||
}) => ({
|
||||
type: ReduxActionTypes.UPLOAD_PROFILE_PHOTO,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const removePhoto = (callback: () => void) => ({
|
||||
type: ReduxActionTypes.REMOVE_PROFILE_PHOTO,
|
||||
payload: { callback },
|
||||
});
|
||||
|
||||
export const leaveOrganization = (orgId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.LEAVE_ORG_INIT,
|
||||
payload: {
|
||||
orgId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchFeatureFlagsInit = () => ({
|
||||
type: ReduxActionTypes.FETCH_FEATURE_FLAGS_INIT,
|
||||
});
|
||||
|
||||
export const fetchFeatureFlagsSuccess = () => ({
|
||||
type: ReduxActionTypes.FETCH_FEATURE_FLAGS_SUCCESS,
|
||||
});
|
||||
|
||||
export const fetchFeatureFlagsError = (error: any) => ({
|
||||
type: ReduxActionErrorTypes.FETCH_FEATURE_FLAGS_ERROR,
|
||||
payload: { error, show: false },
|
||||
});
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
|
||||
export const historyPush = (url: string) => ({
|
||||
type: ReduxActionTypes.HISTORY_PUSH,
|
||||
payload: {
|
||||
url,
|
||||
},
|
||||
});
|
||||
|
||||
export const windowRedirect = (url: string) => ({
|
||||
type: ReduxActionTypes.REDIRECT_WINDOW_LOCATION,
|
||||
payload: {
|
||||
url,
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxSagaChannels,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { reconnectWebsocketEvent } from "constants/WebsocketConstants";
|
||||
|
||||
export const setIsWebsocketConnected = (payload: boolean) => ({
|
||||
type: ReduxActionTypes.SET_IS_WEBSOCKET_CONNECTED,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const websocketWriteEvent = (payload: {
|
||||
type: string;
|
||||
payload?: any;
|
||||
}) => ({
|
||||
type: ReduxSagaChannels.WEBSOCKET_WRITE_CHANNEL,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const reconnectWebsocket = () =>
|
||||
websocketWriteEvent(reconnectWebsocketEvent());
|
||||
|
||||
export const retrySocketConnection = () => ({
|
||||
type: ReduxActionTypes.RETRY_WEBSOCKET_CONNECTION,
|
||||
});
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxAction,
|
||||
ReduxActionErrorTypes,
|
||||
ReduxActionWithoutPayload,
|
||||
WidgetReduxActionTypes,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import {
|
||||
ExecuteActionPayload,
|
||||
ExecuteErrorPayload,
|
||||
} from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { BatchAction, batchAction } from "actions/batchActions";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
|
||||
export const executeAction = (
|
||||
payload: ExecuteActionPayload,
|
||||
): BatchAction<ExecuteActionPayload> =>
|
||||
batchAction({
|
||||
type: ReduxActionTypes.EXECUTE_ACTION,
|
||||
payload,
|
||||
});
|
||||
|
||||
export const executeActionError = (
|
||||
executeErrorPayload: ExecuteErrorPayload,
|
||||
): ReduxAction<ExecuteErrorPayload> => {
|
||||
return {
|
||||
type: ReduxActionErrorTypes.EXECUTE_ACTION_ERROR,
|
||||
payload: executeErrorPayload,
|
||||
};
|
||||
};
|
||||
|
||||
export const executePageLoadActions = (): ReduxActionWithoutPayload => ({
|
||||
type: ReduxActionTypes.EXECUTE_PAGE_LOAD_ACTIONS,
|
||||
});
|
||||
|
||||
export const disableDragAction = (
|
||||
isDraggingDisabled: boolean,
|
||||
): ReduxAction<{ isDraggingDisabled: boolean }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.DISABLE_WIDGET_DRAG,
|
||||
payload: {
|
||||
isDraggingDisabled,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const createModalAction = (
|
||||
modalName: string,
|
||||
): ReduxAction<{ modalName: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.CREATE_MODAL_INIT,
|
||||
payload: {
|
||||
modalName,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const focusWidget = (
|
||||
widgetId?: string,
|
||||
): ReduxAction<{ widgetId?: string }> => ({
|
||||
type: ReduxActionTypes.FOCUS_WIDGET,
|
||||
payload: { widgetId },
|
||||
});
|
||||
|
||||
export const showModal = (id: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SHOW_MODAL,
|
||||
payload: {
|
||||
modalId: id,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const closeAllModals = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.CLOSE_MODAL,
|
||||
payload: {},
|
||||
};
|
||||
};
|
||||
|
||||
export const forceOpenPropertyPane = (id: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SHOW_PROPERTY_PANE,
|
||||
payload: {
|
||||
widgetId: id,
|
||||
force: true,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const closePropertyPane = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.HIDE_PROPERTY_PANE,
|
||||
payload: {
|
||||
force: false,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const closeTableFilterPane = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.HIDE_TABLE_FILTER_PANE,
|
||||
payload: {
|
||||
force: false,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const copyWidget = (isShortcut: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.COPY_SELECTED_WIDGET_INIT,
|
||||
payload: {
|
||||
isShortcut: !!isShortcut,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const pasteWidget = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.PASTE_COPIED_WIDGET_INIT,
|
||||
};
|
||||
};
|
||||
|
||||
export const deleteSelectedWidget = (
|
||||
isShortcut: boolean,
|
||||
disallowUndo = false,
|
||||
) => {
|
||||
return {
|
||||
type: WidgetReduxActionTypes.WIDGET_DELETE,
|
||||
payload: {
|
||||
isShortcut,
|
||||
disallowUndo,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const cutWidget = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.CUT_SELECTED_WIDGET,
|
||||
};
|
||||
};
|
||||
|
||||
export const addSuggestedWidget = (payload: Partial<WidgetProps>) => {
|
||||
return {
|
||||
type: ReduxActionTypes.ADD_SUGGESTED_WIDGET,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
import { ReduxActionTypes, ReduxAction } from "constants/ReduxActionConstants";
|
||||
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
|
||||
|
||||
export const selectWidgetAction = (
|
||||
widgetId?: string,
|
||||
isMultiSelect?: boolean,
|
||||
): ReduxAction<{ widgetId?: string; isMultiSelect?: boolean }> => ({
|
||||
type: ReduxActionTypes.SELECT_WIDGET,
|
||||
payload: { widgetId, isMultiSelect },
|
||||
});
|
||||
|
||||
export const selectWidgetInitAction = (
|
||||
widgetId?: string,
|
||||
isMultiSelect?: boolean,
|
||||
): ReduxAction<{ widgetId?: string; isMultiSelect?: boolean }> => ({
|
||||
type: ReduxActionTypes.SELECT_WIDGET_INIT,
|
||||
payload: { widgetId, isMultiSelect },
|
||||
});
|
||||
|
||||
export const selectMultipleWidgetsAction = (
|
||||
widgetIds?: string[],
|
||||
): ReduxAction<{ widgetIds?: string[] }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SELECT_MULTIPLE_WIDGETS,
|
||||
payload: { widgetIds },
|
||||
};
|
||||
};
|
||||
|
||||
export const silentAddSelectionsAction = (
|
||||
widgetIds?: string[],
|
||||
): ReduxAction<{ widgetIds?: string[] }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SELECT_WIDGETS,
|
||||
payload: { widgetIds },
|
||||
};
|
||||
};
|
||||
|
||||
export const deselectMultipleWidgetsAction = (
|
||||
widgetIds?: string[],
|
||||
): ReduxAction<{ widgetIds?: string[] }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.DESELECT_WIDGETS,
|
||||
payload: { widgetIds },
|
||||
};
|
||||
};
|
||||
|
||||
export const selectAllWidgetsInCanvasInitAction = (
|
||||
canvasId = MAIN_CONTAINER_WIDGET_ID,
|
||||
): ReduxAction<{ canvasId: string }> => {
|
||||
return {
|
||||
type: ReduxActionTypes.SELECT_ALL_WIDGETS_IN_CANVAS_INIT,
|
||||
payload: {
|
||||
canvasId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const selectMultipleWidgetsInitAction = (widgetIds: string[]) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SELECT_MULTIPLE_WIDGETS_INIT,
|
||||
payload: { widgetIds },
|
||||
};
|
||||
};
|
||||
|
||||
export const shiftSelectWidgetsEntityExplorerInitAction = (
|
||||
widgetId: string,
|
||||
siblingWidgets: string[],
|
||||
): ReduxAction<{ widgetId: string; siblingWidgets: string[] }> => ({
|
||||
type: ReduxActionTypes.SHIFT_SELECT_WIDGET_INIT,
|
||||
payload: { widgetId, siblingWidgets },
|
||||
});
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import {
|
||||
ReduxActionTypes,
|
||||
ReduxActionErrorTypes,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { WidgetCardProps } from "widgets/BaseWidget";
|
||||
|
||||
export const fetchWidgetCards = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_WIDGET_CARDS,
|
||||
};
|
||||
};
|
||||
|
||||
export const errorFetchingWidgetCards = (error: any) => {
|
||||
return {
|
||||
type: ReduxActionErrorTypes.FETCH_WIDGET_CARDS_ERROR,
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
||||
export const successFetchingWidgetCards = (cards: {
|
||||
[id: string]: WidgetCardProps[];
|
||||
}) => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_WIDGET_CARDS_SUCCESS,
|
||||
cards,
|
||||
};
|
||||
};
|
||||
|
||||
export default {
|
||||
fetchWidgetCards,
|
||||
errorFetchingWidgetCards,
|
||||
successFetchingWidgetCards,
|
||||
};
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
import API, { HttpMethod } from "api/Api";
|
||||
import { ApiResponse, GenericApiResponse, ResponseMeta } from "./ApiResponses";
|
||||
import { DEFAULT_EXECUTE_ACTION_TIMEOUT_MS } from "constants/ApiConstants";
|
||||
import axios, { AxiosPromise, CancelTokenSource } from "taro-axios";
|
||||
import { Action, ActionViewMode } from "entities/Action";
|
||||
import { APIRequest } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
|
||||
export interface CreateActionRequest<T> extends APIRequest {
|
||||
datasourceId: string;
|
||||
pageId: string;
|
||||
name: string;
|
||||
actionConfiguration: T;
|
||||
}
|
||||
|
||||
export interface UpdateActionRequest<T> extends CreateActionRequest<T> {
|
||||
actionId: string;
|
||||
}
|
||||
|
||||
export interface Property {
|
||||
key: string;
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export interface BodyFormData {
|
||||
editable: boolean;
|
||||
mandatory: boolean;
|
||||
description: string;
|
||||
key: string;
|
||||
value?: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface QueryConfig {
|
||||
queryString: string;
|
||||
}
|
||||
|
||||
export interface ActionCreateUpdateResponse extends ApiResponse {
|
||||
id: string;
|
||||
jsonPathKeys: Record<string, string>;
|
||||
}
|
||||
|
||||
export type PaginationField = "PREV" | "NEXT";
|
||||
|
||||
export interface ExecuteActionRequest extends APIRequest {
|
||||
actionId: string;
|
||||
params?: Property[];
|
||||
paginationField?: PaginationField;
|
||||
viewMode: boolean;
|
||||
}
|
||||
|
||||
export interface ExecuteActionResponse extends ApiResponse {
|
||||
actionId: string;
|
||||
data: any;
|
||||
}
|
||||
|
||||
export interface ActionApiResponseReq {
|
||||
headers: Record<string, string[]>;
|
||||
body: Record<string, unknown> | null;
|
||||
httpMethod: HttpMethod | "";
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface ActionExecutionResponse {
|
||||
responseMeta: ResponseMeta;
|
||||
data: {
|
||||
body: Record<string, unknown> | string;
|
||||
headers: Record<string, string[]>;
|
||||
statusCode: string;
|
||||
isExecutionSuccess: boolean;
|
||||
request: ActionApiResponseReq;
|
||||
};
|
||||
clientMeta: {
|
||||
duration: string;
|
||||
size: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SuggestedWidget {
|
||||
type: WidgetType;
|
||||
bindingQuery: string;
|
||||
}
|
||||
|
||||
export interface ActionResponse {
|
||||
body: unknown;
|
||||
headers: Record<string, string[]>;
|
||||
request?: ActionApiResponseReq;
|
||||
statusCode: string;
|
||||
duration: string;
|
||||
size: string;
|
||||
isExecutionSuccess?: boolean;
|
||||
suggestedWidgets?: SuggestedWidget[];
|
||||
messages?: Array<string>;
|
||||
}
|
||||
|
||||
export interface MoveActionRequest {
|
||||
action: Action;
|
||||
destinationPageId: string;
|
||||
}
|
||||
|
||||
export interface CopyActionRequest {
|
||||
action: Action;
|
||||
pageId: string;
|
||||
}
|
||||
|
||||
export interface UpdateActionNameRequest {
|
||||
pageId: string;
|
||||
actionId: string;
|
||||
layoutId: string;
|
||||
newName: string;
|
||||
oldName: string;
|
||||
}
|
||||
|
||||
class ActionAPI extends API {
|
||||
static url = "v1/actions";
|
||||
static apiUpdateCancelTokenSource: CancelTokenSource;
|
||||
static queryUpdateCancelTokenSource: CancelTokenSource;
|
||||
|
||||
static createAction(
|
||||
apiConfig: Partial<Action>,
|
||||
): AxiosPromise<ActionCreateUpdateResponse> {
|
||||
return API.post(ActionAPI.url, apiConfig);
|
||||
}
|
||||
|
||||
static fetchActions(
|
||||
applicationId: string,
|
||||
): AxiosPromise<GenericApiResponse<Action[]>> {
|
||||
return API.get(ActionAPI.url, { applicationId });
|
||||
}
|
||||
|
||||
static fetchActionsForViewMode(
|
||||
applicationId: string,
|
||||
): AxiosPromise<GenericApiResponse<ActionViewMode[]>> {
|
||||
return API.get(`${ActionAPI.url}/view`, { applicationId });
|
||||
}
|
||||
|
||||
static fetchActionsByPageId(
|
||||
pageId: string,
|
||||
): AxiosPromise<GenericApiResponse<Action[]>> {
|
||||
return API.get(ActionAPI.url, { pageId });
|
||||
}
|
||||
|
||||
static updateAction(
|
||||
apiConfig: Partial<Action>,
|
||||
): AxiosPromise<ActionCreateUpdateResponse> {
|
||||
if (ActionAPI.apiUpdateCancelTokenSource) {
|
||||
ActionAPI.apiUpdateCancelTokenSource.cancel();
|
||||
}
|
||||
ActionAPI.apiUpdateCancelTokenSource = axios.CancelToken.source();
|
||||
const action = Object.assign({}, apiConfig);
|
||||
// While this line is not required, name can not be changed from this endpoint
|
||||
delete action.name;
|
||||
return API.put(`${ActionAPI.url}/${action.id}`, action, undefined, {
|
||||
cancelToken: ActionAPI.apiUpdateCancelTokenSource.token,
|
||||
});
|
||||
}
|
||||
|
||||
static updateActionName(updateActionNameRequest: UpdateActionNameRequest) {
|
||||
return API.put(ActionAPI.url + "/refactor", updateActionNameRequest);
|
||||
}
|
||||
|
||||
static deleteAction(id: string) {
|
||||
return API.delete(`${ActionAPI.url}/${id}`);
|
||||
}
|
||||
|
||||
static executeAction(
|
||||
executeAction: ExecuteActionRequest,
|
||||
timeout?: number,
|
||||
): AxiosPromise<ActionExecutionResponse> {
|
||||
return API.post(ActionAPI.url + "/execute", executeAction, undefined, {
|
||||
timeout: timeout || DEFAULT_EXECUTE_ACTION_TIMEOUT_MS,
|
||||
});
|
||||
}
|
||||
|
||||
static moveAction(moveRequest: MoveActionRequest) {
|
||||
return API.put(ActionAPI.url + "/move", moveRequest, undefined, {
|
||||
timeout: DEFAULT_EXECUTE_ACTION_TIMEOUT_MS,
|
||||
});
|
||||
}
|
||||
|
||||
static toggleActionExecuteOnLoad(actionId: string, shouldExecute: boolean) {
|
||||
return API.put(ActionAPI.url + `/executeOnLoad/${actionId}`, undefined, {
|
||||
flag: shouldExecute.toString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ActionAPI;
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
import axios, { AxiosInstance, AxiosRequestConfig } from "taro-axios";
|
||||
import { REQUEST_TIMEOUT_MS } from "constants/ApiConstants";
|
||||
import { convertObjectToQueryParams } from "utils/AppsmithUtils";
|
||||
import {
|
||||
apiFailureResponseInterceptor,
|
||||
apiRequestInterceptor,
|
||||
apiSuccessResponseInterceptor,
|
||||
} from "api/ApiUtils";
|
||||
import { API_REQUEST_HEADERS } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
|
||||
//TODO(abhinav): Refactor this to make more composable.
|
||||
export const apiRequestConfig = {
|
||||
baseURL: API_BASE_URL,
|
||||
timeout: REQUEST_TIMEOUT_MS,
|
||||
headers: API_REQUEST_HEADERS,
|
||||
withCredentials: true,
|
||||
};
|
||||
|
||||
const axiosInstance: AxiosInstance = axios.create();
|
||||
|
||||
axiosInstance.interceptors.request.use(apiRequestInterceptor);
|
||||
axiosInstance.interceptors.response.use(
|
||||
apiSuccessResponseInterceptor,
|
||||
apiFailureResponseInterceptor,
|
||||
);
|
||||
|
||||
class Api {
|
||||
static get(
|
||||
url: string,
|
||||
queryParams?: any,
|
||||
config: Partial<AxiosRequestConfig> = {},
|
||||
) {
|
||||
return axiosInstance.get(url + convertObjectToQueryParams(queryParams), {
|
||||
...apiRequestConfig,
|
||||
...config,
|
||||
});
|
||||
}
|
||||
|
||||
static post(
|
||||
url: string,
|
||||
body?: any,
|
||||
queryParams?: any,
|
||||
config: Partial<AxiosRequestConfig> = {},
|
||||
) {
|
||||
return axiosInstance.post(
|
||||
url + convertObjectToQueryParams(queryParams),
|
||||
body,
|
||||
{
|
||||
...apiRequestConfig,
|
||||
...config,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static put(
|
||||
url: string,
|
||||
body?: any,
|
||||
queryParams?: any,
|
||||
config: Partial<AxiosRequestConfig> = {},
|
||||
) {
|
||||
return axiosInstance.put(
|
||||
url + convertObjectToQueryParams(queryParams),
|
||||
body,
|
||||
{
|
||||
...apiRequestConfig,
|
||||
...config,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static patch(
|
||||
url: string,
|
||||
body?: any,
|
||||
queryParams?: any,
|
||||
config: Partial<AxiosRequestConfig> = {},
|
||||
) {
|
||||
return axiosInstance.patch(
|
||||
url + convertObjectToQueryParams(queryParams),
|
||||
body,
|
||||
{
|
||||
...apiRequestConfig,
|
||||
...config,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static delete(
|
||||
url: string,
|
||||
queryParams?: any,
|
||||
config: Partial<AxiosRequestConfig> = {},
|
||||
) {
|
||||
return axiosInstance.delete(url + convertObjectToQueryParams(queryParams), {
|
||||
...apiRequestConfig,
|
||||
...config,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
||||
|
||||
export default Api;
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
export type APIResponseError = {
|
||||
code: number;
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type ResponseMeta = {
|
||||
status: number;
|
||||
success: boolean;
|
||||
error?: APIResponseError;
|
||||
};
|
||||
|
||||
export type ApiResponse = {
|
||||
responseMeta: ResponseMeta;
|
||||
data: any;
|
||||
};
|
||||
|
||||
export type GenericApiResponse<T> = {
|
||||
responseMeta: ResponseMeta;
|
||||
data: T;
|
||||
};
|
||||
|
||||
// NO_DATASOURCES_FOUND, 1000, "Unable to find {0} with id {1}"
|
||||
// INVALID_PARAMTER, 4000, "Invalid parameter {0} provided in the input"
|
||||
// PLUGIN_NOT_INSTALLED, 4001, "Plugin {0} not installed"
|
||||
// MISSING_PLUGIN_ID, 4002, "Missing plugin id. Please input correct plugin id"
|
||||
// MISSING_DATASOURCES_ID, 4003, "Missing datasource id. Please input correct datasource id"
|
||||
// MISSING_PAGE_ID, 4004, "Missing page id. Pleaes input correct page id"
|
||||
// PAGE_DOES_NOT_EXIST_IN_ORG, 4006, "Page {0} does not belong to the current user {1} organization."
|
||||
// UNAUTHORIZED_DOMAIN, 4001, "Invalid email domain provided. Please sign in with a valid work email ID"
|
||||
// INTERNAL_SERVER_ERROR, 5000, "Internal server error while processing request"
|
||||
// REPOSITORY_SAVE_FAILED, 5001, "Repository save failed."
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
import {
|
||||
createMessage,
|
||||
ERROR_0,
|
||||
ERROR_500,
|
||||
SERVER_API_TIMEOUT_ERROR,
|
||||
} from "constants/messages";
|
||||
import axios, { AxiosRequestConfig, AxiosResponse } from "taro-axios";
|
||||
import {
|
||||
API_STATUS_CODES,
|
||||
ERROR_CODES,
|
||||
SERVER_ERROR_CODES,
|
||||
} from "constants/ApiConstants";
|
||||
import log from "loglevel";
|
||||
import { ActionExecutionResponse } from "api/ActionAPI";
|
||||
import { logoutUser } from "actions/userActions";
|
||||
import { AUTH_LOGIN_URL } from "constants/routes";
|
||||
|
||||
const executeActionRegex = /actions\/execute/;
|
||||
const timeoutErrorRegex = /timeout of (\d+)ms exceeded/;
|
||||
export const axiosConnectionAbortedCode = "ECONNABORTED";
|
||||
|
||||
// polyfill
|
||||
const performance = Date;
|
||||
|
||||
const makeExecuteActionResponse = (response: any): ActionExecutionResponse => ({
|
||||
...response.data,
|
||||
clientMeta: {
|
||||
size: response.headers["content-length"],
|
||||
duration: Number(performance.now() - response.config.timer).toFixed(),
|
||||
},
|
||||
});
|
||||
|
||||
const is404orAuthPath = () => {
|
||||
const pathName = window.location.pathname;
|
||||
return /^\/404/.test(pathName) || /^\/user\/\w+/.test(pathName);
|
||||
};
|
||||
|
||||
// Request interceptor will add a timer property to the request.
|
||||
// this will be used to calculate the time taken for an action
|
||||
// execution request
|
||||
export const apiRequestInterceptor = (config: AxiosRequestConfig) => {
|
||||
return { ...config, timer: performance.now() };
|
||||
};
|
||||
|
||||
// On success of an API, if the api is an action execution,
|
||||
// add the client meta object with size and time taken info
|
||||
// otherwise just return the data
|
||||
export const apiSuccessResponseInterceptor = (
|
||||
response: AxiosResponse,
|
||||
): AxiosResponse["data"] => {
|
||||
if (response.config.url) {
|
||||
if (response.config.url.match(executeActionRegex)) {
|
||||
return makeExecuteActionResponse(response);
|
||||
}
|
||||
}
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// Handle different api failure scenarios
|
||||
export const apiFailureResponseInterceptor = (error: any) => {
|
||||
// Return error when there is no internet
|
||||
if (!window.navigator.onLine) {
|
||||
return Promise.reject({
|
||||
...error,
|
||||
message: createMessage(ERROR_0),
|
||||
});
|
||||
}
|
||||
|
||||
// Return if the call was cancelled via cancel token
|
||||
if (axios.isCancel(error)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Return modified response if action execution failed
|
||||
if (error.config && error.config.url.match(executeActionRegex)) {
|
||||
return makeExecuteActionResponse(error.response);
|
||||
}
|
||||
// Return error if any timeout happened in other api calls
|
||||
if (
|
||||
error.code === axiosConnectionAbortedCode &&
|
||||
error.message &&
|
||||
error.message.match(timeoutErrorRegex)
|
||||
) {
|
||||
return Promise.reject({
|
||||
...error,
|
||||
message: createMessage(SERVER_API_TIMEOUT_ERROR),
|
||||
code: ERROR_CODES.REQUEST_TIMEOUT,
|
||||
});
|
||||
}
|
||||
|
||||
if (error.response) {
|
||||
if (error.response.status === API_STATUS_CODES.SERVER_ERROR) {
|
||||
return Promise.reject({
|
||||
...error,
|
||||
code: ERROR_CODES.SERVER_ERROR,
|
||||
message: createMessage(ERROR_500),
|
||||
});
|
||||
}
|
||||
|
||||
// The request was made and the server responded with a status code
|
||||
// that falls out of the range of 2xx
|
||||
if (!is404orAuthPath()) {
|
||||
const currentUrl = `${window.location.href}`;
|
||||
if (error.response.status === API_STATUS_CODES.REQUEST_NOT_AUTHORISED) {
|
||||
// Redirect to login and set a redirect url.
|
||||
console.log("redirect logout");
|
||||
// store.dispatch(
|
||||
// logoutUser({
|
||||
// redirectURL: `${AUTH_LOGIN_URL}?redirectUrl=${encodeURIComponent(
|
||||
// currentUrl,
|
||||
// )}`,
|
||||
// }),
|
||||
// );
|
||||
return Promise.reject({
|
||||
code: ERROR_CODES.REQUEST_NOT_AUTHORISED,
|
||||
message: "Unauthorized. Redirecting to login page...",
|
||||
show: false,
|
||||
});
|
||||
}
|
||||
const errorData = error.response.data.responseMeta;
|
||||
if (
|
||||
errorData.status === API_STATUS_CODES.RESOURCE_NOT_FOUND &&
|
||||
errorData.error.code === SERVER_ERROR_CODES.RESOURCE_NOT_FOUND
|
||||
) {
|
||||
return Promise.reject({
|
||||
code: ERROR_CODES.PAGE_NOT_FOUND,
|
||||
message: "Resource Not Found",
|
||||
show: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (error.response.data.responseMeta) {
|
||||
return Promise.resolve(error.response.data);
|
||||
}
|
||||
return Promise.reject(error.response.data);
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
log.error(error.request);
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
log.error("Error", error.message);
|
||||
}
|
||||
console.log(error.config);
|
||||
return Promise.resolve(error);
|
||||
};
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
import Api from "api/Api";
|
||||
import { ApiResponse } from "./ApiResponses";
|
||||
import { AxiosPromise } from "taro-axios";
|
||||
import { AppLayoutConfig } from "reducers/entityReducers/pageListReducer";
|
||||
|
||||
export interface PublishApplicationRequest {
|
||||
applicationId: string;
|
||||
}
|
||||
|
||||
export interface ChangeAppViewAccessRequest {
|
||||
applicationId: string;
|
||||
publicAccess: boolean;
|
||||
}
|
||||
|
||||
export interface PublishApplicationResponse extends ApiResponse {
|
||||
data: unknown;
|
||||
}
|
||||
|
||||
export interface ApplicationPagePayload {
|
||||
id: string;
|
||||
name: string;
|
||||
isDefault: boolean;
|
||||
}
|
||||
|
||||
export interface ApplicationResponsePayload {
|
||||
id: string;
|
||||
name: string;
|
||||
organizationId: string;
|
||||
pages?: ApplicationPagePayload[];
|
||||
appIsExample: boolean;
|
||||
appLayout?: AppLayoutConfig;
|
||||
unreadCommentThreads?: number;
|
||||
}
|
||||
|
||||
export interface FetchApplicationResponse extends ApiResponse {
|
||||
data: ApplicationResponsePayload & { pages: ApplicationPagePayload[] };
|
||||
}
|
||||
|
||||
export interface FetchApplicationsResponse extends ApiResponse {
|
||||
data: Array<ApplicationResponsePayload & { pages: ApplicationPagePayload[] }>;
|
||||
}
|
||||
|
||||
export interface SetDefaultPageRequest {
|
||||
id: string;
|
||||
applicationId: string;
|
||||
}
|
||||
|
||||
export interface DeleteApplicationRequest {
|
||||
applicationId: string;
|
||||
}
|
||||
|
||||
export interface DuplicateApplicationRequest {
|
||||
applicationId: string;
|
||||
}
|
||||
|
||||
export interface ForkApplicationRequest {
|
||||
applicationId: string;
|
||||
organizationId: string;
|
||||
}
|
||||
|
||||
export interface GetAllApplicationResponse extends ApiResponse {
|
||||
data: Array<ApplicationResponsePayload & { pages: ApplicationPagePayload[] }>;
|
||||
}
|
||||
|
||||
export type UpdateApplicationPayload = {
|
||||
icon?: string;
|
||||
color?: string;
|
||||
name?: string;
|
||||
currentApp?: boolean;
|
||||
appLayout?: AppLayoutConfig;
|
||||
};
|
||||
|
||||
export type UpdateApplicationRequest = UpdateApplicationPayload & {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export interface ApplicationObject {
|
||||
id: string;
|
||||
name: string;
|
||||
icon?: string;
|
||||
color?: string;
|
||||
organizationId: string;
|
||||
pages: ApplicationPagePayload[];
|
||||
userPermissions: string[];
|
||||
}
|
||||
|
||||
export interface UserRoles {
|
||||
name: string;
|
||||
roleName: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface OrganizationApplicationObject {
|
||||
applications: Array<ApplicationObject>;
|
||||
organization: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
userRoles: Array<UserRoles>;
|
||||
}
|
||||
export interface FetchUsersApplicationsOrgsResponse extends ApiResponse {
|
||||
data: {
|
||||
organizationApplications: Array<OrganizationApplicationObject>;
|
||||
user: string;
|
||||
newReleasesCount: string;
|
||||
releaseItems: Array<Record<string, any>>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ImportApplicationRequest {
|
||||
orgId: string;
|
||||
applicationFile?: File;
|
||||
progress?: (progressEvent: ProgressEvent) => void;
|
||||
onSuccessCallback?: () => void;
|
||||
}
|
||||
|
||||
class ApplicationApi extends Api {
|
||||
static baseURL = "v1/applications/";
|
||||
static publishURLPath = (applicationId: string) => `publish/${applicationId}`;
|
||||
static createApplicationPath = (orgId: string) => `?orgId=${orgId}`;
|
||||
static changeAppViewAccessPath = (applicationId: string) =>
|
||||
`${applicationId}/changeAccess`;
|
||||
static setDefaultPagePath = (request: SetDefaultPageRequest) =>
|
||||
`${ApplicationApi.baseURL}${request.applicationId}/page/${request.id}/makeDefault`;
|
||||
static publishApplication(
|
||||
publishApplicationRequest: PublishApplicationRequest,
|
||||
): AxiosPromise<PublishApplicationResponse> {
|
||||
return Api.post(
|
||||
ApplicationApi.baseURL +
|
||||
ApplicationApi.publishURLPath(publishApplicationRequest.applicationId),
|
||||
undefined,
|
||||
{},
|
||||
);
|
||||
}
|
||||
static fetchApplications(): AxiosPromise<FetchApplicationsResponse> {
|
||||
return Api.get(ApplicationApi.baseURL);
|
||||
}
|
||||
|
||||
static getAllApplication(): AxiosPromise<GetAllApplicationResponse> {
|
||||
return Api.get(ApplicationApi.baseURL + "new");
|
||||
}
|
||||
|
||||
static fetchApplication(
|
||||
applicationId: string,
|
||||
): AxiosPromise<FetchApplicationResponse> {
|
||||
return Api.get(ApplicationApi.baseURL + applicationId);
|
||||
}
|
||||
|
||||
static fetchApplicationForViewMode(
|
||||
applicationId: string,
|
||||
): AxiosPromise<FetchApplicationResponse> {
|
||||
return Api.get(ApplicationApi.baseURL + `view/${applicationId}`);
|
||||
}
|
||||
|
||||
static setDefaultApplicationPage(
|
||||
request: SetDefaultPageRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.put(ApplicationApi.setDefaultPagePath(request));
|
||||
}
|
||||
|
||||
static changeAppViewAccess(
|
||||
request: ChangeAppViewAccessRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.put(
|
||||
ApplicationApi.baseURL +
|
||||
ApplicationApi.changeAppViewAccessPath(request.applicationId),
|
||||
{ publicAccess: request.publicAccess },
|
||||
);
|
||||
}
|
||||
|
||||
static updateApplication(
|
||||
request: UpdateApplicationRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
const { id, ...rest } = request;
|
||||
return Api.put(ApplicationApi.baseURL + id, rest);
|
||||
}
|
||||
|
||||
static deleteApplication(
|
||||
request: DeleteApplicationRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.delete(ApplicationApi.baseURL + request.applicationId);
|
||||
}
|
||||
|
||||
static duplicateApplication(
|
||||
request: DuplicateApplicationRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.post(ApplicationApi.baseURL + "clone/" + request.applicationId);
|
||||
}
|
||||
|
||||
static forkApplication(
|
||||
request: ForkApplicationRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.post(
|
||||
"v1/applications/" +
|
||||
request.applicationId +
|
||||
"/fork/" +
|
||||
request.organizationId,
|
||||
);
|
||||
}
|
||||
|
||||
static importApplicationToOrg(
|
||||
request: ImportApplicationRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
const formData = new FormData();
|
||||
if (request.applicationFile) {
|
||||
formData.append("file", request.applicationFile);
|
||||
}
|
||||
return Api.post("v1/applications/import/" + request.orgId, formData, null, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
onUploadProgress: request.progress,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ApplicationApi;
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import { AxiosPromise } from "taro-axios";
|
||||
import Api from "api/Api";
|
||||
import { ImportedCollections } from "constants/collectionsConstants";
|
||||
|
||||
class ImportedCollectionsApi extends Api {
|
||||
static importedCollectionsURL = "v1/import/templateCollections";
|
||||
static fetchImportedCollections(): AxiosPromise<ImportedCollections> {
|
||||
return Api.get(ImportedCollectionsApi.importedCollectionsURL);
|
||||
}
|
||||
}
|
||||
|
||||
export default ImportedCollectionsApi;
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
import { DEFAULT_TEST_DATA_SOURCE_TIMEOUT_MS } from "constants/ApiConstants";
|
||||
import API from "api/Api";
|
||||
import { GenericApiResponse } from "./ApiResponses";
|
||||
import { AxiosPromise } from "taro-axios";
|
||||
|
||||
import { DatasourceAuthentication, Datasource } from "entities/Datasource";
|
||||
export interface CreateDatasourceConfig {
|
||||
name: string;
|
||||
pluginId: string;
|
||||
datasourceConfiguration: {
|
||||
url: string;
|
||||
databaseName?: string;
|
||||
authentication?: DatasourceAuthentication;
|
||||
};
|
||||
//Passed for logging purposes.
|
||||
appName?: string;
|
||||
}
|
||||
|
||||
export interface EmbeddedRestDatasourceRequest {
|
||||
datasourceConfiguration: { url: string };
|
||||
invalids: Array<string>;
|
||||
isValid: boolean;
|
||||
name: string;
|
||||
organizationId: string;
|
||||
pluginId: string;
|
||||
}
|
||||
|
||||
type executeQueryData = Array<{ key: string; value?: string }>;
|
||||
|
||||
export interface executeDatasourceQueryRequest {
|
||||
datasourceId: string;
|
||||
data: executeQueryData;
|
||||
}
|
||||
|
||||
class DatasourcesApi extends API {
|
||||
static url = "v1/datasources";
|
||||
|
||||
static fetchDatasources(
|
||||
orgId: string,
|
||||
): AxiosPromise<GenericApiResponse<Datasource[]>> {
|
||||
return API.get(DatasourcesApi.url + `?organizationId=${orgId}`);
|
||||
}
|
||||
|
||||
static createDatasource(datasourceConfig: Partial<Datasource>): Promise<any> {
|
||||
return API.post(DatasourcesApi.url, datasourceConfig);
|
||||
}
|
||||
|
||||
static testDatasource(datasourceConfig: Partial<Datasource>): Promise<any> {
|
||||
return API.post(`${DatasourcesApi.url}/test`, datasourceConfig, undefined, {
|
||||
timeout: DEFAULT_TEST_DATA_SOURCE_TIMEOUT_MS,
|
||||
});
|
||||
}
|
||||
|
||||
static updateDatasource(
|
||||
datasourceConfig: Partial<Datasource>,
|
||||
id: string,
|
||||
): Promise<any> {
|
||||
return API.put(DatasourcesApi.url + `/${id}`, datasourceConfig);
|
||||
}
|
||||
|
||||
static deleteDatasource(id: string): Promise<any> {
|
||||
return API.delete(DatasourcesApi.url + `/${id}`);
|
||||
}
|
||||
|
||||
static fetchDatasourceStructure(
|
||||
id: string,
|
||||
ignoreCache = false,
|
||||
): Promise<any> {
|
||||
return API.get(
|
||||
DatasourcesApi.url + `/${id}/structure?ignoreCache=${ignoreCache}`,
|
||||
);
|
||||
}
|
||||
|
||||
static fetchMockDatasources(): AxiosPromise<
|
||||
GenericApiResponse<Datasource[]>
|
||||
> {
|
||||
return API.get(DatasourcesApi.url + "/mocks");
|
||||
}
|
||||
|
||||
static addMockDbToDatasources(
|
||||
name: string,
|
||||
organizationId: string,
|
||||
pluginId: string,
|
||||
packageName: string,
|
||||
): Promise<any> {
|
||||
return API.post(DatasourcesApi.url + `/mocks`, {
|
||||
name,
|
||||
organizationId,
|
||||
pluginId,
|
||||
packageName,
|
||||
});
|
||||
}
|
||||
|
||||
static executeDatasourceQuery({
|
||||
data,
|
||||
datasourceId,
|
||||
}: executeDatasourceQueryRequest) {
|
||||
return API.put(
|
||||
DatasourcesApi.url + `/datasource-query` + `/${datasourceId}`,
|
||||
data,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DatasourcesApi;
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import { AxiosPromise } from "taro-axios";
|
||||
import Api from "api/Api";
|
||||
import { ApiResponse } from "./ApiResponses";
|
||||
|
||||
export interface CurlImportRequest {
|
||||
type: string;
|
||||
pageId: string;
|
||||
name: string;
|
||||
curl: string;
|
||||
organizationId: string;
|
||||
}
|
||||
|
||||
class CurlImportApi extends Api {
|
||||
static curlImportURL = `v1/import`;
|
||||
|
||||
static curlImport(request: CurlImportRequest): AxiosPromise<ApiResponse> {
|
||||
const { curl, name, organizationId, pageId } = request;
|
||||
return Api.post(CurlImportApi.curlImportURL, curl, {
|
||||
type: "CURL",
|
||||
pageId,
|
||||
name,
|
||||
organizationId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default CurlImportApi;
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import { AxiosPromise } from "taro-axios";
|
||||
import Api from "./Api";
|
||||
import { ApiResponse } from "./ApiResponses";
|
||||
|
||||
class NotificationsApi extends Api {
|
||||
static baseURL = "v1/notifications";
|
||||
static markAsReadURL = `${NotificationsApi.baseURL}/isRead`;
|
||||
static markAllAsReadURL = `${NotificationsApi.markAsReadURL}/all`;
|
||||
static fetchUnreadNotificationsCountURL = `${NotificationsApi.baseURL}/count/unread`;
|
||||
|
||||
static fetchNotifications(beforeDate?: string): AxiosPromise<ApiResponse> {
|
||||
return Api.get(NotificationsApi.baseURL, beforeDate ? { beforeDate } : {});
|
||||
}
|
||||
|
||||
static markAllNotificationsAsRead(): AxiosPromise<ApiResponse> {
|
||||
return Api.patch(NotificationsApi.markAllAsReadURL, { isRead: true });
|
||||
}
|
||||
|
||||
static fetchUnreadNotificationsCount(): AxiosPromise<ApiResponse> {
|
||||
return Api.get(NotificationsApi.fetchUnreadNotificationsCountURL);
|
||||
}
|
||||
|
||||
static markNotificationsAsRead(
|
||||
ids: Array<string>,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.patch(NotificationsApi.markAsReadURL, {
|
||||
isRead: true,
|
||||
idList: ids,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default NotificationsApi;
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
import { AxiosPromise } from "taro-axios";
|
||||
import Api from "api/Api";
|
||||
import { ApiResponse } from "./ApiResponses";
|
||||
import { OrgRole, Org } from "constants/orgConstants";
|
||||
|
||||
export interface FetchOrgRolesResponse extends ApiResponse {
|
||||
data: OrgRole[];
|
||||
}
|
||||
|
||||
export interface FetchOrgsResponse extends ApiResponse {
|
||||
data: Org[];
|
||||
}
|
||||
export interface FetchOrgResponse extends ApiResponse {
|
||||
data: Org;
|
||||
}
|
||||
|
||||
export interface FetchAllUsersResponse extends ApiResponse {
|
||||
data: OrgRole[];
|
||||
}
|
||||
|
||||
export interface FetchAllRolesResponse extends ApiResponse {
|
||||
data: Org[];
|
||||
}
|
||||
|
||||
export interface FetchOrgRequest {
|
||||
orgId: string;
|
||||
skipValidation?: boolean;
|
||||
}
|
||||
|
||||
export interface FetchAllUsersRequest {
|
||||
orgId: string;
|
||||
}
|
||||
|
||||
export interface ChangeUserRoleRequest {
|
||||
orgId: string;
|
||||
role: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface DeleteOrgUserRequest {
|
||||
orgId: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface FetchAllRolesRequest {
|
||||
orgId: string;
|
||||
}
|
||||
|
||||
export interface SaveOrgRequest {
|
||||
id: string;
|
||||
name?: string;
|
||||
website?: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
export interface SaveOrgLogo {
|
||||
id: string;
|
||||
logo: File;
|
||||
progress: (progressEvent: ProgressEvent) => void;
|
||||
}
|
||||
|
||||
export interface CreateOrgRequest {
|
||||
name: string;
|
||||
}
|
||||
|
||||
class OrgApi extends Api {
|
||||
static rolesURL = "v1/groups";
|
||||
static orgsURL = "v1/organizations";
|
||||
static fetchRoles(): AxiosPromise<FetchOrgRolesResponse> {
|
||||
return Api.get(OrgApi.rolesURL);
|
||||
}
|
||||
static fetchOrgs(): AxiosPromise<FetchOrgsResponse> {
|
||||
return Api.get(OrgApi.orgsURL);
|
||||
}
|
||||
static fetchOrg(request: FetchOrgRequest): AxiosPromise<FetchOrgResponse> {
|
||||
return Api.get(OrgApi.orgsURL + "/" + request.orgId);
|
||||
}
|
||||
static saveOrg(request: SaveOrgRequest): AxiosPromise<ApiResponse> {
|
||||
return Api.put(OrgApi.orgsURL + "/" + request.id, request);
|
||||
}
|
||||
static createOrg(request: CreateOrgRequest): AxiosPromise<ApiResponse> {
|
||||
return Api.post(OrgApi.orgsURL, request);
|
||||
}
|
||||
static fetchAllUsers(
|
||||
request: FetchAllUsersRequest,
|
||||
): AxiosPromise<FetchAllUsersResponse> {
|
||||
return Api.get(OrgApi.orgsURL + "/" + request.orgId + "/members");
|
||||
}
|
||||
static fetchAllRoles(
|
||||
request: FetchAllRolesRequest,
|
||||
): AxiosPromise<FetchAllRolesResponse> {
|
||||
return Api.get(OrgApi.orgsURL + `/roles?organizationId=${request.orgId}`);
|
||||
}
|
||||
static changeOrgUserRole(
|
||||
request: ChangeUserRoleRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.put(OrgApi.orgsURL + "/" + request.orgId + "/role", {
|
||||
username: request.username,
|
||||
roleName: request.role,
|
||||
});
|
||||
}
|
||||
static deleteOrgUser(
|
||||
request: DeleteOrgUserRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.put(OrgApi.orgsURL + "/" + request.orgId + "/role", {
|
||||
username: request.username,
|
||||
roleName: null,
|
||||
});
|
||||
}
|
||||
static saveOrgLogo(request: SaveOrgLogo): AxiosPromise<ApiResponse> {
|
||||
const formData = new FormData();
|
||||
if (request.logo) {
|
||||
formData.append("file", request.logo);
|
||||
}
|
||||
|
||||
return Api.post(
|
||||
OrgApi.orgsURL + "/" + request.id + "/logo",
|
||||
formData,
|
||||
null,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
onUploadProgress: request.progress,
|
||||
},
|
||||
);
|
||||
}
|
||||
static deleteOrgLogo(request: { id: string }): AxiosPromise<ApiResponse> {
|
||||
return Api.delete(OrgApi.orgsURL + "/" + request.id + "/logo");
|
||||
}
|
||||
}
|
||||
export default OrgApi;
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
import Api from "api/Api";
|
||||
import { ContainerWidgetProps } from "widgets/ContainerWidget";
|
||||
import { ApiResponse } from "./ApiResponses";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
import axios, { AxiosPromise, CancelTokenSource } from "taro-axios";
|
||||
import { PageAction } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
|
||||
export interface FetchPageRequest {
|
||||
id: string;
|
||||
isFirstLoad?: boolean;
|
||||
}
|
||||
|
||||
export interface FetchPublishedPageRequest {
|
||||
pageId: string;
|
||||
bustCache?: boolean;
|
||||
}
|
||||
|
||||
export interface SavePageRequest {
|
||||
dsl: ContainerWidgetProps<WidgetProps>;
|
||||
layoutId: string;
|
||||
pageId: string;
|
||||
}
|
||||
|
||||
export interface PageLayout {
|
||||
id: string;
|
||||
dsl: Partial<ContainerWidgetProps<any>>;
|
||||
layoutOnLoadActions: PageAction[][];
|
||||
layoutActions: PageAction[];
|
||||
}
|
||||
|
||||
export type FetchPageResponse = ApiResponse & {
|
||||
data: {
|
||||
id: string;
|
||||
name: string;
|
||||
applicationId: string;
|
||||
layouts: Array<PageLayout>;
|
||||
};
|
||||
};
|
||||
|
||||
export type FetchPublishedPageResponse = ApiResponse & {
|
||||
data: {
|
||||
id: string;
|
||||
dsl: Partial<ContainerWidgetProps<any>>;
|
||||
pageId: string;
|
||||
};
|
||||
};
|
||||
|
||||
export interface SavePageResponse extends ApiResponse {
|
||||
data: {
|
||||
id: string;
|
||||
layoutOnLoadActions: PageAction[][];
|
||||
dsl: Partial<ContainerWidgetProps<any>>;
|
||||
messages: string[];
|
||||
actionUpdates: Array<{
|
||||
executeOnLoad: boolean;
|
||||
id: string;
|
||||
name: string;
|
||||
}>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface CreatePageRequest {
|
||||
applicationId: string;
|
||||
name: string;
|
||||
layouts: Partial<PageLayout>[];
|
||||
}
|
||||
|
||||
export interface UpdatePageRequest {
|
||||
id: string;
|
||||
name: string;
|
||||
isHidden?: boolean;
|
||||
}
|
||||
|
||||
export interface CreatePageResponse extends ApiResponse {
|
||||
data: unknown;
|
||||
}
|
||||
|
||||
export interface FetchPageListResponse extends ApiResponse {
|
||||
data: {
|
||||
pages: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
isDefault: boolean;
|
||||
isHidden?: boolean;
|
||||
layouts: Array<PageLayout>;
|
||||
icon?: string;
|
||||
}>;
|
||||
organizationId: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DeletePageRequest {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface ClonePageRequest {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface UpdateWidgetNameRequest {
|
||||
pageId: string;
|
||||
layoutId: string;
|
||||
newName: string;
|
||||
oldName: string;
|
||||
}
|
||||
|
||||
export interface UpdateWidgetNameResponse extends ApiResponse {
|
||||
data: PageLayout;
|
||||
}
|
||||
|
||||
export interface GenerateTemplatePageRequest {
|
||||
pageId: string;
|
||||
tableName: string;
|
||||
datasourceId: string;
|
||||
applicationId: string;
|
||||
columns?: string[];
|
||||
searchColumn?: string;
|
||||
mode?: string;
|
||||
}
|
||||
|
||||
export type GenerateTemplatePageRequestResponse = ApiResponse & {
|
||||
data: {
|
||||
id: string;
|
||||
name: string;
|
||||
applicationId: string;
|
||||
layouts: Array<PageLayout>;
|
||||
};
|
||||
};
|
||||
|
||||
class PageApi extends Api {
|
||||
static url = "v1/pages";
|
||||
static refactorLayoutURL = "v1/layouts/refactor";
|
||||
static pageUpdateCancelTokenSource?: CancelTokenSource = undefined;
|
||||
static getLayoutUpdateURL = (pageId: string, layoutId: string) => {
|
||||
return `v1/layouts/${layoutId}/pages/${pageId}`;
|
||||
};
|
||||
|
||||
static getGenerateTemplateURL = (pageId?: string) => {
|
||||
return `${PageApi.url}/crud-page${pageId ? `/${pageId}` : ""}`;
|
||||
};
|
||||
|
||||
static getPublishedPageURL = (pageId: string, bustCache?: boolean) => {
|
||||
const url = `v1/pages/${pageId}/view`;
|
||||
return !!bustCache ? url + "?v=" + +new Date() : url;
|
||||
};
|
||||
|
||||
static updatePageUrl = (pageId: string) => `${PageApi.url}/${pageId}`;
|
||||
|
||||
static fetchPage(
|
||||
pageRequest: FetchPageRequest,
|
||||
): AxiosPromise<FetchPageResponse> {
|
||||
return Api.get(PageApi.url + "/" + pageRequest.id);
|
||||
}
|
||||
|
||||
static savePage(
|
||||
savePageRequest: SavePageRequest,
|
||||
): AxiosPromise<SavePageResponse> | undefined {
|
||||
if (PageApi.pageUpdateCancelTokenSource) {
|
||||
PageApi.pageUpdateCancelTokenSource.cancel();
|
||||
}
|
||||
const body = { dsl: savePageRequest.dsl };
|
||||
PageApi.pageUpdateCancelTokenSource = axios.CancelToken.source();
|
||||
return Api.put(
|
||||
PageApi.getLayoutUpdateURL(
|
||||
savePageRequest.pageId,
|
||||
savePageRequest.layoutId,
|
||||
),
|
||||
body,
|
||||
undefined,
|
||||
{ cancelToken: PageApi.pageUpdateCancelTokenSource.token },
|
||||
);
|
||||
}
|
||||
|
||||
static fetchPublishedPage(
|
||||
pageRequest: FetchPublishedPageRequest,
|
||||
): AxiosPromise<FetchPublishedPageResponse> {
|
||||
return Api.get(
|
||||
PageApi.getPublishedPageURL(pageRequest.pageId, pageRequest.bustCache),
|
||||
);
|
||||
}
|
||||
|
||||
static createPage(
|
||||
createPageRequest: CreatePageRequest,
|
||||
): AxiosPromise<FetchPageResponse> {
|
||||
return Api.post(PageApi.url, createPageRequest);
|
||||
}
|
||||
|
||||
static updatePage(request: UpdatePageRequest): AxiosPromise<ApiResponse> {
|
||||
return Api.put(PageApi.updatePageUrl(request.id), request);
|
||||
}
|
||||
|
||||
static generateTemplatePage(
|
||||
request: GenerateTemplatePageRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
if (request.pageId) {
|
||||
return Api.put(PageApi.getGenerateTemplateURL(request.pageId), request);
|
||||
} else {
|
||||
return Api.post(PageApi.getGenerateTemplateURL(), request);
|
||||
}
|
||||
}
|
||||
|
||||
static fetchPageList(
|
||||
applicationId: string,
|
||||
): AxiosPromise<FetchPageListResponse> {
|
||||
return Api.get(PageApi.url + "/application/" + applicationId);
|
||||
}
|
||||
|
||||
static fetchPageListViewMode(
|
||||
applicationId: string,
|
||||
): AxiosPromise<FetchPageListResponse> {
|
||||
return Api.get(PageApi.url + "/view/application/" + applicationId);
|
||||
}
|
||||
|
||||
static deletePage(request: DeletePageRequest): AxiosPromise<ApiResponse> {
|
||||
return Api.delete(PageApi.url + "/" + request.id);
|
||||
}
|
||||
|
||||
static clonePage(request: ClonePageRequest): AxiosPromise<ApiResponse> {
|
||||
return Api.post(PageApi.url + "/clone/" + request.id);
|
||||
}
|
||||
|
||||
static updateWidgetName(
|
||||
request: UpdateWidgetNameRequest,
|
||||
): AxiosPromise<UpdateWidgetNameResponse> {
|
||||
return Api.put(PageApi.refactorLayoutURL, request);
|
||||
}
|
||||
}
|
||||
|
||||
export default PageApi;
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import Api from "api/Api";
|
||||
import { AxiosPromise } from "taro-axios";
|
||||
import { GenericApiResponse } from "api/ApiResponses";
|
||||
import { PluginType } from "entities/Action";
|
||||
import { DependencyMap } from "utils/DynamicBindingUtils";
|
||||
|
||||
export type PluginId = string;
|
||||
export type PluginPackageName = string;
|
||||
export type GenerateCRUDEnabledPluginMap = Record<PluginId, PluginPackageName>;
|
||||
|
||||
export interface Plugin {
|
||||
id: string;
|
||||
name: string;
|
||||
type: PluginType;
|
||||
packageName: string;
|
||||
iconLocation?: string;
|
||||
uiComponent: "ApiEditorForm" | "RapidApiEditorForm" | "DbEditorForm";
|
||||
datasourceComponent: "RestAPIDatasourceForm" | "AutoForm";
|
||||
allowUserDatasources?: boolean;
|
||||
templates: Record<string, string>;
|
||||
responseType?: "TABLE" | "JSON";
|
||||
documentationLink?: string;
|
||||
generateCRUDPageComponent?: string;
|
||||
}
|
||||
|
||||
export interface PluginFormPayload {
|
||||
form: any[];
|
||||
editor: any[];
|
||||
setting: any[];
|
||||
dependencies: DependencyMap;
|
||||
}
|
||||
|
||||
class PluginsApi extends Api {
|
||||
static url = "v1/plugins";
|
||||
static fetchPlugins(
|
||||
orgId: string,
|
||||
): AxiosPromise<GenericApiResponse<Plugin[]>> {
|
||||
return Api.get(PluginsApi.url, { organizationId: orgId });
|
||||
}
|
||||
|
||||
static fetchFormConfig(
|
||||
id: string,
|
||||
): AxiosPromise<GenericApiResponse<PluginFormPayload>> {
|
||||
return Api.get(PluginsApi.url + `/${id}/form`);
|
||||
}
|
||||
}
|
||||
|
||||
export default PluginsApi;
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
import { AxiosPromise } from "taro-axios";
|
||||
import Api from "api/Api";
|
||||
import { ApiResponse } from "./ApiResponses";
|
||||
import {
|
||||
Providers,
|
||||
ProviderTemplates,
|
||||
SearchResultsProviders,
|
||||
ProvidersDataArray,
|
||||
} from "constants/providerConstants";
|
||||
|
||||
export interface FetchProvidersResponse extends ApiResponse {
|
||||
data: Providers;
|
||||
}
|
||||
|
||||
export interface FetchProviderDetailsResponse extends ApiResponse {
|
||||
data: ProvidersDataArray;
|
||||
}
|
||||
|
||||
export interface FetchProviderCategoriesResponse extends ApiResponse {
|
||||
data: string[];
|
||||
}
|
||||
|
||||
export interface FetchProviderTemplateResponse extends ApiResponse {
|
||||
data: ProviderTemplates[];
|
||||
}
|
||||
|
||||
export interface SearchApiOrProviderResponse extends ApiResponse {
|
||||
data: {
|
||||
providers: SearchResultsProviders[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface FetchProviderTemplatesRequest {
|
||||
providerId: string;
|
||||
}
|
||||
|
||||
export interface FetchProviderDetailsByProviderIdRequest {
|
||||
providerId: string;
|
||||
}
|
||||
|
||||
export interface FetchProviderWithCategoryRequest {
|
||||
category: string;
|
||||
page: number;
|
||||
}
|
||||
|
||||
export interface SearchApiOrProviderRequest {
|
||||
searchKey: string;
|
||||
}
|
||||
|
||||
export interface AddApiToPageRequest {
|
||||
name: string;
|
||||
pageId: string;
|
||||
marketplaceElement: any;
|
||||
organizationId?: string;
|
||||
// Added for analytics
|
||||
source?: string;
|
||||
}
|
||||
|
||||
export class ProvidersApi extends Api {
|
||||
static providersURL = "v1/providers";
|
||||
static providerCategoriesURL = "v1/providers/categories";
|
||||
|
||||
static providerDetailsByIdURL = (providerId: string) => {
|
||||
return `v1/marketplace/providers/${providerId}`;
|
||||
};
|
||||
|
||||
static providerTemplateURL = (providerId: string) => {
|
||||
return `v1/marketplace/templates?providerId=${providerId}`;
|
||||
};
|
||||
|
||||
static searchApiOrProviderUrl = (searchKey: string) => {
|
||||
return `v1/marketplace/search?searchKey=${searchKey}`;
|
||||
};
|
||||
|
||||
static providersWithCategoryURL = (category: string, page: number) => {
|
||||
return `v1/marketplace/providers?category=${category}&page=${page}&size=50`;
|
||||
};
|
||||
|
||||
static addApiToPageURL = `v1/items/addToPage`;
|
||||
|
||||
static fetchProviders(): AxiosPromise<FetchProvidersResponse> {
|
||||
return Api.get(ProvidersApi.providersURL);
|
||||
}
|
||||
|
||||
static fetchProviderTemplates(
|
||||
request: FetchProviderTemplatesRequest,
|
||||
): AxiosPromise<FetchProviderTemplateResponse> {
|
||||
const { providerId } = request;
|
||||
return Api.get(ProvidersApi.providerTemplateURL(providerId));
|
||||
}
|
||||
|
||||
static seachApiOrProvider(
|
||||
request: SearchApiOrProviderRequest,
|
||||
): AxiosPromise<SearchApiOrProviderResponse> {
|
||||
const { searchKey } = request;
|
||||
return Api.get(ProvidersApi.searchApiOrProviderUrl(searchKey));
|
||||
}
|
||||
|
||||
static addApiToPage(request: AddApiToPageRequest): AxiosPromise<ApiResponse> {
|
||||
return Api.post(ProvidersApi.addApiToPageURL, request);
|
||||
}
|
||||
|
||||
static fetchProvidersCategories(): AxiosPromise<
|
||||
FetchProviderCategoriesResponse
|
||||
> {
|
||||
return Api.get(ProvidersApi.providerCategoriesURL);
|
||||
}
|
||||
|
||||
static fetchProvidersWithCategory(
|
||||
request: FetchProviderWithCategoryRequest,
|
||||
): AxiosPromise<FetchProvidersResponse> {
|
||||
const { page } = request;
|
||||
return Api.get(
|
||||
ProvidersApi.providersWithCategoryURL(request.category, page),
|
||||
);
|
||||
}
|
||||
|
||||
static fetchProviderDetailsByProviderId(
|
||||
request: FetchProviderDetailsByProviderIdRequest,
|
||||
): AxiosPromise<FetchProviderDetailsResponse> {
|
||||
const { providerId } = request;
|
||||
return Api.get(ProvidersApi.providerDetailsByIdURL(providerId));
|
||||
}
|
||||
}
|
||||
|
||||
export default ProvidersApi;
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { AxiosPromise } from "taro-axios";
|
||||
import Api from "api/Api";
|
||||
import { ApiResponse } from "./ApiResponses";
|
||||
|
||||
class ReleasesAPI extends Api {
|
||||
static markAsReadURL = `v1/users/setReleaseNotesViewed`;
|
||||
|
||||
static markAsRead(): AxiosPromise<ApiResponse> {
|
||||
return Api.put(ReleasesAPI.markAsReadURL);
|
||||
}
|
||||
}
|
||||
|
||||
export default ReleasesAPI;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import Api from "./Api";
|
||||
import { AxiosPromise } from "taro-axios";
|
||||
import { GenericApiResponse } from "api/ApiResponses";
|
||||
import { Datasource } from "entities/Datasource";
|
||||
|
||||
class SaasApi extends Api {
|
||||
static url = "v1/saas";
|
||||
static getAppsmithToken(
|
||||
datasourceId: string,
|
||||
pageId: string,
|
||||
): AxiosPromise<GenericApiResponse<string>> {
|
||||
return Api.post(`${SaasApi.url}/${datasourceId}/pages/${pageId}/oauth`);
|
||||
}
|
||||
|
||||
static getAccessToken(
|
||||
datasourceId: string,
|
||||
token: string,
|
||||
): AxiosPromise<GenericApiResponse<Datasource>> {
|
||||
return Api.post(
|
||||
`${SaasApi.url}/${datasourceId}/token?appsmithToken=${token}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SaasApi;
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
import { AxiosPromise } from "taro-axios";
|
||||
import Api from "api/Api";
|
||||
import { ApiResponse } from "./ApiResponses";
|
||||
|
||||
export interface LoginUserRequest {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface CreateUserRequest {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface CreateUserResponse extends ApiResponse {
|
||||
email: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface ForgotPasswordRequest {
|
||||
email: string;
|
||||
}
|
||||
|
||||
export interface TokenPasswordUpdateRequest {
|
||||
token: string;
|
||||
password: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
export interface VerifyTokenRequest {
|
||||
email: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
export interface FetchUserResponse extends ApiResponse {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface FetchUserRequest {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface LeaveOrgRequest {
|
||||
orgId: string;
|
||||
}
|
||||
|
||||
export interface InviteUserRequest {
|
||||
email: string;
|
||||
groupIds: string[];
|
||||
status?: string;
|
||||
}
|
||||
|
||||
export interface UpdateUserRequest {
|
||||
name?: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
class UserApi extends Api {
|
||||
static usersURL = "v1/users";
|
||||
static forgotPasswordURL = `${UserApi.usersURL}/forgotPassword`;
|
||||
static verifyResetPasswordTokenURL = `${UserApi.usersURL}/verifyPasswordResetToken`;
|
||||
static resetPasswordURL = `${UserApi.usersURL}/resetPassword`;
|
||||
static inviteUserURL = "v1/users/invite";
|
||||
static verifyInviteTokenURL = `${UserApi.inviteUserURL}/verify`;
|
||||
static confirmUserInviteURL = `${UserApi.inviteUserURL}/confirm`;
|
||||
static addOrgURL = `${UserApi.usersURL}/addOrganization`;
|
||||
static leaveOrgURL = `${UserApi.usersURL}/leaveOrganization`;
|
||||
static logoutURL = "v1/logout";
|
||||
static currentUserURL = "v1/users/me";
|
||||
static photoURL = "v1/users/photo";
|
||||
static featureFlagsURL = "v1/users/features";
|
||||
|
||||
static createUser(
|
||||
request: CreateUserRequest,
|
||||
): AxiosPromise<CreateUserResponse> {
|
||||
return Api.post(UserApi.usersURL, request);
|
||||
}
|
||||
|
||||
static updateUser(request: UpdateUserRequest): AxiosPromise<ApiResponse> {
|
||||
return Api.put(UserApi.usersURL, request);
|
||||
}
|
||||
|
||||
static fetchUser(request: FetchUserRequest): AxiosPromise<FetchUserResponse> {
|
||||
return Api.get(UserApi.usersURL + "/" + request.id);
|
||||
}
|
||||
|
||||
static getCurrentUser(): AxiosPromise<ApiResponse> {
|
||||
return Api.get(UserApi.currentUserURL);
|
||||
}
|
||||
|
||||
static forgotPassword(
|
||||
request: ForgotPasswordRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.post(UserApi.forgotPasswordURL, request);
|
||||
}
|
||||
|
||||
static verifyResetPasswordToken(
|
||||
request: VerifyTokenRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.get(UserApi.verifyResetPasswordTokenURL, request);
|
||||
}
|
||||
|
||||
static resetPassword(
|
||||
request: TokenPasswordUpdateRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.put(UserApi.resetPasswordURL, request);
|
||||
}
|
||||
|
||||
static inviteUser(request: InviteUserRequest): AxiosPromise<ApiResponse> {
|
||||
return Api.post(UserApi.inviteUserURL, request);
|
||||
}
|
||||
|
||||
static verifyUserInvite(
|
||||
request: VerifyTokenRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.get(UserApi.verifyInviteTokenURL, request);
|
||||
}
|
||||
|
||||
static confirmInvitedUserSignup(
|
||||
request: TokenPasswordUpdateRequest,
|
||||
): AxiosPromise<ApiResponse> {
|
||||
return Api.put(UserApi.confirmUserInviteURL, request);
|
||||
}
|
||||
|
||||
static logoutUser(): AxiosPromise<ApiResponse> {
|
||||
return Api.post(UserApi.logoutURL);
|
||||
}
|
||||
|
||||
static uploadPhoto(request: { file: File }): AxiosPromise<ApiResponse> {
|
||||
const formData = new FormData();
|
||||
if (request.file) {
|
||||
formData.append("file", request.file);
|
||||
}
|
||||
|
||||
return Api.post(UserApi.photoURL, formData, null, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
static deletePhoto(): AxiosPromise<ApiResponse> {
|
||||
return Api.delete(UserApi.photoURL);
|
||||
}
|
||||
|
||||
static leaveOrg(request: LeaveOrgRequest): AxiosPromise<LeaveOrgRequest> {
|
||||
return Api.put(UserApi.leaveOrgURL + "/" + request.orgId);
|
||||
}
|
||||
|
||||
static fetchFeatureFlags(): AxiosPromise<ApiResponse> {
|
||||
return Api.get(UserApi.featureFlagsURL);
|
||||
}
|
||||
}
|
||||
|
||||
export default UserApi;
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import Api from "api/Api";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
import { WidgetConfigProps } from "reducers/entityReducers/widgetConfigReducer";
|
||||
import { AxiosPromise } from "taro-axios";
|
||||
|
||||
export interface WidgetConfigsResponse {
|
||||
config: Record<WidgetType, Partial<WidgetProps> & WidgetConfigProps>;
|
||||
}
|
||||
|
||||
class WidgetConfigsApi extends Api {
|
||||
static url = "/widgetConfigs";
|
||||
static fetchWidgetConfigs(): AxiosPromise<WidgetConfigsResponse> {
|
||||
return Api.get(WidgetConfigsApi.url);
|
||||
}
|
||||
}
|
||||
|
||||
export default WidgetConfigsApi;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import Api from "api/Api";
|
||||
import { WidgetCardProps } from "widgets/BaseWidget";
|
||||
import { AxiosPromise } from "taro-axios";
|
||||
|
||||
export interface WidgetSidebarResponse {
|
||||
cards: { [id: string]: WidgetCardProps[] };
|
||||
}
|
||||
// export interface WidgetCardsPaneRequest {}
|
||||
|
||||
class WidgetSidebarApi extends Api {
|
||||
static url = "/widgetCards";
|
||||
static fetchWidgetCards(): AxiosPromise<WidgetSidebarResponse> {
|
||||
return Api.get(WidgetSidebarApi.url);
|
||||
}
|
||||
}
|
||||
|
||||
export default WidgetSidebarApi;
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
export default {
|
||||
pages: [
|
||||
'pages/index/index',
|
||||
'pages/page1/index',
|
||||
],
|
||||
window: {
|
||||
backgroundTextStyle: 'light',
|
||||
navigationBarBackgroundColor: '#fff',
|
||||
navigationBarTitleText: 'WeChat',
|
||||
navigationBarTextStyle: 'black'
|
||||
},
|
||||
workers: 'worker',
|
||||
"lazyCodeLoading": "requiredComponents",
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
.h5-span {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
view {
|
||||
box-sizing: border-box;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.rich-p {
|
||||
margin: 0;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.rich-img {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { Component } from "react";
|
||||
import { appInitializer } from "utils/AppsmithUtils";
|
||||
|
||||
import "./app.less";
|
||||
|
||||
// init
|
||||
appInitializer();
|
||||
|
||||
class App extends Component {
|
||||
componentDidMount() {}
|
||||
|
||||
componentDidShow() {}
|
||||
|
||||
componentDidHide() {}
|
||||
|
||||
componentDidCatchError() {}
|
||||
|
||||
// 在 App 类中的 render() 函数没有实际作用
|
||||
// 请勿修改此函数
|
||||
render() {
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" fill="none" viewBox="0 0 34 34"><circle cx="17" cy="17" r="17" fill="#C4C4C4"/></svg>
|
||||
|
After Width: | Height: | Size: 148 B |
|
|
@ -0,0 +1,35 @@
|
|||
import React, { useContext } from "react";
|
||||
import { styled } from "linaria/react";
|
||||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
import { RenderModes } from "constants/WidgetConstants";
|
||||
import WidgetFactory from "utils/WidgetFactory";
|
||||
import { ContainerWidgetProps } from "widgets/ContainerWidget";
|
||||
import { useDynamicAppLayout } from "utils/hooks/useDynamicAppLayout";
|
||||
import ReduxContext from "./ReduxContext";
|
||||
|
||||
const PageView = styled.div<{ width: number }>`
|
||||
height: 100%;
|
||||
position: relative;
|
||||
width: ${(props) => props.width}px;
|
||||
margin: 0 auto;
|
||||
`;
|
||||
|
||||
type AppPageProps = {
|
||||
dsl: ContainerWidgetProps<WidgetProps>;
|
||||
pageName?: string;
|
||||
appName?: string;
|
||||
};
|
||||
|
||||
export function AppPage(props: AppPageProps) {
|
||||
const { useDispatch, useSelector, context } = useContext(ReduxContext);
|
||||
const dispatch = useDispatch();
|
||||
useDynamicAppLayout(dispatch, useSelector);
|
||||
return (
|
||||
<PageView width={props.dsl.rightColumn}>
|
||||
{props.dsl.widgetId &&
|
||||
WidgetFactory.createWidget({ ...props.dsl, context }, RenderModes.PAGE)}
|
||||
</PageView>
|
||||
);
|
||||
}
|
||||
|
||||
export default AppPage;
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
import { useEffect, useContext } from "react";
|
||||
import { styled } from "linaria/react";
|
||||
import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import { getIsInitialized } from "selectors/appViewSelectors";
|
||||
import { executeAction } from "actions/widgetActions";
|
||||
import { ExecuteActionPayload } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import {
|
||||
resetChildrenMetaProperty,
|
||||
updateWidgetMetaProperty,
|
||||
} from "actions/metaActions";
|
||||
import { getShowTabBar } from "selectors/editorSelectors";
|
||||
import { EditorContext } from "components/editorComponents/EditorContextProvider";
|
||||
import AppViewerPageContainer from "./AppViewerPageContainer";
|
||||
import { ConfigProvider } from "@taroify/core";
|
||||
import { taroifyTheme } from "constants/DefaultTheme";
|
||||
import TabBar from "components/designSystems/taro/TabBar";
|
||||
import Taro from "@tarojs/taro";
|
||||
import ReduxContext from "./ReduxContext";
|
||||
import { editorInitializer } from "utils/EditorUtils";
|
||||
|
||||
const AppViewerBody = styled.section<{
|
||||
showTabBar: boolean;
|
||||
}>`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
height: calc(
|
||||
100vh -
|
||||
${(props) =>
|
||||
props.showTabBar ? "100rpx - constant(safe-area-inset-bottom)" : "0px"}
|
||||
);
|
||||
height: calc(
|
||||
100vh -
|
||||
${(props) =>
|
||||
props.showTabBar ? "100rpx - env(safe-area-inset-bottom)" : "0px"}
|
||||
);
|
||||
`;
|
||||
|
||||
const ContainerWrapper = styled.div`
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: translate(0, 0);
|
||||
`;
|
||||
|
||||
const AppViewerBodyContainer = styled.div`
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
margin: 0 auto;
|
||||
`;
|
||||
|
||||
const LATEST_SCENE_APP_ID = "PAGEPLUG_LATEST_SCENE_APP_ID";
|
||||
|
||||
const AppViewer = () => {
|
||||
const { useDispatch, useSelector } = useContext(ReduxContext);
|
||||
const dispatch = useDispatch();
|
||||
const initializeAppViewer = (applicationId: string, pageId?: string) => {
|
||||
dispatch({
|
||||
type: ReduxActionTypes.INITIALIZE_PAGE_VIEWER,
|
||||
payload: { applicationId, pageId },
|
||||
});
|
||||
};
|
||||
const isInitialized = useSelector(getIsInitialized);
|
||||
const showTabBar = useSelector(getShowTabBar);
|
||||
|
||||
useEffect(() => {
|
||||
const { applicationId, pageId, scene } =
|
||||
Taro.getCurrentInstance().router?.params || {};
|
||||
editorInitializer();
|
||||
if (scene) {
|
||||
Taro.setStorageSync(LATEST_SCENE_APP_ID, scene);
|
||||
initializeAppViewer(scene);
|
||||
} else if (applicationId) {
|
||||
initializeAppViewer(applicationId, pageId);
|
||||
} else {
|
||||
const lastScene = Taro.getStorageSync(LATEST_SCENE_APP_ID);
|
||||
initializeAppViewer(lastScene || DEFAULT_APP);
|
||||
}
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<EditorContext.Provider
|
||||
value={{
|
||||
executeAction: (actionPayload: ExecuteActionPayload) =>
|
||||
dispatch(executeAction(actionPayload)),
|
||||
updateWidgetMetaProperty: (
|
||||
widgetId: string,
|
||||
propertyName: string,
|
||||
propertyValue: any
|
||||
) =>
|
||||
dispatch(
|
||||
updateWidgetMetaProperty(widgetId, propertyName, propertyValue)
|
||||
),
|
||||
resetChildrenMetaProperty: (widgetId: string) =>
|
||||
dispatch(resetChildrenMetaProperty(widgetId)),
|
||||
}}
|
||||
>
|
||||
<ConfigProvider theme={taroifyTheme}>
|
||||
<ContainerWrapper>
|
||||
<AppViewerBodyContainer>
|
||||
<AppViewerBody showTabBar={showTabBar}>
|
||||
{isInitialized && <AppViewerPageContainer />}
|
||||
</AppViewerBody>
|
||||
</AppViewerBodyContainer>
|
||||
</ContainerWrapper>
|
||||
<TabBar />
|
||||
</ConfigProvider>
|
||||
</EditorContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppViewer;
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
import React, { useContext } from "react";
|
||||
import { getIsFetchingPage } from "selectors/appViewSelectors";
|
||||
import { styled } from "linaria/react";
|
||||
import { Loading, SafeArea } from "@taroify/core";
|
||||
import AppPage from "./AppPage";
|
||||
import {
|
||||
getCanvasWidgetDsl,
|
||||
getCurrentPageName,
|
||||
} from "selectors/editorSelectors";
|
||||
import { getCurrentApplication } from "selectors/applicationSelectors";
|
||||
import ReduxContext from "./ReduxContext";
|
||||
|
||||
const LoadingContainer = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
|
||||
.taroify-loading {
|
||||
color: var(--primary-color);
|
||||
|
||||
.taroify-loading__text {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const Section = styled.section`
|
||||
background: #f6f6f6;
|
||||
height: max-content;
|
||||
min-height: 100%;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
`;
|
||||
|
||||
const SafeFixedArea = styled.div<{
|
||||
height: number;
|
||||
}>`
|
||||
margin-bottom: ${(props) => props.height}px;
|
||||
`;
|
||||
|
||||
const AppViewerPageContainer: any = () => {
|
||||
const { useSelector } = useContext(ReduxContext);
|
||||
const currentApp = useSelector(getCurrentApplication);
|
||||
const widgets = useSelector(getCanvasWidgetDsl);
|
||||
const isFetchingPage = useSelector(getIsFetchingPage);
|
||||
const currentPageName = useSelector(getCurrentPageName);
|
||||
const currentAppName = currentApp?.name;
|
||||
const hasFixedWidget = widgets.children?.find(
|
||||
(w) => w.type === "TARO_BOTTOM_BAR_WIDGET"
|
||||
);
|
||||
|
||||
const pageNotFound = <div>页面空空如也😅</div>;
|
||||
if (isFetchingPage) {
|
||||
return (
|
||||
<LoadingContainer>
|
||||
<Loading size="48px" />
|
||||
</LoadingContainer>
|
||||
);
|
||||
} else if (
|
||||
!isFetchingPage &&
|
||||
!(widgets && widgets.children && widgets.children.length > 0)
|
||||
) {
|
||||
return pageNotFound;
|
||||
} else if (!isFetchingPage && widgets) {
|
||||
return (
|
||||
<Section>
|
||||
<AppPage
|
||||
appName={currentAppName}
|
||||
dsl={widgets}
|
||||
pageName={currentPageName}
|
||||
/>
|
||||
{hasFixedWidget ? (
|
||||
<SafeFixedArea height={hasFixedWidget?.height || 0} />
|
||||
) : null}
|
||||
<SafeArea position="bottom" />
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default AppViewerPageContainer;
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import React from "react";
|
||||
import {
|
||||
Provider,
|
||||
createStoreHook,
|
||||
createDispatchHook,
|
||||
createSelectorHook,
|
||||
} from "react-redux";
|
||||
import { newStore } from "store";
|
||||
import AppViewer from "./AppViewer";
|
||||
import ReduxContext from "./ReduxContext";
|
||||
|
||||
const Page = () => {
|
||||
const context: any = React.createContext(null);
|
||||
const useStore = createStoreHook(context);
|
||||
const useDispatch = createDispatchHook(context);
|
||||
const useSelector = createSelectorHook(context);
|
||||
const store = newStore();
|
||||
const contextValue = {
|
||||
useStore,
|
||||
useSelector,
|
||||
useDispatch,
|
||||
context,
|
||||
};
|
||||
return (
|
||||
<ReduxContext.Provider value={contextValue}>
|
||||
<Provider store={store} context={context}>
|
||||
<AppViewer />
|
||||
</Provider>
|
||||
</ReduxContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Page;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import React from "react";
|
||||
|
||||
const noop = () => {};
|
||||
const ReduxContext = React.createContext<{
|
||||
useStore: any;
|
||||
useSelector: any;
|
||||
useDispatch: any;
|
||||
context: any;
|
||||
}>({
|
||||
useStore: noop,
|
||||
useSelector: noop,
|
||||
useDispatch: noop,
|
||||
context: null,
|
||||
});
|
||||
export default ReduxContext;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { Component } from "react";
|
||||
import { Color } from "constants/Colors";
|
||||
|
||||
/***
|
||||
* Components are responsible for binding render inputs to corresponding UI SDKs
|
||||
*/
|
||||
abstract class BaseComponent<T extends ComponentProps> extends Component<T> {}
|
||||
|
||||
export interface ComponentProps {
|
||||
widgetId: string;
|
||||
widgetName?: string;
|
||||
isDisabled?: boolean;
|
||||
isVisible?: boolean;
|
||||
backgroundColor?: Color;
|
||||
}
|
||||
|
||||
export default BaseComponent;
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import React, { ReactNode, useRef, RefObject } from "react";
|
||||
import { styled } from "linaria/react";
|
||||
import { ComponentProps } from "./BaseComponent";
|
||||
import { Color } from "constants/Colors";
|
||||
|
||||
const StyledContainerComponent: any = styled.div`
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: ${(props) => props.backgroundColor || "unset"};
|
||||
opacity: ${(props) => (props.resizeDisabled ? "0.8" : "1")};
|
||||
position: relative;
|
||||
box-shadow: ${(props) =>
|
||||
props.selected ? "0px 0px 0px 3px rgba(59,130,246,0.5)" : "none"};
|
||||
z-index: ${(props) => (props.focused ? "3" : props.selected ? "2" : "1")};
|
||||
`;
|
||||
|
||||
function ContainerComponent(props: ContainerComponentProps) {
|
||||
const containerStyle = props.containerStyle || "card";
|
||||
const containerRef: RefObject<HTMLDivElement> = useRef<HTMLDivElement>(null);
|
||||
return (
|
||||
<StyledContainerComponent
|
||||
{...props}
|
||||
containerStyle={containerStyle}
|
||||
// Before you remove: generateClassName is used for bounding the resizables within this canvas
|
||||
// getCanvasClassName is used to add a scrollable parent.
|
||||
ref={containerRef}
|
||||
>
|
||||
{props.children}
|
||||
</StyledContainerComponent>
|
||||
);
|
||||
}
|
||||
|
||||
export type ContainerStyle = "border" | "card" | "rounded-border" | "none";
|
||||
|
||||
export interface ContainerComponentProps extends ComponentProps {
|
||||
containerStyle?: ContainerStyle;
|
||||
children?: ReactNode;
|
||||
className?: string;
|
||||
backgroundColor?: Color;
|
||||
shouldScrollContents?: boolean;
|
||||
resizeDisabled?: boolean;
|
||||
selected?: boolean;
|
||||
focused?: boolean;
|
||||
minHeight?: number;
|
||||
}
|
||||
|
||||
export default ContainerComponent;
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
import React, { CSSProperties, ReactNode, useMemo } from "react";
|
||||
import { BaseStyle } from "widgets/BaseWidget";
|
||||
import { WIDGET_PADDING } from "constants/WidgetConstants";
|
||||
import { generateClassName } from "utils/generators";
|
||||
import { styled } from 'linaria/react';
|
||||
import { Layers } from "constants/Layers";
|
||||
|
||||
const PositionedWidget = styled.div`
|
||||
&:hover {
|
||||
z-index: 2 !important;
|
||||
}
|
||||
`;
|
||||
type PositionedContainerProps = {
|
||||
style: BaseStyle;
|
||||
children: ReactNode;
|
||||
widgetId: string;
|
||||
widgetType: string;
|
||||
selected?: boolean;
|
||||
focused?: boolean;
|
||||
resizeDisabled?: boolean;
|
||||
};
|
||||
|
||||
export function PositionedContainer(props: PositionedContainerProps) {
|
||||
const x = props.style.xPosition + (props.style.xPositionUnit || "px");
|
||||
const y = props.style.yPosition + (props.style.yPositionUnit || "px");
|
||||
const padding = WIDGET_PADDING;
|
||||
// memoized classname
|
||||
const containerClassName = useMemo(() => {
|
||||
return (
|
||||
generateClassName(props.widgetId) +
|
||||
" positioned-widget " +
|
||||
`t--widget-${props.widgetType
|
||||
.split("_")
|
||||
.join("")
|
||||
.toLowerCase()}`
|
||||
);
|
||||
}, [props.widgetType, props.widgetId]);
|
||||
const containerStyle: CSSProperties = useMemo(() => {
|
||||
return {
|
||||
position: "absolute",
|
||||
left: x,
|
||||
top: y,
|
||||
height: props.style.componentHeight + (props.style.heightUnit || "px"),
|
||||
width: props.style.componentWidth + (props.style.widthUnit || "px"),
|
||||
padding: padding + "px",
|
||||
zIndex:
|
||||
props.selected || props.focused
|
||||
? Layers.selectedWidget
|
||||
: Layers.positionedWidget,
|
||||
backgroundColor: "inherit",
|
||||
};
|
||||
}, [props.style]);
|
||||
|
||||
const stopEventPropagation = (e: any) => {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
return (
|
||||
<PositionedWidget
|
||||
className={containerClassName}
|
||||
data-testid="test-widget"
|
||||
id={props.widgetId}
|
||||
key={`positioned-container-${props.widgetId}`}
|
||||
onClick={stopEventPropagation}
|
||||
//Before you remove: This is used by property pane to reference the element
|
||||
style={containerStyle}
|
||||
>
|
||||
{props.children}
|
||||
</PositionedWidget>
|
||||
);
|
||||
}
|
||||
|
||||
PositionedContainer.padding = WIDGET_PADDING;
|
||||
|
||||
export default PositionedContainer;
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
import { isString } from "lodash";
|
||||
import dayjs from "dayjs";
|
||||
import { TextSize } from "constants/WidgetConstants";
|
||||
|
||||
export type TableSizes = {
|
||||
COLUMN_HEADER_HEIGHT: number;
|
||||
TABLE_HEADER_HEIGHT: number;
|
||||
ROW_HEIGHT: number;
|
||||
ROW_FONT_SIZE: number;
|
||||
};
|
||||
|
||||
export enum CompactModeTypes {
|
||||
SHORT = "SHORT",
|
||||
DEFAULT = "DEFAULT",
|
||||
TALL = "TALL",
|
||||
}
|
||||
|
||||
export enum CellAlignmentTypes {
|
||||
LEFT = "LEFT",
|
||||
RIGHT = "RIGHT",
|
||||
CENTER = "CENTER",
|
||||
}
|
||||
|
||||
export enum VerticalAlignmentTypes {
|
||||
TOP = "TOP",
|
||||
BOTTOM = "BOTTOM",
|
||||
CENTER = "CENTER",
|
||||
}
|
||||
|
||||
export const TABLE_SIZES: { [key: string]: TableSizes } = {
|
||||
[CompactModeTypes.DEFAULT]: {
|
||||
COLUMN_HEADER_HEIGHT: 32,
|
||||
TABLE_HEADER_HEIGHT: 38,
|
||||
ROW_HEIGHT: 40,
|
||||
ROW_FONT_SIZE: 14,
|
||||
},
|
||||
[CompactModeTypes.SHORT]: {
|
||||
COLUMN_HEADER_HEIGHT: 32,
|
||||
TABLE_HEADER_HEIGHT: 38,
|
||||
ROW_HEIGHT: 20,
|
||||
ROW_FONT_SIZE: 12,
|
||||
},
|
||||
[CompactModeTypes.TALL]: {
|
||||
COLUMN_HEADER_HEIGHT: 32,
|
||||
TABLE_HEADER_HEIGHT: 38,
|
||||
ROW_HEIGHT: 60,
|
||||
ROW_FONT_SIZE: 18,
|
||||
},
|
||||
};
|
||||
|
||||
export enum ColumnTypes {
|
||||
DATE = "date",
|
||||
VIDEO = "video",
|
||||
IMAGE = "image",
|
||||
TEXT = "text",
|
||||
NUMBER = "number",
|
||||
URL = "url",
|
||||
}
|
||||
|
||||
export enum OperatorTypes {
|
||||
OR = "OR",
|
||||
AND = "AND",
|
||||
}
|
||||
|
||||
export interface TableStyles {
|
||||
cellBackground?: string;
|
||||
textColor?: string;
|
||||
textSize?: TextSize;
|
||||
fontStyle?: string;
|
||||
horizontalAlignment?: CellAlignment;
|
||||
verticalAlignment?: VerticalAlignment;
|
||||
}
|
||||
|
||||
export type CompactMode = keyof typeof CompactModeTypes;
|
||||
export type Condition = keyof typeof ConditionFunctions | "";
|
||||
export type Operator = keyof typeof OperatorTypes;
|
||||
export type CellAlignment = keyof typeof CellAlignmentTypes;
|
||||
export type VerticalAlignment = keyof typeof VerticalAlignmentTypes;
|
||||
|
||||
export interface ReactTableFilter {
|
||||
column: string;
|
||||
operator: Operator;
|
||||
condition: Condition;
|
||||
value: any;
|
||||
}
|
||||
|
||||
export interface CellLayoutProperties {
|
||||
horizontalAlignment?: CellAlignment;
|
||||
verticalAlignment?: VerticalAlignment;
|
||||
textSize?: TextSize;
|
||||
fontStyle?: string;
|
||||
textColor?: string;
|
||||
cellBackground?: string;
|
||||
buttonStyle?: string;
|
||||
buttonLabelColor?: string;
|
||||
buttonLabel?: string;
|
||||
displayText?: string;
|
||||
}
|
||||
|
||||
export interface TableColumnMetaProps {
|
||||
isHidden: boolean;
|
||||
format?: string;
|
||||
inputFormat?: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface TableColumnProps {
|
||||
Header: string;
|
||||
accessor: string;
|
||||
width?: number;
|
||||
minWidth: number;
|
||||
draggable: boolean;
|
||||
isHidden?: boolean;
|
||||
isAscOrder?: boolean;
|
||||
metaProperties?: TableColumnMetaProps;
|
||||
isDerived?: boolean;
|
||||
columnProperties: ColumnProperties;
|
||||
}
|
||||
export interface ReactTableColumnProps extends TableColumnProps {
|
||||
Cell: (props: any) => JSX.Element;
|
||||
}
|
||||
|
||||
export interface ColumnProperties {
|
||||
id: string;
|
||||
label: string;
|
||||
columnType: string;
|
||||
isVisible: boolean;
|
||||
index: number;
|
||||
width: number;
|
||||
cellBackground?: string;
|
||||
horizontalAlignment?: CellAlignment;
|
||||
verticalAlignment?: VerticalAlignment;
|
||||
textSize?: TextSize;
|
||||
fontStyle?: string;
|
||||
textColor?: string;
|
||||
enableFilter?: boolean;
|
||||
enableSort?: boolean;
|
||||
isDerived: boolean;
|
||||
computedValue: string;
|
||||
buttonLabel?: string;
|
||||
buttonStyle?: string;
|
||||
buttonLabelColor?: string;
|
||||
onClick?: string;
|
||||
outputFormat?: string;
|
||||
inputFormat?: string;
|
||||
dropdownOptions?: string;
|
||||
onOptionChange?: string;
|
||||
displayText?: string;
|
||||
}
|
||||
|
||||
export const ConditionFunctions: {
|
||||
[key: string]: (a: any, b: any) => boolean;
|
||||
} = {
|
||||
isExactly: (a: any, b: any) => {
|
||||
return a.toString() === b.toString();
|
||||
},
|
||||
empty: (a: any) => {
|
||||
return a === "" || a === undefined || a === null;
|
||||
},
|
||||
notEmpty: (a: any) => {
|
||||
return a !== "" && a !== undefined && a !== null;
|
||||
},
|
||||
notEqualTo: (a: any, b: any) => {
|
||||
return a.toString() !== b.toString();
|
||||
},
|
||||
isEqualTo: (a: any, b: any) => {
|
||||
return a.toString() === b.toString();
|
||||
},
|
||||
lessThan: (a: any, b: any) => {
|
||||
const numericB = Number(b);
|
||||
const numericA = Number(a);
|
||||
return numericA < numericB;
|
||||
},
|
||||
lessThanEqualTo: (a: any, b: any) => {
|
||||
const numericB = Number(b);
|
||||
const numericA = Number(a);
|
||||
return numericA <= numericB;
|
||||
},
|
||||
greaterThan: (a: any, b: any) => {
|
||||
const numericB = Number(b);
|
||||
const numericA = Number(a);
|
||||
return numericA > numericB;
|
||||
},
|
||||
greaterThanEqualTo: (a: any, b: any) => {
|
||||
const numericB = Number(b);
|
||||
const numericA = Number(a);
|
||||
return numericA >= numericB;
|
||||
},
|
||||
contains: (a: any, b: any) => {
|
||||
if (isString(a) && isString(b)) {
|
||||
return a.includes(b);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
doesNotContain: (a: any, b: any) => {
|
||||
if (isString(a) && isString(b)) {
|
||||
return !a.includes(b);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
startsWith: (a: any, b: any) => {
|
||||
if (isString(a) && isString(b)) {
|
||||
return a.indexOf(b) === 0;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
endsWith: (a: any, b: any) => {
|
||||
if (isString(a) && isString(b)) {
|
||||
return a.length === a.lastIndexOf(b) + b.length;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
is: (a: any, b: any) => {
|
||||
return dayjs(a).isSame(dayjs(b), "day");
|
||||
},
|
||||
isNot: (a: any, b: any) => {
|
||||
return !dayjs(a).isSame(dayjs(b), "day");
|
||||
},
|
||||
isAfter: (a: any, b: any) => {
|
||||
return !dayjs(a).isAfter(dayjs(b), "day");
|
||||
},
|
||||
isBefore: (a: any, b: any) => {
|
||||
return !dayjs(a).isBefore(dayjs(b), "day");
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import { uniq, without } from "lodash";
|
||||
import { ColumnProperties } from "./Constants";
|
||||
|
||||
export const removeSpecialChars = (value: string, limit?: number) => {
|
||||
const separatorRegex = /\s/;
|
||||
return value
|
||||
.split(separatorRegex)
|
||||
.join("_")
|
||||
.slice(0, limit || 30);
|
||||
};
|
||||
|
||||
export const getAllTableColumnKeys = (
|
||||
tableData?: Array<Record<string, unknown>>,
|
||||
) => {
|
||||
const columnKeys: string[] = [];
|
||||
if (tableData) {
|
||||
for (let i = 0, tableRowCount = tableData.length; i < tableRowCount; i++) {
|
||||
const row = tableData[i];
|
||||
for (const key in row) {
|
||||
// Replace all special characters to _, limit key length to 200 characters.
|
||||
const sanitizedKey = removeSpecialChars(key, 200);
|
||||
if (!columnKeys.includes(sanitizedKey)) {
|
||||
columnKeys.push(sanitizedKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return columnKeys;
|
||||
};
|
||||
|
||||
export const reorderColumns = (
|
||||
columns: Record<string, ColumnProperties>,
|
||||
columnOrder: string[],
|
||||
) => {
|
||||
const newColumnsInOrder: Record<string, ColumnProperties> = {};
|
||||
uniq(columnOrder).forEach((id: string, index: number) => {
|
||||
if (columns[id]) newColumnsInOrder[id] = { ...columns[id], index };
|
||||
});
|
||||
const remaining = without(
|
||||
Object.keys(columns),
|
||||
...Object.keys(newColumnsInOrder),
|
||||
);
|
||||
const len = Object.keys(newColumnsInOrder).length;
|
||||
if (remaining && remaining.length > 0) {
|
||||
remaining.forEach((id: string, index: number) => {
|
||||
newColumnsInOrder[id] = { ...columns[id], index: len + index };
|
||||
});
|
||||
}
|
||||
return newColumnsInOrder;
|
||||
};
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import React, { useContext, useMemo } from "react";
|
||||
import clsx from "clsx";
|
||||
import { ActionBarProps } from "./PropsType";
|
||||
import ActionBarContext from "./ActionBarContext";
|
||||
import { BEM, createBEM } from "../SkuComponent/bem";
|
||||
|
||||
const ActionBar: React.FC<ActionBarProps> = (props: any) => {
|
||||
const bem = createBEM("rv-action-bar");
|
||||
const children = useMemo(() => React.Children.toArray(props.children), [
|
||||
props.children,
|
||||
]);
|
||||
|
||||
return (
|
||||
<ActionBarContext.Provider value={{ parent: { children } }}>
|
||||
<div
|
||||
className={clsx(props.className, bem(), {
|
||||
"rv-safe-area-bottom": props.safeAreaInsetBottom,
|
||||
})}
|
||||
style={props.style}
|
||||
>
|
||||
{React.Children.toArray(props.children)
|
||||
.filter(Boolean)
|
||||
.map((child: any, index: number) =>
|
||||
React.cloneElement(child, {
|
||||
index,
|
||||
}),
|
||||
)}
|
||||
</div>
|
||||
</ActionBarContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
ActionBar.defaultProps = {
|
||||
safeAreaInsetBottom: true,
|
||||
};
|
||||
|
||||
export default ActionBar;
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import React, { useContext, useMemo } from "react";
|
||||
import clsx from "clsx";
|
||||
import { ActionBarButtonProps } from "./PropsType";
|
||||
import { Button } from "@taroify/core";
|
||||
import ActionBarContext from "./ActionBarContext";
|
||||
import { BEM, createBEM } from "../SkuComponent/bem";
|
||||
|
||||
const ActionBarButton: React.FC<ActionBarButtonProps> = (props) => {
|
||||
const { type, icon, text, color, loading, disabled, index } = props;
|
||||
const bem = createBEM("rv-action-bar-button");
|
||||
const { parent } = useContext(ActionBarContext);
|
||||
|
||||
const isFirst = useMemo(() => {
|
||||
if (parent && typeof index !== "undefined") {
|
||||
const prev = parent.children[index - 1];
|
||||
return !(prev && "isButton" in prev.type);
|
||||
}
|
||||
return false;
|
||||
}, [index, parent]);
|
||||
|
||||
const isLast = useMemo(() => {
|
||||
if (parent && typeof index !== "undefined") {
|
||||
const next = parent.children[index + 1];
|
||||
return !(next && "isButton" in next.type);
|
||||
}
|
||||
return false;
|
||||
}, [index, parent]);
|
||||
|
||||
const style = {
|
||||
"--rv-action-bar-theme-color": color || "unset",
|
||||
...props.style,
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
className={clsx(
|
||||
props.className,
|
||||
bem([
|
||||
type,
|
||||
{
|
||||
last: isLast,
|
||||
first: isFirst,
|
||||
},
|
||||
]),
|
||||
)}
|
||||
style={style}
|
||||
size="large"
|
||||
icon={icon}
|
||||
color={type}
|
||||
loading={loading}
|
||||
disabled={disabled}
|
||||
onClick={props.onClick}
|
||||
>
|
||||
{props.children ? props.children : text}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
const ActionBarButtonNameSpace = Object.assign(ActionBarButton, {
|
||||
isButton: true,
|
||||
});
|
||||
|
||||
export default ActionBarButtonNameSpace;
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { createContext, Context } from "react";
|
||||
|
||||
export interface ActionBarState {
|
||||
parent?: Record<string, any>;
|
||||
}
|
||||
|
||||
const ActionButtonContext: Context<ActionBarState> = createContext({});
|
||||
|
||||
export default ActionButtonContext;
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import React, { isValidElement } from "react";
|
||||
import clsx from "clsx";
|
||||
import { ActionBarIconProps } from "./PropsType";
|
||||
import { createVanIconComponent } from "@taroify/icons/van";
|
||||
import { Badge } from "@taroify/core";
|
||||
import { BEM, createBEM } from "../SkuComponent/bem";
|
||||
|
||||
const ActionBarIcon: React.FC<ActionBarIconProps> = (props) => {
|
||||
const bem = createBEM("rv-action-bar-icon");
|
||||
|
||||
const renderIcon = () => {
|
||||
const { badge, icon, color } = props;
|
||||
let iconContent = icon;
|
||||
if (typeof icon === "string") {
|
||||
const Icon = createVanIconComponent(icon);
|
||||
iconContent = <Icon color={color} size={20} />;
|
||||
}
|
||||
if (isValidElement(iconContent)) {
|
||||
return <Badge {...badge}>{iconContent}</Badge>;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
role="button"
|
||||
className={clsx(props.className, bem())}
|
||||
style={props.style}
|
||||
tabIndex={0}
|
||||
onClick={props.onClick}
|
||||
>
|
||||
{renderIcon()}
|
||||
{props.children || props.text}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ActionBarIcon;
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import React, { CSSProperties } from "react";
|
||||
|
||||
export interface BaseTypeProps {
|
||||
style?: CSSProperties | any;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export interface ActionBarProps extends BaseTypeProps {
|
||||
/** 是否开启底部安全区适配 */
|
||||
safeAreaInsetBottom?: boolean;
|
||||
}
|
||||
|
||||
export interface ActionBarIconProps extends BaseTypeProps {
|
||||
/** 按钮文字 */
|
||||
text?: React.ReactNode;
|
||||
/** 图标 */
|
||||
icon?: string | React.ReactNode;
|
||||
/** 图标颜色 */
|
||||
color?: string;
|
||||
/** 图标额外类名 */
|
||||
iconClass?: string;
|
||||
/** 图标类名前缀,等同于 Icon 组件的 class-prefix 属性 */
|
||||
iconPrefix?: string;
|
||||
/** 图标右上角徽标的内容 */
|
||||
badge?: any;
|
||||
onClick?: (event: any) => void;
|
||||
}
|
||||
|
||||
export interface ActionBarButtonProps extends BaseTypeProps {
|
||||
/** 按钮文字 */
|
||||
text?: React.ReactNode;
|
||||
/** 按钮类型 */
|
||||
type?: any;
|
||||
/** 按钮图标 */
|
||||
icon?: string | React.ReactNode;
|
||||
/** 按钮颜色,支持传入 linear-gradient 渐变色 */
|
||||
color?: string;
|
||||
/** 是否禁用按钮 */
|
||||
disabled?: boolean;
|
||||
/** 是否显示为加载状态 */
|
||||
loading?: boolean;
|
||||
onClick?: (event: any) => void;
|
||||
/** @private */
|
||||
index?: number;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import ActionBar from "./ActionBar";
|
||||
import ActionBarIcon from "./ActionBarIcon";
|
||||
import ActionBarButton from "./ActionBarButton";
|
||||
import "./style/index.less";
|
||||
|
||||
const ActionBarNamespace = Object.assign(ActionBar, {
|
||||
Icon: ActionBarIcon,
|
||||
Button: ActionBarButton,
|
||||
});
|
||||
|
||||
export { ActionBarNamespace as ActionBar, ActionBarIcon, ActionBarButton };
|
||||
export default ActionBarNamespace;
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
@import './var.less';
|
||||
|
||||
.@{rv-prefix}-action-bar {
|
||||
--rv-action-bar-theme-color: @red;
|
||||
--rv-action-bar-background-color: @action-bar-background-color;
|
||||
--rv-action-bar-height: @action-bar-height;
|
||||
--rv-action-bar-button-height: @action-bar-button-height;
|
||||
--rv-action-bar-icon-width: @action-bar-icon-width;
|
||||
--rv-action-bar-icon-height: @action-bar-icon-height;
|
||||
--rv-action-bar-icon-color: @action-bar-icon-color;
|
||||
--rv-action-bar-icon-size: @action-bar-icon-size;
|
||||
--rv-action-bar-icon-font-size: @action-bar-icon-font-size;
|
||||
--rv-action-bar-icon-active-color: @action-bar-icon-active-color;
|
||||
--rv-action-bar-icon-text-color: @action-bar-icon-text-color;
|
||||
--rv-action-bar-icon-background-color: @action-bar-icon-background-color;
|
||||
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: content-box;
|
||||
height: var(--rv-action-bar-height);
|
||||
background-color: var(--rv-action-bar-background-color);
|
||||
}
|
||||
|
||||
.@{rv-prefix}-action-bar-button {
|
||||
flex: 1;
|
||||
height: var(--rv-action-bar-button-height);
|
||||
font-weight: @font-weight-bold;
|
||||
font-size: @font-size-md;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
|
||||
&--first {
|
||||
margin-left: 5 * @hd;
|
||||
border-top-left-radius: @border-radius-max;
|
||||
border-bottom-left-radius: @border-radius-max;
|
||||
}
|
||||
|
||||
&--last {
|
||||
margin-right: 5 * @hd;
|
||||
border-top-right-radius: @border-radius-max;
|
||||
border-bottom-right-radius: @border-radius-max;
|
||||
}
|
||||
|
||||
&--warning {
|
||||
background: transparent;
|
||||
color: var(--rv-action-bar-theme-color);
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
content: ' ';
|
||||
transform: translate(-50%, -50%);
|
||||
background: currentColor;
|
||||
opacity: 0.2;
|
||||
border-color: currentColor;
|
||||
border-style: inherit;
|
||||
border-width: inherit;
|
||||
border-radius: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
&--danger {
|
||||
background: var(--rv-action-bar-theme-color);
|
||||
}
|
||||
|
||||
@media (max-width: 321px) {
|
||||
font-size: 13 * @hd;
|
||||
}
|
||||
}
|
||||
|
||||
.@{rv-prefix}-action-bar-icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-width: var(--rv-action-bar-icon-width);
|
||||
height: var(--rv-action-bar-icon-height);
|
||||
color: var(--rv-action-bar-icon-text-color);
|
||||
font-size: var(--rv-action-bar-icon-font-size);
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
background-color: var(--rv-action-bar-icon-background-color);
|
||||
cursor: pointer;
|
||||
|
||||
& > .taroify-badge-wrapper {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--rv-action-bar-icon-active-color);
|
||||
}
|
||||
|
||||
&__icon {
|
||||
margin: 0 auto @padding-base;
|
||||
color: var(--rv-action-bar-icon-color);
|
||||
font-size: var(--rv-action-bar-icon-size);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
@import '../../rvStyle/var.less';
|
||||
|
||||
@action-bar-background-color: transparent;
|
||||
@action-bar-height: 50 * @hd;
|
||||
|
||||
@action-bar-button-height: 40 * @hd;
|
||||
@action-bar-button-warning-color: @gradient-orange;
|
||||
@action-bar-button-danger-color: @gradient-red;
|
||||
|
||||
@action-bar-icon-width: 48 * @hd;
|
||||
@action-bar-icon-height: 100%;
|
||||
@action-bar-icon-color: @text-color;
|
||||
@action-bar-icon-size: 18 * @hd;
|
||||
@action-bar-icon-font-size: @font-size-xs;
|
||||
@action-bar-icon-active-color: @active-color;
|
||||
@action-bar-icon-text-color: @gray-7;
|
||||
@action-bar-icon-background-color: transparent;
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import React, { ReactNode, useContext } from "react";
|
||||
import { styled } from "linaria/react";
|
||||
import { getCanvasClassName } from "utils/generators";
|
||||
import { Popup } from "@taroify/core";
|
||||
import { PopupProps } from "@taroify/core/popup/popup";
|
||||
import { getShowTabBar } from "selectors/editorSelectors";
|
||||
import ReduxContext from "components/common/ReduxContext";
|
||||
import { transformDynamicSize } from "utils/AppsmithUtils";
|
||||
|
||||
const Container = styled(Popup)<
|
||||
{
|
||||
height: number;
|
||||
showTabBar: boolean;
|
||||
} & PopupProps
|
||||
>`
|
||||
height: calc(
|
||||
${(props) => transformDynamicSize(props.height)} +
|
||||
${(props) =>
|
||||
props.showTabBar ? "0px" : "constant(safe-area-inset-bottom)"}
|
||||
);
|
||||
height: calc(
|
||||
${(props) => transformDynamicSize(props.height)} +
|
||||
${(props) => (props.showTabBar ? "0px" : "env(safe-area-inset-bottom)")}
|
||||
);
|
||||
max-height: 200px;
|
||||
min-height: 80px;
|
||||
overflow: visible;
|
||||
background: #fff;
|
||||
z-index: 1009;
|
||||
`;
|
||||
|
||||
const Content = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
export type BottomBarComponentProps = {
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
height?: number;
|
||||
};
|
||||
|
||||
/* eslint-disable react/display-name */
|
||||
export function BottomBarComponent(props: BottomBarComponentProps) {
|
||||
const { useSelector } = useContext(ReduxContext);
|
||||
const showTabBar = useSelector(getShowTabBar);
|
||||
return (
|
||||
<Container
|
||||
defaultOpen
|
||||
placement="bottom"
|
||||
height={props.height}
|
||||
duration={0}
|
||||
showTabBar={showTabBar}
|
||||
>
|
||||
<Popup.Backdrop open={false} closeable={false} />
|
||||
<Content className={`${getCanvasClassName()} ${props.className}`}>
|
||||
{props.children}
|
||||
</Content>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
export default BottomBarComponent;
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
import React from "react";
|
||||
import { Button } from "@taroify/core";
|
||||
import { transformDynamicSize } from "utils/AppsmithUtils";
|
||||
|
||||
export enum FontWeight {
|
||||
BOLD = "bold",
|
||||
NORMAL = "normal",
|
||||
}
|
||||
|
||||
interface ButtonComponentProps {
|
||||
text?: string;
|
||||
color?: string;
|
||||
textColor?: string;
|
||||
fontSize?: string;
|
||||
isBold?: boolean;
|
||||
onClick?: any;
|
||||
rounded?: boolean;
|
||||
isDisabled?: boolean;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const ButtonComponent = ({
|
||||
text,
|
||||
color,
|
||||
textColor,
|
||||
fontSize,
|
||||
isBold,
|
||||
onClick,
|
||||
rounded,
|
||||
isDisabled,
|
||||
isLoading,
|
||||
}: ButtonComponentProps) => {
|
||||
const style = {
|
||||
height: "100%",
|
||||
backgroundColor: color || "var(--primary-color)",
|
||||
color: textColor || "#fff",
|
||||
fontSize: transformDynamicSize(parseInt(fontSize || "20px")),
|
||||
fontWeight: isBold ? FontWeight.BOLD : undefined,
|
||||
"--loading-color": textColor || "#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,91 @@
|
|||
import React from "react";
|
||||
import { ScrollView, Text } from "@tarojs/components";
|
||||
import { Cell, Image } from "@taroify/core";
|
||||
import { Arrow, PhotoFail } from "@taroify/icons";
|
||||
import { createVanIconComponent } from "@taroify/icons/van";
|
||||
import _ from "lodash";
|
||||
|
||||
export interface CellComponentProps {
|
||||
cells: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
widgetId: string;
|
||||
picType: "none" | "icon" | "image" | "text";
|
||||
prefix?: string;
|
||||
icon?: string;
|
||||
iconColor?: string;
|
||||
picSrc?: string;
|
||||
isVisible?: boolean;
|
||||
showArrow?: boolean;
|
||||
content?: string;
|
||||
brief?: string;
|
||||
onClick?: string;
|
||||
}>;
|
||||
title?: string;
|
||||
inset: boolean;
|
||||
bordered: boolean;
|
||||
runAction: (a: string) => void;
|
||||
}
|
||||
|
||||
const CellComponent = (props: CellComponentProps) => {
|
||||
const { cells, title, inset, bordered, runAction } = props;
|
||||
|
||||
const onClickCellItem = (action: string) => (e: any) => {
|
||||
if (action) {
|
||||
runAction(action);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ScrollView style={{ height: "100%" }} scrollY>
|
||||
<Cell.Group title={title} inset={inset} bordered={bordered}>
|
||||
{cells.map((cell, index) => {
|
||||
let icon: any = null;
|
||||
if (cell.picType === "image") {
|
||||
icon = (
|
||||
<Image
|
||||
key={cell.picSrc}
|
||||
src={cell.picSrc}
|
||||
style={{
|
||||
width: "32px",
|
||||
height: "32px",
|
||||
borderRadius: "4px",
|
||||
marginRight: "20px",
|
||||
}}
|
||||
mode="aspectFit"
|
||||
fallback={<PhotoFail />}
|
||||
/>
|
||||
);
|
||||
} else if (cell.picType === "icon" && cell.icon) {
|
||||
const Icon = createVanIconComponent(cell.icon);
|
||||
icon = <Icon color={cell.iconColor} />;
|
||||
} else if (cell.picType === "text") {
|
||||
icon = (
|
||||
<Text
|
||||
style={{ color: "#999", fontSize: "16px", marginRight: "20px" }}
|
||||
>
|
||||
{cell.prefix}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Cell
|
||||
key={index}
|
||||
clickable
|
||||
bordered
|
||||
title={cell.label}
|
||||
brief={cell.brief}
|
||||
icon={icon}
|
||||
rightIcon={cell.showArrow ? <Arrow /> : null}
|
||||
onClick={onClickCellItem(cell.onClick || "")}
|
||||
>
|
||||
{cell.content}
|
||||
</Cell>
|
||||
);
|
||||
})}
|
||||
</Cell.Group>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
export default CellComponent;
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
import React from "react";
|
||||
import { styled } from "linaria/react";
|
||||
import { View } from "@tarojs/components";
|
||||
import { Image, Button } from "@taroify/core";
|
||||
import { PhotoFail } from "@taroify/icons";
|
||||
|
||||
const EmptyContainer = styled(View)`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.taroify-image {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
`;
|
||||
|
||||
const EmptyText = styled(View)`
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
`;
|
||||
|
||||
const EmptyButton = styled(Button)`
|
||||
margin-top: 8px;
|
||||
`;
|
||||
|
||||
export interface EmptyProps {
|
||||
text?: string;
|
||||
pic?: string;
|
||||
enableButton?: boolean;
|
||||
buttonText?: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
const Empty = ({
|
||||
text,
|
||||
pic,
|
||||
enableButton,
|
||||
buttonText,
|
||||
onClick,
|
||||
}: EmptyProps) => {
|
||||
return (
|
||||
<EmptyContainer>
|
||||
<View>
|
||||
<Image
|
||||
mode="aspectFit"
|
||||
fallback={<PhotoFail />}
|
||||
src={pic || EMPTY_IMAGE_URL}
|
||||
/>
|
||||
<EmptyText>{text || "暂无数据"}</EmptyText>
|
||||
{enableButton ? (
|
||||
<EmptyButton onClick={onClick} color="primary" block>
|
||||
{buttonText || "登录"}
|
||||
</EmptyButton>
|
||||
) : null}
|
||||
</View>
|
||||
</EmptyContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Empty;
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { ArrowRight } from "@taroify/icons";
|
||||
import { Form, AreaPicker, Input, Popup } from "@taroify/core";
|
||||
import { FormItemInstance } from "@taroify/core/form";
|
||||
import { areaList } from "@vant/area-data";
|
||||
|
||||
export interface FieldProps {
|
||||
label: string;
|
||||
name: string;
|
||||
required: boolean;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
const provinceList: any = areaList.province_list;
|
||||
const cityList: any = areaList.city_list;
|
||||
const countyList: any = areaList.county_list;
|
||||
|
||||
const hiddenStyle = {
|
||||
height: 0,
|
||||
padding: 0,
|
||||
};
|
||||
|
||||
function PickerField({ label, name, required, placeholder }: FieldProps) {
|
||||
const itemRef = useRef<FormItemInstance>();
|
||||
const provinceNameRef = useRef<FormItemInstance>();
|
||||
const cityNameRef = useRef<FormItemInstance>();
|
||||
const countyNameRef = useRef<FormItemInstance>();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [areaValue, setAreaValue] = useState<string[]>();
|
||||
const current = itemRef.current?.getValue();
|
||||
|
||||
useEffect(() => {
|
||||
if (current) {
|
||||
const currentProvince = current.substr(0, 2) + "0000";
|
||||
const currentCity = current.substr(0, 4) + "00";
|
||||
setAreaValue([currentProvince, currentCity, current]);
|
||||
}
|
||||
}, [current]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
ref={itemRef}
|
||||
name={name}
|
||||
clickable
|
||||
rightIcon={<ArrowRight />}
|
||||
rules={[{ required, message: `请选择${label}` }]}
|
||||
>
|
||||
<Form.Label>{label}</Form.Label>
|
||||
<Form.Control>
|
||||
{(props) => {
|
||||
let currentLabel = "";
|
||||
const county = props.value;
|
||||
if (county?.length === 6) {
|
||||
const province = county.substr(0, 2) + "0000";
|
||||
const city = county.substr(0, 4) + "00";
|
||||
currentLabel = [
|
||||
provinceList[province],
|
||||
cityList[city],
|
||||
countyList[county],
|
||||
].join("");
|
||||
}
|
||||
return (
|
||||
<Input
|
||||
readonly
|
||||
placeholder={placeholder || `请选择${label}`}
|
||||
onClick={() => setOpen(true)}
|
||||
value={currentLabel}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Form.Control>
|
||||
</Form.Item>
|
||||
<Form.Item name="province" ref={provinceNameRef} style={hiddenStyle}>
|
||||
<Input readonly />
|
||||
</Form.Item>
|
||||
<Form.Item name="city" ref={cityNameRef} style={hiddenStyle}>
|
||||
<Input readonly />
|
||||
</Form.Item>
|
||||
<Form.Item name="county" ref={countyNameRef} style={hiddenStyle}>
|
||||
<Input readonly />
|
||||
</Form.Item>
|
||||
<Popup
|
||||
style={{ height: "375px" }}
|
||||
mountOnEnter={false}
|
||||
open={open}
|
||||
rounded
|
||||
placement="bottom"
|
||||
onClose={setOpen}
|
||||
>
|
||||
<AreaPicker
|
||||
value={areaValue}
|
||||
onCancel={() => setOpen(false)}
|
||||
onConfirm={(newValue) => {
|
||||
itemRef.current?.setValue(newValue[2]);
|
||||
provinceNameRef.current?.setValue(provinceList[newValue[0]]);
|
||||
cityNameRef.current?.setValue(cityList[newValue[1]]);
|
||||
countyNameRef.current?.setValue(countyList[newValue[2]]);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<AreaPicker.Toolbar>
|
||||
<AreaPicker.Button>取消</AreaPicker.Button>
|
||||
<AreaPicker.Button>确认</AreaPicker.Button>
|
||||
</AreaPicker.Toolbar>
|
||||
<AreaPicker.Columns>{areaList}</AreaPicker.Columns>
|
||||
</AreaPicker>
|
||||
</Popup>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default PickerField;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import React from "react";
|
||||
import { Form, Checkbox } from "@taroify/core";
|
||||
|
||||
export interface FieldProps {
|
||||
label: string;
|
||||
name: string;
|
||||
required: boolean;
|
||||
options: Array<{
|
||||
label: string;
|
||||
value: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
function Field({ label, name, required, options }: FieldProps) {
|
||||
return (
|
||||
<Form.Item name={name} rules={[{ required, message: `请选择${label}` }]}>
|
||||
<Form.Label>{label}</Form.Label>
|
||||
<Form.Control>
|
||||
<Checkbox.Group direction="horizontal">
|
||||
{options?.map((o, index) => (
|
||||
<Checkbox
|
||||
name={o.value}
|
||||
key={index}
|
||||
shape="square"
|
||||
style={{ marginBottom: "8px" }}
|
||||
>
|
||||
{o.label}
|
||||
</Checkbox>
|
||||
))}
|
||||
</Checkbox.Group>
|
||||
</Form.Control>
|
||||
</Form.Item>
|
||||
);
|
||||
}
|
||||
|
||||
export default Field;
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import React from "react";
|
||||
import { Form, Input } from "@taroify/core";
|
||||
|
||||
export interface FieldProps {
|
||||
label: string;
|
||||
name: string;
|
||||
required: boolean;
|
||||
inputType: "text" | "number" | "idcard" | "digit" | "password";
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
function Field({ label, name, required, inputType, placeholder }: FieldProps) {
|
||||
const isPassword = inputType === "password";
|
||||
return (
|
||||
<Form.Item name={name} rules={[{ required, message: `请填写${label}` }]}>
|
||||
<Form.Label>{label}</Form.Label>
|
||||
<Form.Control>
|
||||
<Input
|
||||
type={isPassword ? "text" : inputType}
|
||||
password={isPassword}
|
||||
placeholder={placeholder || label}
|
||||
/>
|
||||
</Form.Control>
|
||||
</Form.Item>
|
||||
);
|
||||
}
|
||||
|
||||
export default Field;
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
import React, { useRef, useState } from "react";
|
||||
import { ArrowRight } from "@taroify/icons";
|
||||
import { Form, Picker, Input, Popup } from "@taroify/core";
|
||||
import { FormItemInstance } from "@taroify/core/form";
|
||||
import _ from "lodash";
|
||||
|
||||
export interface FieldProps {
|
||||
label: string;
|
||||
name: string;
|
||||
required: boolean;
|
||||
options: Array<{
|
||||
label: string;
|
||||
value: string;
|
||||
}>;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
function PickerField({
|
||||
label,
|
||||
name,
|
||||
required,
|
||||
options,
|
||||
placeholder,
|
||||
}: FieldProps) {
|
||||
const itemRef = useRef<FormItemInstance>();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const current = itemRef.current?.getValue();
|
||||
let currentLabel: any = undefined;
|
||||
if (current?.length === 1) {
|
||||
currentLabel = _.find(options, { value: current[0] })?.label;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
ref={itemRef}
|
||||
name={name}
|
||||
clickable
|
||||
rightIcon={<ArrowRight />}
|
||||
rules={[{ required, message: `请选择${label}` }]}
|
||||
>
|
||||
<Form.Label>{label}</Form.Label>
|
||||
<Form.Control>
|
||||
<Input
|
||||
readonly
|
||||
placeholder={placeholder || `请选择${label}`}
|
||||
onClick={() => setOpen(true)}
|
||||
value={currentLabel}
|
||||
/>
|
||||
</Form.Control>
|
||||
</Form.Item>
|
||||
<Popup
|
||||
style={{ height: "375px" }}
|
||||
mountOnEnter={false}
|
||||
open={open}
|
||||
rounded
|
||||
placement="bottom"
|
||||
onClose={setOpen}
|
||||
>
|
||||
<Picker
|
||||
onCancel={() => setOpen(false)}
|
||||
onConfirm={(v) => {
|
||||
itemRef.current?.setValue(v);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<Picker.Toolbar>
|
||||
<Picker.Button>取消</Picker.Button>
|
||||
<Picker.Button>确认</Picker.Button>
|
||||
</Picker.Toolbar>
|
||||
<Picker.Column>
|
||||
{options?.map((o, index) => (
|
||||
<Picker.Option key={index} value={o.value}>
|
||||
{o.label}
|
||||
</Picker.Option>
|
||||
))}
|
||||
</Picker.Column>
|
||||
</Picker>
|
||||
</Popup>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default PickerField;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue