mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-09-21 15:38:59 +03:00
publish: incorporate group filter component
This commit is contained in:
parent
9cb90405c1
commit
21c989fee1
@ -139,6 +139,15 @@ class UrbitApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setSelected(selected) {
|
||||||
|
store.handleEvent({
|
||||||
|
type: "local",
|
||||||
|
data: {
|
||||||
|
selected: selected
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export let api = new UrbitApi();
|
export let api = new UrbitApi();
|
||||||
|
231
pkg/interface/publish/src/js/components/lib/group-filter.js
Normal file
231
pkg/interface/publish/src/js/components/lib/group-filter.js
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
import React, { Component } from 'react'
|
||||||
|
|
||||||
|
export class GroupFilter extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
open: false,
|
||||||
|
selected: [],
|
||||||
|
groups: [],
|
||||||
|
searchTerm: "",
|
||||||
|
results: []
|
||||||
|
}
|
||||||
|
this.toggleOpen = this.toggleOpen.bind(this);
|
||||||
|
this.handleClickOutside = this.handleClickOutside.bind(this);
|
||||||
|
this.groupIndex = this.groupIndex.bind(this);
|
||||||
|
this.search = this.search.bind(this);
|
||||||
|
this.addGroup = this.addGroup.bind(this);
|
||||||
|
this.deleteGroup = this.deleteGroup.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
document.addEventListener('mousedown', this.handleClickOutside);
|
||||||
|
this.groupIndex();
|
||||||
|
let selected = localStorage.getItem("urbit-selectedGroups");
|
||||||
|
if (selected) {
|
||||||
|
this.setState({selected: JSON.parse(selected)}, (() => {
|
||||||
|
window.api.setSelected(this.state.selected);
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
document.removeEventListener('mousedown', this.handleClickOutside);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (prevProps !== this.props) {
|
||||||
|
this.groupIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClickOutside(evt) {
|
||||||
|
if ((this.dropdown && !this.dropdown.contains(evt.target))
|
||||||
|
&& (this.toggleButton && !this.toggleButton.contains(evt.target))) {
|
||||||
|
this.setState({ open: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleOpen() {
|
||||||
|
this.setState({open: !this.state.open});
|
||||||
|
}
|
||||||
|
|
||||||
|
groupIndex() {
|
||||||
|
const { props, state } = this;
|
||||||
|
let index = [];
|
||||||
|
let associations = !!props.associations ? props.associations.contacts : {};
|
||||||
|
index = Object.keys(associations).map((each) => {
|
||||||
|
let eachGroup = [];
|
||||||
|
eachGroup.push(each);
|
||||||
|
let name = each;
|
||||||
|
if (associations[each].metadata) {
|
||||||
|
name = (associations[each].metadata.title !== "")
|
||||||
|
? associations[each].metadata.title : name;
|
||||||
|
}
|
||||||
|
eachGroup.push(name);
|
||||||
|
return eachGroup;
|
||||||
|
});
|
||||||
|
this.setState({groups: index})
|
||||||
|
}
|
||||||
|
|
||||||
|
search(evt) {
|
||||||
|
this.setState({searchTerm: evt.target.value});
|
||||||
|
let term = evt.target.value.toLowerCase();
|
||||||
|
|
||||||
|
if (term.length < 3) {
|
||||||
|
return this.setState({results: []})
|
||||||
|
}
|
||||||
|
|
||||||
|
let groupMatches = [];
|
||||||
|
groupMatches = this.state.groups.filter(e => {
|
||||||
|
return (e[0].includes(term) || e[1].includes(term));
|
||||||
|
});
|
||||||
|
this.setState({results: groupMatches});
|
||||||
|
}
|
||||||
|
|
||||||
|
addGroup(group) {
|
||||||
|
let selected = this.state.selected;
|
||||||
|
if (!(group in selected)) {
|
||||||
|
selected.push(group);
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
searchTerm: "",
|
||||||
|
selected: selected,
|
||||||
|
results: []
|
||||||
|
}, (() => {
|
||||||
|
window.api.setSelected(this.state.selected);
|
||||||
|
localStorage.setItem("urbit-selectedGroups", JSON.stringify(this.state.selected));
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteGroup(group) {
|
||||||
|
let selected = this.state.selected;
|
||||||
|
selected = selected.filter(e => {
|
||||||
|
return e !== group;
|
||||||
|
});
|
||||||
|
this.setState({selected: selected}, (() => {
|
||||||
|
window.api.setSelected(this.state.selected);
|
||||||
|
localStorage.setItem("urbit-selectedGroups", JSON.stringify(this.state.selected));
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { props, state } = this;
|
||||||
|
|
||||||
|
let currentGroup = "All Groups";
|
||||||
|
|
||||||
|
if (state.selected.length > 0) {
|
||||||
|
let titles = state.selected.map((each) => {
|
||||||
|
return each[1];
|
||||||
|
})
|
||||||
|
currentGroup = titles.join(" + ");
|
||||||
|
}
|
||||||
|
|
||||||
|
let buttonOpened = (state.open)
|
||||||
|
? "bg-gray5 bg-gray1-d white-d" : "hover-bg-gray5 hover-bg-gray1-d white-d";
|
||||||
|
|
||||||
|
let dropdownClass = (state.open)
|
||||||
|
? "absolute db z-2 bg-white bg-gray0-d white-d ba b--gray3 b--gray1-d"
|
||||||
|
: "dn";
|
||||||
|
|
||||||
|
let inviteCount = (props.invites && props.invites.length > 0)
|
||||||
|
? <template className="dib fr" style={{paddingTop: 1}}>
|
||||||
|
<p className="dib bg-green2 bg-gray2-d white fw6 ph1 br1 v-mid" style={{ marginBottom: 2 }}>
|
||||||
|
{props.invites.length}
|
||||||
|
</p>
|
||||||
|
<span className="dib v-mid ml1">
|
||||||
|
<img
|
||||||
|
className="v-mid"
|
||||||
|
src="/~launch/img/Chevron.png"
|
||||||
|
style={{ height: 16, width: 16, paddingBottom: 1 }}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
: <template className="dib fr" style={{paddingTop: 1}}>
|
||||||
|
<span className="dib v-top ml1">
|
||||||
|
<img className="v-mid"
|
||||||
|
src="/~launch/img/Chevron.png"
|
||||||
|
style={{ height: 16, width: 16, paddingBottom: 1 }}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</template>;
|
||||||
|
|
||||||
|
let selectedGroups = <div/>
|
||||||
|
let searchResults = <div/>
|
||||||
|
|
||||||
|
if (state.results.length > 0) {
|
||||||
|
let groupResults = state.results.map((group => {
|
||||||
|
return(
|
||||||
|
<li
|
||||||
|
key={group[0]}
|
||||||
|
className="tl list white-d f9 pv2 ph3 pointer hover-bg-gray4 hover-bg-gray1-d inter" onClick={() => this.addGroup(group)}>
|
||||||
|
<span className="mix-blend-diff white">{(group[1]) ? group[1] : group[0]}</span>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
searchResults = (
|
||||||
|
<div className={"tl absolute bg-white bg-gray0-d white-d pv3 z-1 w-100 ba b--gray4 b--white-d overflow-y-scroll"} style={{maxWidth: "15.67rem", maxHeight: "8rem"}}>
|
||||||
|
<p className="f9 tl gray2 ph3 pb2">Groups</p>
|
||||||
|
{groupResults}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.selected.length > 0) {
|
||||||
|
let allSelected = this.state.selected.map((each) => {
|
||||||
|
let name = each[1];
|
||||||
|
return(
|
||||||
|
<span
|
||||||
|
key={each[0]}
|
||||||
|
className={"f9 inter black pa2 bg-gray5 bg-gray1-d " +
|
||||||
|
"ba b--gray4 b--gray2-d white-d dib mr2 mt2 c-default"}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
<span
|
||||||
|
className="white-d ml3 mono pointer"
|
||||||
|
onClick={e => this.deleteGroup(each)}>
|
||||||
|
x
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
selectedGroups = (
|
||||||
|
<div className={
|
||||||
|
"f9 gray2 bb bl br b--gray3 b--gray2-d bg-gray0-d " +
|
||||||
|
"white-d pa3 db w-100 inter bg-gray5 lh-solid tl"
|
||||||
|
}>
|
||||||
|
{allSelected}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ml1 dib">
|
||||||
|
<div className={buttonOpened}
|
||||||
|
onClick={() => this.toggleOpen()}
|
||||||
|
ref={(el) => this.toggleButton = el}>
|
||||||
|
<p className="dib f9 pointer pa1 mw5 truncate v-mid">{currentGroup}</p>
|
||||||
|
</div>
|
||||||
|
<div className={dropdownClass}
|
||||||
|
style={{ maxHeight: "24rem", width: 285 }}
|
||||||
|
ref={(el) => { this.dropdown = el }}>
|
||||||
|
<p className="tc bb b--gray3 b--gray1-d gray3 pv4 f9">Group Select and Filter</p>
|
||||||
|
<a href="/~groups" className="ma4 bg-gray5 bg-gray1-d f9 tl pa1 br1 db no-underline" style={{paddingLeft: "6.5px", paddingRight: "6.5px"}}>Manage all Groups
|
||||||
|
{inviteCount}
|
||||||
|
</a>
|
||||||
|
<p className="pt4 gray3 f9 tl mh4">Filter Groups</p>
|
||||||
|
<div className="relative pb6 w-100 ph4 pt2">
|
||||||
|
<input className="ba b--gray3 white-d bg-gray0-d inter w-100 f9 pa2" style={{boxSizing: "border-box"}} placeholder="Group name..."
|
||||||
|
onChange={this.search}
|
||||||
|
value={state.searchTerm}
|
||||||
|
/>
|
||||||
|
{searchResults}
|
||||||
|
{selectedGroups}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GroupFilter;
|
@ -1,61 +1,49 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from "react";
|
||||||
import { IconHome } from '/components/lib/icons/icon-home';
|
import { GroupFilter } from "./group-filter";
|
||||||
import { Sigil } from '/components/lib/icons/sigil';
|
import { Sigil } from "/components/lib/icons/sigil";
|
||||||
import { cite } from '../../lib/util';
|
|
||||||
|
|
||||||
export class HeaderBar extends Component {
|
export class HeaderBar extends Component {
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let popout = (window.location.href.includes("popout/"))
|
let popout = window.location.href.includes("popout/")
|
||||||
? "dn"
|
? "dn" : "dn db-m db-l db-xl";
|
||||||
: "dn db-m db-l db-xl";
|
|
||||||
|
|
||||||
let title = (document.title === "Home")
|
// let spinner = !!this.props.spinner
|
||||||
? ""
|
// ? this.props.spinner : false;
|
||||||
: document.title;
|
|
||||||
|
|
||||||
let spinner = !!this.props.spinner
|
// let spinnerClasses = "";
|
||||||
? this.props.spinner : false;
|
|
||||||
|
|
||||||
let spinnerClasses = "";
|
// if (spinner === true) {
|
||||||
|
// spinnerClasses = "spin-active";
|
||||||
|
// }
|
||||||
|
|
||||||
if (spinner === true) {
|
let invites = (this.props.invites && this.props.invites.contacts)
|
||||||
spinnerClasses = "spin-active";
|
? this.props.invites.contacts
|
||||||
}
|
: {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"bg-white bg-gray0-d white-d w-100 justify-between relative tc pt3 "
|
<div
|
||||||
+ popout}
|
className={
|
||||||
|
"bg-white bg-gray0-d w-100 justify-between relative tc pt3 " + popout
|
||||||
|
}
|
||||||
style={{ height: 40 }}>
|
style={{ height: 40 }}>
|
||||||
<a className="dib gray2 f9 inter absolute left-0"
|
<div className="fl lh-copy absolute left-0" style={{ top: 8 }}>
|
||||||
href='/'
|
<a href="/~groups/me" className="dib v-mid">
|
||||||
style={{top: 14}}>
|
<Sigil
|
||||||
<IconHome classes={spinnerClasses}/>
|
ship={"~" + window.ship}
|
||||||
<span className="ml2 v-top lh-title white-d"
|
classes="v-mid mix-blend-diff"
|
||||||
style={{paddingTop: 3}}>
|
size={16}
|
||||||
Home
|
color={"#000000"}
|
||||||
</span>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<span className="f9 inter dib"
|
<GroupFilter invites={invites} associations={this.props.associations} />
|
||||||
style={{
|
<span className="dib f9 v-mid gray2 ml1 mr1 c-default inter">/</span>
|
||||||
verticalAlign: "text-top",
|
<a
|
||||||
paddingTop: 3
|
className="dib f9 v-mid inter ml1"
|
||||||
}}>
|
href="/"
|
||||||
{title}
|
style={{ top: 14 }}>
|
||||||
</span>
|
⟵ Publishing</a>
|
||||||
<div className="absolute right-0 lh-copy" style={{top: 12}}>
|
|
||||||
<Sigil
|
|
||||||
ship={"~" + window.ship}
|
|
||||||
classes="mix-blend-diff v-mid"
|
|
||||||
size={16}
|
|
||||||
color={"#000000"}
|
|
||||||
/>
|
|
||||||
<span className="mono f9 ml2 c-default">{cite(window.ship)}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,11 +61,21 @@ export class Sidebar extends Component {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let selectedGroups = !!props.selectedGroups ? props.selectedGroups: [];
|
||||||
let groupedItems = Object.keys(associations)
|
let groupedItems = Object.keys(associations)
|
||||||
|
.filter((each) => {
|
||||||
|
if (selectedGroups.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let selectedPaths = selectedGroups.map((e) => { return e[0] });
|
||||||
|
return (selectedPaths.includes(each));
|
||||||
|
})
|
||||||
.map((each, i) => {
|
.map((each, i) => {
|
||||||
let books = groupedNotebooks[each];
|
let books = groupedNotebooks[each];
|
||||||
if (books.length === 0) return;
|
if (books.length === 0) return;
|
||||||
if (groupedNotebooks["/~/"] && groupedNotebooks["/~/"].length !== 0) {
|
if ((selectedGroups.length === 0) &&
|
||||||
|
groupedNotebooks["/~/"] &&
|
||||||
|
groupedNotebooks["/~/"].length !== 0) {
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
}
|
}
|
||||||
return(
|
return(
|
||||||
@ -79,7 +89,9 @@ export class Sidebar extends Component {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
if (groupedNotebooks["/~/"] && groupedNotebooks["/~/"].length !== 0) {
|
if ((selectedGroups.length === 0) &&
|
||||||
|
groupedNotebooks["/~/"] &&
|
||||||
|
groupedNotebooks["/~/"].length !== 0) {
|
||||||
groupedItems.unshift(
|
groupedItems.unshift(
|
||||||
<GroupItem
|
<GroupItem
|
||||||
key={"/~/"}
|
key={"/~/"}
|
||||||
|
@ -24,6 +24,7 @@ export class Root extends Component {
|
|||||||
|
|
||||||
let contacts = !!state.contacts ? state.contacts : {};
|
let contacts = !!state.contacts ? state.contacts : {};
|
||||||
let associations = !!state.associations ? state.associations : {contacts: {}}
|
let associations = !!state.associations ? state.associations : {contacts: {}}
|
||||||
|
let selectedGroups = !!state.selected ? state.selected : [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
@ -39,6 +40,7 @@ export class Root extends Component {
|
|||||||
invites={state.invites}
|
invites={state.invites}
|
||||||
notebooks={state.notebooks}
|
notebooks={state.notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
|
selectedGroups={selectedGroups}
|
||||||
contacts={contacts}>
|
contacts={contacts}>
|
||||||
<div className={`h-100 w-100 overflow-x-hidden flex flex-column
|
<div className={`h-100 w-100 overflow-x-hidden flex flex-column
|
||||||
bg-white bg-gray0-d dn db-ns`}>
|
bg-white bg-gray0-d dn db-ns`}>
|
||||||
@ -64,6 +66,7 @@ export class Root extends Component {
|
|||||||
invites={state.invites}
|
invites={state.invites}
|
||||||
notebooks={state.notebooks}
|
notebooks={state.notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
|
selectedGroups={selectedGroups}
|
||||||
contacts={contacts}>
|
contacts={contacts}>
|
||||||
<NewScreen
|
<NewScreen
|
||||||
associations={associations.contacts}
|
associations={associations.contacts}
|
||||||
@ -90,6 +93,7 @@ export class Root extends Component {
|
|||||||
invites={state.invites}
|
invites={state.invites}
|
||||||
notebooks={state.notebooks}
|
notebooks={state.notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
|
selectedGroups={selectedGroups}
|
||||||
contacts={contacts}>
|
contacts={contacts}>
|
||||||
<JoinScreen
|
<JoinScreen
|
||||||
notebooks={state.notebooks}
|
notebooks={state.notebooks}
|
||||||
@ -128,6 +132,7 @@ export class Root extends Component {
|
|||||||
invites={state.invites}
|
invites={state.invites}
|
||||||
notebooks={state.notebooks}
|
notebooks={state.notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
|
selectedGroups={selectedGroups}
|
||||||
contacts={contacts}
|
contacts={contacts}
|
||||||
path={path}>
|
path={path}>
|
||||||
<NewPost
|
<NewPost
|
||||||
@ -153,6 +158,7 @@ export class Root extends Component {
|
|||||||
notebooks={state.notebooks}
|
notebooks={state.notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
contacts={contacts}
|
contacts={contacts}
|
||||||
|
selectedGroups={selectedGroups}
|
||||||
path={path}>
|
path={path}>
|
||||||
<Notebook
|
<Notebook
|
||||||
notebooks={state.notebooks}
|
notebooks={state.notebooks}
|
||||||
@ -196,6 +202,7 @@ export class Root extends Component {
|
|||||||
spinner={state.spinner}
|
spinner={state.spinner}
|
||||||
invites={state.invites}
|
invites={state.invites}
|
||||||
notebooks={state.notebooks}
|
notebooks={state.notebooks}
|
||||||
|
selectedGroups={selectedGroups}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
contacts={contacts}
|
contacts={contacts}
|
||||||
path={path}>
|
path={path}>
|
||||||
@ -221,6 +228,7 @@ export class Root extends Component {
|
|||||||
invites={state.invites}
|
invites={state.invites}
|
||||||
notebooks={state.notebooks}
|
notebooks={state.notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
|
selectedGroups={selectedGroups}
|
||||||
contacts={contacts}
|
contacts={contacts}
|
||||||
path={path}>
|
path={path}>
|
||||||
<Note
|
<Note
|
||||||
|
@ -20,7 +20,10 @@ export class Skeleton extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"absolute h-100 w-100 " + popoutWindow}>
|
<div className={"absolute h-100 w-100 " + popoutWindow}>
|
||||||
<HeaderBar spinner={this.props.spinner} />
|
<HeaderBar
|
||||||
|
spinner={props.spinner}
|
||||||
|
invites={props.invites}
|
||||||
|
associations={props.associations} />
|
||||||
<div className={`cf w-100 h-100 flex ` + popoutBorder}>
|
<div className={`cf w-100 h-100 flex ` + popoutBorder}>
|
||||||
<Sidebar
|
<Sidebar
|
||||||
popout={popout}
|
popout={popout}
|
||||||
@ -31,6 +34,7 @@ export class Skeleton extends Component {
|
|||||||
path={props.path}
|
path={props.path}
|
||||||
invites={props.invites}
|
invites={props.invites}
|
||||||
associations={props.associations}
|
associations={props.associations}
|
||||||
|
selectedGroups={props.selectedGroups}
|
||||||
/>
|
/>
|
||||||
<div className={"h-100 w-100 relative white-d flex-auto " + rightPanelHide} style={{
|
<div className={"h-100 w-100 relative white-d flex-auto " + rightPanelHide} style={{
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
|
@ -21,6 +21,7 @@ export class ResponseReducer {
|
|||||||
case "local":
|
case "local":
|
||||||
this.sidebarToggle(json, state);
|
this.sidebarToggle(json, state);
|
||||||
this.setSpinner(json, state);
|
this.setSpinner(json, state);
|
||||||
|
this.setSelected(json, state);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -210,5 +211,11 @@ export class ResponseReducer {
|
|||||||
state.spinner = json.data.spinner;
|
state.spinner = json.data.spinner;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setSelected(json, state) {
|
||||||
|
let data = _.has(json.data, 'selected', false);
|
||||||
|
if (data) {
|
||||||
|
state.selected = json.data.selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ class Store {
|
|||||||
},
|
},
|
||||||
permissions: {},
|
permissions: {},
|
||||||
invites: {},
|
invites: {},
|
||||||
|
selected: [],
|
||||||
spinner: false,
|
spinner: false,
|
||||||
sidebarShown: true
|
sidebarShown: true
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user