mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-26 23:50:52 +01:00
GroupMembers updates
This commit is contained in:
parent
8b6f08b989
commit
3cd6d56b3e
@ -1,6 +1,7 @@
|
||||
import { CreateLinkEvent } from '..';
|
||||
|
||||
export function GetGroupMembers(groupId: number): void
|
||||
export function GetGroupMembers(groupId: number, levelId?: number): void
|
||||
{
|
||||
CreateLinkEvent(`groups/members/${groupId}`);
|
||||
if(!levelId) CreateLinkEvent(`groups/members/${groupId}`);
|
||||
else CreateLinkEvent(`groups/members/${groupId}/${levelId}`);
|
||||
}
|
||||
|
@ -2,4 +2,5 @@ export * from './core';
|
||||
export * from './groups';
|
||||
export * from './navigator';
|
||||
export * from './nitro';
|
||||
export * from './user';
|
||||
export * from './utils';
|
||||
|
7
src/api/user/GetUserProfile.ts
Normal file
7
src/api/user/GetUserProfile.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { UserProfileComposer } from '@nitrots/nitro-renderer';
|
||||
import { SendMessageHook } from '../../hooks';
|
||||
|
||||
export function GetUserProfile(userId: number): void
|
||||
{
|
||||
SendMessageHook(new UserProfileComposer(userId));
|
||||
}
|
1
src/api/user/index.ts
Normal file
1
src/api/user/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './GetUserProfile';
|
BIN
src/assets/images/groups/icons/group_icon_accept_member.png
Normal file
BIN
src/assets/images/groups/icons/group_icon_accept_member.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 B |
Binary file not shown.
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 173 B |
@ -621,6 +621,12 @@
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
&.icon-group-accept-member {
|
||||
background: url('../images/groups/icons/group_icon_accept_member.png');
|
||||
width: 13px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
&.icon-group-small-owner {
|
||||
background: url('../images/groups/icons/group_icon_small_owner.png');
|
||||
width: 13px;
|
||||
|
@ -114,8 +114,8 @@ export const GroupsMessageHandler: FC<{}> = props =>
|
||||
parser.badgeParts.forEach((part, id) =>
|
||||
{
|
||||
groupBadgeParts.push(new GroupBadgePart(
|
||||
part.isBase ? GroupBadgePart.BASE : part.key >= 100 ? GroupBadgePart.SYMBOL_ALT : GroupBadgePart.SYMBOL,
|
||||
part.key >= 100 ? part.key - 100 : part.key,
|
||||
part.isBase ? GroupBadgePart.BASE : GroupBadgePart.SYMBOL,
|
||||
part.key,
|
||||
part.color,
|
||||
part.position
|
||||
));
|
||||
|
@ -2,7 +2,6 @@ export class GroupBadgePart
|
||||
{
|
||||
public static BASE: string = 'b';
|
||||
public static SYMBOL: string = 's';
|
||||
public static SYMBOL_ALT: string = 't';
|
||||
|
||||
public type: string;
|
||||
public key: number;
|
||||
@ -26,6 +25,6 @@ export class GroupBadgePart
|
||||
|
||||
public static getCode(type: string, key: number, color: number, position: number): string
|
||||
{
|
||||
return (type === GroupBadgePart.BASE ? type : key >= 100 ? GroupBadgePart.SYMBOL_ALT : GroupBadgePart.SYMBOL) + (key < 10 ? '0' : '') + (type === GroupBadgePart.BASE ? key : key >= 100 ? key - 100 : key) + (color < 10 ? '0' : '') + color + position;
|
||||
return type + (key < 10 ? '0' : '') + key + (color < 10 ? '0' : '') + color + position;
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,11 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
|
||||
|
||||
const leaveGroup = useCallback(() =>
|
||||
{
|
||||
SendMessageHook(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));
|
||||
if(onClose) onClose();
|
||||
if(window.confirm(LocalizeText('group.leaveconfirm.desc')))
|
||||
{
|
||||
SendMessageHook(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));
|
||||
if(onClose) onClose();
|
||||
}
|
||||
}, [ groupInformation, onClose ]);
|
||||
|
||||
const isRealOwner = useCallback(() =>
|
||||
@ -80,6 +83,9 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
|
||||
case 'members':
|
||||
GetGroupMembers(groupInformation.id);
|
||||
break;
|
||||
case 'members_pending':
|
||||
GetGroupMembers(groupInformation.id, 2);
|
||||
break;
|
||||
case 'manage':
|
||||
GetGroupManager(groupInformation.id);
|
||||
break;
|
||||
@ -104,8 +110,8 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
|
||||
<div className="mt-3 cursor-pointer" onClick={ () => handleAction('members') }>
|
||||
{ LocalizeText('group.membercount', ['totalMembers'], [groupInformation.membersCount.toString()]) }
|
||||
</div>
|
||||
{ groupInformation.pendingRequestsCount > 0 && <div className="cursor-pointer">
|
||||
{ LocalizeText('group.pendingmembercount', ['totalMembers'], [groupInformation.pendingRequestsCount.toString()]) }
|
||||
{ groupInformation.pendingRequestsCount > 0 && <div className="cursor-pointer" onClick={ () => handleAction('members_pending') }>
|
||||
{ LocalizeText('group.pendingmembercount', ['amount'], [groupInformation.pendingRequestsCount.toString()]) }
|
||||
</div> }
|
||||
{ groupInformation.isOwner && <div className="cursor-pointer" onClick={ () => handleAction('manage') }>
|
||||
{ LocalizeText('group.manage') }
|
||||
|
@ -16,12 +16,12 @@
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
height: 50px;
|
||||
|
||||
.avatar-image {
|
||||
position: absolute;
|
||||
left: -25px;
|
||||
top: -25px;
|
||||
top: -20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { GroupMemberParser, GroupMembersComposer, GroupMembersEvent, GroupMembersParser, GroupRank } from '@nitrots/nitro-renderer';
|
||||
import { GroupAdminGiveComposer, GroupAdminTakeComposer, GroupConfirmMemberRemoveEvent, GroupConfirmRemoveMemberComposer, GroupMemberParser, GroupMembersComposer, GroupMembersEvent, GroupMembershipAcceptComposer, GroupMembershipDeclineComposer, GroupMembersParser, GroupRank, GroupRemoveMemberComposer } from '@nitrots/nitro-renderer';
|
||||
import classNames from 'classnames';
|
||||
import { FC, KeyboardEvent, useCallback, useEffect, useState } from 'react';
|
||||
import { GetSessionDataManager, LocalizeText } from '../../../../api';
|
||||
import { GetSessionDataManager, GetUserProfile, LocalizeText } from '../../../../api';
|
||||
import { CreateMessageHook, SendMessageHook } from '../../../../hooks';
|
||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
|
||||
import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView';
|
||||
@ -16,23 +16,40 @@ export const GroupMembersView: FC<GroupMembersViewProps> = props =>
|
||||
const [ searchQuery, setSearchQuery ] = useState<string>('');
|
||||
const [ searchLevelId, setSearchLevelId ] = useState<number>(3);
|
||||
const [ totalPages, setTotalPages ] = useState<number>(0);
|
||||
const [ removingMemberName, setRemovingMemberName ] = useState<string>(null);
|
||||
|
||||
const searchMembers = useCallback((pageId: number) =>
|
||||
const searchMembers = useCallback((pageId: number, newLevelId?: number) =>
|
||||
{
|
||||
if(!groupId) return;
|
||||
|
||||
SendMessageHook(new GroupMembersComposer(groupId, pageId, searchQuery, searchLevelId));
|
||||
SendMessageHook(new GroupMembersComposer(groupId, pageId, searchQuery, newLevelId !== null ? newLevelId : searchLevelId));
|
||||
}, [ groupId, searchQuery, searchLevelId ]);
|
||||
|
||||
const onGroupMembersEvent = useCallback((event: GroupMembersEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
setPageData(null);
|
||||
setPageData(parser);
|
||||
setSearchLevelId(parser.level);
|
||||
setTotalPages(Math.ceil(parser.totalMembersCount / parser.pageSize));
|
||||
}, []);
|
||||
|
||||
const onGroupConfirmMemberRemoveEvent = useCallback((event: GroupConfirmMemberRemoveEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
if(window.confirm(LocalizeText(parser.furnitureCount > 0 ? 'group.kickconfirm.desc' : 'group.kickconfirm_nofurni.desc', ['user', 'amount'], [removingMemberName, parser.furnitureCount.toString()])))
|
||||
{
|
||||
SendMessageHook(new GroupRemoveMemberComposer(pageData.groupId, parser.userId));
|
||||
searchMembers(pageData.pageIndex);
|
||||
}
|
||||
|
||||
setRemovingMemberName(null);
|
||||
}, [ pageData, removingMemberName, searchMembers ]);
|
||||
|
||||
CreateMessageHook(GroupMembersEvent, onGroupMembersEvent);
|
||||
CreateMessageHook(GroupConfirmMemberRemoveEvent, onGroupConfirmMemberRemoveEvent);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
@ -43,13 +60,15 @@ export const GroupMembersView: FC<GroupMembersViewProps> = props =>
|
||||
if(!groupId) return;
|
||||
|
||||
if(levelId !== null) setSearchLevelId(levelId);
|
||||
searchMembers(0);
|
||||
|
||||
searchMembers(0, levelId);
|
||||
}, [ groupId, levelId ]);
|
||||
|
||||
useEffect(() =>
|
||||
const selectSearchLevelId = useCallback((level: number) =>
|
||||
{
|
||||
searchMembers(0);
|
||||
}, [ searchLevelId ]);
|
||||
setSearchLevelId(level);
|
||||
searchMembers(0, level);
|
||||
}, [ searchMembers ]);
|
||||
|
||||
const previousPage = useCallback(() =>
|
||||
{
|
||||
@ -82,6 +101,45 @@ export const GroupMembersView: FC<GroupMembersViewProps> = props =>
|
||||
return '';
|
||||
}, [ pageData ]);
|
||||
|
||||
const toggleAdmin = useCallback((member: GroupMemberParser) =>
|
||||
{
|
||||
if(member.rank === GroupRank.OWNER) return;
|
||||
|
||||
if(member.rank !== GroupRank.ADMIN)
|
||||
{
|
||||
SendMessageHook(new GroupAdminGiveComposer(pageData.groupId, member.id));
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessageHook(new GroupAdminTakeComposer(pageData.groupId, member.id));
|
||||
}
|
||||
|
||||
searchMembers(pageData.pageIndex);
|
||||
}, [ pageData ]);
|
||||
|
||||
const acceptMembership = useCallback((member) =>
|
||||
{
|
||||
if(member.rank === GroupRank.REQUESTED)
|
||||
{
|
||||
SendMessageHook(new GroupMembershipAcceptComposer(pageData.groupId, member.id));
|
||||
searchMembers(pageData.pageIndex);
|
||||
}
|
||||
}, [ pageData ]);
|
||||
|
||||
const removeMemberOrDeclineMembership = useCallback((member) =>
|
||||
{
|
||||
if(member.rank === GroupRank.REQUESTED)
|
||||
{
|
||||
SendMessageHook(new GroupMembershipDeclineComposer(pageData.groupId, member.id));
|
||||
searchMembers(pageData.pageIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
setRemovingMemberName(member.name);
|
||||
SendMessageHook(new GroupConfirmRemoveMemberComposer(pageData.groupId, member.id));
|
||||
}
|
||||
}, [ pageData ]);
|
||||
|
||||
if(!pageData) return null;
|
||||
|
||||
return (
|
||||
@ -94,7 +152,7 @@ export const GroupMembersView: FC<GroupMembersViewProps> = props =>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<input type="text" className="form-control form-control-sm w-100 mb-1" placeholder={ LocalizeText('group.members.searchinfo') } value={ searchQuery } onChange={ (e) => setSearchQuery(e.target.value) } onBlur={ () => searchMembers(pageData.pageIndex) } onKeyDown={ onKeyDown } />
|
||||
<select className="form-select form-select-sm w-100" value={ searchLevelId } onChange={ (e) => setSearchLevelId(Number(e.target.value)) }>
|
||||
<select className="form-select form-select-sm w-100" value={ searchLevelId } onChange={ (e) => selectSearchLevelId(Number(e.target.value)) }>
|
||||
<option value="0">{ LocalizeText('group.members.search.all') }</option>
|
||||
<option value="1">{ LocalizeText('group.members.search.admins') }</option>
|
||||
<option value="2">{ LocalizeText('group.members.search.pending') }</option>
|
||||
@ -107,19 +165,22 @@ export const GroupMembersView: FC<GroupMembersViewProps> = props =>
|
||||
return (
|
||||
<div key={ index } className={ 'col pb-1' + classNames({ ' pe-1': index % 2 === 0 }) }>
|
||||
<div className="list-member bg-white rounded d-flex text-black">
|
||||
<div className="avatar-head flex-shrink-0">
|
||||
<div className="avatar-head flex-shrink-0 cursor-pointer" onClick={ () => { GetUserProfile(member.id) } }>
|
||||
<AvatarImageView figure={ member.figure } headOnly={ true } direction={ 2 } />
|
||||
</div>
|
||||
<div className="p-1 w-100">
|
||||
<div className="fw-bold small">{ member.name }</div>
|
||||
<div className="text-muted fst-italic small">{ LocalizeText('group.members.since', ['date'], [member.joinedAt]) }</div>
|
||||
<div className="p-1 w-100 d-flex flex-column justify-content-center">
|
||||
<div className="fw-bold small cursor-pointer" onClick={ () => { GetUserProfile(member.id) } }>{ member.name }</div>
|
||||
{ member.rank !== GroupRank.REQUESTED && <div className="text-muted fst-italic small">{ LocalizeText('group.members.since', ['date'], [member.joinedAt]) }</div> }
|
||||
</div>
|
||||
<div className="d-flex flex-column pe-2 align-items-center justify-content-center">
|
||||
<div className="d-flex align-items-center">
|
||||
<i className={ 'icon icon-group-small-' + classNames({ 'owner': member.rank === GroupRank.OWNER, 'admin': member.rank === GroupRank.ADMIN, 'not-admin': member.rank === GroupRank.MEMBER, 'cursor-pointer': pageData.admin }) } title={ LocalizeText(getRankDescription(member)) } />
|
||||
<i className={ 'icon icon-group-small-' + classNames({ 'owner': member.rank === GroupRank.OWNER, 'admin': member.rank === GroupRank.ADMIN, 'not-admin': member.rank === GroupRank.MEMBER, 'cursor-pointer': pageData.admin }) } title={ LocalizeText(getRankDescription(member)) } onClick={ () => toggleAdmin(member) } />
|
||||
</div>
|
||||
{ member.rank === GroupRank.REQUESTED && <div className="d-flex align-items-center">
|
||||
<i className="icon cursor-pointer icon-group-accept-member" title={ LocalizeText('group.members.accept') } onClick={ () => acceptMembership(member) } />
|
||||
</div> }
|
||||
{ member.rank !== GroupRank.OWNER && pageData.admin && member.id !== GetSessionDataManager().userId &&<div className="d-flex align-items-center mt-1">
|
||||
<i className="icon cursor-pointer icon-group-remove-member" title={ LocalizeText(member.rank === GroupRank.REQUESTED ? 'group.members.reject' : 'group.members.kick') } />
|
||||
<i className="icon cursor-pointer icon-group-remove-member" title={ LocalizeText(member.rank === GroupRank.REQUESTED ? 'group.members.reject' : 'group.members.kick') } onClick={ () => removeMemberOrDeclineMembership(member) } />
|
||||
</div> }
|
||||
</div>
|
||||
</div>
|
||||
|
@ -65,8 +65,11 @@ export const GroupRoomInformationView: FC<{}> = props =>
|
||||
|
||||
const tryLeaveGroup = useCallback(() =>
|
||||
{
|
||||
SendMessageHook(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));
|
||||
SendMessageHook(new GroupInformationComposer(groupInformation.id, false));
|
||||
if(window.confirm(LocalizeText('group.leaveconfirm.desc')))
|
||||
{
|
||||
SendMessageHook(new GroupRemoveMemberComposer(groupInformation.id, GetSessionDataManager().userId));
|
||||
SendMessageHook(new GroupInformationComposer(groupInformation.id, false));
|
||||
}
|
||||
}, [ groupInformation ]);
|
||||
|
||||
const getButtonText = useCallback(() =>
|
||||
|
@ -1,18 +1,12 @@
|
||||
import { UserProfileComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback } from 'react';
|
||||
import { SendMessageHook } from '../../../hooks';
|
||||
import { FC } from 'react';
|
||||
import { GetUserProfile } from '../../../api';
|
||||
import { UserProfileIconViewProps } from './UserProfileIconView.types';
|
||||
|
||||
export const UserProfileIconView: FC<UserProfileIconViewProps> = props =>
|
||||
{
|
||||
const { userId = 0, userName = null } = props;
|
||||
|
||||
const visitProfile = useCallback(() =>
|
||||
{
|
||||
if(userId) SendMessageHook(new UserProfileComposer(userId));
|
||||
}, [ userId ]);
|
||||
|
||||
return (<>
|
||||
<i className="icon icon-user-profile me-1 cursor-pointer" onClick={ visitProfile } />
|
||||
<i className="icon icon-user-profile me-1 cursor-pointer" onClick={ () => GetUserProfile(userId) } />
|
||||
</>);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user