mirror of
https://github.com/urbit/shrub.git
synced 2024-12-01 06:35:32 +03:00
interface: removed unused links files
This commit is contained in:
parent
77b1db2d16
commit
97e1fa12a9
@ -232,29 +232,6 @@ export function stringToTa(string) {
|
|||||||
return '~.' + out;
|
return '~.' + out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// used in Links
|
|
||||||
|
|
||||||
export function makeRoutePath(
|
|
||||||
resource,
|
|
||||||
page = 0,
|
|
||||||
url = null,
|
|
||||||
index = 0,
|
|
||||||
compage = 0
|
|
||||||
) {
|
|
||||||
let route = '/~link' + resource;
|
|
||||||
if (!url) {
|
|
||||||
if (page !== 0) {
|
|
||||||
route = route + '/' + page;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
route = `${route}/${page}/${index}/${base64urlEncode(url)}`;
|
|
||||||
if (compage !== 0) {
|
|
||||||
route = route + '/' + compage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return route;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function amOwnerOfGroup(groupPath) {
|
export function amOwnerOfGroup(groupPath) {
|
||||||
if (!groupPath)
|
if (!groupPath)
|
||||||
return false;
|
return false;
|
||||||
|
@ -7,14 +7,13 @@ import { StoreState } from "~/logic/store/type";
|
|||||||
import { uxToHex } from '~/logic/lib/util';
|
import { uxToHex } from '~/logic/lib/util';
|
||||||
import { Association, GraphNode } from "~/types";
|
import { Association, GraphNode } from "~/types";
|
||||||
import { RouteComponentProps } from "react-router-dom";
|
import { RouteComponentProps } from "react-router-dom";
|
||||||
import { LinkList } from "./components/link-list";
|
|
||||||
import { LinkDetail } from "./components/link-detail";
|
|
||||||
|
|
||||||
import { LinkItem } from "./components/lib/link-item";
|
import { LinkItem } from "./components/link-item";
|
||||||
import { LinkSubmit } from "./components/lib/link-submit";
|
import { LinkSubmit } from "./components/link-submit";
|
||||||
import { LinkPreview } from "./components/lib/link-preview";
|
import { LinkPreview } from "./components/link-preview";
|
||||||
import { CommentSubmit } from "./components/lib/comment-submit";
|
import { CommentSubmit } from "./components/comment-submit";
|
||||||
import { Comments } from "./components/lib/comments";
|
import { Comments } from "./components/comments";
|
||||||
|
|
||||||
import "./css/custom.css";
|
import "./css/custom.css";
|
||||||
|
|
||||||
type LinkResourceProps = StoreState & {
|
type LinkResourceProps = StoreState & {
|
||||||
|
@ -1,227 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import { Switch, Route } from 'react-router-dom';
|
|
||||||
import Helmet from 'react-helmet';
|
|
||||||
|
|
||||||
import _ from 'lodash';
|
|
||||||
|
|
||||||
import './css/custom.css';
|
|
||||||
|
|
||||||
import { Skeleton } from './components/skeleton';
|
|
||||||
import { NewScreen } from './components/new';
|
|
||||||
import { SettingsScreen } from './components/settings';
|
|
||||||
import { MessageScreen } from './components/lib/message-screen';
|
|
||||||
import { LinkList } from './components/link-list';
|
|
||||||
import { LinkDetail } from './components/link-detail';
|
|
||||||
|
|
||||||
import {
|
|
||||||
amOwnerOfGroup,
|
|
||||||
base64urlDecode
|
|
||||||
} from '~/logic/lib/util';
|
|
||||||
|
|
||||||
|
|
||||||
export default class LinksApp extends Component {
|
|
||||||
componentDidMount() {
|
|
||||||
// preload spinner asset
|
|
||||||
new Image().src = '/~landscape/img/Spinner.png';
|
|
||||||
|
|
||||||
this.props.subscription.startApp('graph');
|
|
||||||
if (!this.props.sidebarShown) {
|
|
||||||
this.props.api.local.sidebarToggle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
this.props.subscription.stopApp('graph');
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { props } = this;
|
|
||||||
const contacts = props.contacts ? props.contacts : {};
|
|
||||||
const groups = props.groups ? props.groups : {};
|
|
||||||
const associations =
|
|
||||||
props.associations ? props.associations : { graph: {}, contacts: {} };
|
|
||||||
const graphKeys = props.graphKeys || new Set([]);
|
|
||||||
const graphs = props.graphs || {};
|
|
||||||
|
|
||||||
const invites = props.invites ?
|
|
||||||
props.invites : {};
|
|
||||||
|
|
||||||
const {
|
|
||||||
api, sidebarShown, s3,
|
|
||||||
hideAvatars, hideNicknames, remoteContentPolicy
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Helmet defer={false}>
|
|
||||||
<title>OS1 - Links</title>
|
|
||||||
</Helmet>
|
|
||||||
<Switch>
|
|
||||||
<Route exact path="/~link"
|
|
||||||
render={ (props) => (
|
|
||||||
<Skeleton
|
|
||||||
active="collections"
|
|
||||||
associations={associations}
|
|
||||||
invites={invites}
|
|
||||||
groups={groups}
|
|
||||||
rightPanelHide={true}
|
|
||||||
sidebarShown={sidebarShown}
|
|
||||||
api={api}
|
|
||||||
graphKeys={graphKeys}>
|
|
||||||
<MessageScreen text="Select or create a collection to begin." />
|
|
||||||
</Skeleton>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Route exact path="/~link/new"
|
|
||||||
render={ (props) => (
|
|
||||||
<Skeleton
|
|
||||||
associations={associations}
|
|
||||||
invites={invites}
|
|
||||||
groups={groups}
|
|
||||||
sidebarShown={sidebarShown}
|
|
||||||
api={api}
|
|
||||||
graphKeys={graphKeys}>
|
|
||||||
<NewScreen
|
|
||||||
api={api}
|
|
||||||
graphKeys={graphKeys}
|
|
||||||
associations={associations}
|
|
||||||
groups={groups}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
</Skeleton>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Route exact path="/~link/:ship/:name/settings"
|
|
||||||
render={ (props) => {
|
|
||||||
const resourcePath =
|
|
||||||
`${props.match.params.ship}/${props.match.params.name}`;
|
|
||||||
const metPath = `/ship/~${resourcePath}`;
|
|
||||||
const resource =
|
|
||||||
associations.graph[metPath] ?
|
|
||||||
associations.graph[metPath] : { metadata: {} };
|
|
||||||
|
|
||||||
const contactDetails = contacts[resource['group-path']] || {};
|
|
||||||
const group = groups[resource['group-path']] || new Set([]);
|
|
||||||
const amOwner = amOwnerOfGroup(resource['group-path']);
|
|
||||||
const hasGraph = !!graphs[resourcePath];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Skeleton
|
|
||||||
associations={associations}
|
|
||||||
invites={invites}
|
|
||||||
groups={groups}
|
|
||||||
selected={resourcePath}
|
|
||||||
sidebarShown={sidebarShown}
|
|
||||||
graphKeys={graphKeys}
|
|
||||||
api={api}>
|
|
||||||
<SettingsScreen
|
|
||||||
sidebarShown={sidebarShown}
|
|
||||||
resource={resource}
|
|
||||||
contacts={contacts}
|
|
||||||
contactDetails={contactDetails}
|
|
||||||
graphResource={graphKeys.has(resourcePath)}
|
|
||||||
hasGraph={!!hasGraph}
|
|
||||||
group={group}
|
|
||||||
amOwner={amOwner}
|
|
||||||
resourcePath={resourcePath}
|
|
||||||
api={api}
|
|
||||||
{...props} />
|
|
||||||
</Skeleton>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Route exact path="/~link/:ship/:name"
|
|
||||||
render={ (props) => {
|
|
||||||
const resourcePath =
|
|
||||||
`${props.match.params.ship}/${props.match.params.name}`;
|
|
||||||
const metPath = `/ship/~${resourcePath}`;
|
|
||||||
const resource =
|
|
||||||
associations.graph[metPath] ?
|
|
||||||
associations.graph[metPath] : { metadata: {} };
|
|
||||||
|
|
||||||
const contactDetails = contacts[resource['group-path']] || {};
|
|
||||||
const graph = graphs[resourcePath] || null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Skeleton
|
|
||||||
associations={associations}
|
|
||||||
invites={invites}
|
|
||||||
groups={groups}
|
|
||||||
selected={resourcePath}
|
|
||||||
sidebarShown={sidebarShown}
|
|
||||||
sidebarHideMobile={true}
|
|
||||||
api={api}
|
|
||||||
graphKeys={graphKeys}>
|
|
||||||
<LinkList
|
|
||||||
{...props}
|
|
||||||
api={api}
|
|
||||||
s3={s3}
|
|
||||||
graph={graph}
|
|
||||||
graphResource={graphKeys.has(resourcePath)}
|
|
||||||
resourcePath={resourcePath}
|
|
||||||
metadata={resource.metadata}
|
|
||||||
contacts={contactDetails}
|
|
||||||
hideAvatars={hideAvatars}
|
|
||||||
hideNicknames={hideNicknames}
|
|
||||||
sidebarShown={sidebarShown}
|
|
||||||
ship={props.match.params.ship}
|
|
||||||
name={props.match.params.name}
|
|
||||||
/>
|
|
||||||
</Skeleton>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Route exact path="/~link/:ship/:name/:index"
|
|
||||||
render={ (props) => {
|
|
||||||
const resourcePath =
|
|
||||||
`${props.match.params.ship}/${props.match.params.name}`;
|
|
||||||
const metPath = `/ship/~${resourcePath}`;
|
|
||||||
const resource =
|
|
||||||
associations.graph[metPath] ?
|
|
||||||
associations.graph[metPath] : { metadata: {} };
|
|
||||||
|
|
||||||
const contactDetails = contacts[resource['group-path']] || {};
|
|
||||||
|
|
||||||
const indexArr = props.match.params.index.split('-');
|
|
||||||
const graph = graphs[resourcePath] || null;
|
|
||||||
|
|
||||||
if (indexArr.length <= 1) {
|
|
||||||
return <div>Malformed URL</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const index = parseInt(indexArr[1], 10);
|
|
||||||
const node = Boolean(graph) ? graph.get(index) : null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Skeleton
|
|
||||||
associations={associations}
|
|
||||||
invites={invites}
|
|
||||||
groups={groups}
|
|
||||||
selected={resourcePath}
|
|
||||||
sidebarShown={sidebarShown}
|
|
||||||
sidebarHideMobile={true}
|
|
||||||
graphKeys={graphKeys}
|
|
||||||
api={api}>
|
|
||||||
<LinkDetail
|
|
||||||
{...props}
|
|
||||||
node={node}
|
|
||||||
graphResource={graphKeys.has(resourcePath)}
|
|
||||||
ship={props.match.params.ship}
|
|
||||||
name={props.match.params.name}
|
|
||||||
resource={resource}
|
|
||||||
contacts={contactDetails}
|
|
||||||
sidebarShown={sidebarShown}
|
|
||||||
api={api}
|
|
||||||
hideAvatars={hideAvatars}
|
|
||||||
hideNicknames={hideNicknames}
|
|
||||||
remoteContentPolicy={remoteContentPolicy} />
|
|
||||||
</Skeleton>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Switch>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
|
|
||||||
export class ChannelItem extends Component {
|
|
||||||
render() {
|
|
||||||
const { props } = this;
|
|
||||||
|
|
||||||
const selectedClass = (props.selected)
|
|
||||||
? 'bg-gray5 bg-gray1-d'
|
|
||||||
: 'pointer hover-bg-gray5 hover-bg-gray1-d';
|
|
||||||
|
|
||||||
const unseenCount = props.unseenCount > 0
|
|
||||||
? <span className="dib white bg-gray3 bg-gray2-d fw6 br1 absolute" style={{ padding: '1px 5px', right: 8 }}>{props.unseenCount}</span>
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link to={`/~link/${props.link}`}>
|
|
||||||
<div className={'w-100 v-mid f9 ph5 z1 pv1 relative ' + selectedClass}>
|
|
||||||
<p className="f9 dib">{props.name}</p>
|
|
||||||
<p className="f9 dib fr">
|
|
||||||
{unseenCount}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { GroupItem } from './group-item';
|
|
||||||
import SidebarInvite from '~/views/components/Sidebar/SidebarInvite';
|
|
||||||
import { Welcome } from './welcome';
|
|
||||||
import { alphabetiseAssociations } from '~/logic/lib/util';
|
|
||||||
|
|
||||||
export const ChannelSidebar = (props) => {
|
|
||||||
const sidebarInvites = Object.keys(props.invites)
|
|
||||||
.map((uid) => {
|
|
||||||
return (
|
|
||||||
<SidebarInvite
|
|
||||||
key={uid}
|
|
||||||
invite={props.invites[uid]}
|
|
||||||
onAccept={() => props.api.invite.accept('/link', uid)}
|
|
||||||
onDecline={() => props.api.invite.decline('/link', uid)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const associations = props.associations.contacts ?
|
|
||||||
alphabetiseAssociations(props.associations.contacts) : {};
|
|
||||||
|
|
||||||
const graphAssoc = props.associations.graph || {};
|
|
||||||
|
|
||||||
const groupedChannels = {};
|
|
||||||
[...props.graphKeys].map((gKey) => {
|
|
||||||
const path = `/ship/~${gKey.split('/')[0]}/${gKey.split('/')[1]}`;
|
|
||||||
const groupPath = graphAssoc[path] ? graphAssoc[path]['group-path'] : '';
|
|
||||||
|
|
||||||
if (groupPath in associations) {
|
|
||||||
// managed
|
|
||||||
|
|
||||||
if (groupedChannels[groupPath]) {
|
|
||||||
const array = groupedChannels[groupPath];
|
|
||||||
array.push(path);
|
|
||||||
groupedChannels[groupPath] = array;
|
|
||||||
} else {
|
|
||||||
groupedChannels[groupPath] = [path];
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// unmanaged
|
|
||||||
|
|
||||||
if (groupedChannels['/~/']) {
|
|
||||||
const array = groupedChannels['/~/'];
|
|
||||||
array.push(path);
|
|
||||||
groupedChannels['/~/'] = array;
|
|
||||||
} else {
|
|
||||||
groupedChannels['/~/'] = [path];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const groupedItems = Object.keys(associations).map((each, i) => {
|
|
||||||
const channels = groupedChannels[each];
|
|
||||||
if (!channels || channels.length === 0) { return; }
|
|
||||||
|
|
||||||
return (
|
|
||||||
<GroupItem
|
|
||||||
key={i + 1}
|
|
||||||
unmanaged={false}
|
|
||||||
association={associations[each]}
|
|
||||||
metadata={graphAssoc}
|
|
||||||
channels={channels}
|
|
||||||
selected={props.selected}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (groupedChannels['/~/'] && groupedChannels['/~/'].length !== 0) {
|
|
||||||
groupedItems.push(
|
|
||||||
<GroupItem
|
|
||||||
key={0}
|
|
||||||
unmanaged={true}
|
|
||||||
association={'/~/'}
|
|
||||||
metadata={graphAssoc}
|
|
||||||
channels={groupedChannels['/~/']}
|
|
||||||
selected={props.selected}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const activeClasses = (props.active === 'collections') ? ' ' : 'dn-s ';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={
|
|
||||||
`bn br-m br-l br-xl b--gray4 b--gray1-d lh-copy h-100` +
|
|
||||||
`flex-shrink-0 mw5-m mw5-l mw5-xl pt3 pt0-m pt0-l pt0-xl relative ` +
|
|
||||||
activeClasses +
|
|
||||||
((props.sidebarShown) ? 'flex-basis-100-s flex-basis-30-ns' : 'dn')
|
|
||||||
}>
|
|
||||||
<div className="overflow-y-scroll h-100">
|
|
||||||
<div className="w-100 bg-transparent">
|
|
||||||
<Link
|
|
||||||
className="dib f9 pointer green2 gray4-d pa4"
|
|
||||||
to={'/~link/new'}>
|
|
||||||
New Collection
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
<Welcome associations={props.associations} />
|
|
||||||
{sidebarInvites}
|
|
||||||
{groupedItems}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import { ChannelItem } from './channel-item';
|
|
||||||
import { deSig } from '~/logic/lib/util';
|
|
||||||
|
|
||||||
|
|
||||||
export const GroupItem = (props) => {
|
|
||||||
const association = props.association ? props.association : {};
|
|
||||||
|
|
||||||
let title =
|
|
||||||
association['app-path'] ? association['app-path'] : 'Unmanaged Collections';
|
|
||||||
|
|
||||||
if (association.metadata && association.metadata.title) {
|
|
||||||
title = association.metadata.title !== ''
|
|
||||||
? association.metadata.title : title;
|
|
||||||
}
|
|
||||||
|
|
||||||
const channels = props.channels ? props.channels : [];
|
|
||||||
const unmanaged = props.unmanaged ? 'pt6' : 'pt1';
|
|
||||||
|
|
||||||
const channelItems = channels.map((each, i) => {
|
|
||||||
const meta = props.metadata[each];
|
|
||||||
if (!meta) { return null; }
|
|
||||||
const link = `${deSig(each.split('/')[2])}/${each.split('/')[3]}`;
|
|
||||||
|
|
||||||
const selected = (props.selected === each);
|
|
||||||
return (
|
|
||||||
<ChannelItem
|
|
||||||
key={each}
|
|
||||||
link={link}
|
|
||||||
selected={selected}
|
|
||||||
name={meta.metadata.title}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={unmanaged}>
|
|
||||||
<p className="f9 ph4 pb2 gray3">{title}</p>
|
|
||||||
{channelItems}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import { Sigil } from '~/logic/lib/sigil';
|
|
||||||
import { uxToHex, cite } from '~/logic/lib/util';
|
|
||||||
export class MemberElement extends Component {
|
|
||||||
onRemove() {
|
|
||||||
const { props } = this;
|
|
||||||
props.api.groups.remove(props.groupPath, [`~${props.ship}`]);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { props } = this;
|
|
||||||
|
|
||||||
let actionElem;
|
|
||||||
if (props.ship === props.owner) {
|
|
||||||
actionElem = (
|
|
||||||
<p className="w-20 dib list-ship black white-d f8 c-default">
|
|
||||||
Host
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
} else if (props.amOwner && window.ship !== props.ship) {
|
|
||||||
actionElem = (
|
|
||||||
<a onClick={this.onRemove.bind(this)}
|
|
||||||
className="w-20 dib list-ship black white-d f8 pointer"
|
|
||||||
>
|
|
||||||
Ban
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
actionElem = (
|
|
||||||
<span></span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const name = props.contact
|
|
||||||
? `${props.contact.nickname} (${cite(props.ship)})`
|
|
||||||
: `${cite(props.ship)}`;
|
|
||||||
const color = props.contact ? uxToHex(props.contact.color) : '000000';
|
|
||||||
|
|
||||||
const img = props.contact.avatar
|
|
||||||
? <img src={props.contact.avatar} height={32} width={32} className="dib" />
|
|
||||||
: <Sigil ship={props.ship} size={32} color={`#${color}`} />;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex mb2">
|
|
||||||
{img}
|
|
||||||
<p className={'w-70 mono list-ship dib v-mid black white-d ml2 nowrap f8'}
|
|
||||||
title={props.ship}
|
|
||||||
>
|
|
||||||
{name}
|
|
||||||
</p>
|
|
||||||
{actionElem}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
|
|
||||||
export class MessageScreen extends Component {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="h-100 w-100 overflow-x-hidden flex flex-column bg-white bg-gray0-d dn db-ns">
|
|
||||||
<div className="pl3 pr3 pt2 dt pb3 w-100 h-100">
|
|
||||||
<p className="f8 pt3 gray2 w-100 h-100 dtc v-mid tc">
|
|
||||||
{this.props.text}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { makeRoutePath } from '~/logic/lib/util';
|
|
||||||
|
|
||||||
export class Pagination extends Component {
|
|
||||||
render() {
|
|
||||||
const props = this.props;
|
|
||||||
|
|
||||||
const prevPage = (Number(props.page) - 1);
|
|
||||||
const nextPage = (Number(props.page) + 1);
|
|
||||||
|
|
||||||
const prevDisplay = ((props.currentPage > 0))
|
|
||||||
? 'dib absolute left-0'
|
|
||||||
: 'dn';
|
|
||||||
|
|
||||||
const nextDisplay = ((props.currentPage + 1) < props.totalPages)
|
|
||||||
? 'dib absolute right-0'
|
|
||||||
: 'dn';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="w-100 inter relative pv6">
|
|
||||||
<div className={prevDisplay + ' inter f8'}>
|
|
||||||
<Link to={makeRoutePath(props.resourcePath, prevPage)}>
|
|
||||||
<- Previous Page
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
<div className={nextDisplay + ' inter f8'}>
|
|
||||||
<Link to={makeRoutePath(props.resourcePath, nextPage)}>
|
|
||||||
Next Page ->
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Pagination;
|
|
@ -1,41 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
|
|
||||||
export class Welcome extends Component {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.state = {
|
|
||||||
show: true
|
|
||||||
};
|
|
||||||
this.disableWelcome = this.disableWelcome.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
disableWelcome() {
|
|
||||||
this.setState({ show: false });
|
|
||||||
localStorage.setItem('urbit-link:wasWelcomed', JSON.stringify(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
let wasWelcomed = localStorage.getItem('urbit-link:wasWelcomed');
|
|
||||||
if (wasWelcomed === null) {
|
|
||||||
localStorage.setItem('urbit-link:wasWelcomed', JSON.stringify(false));
|
|
||||||
return wasWelcomed = false;
|
|
||||||
} else {
|
|
||||||
wasWelcomed = JSON.parse(wasWelcomed);
|
|
||||||
}
|
|
||||||
|
|
||||||
const associations = this.props.associations ? this.props.associations : {};
|
|
||||||
|
|
||||||
return ((!wasWelcomed && this.state.show) && (associations.length !== 0)) ? (
|
|
||||||
<div className="ma4 pa2 bg-welcome-green bg-gray1-d white-d">
|
|
||||||
<p className="f8 lh-copy">Links are for collecting and discussing outside content. Each post is a URL and a comment thread.</p>
|
|
||||||
<p className="f8 pt2 dib bb pointer"
|
|
||||||
onClick={(() => this.disableWelcome())}
|
|
||||||
>
|
|
||||||
Close this
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
) : <div />;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Welcome;
|
|
@ -1,100 +0,0 @@
|
|||||||
import React, { useEffect } from 'react';
|
|
||||||
import { TabBar } from '~/views/components/chat-link-tabbar';
|
|
||||||
import { LinkPreview } from './lib/link-preview';
|
|
||||||
import { CommentSubmit } from './lib/comment-submit';
|
|
||||||
import { SidebarSwitcher } from '~/views/components/SidebarSwitch';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { Comments } from './lib/comments';
|
|
||||||
import { getContactDetails } from '~/logic/lib/util';
|
|
||||||
|
|
||||||
import { Box } from '@tlon/indigo-react';
|
|
||||||
|
|
||||||
export const LinkDetail = (props) => {
|
|
||||||
if (!props.node && props.graphResource) {
|
|
||||||
useEffect(() => {
|
|
||||||
props.api.graph.getGraph(
|
|
||||||
`~${props.match.params.ship}`,
|
|
||||||
props.match.params.name
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>Loading...</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!props.node) {
|
|
||||||
return (
|
|
||||||
<div>Not found</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { nickname } = getContactDetails(props.contacts[props.node?.post?.author]);
|
|
||||||
const resourcePath = `${props.ship}/${props.name}`;
|
|
||||||
const title = props.resource.metadata.title || resourcePath;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="h-100 w-100 overflow-hidden flex flex-column">
|
|
||||||
<Box
|
|
||||||
pl='12px'
|
|
||||||
pt='2'
|
|
||||||
display='flex'
|
|
||||||
position='relative'
|
|
||||||
overflowX={['scroll', 'auto']}
|
|
||||||
flexShrink='0'
|
|
||||||
borderBottom='1px solid'
|
|
||||||
borderColor='washedGray'
|
|
||||||
height='48px'
|
|
||||||
>
|
|
||||||
<SidebarSwitcher
|
|
||||||
sidebarShown={props.sidebarShown}
|
|
||||||
api={props.api}
|
|
||||||
/>
|
|
||||||
<Link className="dib f9 fw4 pt2 gray2 lh-solid"
|
|
||||||
to={`/~link/${resourcePath}`}
|
|
||||||
>
|
|
||||||
<h2
|
|
||||||
className="dib f9 fw4 lh-solid v-top black white-d"
|
|
||||||
style={{ width: 'max-content' }}
|
|
||||||
>
|
|
||||||
{`${title}`}
|
|
||||||
</h2>
|
|
||||||
</Link>
|
|
||||||
<TabBar
|
|
||||||
location={props.location}
|
|
||||||
settings={`/~link/${resourcePath}/settings`}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<div className="w-100 mt2 flex justify-center overflow-y-scroll ph4 pb4">
|
|
||||||
<div className="w-100 mw7">
|
|
||||||
<LinkPreview
|
|
||||||
resourcePath={resourcePath}
|
|
||||||
post={props.node.post}
|
|
||||||
nickname={nickname}
|
|
||||||
hideNicknames={props.hideNicknames}
|
|
||||||
commentNumber={props.node.children.size}
|
|
||||||
remoteContentPolicy={props.remoteContentPolicy}
|
|
||||||
/>
|
|
||||||
<div className="flex">
|
|
||||||
<CommentSubmit
|
|
||||||
name={props.name}
|
|
||||||
ship={props.ship}
|
|
||||||
api={props.api}
|
|
||||||
parentIndex={props.node.post.index}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Comments
|
|
||||||
comments={props.node.children}
|
|
||||||
resourcePath={resourcePath}
|
|
||||||
contacts={props.contacts}
|
|
||||||
api={props.api}
|
|
||||||
hideAvatars={props.hideAvatars}
|
|
||||||
hideNicknames={props.hideNicknames}
|
|
||||||
remoteContentPolicy={props.remoteContentPolicy}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -33,7 +33,7 @@ export const LinkItem = (props) => {
|
|||||||
? <img src={props.avatar} height={36} width={36} className="dib" />
|
? <img src={props.avatar} height={36} width={36} className="dib" />
|
||||||
: <Sigil ship={`~${author}`} size={36} color={'#' + props.color} />;
|
: <Sigil ship={`~${author}`} size={36} color={'#' + props.color} />;
|
||||||
|
|
||||||
const baseUrl = props.baseUrl || `/~link/${resource}`;
|
const baseUrl = props.baseUrl || `/~404/${resource}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row minWidth='0' flexShrink='0' width="100%" alignItems="center" py={3} bg="white">
|
<Row minWidth='0' flexShrink='0' width="100%" alignItems="center" py={3} bg="white">
|
@ -1,91 +0,0 @@
|
|||||||
import React, { useEffect } from "react";
|
|
||||||
|
|
||||||
import { TabBar } from '~/views/components/chat-link-tabbar';
|
|
||||||
import { SidebarSwitcher } from '~/views/components/SidebarSwitch';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { LinkItem } from './lib/link-item';
|
|
||||||
import LinkSubmit from './lib/link-submit';
|
|
||||||
import { Box } from '@tlon/indigo-react';
|
|
||||||
|
|
||||||
import { getContactDetails } from "~/logic/lib/util";
|
|
||||||
|
|
||||||
export const LinkList = (props) => {
|
|
||||||
const resource = `${props.ship}/${props.name}`;
|
|
||||||
const title = props.metadata.title || resource;
|
|
||||||
useEffect(() => {
|
|
||||||
props.api.graph.getGraph(
|
|
||||||
`~${props.match.params.ship}`,
|
|
||||||
props.match.params.name
|
|
||||||
);
|
|
||||||
}, [props.match.params.ship, props.match.params.name]);
|
|
||||||
|
|
||||||
if (!props.graph && props.graphResource) {
|
|
||||||
return <div>Loading...</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!props.graph) {
|
|
||||||
return <div>Not found</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="h-100 w-100 overflow-hidden flex flex-column">
|
|
||||||
<div
|
|
||||||
className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8"
|
|
||||||
style={{ height: "1rem" }}
|
|
||||||
>
|
|
||||||
<Link to="/~link">{"⟵ All Channels"}</Link>
|
|
||||||
</div>
|
|
||||||
<Box
|
|
||||||
pl='12px'
|
|
||||||
pt='2'
|
|
||||||
display='flex'
|
|
||||||
position='relative'
|
|
||||||
overflowX={['scroll', 'auto']}
|
|
||||||
flexShrink='0'
|
|
||||||
borderBottom='1px solid'
|
|
||||||
borderColor='washedGray'
|
|
||||||
height='48px'>
|
|
||||||
<SidebarSwitcher
|
|
||||||
sidebarShown={props.sidebarShown}
|
|
||||||
api={props.api} />
|
|
||||||
<h2
|
|
||||||
className="dib f9 fw4 pt2 lh-solid v-top black white-d"
|
|
||||||
style={{ width: 'max-content' }}>
|
|
||||||
{title}
|
|
||||||
</h2>
|
|
||||||
<TabBar
|
|
||||||
location={props.location}
|
|
||||||
settings={`/~link/${resource}/settings`}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<div className="w-100 mt6 flex justify-center overflow-y-scroll ph4 pb4">
|
|
||||||
<div className="w-100 mw7">
|
|
||||||
<div className="flex">
|
|
||||||
<LinkSubmit
|
|
||||||
name={props.name}
|
|
||||||
ship={props.ship}
|
|
||||||
api={props.api}
|
|
||||||
s3={props.s3} />
|
|
||||||
</div>
|
|
||||||
{ Array.from(props.graph).map(([date, node]) => {
|
|
||||||
const { nickname, color, avatar } =
|
|
||||||
getContactDetails(props.contacts[node?.post?.author]);
|
|
||||||
return (
|
|
||||||
<LinkItem
|
|
||||||
key={date}
|
|
||||||
resource={resource}
|
|
||||||
node={node}
|
|
||||||
nickname={nickname}
|
|
||||||
color={color}
|
|
||||||
avatar={avatar}
|
|
||||||
hideAvatars={props.hideAvatars}
|
|
||||||
hideNicknames={props.hideNicknames}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,8 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import { MessageScreen } from './lib/message-screen';
|
|
||||||
|
|
||||||
export class LoadingScreen extends Component {
|
|
||||||
render() {
|
|
||||||
return (<MessageScreen text="Loading..." />);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
import React, { useCallback } from "react";
|
|
||||||
import { RouteComponentProps } from "react-router-dom";
|
|
||||||
import { Box, ManagedTextInputField as Input, Col } from "@tlon/indigo-react";
|
|
||||||
import { Formik, Form } from "formik";
|
|
||||||
import * as Yup from "yup";
|
|
||||||
|
|
||||||
import { AsyncButton } from "~/views/components/AsyncButton";
|
|
||||||
import { FormError } from "~/views/components/FormError";
|
|
||||||
import GroupSearch from "~/views/components/GroupSearch";
|
|
||||||
|
|
||||||
import GlobalApi from "~/logic/api/global";
|
|
||||||
import { stringToSymbol } from "~/logic/lib/util";
|
|
||||||
import { useWaitForProps } from "~/logic/lib/useWaitForProps";
|
|
||||||
|
|
||||||
import { Associations } from "~/types/metadata-update";
|
|
||||||
import { Notebooks } from "~/types/publish-update";
|
|
||||||
import { Groups, GroupPolicy } from "~/types/group-update";
|
|
||||||
|
|
||||||
const formSchema = Yup.object({
|
|
||||||
name: Yup.string().required("Collection must have a name"),
|
|
||||||
description: Yup.string(),
|
|
||||||
group: Yup.string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
export function NewScreen(props: object) {
|
|
||||||
const { history, api } = props;
|
|
||||||
const waiter = useWaitForProps(props, 5000);
|
|
||||||
|
|
||||||
const onSubmit = async (values: object, actions) => {
|
|
||||||
const resourceId = stringToSymbol(values.name);
|
|
||||||
try {
|
|
||||||
const { name, description, group } = values;
|
|
||||||
if (!!group) {
|
|
||||||
await props.api.graph.createManagedGraph(
|
|
||||||
resourceId,
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
group,
|
|
||||||
"link"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
await props.api.graph.createUnmanagedGraph(
|
|
||||||
resourceId,
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
{ invite: { pending: [] } },
|
|
||||||
"link"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await waiter((p) => p?.graphKeys?.has(`${window.ship}/${resourceId}`));
|
|
||||||
actions.setStatus({ success: null });
|
|
||||||
history.push(`/~link/${window.ship}/${resourceId}`);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
actions.setStatus({ error: "Collection creation failed" });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Col p={3}>
|
|
||||||
<Box mb={4} color="black">New Collection</Box>
|
|
||||||
<Formik
|
|
||||||
validationSchema={formSchema}
|
|
||||||
initialValues={{ name: "", description: "", group: "" }}
|
|
||||||
onSubmit={onSubmit}>
|
|
||||||
<Form>
|
|
||||||
<Box
|
|
||||||
display="grid"
|
|
||||||
gridTemplateRows="auto"
|
|
||||||
gridRowGap={4}
|
|
||||||
gridTemplateColumns="300px">
|
|
||||||
<Input
|
|
||||||
id="name"
|
|
||||||
label="Name"
|
|
||||||
caption="Provide a name for your collection"
|
|
||||||
placeholder="eg. My Links"
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
id="description"
|
|
||||||
label="Description"
|
|
||||||
caption="What's your collection about?"
|
|
||||||
placeholder="Collection description"
|
|
||||||
/>
|
|
||||||
<GroupSearch
|
|
||||||
id="group"
|
|
||||||
label="Group"
|
|
||||||
caption="What group is the collection for?"
|
|
||||||
associations={props.associations}
|
|
||||||
/>
|
|
||||||
<Box justifySelf="start">
|
|
||||||
<AsyncButton loadingText="Creating..." type="submit" border>
|
|
||||||
Create Collection
|
|
||||||
</AsyncButton>
|
|
||||||
</Box>
|
|
||||||
<FormError message="Collection creation failed" />
|
|
||||||
</Box>
|
|
||||||
</Form>
|
|
||||||
</Formik>
|
|
||||||
</Col>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default NewScreen;
|
|
@ -1,184 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { LoadingScreen } from './loading';
|
|
||||||
import { Spinner } from '~/views/components/Spinner';
|
|
||||||
import { TabBar } from '~/views/components/chat-link-tabbar';
|
|
||||||
import SidebarSwitcher from '~/views/components/SidebarSwitch';
|
|
||||||
|
|
||||||
import { MetadataSettings } from '~/views/components/metadata/settings';
|
|
||||||
|
|
||||||
import { Box, Text, Button, Col, Row } from '@tlon/indigo-react';
|
|
||||||
|
|
||||||
export class SettingsScreen extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
isLoading: false,
|
|
||||||
awaiting: false,
|
|
||||||
type: 'Editing'
|
|
||||||
};
|
|
||||||
|
|
||||||
this.renderDelete = this.renderDelete.bind(this);
|
|
||||||
this.changeLoading = this.changeLoading.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
const { props, state } = this;
|
|
||||||
|
|
||||||
if (Boolean(state.isLoading) && !props.resource) {
|
|
||||||
this.setState({
|
|
||||||
isLoading: false
|
|
||||||
}, () => {
|
|
||||||
props.history.push('/~link');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
changeLoading(isLoading, awaiting, type, closure) {
|
|
||||||
this.setState({
|
|
||||||
isLoading,
|
|
||||||
awaiting,
|
|
||||||
type
|
|
||||||
}, closure);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeCollection() {
|
|
||||||
const { props } = this;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
isLoading: true,
|
|
||||||
awaiting: true,
|
|
||||||
type: 'Removing'
|
|
||||||
});
|
|
||||||
|
|
||||||
props.api.graph.leaveGraph(
|
|
||||||
`~${props.match.params.ship}`,
|
|
||||||
props.match.params.name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteCollection() {
|
|
||||||
const { props } = this;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
isLoading: true,
|
|
||||||
awaiting: true,
|
|
||||||
type: 'Deleting'
|
|
||||||
});
|
|
||||||
|
|
||||||
props.api.graph.deleteGraph(props.match.params.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderRemove() {
|
|
||||||
const { props } = this;
|
|
||||||
|
|
||||||
if (props.amOwner) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<Box width='100%' mt='3'>
|
|
||||||
<Text display='block' mt='3' fontSize='1' mb='1'>Remove Collection</Text>
|
|
||||||
<Text display='block' fontSize='0' gray mb='4'>
|
|
||||||
Remove this collection from your collection list
|
|
||||||
</Text>
|
|
||||||
<Button onClick={this.removeCollection.bind(this)}>
|
|
||||||
Remove collection
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderDelete() {
|
|
||||||
const { props } = this;
|
|
||||||
|
|
||||||
if (!props.amOwner) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<Box width='100%' mt='3'>
|
|
||||||
<Text fontSize='1' mt='3' display='block' mb='1'>Delete collection</Text>
|
|
||||||
<Text fontSize='0' gray display='block' mb='4'>
|
|
||||||
Delete this collection, for you and all group members
|
|
||||||
</Text>
|
|
||||||
<Button primary onClick={this.deleteCollection.bind(this)} destructive mb='4'>
|
|
||||||
Delete collection
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { props, state } = this;
|
|
||||||
const title = props.resource.metadata.title || props.resourcePath;
|
|
||||||
|
|
||||||
if (
|
|
||||||
(!props.hasGraph || !props.resource.metadata.color)
|
|
||||||
&& props.graphResource
|
|
||||||
) {
|
|
||||||
return <LoadingScreen />;
|
|
||||||
} else if (!props.graphResource) {
|
|
||||||
props.history.push('/~link');
|
|
||||||
return <Box />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Col height='100%' width='100' overflowX='hidden'>
|
|
||||||
<Box width='100%' display={['block', 'none']} pt='4' pb='6' pl='3' fontSize='1' height='1rem'>
|
|
||||||
<Link to="/~link">{'⟵ All Collections'}</Link>
|
|
||||||
</Box>
|
|
||||||
<Row
|
|
||||||
pl='12px'
|
|
||||||
pt='2'
|
|
||||||
borderBottom='1px solid'
|
|
||||||
borderColor='washedGray'
|
|
||||||
flexShrink='0'
|
|
||||||
overflowX={['scroll', 'auto']}
|
|
||||||
height='48px'
|
|
||||||
>
|
|
||||||
<SidebarSwitcher
|
|
||||||
sidebarShown={this.props.sidebarShown}
|
|
||||||
api={this.props.api}
|
|
||||||
/>
|
|
||||||
<Link className="dib f9 fw4 pt2 gray2 lh-solid"
|
|
||||||
to={`/~link/${props.resourcePath}`}>
|
|
||||||
<Text
|
|
||||||
display='inline-block'
|
|
||||||
fontSize='0'
|
|
||||||
verticalAlign='top'
|
|
||||||
width='max-content'>
|
|
||||||
{title}
|
|
||||||
</Text>
|
|
||||||
</Link>
|
|
||||||
<TabBar
|
|
||||||
location={props.location}
|
|
||||||
settings={`/~link/${props.resourcePath}/settings`}
|
|
||||||
/>
|
|
||||||
</Row>
|
|
||||||
<Box width='100' pl='3' mt='3'>
|
|
||||||
<Text display='block' fontSize='1' pb='2'>Collection Settings</Text>
|
|
||||||
{this.renderRemove()}
|
|
||||||
{this.renderDelete()}
|
|
||||||
<MetadataSettings
|
|
||||||
isOwner={props.amOwner}
|
|
||||||
changeLoading={this.changeLoading}
|
|
||||||
api={props.api}
|
|
||||||
association={props.resource}
|
|
||||||
resource="collection"
|
|
||||||
app="graph"
|
|
||||||
module="link"
|
|
||||||
/>
|
|
||||||
<Spinner
|
|
||||||
awaiting={this.state.awaiting}
|
|
||||||
classes="absolute right-1 bottom-1 pa2 ba b--black b--gray0-d white-d"
|
|
||||||
text={this.state.type}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Col>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import { ChannelSidebar } from './lib/channel-sidebar';
|
|
||||||
import ErrorBoundary from '~/views/components/ErrorBoundary';
|
|
||||||
|
|
||||||
export class Skeleton extends Component {
|
|
||||||
render() {
|
|
||||||
const { props } = this;
|
|
||||||
const rightPanelHide = props.rightPanelHide ? 'dn-s' : '';
|
|
||||||
|
|
||||||
const linkInvites = ('/link' in props.invites)
|
|
||||||
? props.invites['/link'] : {};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='absolute w-100 ph4-m ph4-l ph4-xl pb4-m pb4-l pb4-xl'
|
|
||||||
style={{ height: 'calc(100% - 45px)' }}>
|
|
||||||
<div className='bg-white bg-gray0-d cf w-100 h-100 flex ba-m ba-l ba-xl b--gray4 b--gray1-d br1'>
|
|
||||||
<ChannelSidebar
|
|
||||||
active={props.active}
|
|
||||||
associations={props.associations}
|
|
||||||
invites={linkInvites}
|
|
||||||
groups={props.groups}
|
|
||||||
selected={props.selected}
|
|
||||||
sidebarShown={props.sidebarShown}
|
|
||||||
api={props.api}
|
|
||||||
graphKeys={props.graphKeys} />
|
|
||||||
<div className={'h-100 w-100 flex-auto relative ' + rightPanelHide}
|
|
||||||
style={{ flexGrow: 1 }}>
|
|
||||||
<ErrorBoundary>
|
|
||||||
{props.children}
|
|
||||||
</ErrorBoundary>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { Box } from '@tlon/indigo-react';
|
|
||||||
|
|
||||||
export const TabBar = (props) => {
|
|
||||||
const {
|
|
||||||
location,
|
|
||||||
settings,
|
|
||||||
} = props;
|
|
||||||
let setColor = '';
|
|
||||||
|
|
||||||
if (location.pathname.includes('/settings')) {
|
|
||||||
setColor = 'black white-d';
|
|
||||||
} else {
|
|
||||||
setColor = 'gray3';
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box display='inline-block' flexShrink='0' flexGrow='1'>
|
|
||||||
<Box display='inline-block' pt='9px' fontSize='0' pl='16px' pr='6'>
|
|
||||||
<Link
|
|
||||||
className={'no-underline ' + setColor}
|
|
||||||
to={settings}>
|
|
||||||
Settings
|
|
||||||
</Link>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user