Skip to content

Commit

Permalink
HF 30 - Private message groups
Browse files Browse the repository at this point in the history
  • Loading branch information
1aerostorm committed Jun 13, 2024
1 parent d23818e commit 6d9fada
Show file tree
Hide file tree
Showing 15 changed files with 361 additions and 63 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"connected-react-router": "^6.9.2",
"counterpart": "^0.18.6",
"emoji-picker-element": "^1.10.1",
"formik": "https://gitpkg.now.sh/golos-blockchain/formik/packages/formik?b697b6ef3f13c795bb862b35589fffde442ab465",
"formik": "https://gitpkg.now.sh/golos-blockchain/formik/packages/formik?3b21166c33ade760d562091e1fa0b71d172a7aaf",
"git-rev-sync": "^3.0.2",
"golos-lib-js": "^0.9.69",
"history": "4.10.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.msgs-start-panel {
.button {
display: block;
width: 100%;
}
}
4 changes: 4 additions & 0 deletions src/components/elements/messages/Stepper/Stepper.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
.bar {
background-color: #0078C4;
}
cursor: pointer;
&:hover {
color: #0078C4;
}
}
&.current {
color: #0078C4;
Expand Down
24 changes: 20 additions & 4 deletions src/components/elements/messages/Stepper/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,25 @@ class Stepper extends React.Component {
}
}

_goToStep = (step) => { // TODO: private, if make public - check step exists
this.setState({
currentStep: step
}, () => {
const { onStep } = this.props
if (onStep) {
onStep({ step })
}
})
}

nextStep = () => {
const { steps } = this.props
const entr = Object.entries(steps)
const { currentStep } = this.state
let found
for (const [key, content] of entr) {
if (found) {
this.setState({
currentStep: key
})
this._goToStep(key)
return key
}
found = key === currentStep
Expand All @@ -42,7 +51,14 @@ class Stepper extends React.Component {
const isCurrent = key === currentStep
foundCurrent = foundCurrent || isCurrent
const cn = foundCurrent ? (isCurrent ? 'current' : '') : 'left'
stepObjs.push(<div className={'step ' + cn} style={{ minWidth: width + '%' }}>
let onClick
if (!foundCurrent) {
onClick = (e) => {
e.preventDefault()
this._goToStep(key)
}
}
stepObjs.push(<div className={'step ' + cn} style={{ minWidth: width + '%' }} onClick={onClick}>
<div className={'bar'}></div>
{content}
</div>)
Expand Down
43 changes: 33 additions & 10 deletions src/components/modules/CreateGroup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,32 @@ import LoadingIndicator from 'app/components/elements/LoadingIndicator'
import FormikAgent from 'app/components/elements/donate/FormikUtils'
import Stepper from 'app/components/elements/messages/Stepper'
import GroupName, { validateNameStep } from 'app/components/modules/groups/GroupName'
import GroupLogo from 'app/components/modules/groups/GroupLogo'
import GroupLogo, { validateLogoStep } from 'app/components/modules/groups/GroupLogo'
import GroupAdmin, { validateAdminStep } from 'app/components/modules/groups/GroupAdmin'
import GroupFinal from 'app/components/modules/groups/GroupFinal'

const STEPS = () => { return {
name: tt('create_group_jsx.step_name'),
logo: tt('create_group_jsx.step_logo'),
admin: tt('create_group_jsx.step_admin'),
create: tt('create_group_jsx.step_create')
final: tt('create_group_jsx.step_create')
} }

class CreateGroup extends React.Component {
constructor(props) {
super(props)
this.state = {
step: 'name',
validators: 0,
initialValues: {
title: '',
name: '',
is_encrypted: true,
privacy: 'public_group',

logo: '',

admin: '',
}
}
this.stepperRef = React.createRef()
Expand Down Expand Up @@ -81,12 +86,24 @@ class CreateGroup extends React.Component {
}
}

setValidating = (validating) => {
this.setState({
validators: this.state.validators + (validating ? 1 : -1),
})
}

validate = async (values) => {
const errors = {}
const { step } = this.state
this.setValidating(true)
if (step === 'name') {
await validateNameStep(values, errors, (validating) => this.setState({ validating }))
await validateNameStep(values, errors)
} else if (step === 'logo') {
await validateLogoStep(values, errors)
} else if (step === 'admin') {
await validateAdminStep(values, errors)
}
this.setValidating(false)
return errors
}

Expand All @@ -96,13 +113,16 @@ class CreateGroup extends React.Component {
goNext = (e, setFieldValue) => {
e.preventDefault()
const step = this.stepperRef.current.nextStep()
}

onStep = ({ step }) => {
this.setState({
step
})
}

render() {
const { step, loaded, createError, validating } = this.state
const { step, loaded, createError, validators } = this.state

let form
if (!loaded) {
Expand Down Expand Up @@ -134,20 +154,23 @@ class CreateGroup extends React.Component {
onSubmit={this._onSubmit}
>
{({
handleSubmit, isSubmitting, isValid, values, setFieldValue, setFieldTouched, handleChange,
handleSubmit, isSubmitting, isValid, values, errors, setFieldValue, applyFieldValue, setFieldTouched, handleChange,
}) => {
const disabled = !isValid || validating
const disabled = !isValid || !!validators
return (
<Form>

{step === 'name' ? <GroupName values={values} setFieldValue={setFieldValue} setFieldTouched={setFieldTouched} /> :
step === 'logo' ? <GroupLogo values={values} setFieldValue={setFieldValue} setFieldTouched={setFieldTouched} /> :
{step === 'name' ? <GroupName values={values} applyFieldValue={applyFieldValue} /> :
step === 'logo' ? <GroupLogo isValidating={!!validators} values={values} errors={errors} applyFieldValue={applyFieldValue} /> :
step === 'admin' ? <GroupAdmin values={values} applyFieldValue={applyFieldValue} /> :
step === 'final' ? <GroupFinal /> :
<React.Fragment></React.Fragment>}

<Stepper ref={this.stepperRef} steps={STEPS()} startStep='name' />
<Stepper ref={this.stepperRef} steps={STEPS()} startStep='name'
onStep={this.onStep} />
{isSubmitting ? <span><LoadingIndicator type='circle' /><br /></span>
: <span>
<button onClick={this.goNext} disabled={disabled} className='button small next-button' title={validating ?
<button onClick={this.goNext} disabled={disabled} className='button small next-button' title={validators ?
tt('create_group_jsx.validating') : tt('create_group_jsx.submit')}>
<Icon name='chevron-right' size='1_25x' />
</button>
Expand Down
12 changes: 12 additions & 0 deletions src/components/modules/CreateGroup.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,17 @@
}
.error {
margin-bottom: 0px !important;
margin-top: 0.5rem;
}

.image-loader {
margin-top: 14px;
}

.image-preview {
max-width: 75px;
max-height: 75px;
margin-top: 0.75rem;
border: none;
}
}
8 changes: 6 additions & 2 deletions src/components/modules/Modals.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ class Modals extends React.Component {
onLoginBackdropClick = (e) => {
const { loginUnclosable } = this.props;
if (loginUnclosable)
throw new Error('Closing login modal is forbidden here');
this.onUnclosableClick(e)
};

onUnclosableClick = (e) => {
throw new Error('Closing modal is forbidden here')
}

render() {
const {
show_login_modal,
Expand Down Expand Up @@ -64,7 +68,7 @@ class Modals extends React.Component {
<CloseButton onClick={hideDonate} />
<Donate />
</Reveal>}
{show_create_group_modal && <Reveal revealStyle={{ overflow: 'hidden' }} onHide={hideCreateGroup} show={show_create_group_modal}>
{show_create_group_modal && <Reveal onBackdropClick={this.onUnclosableClick} revealStyle={{ overflow: 'hidden' }} onHide={hideCreateGroup} show={show_create_group_modal}>
<CloseButton onClick={hideCreateGroup} />
<CreateGroup />
</Reveal>}
Expand Down
104 changes: 104 additions & 0 deletions src/components/modules/groups/GroupAdmin.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React from 'react'
import { connect } from 'react-redux'
import { Field, ErrorMessage, } from 'formik'
import tt from 'counterpart'
import { api } from 'golos-lib-js'
import { validateAccountName } from 'golos-lib-js/lib/utils'

import Input from 'app/components/elements/common/Input';

export async function validateAdminStep(values, errors) {
if (!values.admin) {
errors.admin = tt('g.required')
} else {
const nameError = validateAccountName(values.admin)
if (nameError.error) {
errors.admin = tt('account_name.' + nameError.error)
} else {
try {
let accs = await api.getAccountsAsync([values.admin])
accs = accs[0]
if (!accs) {
errors.admin = tt('g.username_does_not_exist')
}
} catch (err) {
console.error(err)
errors.admin = 'Blockchain unavailable :('
}
}
}
}

class GroupAdmin extends React.Component {
state = {}

constructor(props) {
super(props)
}

componentDidMount() {
this.load()
}

componentDidUpdate() {
this.load()
}

load = () => {
const { loaded } = this.state
if (!loaded) {
const { username, applyFieldValue } = this.props
if (username) {
applyFieldValue('admin', username)
this.setState({
loaded: true
})
}
}
}

onChange = async (e) => {
e.preventDefault()
const { applyFieldValue } = this.props
applyFieldValue('admin', e.target.value)
}

render() {
const { uploading } = this.state

return <React.Fragment>
<div className='row' style={{ marginTop: '0rem' }}>
<div className='column small-12' style={{paddingTop: 5, fontSize: '110%'}}>
{tt('create_group_jsx.admin_desc')}
</div>
</div>
<div className='row' style={{ marginTop: '0.5rem', marginBottom: '2rem' }}>
<div className='column small-12'>
<Field name='admin'
block
as={Input}
autoFocus
className='AddImageDialog__link-input'
onChange={e => this.onChange(e)}
>
</Field>
<ErrorMessage name='admin' component='div' className='error' />
</div>
</div>
</React.Fragment>
}
}

export default connect(
// mapStateToProps
(state, ownProps) => {
const currentUser = state.user.get('current')
const username = currentUser && currentUser.get('username')
return {
...ownProps,
username,
}
},
dispatch => ({
})
)(GroupAdmin)
30 changes: 30 additions & 0 deletions src/components/modules/groups/GroupFinal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react'
import { connect } from 'react-redux'
import { Field, ErrorMessage, } from 'formik'
import tt from 'counterpart'

class GroupFinal extends React.Component {
state = {}

constructor(props) {
super(props)
}

render() {
return <React.Fragment>
<div className='row' style={{ marginTop: '0rem', marginBottom: '2rem' }}>
<div className='column small-12' style={{paddingTop: 5, fontSize: '110%'}}>
{tt('create_group_jsx.final_desc')}
</div>
</div>
</React.Fragment>
}
}

export default connect(
// mapStateToProps
(state, ownProps) => {
},
dispatch => ({
})
)(GroupFinal)
Loading

0 comments on commit 6d9fada

Please sign in to comment.