diff --git a/.umirc.js b/.umirc.js index da950f3a..9412f468 100644 --- a/.umirc.js +++ b/.umirc.js @@ -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'), diff --git a/globals/settings.json b/globals/settings.js similarity index 59% rename from globals/settings.json rename to globals/settings.js index 1a1b85dd..5f78d590 100644 --- a/globals/settings.json +++ b/globals/settings.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 } ] \ No newline at end of file diff --git a/mock/route.js b/mock/route.js index bc8d31b2..8a0145f8 100644 --- a/mock/route.js +++ b/mock/route.js @@ -14,6 +14,12 @@ const database = [ name: 'Main', route: '/main', }, + { + id: '2', + icon: 'user', + name: 'App Settings', + route: '/settings' + } ] diff --git a/mock/user.js b/mock/user.js deleted file mode 100644 index 92ef41c0..00000000 --- a/mock/user.js +++ /dev/null @@ -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 }) - } - ) - }, - - -} diff --git a/src/@ycore/libs/ycore_sdcp/pre.js b/src/@ycore/libs/ycore_sdcp/pre.js index 797b7a8e..07a292ce 100644 --- a/src/@ycore/libs/ycore_sdcp/pre.js +++ b/src/@ycore/libs/ycore_sdcp/pre.js @@ -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 diff --git a/src/@ycore/libs/yulio_id/pre.js b/src/@ycore/libs/yulio_id/pre.js index af852e40..e5d8f9d9 100644 --- a/src/@ycore/libs/yulio_id/pre.js +++ b/src/@ycore/libs/yulio_id/pre.js @@ -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 () { diff --git a/src/@ycore/ycore_worker.js b/src/@ycore/ycore_worker.js index ac1044c8..960f1b09 100644 --- a/src/@ycore/ycore_worker.js +++ b/src/@ycore/ycore_worker.js @@ -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){ diff --git a/src/components/UserProfile/index.js b/src/components/UserProfile/index.js index eebbcfb9..bf74d818 100644 --- a/src/components/UserProfile/index.js +++ b/src/components/UserProfile/index.js @@ -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) => { diff --git a/src/pages/$page/index.js b/src/pages/$page/index.js index bfa36133..bd1b35ee 100644 --- a/src/pages/$page/index.js +++ b/src/pages/$page/index.js @@ -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(
) } if (matchSearch) { - console.log(`Search matched! ${location.pathname}`) + ycore.DevOptions.ShowFunctionsLogs ? console.log(`Search matched! ${location.pathname}`) : null return(
) diff --git a/src/pages/$page/model/detail.js b/src/pages/$page/model/detail.js deleted file mode 100644 index 7543c66c..00000000 --- a/src/pages/$page/model/detail.js +++ /dev/null @@ -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, - } - }, - }, -} \ No newline at end of file diff --git a/src/pages/main/index.js b/src/pages/main/index.js index 087bfd41..83162799 100644 --- a/src/pages/main/index.js +++ b/src/pages/main/index.js @@ -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 }) ) diff --git a/src/pages/settings/components/base.js b/src/pages/settings/components/base.js new file mode 100644 index 00000000..ab14d826 --- /dev/null +++ b/src/pages/settings/components/base.js @@ -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( + ( + + + this.onChange(item)} /> + + )} + /> + ) + } + catch (err){ + return console.log(err) + } + } + handleControlBar(){ + const ListControls = [ + (
+ + +
+ ) + ] + 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 ( + +
+

Behaviors

+ {this.SettingRender(this.state.SettingRepo)} +
+
+ ); + } +} + +export default Base; diff --git a/src/pages/settings/components/notification.js b/src/pages/settings/components/notification.js new file mode 100644 index 00000000..26bd3277 --- /dev/null +++ b/src/pages/settings/components/notification.js @@ -0,0 +1,49 @@ +import * as antd from 'antd'; +import React, { Component, Fragment } from 'react'; + +class NotificationView extends Component { + getData = () => { + const Action = ( + + ); + 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 ( + + ( + + + + )} /> + + ); + } +} + +export default NotificationView; diff --git a/src/pages/settings/components/security.js b/src/pages/settings/components/security.js new file mode 100644 index 00000000..e1937669 --- /dev/null +++ b/src/pages/settings/components/security.js @@ -0,0 +1,85 @@ +import React, { Component, Fragment } from 'react'; +import { List } from 'antd'; + +const passwordStrength = { + strong: ( + + Strong + + ), + medium: ( + + Medium + + ), + weak: ( + + Weak + + ), +}; + +class SecurityView extends Component { + getData = () => [ + { + title:

Password

, + description: ( + +

Something

+ {passwordStrength.strong} +
+ ), + actions: [ + + Modify + , + ], + }, + { + title:

Security question

, + description: 'Security cuesting seting', + actions: [ + + Set + , + ], + }, + { + title: 'Mail', + description: 'YourEmail@jeje.com', + actions: [ + + Modify + , + ], + }, + { + title: 'mfa', + description: 'mfa settings', + actions: [ + + Bind + , + ], + }, + ]; + + render() { + const data = this.getData(); + return ( + + ( + + + + )} + /> + + ); + } +} + +export default SecurityView; diff --git a/src/pages/settings/index.js b/src/pages/settings/index.js new file mode 100644 index 00000000..9854e57c --- /dev/null +++ b/src/pages/settings/index.js @@ -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 => {menuMap[item]}); + }; + + selectKey = (key) => { + this.setState({ + selectKey: key, + }); + }; + + renderChildren = () => { + const { selectKey } = this.state; + switch (selectKey) { + case 'base': + return ; + case 'security': + return ; + case 'notification': + return ; + default: + break; + } + + return null; + }; + + render() { + const { mode, selectKey } = this.state; + return ( +
+ <Icon type="setting" /> Settings + +
{ + if (ref) { + this.main = ref; + } + }} + > +
+ this.selectKey(key)} + > + {this.getMenu()} + +
+
+ {this.renderChildren()} +
+
+
+
+ ); + } +} + +export default GeneralSettings diff --git a/src/pages/settings/style.less b/src/pages/settings/style.less new file mode 100644 index 00000000..e7b494f5 --- /dev/null +++ b/src/pages/settings/style.less @@ -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; + } + } +}