mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 02:24:16 +00:00
Settings & yCore Optimization
This commit is contained in:
parent
76e5c4f801
commit
e5873d8c34
@ -64,7 +64,6 @@ export default {
|
||||
// Webpack Configuration
|
||||
alias: {
|
||||
ycore: resolve(__dirname, './src/@ycore/ycore_worker.js'),
|
||||
ycstyle: resolve(__dirname, './src/@ycore/ycore_style.scss'),
|
||||
api: resolve(__dirname, './src/services/'),
|
||||
components: resolve(__dirname, './src/components'),
|
||||
config: resolve(__dirname, './config/ycore.config.js'),
|
||||
|
@ -1,26 +1,34 @@
|
||||
[
|
||||
const fromStorage = JSON.parse(localStorage.getItem('app_settings'))
|
||||
function StorageValued(e){
|
||||
const Ite = fromStorage.map(item => {
|
||||
return item.SettingID === e? item.value : null
|
||||
})
|
||||
const fr = Ite.filter(Boolean)
|
||||
return fr.toString()
|
||||
}
|
||||
export default [
|
||||
{
|
||||
"SettingID": "strict_lightMode",
|
||||
"title": "Strict Light Mode",
|
||||
"description": "Force the app to apply full light mode theme when the light mode is activated... (Experimental)",
|
||||
"value": false
|
||||
"value": StorageValued('strict_lightMode') || false
|
||||
},
|
||||
{
|
||||
"SettingID": "force_collapse",
|
||||
"title": "Collapsed Default",
|
||||
"description": "Force the app to apply collapse mode when an component has updated",
|
||||
"value": false
|
||||
"value": StorageValued('force_collapse') || false
|
||||
},
|
||||
{
|
||||
"SettingID": "force_showDevLogs",
|
||||
"title": "Show Functions Logs",
|
||||
"description": "Show all console logs... [Developer]",
|
||||
"value": true
|
||||
"value": StorageValued('force_showDevLogs') || true
|
||||
},
|
||||
{
|
||||
"SettingID": "sessions_noexpire",
|
||||
"title": "No expire session",
|
||||
"description": "Force the app to not expire any session... [Developer]",
|
||||
"value": true
|
||||
"value": StorageValued('sessions_noexpire') || true
|
||||
}
|
||||
]
|
@ -14,6 +14,12 @@ const database = [
|
||||
name: 'Main',
|
||||
route: '/main',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
icon: 'user',
|
||||
name: 'App Settings',
|
||||
route: '/settings'
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
|
27
mock/user.js
27
mock/user.js
@ -1,27 +0,0 @@
|
||||
import { Mock, Constant, qs, randomAvatar } from './_utils'
|
||||
import jwt from 'jsonwebtoken';
|
||||
import keys from '../config/keys.js';
|
||||
|
||||
const { ApiPrefix } = Constant
|
||||
|
||||
|
||||
module.exports = {
|
||||
[`POST ${ApiPrefix}/user/login`](req, res) {
|
||||
var ExpireTime = '1556952'
|
||||
const now = new Date()
|
||||
now.setDate(now.getDate() + 1)
|
||||
const { UserID, UserToken } = req.body
|
||||
const frame = { UserID, UserToken, deadline: now.getTime()}
|
||||
jwt.sign(
|
||||
frame,
|
||||
keys.secretOrKey,
|
||||
{ expiresIn: ExpireTime },
|
||||
(err, token) => {
|
||||
res.cookie('token', token, { maxAge: ExpireTime, httpOnly: false }),
|
||||
res.json({ success: true, token: token })
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
|
||||
}
|
@ -43,11 +43,11 @@ export function UpdateSDCP() {
|
||||
const e2 = btoa(Nsdcp)
|
||||
const n = e1.localeCompare(e2)
|
||||
if (!e2) {
|
||||
console.log(prefix, 'API Returned empty response! We recommend to logout')
|
||||
ycore.DevOptions.ShowFunctionsLogs? console.log(prefix, 'API Returned empty response! We recommend to logout') : null
|
||||
return
|
||||
}
|
||||
if (e1 == e2) {
|
||||
console.log(prefix, 'SDCP Equality')
|
||||
ycore.DevOptions.ShowFunctionsLogs? console.log(prefix, 'SDCP Equality') : null
|
||||
}else{
|
||||
ycore.DevOptions.ShowFunctionsLogs? console.log(prefix, 'SDCP Update detected ! => ', n) : null
|
||||
ycore.DevOptions.ShowFunctionsLogs? console.debug(`Compare versions => NEW ${[e1]} || OLD ${[e2]} `) : null
|
||||
|
@ -169,7 +169,7 @@ export const GetUserToken = {
|
||||
if (!FB) {
|
||||
final = FC
|
||||
}
|
||||
console.log(final)
|
||||
ycore.DevOptions.ShowFunctionsLogs ? console.debug(final) : null
|
||||
return final
|
||||
},
|
||||
raw: function () {
|
||||
|
@ -4,12 +4,14 @@ import * as antd from "antd"
|
||||
import './libs.js'
|
||||
export * from "./libs.js"
|
||||
|
||||
import * as AppSettings from '../../globals/settings.js'
|
||||
export var DevOptions = AppSettings;
|
||||
|
||||
var package_json = require("../../package.json");
|
||||
var config = require("config");
|
||||
|
||||
export var { router } = require("utils")
|
||||
export var endpoints = config.Endpoints;
|
||||
export var DevOptions = config.DevOptions;
|
||||
export var yConfig = config.yConfig;
|
||||
|
||||
export function booleanFix(e){
|
||||
|
@ -9,7 +9,7 @@ const userData = ycore.SDCP();
|
||||
|
||||
function isOwnProfile(id){
|
||||
if(id == userData.username){
|
||||
console.log('Is your own profile !!')
|
||||
ycore.DevOptions.ShowFunctionsLogs ? console.log('Is your own profile !!'): null
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@ -93,7 +93,7 @@ class UserProfile extends React.Component {
|
||||
const c1 = rp['0'].username.toLowerCase()
|
||||
const c2 = string.toLowerCase()
|
||||
if (c1 !== c2) {
|
||||
console.log(`Using aproximate user! => ${c1} / ${c2}`)
|
||||
ycore.DevOptions.ShowFunctionsLogs ? console.log(`Using aproximate user! => ${c1} / ${c2}`) : null
|
||||
ycore.crouter.native(`@${c1}`)
|
||||
}
|
||||
ycore.GetUserPosts(rp['0'].user_id, (exception, response) => {
|
||||
|
@ -4,28 +4,21 @@ import { pathMatchRegexp } from 'utils'
|
||||
import Error404 from '../404.js'
|
||||
import * as ycore from 'ycore'
|
||||
|
||||
const userData = ycore.SDCP()
|
||||
|
||||
class PageIndexer extends PureComponent {
|
||||
componentDidMount(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const {location} = this.props
|
||||
|
||||
const matchUser = pathMatchRegexp("/@:id", location.pathname);
|
||||
const matchSearch = pathMatchRegexp("/s/:id", location.pathname);
|
||||
|
||||
if (matchUser) {
|
||||
console.log(`User matched! ${location.pathname}`)
|
||||
ycore.DevOptions.ShowFunctionsLogs ? console.log(`User matched! ${location.pathname}`) : null
|
||||
return(<div>
|
||||
<UserProfile regx={matchUser} />
|
||||
</div>)
|
||||
}
|
||||
if (matchSearch) {
|
||||
console.log(`Search matched! ${location.pathname}`)
|
||||
ycore.DevOptions.ShowFunctionsLogs ? console.log(`Search matched! ${location.pathname}`) : null
|
||||
return(<div>
|
||||
<UserProfile regx={matchSearch} />
|
||||
</div>)
|
||||
|
@ -1,50 +0,0 @@
|
||||
import { pathMatchRegexp } from 'utils'
|
||||
import api from 'api'
|
||||
|
||||
const { queryUser } = api
|
||||
|
||||
export default {
|
||||
namespace: 'userDetail',
|
||||
|
||||
state: {
|
||||
data: {},
|
||||
},
|
||||
|
||||
subscriptions: {
|
||||
setup({ dispatch, history }) {
|
||||
history.listen(({ pathname }) => {
|
||||
const match = pathMatchRegexp('/:user', pathname)
|
||||
if (match) {
|
||||
dispatch({ type: 'query', payload: { id: match[1] } })
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
effects: {
|
||||
*query({ payload }, { call, put }) {
|
||||
const data = yield call(queryUser, payload)
|
||||
const { success, message, status, ...other } = data
|
||||
if (success) {
|
||||
yield put({
|
||||
type: 'querySuccess',
|
||||
payload: {
|
||||
data: other,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
reducers: {
|
||||
querySuccess(state, { payload }) {
|
||||
const { data } = payload
|
||||
return {
|
||||
...state,
|
||||
data,
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
@ -32,7 +32,6 @@ class Main extends React.Component {
|
||||
feedParsed.map(item=> {
|
||||
const {id, postText, post_time, publisher, postFile, postFileName} = item
|
||||
const paylodd = {user: publisher.username, ago: post_time, avatar: publisher.avatar, content: postText, file: postFile, postFileName: postFileName, publisher: publisher }
|
||||
ycore.DevOptions.ShowFunctionsLogs? console.log([item], paylodd) : null
|
||||
return <PostCard payload={paylodd} key={id} />
|
||||
})
|
||||
)
|
||||
|
92
src/pages/settings/components/base.js
Normal file
92
src/pages/settings/components/base.js
Normal file
@ -0,0 +1,92 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { List, Icon, Switch, Button, notification } from 'antd';
|
||||
import Settings from '../../../../globals/settings.js'
|
||||
import { DevOptions, ControlBar } from 'ycore'
|
||||
import update from 'immutability-helper'
|
||||
|
||||
class Base extends Component {
|
||||
constructor(props){
|
||||
super(props),
|
||||
this.state = {
|
||||
SettingRepo: Settings,
|
||||
backupSettings: JSON.parse(localStorage.getItem('app_settings')) || Settings,
|
||||
forSave: false
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
if (!localStorage.getItem('app_settings')) {
|
||||
DevOptions.ShowFunctionsLogs? console.warn('The settings for this app in your Account isnt set yet, Using stock settings...') : null
|
||||
}
|
||||
}
|
||||
SettingRender = data =>{
|
||||
try{
|
||||
const {SettingRepo} = this.state
|
||||
return(
|
||||
<List
|
||||
itemLayout="horizontal"
|
||||
dataSource={data}
|
||||
renderItem={item => (
|
||||
<List.Item actions={item.actions} >
|
||||
<List.Item.Meta title={item.title} description={item.description} />
|
||||
<Switch checkedChildren={'Enabled'} unCheckedChildren={'Disabled'} checked={item.value} onChange={() => this.onChange(item)} />
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
catch (err){
|
||||
return console.log(err)
|
||||
}
|
||||
}
|
||||
handleControlBar(){
|
||||
const ListControls = [
|
||||
(<div>
|
||||
<Button type="done" icon='save' onClick={() => this.saveChanges()} >Save</Button>
|
||||
<Button type="dashed" icon="close" shape="circle" onClick={() => this.handleCancel()}></Button>
|
||||
</div>
|
||||
)
|
||||
]
|
||||
ControlBar.set(ListControls)
|
||||
}
|
||||
handleCancel(){
|
||||
const back = this.state.backupSettings;
|
||||
this.setState({ SettingRepo: back, forSave: false})
|
||||
DevOptions.ShowFunctionsLogs? console.log(`Restored ${JSON.stringify(back)}`) : null
|
||||
ControlBar.close()
|
||||
}
|
||||
saveChanges(){
|
||||
localStorage.setItem('app_settings', JSON.stringify(this.state.SettingRepo))
|
||||
this.setState({ forSave: false })
|
||||
notification.success({
|
||||
message: 'Settings saved',
|
||||
description:'The configuration has been saved, it may for some configuration to make changes you need to reload the application',
|
||||
})
|
||||
ControlBar.close()
|
||||
}
|
||||
onChange(item) {
|
||||
try {
|
||||
this.handleControlBar()
|
||||
const to = !item.value
|
||||
const updatedValue = [...this.state.SettingRepo]
|
||||
.map(ita => ita === item? Object.assign(ita, { "value": to }) : ita);
|
||||
this.setState({SettingRepo: updatedValue, forSave: true})
|
||||
DevOptions.ShowFunctionsLogs? console.log(`Changing ${item.SettingID} to value ${to}`) : null
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Fragment>
|
||||
<div>
|
||||
<h1><Icon type="global" /> Behaviors</h1>
|
||||
{this.SettingRender(this.state.SettingRepo)}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Base;
|
49
src/pages/settings/components/notification.js
Normal file
49
src/pages/settings/components/notification.js
Normal file
@ -0,0 +1,49 @@
|
||||
import * as antd from 'antd';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
|
||||
class NotificationView extends Component {
|
||||
getData = () => {
|
||||
const Action = (
|
||||
<antd.Switch
|
||||
checkedChildren={'open'}
|
||||
unCheckedChildren={'close'}
|
||||
defaultChecked
|
||||
/>
|
||||
);
|
||||
return [
|
||||
{
|
||||
title: 'Title 1',
|
||||
description: 'Description 1',
|
||||
actions: [Action],
|
||||
},
|
||||
{
|
||||
title: 'Title 2',
|
||||
description: 'Description 2',
|
||||
actions: [Action],
|
||||
},
|
||||
{
|
||||
title: 'Title 3',
|
||||
description: 'Description 3',
|
||||
actions: [Action],
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
render() {
|
||||
const data = this.getData();
|
||||
return (
|
||||
<Fragment>
|
||||
<antd.List
|
||||
itemLayout="horizontal"
|
||||
dataSource={data}
|
||||
renderItem={item => (
|
||||
<antd.List.Item actions={item.actions}>
|
||||
<antd.List.Item.Meta title={item.title} description={item.description} />
|
||||
</antd.List.Item>
|
||||
)} />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default NotificationView;
|
85
src/pages/settings/components/security.js
Normal file
85
src/pages/settings/components/security.js
Normal file
@ -0,0 +1,85 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { List } from 'antd';
|
||||
|
||||
const passwordStrength = {
|
||||
strong: (
|
||||
<span className="strong">
|
||||
Strong
|
||||
</span>
|
||||
),
|
||||
medium: (
|
||||
<span className="medium">
|
||||
Medium
|
||||
</span>
|
||||
),
|
||||
weak: (
|
||||
<span className="weak">
|
||||
Weak
|
||||
</span>
|
||||
),
|
||||
};
|
||||
|
||||
class SecurityView extends Component {
|
||||
getData = () => [
|
||||
{
|
||||
title: <h1>Password</h1>,
|
||||
description: (
|
||||
<Fragment>
|
||||
<p>Something</p>
|
||||
{passwordStrength.strong}
|
||||
</Fragment>
|
||||
),
|
||||
actions: [
|
||||
<a key="Modify">
|
||||
Modify
|
||||
</a>,
|
||||
],
|
||||
},
|
||||
{
|
||||
title: <h1>Security question</h1>,
|
||||
description: 'Security cuesting seting',
|
||||
actions: [
|
||||
<a key="Set">
|
||||
Set
|
||||
</a>,
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Mail',
|
||||
description: 'YourEmail@jeje.com',
|
||||
actions: [
|
||||
<a key="Modify">
|
||||
Modify
|
||||
</a>,
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'mfa',
|
||||
description: 'mfa settings',
|
||||
actions: [
|
||||
<a key="bind">
|
||||
Bind
|
||||
</a>,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
render() {
|
||||
const data = this.getData();
|
||||
return (
|
||||
<Fragment>
|
||||
<List
|
||||
itemLayout="horizontal"
|
||||
dataSource={data}
|
||||
renderItem={item => (
|
||||
<List.Item actions={item.actions}>
|
||||
<List.Item.Meta title={item.title} description={item.description} />
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SecurityView;
|
86
src/pages/settings/index.js
Normal file
86
src/pages/settings/index.js
Normal file
@ -0,0 +1,86 @@
|
||||
import React from 'react';
|
||||
import { GridContent } from '@ant-design/pro-layout';
|
||||
import { Menu, Typography, Icon } from 'antd';
|
||||
import styles from './style.less';
|
||||
|
||||
import NotificationView from './components/notification.js';
|
||||
import SecurityView from './components/security.js';
|
||||
import Base from './components/base.js'
|
||||
|
||||
const { Item } = Menu;
|
||||
const menuMap = {
|
||||
base: 'App',
|
||||
security: 'Security',
|
||||
notification: 'Notification',
|
||||
};
|
||||
|
||||
const { Title } = Typography;
|
||||
class GeneralSettings extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
mode: 'inline',
|
||||
selectKey: 'base',
|
||||
};
|
||||
}
|
||||
|
||||
getMenu = () => {
|
||||
return Object.keys(menuMap).map(item => <Item key={item}>{menuMap[item]}</Item>);
|
||||
};
|
||||
|
||||
selectKey = (key) => {
|
||||
this.setState({
|
||||
selectKey: key,
|
||||
});
|
||||
};
|
||||
|
||||
renderChildren = () => {
|
||||
const { selectKey } = this.state;
|
||||
switch (selectKey) {
|
||||
case 'base':
|
||||
return <Base />;
|
||||
case 'security':
|
||||
return <SecurityView />;
|
||||
case 'notification':
|
||||
return <NotificationView />;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { mode, selectKey } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<Title className={styles.titleHead}><Icon type="setting" /> Settings</Title>
|
||||
<GridContent>
|
||||
<div
|
||||
className={styles.main}
|
||||
ref={ref => {
|
||||
if (ref) {
|
||||
this.main = ref;
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className={styles.leftMenu}>
|
||||
<Menu
|
||||
mode={mode}
|
||||
selectedKeys={[selectKey]}
|
||||
onClick={({ key }) => this.selectKey(key)}
|
||||
>
|
||||
{this.getMenu()}
|
||||
</Menu>
|
||||
</div>
|
||||
<div className={styles.right}>
|
||||
{this.renderChildren()}
|
||||
</div>
|
||||
</div>
|
||||
</GridContent>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default GeneralSettings
|
98
src/pages/settings/style.less
Normal file
98
src/pages/settings/style.less
Normal file
@ -0,0 +1,98 @@
|
||||
@import '~themes/vars.less';
|
||||
|
||||
.titleHead{
|
||||
font-family: "Nunito", sans-serif;
|
||||
}
|
||||
.main {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: @menu-bg;
|
||||
.leftMenu {
|
||||
width: 224px;
|
||||
border-right: @border-width-base @border-style-base @border-color-split;
|
||||
:global {
|
||||
.ant-menu-inline {
|
||||
border: none;
|
||||
}
|
||||
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
.right {
|
||||
flex: 1;
|
||||
padding-top: 8px;
|
||||
padding-right: 40px;
|
||||
padding-bottom: 8px;
|
||||
padding-left: 40px;
|
||||
.title {
|
||||
margin-bottom: 12px;
|
||||
color: @heading-color;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
:global {
|
||||
.ant-list-split .ant-list-item:last-child {
|
||||
border-bottom: 1px solid @border-color-split;
|
||||
}
|
||||
.ant-list-item {
|
||||
padding-top: 14px;
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
:global {
|
||||
.ant-list-item-meta {
|
||||
// 账号绑定图标
|
||||
.taobao {
|
||||
display: block;
|
||||
color: #ff4000;
|
||||
font-size: 48px;
|
||||
line-height: 48px;
|
||||
border-radius: @border-radius-base;
|
||||
}
|
||||
.dingding {
|
||||
margin: 2px;
|
||||
padding: 6px;
|
||||
color: #fff;
|
||||
font-size: 32px;
|
||||
line-height: 32px;
|
||||
background-color: #2eabff;
|
||||
border-radius: @border-radius-base;
|
||||
}
|
||||
.alipay {
|
||||
color: #2eabff;
|
||||
font-size: 48px;
|
||||
line-height: 48px;
|
||||
border-radius: @border-radius-base;
|
||||
}
|
||||
}
|
||||
|
||||
// 密码强度
|
||||
font.strong {
|
||||
color: @success-color;
|
||||
}
|
||||
font.medium {
|
||||
color: @warning-color;
|
||||
}
|
||||
font.weak {
|
||||
color: @error-color;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @screen-md) {
|
||||
.main {
|
||||
flex-direction: column;
|
||||
.leftMenu {
|
||||
width: 100%;
|
||||
border: none;
|
||||
}
|
||||
.right {
|
||||
padding: 40px;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user