change(ui): make components|
This commit is contained in:
parent
7c12c6683e
commit
3d760b4ed0
6 changed files with 259 additions and 0 deletions
|
|
@ -0,0 +1,137 @@
|
|||
import React from 'react'
|
||||
import { Loader, Pagination, Tooltip } from 'UI';
|
||||
import { connect } from 'react-redux';
|
||||
import SessionItem from 'Shared/SessionItem';
|
||||
import { addFilterByKeyAndValue, updateCurrentPage, applyFilter } from 'Duck/liveSearch';
|
||||
import { List } from 'immutable';
|
||||
import { FilterKey } from 'App/types/filter/filterType';
|
||||
import Select from 'Shared/Select';
|
||||
import SortOrderButton from 'Shared/SortOrderButton';
|
||||
import { KEYS } from 'Types/filter/customFilter';
|
||||
import { capitalize } from 'App/utils';
|
||||
import { useStore } from 'App/mstore'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
|
||||
import cn from 'classnames'
|
||||
import Session from 'App/mstore/types/session';
|
||||
|
||||
const PER_PAGE = 10;
|
||||
|
||||
interface OwnProps {}
|
||||
interface ConnectProps {
|
||||
loading: boolean;
|
||||
metaListLoading: boolean;
|
||||
list: List<any>;
|
||||
filter: any;
|
||||
currentPage: number;
|
||||
metaList: any;
|
||||
sort: any;
|
||||
total: number;
|
||||
addFilterByKeyAndValue: (key: FilterKey, value: string) => void;
|
||||
updateCurrentPage: (page: number) => void;
|
||||
applyFilter: (filter: any) => void;
|
||||
onAdd: () => void;
|
||||
}
|
||||
|
||||
type Props = OwnProps & ConnectProps;
|
||||
|
||||
function AssistSessionsModal(props: Props) {
|
||||
const { assistTabStore } = useStore();
|
||||
const { loading, list, metaList = [], filter, currentPage, total, onAdd } = props;
|
||||
const onUserClick = () => false;
|
||||
const { filters } = filter;
|
||||
const hasUserFilter = filters.map((i: any) => i.key).includes(KEYS.USERID);
|
||||
|
||||
const sortOptions = metaList
|
||||
.map((i: any) => ({
|
||||
label: capitalize(i),
|
||||
value: i,
|
||||
}))
|
||||
.toJS();
|
||||
|
||||
React.useEffect(() => {
|
||||
props.applyFilter({ ...filter });
|
||||
}, []);
|
||||
const onSortChange = ({ value }: any) => {
|
||||
props.applyFilter({ sort: value.value });
|
||||
};
|
||||
const onSessionAdd = (session: Session) => {
|
||||
assistTabStore.addSession(session);
|
||||
onAdd()
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-gray-lightest box-shadow h-screen p-4" style={{ width: '840px' }}>
|
||||
<div className="flex items-center my-2">
|
||||
<div className="flex items-center">
|
||||
<span className="mr-2 color-gray-medium">Sort By</span>
|
||||
<Tooltip
|
||||
title="No metadata available to sort"
|
||||
disabled={sortOptions.length > 0}
|
||||
>
|
||||
<div className={cn("flex items-center", { 'disabled': sortOptions.length === 0 })} >
|
||||
<Select
|
||||
plain
|
||||
right
|
||||
options={sortOptions}
|
||||
onChange={onSortChange}
|
||||
value={sortOptions.find((i: any) => i.value === filter.sort) || sortOptions[0]}
|
||||
/>
|
||||
<div className="mx-2" />
|
||||
<SortOrderButton onChange={(state: any) => props.applyFilter({ order: state })} sortOrder={filter.order} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<Loader loading={loading}>
|
||||
<>
|
||||
{list.map((session) => (
|
||||
<React.Fragment key={session.sessionID}>
|
||||
<div className="rounded bg-white mb-2 overflow-hidden border">
|
||||
<SessionItem
|
||||
key={session.sessionId}
|
||||
session={session}
|
||||
live
|
||||
hasUserFilter={hasUserFilter}
|
||||
onUserClick={onUserClick}
|
||||
metaList={metaList}
|
||||
onClick={() => onSessionAdd(session)}
|
||||
/>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
|
||||
))}
|
||||
</>
|
||||
</Loader>
|
||||
|
||||
{total > PER_PAGE && (
|
||||
<div className="w-full flex items-center justify-center py-6">
|
||||
<Pagination
|
||||
page={currentPage}
|
||||
totalPages={Math.ceil(total / PER_PAGE)}
|
||||
onPageChange={(page: any) => props.updateCurrentPage(page)}
|
||||
limit={PER_PAGE}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(
|
||||
(state: any) => ({
|
||||
list: state.getIn(['liveSearch', 'list']),
|
||||
loading: state.getIn(['liveSearch', 'fetchList', 'loading']),
|
||||
metaListLoading: state.getIn(['customFields', 'fetchRequest', 'loading']),
|
||||
filter: state.getIn(['liveSearch', 'instance']),
|
||||
total: state.getIn(['liveSearch', 'total']),
|
||||
currentPage: state.getIn(['liveSearch', 'currentPage']),
|
||||
metaList: state.getIn(['customFields', 'list']).map((i: any) => i.key),
|
||||
sort: state.getIn(['liveSearch', 'sort']),
|
||||
}),
|
||||
{
|
||||
applyFilter,
|
||||
addFilterByKeyAndValue,
|
||||
updateCurrentPage,
|
||||
}
|
||||
)(AssistSessionsModal);
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from './AssistSessionsModal'
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
import React from 'react';
|
||||
import cn from 'classnames';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import { Icon } from 'UI';
|
||||
import AssistSessionsModal from '../AssistSessionsModal';
|
||||
import { useStore } from 'App/mstore'
|
||||
import Session from 'App/mstore/types/session'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
|
||||
interface ITab {
|
||||
onClick?: () => void;
|
||||
onDoubleClick?: () => void;
|
||||
classNames?: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const Tab = (props: ITab) => (
|
||||
<div
|
||||
onDoubleClick={props.onDoubleClick}
|
||||
onClick={props.onClick}
|
||||
className={cn('p-1 rounded flex items-center justify-center cursor-pointer', props.classNames)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
|
||||
const InactiveTab = (props: Omit<ITab, 'children' | 'onDoubleClick'>) => (
|
||||
<Tab onClick={props.onClick} classNames="hover:bg-gray-bg bg-gray-light">
|
||||
<Icon name="plus" size="22" color="white" />
|
||||
</Tab>
|
||||
);
|
||||
const ActiveTab = (props: Omit<ITab, 'children'>) => (
|
||||
<Tab onDoubleClick={props.onDoubleClick} classNames="hover:bg-teal bg-borderColor-primary">
|
||||
<Icon name="play-fill-new" size="22" color="white" />
|
||||
</Tab>
|
||||
);
|
||||
const CurrentTab = () => (
|
||||
<Tab classNames="bg-teal color-white">
|
||||
<span style={{ fontSize: '0.65rem' }}>PLAYING</span>
|
||||
</Tab>
|
||||
);
|
||||
|
||||
function AssistTabs({ session }: { session: Session }) {
|
||||
const { showModal, hideModal } = useModal();
|
||||
const { assistTabStore } = useStore()
|
||||
|
||||
const placeholder = new Array(4 - assistTabStore.sessions.length).fill(0)
|
||||
|
||||
React.useEffect(() => {
|
||||
if (assistTabStore.sessions.length === 0) {
|
||||
assistTabStore.addSession(session)
|
||||
assistTabStore.setActiveSession(session.sessionId)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const showAssistList = () => showModal(<AssistSessionsModal onAdd={hideModal} />, { right: true });
|
||||
return (
|
||||
<div className="grid grid-cols-2 w-28 h-full" style={{ gap: '4px' }}>
|
||||
{assistTabStore.sessions.map(session => (
|
||||
<React.Fragment key={session.sessionId}>
|
||||
{assistTabStore.isActive(session.sessionId)
|
||||
? <CurrentTab /> : <ActiveTab />}
|
||||
</React.Fragment>
|
||||
)
|
||||
)}
|
||||
{placeholder.map((_, i) => (
|
||||
<React.Fragment key={i}>
|
||||
<InactiveTab onClick={showAssistList} />
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default observer(AssistTabs);
|
||||
|
|
@ -3,6 +3,7 @@ import cn from 'classnames';
|
|||
import { connect } from 'react-redux';
|
||||
import { STORAGE_TYPES, selectStorageType } from 'Player';
|
||||
import LiveTag from 'Shared/LiveTag';
|
||||
import AssistSessionsTabs from './AssistSessionsTabs';
|
||||
|
||||
import { Icon, Tooltip } from 'UI';
|
||||
import {
|
||||
|
|
@ -95,6 +96,7 @@ function Controls(props: any) {
|
|||
skipInterval,
|
||||
disabledRedux,
|
||||
showStorageRedux,
|
||||
session,
|
||||
// showStackRedux,
|
||||
} = props;
|
||||
|
||||
|
|
@ -259,6 +261,10 @@ function Controls(props: any) {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<AssistSessionsTabs session={session} />
|
||||
</div>
|
||||
|
||||
<div className="flex items-center h-full">
|
||||
<ControlButton
|
||||
disabled={disabled && !inspectorMode}
|
||||
|
|
@ -368,6 +374,7 @@ export default connect(
|
|||
bottomBlock: state.getIn(['components', 'player', 'bottomBlock']),
|
||||
showStorageRedux: !state.getIn(['components', 'player', 'hiddenHints', 'storage']),
|
||||
showStackRedux: !state.getIn(['components', 'player', 'hiddenHints', 'stack']),
|
||||
session: state.getIn(['sessions', 'current']),
|
||||
closedLive:
|
||||
!!state.getIn(['sessions', 'errors']) || !state.getIn(['sessions', 'current', 'live']),
|
||||
skipInterval: state.getIn(['components', 'player', 'skipInterval']),
|
||||
|
|
|
|||
36
frontend/app/mstore/assistTabStore.ts
Normal file
36
frontend/app/mstore/assistTabStore.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import { makeAutoObservable } from "mobx"
|
||||
import Session from './types/session';
|
||||
|
||||
type TabSessions = [Session?,Session?,Session?,Session?]
|
||||
|
||||
export default class AssistTabStore {
|
||||
sessions: TabSessions = []
|
||||
activeSession: Session = null
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this)
|
||||
}
|
||||
|
||||
isActive(sessionId: string): boolean {
|
||||
return this.activeSession.sessionId === sessionId
|
||||
}
|
||||
|
||||
setSessions(sessions: TabSessions) {
|
||||
this.sessions = sessions
|
||||
}
|
||||
|
||||
addSession(session: Session) {
|
||||
if (this.sessions.length < 4) {
|
||||
this.sessions.push(session)
|
||||
}
|
||||
}
|
||||
|
||||
setActiveSession(sessionId: string) {
|
||||
this.activeSession = this.sessions.find(session => session.sessionId === sessionId)
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.sessions = []
|
||||
this.activeSession = null
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ import SessionStore from './sessionStore';
|
|||
import NotesStore from './notesStore';
|
||||
import BugReportStore from './bugReportStore'
|
||||
import RecordingsStore from './recordingsStore'
|
||||
import AssistTabStore from './assistTabStore';
|
||||
|
||||
export class RootStore {
|
||||
dashboardStore: DashboardStore;
|
||||
|
|
@ -39,6 +40,7 @@ export class RootStore {
|
|||
notesStore: NotesStore;
|
||||
bugReportStore: BugReportStore;
|
||||
recordingsStore: RecordingsStore;
|
||||
assistTabStore: AssistTabStore;
|
||||
|
||||
constructor() {
|
||||
this.dashboardStore = new DashboardStore();
|
||||
|
|
@ -54,6 +56,7 @@ export class RootStore {
|
|||
this.notesStore = new NotesStore();
|
||||
this.bugReportStore = new BugReportStore();
|
||||
this.recordingsStore = new RecordingsStore();
|
||||
this.assistTabStore = new AssistTabStore();
|
||||
}
|
||||
|
||||
initClient() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue