import * as React from "react" import intl from "react-intl-universal" import { SourceGroup } from "../../schema-types" import { SourceState, RSSSource } from "../../scripts/models/source" import { IColumn, Selection, SelectionMode, DetailsList, Label, Stack, TextField, PrimaryButton, DefaultButton, Dropdown, IDropdownOption, CommandBarButton, MarqueeSelection, IDragDropEvents, MessageBar, MessageBarType } from "@fluentui/react" import DangerButton from "../utils/danger-button" type GroupsTabProps = { sources: SourceState, groups: SourceGroup[], serviceOn: boolean, createGroup: (name: string) => void, updateGroup: (group: SourceGroup) => void, addToGroup: (groupIndex: number, sid: number) => void, deleteGroup: (groupIndex: number) => void, removeFromGroup: (groupIndex: number, sids: number[]) => void, reorderGroups: (groups: SourceGroup[]) => void } type GroupsTabState = { [formName: string]: any, selectedGroup: SourceGroup, selectedSources: RSSSource[], dropdownIndex: number, manageGroup: boolean } class GroupsTab extends React.Component { groupSelection: Selection groupDragDropEvents: IDragDropEvents groupDraggedItem: SourceGroup groupDraggedIndex = -1 sourcesSelection: Selection sourcesDragDropEvents: IDragDropEvents sourcesDraggedItem: RSSSource sourcesDraggedIndex = -1 constructor(props) { super(props) this.state = { editGroupName: "", newGroupName: "", selectedGroup: null, selectedSources: null, dropdownIndex: null, manageGroup: false } this.groupDragDropEvents = this.getGroupDragDropEvents() this.sourcesDragDropEvents = this.getSourcesDragDropEvents() this.groupSelection = new Selection({ getKey: g => (g as SourceGroup).index, onSelectionChanged: () => { let g = this.groupSelection.getSelectedCount() ? this.groupSelection.getSelection()[0] as SourceGroup : null this.setState({ selectedGroup: g, editGroupName: g && g.isMultiple ? g.name : "" }) } }) this.sourcesSelection = new Selection({ getKey: s => (s as RSSSource).sid, onSelectionChanged: () => { let sources = this.sourcesSelection.getSelectedCount() ? this.sourcesSelection.getSelection() as RSSSource[] : null this.setState({ selectedSources: sources }) } }) } groupColumns = (): IColumn[] => [ { key: "type", name: intl.get("groups.type"), minWidth: 40, maxWidth: 40, data: "string", onRender: (g: SourceGroup) => <> {g.isMultiple ? intl.get("groups.group") : intl.get("groups.source")} }, { key: "capacity", name: intl.get("groups.capacity"), minWidth: 40, maxWidth: 60, data: "string", onRender: (g: SourceGroup) => <> {g.isMultiple ? g.sids.length : ""} }, { key: "name", name: intl.get("name"), minWidth: 200, data: "string", isRowHeader: true, onRender: (g: SourceGroup) => <> {g.isMultiple ? g.name : this.props.sources[g.sids[0]].name} } ] sourceColumns: IColumn[] = [ { key: "favicon", name: intl.get("icon"), fieldName: "name", isIconOnly: true, iconName: "ImagePixel", minWidth: 16, maxWidth: 16, onRender: (s: RSSSource) => s.iconurl && ( ) }, { key: "name", name: intl.get("name"), fieldName: "name", minWidth: 200, data: 'string', isRowHeader: true }, { key: "url", name: "URL", fieldName: "url", minWidth: 280, data: 'string' } ] getGroupDragDropEvents = (): IDragDropEvents => ({ canDrop: () => true, canDrag: () => true, onDrop: (item?: SourceGroup) => { if (this.groupDraggedItem) { this.reorderGroups(item) } }, onDragStart: (item?: SourceGroup, itemIndex?: number) => { this.groupDraggedItem = item this.groupDraggedIndex = itemIndex! }, onDragEnd: () => { this.groupDraggedItem = undefined this.groupDraggedIndex = -1 }, }) reorderGroups = (item: SourceGroup) => { let draggedItem = this.groupSelection.isIndexSelected(this.groupDraggedIndex) ? this.groupSelection.getSelection()[0] as SourceGroup : this.groupDraggedItem! let insertIndex = item.index let groups = this.props.groups.filter(g => g.index != draggedItem.index) groups.splice(insertIndex, 0, draggedItem) this.groupSelection.setAllSelected(false) this.props.reorderGroups(groups) } getSourcesDragDropEvents = (): IDragDropEvents => ({ canDrop: () => true, canDrag: () => true, onDrop: (item?: RSSSource) => { if (this.sourcesDraggedItem) { this.reorderSources(item) } }, onDragStart: (item?: RSSSource, itemIndex?: number) => { this.sourcesDraggedItem = item this.sourcesDraggedIndex = itemIndex! }, onDragEnd: () => { this.sourcesDraggedItem = undefined this.sourcesDraggedIndex = -1 }, }) reorderSources = (item: RSSSource) => { let draggedItems = this.sourcesSelection.isIndexSelected(this.sourcesDraggedIndex) ? (this.sourcesSelection.getSelection() as RSSSource[]).map(s => s.sid) : [this.sourcesDraggedItem!.sid] let insertIndex = this.state.selectedGroup.sids.indexOf(item.sid) let items = this.state.selectedGroup.sids.filter(sid => !draggedItems.includes(sid)) items.splice(insertIndex, 0, ...draggedItems) let group = { ...this.state.selectedGroup, sids: items } this.props.updateGroup(group) this.setState({ selectedGroup: group }) } manageGroup = (g: SourceGroup) => { if (g.isMultiple) { this.setState({ selectedGroup: g, editGroupName: g && g.isMultiple ? g.name : "", manageGroup: true }) } } dropdownOptions = () => this.props.groups.filter(g => g.isMultiple).map(g => ({ key: g.index, text: g.name })) handleInputChange = (event) => { const name: string = event.target.name this.setState({[name]: event.target.value}) } validateNewGroupName = (v: string) => { const name = v.trim() if (name.length == 0) { return intl.get("emptyName") } for (let group of this.props.groups) { if (group.isMultiple && group.name === name) { return intl.get("groups.exist") } } return "" } createGroup = (event: React.FormEvent) => { event.preventDefault() let trimmed = this.state.newGroupName.trim() if (this.validateNewGroupName(trimmed) === "") this.props.createGroup(trimmed) } addToGroup = () => { this.props.addToGroup(this.state.dropdownIndex, this.state.selectedGroup.sids[0]) } removeFromGroup = () => { this.props.removeFromGroup(this.state.selectedGroup.index, this.state.selectedSources.map(s => s.sid)) this.setState({ selectedSources: null }) } deleteGroup = () => { this.props.deleteGroup(this.state.selectedGroup.index) this.groupSelection.setIndexSelected(this.state.selectedGroup.index, false, false) this.setState({ selectedGroup: null }) } updateGroupName = () => { let group = this.state.selectedGroup group = { ...group, name: this.state.editGroupName.trim() } this.props.updateGroup(group) } dropdownChange = (_, item: IDropdownOption) => { this.setState({ dropdownIndex: item ? Number(item.key) : null }) } render = () => (
{this.props.serviceOn && ( {intl.get("service.groupsWarning")} )} {this.state.manageGroup && this.state.selectedGroup && <> this.setState({manageGroup: false})} /> {this.state.selectedSources != null && } this.props.sources[sid])} columns={this.sourceColumns} dragDropEvents={this.sourcesDragDropEvents} setKey="multiple" selection={this.sourcesSelection} selectionMode={SelectionMode.multiple} /> {intl.get("groups.sourceHint")} } {(!this.state.manageGroup || !this.state.selectedGroup) ?<>
{this.state.selectedGroup ? ( this.state.selectedGroup.isMultiple ?<> v.trim().length == 0 ? intl.get("emptyName") : ""} validateOnLoad={false} placeholder={intl.get("groups.enterName")} value={this.state.editGroupName} name="editGroupName" onChange={this.handleInputChange} /> :<> ) : {intl.get("groups.groupHint")} } : null}
) } export default GroupsTab