mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 10:34:17 +00:00
0.7.31
This commit is contained in:
parent
660d4848cb
commit
3d9140d599
@ -47,6 +47,7 @@
|
||||
"enquire-js": "^0.2.1",
|
||||
"feather-reactjs": "^2.0.13",
|
||||
"jquery": "^3.5.1",
|
||||
"jsdoc": "^3.6.5",
|
||||
"less-vars-to-js": "^1.3.0",
|
||||
"lint-staged": "^10.0.7",
|
||||
"localforage": "^1.7.4",
|
||||
|
@ -3,6 +3,7 @@ import { format } from 'timeago.js';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import store from 'store';
|
||||
import { i18n, app_config } from 'config';
|
||||
import * as errorHandlers from 'core/libs/errorhandler'
|
||||
|
||||
const { pathToRegexp } = require('path-to-regexp');
|
||||
|
||||
@ -24,6 +25,53 @@ export const app_info = {
|
||||
logo_dark: app_config.DarkFullLogoPath,
|
||||
};
|
||||
|
||||
export function imageToBase64(img, callback){
|
||||
const reader = new FileReader()
|
||||
reader.addEventListener('load', () => callback(reader.result))
|
||||
reader.readAsDataURL(img)
|
||||
}
|
||||
|
||||
export function urlToBase64(url, callback){
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.onload = function() {
|
||||
let reader = new FileReader();
|
||||
reader.onloadend = function() {
|
||||
callback(reader.result);
|
||||
}
|
||||
reader.readAsDataURL(xhr.response);
|
||||
};
|
||||
xhr.open('GET', url);
|
||||
xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
|
||||
xhr.responseType = 'blob';
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a download with encoded uri
|
||||
*
|
||||
* @param {object} payload - Generation Data
|
||||
*/
|
||||
export function downloadEncodedURI(payload){
|
||||
if(!payload) return false
|
||||
let { data, type, charset, filename } = payload
|
||||
/**
|
||||
*
|
||||
* @param {object} payload - Generation Data
|
||||
*/
|
||||
if (!data || !type) return false
|
||||
try {
|
||||
if (!filename) {
|
||||
filename = `export_${time.now()}.${type.split("/")[1]}`
|
||||
}
|
||||
let tmp = document.createElement('a')
|
||||
tmp.href = `data:${type};charset=${charset},${encodeURIComponent(data)}`
|
||||
tmp.download=filename
|
||||
tmp.click()
|
||||
} catch (error) {
|
||||
errorHandlers.onError.internal_proccess(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last object from array
|
||||
*
|
||||
@ -36,28 +84,96 @@ export function objectLast(array, n) {
|
||||
return array.slice(Math.max(array.length - n, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Object to array scheme RSA-YCORE-ARRAYPROTO.2
|
||||
*
|
||||
* @param object {object}
|
||||
* @return array
|
||||
*/
|
||||
export function objectToArray(object) {
|
||||
if(!object) return false
|
||||
let tmp = []
|
||||
|
||||
const keys = Object.keys(object)
|
||||
const values = Object.values(object)
|
||||
const lenght = keys.length
|
||||
|
||||
for (let i = 0; i < lenght; i++) {
|
||||
let obj = {}
|
||||
obj.key = keys[i]
|
||||
obj.value = values[i]
|
||||
|
||||
tmp[i] = obj
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
/**
|
||||
* Object to array scheme RSA-YCORE-ARRAYPROTO.2
|
||||
*
|
||||
* @param object {object}
|
||||
* @return array
|
||||
*/
|
||||
export function arrayToObject(array) {
|
||||
if(!array) return false
|
||||
let tmp = []
|
||||
|
||||
array.forEach((e) => {
|
||||
tmp[e.key] = e.value
|
||||
})
|
||||
|
||||
return tmp
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element by id from an object array
|
||||
*
|
||||
* @param object {object}
|
||||
* @param id {string}
|
||||
* @return array
|
||||
*/
|
||||
export function objectRemoveByID(object, id) {
|
||||
let arr = objectToArray(object)
|
||||
return arr.filter((e) => {
|
||||
return e.id != id;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Remove an element by key from an object array
|
||||
*
|
||||
* @param object {object}
|
||||
* @param key {string}
|
||||
* @return array
|
||||
*/
|
||||
export function objectRemoveByKEY(object, key) {
|
||||
let arr = objectToArray(object)
|
||||
return arr.filter((e) => {
|
||||
return e.key != key;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an element by id from an array
|
||||
*
|
||||
* @param array {array}
|
||||
* @param value {string}
|
||||
* @return object
|
||||
* @param id {string}
|
||||
* @return array
|
||||
*/
|
||||
export function arrayRemoveByID(arr, value) {
|
||||
export function arrayRemoveByID(arr, id) {
|
||||
return arr.filter(function(ele) {
|
||||
return ele.id != value;
|
||||
return ele.id != id;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Remove an element by key from an array
|
||||
*
|
||||
* @param array {array}
|
||||
* @param value {string}
|
||||
* @return object
|
||||
* @param key {string}
|
||||
* @return array
|
||||
*/
|
||||
export function arrayRemoveByKEY(arr, value) {
|
||||
export function arrayRemoveByKEY(arr, key) {
|
||||
return arr.filter(function(ele) {
|
||||
return ele.key != value;
|
||||
return ele.key != key;
|
||||
});
|
||||
}
|
||||
|
||||
@ -65,7 +181,7 @@ export function arrayRemoveByKEY(arr, value) {
|
||||
* Global fix for convert '1, 0' to string boolean 'true, false'
|
||||
*
|
||||
* @param e {int} Numeric boolean reference
|
||||
* @return {bool} Boolean value
|
||||
* @return bool
|
||||
*/
|
||||
export function booleanFix(e) {
|
||||
if (e == 1) return true;
|
||||
@ -109,6 +225,9 @@ export const time = {
|
||||
relativeToNow: (a, b) => {
|
||||
return moment(a, b || 'DDMMYYYY').fromNow();
|
||||
},
|
||||
now: () => {
|
||||
return new Date().toLocaleString();
|
||||
}
|
||||
};
|
||||
|
||||
export function pathMatchRegexp(regexp, pathname) {
|
||||
|
@ -4,11 +4,28 @@ import verbosity from 'core/libs/verbosity'
|
||||
// STRINGS
|
||||
export const OVERLAY_BADPOSITION = `Invalid overlay position! Was expected "primary" or "secondary"`
|
||||
export const INTERNAL_PROCESS_FAILED = `An internal error has occurred! `
|
||||
export const INVALID_DATA = `A function has been executed with invalid data and has caused an error!`
|
||||
// HANDLERS
|
||||
export const onError = {
|
||||
internal_proccess: (...rest) => {
|
||||
verbosity.error(...rest)
|
||||
notify.warn(INTERNAL_PROCESS_FAILED, ...rest)
|
||||
return false
|
||||
},
|
||||
invalid_data: (error, expecting) => {
|
||||
verbosity.error(error)
|
||||
notify.open({
|
||||
message: 'Invalid Data',
|
||||
description:
|
||||
<div style={{ display: 'flex', flexDirection: 'column', margin: 'auto' }}>
|
||||
<div style={{ margin: '10px 0' }}> {INVALID_DATA} </div>
|
||||
<div style={{ margin: '10px 0', color: '#333' }}>
|
||||
<h4>Expected: {expecting}</h4>
|
||||
<h4 style={{ backgroundColor: 'rgba(221, 42, 42, 0.8)' }} >{`${error}`} </h4>
|
||||
</div>
|
||||
</div>,
|
||||
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
40
src/core/libs/interface/export_data/index.tsx
Normal file
40
src/core/libs/interface/export_data/index.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import * as React from 'react'
|
||||
import * as antd from 'antd'
|
||||
import * as Icons from 'components/Icons'
|
||||
import { downloadEncodedURI } from 'core'
|
||||
|
||||
export interface exportData_props {
|
||||
data: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
const exportCodeRender = (data) => {
|
||||
if(data.length > 500){
|
||||
return <div style={{ textAlign: 'center', width: '100%', padding: '30px 0 30px 0' }}>
|
||||
<Icons.HardDrive style={{ fontSize: '45px', margin: '0' }} />
|
||||
<h4>Hey, this file is too much large!</h4>
|
||||
<span>So it couldn't be displayed.</span>
|
||||
</div>
|
||||
}
|
||||
return <div>
|
||||
{data}
|
||||
</div>
|
||||
}
|
||||
|
||||
const exportData_render = (props: exportData_props) => {
|
||||
antd.Modal.confirm({
|
||||
title: <div><Icons.Code /> Your export <antd.Tag> {`${props.type.split("/")[1]}`} </antd.Tag></div>,
|
||||
icon: null,
|
||||
onOk: () => downloadEncodedURI({data: props.data, type: props.type}),
|
||||
okText: <><Icons.Download />Download as File</> ,
|
||||
cancelText: "Done",
|
||||
content: exportCodeRender(props.data),
|
||||
});
|
||||
}
|
||||
|
||||
exportData_render.defaultProps = {
|
||||
data: '',
|
||||
type: 'text/txt',
|
||||
}
|
||||
|
||||
export default exportData_render
|
@ -1,4 +1,4 @@
|
||||
import { notification } from 'antd'
|
||||
import { notification, message } from 'antd'
|
||||
import * as Icons from 'components/Icons'
|
||||
|
||||
export const notify = {
|
||||
@ -79,4 +79,14 @@ export const notify = {
|
||||
placement: 'bottomLeft',
|
||||
})
|
||||
},
|
||||
open: (props) => {
|
||||
notification.open({
|
||||
placement: props.placement? props.placement : 'bottomLeft',
|
||||
duration: props.duration? props.placement : 15,
|
||||
icon: props.icon? props.icon : <Icons.Triangle style={{ color: '#fa8c16' }} />,
|
||||
message: props.message? props.message : '',
|
||||
description: props.description? props.description : ''
|
||||
})
|
||||
},
|
||||
|
||||
}
|
@ -2,22 +2,23 @@ import store from 'store';
|
||||
import { app_config } from 'config';
|
||||
import verbosity from 'core/libs/verbosity'
|
||||
import * as errorHandlers from 'core/libs/errorhandler'
|
||||
import { negate } from 'lodash';
|
||||
import * as core from 'core'
|
||||
|
||||
const { appTheme_desiredContrast, appTheme_container } = app_config
|
||||
|
||||
export const theme = {
|
||||
get: (key) => {
|
||||
if(!localStorage.getItem(appTheme_container)) return false
|
||||
const raw = store.get(appTheme_container)
|
||||
if(!raw) return false
|
||||
let container = []
|
||||
if (raw) {
|
||||
raw.forEach((e)=>{
|
||||
container[e.key] = e.value
|
||||
})
|
||||
return container
|
||||
try {
|
||||
raw.forEach((e)=>{container[e.key] = e.value})
|
||||
} catch (error) {
|
||||
return errorHandlers.onError.invalid_data(error, "ThemeScheme")
|
||||
}
|
||||
return null
|
||||
return container
|
||||
|
||||
|
||||
},
|
||||
set: (data) => {
|
||||
if (!data || data.length > 2) return false
|
||||
|
@ -6,6 +6,7 @@ import keys from 'config/app_keys';
|
||||
import * as core from 'core';
|
||||
import { session } from 'core/cores';
|
||||
import verbosity from 'core/libs/verbosity'
|
||||
import { theme } from 'core/libs/style'
|
||||
|
||||
export default {
|
||||
namespace: 'app',
|
||||
@ -27,7 +28,7 @@ export default {
|
||||
feedOutdated: false,
|
||||
|
||||
app_settings: store.get(app_config.app_settings_storage),
|
||||
app_theme: store.get(app_config.appTheme_container),
|
||||
app_theme: store.get(app_config.appTheme_container) || [],
|
||||
notifications: [],
|
||||
locationQuery: {},
|
||||
|
||||
@ -114,24 +115,24 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
*updateTheme({payload}, {call, put, select}){
|
||||
*updateTheme({payload}, {put, select}){
|
||||
if (!payload) return false;
|
||||
let tmp = []
|
||||
let container = yield select(state => state.app.app_theme);
|
||||
let container_2 = []
|
||||
|
||||
const keys = Object.keys(payload)
|
||||
const values = Object.values(payload)
|
||||
const lenght = keys.length
|
||||
|
||||
for (let i = 0; i < lenght; i++) {
|
||||
let obj = {}
|
||||
obj.key = keys[i]
|
||||
obj.value = values[i]
|
||||
|
||||
tmp[i] = obj
|
||||
const containerlength = Object.entries(container).length
|
||||
|
||||
if (container && containerlength > 1) {
|
||||
container.forEach(e =>{
|
||||
let tmp = {key: e.key}
|
||||
e.key === payload.key? (tmp.value = payload.value) : (tmp.value = e.value)
|
||||
container_2.push(tmp)
|
||||
})
|
||||
}else{
|
||||
container_2 = [payload]
|
||||
}
|
||||
|
||||
return yield put({ type: 'handleUpdateTheme', payload: tmp });
|
||||
|
||||
return container_2? yield put({ type: 'handleUpdateTheme', payload: container_2 }) : null
|
||||
},
|
||||
},
|
||||
reducers: {
|
||||
|
@ -4,32 +4,11 @@ import * as antd from 'antd'
|
||||
import themeSettings from 'globals/theme_settings'
|
||||
import {connect} from 'umi'
|
||||
import styles from './index.less'
|
||||
import json_prune from 'core/libs/json_prune'
|
||||
|
||||
|
||||
import { SketchPicker } from 'react-color';
|
||||
import { theme, getOptimalOpacityFromIMG, get_style_rule_value } from 'core/libs/style'
|
||||
|
||||
|
||||
function getBase64(img, callback) {
|
||||
const reader = new FileReader()
|
||||
reader.addEventListener('load', () => callback(reader.result))
|
||||
reader.readAsDataURL(img)
|
||||
}
|
||||
|
||||
function toDataUrl(url, callback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onload = function() {
|
||||
var reader = new FileReader();
|
||||
reader.onloadend = function() {
|
||||
callback(reader.result);
|
||||
}
|
||||
reader.readAsDataURL(xhr.response);
|
||||
};
|
||||
xhr.open('GET', url);
|
||||
xhr.responseType = 'blob';
|
||||
xhr.send();
|
||||
}
|
||||
import { urlToBase64, imageToBase64, arrayToObject } from 'core'
|
||||
import exportDataAsFile from 'core/libs/interface/export_data'
|
||||
|
||||
class BackgroundColor extends React.Component{
|
||||
state = {
|
||||
@ -52,6 +31,25 @@ class BackgroundColor extends React.Component{
|
||||
}
|
||||
}
|
||||
|
||||
@connect(({ app }) => ({ app }))
|
||||
class DarkMode extends React.Component{
|
||||
state = {
|
||||
model: { active: false, autoTime: '' }
|
||||
}
|
||||
render(){
|
||||
return <>
|
||||
<div>
|
||||
<h2><Icons.Moon /> Dark Mode</h2>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@connect(({ app }) => ({ app }))
|
||||
class BackgroundImage extends React.Component{
|
||||
state = {
|
||||
@ -67,7 +65,7 @@ class BackgroundImage extends React.Component{
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
this.setState({ processing: true })
|
||||
getBase64(info.file.originFileObj, fileURL => {
|
||||
imageToBase64(info.file.originFileObj, fileURL => {
|
||||
this.setState({ fileURL: fileURL })
|
||||
this.proccessBackground(fileURL)
|
||||
})
|
||||
@ -75,10 +73,8 @@ class BackgroundImage extends React.Component{
|
||||
}
|
||||
|
||||
handleCustomURL(url){
|
||||
this.setState({ processing: true })
|
||||
this.setState({ fileURL: url })
|
||||
|
||||
toDataUrl(url, fileURL => {
|
||||
this.setState({ processing: true, fileURL: url })
|
||||
urlToBase64(url, fileURL => {
|
||||
this.proccessBackground(fileURL)
|
||||
})
|
||||
}
|
||||
@ -90,43 +86,19 @@ class BackgroundImage extends React.Component{
|
||||
this.setState({ model: payload, processing: false })
|
||||
this.props.dispatch({
|
||||
type: 'app/updateTheme',
|
||||
payload: { backgroundImage: payload }
|
||||
payload: {
|
||||
key: 'backgroundImage',
|
||||
value: payload
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
handleErase(){
|
||||
this.handleUpdate({})
|
||||
this.handleUpdate({})
|
||||
}
|
||||
|
||||
handleExport(){
|
||||
const string = JSON.stringify(this.state.model)
|
||||
const exportCodeRender = () => {
|
||||
if(string.length > 500){
|
||||
return <div style={{ textAlign: 'center', width: '100%', padding: '30px 0 30px 0' }}>
|
||||
<Icons.HardDrive style={{ fontSize: '45px', margin: '0' }} />
|
||||
<h4>Hey, this file is too much large!</h4>
|
||||
<span>So it couldn't be displayed.</span>
|
||||
</div>
|
||||
}
|
||||
return <div>
|
||||
{string}
|
||||
</div>
|
||||
}
|
||||
antd.Modal.confirm({
|
||||
title: <div><Icons.Code /> Your export <antd.Tag> JSON </antd.Tag></div>,
|
||||
icon: null,
|
||||
onOk: () => {
|
||||
let tmp = document.createElement('a')
|
||||
tmp.href = `data:text/json;charset=utf-8,${encodeURIComponent(string)}`
|
||||
tmp.download="export.json"
|
||||
tmp.click()
|
||||
},
|
||||
okText: <><Icons.Download />Download as File</> ,
|
||||
cancelText: "Done",
|
||||
content: exportCodeRender(),
|
||||
});
|
||||
|
||||
|
||||
exportDataAsFile({data: JSON.stringify(this.state.model), type: 'text/json'})
|
||||
}
|
||||
|
||||
proccessBackground(data){
|
||||
@ -149,9 +121,10 @@ class BackgroundImage extends React.Component{
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
const storaged = theme.get()["backgroundImage"]
|
||||
const storaged = theme.get()
|
||||
|
||||
if(storaged){
|
||||
this.setState({ model: storaged })
|
||||
this.setState({ model: storaged["backgroundImage"] })
|
||||
}
|
||||
|
||||
let textColor = this.rgbToScheme(get_style_rule_value('#root', 'color'))
|
||||
@ -200,30 +173,23 @@ class BackgroundImage extends React.Component{
|
||||
checkedChildren="Enabled"
|
||||
unCheckedChildren="Disabled"
|
||||
loading={this.state.processing}
|
||||
onChange={(e) => {
|
||||
promiseState(prevState => ({ model: { ...prevState.model, active: e }})).then(() => this.handleUpdate())
|
||||
}}
|
||||
onChange={(e) => {promiseState(prevState => ({ model: { ...prevState.model, active: e }})).then(() => this.handleUpdate())}}
|
||||
checked={this.state.model.active}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h4><Icons.Layers />Opacity</h4>
|
||||
<antd.Slider disabled={!this.state.model.src} onChange={(e) => {
|
||||
this.setState(
|
||||
prevState => ({
|
||||
model: {
|
||||
...prevState.model,
|
||||
opacity: e/100
|
||||
}
|
||||
})
|
||||
)
|
||||
}} onAfterChange={() => this.handleUpdate()} value={this.state.model.opacity*100} />
|
||||
<antd.Slider disabled={!this.state.model.src} onChange={(e) => {this.setState(prevState => ({model: {...prevState.model, opacity: e/100}}))}} onAfterChange={() => this.handleUpdate()} value={this.state.model.opacity*100} />
|
||||
</div>
|
||||
<div>
|
||||
<h4><Icons.Code />Export Code</h4>
|
||||
<antd.Button disabled={!this.state.model.src} size="small" onClick={() => this.handleExport()}> Export </antd.Button>
|
||||
</div>
|
||||
<div>
|
||||
<h4><Icons.Copy />Import Code</h4>
|
||||
<antd.Button size="small" onClick={() => null}> Import </antd.Button>
|
||||
</div>
|
||||
<div>
|
||||
<h4><Icons.Trash />Erase</h4>
|
||||
<antd.Popconfirm disabled={!this.state.model.src} placement="topLeft" title="Are you sure?" onConfirm={() => this.handleErase()} okText="Yes" cancelText="No">
|
||||
@ -270,31 +236,11 @@ class BackgroundImage extends React.Component{
|
||||
}
|
||||
}
|
||||
|
||||
export default class ThemeSettings extends React.PureComponent{
|
||||
@connect(({ app }) => ({ app }))
|
||||
export default class ThemeSettings extends React.Component{
|
||||
state = {
|
||||
helper_visible: false,
|
||||
helper_fragment: null,
|
||||
style: theme.get(),
|
||||
}
|
||||
|
||||
|
||||
handleRemove(key){
|
||||
try {
|
||||
const storaged = JSON.parse(app.app_theme.getString())
|
||||
let mix = {};
|
||||
storaged.forEach((e)=>{
|
||||
return e.key !== key? mix[e.key] = e.value : null
|
||||
})
|
||||
console.log(mix)
|
||||
this.encode(mix, (res)=> {
|
||||
app.app_theme.set(res)
|
||||
this.decodeData()
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
helper = {
|
||||
@ -303,18 +249,20 @@ export default class ThemeSettings extends React.PureComponent{
|
||||
},
|
||||
close: () => {
|
||||
this.setState({ helper_visible: false, helper_fragment: null })
|
||||
},
|
||||
backgroundImage: () => {
|
||||
this.helper.open(<BackgroundImage />)
|
||||
},
|
||||
backgroundColor: () => {
|
||||
this.helper.open(<BackgroundColor />)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render(){
|
||||
const settingClick = { backgroundImage: () => this.helper.backgroundImage(), backgroundColor: () => this.helper.backgroundColor() }
|
||||
const settingClick = {
|
||||
backgroundImage: () => this.helper.open(<BackgroundImage />),
|
||||
overlay: () => this.helper.open(<BackgroundColor />) ,
|
||||
darkmode: () => this.helper.open(<DarkMode />)
|
||||
}
|
||||
|
||||
const isActive = (key) => {
|
||||
return key? key.active : false
|
||||
}
|
||||
return(
|
||||
<div>
|
||||
<h2><Icons.Layers/> Theme</h2>
|
||||
@ -322,16 +270,18 @@ export default class ThemeSettings extends React.PureComponent{
|
||||
itemLayout="horizontal"
|
||||
dataSource={themeSettings}
|
||||
renderItem={item => (
|
||||
<antd.Card size="small" bodyStyle={{ width: '100%' }} style={{ display: "flex", flexDirection: "row", margin: 'auto' }} hoverable onClick={settingClick[item.id]}>
|
||||
<h3>{item.icon}{item.title} <div style={{ float: "right" }}><antd.Tag color={this.state.style[item.id]? "green" : "default"} > {this.state.style[item.id]? "Enabled" : "Disabled"} </antd.Tag></div></h3>
|
||||
<div style={{ margin: '10px 0 10px 0' }} >
|
||||
<antd.Card size="small" bodyStyle={{ width: '100%' }} style={{ display: "flex", flexDirection: "row", margin: 'auto', borderRadius: '12px' }} hoverable onClick={settingClick[item.id]}>
|
||||
<h3>{item.icon}{item.title} <div style={{ float: "right" }}><antd.Tag color={isActive(arrayToObject(this.props.app.app_theme)[item.id])? "green" : "default"} > {isActive(arrayToObject(this.props.app.app_theme)[item.id])? "Enabled" : "Disabled"} </antd.Tag></div></h3>
|
||||
<p>{item.description}</p>
|
||||
</antd.Card>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
|
||||
<antd.Drawer
|
||||
placement="right"
|
||||
width="600px"
|
||||
width="700px"
|
||||
closable={true}
|
||||
onClose={this.helper.close}
|
||||
visible={this.state.helper_visible}
|
||||
|
Loading…
x
Reference in New Issue
Block a user