Changeset View
Changeset View
Standalone View
Standalone View
web/calendar/filter-panel.react.js
Show All 30 Lines | |||||
import type { Dispatch } from 'lib/types/redux-types.js'; | import type { Dispatch } from 'lib/types/redux-types.js'; | ||||
import css from './filter-panel.css'; | import css from './filter-panel.css'; | ||||
import ThreadSettingsModal from '../modals/threads/settings/thread-settings-modal.react.js'; | import ThreadSettingsModal from '../modals/threads/settings/thread-settings-modal.react.js'; | ||||
import { useSelector } from '../redux/redux-utils.js'; | import { useSelector } from '../redux/redux-utils.js'; | ||||
import { | import { | ||||
useFilterThreadInfos, | useFilterThreadInfos, | ||||
useFilterThreadSearchIndex, | useFilterThreadSearchIndex, | ||||
filterThreadIDsBelongingToCommunitySelector, | |||||
} from '../selectors/calendar-selectors.js'; | } from '../selectors/calendar-selectors.js'; | ||||
import { MagnifyingGlass } from '../vectors.react.js'; | import { MagnifyingGlass } from '../vectors.react.js'; | ||||
type Props = { | type Props = { | ||||
+filterThreadInfos: $ReadOnlyArray<FilterThreadInfo>, | +filterThreadInfos: $ReadOnlyArray<FilterThreadInfo>, | ||||
+filterThreadSearchIndex: SearchIndex, | +filterThreadSearchIndex: SearchIndex, | ||||
+filteredThreadIDs: ?$ReadOnlySet<string>, | +filteredThreadIDs: ?$ReadOnlySet<string>, | ||||
+filteredCommunityThreadIDs: ?$ReadOnlySet<string>, | |||||
+includeDeleted: boolean, | +includeDeleted: boolean, | ||||
+dispatch: Dispatch, | +dispatch: Dispatch, | ||||
+pushModal: PushModal, | +pushModal: PushModal, | ||||
}; | }; | ||||
type State = { | type State = { | ||||
+query: string, | +query: string, | ||||
+searchResults: $ReadOnlyArray<FilterThreadInfo>, | +searchResults: $ReadOnlyArray<FilterThreadInfo>, | ||||
+collapsed: boolean, | +collapsed: boolean, | ||||
}; | }; | ||||
class FilterPanel extends React.PureComponent<Props, State> { | class FilterPanel extends React.PureComponent<Props, State> { | ||||
state: State = { | state: State = { | ||||
query: '', | query: '', | ||||
searchResults: [], | searchResults: [], | ||||
collapsed: false, | collapsed: false, | ||||
}; | }; | ||||
currentlySelected(threadID: string): boolean { | currentlySelected(threadID: string): boolean { | ||||
if (!this.props.filteredThreadIDs) { | if (!this.props.filteredThreadIDs) { | ||||
return true; | return true; | ||||
} | } | ||||
return this.props.filteredThreadIDs.has(threadID); | return this.props.filteredThreadIDs.has(threadID); | ||||
} | } | ||||
inCurrentCommunity(threadID: string): boolean { | |||||
if (!this.props.filteredCommunityThreadIDs) { | |||||
return true; | |||||
} | |||||
return this.props.filteredCommunityThreadIDs.has(threadID); | |||||
} | |||||
render() { | render() { | ||||
const filterThreadInfos = this.state.query | const filterThreadInfos = this.state.query | ||||
? this.state.searchResults | ? this.state.searchResults | ||||
: this.props.filterThreadInfos; | : this.props.filterThreadInfos; | ||||
const filterThreadInfosInCurrentCommunity = filterThreadInfos.filter(item => | |||||
this.inCurrentCommunity(item.threadInfo.id), | |||||
); | |||||
let filters = []; | let filters = []; | ||||
if (!this.state.query || filterThreadInfos.length > 0) { | if (!this.state.query || filterThreadInfosInCurrentCommunity.length > 0) { | ||||
filters.push( | filters.push( | ||||
<Category | <Category | ||||
numThreads={filterThreadInfos.length} | numThreads={filterThreadInfosInCurrentCommunity.length} | ||||
onToggle={this.onToggleAll} | onToggle={this.onToggleAll} | ||||
collapsed={this.state.collapsed} | collapsed={this.state.collapsed} | ||||
onCollapse={this.onCollapse} | onCollapse={this.onCollapse} | ||||
selected={!this.props.filteredThreadIDs} | selected={ | ||||
!this.props.filteredThreadIDs || | |||||
this.props.filteredThreadIDs.size === | |||||
this.props.filteredCommunityThreadIDs?.size | |||||
} | |||||
key="all" | key="all" | ||||
/>, | />, | ||||
); | ); | ||||
} else { | } else { | ||||
filters.push( | filters.push( | ||||
<div className={css.noResults} key="noResults"> | <div className={css.noResults} key="noResults"> | ||||
No results | No results | ||||
</div>, | </div>, | ||||
); | ); | ||||
} | } | ||||
if (!this.state.collapsed) { | if (!this.state.collapsed) { | ||||
const options = filterThreadInfos.map(filterThreadInfo => ( | const options = filterThreadInfosInCurrentCommunity.map( | ||||
filterThreadInfo => ( | |||||
<Item | <Item | ||||
filterThreadInfo={filterThreadInfo} | filterThreadInfo={filterThreadInfo} | ||||
onToggle={this.onToggle} | onToggle={this.onToggle} | ||||
onClickOnly={this.onClickOnly} | onClickOnly={this.onClickOnly} | ||||
onClickSettings={this.onClickSettings} | onClickSettings={this.onClickSettings} | ||||
selected={this.currentlySelected(filterThreadInfo.threadInfo.id)} | selected={this.currentlySelected(filterThreadInfo.threadInfo.id)} | ||||
key={filterThreadInfo.threadInfo.id} | key={filterThreadInfo.threadInfo.id} | ||||
/> | /> | ||||
)); | ), | ||||
); | |||||
filters = [...filters, ...options]; | filters = [...filters, ...options]; | ||||
} | } | ||||
let clearQueryButton = null; | let clearQueryButton = null; | ||||
if (this.state.query) { | if (this.state.query) { | ||||
clearQueryButton = ( | clearQueryButton = ( | ||||
<a href="#" onClick={this.clearQuery}> | <a href="#" onClick={this.clearQuery}> | ||||
<FontAwesomeIcon icon={faTimesCircle} className={css.clearQuery} /> | <FontAwesomeIcon icon={faTimesCircle} className={css.clearQuery} /> | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | onToggle = (threadID: string, value: boolean) => { | ||||
} else { | } else { | ||||
// Thread filter exists and thread is being added | // Thread filter exists and thread is being added | ||||
newThreadIDs = [...selectedThreadIDs, threadID]; | newThreadIDs = [...selectedThreadIDs, threadID]; | ||||
} | } | ||||
this.setFilterThreads(newThreadIDs); | this.setFilterThreads(newThreadIDs); | ||||
}; | }; | ||||
onToggleAll = (value: boolean) => { | onToggleAll = (value: boolean) => { | ||||
this.setFilterThreads(value ? null : []); | if (!value) { | ||||
this.setFilterThreads([]); | |||||
return; | |||||
} | |||||
const allChats = this.props.filteredCommunityThreadIDs | |||||
? Array.from(this.props.filteredCommunityThreadIDs) | |||||
: null; | |||||
this.setFilterThreads(allChats); | |||||
}; | }; | ||||
onClickOnly = (threadID: string) => { | onClickOnly = (threadID: string) => { | ||||
this.setFilterThreads([threadID]); | this.setFilterThreads([threadID]); | ||||
}; | }; | ||||
setFilterThreads(threadIDs: ?$ReadOnlyArray<string>) { | setFilterThreads(threadIDs: ?$ReadOnlyArray<string>) { | ||||
if (!threadIDs) { | if (!threadIDs) { | ||||
▲ Show 20 Lines • Show All 165 Lines • ▼ Show 20 Lines | onCollapse = (event: SyntheticEvent<HTMLAnchorElement>) => { | ||||
event.preventDefault(); | event.preventDefault(); | ||||
this.props.onCollapse(!this.props.collapsed); | this.props.onCollapse(!this.props.collapsed); | ||||
}; | }; | ||||
} | } | ||||
const ConnectedFilterPanel: React.ComponentType<{}> = React.memo<{}>( | const ConnectedFilterPanel: React.ComponentType<{}> = React.memo<{}>( | ||||
function ConnectedFilterPanel(): React.Node { | function ConnectedFilterPanel(): React.Node { | ||||
const filteredThreadIDs = useSelector(filteredThreadIDsSelector); | const filteredThreadIDs = useSelector(filteredThreadIDsSelector); | ||||
const filteredCommunityThreadIDs = useSelector( | |||||
filterThreadIDsBelongingToCommunitySelector, | |||||
); | |||||
const filterThreadInfos = useFilterThreadInfos(); | const filterThreadInfos = useFilterThreadInfos(); | ||||
const filterThreadSearchIndex = useFilterThreadSearchIndex(); | const filterThreadSearchIndex = useFilterThreadSearchIndex(); | ||||
const includeDeleted = useSelector(includeDeletedSelector); | const includeDeleted = useSelector(includeDeletedSelector); | ||||
const dispatch = useDispatch(); | const dispatch = useDispatch(); | ||||
const modalContext = useModalContext(); | const modalContext = useModalContext(); | ||||
return ( | return ( | ||||
<FilterPanel | <FilterPanel | ||||
filteredThreadIDs={filteredThreadIDs} | filteredThreadIDs={filteredThreadIDs} | ||||
filteredCommunityThreadIDs={filteredCommunityThreadIDs} | |||||
filterThreadInfos={filterThreadInfos} | filterThreadInfos={filterThreadInfos} | ||||
filterThreadSearchIndex={filterThreadSearchIndex} | filterThreadSearchIndex={filterThreadSearchIndex} | ||||
includeDeleted={includeDeleted} | includeDeleted={includeDeleted} | ||||
dispatch={dispatch} | dispatch={dispatch} | ||||
pushModal={modalContext.pushModal} | pushModal={modalContext.pushModal} | ||||
/> | /> | ||||
); | ); | ||||
}, | }, | ||||
); | ); | ||||
export default ConnectedFilterPanel; | export default ConnectedFilterPanel; |