From bb8e09b3ce98aa6fa3cd821f2d5010d9e14b10e0 Mon Sep 17 00:00:00 2001 From: 1aerostorm Date: Mon, 16 Dec 2024 04:09:51 +0300 Subject: [PATCH] Private groups - Tabs instead of checkboxes --- .../elements/MarkNotificationRead.jsx | 34 +++-- src/components/modules/MessagesTopCenter.jsx | 2 +- .../modules/groups/GroupMembers.jsx | 141 ++++++++---------- .../modules/groups/GroupMembers.scss | 7 + src/components/modules/groups/MyGroups.jsx | 58 ++++--- src/components/modules/groups/MyGroups.scss | 3 + src/locales/en.json | 8 +- src/locales/ru-RU.json | 8 +- src/redux/UserReducer.js | 4 +- 9 files changed, 139 insertions(+), 126 deletions(-) diff --git a/src/components/elements/MarkNotificationRead.jsx b/src/components/elements/MarkNotificationRead.jsx index e75d6420..2987bc68 100644 --- a/src/components/elements/MarkNotificationRead.jsx +++ b/src/components/elements/MarkNotificationRead.jsx @@ -15,18 +15,21 @@ class MarkNotificationRead extends React.Component { }; shouldComponentUpdate(nextProps) { - if (this.props.interval !== nextProps.interval) { + if (this.props.interval !== nextProps.interval || + this.props.fields !== nextProps.fields) { return true } return false; } + _markIt = () => { + const { account, update } = this.props + markNotificationRead(account, this.fields_array).then(nc => update(nc)) + } + _activateInterval = (interval) => { if (!this.interval) { - const { account, update } = this.props; - this.interval = setInterval(() => { - markNotificationRead(account, this.fields_array).then(nc => update(nc)); - }, interval); + this.interval = setInterval(this._markIt, interval) } } @@ -38,23 +41,26 @@ class MarkNotificationRead extends React.Component { } componentDidMount() { - const { account, fields, update, interval, delay } = this.props; - this.fields_array = fields.replace(/\s/g,'').split(','); - const firstMark = () => { - markNotificationRead(account, this.fields_array).then(nc => update(nc)) - } + const { fields, interval, delay } = this.props; + this.fields_array = fields.replace(/\s/g,'').split(',') if (delay) { - setTimeout(firstMark, delay) + setTimeout(this._markIt, delay) } if (interval) { this._activateInterval(interval); } else if (!delay) { - firstMark() + this._markIt() } } - componentDidUpdate() { - const { interval } = this.props + componentDidUpdate(prevProps) { + const { interval, delay, fields } = this.props + if (prevProps.fields !== fields) { + this.fields_array = fields.replace(/\s/g,'').split(',') + if (delay) { + setTimeout(this._markIt, delay) + } + } if (interval) { this._activateInterval(interval); } else { diff --git a/src/components/modules/MessagesTopCenter.jsx b/src/components/modules/MessagesTopCenter.jsx index 23201bd2..7a884fc9 100644 --- a/src/components/modules/MessagesTopCenter.jsx +++ b/src/components/modules/MessagesTopCenter.jsx @@ -132,7 +132,7 @@ class MessagesTopCenter extends React.Component { btnType = 'join' } else if (isModer) { myStatus = tt('msgs_group_dropdown.moder') - btnType = 'retire' + //btnType = 'retire' } else if (isMember) { btnType = 'retire' } else if (member_type === 'banned') { diff --git a/src/components/modules/groups/GroupMembers.jsx b/src/components/modules/groups/GroupMembers.jsx index 18e45034..1db996df 100644 --- a/src/components/modules/groups/GroupMembers.jsx +++ b/src/components/modules/groups/GroupMembers.jsx @@ -23,8 +23,7 @@ class GroupMembers extends React.Component { constructor(props) { super(props) this.state = { - showModers: false, - showPendings: !!props.showPendings, + currentTab: props.current_tab || 'member', } } @@ -47,28 +46,25 @@ class GroupMembers extends React.Component { init = (force = false) => { const { initialized } = this.state if (!initialized || force) { - const { currentGroup } = this.props + const { currentGroup, username } = this.props if (currentGroup) { const group = currentGroup - const memberTypes = ['moder'] + let { amModer } = getRoleInGroup(group, username) + + const memberTypes = [] const sortConditions = [] - const { showPendings, showBanneds, showModers } = this.state - if (!showModers) memberTypes.push('member') - if (showPendings) { - memberTypes.push('pending') - sortConditions.push({ - member_type: 'pending', - direction: 'up' - }) - } - if (showBanneds) { - memberTypes.push('banned') - sortConditions.push({ - member_type: 'banned', - direction: 'up' - }) + const { currentTab } = this.state + if (!amModer && currentTab === 'member') { + memberTypes.push('moder') + memberTypes.push('member') + } else if (currentTab) { + memberTypes.push(currentTab) } + // sortConditions.push({ + // member_type: 'banned', + // direction: 'up' + // }) this.props.fetchGroupMembers(group, memberTypes, sortConditions) this.setState({ @@ -78,37 +74,12 @@ class GroupMembers extends React.Component { } } - toggleModers = (e) => { - this.setState({ - showModers: !this.state.showModers - }, () => { - this.init(true) - }) - } - - togglePendings = (e) => { - const { checked } = e.target - this.setState({ - showPendings: checked - }, () => { - this.init(true) - }) - } - - toggleBanneds = (e) => { - const { checked } = e.target - this.setState({ - showBanneds: checked - }, () => { - this.init(true) - }) - } - onAddAccount = (e) => { try { const { value } = e.target const member = value - const member_type = 'member' + const { currentTab } = this.state + const member_type = currentTab const { username, currentGroup } = this.props const { creatingNew } = currentGroup @@ -133,20 +104,39 @@ class GroupMembers extends React.Component { } } - _renderMemberTypeSwitch = () => { + _renderMemberTypeSwitch = (amModer, ownerRight) => { const { currentGroup, } = this.props const { moders, members, } = currentGroup - const { showModers } = this.state - const disabled = !moders - return -
- {tt('group_members_jsx.all') + ' (' + (moders + members) + ')'} -
- -
- {tt('group_members_jsx.moders') + ' (' + moders + ')'} -
-
+ const { currentTab } = this.state + const disabled = !amModer && !moders + let tabs = [] + + let memTypes = ['member', 'moder'] + if (amModer) { + memTypes.unshift('pending') + memTypes.push('banned') + } + for (const key of memTypes) { + let title + if (!amModer && key === 'member') { + title = tt('group_members_jsx.all') + ' (' + (moders + members) + ')' + } else { + title = tt('group_members_jsx.' + key + 's') + ' (' + (currentGroup[key + 's']) + ')' + } + tabs.push(
{ + this.setState({ + currentTab: key + }, () => { + this.init(true) + }) + } : undefined}> + {title} +
) + } + return
+ {tabs} + {ownerRight} +
} render() { @@ -189,6 +179,7 @@ class GroupMembers extends React.Component { />) } + const isEmpty = !mems.length mems = {mems} @@ -201,6 +192,8 @@ class GroupMembers extends React.Component { filterAccs.add(m.account) } + const { currentTab } = this.state + mems =
{amModer ?
@@ -211,12 +204,14 @@ class GroupMembers extends React.Component { onAccountsLoad={(accs) => { this.props.receiveAccounts(accs) }} + isDisabled={currentTab === 'pending'} />
: null}
- {mems} + {!isEmpty ? mems :
+ {tt('group_members_jsx.empty')}
}
@@ -237,8 +232,6 @@ class GroupMembers extends React.Component { title = tt('group_members_jsx.title') + title + tt('group_members_jsx.title2') - const { showPendings, showBanneds } = this.state - let ownerRight, ownerRow let ownerBlock = {tt('group_settings_jsx.owner') + ' - '} @@ -264,25 +257,11 @@ class GroupMembers extends React.Component { {ownerRow} - {amModer ?
+
- - - - {ownerRight} + {this._renderMemberTypeSwitch(amModer, ownerRight)}
-
:
-
- {this._renderMemberTypeSwitch()} - {ownerRight} -
-
} +
} @@ -300,14 +279,14 @@ export default connect( const username = currentUser && currentUser.get('username') const { newGroup } = ownProps - let currentGroup, showPendings + let currentGroup, current_tab if (newGroup) { currentGroup = newGroup } else { const options = state.user.get('group_members_modal') if (options) { currentGroup = options.get('group') - showPendings = options.get('show_pendings') + current_tab = options.get('current_tab') } if (currentGroup) { const [ path, name ] = currentGroup @@ -325,7 +304,7 @@ export default connect( username, currentGroup, group, - showPendings, + current_tab, } }, dispatch => ({ diff --git a/src/components/modules/groups/GroupMembers.scss b/src/components/modules/groups/GroupMembers.scss index 4f81660e..474b43c0 100644 --- a/src/components/modules/groups/GroupMembers.scss +++ b/src/components/modules/groups/GroupMembers.scss @@ -1,4 +1,7 @@ .GroupMembers { + h4 { + margin-bottom: 1rem; + } .member-name { margin-left: 0.5rem; line-height: 40px; @@ -7,9 +10,13 @@ @include themify($themes) { .label { padding: 0.5rem; + transition: all .1s ease-in; user-select: none; + margin-right: 0.5rem; + margin-bottom: 0.5rem; + &:not(.disabled) { cursor: pointer; } diff --git a/src/components/modules/groups/MyGroups.jsx b/src/components/modules/groups/MyGroups.jsx index 6b69b1f0..7590e523 100644 --- a/src/components/modules/groups/MyGroups.jsx +++ b/src/components/modules/groups/MyGroups.jsx @@ -117,10 +117,10 @@ class MyGroups extends React.Component { this.props.showGroupSettings({ group }) } - showGroupMembers = (e, group, show_pendings) => { + showGroupMembers = (e, group, current_tab) => { e.preventDefault() const { name } = group - this.props.showGroupMembers({ group: name, show_pendings }) + this.props.showGroupMembers({ group: name, current_tab }) } onGoGroup = (e) => { @@ -155,13 +155,12 @@ class MyGroups extends React.Component { this.deleteGroup(e, group, titleShr) }, value: tt('g.delete') }) } - if (amMember || (amModer && !amOwner)) { + if (amMember/* || (amModer && !amOwner)*/) { kebabItems.push({ link: '#', onClick: e => { this.retireCancel(e, group, titleShr, amPending) }, value: tt('msgs_group_dropdown.retire') }) } - const noMembers = !pendings && !members && !moders return
@@ -184,7 +183,7 @@ class MyGroups extends React.Component { {amPending ? tt('msgs_group_dropdown.cancel') : tt('msgs_group_dropdown.retire')} : null} {(amModer && pendings) ? : null} @@ -215,21 +214,25 @@ class MyGroups extends React.Component { } - _renderGroupTypeSwitch = () => { + _renderTabs = () => { const { stat, } = this.props let { currentTab } = this.state currentTab = currentTab || stat.current + let markRead = [] let tabs = [] for (const key of ['pending', 'member', 'moder', 'own']) { - if (!stat[key]) continue - let counter + let counter = [] if (key === 'member') { - counter = 'group_member_mem' + counter = ['group_member_mem'] } else if (key === 'moder') { - counter = 'join_request_mod,group_member_mod' + counter = ['join_request_mod', 'group_member_mod'] } else if (key === 'own') { - counter = 'join_request_own' + counter = ['join_request_own'] + } + if (currentTab === key || !stat[key]) { + markRead.push(counter) } + if (!stat[key]) continue tabs.push(
{ this.setState({ @@ -239,27 +242,36 @@ class MyGroups extends React.Component { {tt('my_groups_jsx.tab_' + key) + ' (' + stat[key] + ')'} - {counter && } + {counter.length ? : null}
) } - if (tabs.length < 1) return null - return
+ if (tabs.length < 1) return { markRead, tabs: null } + tabs =
{tabs}
+ return { markRead, tabs } } render() { let groups, hasGroups - let { my_groups } = this.props + let { my_groups, username } = this.props if (!my_groups) { groups = } else { my_groups = my_groups.toJS() + let { tabs, markRead } = this._renderTabs() + + const reader = (username && markRead.length) ? + : null + if (!my_groups.length) { groups =
+ {tabs} + {reader} {tt('my_groups_jsx.empty')} {tt('my_groups_jsx.empty2')} @@ -284,8 +296,10 @@ class MyGroups extends React.Component { if (currentTab && g.my_role !== currentTab) continue groups.push(this._renderGroup(g)) } + groups = - {this._renderGroupTypeSwitch()} + {tabs} + {reader}
{groups} @@ -309,8 +323,6 @@ class MyGroups extends React.Component { } - const { username } = this.props - return

{tt('my_groups_jsx.title')}

@@ -318,8 +330,6 @@ class MyGroups extends React.Component { {button} {groups} {hasGroups ?
: null} - {username ? : null}
} } @@ -353,8 +363,8 @@ export default connect( showGroupSettings({ group }) { dispatch(user.actions.showGroupSettings({ group })) }, - showGroupMembers({ group, show_pendings }) { - dispatch(user.actions.showGroupMembers({ group: ['my_groups', group], show_pendings })) + showGroupMembers({ group, current_tab }) { + dispatch(user.actions.showGroupMembers({ group: ['my_groups', group], current_tab })) }, deleteGroup: ({ owner, name, password, onSuccess, onError }) => { diff --git a/src/components/modules/groups/MyGroups.scss b/src/components/modules/groups/MyGroups.scss index 5b12e572..f4bb37fb 100644 --- a/src/components/modules/groups/MyGroups.scss +++ b/src/components/modules/groups/MyGroups.scss @@ -1,4 +1,7 @@ .MyGroups { + h3 { + margin-bottom: 0.75rem; + } .group-logo { width: 67px; img { diff --git a/src/locales/en.json b/src/locales/en.json index 497da822..b1c1c96c 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -181,7 +181,7 @@ "members_list": "Members:", "image_wrong": "Cannot load this image.", "image_timeout": "Cannot load this image, it is loading too long...", - "add_member": "+ Add Member...", + "add_member": "+ Add Account...", "add_member2": "+ Add..." }, "my_groups_jsx": { @@ -223,7 +223,10 @@ "check_pending_hint": "Pending Group Join Requests", "check_banned": "Blocked", "all": "All", + "pendings": "Pendings", "moders": "Moderators", + "members": "Members", + "banneds": "Ban", "member": "Member", "moder": "Moderator", "owner": "Group Owner", @@ -231,7 +234,8 @@ "make_moder": "Make Moderator", "ban": "Ban", "unban": "Unban", - "banned": "Banned" + "banned": "Banned", + "empty": "No such yet..." }, "group_settings_jsx": { "title_GROUP": "%(GROUP)s Group", diff --git a/src/locales/ru-RU.json b/src/locales/ru-RU.json index 2c9cd944..fed77b4c 100644 --- a/src/locales/ru-RU.json +++ b/src/locales/ru-RU.json @@ -188,7 +188,7 @@ "members_list": "Участники:", "image_wrong": "Не удается загрузить картинку.", "image_timeout": "Не удается загрузить картинку, она загружается слишком долго...", - "add_member": "+ Добавить участника...", + "add_member": "+ Добавить аккаунт...", "add_member2": "+ Добавить...", "cannot_set_members": "Группа создана успешно. Но, к сожалению, не получилось задать участников из-за ошибки.", "cannot_set_members2": "Вы можете попытаться сделать это заново в настройках группы." @@ -232,7 +232,10 @@ "check_pending_hint": "Заявки на вступление в группу", "check_banned": "Забаненные", "all": "Все", + "pendings": "Заявки", "moders": "Модераторы", + "members": "Участники", + "banneds": "Бан", "member": "Обычный участник", "moder": "Модератор", "owner": "Владелец группы", @@ -240,7 +243,8 @@ "make_moder": "Сделать модератором", "ban": "Заблокировать", "unban": "Разблокировать", - "banned": "Заблокирован(-а)" + "banned": "Заблокирован(-а)", + "empty": "Таких пока нет..." }, "group_settings_jsx": { "title_GROUP": "Группа %(GROUP)s", diff --git a/src/redux/UserReducer.js b/src/redux/UserReducer.js index 691307dd..0421d8c0 100644 --- a/src/redux/UserReducer.js +++ b/src/redux/UserReducer.js @@ -149,11 +149,11 @@ export default createModule({ return state }}, { action: 'HIDE_GROUP_SETTINGS', reducer: state => state.set('show_group_settings_modal', false) }, - { action: 'SHOW_GROUP_MEMBERS', reducer: (state, { payload: { group, show_pendings }}) => { + { action: 'SHOW_GROUP_MEMBERS', reducer: (state, { payload: { group, current_tab }}) => { state = state.set('show_group_members_modal', true) state = state.set('group_members_modal', fromJS({ group, - show_pendings, + current_tab, })) return state }},