mirror of
https://github.com/billsonnn/nitro-react.git
synced 2025-02-18 18:02:36 +01:00
Groups Updates
This commit is contained in:
parent
a2ed795cd2
commit
a5dbd3574e
6
src/api/groups/GetGroupManager.ts
Normal file
6
src/api/groups/GetGroupManager.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { CreateLinkEvent } from '..';
|
||||
|
||||
export function GetGroupManager(groupId: number): void
|
||||
{
|
||||
CreateLinkEvent(`groups/manage/${groupId}`);
|
||||
}
|
@ -1,5 +1,53 @@
|
||||
.nitro-groups {
|
||||
.tab-image {
|
||||
width: 122px;
|
||||
height: 68px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
div {
|
||||
background-image: url('../../assets/images/groups/creator_images.png');
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
&.tab-1 {
|
||||
div {
|
||||
background-position: 0px 0px;
|
||||
width: 99px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
&.tab-2 {
|
||||
div {
|
||||
background-position: -99px 0px;
|
||||
width: 98px;
|
||||
height: 62px;
|
||||
}
|
||||
}
|
||||
|
||||
&.tab-3 {
|
||||
div {
|
||||
background-position: 0px -50px;
|
||||
width: 96px;
|
||||
height: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
&.tab-4, &.tab-5 {
|
||||
div {
|
||||
background-position: 0px -95px;
|
||||
width: 114px;
|
||||
height: 61px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@import './views/creator/GroupCreatorView';
|
||||
@import './views/information/GroupInformationView';
|
||||
@import './views/information-standalone/GroupInformationStandaloneView';
|
||||
@import './views/manager/GroupManagerView';
|
||||
@import './views/room-information/GroupRoomInformationView';
|
||||
@import './views/shared-tabs/GroupSharedTabs';
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { GroupBadgePartsEvent, GroupBuyDataEvent, RoomCreatedEvent } from '@nitrots/nitro-renderer';
|
||||
import { GroupBadgePartsEvent, GroupBuyDataEvent, GroupSettingsEvent, RoomCreatedEvent } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback } from 'react';
|
||||
import { CreateMessageHook } from '../../hooks';
|
||||
import { GroupBadgePart } from './common/GroupBadgePart';
|
||||
import { useGroupsContext } from './context/GroupsContext';
|
||||
import { GroupsActions } from './context/GroupsContext.types';
|
||||
|
||||
@ -30,8 +31,8 @@ export const GroupsMessageHandler: FC<{}> = props =>
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.SET_PURHCASE_SETTINGS,
|
||||
payload: {
|
||||
objectArrays: rooms,
|
||||
numberValue: parser.groupCost
|
||||
objectValues: rooms,
|
||||
numberValues: [ parser.groupCost ]
|
||||
}
|
||||
});
|
||||
}, [ dispatchGroupsState ]);
|
||||
@ -50,11 +51,10 @@ export const GroupsMessageHandler: FC<{}> = props =>
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.SET_PURHCASE_SETTINGS,
|
||||
payload: {
|
||||
objectArrays: clonedRooms
|
||||
objectValues: clonedRooms
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
}, [ availableRooms, dispatchGroupsState ]);
|
||||
|
||||
const onGroupBadgePartsEvent = useCallback((event: GroupBadgePartsEvent) =>
|
||||
{
|
||||
@ -100,14 +100,42 @@ export const GroupsMessageHandler: FC<{}> = props =>
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.SET_GROUP_BADGE_PARTS_CONFIG,
|
||||
payload: {
|
||||
objectArrays: [ bases, symbols, partColors, colorsA, colorsB ]
|
||||
objectValues: [ bases, symbols, partColors, colorsA, colorsB ]
|
||||
}
|
||||
})
|
||||
});
|
||||
}, [ dispatchGroupsState ]);
|
||||
|
||||
const onGroupSettingsEvent = useCallback((event: GroupSettingsEvent) =>
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
const groupBadgeParts: GroupBadgePart[] = [];
|
||||
|
||||
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.color,
|
||||
part.position
|
||||
));
|
||||
});
|
||||
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.SET_GROUP_SETTINGS,
|
||||
payload: {
|
||||
stringValues: [ parser.title, parser.description ],
|
||||
numberValues: [ parser.id, parser.state, parser.colorA, parser.colorB ],
|
||||
boolValues: [ parser.canMembersDecorate ],
|
||||
objectValues: groupBadgeParts
|
||||
}
|
||||
});
|
||||
}, [ dispatchGroupsState ]);
|
||||
|
||||
CreateMessageHook(GroupBuyDataEvent, onGroupBuyDataEvent);
|
||||
CreateMessageHook(RoomCreatedEvent, onRoomCreatedEvent);
|
||||
CreateMessageHook(GroupBadgePartsEvent, onGroupBadgePartsEvent);
|
||||
CreateMessageHook(GroupSettingsEvent, onGroupSettingsEvent);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { GroupBadgePartsComposer, GroupPurchasedEvent, ILinkEventTracker } from '@nitrots/nitro-renderer';
|
||||
import { GroupBadgePartsComposer, GroupPurchasedEvent, GroupSettingsComposer, ILinkEventTracker } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useEffect, useReducer, useState } from 'react';
|
||||
import { AddEventLinkTracker, RemoveLinkEventTracker, TryVisitRoom } from '../../api';
|
||||
import { CreateMessageHook, SendMessageHook } from '../../hooks';
|
||||
@ -7,6 +7,7 @@ import { GroupsReducer, initialGroups } from './context/GroupsContext.types';
|
||||
import { GroupsMessageHandler } from './GroupsMessageHandler';
|
||||
import { GroupCreatorView } from './views/creator/GroupCreatorView';
|
||||
import { GroupInformationStandaloneView } from './views/information-standalone/GroupInformationStandaloneView';
|
||||
import { GroupManagerView } from './views/manager/GroupManagerView';
|
||||
|
||||
export const GroupsView: FC<{}> = props =>
|
||||
{
|
||||
@ -30,6 +31,11 @@ export const GroupsView: FC<{}> = props =>
|
||||
case 'create':
|
||||
setIsCreatorVisible(true);
|
||||
return;
|
||||
case 'manage':
|
||||
if(!parts[2]) return;
|
||||
|
||||
SendMessageHook(new GroupSettingsComposer(Number(parts[2])));
|
||||
return;
|
||||
}
|
||||
}, []);
|
||||
|
||||
@ -60,6 +66,7 @@ export const GroupsView: FC<{}> = props =>
|
||||
<GroupsMessageHandler />
|
||||
<div className="nitro-groups">
|
||||
<GroupCreatorView isVisible={ isCreatorVisible } onClose={ () => setIsCreatorVisible(false) } />
|
||||
<GroupManagerView />
|
||||
<GroupInformationStandaloneView />
|
||||
</div>
|
||||
</GroupsContextProvider>
|
||||
|
@ -19,6 +19,7 @@ export interface IGroupsState
|
||||
badgeBases: { id: number, images: string[] }[];
|
||||
badgeSymbols: { id: number, images: string[] }[];
|
||||
badgePartColors: { id: number, color: string }[];
|
||||
groupId: number;
|
||||
groupColorsA: { id: number, color: string }[];
|
||||
groupColorsB: { id: number, color: string }[];
|
||||
groupName: string;
|
||||
@ -26,15 +27,18 @@ export interface IGroupsState
|
||||
groupHomeroomId: number;
|
||||
groupBadgeParts: GroupBadgePart[];
|
||||
groupColors: number[];
|
||||
groupState: number;
|
||||
groupCanMembersDecorate: boolean;
|
||||
}
|
||||
|
||||
export interface IGroupsAction
|
||||
{
|
||||
type: string;
|
||||
payload?: {
|
||||
objectArrays?: any[];
|
||||
stringValue?: string;
|
||||
numberValue?: number;
|
||||
objectValues?: any[];
|
||||
stringValues?: string[];
|
||||
numberValues?: number[];
|
||||
boolValues?: boolean[];
|
||||
badgeParts?: GroupBadgePart[];
|
||||
}
|
||||
}
|
||||
@ -48,6 +52,9 @@ export class GroupsActions
|
||||
public static SET_GROUP_HOMEROOM_ID: string = 'GA_SET_GROUP_HOMEROOM_ID';
|
||||
public static SET_GROUP_BADGE_PARTS: string = 'GA_SET_BADGE_PARTS';
|
||||
public static SET_GROUP_COLORS: string = 'GA_SET_GROUP_COLORS';
|
||||
public static SET_GROUP_STATE: string = 'GA_SET_GROUP_STATE';
|
||||
public static SET_GROUP_CAN_MEMBERS_DECORATE: string = 'GA_SET_GROUP_CAN_MEMBERS_DECORATE';
|
||||
public static SET_GROUP_SETTINGS: string = 'GA_SET_GROUP_SETTINGS';
|
||||
public static RESET_GROUP_SETTINGS: string = 'GA_RESET_GROUP_SETTINGS';
|
||||
}
|
||||
|
||||
@ -57,13 +64,16 @@ export const initialGroups: IGroupsState = {
|
||||
badgeBases: null,
|
||||
badgeSymbols: null,
|
||||
badgePartColors: null,
|
||||
groupId: null,
|
||||
groupColorsA: null,
|
||||
groupColorsB: null,
|
||||
groupName: '',
|
||||
groupDescription: '',
|
||||
groupHomeroomId: 0,
|
||||
groupBadgeParts: null,
|
||||
groupColors: null
|
||||
groupColors: null,
|
||||
groupState: null,
|
||||
groupCanMembersDecorate: null
|
||||
};
|
||||
|
||||
export const GroupsReducer: Reducer<IGroupsState, IGroupsAction> = (state, action) =>
|
||||
@ -71,32 +81,32 @@ export const GroupsReducer: Reducer<IGroupsState, IGroupsAction> = (state, actio
|
||||
switch(action.type)
|
||||
{
|
||||
case GroupsActions.SET_PURHCASE_SETTINGS: {
|
||||
const availableRooms = action.payload.objectArrays;
|
||||
const purchaseCost = (action.payload.numberValue || state.purchaseCost || 0);
|
||||
const availableRooms = action.payload.objectValues;
|
||||
const purchaseCost = (action.payload.numberValues[0] || state.purchaseCost || 0);
|
||||
|
||||
return { ...state, availableRooms, purchaseCost };
|
||||
}
|
||||
case GroupsActions.SET_GROUP_BADGE_PARTS_CONFIG: {
|
||||
const badgeBases = (action.payload.objectArrays[0] || state.badgeBases || null);
|
||||
const badgeSymbols = (action.payload.objectArrays[1] || state.badgeSymbols || null);
|
||||
const badgePartColors = (action.payload.objectArrays[2] || state.badgePartColors || null);
|
||||
const groupColorsA = (action.payload.objectArrays[3] || state.groupColorsA || null);
|
||||
const groupColorsB = (action.payload.objectArrays[4] || state.groupColorsB || null);
|
||||
const badgeBases = (action.payload.objectValues[0] || state.badgeBases || null);
|
||||
const badgeSymbols = (action.payload.objectValues[1] || state.badgeSymbols || null);
|
||||
const badgePartColors = (action.payload.objectValues[2] || state.badgePartColors || null);
|
||||
const groupColorsA = (action.payload.objectValues[3] || state.groupColorsA || null);
|
||||
const groupColorsB = (action.payload.objectValues[4] || state.groupColorsB || null);
|
||||
|
||||
return { ...state, badgeBases, badgeSymbols, badgePartColors, groupColorsA, groupColorsB };
|
||||
}
|
||||
case GroupsActions.SET_GROUP_NAME: {
|
||||
const groupName = action.payload.stringValue;
|
||||
const groupName = action.payload.stringValues[0];
|
||||
|
||||
return { ...state, groupName };
|
||||
}
|
||||
case GroupsActions.SET_GROUP_DESCRIPTION: {
|
||||
const groupDescription = action.payload.stringValue;
|
||||
const groupDescription = action.payload.stringValues[0];
|
||||
|
||||
return { ...state, groupDescription };
|
||||
}
|
||||
case GroupsActions.SET_GROUP_HOMEROOM_ID: {
|
||||
const groupHomeroomId = action.payload.numberValue;
|
||||
const groupHomeroomId = action.payload.numberValues[0];
|
||||
|
||||
return { ...state, groupHomeroomId };
|
||||
}
|
||||
@ -106,18 +116,42 @@ export const GroupsReducer: Reducer<IGroupsState, IGroupsAction> = (state, actio
|
||||
return { ...state, groupBadgeParts };
|
||||
}
|
||||
case GroupsActions.SET_GROUP_COLORS: {
|
||||
const groupColors = action.payload.objectArrays;
|
||||
const groupColors = action.payload.objectValues;
|
||||
|
||||
return { ...state, groupColors };
|
||||
}
|
||||
case GroupsActions.SET_GROUP_STATE: {
|
||||
const groupState = action.payload.numberValues[0];
|
||||
|
||||
return { ...state, groupState };
|
||||
}
|
||||
case GroupsActions.SET_GROUP_CAN_MEMBERS_DECORATE: {
|
||||
const groupCanMembersDecorate = action.payload.boolValues[0];
|
||||
|
||||
return { ...state, groupCanMembersDecorate };
|
||||
}
|
||||
case GroupsActions.SET_GROUP_SETTINGS: {
|
||||
const groupId = action.payload.numberValues[0];
|
||||
const groupName = action.payload.stringValues[0];
|
||||
const groupDescription = action.payload.stringValues[1];
|
||||
const groupBadgeParts = action.payload.objectValues;
|
||||
const groupState = action.payload.numberValues[1];
|
||||
const groupColors = action.payload.numberValues.slice(2);
|
||||
const groupCanMembersDecorate = action.payload.boolValues[0];
|
||||
|
||||
return { ...state, groupId, groupName, groupDescription, groupBadgeParts, groupColors, groupState, groupCanMembersDecorate };
|
||||
}
|
||||
case GroupsActions.RESET_GROUP_SETTINGS: {
|
||||
const groupId = null;
|
||||
const groupName = '';
|
||||
const groupDescription = '';
|
||||
const groupHomeroomId = 0;
|
||||
const groupBadgeParts = null;
|
||||
const groupColors = null;
|
||||
const groupState = null;
|
||||
const groupCanMembersDecorate = null;
|
||||
|
||||
return { ...state, groupName, groupDescription, groupHomeroomId, groupBadgeParts, groupColors };
|
||||
return { ...state, groupId, groupName, groupDescription, groupHomeroomId, groupBadgeParts, groupColors, groupState, groupCanMembersDecorate };
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
|
@ -68,51 +68,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tab-image {
|
||||
width: 122px;
|
||||
height: 68px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
div {
|
||||
background-image: url('../../../../assets/images/groups/creator_images.png');
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
&.tab-1 {
|
||||
div {
|
||||
background-position: 0px 0px;
|
||||
width: 99px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
&.tab-2 {
|
||||
div {
|
||||
background-position: -99px 0px;
|
||||
width: 98px;
|
||||
height: 62px;
|
||||
}
|
||||
}
|
||||
|
||||
&.tab-3 {
|
||||
div {
|
||||
background-position: 0px -50px;
|
||||
width: 96px;
|
||||
height: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
&.tab-4 {
|
||||
div {
|
||||
background-position: 0px -95px;
|
||||
width: 114px;
|
||||
height: 61px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.creator-tab {
|
||||
height: 230px;
|
||||
min-height: 230px;
|
||||
|
@ -9,9 +9,9 @@ import { useGroupsContext } from '../../context/GroupsContext';
|
||||
import { GroupsActions } from '../../context/GroupsContext.types';
|
||||
import { GroupSharedTabBadgeView } from '../shared-tabs/tab-badge/GroupSharedTabBadgeView';
|
||||
import { GroupSharedTabColorsView } from '../shared-tabs/tab-colors/GroupSharedTabColorsView';
|
||||
import { GroupSharedTabIdentityView } from '../shared-tabs/tab-identity/GroupSharedTabIdentityView';
|
||||
import { GroupCreatorViewProps } from './GroupCreatorView.types';
|
||||
import { GroupCreatorTabConfirmationView } from './views/tab-confirmation/GroupCreatorTabConfirmationView';
|
||||
import { GroupCreatorTabIdentityView } from './views/tab-identity/GroupCreatorTabIdentityView';
|
||||
import { GroupCreatorTabConfirmationView } from './tab-confirmation/GroupCreatorTabConfirmationView';
|
||||
|
||||
const TABS: number[] = [1, 2, 3, 4];
|
||||
|
||||
@ -113,7 +113,7 @@ export const GroupCreatorView: FC<GroupCreatorViewProps> = props =>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-black creator-tab">
|
||||
{ currentTab === 1 && <GroupCreatorTabIdentityView /> }
|
||||
{ currentTab === 1 && <GroupSharedTabIdentityView isCreator={ true } /> }
|
||||
{ currentTab === 2 && <GroupSharedTabBadgeView /> }
|
||||
{ currentTab === 3 && <GroupSharedTabColorsView /> }
|
||||
{ currentTab === 4 && <GroupCreatorTabConfirmationView /> }
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { FC, useCallback } from 'react';
|
||||
import { LocalizeText } from '../../../../../../api';
|
||||
import { BadgeImageView } from '../../../../../shared/badge-image/BadgeImageView';
|
||||
import { useGroupsContext } from '../../../../context/GroupsContext';
|
||||
import { LocalizeText } from '../../../../../api';
|
||||
import { BadgeImageView } from '../../../../shared/badge-image/BadgeImageView';
|
||||
import { useGroupsContext } from '../../../context/GroupsContext';
|
||||
|
||||
export const GroupCreatorTabConfirmationView: FC<{}> = props =>
|
||||
{
|
@ -1,6 +1,7 @@
|
||||
import { GroupDeleteComposer, GroupRemoveMemberComposer } from '@nitrots/nitro-renderer';
|
||||
import { GroupRemoveMemberComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback } from 'react';
|
||||
import { CreateLinkEvent, GetSessionDataManager, LocalizeText, TryVisitRoom } from '../../../../api';
|
||||
import { GetGroupManager } from '../../../../api/groups/GetGroupManager';
|
||||
import { TryJoinGroup } from '../../../../api/groups/TryJoinGroup';
|
||||
import { SendMessageHook } from '../../../../hooks';
|
||||
import { CatalogPageName } from '../../../catalog/common/CatalogPageName';
|
||||
@ -81,13 +82,6 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
|
||||
case 'furniture':
|
||||
CreateLinkEvent('catalog/open/' + CatalogPageName.GUILD_CUSTOM_FURNI);
|
||||
break;
|
||||
case 'delete':
|
||||
if(window.confirm(LocalizeText('group.deleteconfirm.title') + ' - ' + LocalizeText('group.deleteconfirm.desc')))
|
||||
{
|
||||
SendMessageHook(new GroupDeleteComposer(groupInformation.id));
|
||||
if(onClose) onClose();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}, [ groupInformation, onClose ]);
|
||||
|
||||
@ -96,26 +90,22 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
|
||||
return (
|
||||
<div className="group-information text-black p-2">
|
||||
<div>
|
||||
<div className="group-badge text-center">
|
||||
<BadgeImageView badgeCode={ groupInformation.badge } isGroup={ true } />
|
||||
<div className="mt-3">
|
||||
<a href="#" className="small text-black">
|
||||
{ LocalizeText('group.membercount', ['totalMembers'], [groupInformation.membersCount.toString()]) }
|
||||
</a>
|
||||
<div className="text-center d-flex flex-column h-100 small text-black text-decoration-underline">
|
||||
<div className="group-badge">
|
||||
<BadgeImageView badgeCode={ groupInformation.badge } isGroup={ true } />
|
||||
</div>
|
||||
<div>
|
||||
{ groupInformation.pendingRequestsCount > 0 && <a href="#" className="small text-black">
|
||||
{ LocalizeText('group.pendingmembercount', ['totalMembers'], [groupInformation.pendingRequestsCount.toString()]) }
|
||||
</a> }
|
||||
<div className="mt-3 cursor-pointer">
|
||||
{ LocalizeText('group.membercount', ['totalMembers'], [groupInformation.membersCount.toString()]) }
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
{ groupInformation.pendingRequestsCount > 0 && <div className="cursor-pointer">
|
||||
{ LocalizeText('group.pendingmembercount', ['totalMembers'], [groupInformation.pendingRequestsCount.toString()]) }
|
||||
</div> }
|
||||
{ groupInformation.isOwner && <div className="cursor-pointer" onClick={ () => GetGroupManager(groupInformation.id) }>
|
||||
{ LocalizeText('group.manage') }
|
||||
</div> }
|
||||
<div className="mt-auto mb-1">
|
||||
{ getRoleIcon() }
|
||||
</div>
|
||||
<div>
|
||||
{ groupInformation.isOwner && <a href="#" className="small text-danger" onClick={ () => handleAction('delete') }>
|
||||
{ LocalizeText('group.delete') }
|
||||
</a> }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ms-2 w-100">
|
||||
@ -126,20 +116,16 @@ export const GroupInformationView: FC<GroupInformationViewProps> = props =>
|
||||
</div>
|
||||
<div>{ LocalizeText('group.created', ['date', 'owner'], [groupInformation.createdAt, groupInformation.ownerName]) }</div>
|
||||
<div className="group-description small overflow-auto">{ groupInformation.description }</div>
|
||||
<div>
|
||||
<a href="#" className="small text-black" onClick={ () => handleAction('homeroom') }>
|
||||
<div className="small text-black text-decoration-underline">
|
||||
<div className="cursor-pointer" onClick={ () => handleAction('homeroom') }>
|
||||
{ LocalizeText('group.linktobase') }
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#" className="small text-black" onClick={ () => handleAction('furniture') }>
|
||||
</div>
|
||||
<div className="cursor-pointer" onClick={ () => handleAction('furniture') }>
|
||||
{ LocalizeText('group.buyfurni') }
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#" className="small text-black">
|
||||
</div>
|
||||
<div className="cursor-pointer">
|
||||
{ LocalizeText('group.showgroups') }
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{ groupInformation.type !== GroupType.PRIVATE &&
|
||||
<button className="btn btn-primary w-100 mt-2" disabled={ groupInformation.membershipType === GroupMembershipType.REQUEST_PENDING || isRealOwner() } onClick={ handleButtonClick }>
|
||||
|
9
src/views/groups/views/manager/GroupManagerView.scss
Normal file
9
src/views/groups/views/manager/GroupManagerView.scss
Normal file
@ -0,0 +1,9 @@
|
||||
.nitro-group-manager {
|
||||
width: 385px;
|
||||
|
||||
.manager-tab {
|
||||
height: 230px;
|
||||
min-height: 230px;
|
||||
max-height: 230px;
|
||||
}
|
||||
}
|
100
src/views/groups/views/manager/GroupManagerView.tsx
Normal file
100
src/views/groups/views/manager/GroupManagerView.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
import { GroupDeleteComposer, GroupSaveBadgeComposer, GroupSaveColorsComposer, GroupSaveInformationComposer, GroupSavePreferencesComposer } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useState } from 'react';
|
||||
import { LocalizeText } from '../../../../api';
|
||||
import { SendMessageHook } from '../../../../hooks';
|
||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../../../layout';
|
||||
import { useGroupsContext } from '../../context/GroupsContext';
|
||||
import { GroupsActions } from '../../context/GroupsContext.types';
|
||||
import { GroupSharedTabBadgeView } from '../shared-tabs/tab-badge/GroupSharedTabBadgeView';
|
||||
import { GroupSharedTabColorsView } from '../shared-tabs/tab-colors/GroupSharedTabColorsView';
|
||||
import { GroupSharedTabIdentityView } from '../shared-tabs/tab-identity/GroupSharedTabIdentityView';
|
||||
import { GroupManagerTabSettingsView } from './tab-settings/GroupManagerTabSettingsView';
|
||||
|
||||
const TABS: number[] = [1, 2, 3, 5];
|
||||
|
||||
export const GroupManagerView: FC<{}> = props =>
|
||||
{
|
||||
const { groupsState = null, dispatchGroupsState = null } = useGroupsContext();
|
||||
const { groupId = null, groupName = null, groupDescription = null, groupColors = null, groupBadgeParts = null, groupState = null, groupCanMembersDecorate = null } = groupsState;
|
||||
|
||||
const [ currentTab, setCurrentTab ] = useState<number>(1);
|
||||
|
||||
const onClose = useCallback(() =>
|
||||
{
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.RESET_GROUP_SETTINGS
|
||||
});
|
||||
}, [ dispatchGroupsState ]);
|
||||
|
||||
const saveGroup = useCallback(() =>
|
||||
{
|
||||
const badge = [];
|
||||
|
||||
if(!groupBadgeParts) return;
|
||||
|
||||
groupBadgeParts.forEach((part) =>
|
||||
{
|
||||
if(part.code)
|
||||
{
|
||||
badge.push(part.key);
|
||||
badge.push(part.color);
|
||||
badge.push(part.position);
|
||||
}
|
||||
});
|
||||
|
||||
SendMessageHook(new GroupSaveInformationComposer(groupId, groupName, groupDescription));
|
||||
SendMessageHook(new GroupSaveBadgeComposer(groupId, badge));
|
||||
SendMessageHook(new GroupSaveColorsComposer(groupId, groupColors[0], groupColors[1]));
|
||||
SendMessageHook(new GroupSavePreferencesComposer(groupId, groupState, groupCanMembersDecorate ? 0 : 1));
|
||||
|
||||
onClose();
|
||||
}, [ groupBadgeParts, groupId, groupName, groupDescription, groupColors, groupState, groupCanMembersDecorate, onClose ]);
|
||||
|
||||
const deleteGroup = useCallback(() =>
|
||||
{
|
||||
if(window.confirm(LocalizeText('group.deleteconfirm.title') + ' - ' + LocalizeText('group.deleteconfirm.desc')))
|
||||
{
|
||||
SendMessageHook(new GroupDeleteComposer(groupId));
|
||||
onClose();
|
||||
}
|
||||
}, [ groupId, onClose ]);
|
||||
|
||||
if(!groupId) return null;
|
||||
|
||||
return (
|
||||
<NitroCardView className="nitro-group-manager" simple={ false }>
|
||||
<NitroCardHeaderView headerText={ LocalizeText('group.window.title') } onCloseClick={ onClose } />
|
||||
<NitroCardContentView className="p-0">
|
||||
<NitroCardTabsView>
|
||||
{ TABS.map(tab =>
|
||||
{
|
||||
return (<NitroCardTabsItemView key={ tab } isActive={ currentTab === tab } onClick={ () => setCurrentTab(tab) }>
|
||||
{ LocalizeText(`group.edit.tab.${tab}`) }
|
||||
</NitroCardTabsItemView>);
|
||||
}) }
|
||||
</NitroCardTabsView>
|
||||
<div className="p-2">
|
||||
<div className="d-flex align-items-center mb-2">
|
||||
<div className={ 'flex-shrink-0 tab-image tab-' + currentTab }>
|
||||
<div></div>
|
||||
</div>
|
||||
<div className="w-100 text-black ms-2">
|
||||
<div className="fw-bold h4 m-0">{ LocalizeText('group.edit.tabcaption.' + currentTab) }</div>
|
||||
<div>{ LocalizeText('group.edit.tabdesc.' + currentTab) }</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-black manager-tab">
|
||||
{ currentTab === 1 && <GroupSharedTabIdentityView /> }
|
||||
{ currentTab === 2 && <GroupSharedTabBadgeView skipDefault={ true } /> }
|
||||
{ currentTab === 3 && <GroupSharedTabColorsView /> }
|
||||
{ currentTab === 5 && <GroupManagerTabSettingsView /> }
|
||||
</div>
|
||||
<div className="d-flex justify-content-between mt-2">
|
||||
<button className="btn btn-danger" onClick={ deleteGroup }>{ LocalizeText('group.delete') }</button>
|
||||
<button className="btn btn-success" onClick={ saveGroup }>{ LocalizeText('save') }</button>
|
||||
</div>
|
||||
</div>
|
||||
</NitroCardContentView>
|
||||
</NitroCardView>
|
||||
);
|
||||
};
|
@ -0,0 +1,55 @@
|
||||
import { FC, useCallback } from 'react';
|
||||
import { LocalizeText } from '../../../../../api/utils/LocalizeText';
|
||||
import { useGroupsContext } from '../../../context/GroupsContext';
|
||||
import { GroupsActions } from '../../../context/GroupsContext.types';
|
||||
|
||||
const STATES: string[] = ['regular', 'exclusive', 'private'];
|
||||
|
||||
export const GroupManagerTabSettingsView: FC<{}> = props =>
|
||||
{
|
||||
const { groupsState = null, dispatchGroupsState = null } = useGroupsContext();
|
||||
const { groupState = null, groupCanMembersDecorate = false } = groupsState;
|
||||
|
||||
const setState = useCallback((state: number) =>
|
||||
{
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.SET_GROUP_STATE,
|
||||
payload: {
|
||||
numberValues: [ state ]
|
||||
}
|
||||
})
|
||||
}, [ dispatchGroupsState ]);
|
||||
|
||||
const toggleCanMembersDecorate = useCallback(() =>
|
||||
{
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.SET_GROUP_CAN_MEMBERS_DECORATE,
|
||||
payload: {
|
||||
boolValues: [ !groupCanMembersDecorate ]
|
||||
}
|
||||
})
|
||||
}, [ dispatchGroupsState, groupCanMembersDecorate ]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{ STATES.map((state, index) =>
|
||||
{
|
||||
return <div key={ index } className="form-check mb-1">
|
||||
<input className="form-check-input" type="radio" name="groupState" id={ `groupState${ index }` } checked={ (groupState === index) } onChange={ () => setState(index) } />
|
||||
<label className="form-check-label d-flex align-items-center gap-1 fw-bold" htmlFor={'groupState' + index}>
|
||||
<i className={ `icon icon-group-type-${index}` } /> { LocalizeText(`group.edit.settings.type.${state}.label`) }
|
||||
</label>
|
||||
<div>{ LocalizeText(`group.edit.settings.type.${state}.help`) }</div>
|
||||
</div>
|
||||
}) }
|
||||
<hr className="bg-dark" />
|
||||
<div className="form-check">
|
||||
<input className="form-check-input" type="checkbox" id="groupCanMembersDecorate" checked={ groupCanMembersDecorate } onChange={() => toggleCanMembersDecorate() } />
|
||||
<label className="form-check-label fw-bold" htmlFor="groupCanMembersDecorate">
|
||||
{ LocalizeText('group.edit.settings.rights.caption') }
|
||||
</label>
|
||||
<div>{ LocalizeText('group.edit.settings.rights.members.help') }</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,6 +1,7 @@
|
||||
import { DesktopViewEvent, GroupInformationComposer, GroupInformationEvent, GroupInformationParser, GroupJoinComposer, GroupRemoveMemberComposer, RoomInfoEvent } from '@nitrots/nitro-renderer';
|
||||
import { FC, useCallback, useState } from 'react';
|
||||
import { GetGroupInformation, GetSessionDataManager, LocalizeText } from '../../../../api';
|
||||
import { GetGroupManager } from '../../../../api/groups/GetGroupManager';
|
||||
import { CreateMessageHook, SendMessageHook } from '../../../../hooks';
|
||||
import { BadgeImageView } from '../../../shared/badge-image/BadgeImageView';
|
||||
import { GroupMembershipType } from '../../common/GroupMembershipType';
|
||||
@ -68,8 +69,6 @@ export const GroupRoomInformationView: FC<{}> = props =>
|
||||
SendMessageHook(new GroupInformationComposer(groupInformation.id, false));
|
||||
}, [ groupInformation ]);
|
||||
|
||||
const manageGroup = useCallback(() => {}, []);
|
||||
|
||||
const getButtonText = useCallback(() =>
|
||||
{
|
||||
if(isRealOwner()) return 'group.manage';
|
||||
@ -90,14 +89,14 @@ export const GroupRoomInformationView: FC<{}> = props =>
|
||||
|
||||
const handleButtonClick = useCallback(() =>
|
||||
{
|
||||
if(isRealOwner()) return manageGroup();
|
||||
if(isRealOwner()) return GetGroupManager(groupInformation.id);
|
||||
|
||||
if(groupInformation.type === GroupType.PRIVATE && groupInformation.membershipType === GroupMembershipType.NOT_MEMBER) return;
|
||||
|
||||
if(groupInformation.membershipType === GroupMembershipType.MEMBER) return tryLeaveGroup();
|
||||
|
||||
return tryJoinGroup();
|
||||
}, [ groupInformation, tryLeaveGroup, tryJoinGroup, isRealOwner, manageGroup ]);
|
||||
}, [ groupInformation, tryLeaveGroup, tryJoinGroup, isRealOwner ]);
|
||||
|
||||
if(!groupInformation) return null;
|
||||
|
||||
|
@ -4,20 +4,23 @@ import { BadgeImageView } from '../../../../shared/badge-image/BadgeImageView';
|
||||
import { GroupBadgePart } from '../../../common/GroupBadgePart';
|
||||
import { useGroupsContext } from '../../../context/GroupsContext';
|
||||
import { GroupsActions } from '../../../context/GroupsContext.types';
|
||||
import { GroupSharedTabBadgeViewProps } from './GroupSharedTabBadgeView.types';
|
||||
|
||||
const POSITIONS: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||
|
||||
export const GroupSharedTabBadgeView: FC<{}> = props =>
|
||||
export const GroupSharedTabBadgeView: FC<GroupSharedTabBadgeViewProps> = props =>
|
||||
{
|
||||
const { groupsState = null, dispatchGroupsState = null } = useGroupsContext();
|
||||
const { badgeBases = null, badgeSymbols = null, badgePartColors = null, groupBadgeParts = null } = groupsState;
|
||||
|
||||
const { skipDefault = null } = props;
|
||||
|
||||
const [ editingIndex, setEditingIndex ] = useState<number>(0);
|
||||
const [ isSelectingModel, setIsSelectingModel ] = useState<boolean>(false);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!badgeBases || !badgePartColors || groupBadgeParts) return;
|
||||
if(skipDefault || !badgeBases || !badgePartColors || groupBadgeParts) return;
|
||||
|
||||
const badgeParts: GroupBadgePart[] = [
|
||||
new GroupBadgePart(GroupBadgePart.BASE, badgeBases[0].id, badgePartColors[0].id),
|
||||
|
@ -0,0 +1,4 @@
|
||||
export interface GroupSharedTabBadgeViewProps
|
||||
{
|
||||
skipDefault?: boolean;
|
||||
}
|
@ -22,7 +22,7 @@ export const GroupSharedTabColorsView: FC<{}> = props =>
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.SET_GROUP_COLORS,
|
||||
payload: {
|
||||
objectArrays: colors
|
||||
objectValues: colors
|
||||
}
|
||||
});
|
||||
|
||||
@ -44,7 +44,7 @@ export const GroupSharedTabColorsView: FC<{}> = props =>
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.SET_GROUP_COLORS,
|
||||
payload: {
|
||||
objectArrays: clonedGroupColors
|
||||
objectValues: clonedGroupColors
|
||||
}
|
||||
});
|
||||
}, [ selectingColorIndex, groupColors, dispatchGroupsState ]);
|
||||
|
@ -1,19 +1,22 @@
|
||||
import { FC, useCallback } from 'react';
|
||||
import { CreateLinkEvent, LocalizeText } from '../../../../../../api';
|
||||
import { useGroupsContext } from '../../../../context/GroupsContext';
|
||||
import { GroupsActions } from '../../../../context/GroupsContext.types';
|
||||
import { CreateLinkEvent, LocalizeText } from '../../../../../api';
|
||||
import { useGroupsContext } from '../../../context/GroupsContext';
|
||||
import { GroupsActions } from '../../../context/GroupsContext.types';
|
||||
import { GroupSharedTabIdentityViewProps } from './GroupSharedTabIdentityView.types';
|
||||
|
||||
export const GroupCreatorTabIdentityView: FC<{}> = props =>
|
||||
export const GroupSharedTabIdentityView: FC<GroupSharedTabIdentityViewProps> = props =>
|
||||
{
|
||||
const { groupsState = null, dispatchGroupsState = null } = useGroupsContext();
|
||||
const { groupName = '', groupDescription = '', groupHomeroomId = 0, availableRooms = null } = groupsState;
|
||||
|
||||
const { isCreator = false } = props;
|
||||
|
||||
const setName = useCallback((name: string) =>
|
||||
{
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.SET_GROUP_NAME,
|
||||
payload: {
|
||||
stringValue: name
|
||||
stringValues: [ name ]
|
||||
}
|
||||
})
|
||||
}, [ dispatchGroupsState ]);
|
||||
@ -23,7 +26,7 @@ export const GroupCreatorTabIdentityView: FC<{}> = props =>
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.SET_GROUP_DESCRIPTION,
|
||||
payload: {
|
||||
stringValue: description
|
||||
stringValues: [ description ]
|
||||
}
|
||||
})
|
||||
}, [ dispatchGroupsState ]);
|
||||
@ -33,7 +36,7 @@ export const GroupCreatorTabIdentityView: FC<{}> = props =>
|
||||
dispatchGroupsState({
|
||||
type: GroupsActions.SET_GROUP_HOMEROOM_ID,
|
||||
payload: {
|
||||
numberValue: id
|
||||
numberValues: [ id ]
|
||||
}
|
||||
})
|
||||
}, [ dispatchGroupsState ]);
|
||||
@ -47,17 +50,19 @@ export const GroupCreatorTabIdentityView: FC<{}> = props =>
|
||||
<label className="fw-bold">{ LocalizeText('group.edit.desc') }</label>
|
||||
<input type="text" className="form-control form-control-sm" value={ groupDescription } maxLength={ 254 } onChange={ (e) => setDescription(e.target.value) } />
|
||||
</div>
|
||||
<div className="form-group mb-1">
|
||||
<label className="fw-bold">{ LocalizeText('group.edit.base') }</label>
|
||||
<select className="form-select form-select-sm" value={ groupHomeroomId } onChange={ (e) => setHomeroomId(Number(e.target.value)) }>
|
||||
<option value={ 0 } disabled>{ LocalizeText('group.edit.base.select.room') }</option>
|
||||
{ availableRooms && availableRooms.map((room, index) =>
|
||||
{
|
||||
return <option key={ index } value={ room.id }>{ room.name }</option>;
|
||||
}) }
|
||||
</select>
|
||||
</div>
|
||||
<div className="small mb-2">{ LocalizeText('group.edit.base.warning') }</div>
|
||||
<div className="cursor-pointer text-decoration-underline text-center" onClick={ () => CreateLinkEvent('navigator/create') }>{ LocalizeText('group.createroom') }</div>
|
||||
{ isCreator && <>
|
||||
<div className="form-group mb-1">
|
||||
<label className="fw-bold">{ LocalizeText('group.edit.base') }</label>
|
||||
<select className="form-select form-select-sm" value={ groupHomeroomId } onChange={ (e) => setHomeroomId(Number(e.target.value)) }>
|
||||
<option value={ 0 } disabled>{ LocalizeText('group.edit.base.select.room') }</option>
|
||||
{ availableRooms && availableRooms.map((room, index) =>
|
||||
{
|
||||
return <option key={ index } value={ room.id }>{ room.name }</option>;
|
||||
}) }
|
||||
</select>
|
||||
</div>
|
||||
<div className="small mb-2">{ LocalizeText('group.edit.base.warning') }</div>
|
||||
<div className="cursor-pointer text-decoration-underline text-center" onClick={ () => CreateLinkEvent('navigator/create') }>{ LocalizeText('group.createroom') }</div>
|
||||
</> }
|
||||
</div>);
|
||||
};
|
@ -0,0 +1,4 @@
|
||||
export interface GroupSharedTabIdentityViewProps
|
||||
{
|
||||
isCreator?: boolean;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user