mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 10:34:17 +00:00
update: app model, login & authframes
This commit is contained in:
parent
90bbda47b2
commit
fc5e4a0106
2
.gitignore
vendored
2
.gitignore
vendored
@ -13,4 +13,4 @@
|
|||||||
/src/.umi-production
|
/src/.umi-production
|
||||||
/src/.umi-test
|
/src/.umi-test
|
||||||
/.env.local
|
/.env.local
|
||||||
api/
|
|
||||||
|
20
.umirc.js
20
.umirc.js
@ -1,25 +1,7 @@
|
|||||||
import { defineConfig } from 'umi';
|
import { defineConfig } from 'umi';
|
||||||
|
|
||||||
const Path = require('path');
|
|
||||||
const { resolve } = require('path');
|
const { resolve } = require('path');
|
||||||
const themePth = require('./src/theme/index.js')
|
|
||||||
const lessToJs = require('less-vars-to-js');
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
const AntDesignThemePlugin = require('antd-theme-webpack-plugin');
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
antDir: Path.join(__dirname, './node_modules/antd'),
|
|
||||||
stylesDir: Path.join(__dirname, './src/styles'),
|
|
||||||
varFile: Path.join(__dirname, './src/styles/variables.less'),
|
|
||||||
themeVariables: ['@primary-color'],
|
|
||||||
indexFileName: 'index.html'
|
|
||||||
}
|
|
||||||
|
|
||||||
const themePlugin = new AntDesignThemePlugin(options);
|
|
||||||
|
|
||||||
|
|
||||||
const convToVars = file => lessToJs(fs.readFileSync(Path.join(__dirname, file), 'utf8'))
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
hash: false,
|
hash: false,
|
||||||
ignoreMomentLocale: true,
|
ignoreMomentLocale: true,
|
||||||
@ -33,7 +15,7 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
alias: {
|
alias: {
|
||||||
antd: resolve(__dirname, './node_modules/antd'),
|
antd: resolve(__dirname, './node_modules/antd'),
|
||||||
api: resolve(__dirname, './node_modules/@ragestudio/ycorejs-lib'),
|
api: resolve(__dirname, './node_modules/@ragestudio/ycorejs-lib'), // ./api
|
||||||
globals: resolve(__dirname, './globals'),
|
globals: resolve(__dirname, './globals'),
|
||||||
core: resolve(__dirname, './src/core'),
|
core: resolve(__dirname, './src/core'),
|
||||||
theme: resolve(__dirname, './src/theme'),
|
theme: resolve(__dirname, './src/theme'),
|
||||||
|
@ -4,4 +4,5 @@ export default {
|
|||||||
logout: 'POST /logout',
|
logout: 'POST /logout',
|
||||||
|
|
||||||
get_data: 'POST /get-user-data',
|
get_data: 'POST /get-user-data',
|
||||||
|
profileData: 'POST /early_user'
|
||||||
};
|
};
|
||||||
|
@ -40,7 +40,7 @@ module.exports = {
|
|||||||
include: [/.*/]
|
include: [/.*/]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
// Default Behaviors
|
// Default Behaviors
|
||||||
defaults: {
|
defaults: {
|
||||||
verbosity: false,
|
verbosity: false,
|
||||||
@ -50,14 +50,16 @@ module.exports = {
|
|||||||
render_pagetransition_preset: 'moveToRightScaleUp',
|
render_pagetransition_preset: 'moveToRightScaleUp',
|
||||||
|
|
||||||
feed_autorefresh: false,
|
feed_autorefresh: false,
|
||||||
|
},
|
||||||
|
|
||||||
post_maxlenght: '512',
|
stricts: {
|
||||||
post_catchlimit: '20',
|
post_maxlenght: '512',
|
||||||
post_hidebar: true,
|
post_catchlimit: '20',
|
||||||
|
post_hidebar: true,
|
||||||
|
|
||||||
// In KB
|
// In KB
|
||||||
api_maxpayload: '101376',
|
api_maxpayload: '101376',
|
||||||
api_maxovertick: 10,
|
api_maxovertick: 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"UUID": "C8mVSr-4nmPp2-pr5Vrz-CU4kg4",
|
"UUID": "C8mVSr-4nmPp2-pr5Vrz-CU4kg4",
|
||||||
"title": "Comty™",
|
"title": "Comty™",
|
||||||
"DevBuild": true,
|
"DevBuild": true,
|
||||||
"version": "0.8.08",
|
"version": "0.8.22",
|
||||||
"stage": "dev-pre",
|
"stage": "dev-pre",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "RageStudio",
|
"author": "RageStudio",
|
||||||
@ -36,6 +36,7 @@
|
|||||||
"@material-ui/core": "^4.9.9",
|
"@material-ui/core": "^4.9.9",
|
||||||
"@material-ui/icons": "^4.9.1",
|
"@material-ui/icons": "^4.9.1",
|
||||||
"@ragestudio/ycorejs-lib": "^0.1.22",
|
"@ragestudio/ycorejs-lib": "^0.1.22",
|
||||||
|
"@steveeeie/react-page-transition": "^1.2.0",
|
||||||
"antd": "^4.5.1",
|
"antd": "^4.5.1",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"babel-core": "^6.26.3",
|
"babel-core": "^6.26.3",
|
||||||
|
@ -4,7 +4,7 @@ import styles from './Loader.less'
|
|||||||
|
|
||||||
const Loader = (loading) => {
|
const Loader = (loading) => {
|
||||||
return (
|
return (
|
||||||
<div className={classNames(styles.wrapper, {[styles.end]: !loading.spinning })}>
|
<div className={classNames(styles.wrapper, {[styles.end]: !loading })}>
|
||||||
<span>Loading... </span>
|
<span>Loading... </span>
|
||||||
<div
|
<div
|
||||||
className={styles.newloader}
|
className={styles.newloader}
|
||||||
|
322
src/components/PostCreator/index.js
Normal file
322
src/components/PostCreator/index.js
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import * as antd from 'antd'
|
||||||
|
import * as core from 'core'
|
||||||
|
import * as Icons from 'components/Icons'
|
||||||
|
import styles from './index.less'
|
||||||
|
import { connect } from 'umi'
|
||||||
|
import { stricts } from 'config'
|
||||||
|
import { settings, newSetting } from 'core/libs/settings'
|
||||||
|
import $ from 'jquery'
|
||||||
|
|
||||||
|
@connect(({ app }) => ({ app }))
|
||||||
|
class PostCreator extends React.PureComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super(props),
|
||||||
|
this.state = {
|
||||||
|
maxFileSize: stricts.api_maxpayload,
|
||||||
|
maxTextLenght: stricts.post_maxlenght,
|
||||||
|
|
||||||
|
renderValid: false,
|
||||||
|
loading: false,
|
||||||
|
|
||||||
|
textLenght: stricts.post_maxlenght,
|
||||||
|
rawText: '',
|
||||||
|
posting: false,
|
||||||
|
postingResult: false,
|
||||||
|
shareWith: 'any',
|
||||||
|
|
||||||
|
uploader: false,
|
||||||
|
uploaderFile: null,
|
||||||
|
uploaderFileOrigin: null,
|
||||||
|
},
|
||||||
|
window.PostCreatorComponent = this
|
||||||
|
}
|
||||||
|
|
||||||
|
dropRef = React.createRef()
|
||||||
|
|
||||||
|
ToogleUploader() {
|
||||||
|
this.setState({ uploader: !this.state.uploader })
|
||||||
|
}
|
||||||
|
handleDeleteFile = () => {
|
||||||
|
this.setState({ uploaderFile: null })
|
||||||
|
}
|
||||||
|
handleFileUpload = info => {
|
||||||
|
if (info.file.status === 'uploading') {
|
||||||
|
this.setState({ loading: true })
|
||||||
|
}
|
||||||
|
if (info.file.status === 'done') {
|
||||||
|
this.setState({ uploaderFileOrigin: info.file.originFileObj, uploader: false })
|
||||||
|
|
||||||
|
core.getBase64(info.file.originFileObj, fileURL => {
|
||||||
|
this.setState({ uploaderFile: fileURL, loading: false })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeUpload = file => {
|
||||||
|
const filter =
|
||||||
|
file.type === 'image/jpeg' ||
|
||||||
|
file.type === 'audio/mp3' ||
|
||||||
|
file.type === 'audio/wav' ||
|
||||||
|
file.type === 'audio/ogg' ||
|
||||||
|
file.type === 'image/png' ||
|
||||||
|
file.type === 'image/jpg' ||
|
||||||
|
file.type === 'image/gif' ||
|
||||||
|
file.type === 'video/mp4'
|
||||||
|
if (!filter) {
|
||||||
|
antd.message.error(`${file.type} This file is not valid!`)
|
||||||
|
}
|
||||||
|
const maxsize = file.size / 1024 / 1024 < stricts.api_maxpayload
|
||||||
|
if (!maxsize) {
|
||||||
|
antd.message.error(
|
||||||
|
`Image must smaller than ${stricts.api_maxpayload} KB!`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return filter && maxsize
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChanges = ({ target: { value } }) => {
|
||||||
|
this.setState({
|
||||||
|
rawText: value,
|
||||||
|
textLenght: this.state.maxTextLenght - value.length,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleKeysProgressBar() {
|
||||||
|
return this.state.textLenght <= (this.state.maxTextLenght / 100) * 30? 'exception' : 'active'
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDragIn = e => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
|
||||||
|
this.state.uploader? this.setState({ uploader: true }) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDragOut = e => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
|
||||||
|
this.state.uploader? null : this.setState({ uploader: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
// Validate for render
|
||||||
|
if (this.props.app.userData) {
|
||||||
|
this.setState({renderValid: true})
|
||||||
|
}
|
||||||
|
|
||||||
|
// const _this = this
|
||||||
|
// $('body').bind('paste', function(je) {
|
||||||
|
// var e = je.originalEvent
|
||||||
|
// for (var i = 0; i < e.clipboardData.items.length; i++) {
|
||||||
|
// var item = e.clipboardData.items[i]
|
||||||
|
// if (item.type.indexOf('image') != -1) {
|
||||||
|
// //item.
|
||||||
|
// let a;
|
||||||
|
// a = item.getAsFile()
|
||||||
|
// _this.setState({ uploaderFileOrigin: a })
|
||||||
|
// core.ReadFileAsB64(a, res => {
|
||||||
|
// _this.setState({ uploaderFile: res })
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// // ignore not images
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// let div = this.dropRef.current
|
||||||
|
// div.addEventListener('dragenter', this.handleDragIn)
|
||||||
|
// div.addEventListener('dragleave', this.handleDragOut)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
// let div = this.dropRef.current
|
||||||
|
// div.removeEventListener('dragenter', this.handleDragIn)
|
||||||
|
// div.removeEventListener('dragleave', this.handleDragOut)
|
||||||
|
}
|
||||||
|
|
||||||
|
canPost() {
|
||||||
|
const isTypedSomething = this.state.textLenght < this.state.maxTextLenght
|
||||||
|
const isUploadedFile = this.state.uploaderFile ? true : false
|
||||||
|
|
||||||
|
return isUploadedFile || isTypedSomething
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { userData } = this.props.app
|
||||||
|
const { textLenght, uploaderFile } = this.state
|
||||||
|
|
||||||
|
const GetPostPrivacy = {
|
||||||
|
bool: (e) => {
|
||||||
|
switch (e) {
|
||||||
|
case 'any':
|
||||||
|
return '0'
|
||||||
|
case 'only_followers':
|
||||||
|
return '1'
|
||||||
|
case 'only_follow':
|
||||||
|
return '2'
|
||||||
|
case 'private':
|
||||||
|
return '3'
|
||||||
|
default:
|
||||||
|
return '0'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
decorator: (e) => {
|
||||||
|
switch (e) {
|
||||||
|
case 'any':
|
||||||
|
return <span><Icons.GlobalOutlined /> Share with everyone</span>
|
||||||
|
case 'only_follow':
|
||||||
|
return <span><Icons.TeamOutlined /> Share with people I follow</span>
|
||||||
|
case 'only_followers':
|
||||||
|
return <span><Icons.UsergroupAddOutlined /> Share with people follow me</span>
|
||||||
|
case 'private':
|
||||||
|
return <span><Icons.EyeInvisibleOutlined /> Dont share, only me</span>
|
||||||
|
default:
|
||||||
|
return <span>Unknown</span>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const shareOptionsMenu = (
|
||||||
|
<antd.Menu onClick={key => this.setState({ shareWith: key })}>
|
||||||
|
<antd.Menu.Item key="any">
|
||||||
|
{GetPostPrivacy.decorator('any')}
|
||||||
|
</antd.Menu.Item>
|
||||||
|
<antd.Menu.Item key="only_follow">
|
||||||
|
{GetPostPrivacy.decorator('only_follow')}
|
||||||
|
</antd.Menu.Item>
|
||||||
|
<antd.Menu.Item key="only_followers">
|
||||||
|
{GetPostPrivacy.decorator('only_followers')}
|
||||||
|
</antd.Menu.Item>
|
||||||
|
<antd.Menu.Item key="private">
|
||||||
|
{GetPostPrivacy.decorator('private')}
|
||||||
|
</antd.Menu.Item>
|
||||||
|
</antd.Menu>
|
||||||
|
)
|
||||||
|
|
||||||
|
const PostCreator_Uploader = () => {
|
||||||
|
return(
|
||||||
|
<div className={styles.uploader}>
|
||||||
|
<antd.Upload.Dragger
|
||||||
|
multiple={false}
|
||||||
|
listType="picture"
|
||||||
|
showUploadList={false}
|
||||||
|
beforeUpload={this.beforeUpload}
|
||||||
|
onChange={this.handleFileUpload}
|
||||||
|
>
|
||||||
|
<Icons.CloudUploadOutlined />
|
||||||
|
<span>Drop your file here o click for upload</span>
|
||||||
|
</antd.Upload.Dragger>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const PostCreator_InputText = () => {
|
||||||
|
return(
|
||||||
|
<>
|
||||||
|
<div className={styles.titleAvatar}>
|
||||||
|
<img src={userData.avatar} />
|
||||||
|
</div>
|
||||||
|
<antd.Input.TextArea
|
||||||
|
disabled={this.state.posting ? true : false}
|
||||||
|
onPressEnter={this.handlePublishPost}
|
||||||
|
value={this.state.rawText}
|
||||||
|
autoSize={{ minRows: 3, maxRows: 5 }}
|
||||||
|
dragable="false"
|
||||||
|
placeholder="What are you thinking?"
|
||||||
|
onChange={this.handleChanges}
|
||||||
|
allowClear
|
||||||
|
maxLength={this.state.maxTextLenght}
|
||||||
|
rows={8}
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<antd.Button
|
||||||
|
disabled={this.state.posting ? true : !this.canPost()}
|
||||||
|
onClick={this.handlePublishPost}
|
||||||
|
type="primary"
|
||||||
|
icon={
|
||||||
|
this.state.postingResult ? (
|
||||||
|
<Icons.CheckCircleOutlined />
|
||||||
|
) : this.state.posting ? (
|
||||||
|
<Icons.LoadingOutlined />
|
||||||
|
) : (
|
||||||
|
<Icons.ExportOutlined />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PostCreatorComponent = () => {
|
||||||
|
return(
|
||||||
|
<>
|
||||||
|
<div ref={this.dropRef} className={styles.inputWrapper}>
|
||||||
|
{this.state.uploader ? <PostCreator_Uploader /> : <PostCreator_InputText /> }
|
||||||
|
</div>
|
||||||
|
<div className={styles.progressHandler}>
|
||||||
|
<antd.Progress
|
||||||
|
className={
|
||||||
|
this.state.posting
|
||||||
|
? styles.proccessUnset
|
||||||
|
: textLenght < 512
|
||||||
|
? styles.proccessSet
|
||||||
|
: styles.proccessUnset
|
||||||
|
}
|
||||||
|
percent={((textLenght / this.state.maxTextLenght) * 100).toFixed(2)}
|
||||||
|
status={this.handleKeysProgressBar()}
|
||||||
|
strokeWidth="4px"
|
||||||
|
showInfo={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{uploaderFile ? this.renderPostPlayer(uploaderFile) : null}
|
||||||
|
<div className={styles.postExtra}>
|
||||||
|
<antd.Button
|
||||||
|
styles={this.state.uploader ? { fontSize: '20px' } : null}
|
||||||
|
type="ghost"
|
||||||
|
onClick={() => this.ToogleUpload()}
|
||||||
|
>
|
||||||
|
|
||||||
|
{this.state.uploader ? (
|
||||||
|
<Icons.Cancel />
|
||||||
|
) : (
|
||||||
|
<Icons.AddCircle />
|
||||||
|
)}
|
||||||
|
</antd.Button>
|
||||||
|
<antd.Button type="ghost" onClick={() => null}>
|
||||||
|
<Icons.Tune />
|
||||||
|
</antd.Button>
|
||||||
|
<antd.Dropdown overlay={shareOptionsMenu}>
|
||||||
|
<a
|
||||||
|
className={styles.shareWith}
|
||||||
|
onClick={e => e.preventDefault()}
|
||||||
|
>
|
||||||
|
{GetPostPrivacy.decorator(this.state.shareWith)}
|
||||||
|
</a>
|
||||||
|
</antd.Dropdown>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const PostCreator_Invalid = () => {
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
<h3>This component cant be displayed!</h3>
|
||||||
|
<antd.Skeleton active />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.cardWrapper}>
|
||||||
|
<antd.Card bordered="false">
|
||||||
|
{ this.state.renderValid? <PostCreatorComponent /> : <PostCreator_Invalid /> }
|
||||||
|
</antd.Card>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default PostCreator
|
315
src/components/PostCreator/index.less
Normal file
315
src/components/PostCreator/index.less
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
@import '~theme/index.less';
|
||||||
|
|
||||||
|
.cardWrapper {
|
||||||
|
// box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
|
||||||
|
border-radius: 7px;
|
||||||
|
max-width: 510px;
|
||||||
|
min-width: 265px;
|
||||||
|
width: auto;
|
||||||
|
margin: 7px auto 50px auto;
|
||||||
|
|
||||||
|
:global {
|
||||||
|
textarea {
|
||||||
|
font-weight: 500;
|
||||||
|
resize: none;
|
||||||
|
outline: none !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea:focus {
|
||||||
|
outline: none !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea:hover {
|
||||||
|
outline: none !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-meta-detail>div:not(:last-child) {
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card {
|
||||||
|
border-radius: 7px;
|
||||||
|
border: 0;
|
||||||
|
border-top: 1px solid #4646460c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-body {
|
||||||
|
padding: 5px 15px 5px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-actions {
|
||||||
|
border-top: 0;
|
||||||
|
background: #EBEBEB;
|
||||||
|
opacity: 0;
|
||||||
|
height: 30px;
|
||||||
|
position: relative;
|
||||||
|
transition: opacity 150ms linear, position 150ms linear, transform 150ms linear;
|
||||||
|
border-radius: 0 0 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-actions:hover {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translate(0, 15px);
|
||||||
|
transition: opacity 150ms linear, position 150ms linear, transform 150ms linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-card-actions>li {
|
||||||
|
margin: -20px 0 0 0;
|
||||||
|
border-right: 0;
|
||||||
|
|
||||||
|
i {
|
||||||
|
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
height: 100%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.titleAvatar {
|
||||||
|
width: 45px;
|
||||||
|
height: 45px;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
:global {
|
||||||
|
img {
|
||||||
|
width: 45px;
|
||||||
|
height: 45px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputWrapper {
|
||||||
|
display: flex;
|
||||||
|
z-index: 10;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
padding: 18px 7px 0 7px;
|
||||||
|
transition: height 150ms linear;
|
||||||
|
|
||||||
|
:global {
|
||||||
|
.ant-btn-primary {
|
||||||
|
z-index: 10;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 0 10px 10px 0;
|
||||||
|
height: 100%;
|
||||||
|
vertical-align: bottom;
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-input {
|
||||||
|
z-index: 10;
|
||||||
|
position: relative;
|
||||||
|
border-color: transparent !important;
|
||||||
|
box-shadow: none;
|
||||||
|
border-radius: 3px 0 0 0;
|
||||||
|
height: 100%;
|
||||||
|
padding: 5px 10px 5px 10px;
|
||||||
|
transition: height 150ms linear;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-input:hover {
|
||||||
|
border-color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-input-affix-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progressHandler {
|
||||||
|
z-index: 10;
|
||||||
|
position: relative;
|
||||||
|
margin: 0 7px 0 7px;
|
||||||
|
|
||||||
|
:global {
|
||||||
|
.ant-progress-bg {
|
||||||
|
border-radius: 0 0 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-progress-inner {
|
||||||
|
border-radius: 0 0 14px 14px;
|
||||||
|
width: calc(100% - 32px);
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.postExtra {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
margin: 0 0 40px 0;
|
||||||
|
|
||||||
|
.shareWith {
|
||||||
|
color: rgb(53, 53, 53);
|
||||||
|
float: right;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global {
|
||||||
|
.MuiSvgIcon-root {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 18px;
|
||||||
|
transition: fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin: 8px;
|
||||||
|
line-height: 1px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-btn .anticon {
|
||||||
|
transition: margin-left 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-btn {
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
|
float: left;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 11px;
|
||||||
|
margin: 0 10px;
|
||||||
|
background-color: #eeeeee;
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-btn:hover {
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploader {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 10px;
|
||||||
|
z-index: 30;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
span {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global {
|
||||||
|
.ant-upload.ant-upload-drag {
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: border-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.anticon svg {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.imagePreviewWrapper {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
// top: -100px;
|
||||||
|
margin: 0 0 15px 0;
|
||||||
|
background-color: #eeeeee;
|
||||||
|
|
||||||
|
.imagePreview {
|
||||||
|
z-index: 5;
|
||||||
|
position: relative;
|
||||||
|
width: 50%;
|
||||||
|
margin: auto;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 150ms linear;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
border: 0.5px rgba(56, 56, 56, 0.459) solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
video {
|
||||||
|
width: 100%;
|
||||||
|
border: 0.5px rgba(56, 56, 56, 0.459) solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
transition: all 150ms linear;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageOverlay {
|
||||||
|
z-index: 10;
|
||||||
|
position: relative;
|
||||||
|
opacity: 0;
|
||||||
|
transition: all 150ms linear;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.imagePreviewWrapper:hover .imagePreview {
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: all 150ms linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imagePreviewWrapper:hover .imageOverlay {
|
||||||
|
opacity: 1;
|
||||||
|
transition: all 150ms linear;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.proccessUnset {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 250ms linear;
|
||||||
|
animation: proccessUnset 250ms linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proccessSet {
|
||||||
|
transition: opacity 250ms linear;
|
||||||
|
animation: proccessSet 250ms linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes proccessSet {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes proccessUnset {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fontct {
|
||||||
|
font-family: "Poppins", sans-serif;
|
||||||
|
}
|
@ -15,6 +15,7 @@ import UserBadges from './UserBadges'
|
|||||||
|
|
||||||
// Post Components
|
// Post Components
|
||||||
import MediaPlayer from './MediaPlayer'
|
import MediaPlayer from './MediaPlayer'
|
||||||
|
import PostCreator from './PostCreator'
|
||||||
|
|
||||||
// Mix & Export all
|
// Mix & Export all
|
||||||
export {
|
export {
|
||||||
@ -25,5 +26,6 @@ export {
|
|||||||
UserBadges,
|
UserBadges,
|
||||||
PageTransition,
|
PageTransition,
|
||||||
MyLayout,
|
MyLayout,
|
||||||
Loader
|
Loader,
|
||||||
|
PostCreator
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
export * from './session';
|
export * from './router'
|
||||||
export * from './user';
|
|
||||||
export * from './router'
|
import * as user from './user'
|
||||||
|
import * as session from './session'
|
||||||
|
|
||||||
|
export { user, session }
|
@ -11,18 +11,18 @@ import { history } from 'umi';
|
|||||||
* Specify the paths of the files, in this case it is pointing to the root
|
* Specify the paths of the files, in this case it is pointing to the root
|
||||||
*/
|
*/
|
||||||
export const router = {
|
export const router = {
|
||||||
go: e => {
|
|
||||||
goTo.element('primaryContent');
|
|
||||||
router.push(e);
|
|
||||||
},
|
|
||||||
push: e => {
|
push: e => {
|
||||||
history.push({
|
history.push({
|
||||||
pathname: `${e}`,
|
pathname: `${e}`,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
goprofile: () => {
|
go: e => {
|
||||||
|
router.push(e);
|
||||||
goTo.element('primaryContent');
|
goTo.element('primaryContent');
|
||||||
|
},
|
||||||
|
goprofile: () => {
|
||||||
router.push(`/@${e}`);
|
router.push(`/@${e}`);
|
||||||
|
goTo.element('primaryContent');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,46 +1,38 @@
|
|||||||
/**
|
|
||||||
*
|
|
||||||
* @param {HTMLTableElement} session - Callback / Credentials
|
|
||||||
* @returns {callback} make an API call to verify credentials
|
|
||||||
* @throws {NotFoundError} show error when credentials were not correctly put
|
|
||||||
* @async
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
import endpoints from 'config/endpoints';
|
import endpoints from 'config/endpoints';
|
||||||
import { v3_model } from 'core/libs';
|
import { v3_model } from 'core/libs';
|
||||||
|
|
||||||
|
|
||||||
// @param {Array} payload callback - check the information and if it is correct give access
|
|
||||||
function auth(payload, callback) {
|
function auth(payload, callback) {
|
||||||
if (!payload) return false;
|
if (!payload) return false;
|
||||||
const { username, password, server_key } = payload;
|
const { username, password, server_key } = payload;
|
||||||
|
|
||||||
if (username && password) {
|
if (username && password) {
|
||||||
|
const frame = { username: atob(username), password: atob(password) }
|
||||||
v3_model.api_request(
|
v3_model.api_request(
|
||||||
{
|
{
|
||||||
|
body: frame,
|
||||||
endpoint: endpoints.auth,
|
endpoint: endpoints.auth,
|
||||||
serverKey: server_key,
|
serverKey: server_key,
|
||||||
verbose: true,
|
verbose: true,
|
||||||
},
|
},
|
||||||
(err, res) => {
|
(err, res) => {
|
||||||
console.log(err, res);
|
return callback(err, res);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return callback(false, true);
|
|
||||||
} else {
|
} else {
|
||||||
const res = { status: 100, message: 'Invalid Credentials!' };
|
const res = { status: 100, message: 'Invalid Credentials!' };
|
||||||
return callback(res, false);
|
return callback(res, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deauth() {}
|
function deauth() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// check the information and if it is correct give access
|
|
||||||
const backup = {
|
const backup = {
|
||||||
get: () => {},
|
get: () => {},
|
||||||
set: () => {},
|
set: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export { auth, deauth, backup };
|
export { auth, deauth, backup };
|
||||||
|
@ -7,21 +7,28 @@ const set = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const get = {
|
export const get = {
|
||||||
data: parms => {
|
data: (parms, callback) => {
|
||||||
if (!parms) return false;
|
if (!parms) return false;
|
||||||
const { id, type } = parms;
|
const { id, access_token, serverKey, fetch } = parms;
|
||||||
|
|
||||||
if (!id) {
|
let req = {
|
||||||
|
fetch: fetch? fetch : 'user_data'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!id || !access_token) {
|
||||||
// core get id data from current session
|
// core get id data from current session
|
||||||
}
|
}
|
||||||
v3_model.api_request(
|
v3_model.api_request(
|
||||||
{
|
{
|
||||||
|
body: {user_id: id, fetch: req.fetch},
|
||||||
|
serverKey: serverKey,
|
||||||
|
userToken: access_token,
|
||||||
endpoint: endpoints.get_data,
|
endpoint: endpoints.get_data,
|
||||||
verbose: true,
|
verbose: true,
|
||||||
},
|
},
|
||||||
(err, res) => {
|
(err, res) => {
|
||||||
console.log(err, res);
|
return callback(err, res)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -33,17 +40,32 @@ const get = {
|
|||||||
// core get id data from current session
|
// core get id data from current session
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
profileData: parms => {
|
profileData: (parms, callback) => {
|
||||||
if (!parms) return false;
|
if (!parms) return false
|
||||||
const { id } = parms;
|
|
||||||
|
|
||||||
if (!id) {
|
const { username } = parms
|
||||||
// core get id data from current session
|
|
||||||
|
if (username) {
|
||||||
|
v3_model.api_request(
|
||||||
|
{
|
||||||
|
body: { username },
|
||||||
|
endpoint: endpoints.profileData,
|
||||||
|
verbose: true,
|
||||||
|
},
|
||||||
|
(err, res) => {
|
||||||
|
err? console.error(err) : null
|
||||||
|
return callback(false, res);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const res = { status: 105, message: 'Invalid Username!' };
|
||||||
|
return callback(res, false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const actions = {
|
export const actions = {
|
||||||
block: parms => {
|
block: parms => {
|
||||||
if (!parms) return false;
|
if (!parms) return false;
|
||||||
const { id, toID } = parms;
|
const { id, toID } = parms;
|
||||||
@ -58,8 +80,3 @@ const actions = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
|
||||||
//set
|
|
||||||
get,
|
|
||||||
actions,
|
|
||||||
};
|
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
import { lib, v3_request } from 'api';
|
import { lib, v3_request } from 'api';
|
||||||
import endpoints_list from 'config/endpoints';
|
import endpoints_list from 'config/endpoints';
|
||||||
import { app_config } from 'config';
|
import { app_config } from 'config';
|
||||||
import * as core from 'core'
|
|
||||||
import { connect } from 'dva';
|
|
||||||
|
|
||||||
const { api_prefix } = app_config;
|
const { api_prefix } = app_config;
|
||||||
const { uri_resolver } = lib;
|
const { uri_resolver } = lib;
|
||||||
|
|
||||||
|
|
||||||
async function compileURI(e, callback) {
|
async function compileURI(e, callback) {
|
||||||
const resolvers = await uri_resolver();
|
const resolvers = await uri_resolver();
|
||||||
const prefix = resolvers[api_prefix];
|
const prefix = resolvers[api_prefix];
|
||||||
@ -15,7 +12,6 @@ async function compileURI(e, callback) {
|
|||||||
let final = null;
|
let final = null;
|
||||||
let url;
|
let url;
|
||||||
let method;
|
let method;
|
||||||
|
|
||||||
const endpointSplit = e.split(' ');
|
const endpointSplit = e.split(' ');
|
||||||
if (endpointSplit.length === 2) {
|
if (endpointSplit.length === 2) {
|
||||||
method = endpointSplit[0];
|
method = endpointSplit[0];
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { PureComponent, Fragment } from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Helmet } from 'react-helmet'
|
import { Helmet } from 'react-helmet'
|
||||||
import { Loader } from 'components'
|
import { Loader } from 'components'
|
||||||
@ -8,39 +8,44 @@ import { queryLayout } from 'core'
|
|||||||
import config from 'config'
|
import config from 'config'
|
||||||
|
|
||||||
import PrimaryLayout from './PrimaryLayout'
|
import PrimaryLayout from './PrimaryLayout'
|
||||||
|
import PublicLayout from './PublicLayout'
|
||||||
import './BaseLayout.less'
|
import './BaseLayout.less'
|
||||||
|
|
||||||
const LayoutMap = {
|
const LayoutMap = {
|
||||||
primary: PrimaryLayout
|
primary: PrimaryLayout,
|
||||||
// public: PublicLayout,
|
public: PublicLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
@withRouter
|
@withRouter
|
||||||
@connect(({ app, loading }) => ({ app, loading }))
|
@connect(({ app, loading }) => ({ app, loading }))
|
||||||
class BaseLayout extends PureComponent {
|
class BaseLayout extends React.Component {
|
||||||
previousPath = ''
|
previousPath = ''
|
||||||
|
renderLoading = true
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { loading, children, location } = this.props
|
const { loading, children, location } = this.props
|
||||||
const Container = LayoutMap[queryLayout(config.layouts, location.pathname)]
|
const Container = LayoutMap[queryLayout(config.layouts, location.pathname)]
|
||||||
|
|
||||||
const currentPath = location.pathname + location.search
|
const currentPath = location.pathname + location.search
|
||||||
|
|
||||||
if (currentPath !== this.previousPath) {
|
if (currentPath !== this.previousPath) {
|
||||||
NProgress.start()
|
NProgress.start()
|
||||||
|
this.renderLoading = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loading.global) {
|
if (!loading.global) {
|
||||||
NProgress.done()
|
NProgress.done()
|
||||||
this.previousPath = currentPath
|
this.previousPath = currentPath
|
||||||
|
this.renderLoading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<React.Fragment>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{config.app_config.siteName}</title>
|
<title>{config.app_config.siteName}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
{Loader(loading)}
|
{Loader(this.renderLoading)}
|
||||||
<Container>{children}</Container>
|
<Container>{children}</Container>
|
||||||
</Fragment>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import PropTypes from 'prop-types'
|
|||||||
import {withRouter, connect} from 'umi'
|
import {withRouter, connect} from 'umi'
|
||||||
import {
|
import {
|
||||||
MyLayout,
|
MyLayout,
|
||||||
PageTransition,
|
|
||||||
} from 'components'
|
} from 'components'
|
||||||
import { enquireScreen, unenquireScreen } from 'enquire-js'
|
import { enquireScreen, unenquireScreen } from 'enquire-js'
|
||||||
import store from 'store'
|
import store from 'store'
|
||||||
@ -103,17 +102,13 @@ class PrimaryLayout extends React.Component {
|
|||||||
<antd.Layout id="app" className={isActive(currentTheme['darkmode'])? "dark_mode" : null }>
|
<antd.Layout id="app" className={isActive(currentTheme['darkmode'])? "dark_mode" : null }>
|
||||||
<Sider {...SiderProps} />
|
<Sider {...SiderProps} />
|
||||||
<div className={styles.primary_layout_container}>
|
<div className={styles.primary_layout_container}>
|
||||||
<PageTransition
|
|
||||||
preset="moveToRightScaleUp"
|
|
||||||
transitionKey={location.pathname}
|
|
||||||
>
|
|
||||||
<Content
|
<Content
|
||||||
id="primaryContent"
|
id="primaryContent"
|
||||||
className={styles.primary_layout_content}
|
className={styles.primary_layout_content}
|
||||||
>
|
>
|
||||||
{children? children : null}
|
{children? children : null}
|
||||||
</Content>
|
</Content>
|
||||||
</PageTransition>
|
|
||||||
</div>
|
</div>
|
||||||
<Overlay {...OverlayProps} />
|
<Overlay {...OverlayProps} />
|
||||||
</antd.Layout>
|
</antd.Layout>
|
||||||
|
67
src/layouts/PublicLayout.js
Normal file
67
src/layouts/PublicLayout.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import store from 'store'
|
||||||
|
|
||||||
|
import {
|
||||||
|
MyLayout,
|
||||||
|
PageTransition,
|
||||||
|
} from 'components'
|
||||||
|
import { enquireScreen, unenquireScreen } from 'enquire-js'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
|
||||||
|
import * as antd from 'antd'
|
||||||
|
import * as Icons from 'components/Icons'
|
||||||
|
|
||||||
|
import styles from './PrimaryLayout.less'
|
||||||
|
|
||||||
|
const { Content } = antd.Layout
|
||||||
|
|
||||||
|
export default class PublicLayout extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
window.PrimaryComponent = this
|
||||||
|
this.state = {
|
||||||
|
isMobile: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.enquireHandler = enquireScreen(mobile => {
|
||||||
|
const { isMobile } = this.state
|
||||||
|
if (isMobile !== mobile) {
|
||||||
|
this.setState({
|
||||||
|
isMobile: mobile,
|
||||||
|
})
|
||||||
|
store.set('mobile_src', mobile)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
unenquireScreen(this.enquireHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { children } = this.props
|
||||||
|
const { isMobile } = this.state
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<antd.Layout id="publicLayout" className={classnames(styles.primary_layout, {[styles.mobile]: isMobile})}>
|
||||||
|
<div className={styles.primary_layout_container}>
|
||||||
|
<PageTransition
|
||||||
|
preset="moveToRightScaleUp"
|
||||||
|
transitionKey={window.location.pathname}
|
||||||
|
>
|
||||||
|
<Content
|
||||||
|
id="publicContent"
|
||||||
|
className={styles.primary_layout_content}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Content>
|
||||||
|
</PageTransition>
|
||||||
|
</div>
|
||||||
|
</antd.Layout>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,9 @@ import store from 'store';
|
|||||||
import { pathMatchRegexp, queryLayout } from 'core';
|
import { pathMatchRegexp, queryLayout } from 'core';
|
||||||
import { app_config } from 'config';
|
import { app_config } from 'config';
|
||||||
import keys from 'config/app_keys';
|
import keys from 'config/app_keys';
|
||||||
import * as core from 'core';
|
import { router } from 'core/cores';
|
||||||
import { session } from 'core/cores';
|
|
||||||
import verbosity from 'core/libs/verbosity'
|
import verbosity from 'core/libs/verbosity'
|
||||||
import { theme } from 'core/libs/style'
|
import { notify } from 'core/libs/interface/notify'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespace: 'app',
|
namespace: 'app',
|
||||||
@ -17,7 +16,7 @@ export default {
|
|||||||
ng_services: false,
|
ng_services: false,
|
||||||
session_valid: false,
|
session_valid: false,
|
||||||
|
|
||||||
session_token: null,
|
session_token: sessionStorage.getItem('session'),
|
||||||
session_data: null,
|
session_data: null,
|
||||||
session_uuid: null,
|
session_uuid: null,
|
||||||
|
|
||||||
@ -63,30 +62,31 @@ export default {
|
|||||||
effects: {
|
effects: {
|
||||||
*query({ payload }, { call, put, select }) {
|
*query({ payload }, { call, put, select }) {
|
||||||
const service = yield select(state => state.app.service_valid);
|
const service = yield select(state => state.app.service_valid);
|
||||||
|
const session = yield select(state => state.app.session_valid);
|
||||||
|
|
||||||
|
yield put({ type: 'updateFrames' })
|
||||||
|
|
||||||
if (!service) {
|
if (!service) {
|
||||||
console.error('❌ Cannot connect with validate session service!');
|
console.error('❌ Cannot connect with validate session service!');
|
||||||
return yield put({
|
|
||||||
type: 'updateState',
|
|
||||||
payload: { service_valid: false },
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session) {
|
|
||||||
if (pathMatchRegexp(['/', '/login'], window.location.pathname)) {
|
|
||||||
app.router.push({ pathname: `${app_config.MainPath}` });
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
// if (session) {
|
||||||
} else if (
|
// if (pathMatchRegexp(['/', '/login'], window.location.pathname)) {
|
||||||
!pathMatchRegexp(['', '/login'], window.location.pathname) &&
|
// app.router.push({ pathname: `${app_config.MainPath}` });
|
||||||
queryLayout(config.layouts, window.location.pathname) !== 'public'
|
// }
|
||||||
) {
|
|
||||||
if (validBackup == true) {
|
// return true;
|
||||||
// logout normal
|
// } else if (
|
||||||
} else {
|
// !pathMatchRegexp(['', '/login'], window.location.pathname) &&
|
||||||
core.router.push({ pathname: '/login' });
|
// queryLayout(config.layouts, window.location.pathname) !== 'public'
|
||||||
}
|
// ) {
|
||||||
}
|
// if (validBackup == true) {
|
||||||
|
// // logout normal
|
||||||
|
// } else {
|
||||||
|
// core.router.push({ pathname: '/login' });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
*update({ payload }, { call, put, select }) {
|
*update({ payload }, { call, put, select }) {
|
||||||
const session = yield select(state => state.app.session_valid);
|
const session = yield select(state => state.app.session_valid);
|
||||||
@ -105,14 +105,10 @@ export default {
|
|||||||
},
|
},
|
||||||
*login({ payload }, { call, put, select }) {
|
*login({ payload }, { call, put, select }) {
|
||||||
if (!payload) return false;
|
if (!payload) return false;
|
||||||
const serverKey = yield select(state => state.app.server_key);
|
|
||||||
const requestPayload = { username: payload.username, password: payload.password, server_key: serverKey }
|
const { user_id, access_token } = payload.authFrame
|
||||||
session.auth(requestPayload, (err, res) => {
|
|
||||||
if (err) {
|
return yield put({ type: 'handleLogin', payload: { user_id, access_token, user_data: payload.dataFrame } })
|
||||||
const { status, message } = err;
|
|
||||||
return console.log(status, message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
*updateTheme({payload}, {put, select}){
|
*updateTheme({payload}, {put, select}){
|
||||||
if (!payload) return false
|
if (!payload) return false
|
||||||
@ -146,6 +142,40 @@ export default {
|
|||||||
...payload,
|
...payload,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
updateFrames(state) {
|
||||||
|
let sessionAuthframe = sessionStorage.getItem('session')
|
||||||
|
let sessionDataframe = sessionStorage.getItem('data')
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (sessionAuthframe) {
|
||||||
|
sessionAuthframe = JSON.parse(atob(sessionAuthframe))
|
||||||
|
}
|
||||||
|
if (sessionDataframe) {
|
||||||
|
sessionDataframe = JSON.parse(atob(sessionDataframe))
|
||||||
|
}
|
||||||
|
|
||||||
|
state.session_token = sessionAuthframe.session_token,
|
||||||
|
state.session_uuid = sessionAuthframe.session_uuid
|
||||||
|
state.session_data = sessionDataframe
|
||||||
|
} catch (error) {
|
||||||
|
verbosity.error(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleLogin(state, { payload }){
|
||||||
|
if (!payload) return false
|
||||||
|
|
||||||
|
state.session_token = payload.access_token
|
||||||
|
state.session_uuid = payload.user_id
|
||||||
|
state.session_data = payload.user_data
|
||||||
|
|
||||||
|
const sessionAuthframe = btoa(JSON.stringify({session_token: payload.access_token, session_uuid: payload.user_id}))
|
||||||
|
const sessionDataframe = btoa(payload.user_data)
|
||||||
|
|
||||||
|
sessionStorage.setItem('session', sessionAuthframe)
|
||||||
|
sessionStorage.setItem('data', sessionDataframe)
|
||||||
|
notify.success('Login done!')
|
||||||
|
router.push('/')
|
||||||
|
},
|
||||||
|
|
||||||
handleThemeChange(state, { payload }) {
|
handleThemeChange(state, { payload }) {
|
||||||
store.set('theme', payload);
|
store.set('theme', payload);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { request } from '@ragestudio/ycorejs-lib';
|
import { request } from 'api';
|
||||||
import {
|
import {
|
||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
|
9
src/pages/explore/index.js
Normal file
9
src/pages/explore/index.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { PostCreator } from 'components'
|
||||||
|
export default class Explore_Page extends React.Component{
|
||||||
|
render(){
|
||||||
|
return(
|
||||||
|
<PostCreator />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'umi';
|
import { connect } from 'umi';
|
||||||
import * as antd from 'antd'
|
import * as antd from 'antd'
|
||||||
|
import * as Icons from 'components/Icons'
|
||||||
|
|
||||||
@connect(({ app }) => ({ app }))
|
@connect(({ app }) => ({ app }))
|
||||||
class PageIndex extends React.PureComponent {
|
class PageIndex extends React.PureComponent {
|
||||||
@ -37,7 +38,13 @@ class PageIndex extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const map = tmp.map(e => {
|
const map = tmp.map(e => {
|
||||||
return(<div style={{ margin: '20px 50px 20px 10px' }} key={e.key} > <h4>{e.key}</h4><span>{JSON.stringify(e.value)}</span> </div>)
|
const v = JSON.stringify(e.value)
|
||||||
|
return(
|
||||||
|
<div style={{ margin: '20px 50px 20px 10px' }} key={e.key} >
|
||||||
|
<h4>{e.key}</h4>
|
||||||
|
{v.length < 500? <span>{v}</span> : <antd.Collapse ><antd.Collapse.Panel header={`Hidden text ( ${v.length} Characters )`}><span>{v}</span></antd.Collapse.Panel></antd.Collapse>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
return map
|
return map
|
||||||
@ -45,7 +52,7 @@ class PageIndex extends React.PureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<antd.Card theme={window.DarkMode? "dark" : null} title="APP STATE">
|
<antd.Card style={{ wordBreak: 'break-all' }} title={<><Icons.Redux style={{ height: '19px', marginRight: '7px' }} /> Redux state</>}>
|
||||||
{AppState()}
|
{AppState()}
|
||||||
</antd.Card>
|
</antd.Card>
|
||||||
|
|
||||||
|
132
src/pages/login/index.js
Normal file
132
src/pages/login/index.js
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { app_info } from 'core'
|
||||||
|
import styles from './index.less'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
|
||||||
|
import * as antd from 'antd'
|
||||||
|
import * as Icons from 'components/Icons'
|
||||||
|
|
||||||
|
import { RegistrationForm } from './register.js'
|
||||||
|
import { NormalLoginForm } from './login.js'
|
||||||
|
|
||||||
|
import { app_config } from 'config'
|
||||||
|
|
||||||
|
export function transitionToogle() {
|
||||||
|
window.LoginComponent.setState({
|
||||||
|
transition: !window.LoginComponent.state.transition,
|
||||||
|
})
|
||||||
|
window.LoginComponent.toogleYulioID()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Login extends React.PureComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
window.LoginComponent = this
|
||||||
|
this.state = {
|
||||||
|
transition: false,
|
||||||
|
using: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switchType = {
|
||||||
|
f: a => {
|
||||||
|
this.setState({ using: a })
|
||||||
|
},
|
||||||
|
login: () => {
|
||||||
|
this.switchType.f(1)
|
||||||
|
},
|
||||||
|
register: () => {
|
||||||
|
this.switchType.f(2)
|
||||||
|
},
|
||||||
|
forgot: () => {
|
||||||
|
this.switchType.f(3)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
renderType(t) {
|
||||||
|
const a = this.state.using
|
||||||
|
if (t) {
|
||||||
|
switch (a) {
|
||||||
|
case 1:
|
||||||
|
return `Sign in ${app_config.siteName}`
|
||||||
|
case 2:
|
||||||
|
return 'Register'
|
||||||
|
case 3:
|
||||||
|
return 'Forgot'
|
||||||
|
default:
|
||||||
|
return 'Auth'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (a) {
|
||||||
|
case 1:
|
||||||
|
return <NormalLoginForm />
|
||||||
|
case 2:
|
||||||
|
return <RegistrationForm />
|
||||||
|
case 3:
|
||||||
|
return null
|
||||||
|
default:
|
||||||
|
return <NormalLoginForm />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderHelperButtons = () => {
|
||||||
|
if (this.state.using == 1) {
|
||||||
|
return (
|
||||||
|
<div className={styles.login_helper_footer}>
|
||||||
|
<antd.Button type="link" onClick={() => this.switchType.forgot()}>
|
||||||
|
Forgotten password
|
||||||
|
</antd.Button>
|
||||||
|
<antd.Button type="link" onClick={() => this.switchType.register()}>
|
||||||
|
Create an account
|
||||||
|
</antd.Button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (this.state.using == 2 || 3) {
|
||||||
|
return (
|
||||||
|
<div className={styles.login_helper_footer}>
|
||||||
|
<antd.Button type="link" onClick={() => this.switchType.login()}>
|
||||||
|
Login
|
||||||
|
</antd.Button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classnames(styles.login_wrapper, {
|
||||||
|
[styles.goOut]: this.state.transition,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: '8px',
|
||||||
|
position: 'absolute',
|
||||||
|
top: '12px',
|
||||||
|
left: '12px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
⚠ Using v{app_info.version} {app_info.stage}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.login_wrapper}>
|
||||||
|
<div className={styles.auth_box}>
|
||||||
|
<div className={styles.left_body}>
|
||||||
|
<h6>
|
||||||
|
<img className={styles.yid_logo} src={'https://api.ragestudio.net/id.svg'} /> YulioID™
|
||||||
|
</h6>
|
||||||
|
<h2> {this.renderType(true)} </h2>
|
||||||
|
</div>
|
||||||
|
<div className={styles.right_body}>
|
||||||
|
{this.renderType()}
|
||||||
|
{this.renderHelperButtons()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default Login
|
234
src/pages/login/index.less
Normal file
234
src/pages/login/index.less
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
@import '~theme/index.less';
|
||||||
|
|
||||||
|
.login_wrapper{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
font-family: "Poppins", sans-serif!important;
|
||||||
|
h1,h2,h3,h4,h5,h6{color: #333;}
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 20px;
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
|
&.goOut{
|
||||||
|
.auth_box{
|
||||||
|
-webkit-animation-name: fadeOutLeft;
|
||||||
|
animation-name: fadeOutLeft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transition: all 300ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.auth_box{
|
||||||
|
display: flex;
|
||||||
|
transition: all 300ms ease-in-out;
|
||||||
|
|
||||||
|
.yid_logo {
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 17px;
|
||||||
|
}
|
||||||
|
:global{
|
||||||
|
input:-webkit-autofill,
|
||||||
|
input:-webkit-autofill:hover,
|
||||||
|
input:-webkit-autofill:focus,
|
||||||
|
textarea:-webkit-autofill,
|
||||||
|
textarea:-webkit-autofill:hover,
|
||||||
|
textarea:-webkit-autofill:focus,
|
||||||
|
select:-webkit-autofill,
|
||||||
|
select:-webkit-autofill:hover,
|
||||||
|
select:-webkit-autofill:focus {
|
||||||
|
border: 0;
|
||||||
|
-webkit-text-fill-color: #333;
|
||||||
|
-webkit-box-shadow: 0 0 0px 1000px #ffffff98 inset;
|
||||||
|
box-shadow: #fff 0px 0px 0px 1000px inset;
|
||||||
|
transition: background-color 5000s ease-in-out 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-input-affix-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
padding: 4px 11px;
|
||||||
|
color: #333;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5715;
|
||||||
|
background-color: #fff; //rgba(255, 255, 255, 0.596);
|
||||||
|
border: 1.5px #2F66DF solid;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.centering_wrapper{
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left_body{
|
||||||
|
z-index: 50;
|
||||||
|
transform: translate(12px,0);
|
||||||
|
float: left;
|
||||||
|
width: 30%;
|
||||||
|
color: #333;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 12px 0 0 12px;
|
||||||
|
box-shadow: 0px 10px 20px 0px rgba(51,51,51,0.52);
|
||||||
|
transition: all 300ms ease-in-out;
|
||||||
|
|
||||||
|
}
|
||||||
|
.right_body{
|
||||||
|
z-index: 51;
|
||||||
|
float: right;
|
||||||
|
width: 70%;
|
||||||
|
max-height: -webkit-fill-available;
|
||||||
|
height: 150px;
|
||||||
|
padding: 20px 50px 20px 50px;
|
||||||
|
color: #333;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0px 10px 20px 0px rgba(51,51,51,0.52);
|
||||||
|
transition: all 300ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.helper_login_btn{
|
||||||
|
transform: translate(-20px, -14px);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.login_helper_footer{
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
margin: auto;
|
||||||
|
:global{
|
||||||
|
.ant-btn{
|
||||||
|
margin: auto;
|
||||||
|
padding: 0 5px 0 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
transform: translate(0, -10px);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes go-out {
|
||||||
|
0% {
|
||||||
|
filter: blur(0px)
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
filter: blur(15px)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Full format
|
||||||
|
// @media (min-width: 486px){
|
||||||
|
// .login_wrapper {
|
||||||
|
// min-height: 580px;
|
||||||
|
// }
|
||||||
|
// .auth_box {
|
||||||
|
// width: 784px;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Medium format max-width: 830px
|
||||||
|
@media (min-width: 486px){
|
||||||
|
.auth_box {
|
||||||
|
padding: 0 16px 40px;
|
||||||
|
width: 500px;
|
||||||
|
min-height: 500px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.left_body{
|
||||||
|
width: 100%;
|
||||||
|
float: none;
|
||||||
|
border-radius: 12px 12px 0 0;
|
||||||
|
padding: 20px 20px 20px 20px;
|
||||||
|
transform: translate(0, 22px);
|
||||||
|
}
|
||||||
|
.right_body{
|
||||||
|
width: 100%;
|
||||||
|
float: none;
|
||||||
|
padding: 20px 60px 20px 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mobile format
|
||||||
|
@media (max-width: 485px){
|
||||||
|
.auth_box {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
padding: 70px 16px 40px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 500px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.left_body{
|
||||||
|
box-shadow: none;
|
||||||
|
width: 100%;
|
||||||
|
float: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
margin-top: 30px;
|
||||||
|
transform: translate(0, 0);
|
||||||
|
}
|
||||||
|
.right_body{
|
||||||
|
box-shadow: none;
|
||||||
|
width: 100%;
|
||||||
|
float: none;
|
||||||
|
padding: 20px 20px 20px 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.register_form{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes fadeOutLeft {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transform: translate3d(-100%, 0, 0);
|
||||||
|
transform: translate3d(-100%, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeOutLeft {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transform: translate3d(-100%, 0, 0);
|
||||||
|
transform: translate3d(-100%, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
277
src/pages/login/login.js
Normal file
277
src/pages/login/login.js
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import styles from './index.less'
|
||||||
|
|
||||||
|
import Fade from 'react-reveal/Fade'
|
||||||
|
import HeadShake from 'react-reveal/HeadShake';
|
||||||
|
|
||||||
|
import * as antd from 'antd'
|
||||||
|
|
||||||
|
import { session, user } from 'core/cores'
|
||||||
|
|
||||||
|
import verbosity from 'core/libs/verbosity'
|
||||||
|
|
||||||
|
import { Form, Input, Button, Checkbox } from 'antd'
|
||||||
|
import {
|
||||||
|
UserOutlined,
|
||||||
|
LockOutlined,
|
||||||
|
BulbOutlined,
|
||||||
|
SwapLeftOutlined
|
||||||
|
} from 'components/Icons'
|
||||||
|
import { connect } from 'umi'
|
||||||
|
|
||||||
|
@connect(({ app }) => ({ app }))
|
||||||
|
export class NormalLoginForm extends React.PureComponent {
|
||||||
|
state = {
|
||||||
|
activeForm: true,
|
||||||
|
step: 1,
|
||||||
|
validating: false,
|
||||||
|
error_count: 0,
|
||||||
|
step_error: false,
|
||||||
|
step_show: true,
|
||||||
|
swpass: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
next = values => {
|
||||||
|
let a = this.state.step
|
||||||
|
const b = btoa(Object.values(values).toString())
|
||||||
|
switch (a) {
|
||||||
|
case 1:
|
||||||
|
const payload = { username: Object.values(values).toString() }
|
||||||
|
user.get.profileData(payload, (err, res) => {
|
||||||
|
if (err || !res) return false
|
||||||
|
try {
|
||||||
|
const res_data = JSON.parse(res)
|
||||||
|
|
||||||
|
if (res_data.api_status == 200) {
|
||||||
|
a++
|
||||||
|
this.anim_transition(300)
|
||||||
|
this.setState({
|
||||||
|
step_error: false,
|
||||||
|
early_data: res_data.data,
|
||||||
|
form_rawd_1: b,
|
||||||
|
step: a,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (res_data.api_status == 400) {
|
||||||
|
this.anim_error()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return true
|
||||||
|
case 2:
|
||||||
|
this.setState({ form_rawd_2: b, step: a })
|
||||||
|
this.auth()
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
back() {
|
||||||
|
let a = this.state.step
|
||||||
|
if (a > 1) {
|
||||||
|
a--
|
||||||
|
this.anim_transition(150)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ step: a })
|
||||||
|
}
|
||||||
|
|
||||||
|
anim_transition(duration) {
|
||||||
|
this.setState({ step_show: false })
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setState({ step_show: true })
|
||||||
|
}, duration || 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
anim_error() {
|
||||||
|
this.setState({ step_error: true, error_count: (this.state.error_count + 1) })
|
||||||
|
}
|
||||||
|
|
||||||
|
anim_close() {
|
||||||
|
this.setState({ step_show: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getAuthFrame(payload) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
session.auth(payload, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
|
||||||
|
}
|
||||||
|
if (res) {
|
||||||
|
try {
|
||||||
|
res = JSON.parse(res)
|
||||||
|
verbosity.log(res)
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Invalid response!')
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (res.api_status.toString()) {
|
||||||
|
case "200": {
|
||||||
|
try {
|
||||||
|
return resolve(res)
|
||||||
|
} catch (error) {
|
||||||
|
verbosity.error(error)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "400": {
|
||||||
|
console.log('Credentials error')
|
||||||
|
this.setState({ validating: false })
|
||||||
|
return this.anim_error()
|
||||||
|
}
|
||||||
|
case "500": {
|
||||||
|
console.log('Server error')
|
||||||
|
this.setState({ validating: false })
|
||||||
|
return this.back()
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
console.log('Unknown error')
|
||||||
|
this.setState({ validating: false })
|
||||||
|
return this.back()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getDataFrame(payload) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
user.get.data(payload, (err, res) => {
|
||||||
|
if(err) {
|
||||||
|
|
||||||
|
}
|
||||||
|
if (res) {
|
||||||
|
try {
|
||||||
|
return resolve(JSON.stringify(JSON.parse(res)['user_data']))
|
||||||
|
} catch (error) {
|
||||||
|
verbosity.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async auth() {
|
||||||
|
const { form_rawd_1, form_rawd_2 } = this.state
|
||||||
|
if (!form_rawd_1 || !form_rawd_2) return false
|
||||||
|
this.setState({ step_error: false, validating: true })
|
||||||
|
|
||||||
|
const authFrame = await this.getAuthFrame({username: form_rawd_1, password: form_rawd_2, server_key: this.props.app.server_key})
|
||||||
|
const dataFrame = await this.getDataFrame({id: authFrame.user_id, access_token: authFrame.access_token, serverKey: this.props.app.server_key})
|
||||||
|
|
||||||
|
return this.props.dispatch({
|
||||||
|
type: 'app/login',
|
||||||
|
payload: {authFrame, dataFrame}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderState = () => {
|
||||||
|
switch (this.state.step) {
|
||||||
|
case 1:
|
||||||
|
return (
|
||||||
|
<Form
|
||||||
|
name="signin_username"
|
||||||
|
className="login-form"
|
||||||
|
onFinish={this.next}
|
||||||
|
>
|
||||||
|
<h5>
|
||||||
|
<BulbOutlined /> You can use your YulioID account to login
|
||||||
|
</h5>
|
||||||
|
<HeadShake spy={this.state.error_count}>
|
||||||
|
<Form.Item
|
||||||
|
name="username"
|
||||||
|
hasFeedback
|
||||||
|
help={this.state.step_error? "It seems that this user does not exist" : null}
|
||||||
|
validateStatus={this.state.step_error? 'error' : this.state.validating? 'validating' : null}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: 'Please use your Username or Email!',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
prefix={<UserOutlined className="site-form-item-icon" />}
|
||||||
|
placeholder="Username or Email"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</HeadShake>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
htmlType="submit"
|
||||||
|
className="login-form-button"
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</Button>
|
||||||
|
</Form>
|
||||||
|
)
|
||||||
|
case 2:
|
||||||
|
return (
|
||||||
|
<Form
|
||||||
|
name="signin_password"
|
||||||
|
className="login-form"
|
||||||
|
onFinish={this.next}
|
||||||
|
>
|
||||||
|
|
||||||
|
<h4><antd.Avatar shape='square' src={this.state.early_data.avatar} /> Welcome Back @{this.state.early_data.username}</h4>
|
||||||
|
<HeadShake spy={this.state.error_count}>
|
||||||
|
<Form.Item
|
||||||
|
name="password"
|
||||||
|
hasFeedback
|
||||||
|
help={this.state.step_error? "Incorrect password" : null}
|
||||||
|
validateStatus={this.state.step_error? 'error' : this.state.validating? 'validating' : null}
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: 'Please input your Password!' },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input.Password
|
||||||
|
prefix={<LockOutlined className="site-form-item-icon" />}
|
||||||
|
type={this.state.swpass ? 'text' : 'password'}
|
||||||
|
placeholder="Password"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</HeadShake>
|
||||||
|
<div className={styles.helper_login_btn}>
|
||||||
|
<antd.Button
|
||||||
|
icon={<SwapLeftOutlined />}
|
||||||
|
type="link"
|
||||||
|
onClick={() => this.back()}
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</antd.Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
htmlType="submit"
|
||||||
|
className="login-form-button"
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
)
|
||||||
|
case 3: {
|
||||||
|
return <h3>Wait a sec...</h3>
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className={styles.login_form}>
|
||||||
|
<Fade left opposite when={this.state.step_show}>
|
||||||
|
{this.state.activeForm? this.renderState() : <div><h4>Mmm, this is taking longer than it should...</h4></div>}
|
||||||
|
</Fade>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
162
src/pages/login/register.js
Normal file
162
src/pages/login/register.js
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import React, { useState } from 'react'
|
||||||
|
import {
|
||||||
|
MailOutlined,
|
||||||
|
TagOutlined,
|
||||||
|
LockOutlined,
|
||||||
|
} from '@ant-design/icons'
|
||||||
|
|
||||||
|
import styles from './index.less'
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Tooltip,
|
||||||
|
Cascader,
|
||||||
|
Select,
|
||||||
|
Row,
|
||||||
|
Col,
|
||||||
|
Checkbox,
|
||||||
|
Button,
|
||||||
|
AutoComplete,
|
||||||
|
} from 'antd'
|
||||||
|
import { QuestionCircleOutlined } from '@ant-design/icons'
|
||||||
|
import ReCAPTCHA from 'react-google-recaptcha'
|
||||||
|
import { g_recaptcha_key } from 'config'
|
||||||
|
|
||||||
|
function capchaOnChange(value) {
|
||||||
|
console.log('Captcha value:', value)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const RegistrationForm = () => {
|
||||||
|
|
||||||
|
const onFinish = values => {
|
||||||
|
console.log('Received values of form: ', values)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.centering_wrapper}>
|
||||||
|
<Form
|
||||||
|
|
||||||
|
name="register"
|
||||||
|
className={styles.register_form}
|
||||||
|
onFinish={onFinish}
|
||||||
|
scrollToFirstError
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
name="username"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: 'Please input your username!',
|
||||||
|
whitespace: true,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input prefix={<TagOutlined />}
|
||||||
|
placeholder="ramdomuser"/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="email"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
type: 'email',
|
||||||
|
message: 'The input is not valid E-mail!',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: 'Please input your E-mail!',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
prefix={<MailOutlined />}
|
||||||
|
placeholder="example@no-real.com"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="password"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: 'Please input your password!',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
hasFeedback
|
||||||
|
>
|
||||||
|
<Input.Password prefix={<LockOutlined />}
|
||||||
|
placeholder="example@no-real.com"/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="confirm"
|
||||||
|
dependencies={['password']}
|
||||||
|
hasFeedback
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: 'Please confirm your password!',
|
||||||
|
},
|
||||||
|
({ getFieldValue }) => ({
|
||||||
|
validator(rule, value) {
|
||||||
|
if (!value || getFieldValue('password') === value) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.reject(
|
||||||
|
'The two passwords that you entered do not match!'
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input.Password prefix={<LockOutlined />}
|
||||||
|
placeholder="example@no-real.com"/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item extra="We must make sure that your are a human.">
|
||||||
|
<Row gutter={8}>
|
||||||
|
<Col span={12}>
|
||||||
|
<Form.Item
|
||||||
|
name="captcha"
|
||||||
|
noStyle
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: 'Please complete the captcha!',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<ReCAPTCHA sitekey={g_recaptcha_key} onChange={capchaOnChange} />
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}></Col>
|
||||||
|
</Row>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="agreement"
|
||||||
|
valuePropName="checked"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
validator: (_, value) =>
|
||||||
|
value
|
||||||
|
? Promise.resolve()
|
||||||
|
: Promise.reject('Should accept agreement'),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Checkbox>
|
||||||
|
I have read the <a href="">agreement</a>
|
||||||
|
</Checkbox>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item >
|
||||||
|
<Button type="primary" htmlType="submit">
|
||||||
|
Register
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user