mirror of
https://github.com/indentlabs/notebook.git
synced 2025-10-26 11:19:22 +00:00
348 lines
11 KiB
JavaScript
348 lines
11 KiB
JavaScript
/*
|
|
Usage:
|
|
<%= react_component("PageLookupSidebar", {document_id: @document.id}) %>
|
|
*/
|
|
|
|
import React from "react"
|
|
import PropTypes from "prop-types"
|
|
|
|
import Drawer from '@material-ui/core/Drawer';
|
|
import List from '@material-ui/core/List';
|
|
import Divider from '@material-ui/core/Divider';
|
|
import ListItem from '@material-ui/core/ListItem';
|
|
import ListItemText from '@material-ui/core/ListItemText';
|
|
import ListSubheader from '@material-ui/core/ListSubheader';
|
|
import Chip from '@material-ui/core/Chip';
|
|
import SimpleFormat from './SimpleFormat.js';
|
|
|
|
import ExpandLess from '@material-ui/icons/ExpandLess';
|
|
import ExpandMore from '@material-ui/icons/ExpandMore';
|
|
import Collapse from '@material-ui/core/Collapse';
|
|
|
|
var pluralize = require('pluralize');
|
|
|
|
import axios from 'axios';
|
|
|
|
class PageLookupSidebar extends React.Component {
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
open: false,
|
|
loading: false,
|
|
show_data: false,
|
|
category_open: {}
|
|
};
|
|
}
|
|
|
|
classIcon(class_name) {
|
|
return window.ContentTypeData[class_name].icon;
|
|
}
|
|
|
|
classColor(class_name) {
|
|
return window.ContentTypeData[class_name].color;
|
|
}
|
|
|
|
async loadPage(page_type, page_id) {
|
|
this.setDrawerVisible(true);
|
|
this.setState({
|
|
show_data: false,
|
|
category_open: {}
|
|
});
|
|
|
|
// make api request
|
|
await axios.get(
|
|
"/api/v1/" + page_type.toLowerCase() + "/" + page_id
|
|
+ '?application_token=4756de490e82956dc6329e6650aaec664e27ccd27e153e2f'
|
|
+ '&authorization_token=167bb93139303904cf67f6480a29e71c9f1eaf7a28e902e1',
|
|
{
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json'
|
|
}
|
|
}
|
|
).then(response => {
|
|
// load response into list
|
|
this.setState({
|
|
page_data: response.data,
|
|
show_data: !response.data.hasOwnProperty('error'),
|
|
page_type: page_type,
|
|
page_id: page_id
|
|
});
|
|
|
|
}).catch(err => {
|
|
console.log(err);
|
|
this.setDrawerVisible(false);
|
|
|
|
return null;
|
|
});
|
|
};
|
|
|
|
content_page_view_path(content_type, content_id) {
|
|
return '/plan/' + pluralize(content_type.toLowerCase()) + '/' + content_id;
|
|
};
|
|
|
|
content_page_edit_path(content_type, content_id) {
|
|
return '/plan/' + pluralize(content_type.toLowerCase()) + '/' + content_id + '/edit';
|
|
};
|
|
|
|
content_page_tag_path(content_type, tag_slug) {
|
|
return '/plan/' + pluralize(content_type.toLowerCase()) + '/tagged/' + tag_slug;
|
|
}
|
|
|
|
link_destroy_path(document_id, page_type, page_id) {
|
|
return '/documents/' + document_id + '/unlink/' + page_type + '/' + page_id;
|
|
}
|
|
|
|
setDrawerVisible(open) {
|
|
this.setState({ open: open });
|
|
};
|
|
|
|
toggleCategoryOpen(category) {
|
|
this.setState({ category_open: {
|
|
[category]: !this.state.category_open[category]
|
|
}});
|
|
};
|
|
|
|
fieldData(field) {
|
|
switch (field.type) {
|
|
case "name":
|
|
case "text_area":
|
|
// console.log(field.value);
|
|
return (
|
|
<React.Fragment key={field.id}>
|
|
<ListSubheader component="div" style={{lineHeight: '1.5em'}}>
|
|
{field.label}
|
|
</ListSubheader>
|
|
<ListItem>
|
|
<SimpleFormat text={ field.value } />
|
|
</ListItem>
|
|
</React.Fragment>
|
|
);
|
|
|
|
case "link":
|
|
return(
|
|
<React.Fragment key={field.id}>
|
|
<ListSubheader component="div" style={{lineHeight: '1.5em'}}>
|
|
{ pluralize(field.label, field.value.length, true) }
|
|
</ListSubheader>
|
|
{field.value.map((link) => (
|
|
<ListItem button key={link.id} onClick={() => { this.loadPage(link.page_type, link.id); }}>
|
|
<ListItemText primary={
|
|
<div>
|
|
<i className={this.classColor(link.page_type) + '-text material-icons left'}>
|
|
{this.classIcon(link.page_type)}
|
|
</i>
|
|
{ link.name }
|
|
</div>
|
|
} />
|
|
</ListItem>
|
|
))}
|
|
</React.Fragment>
|
|
);
|
|
|
|
case "universe":
|
|
// console.log(field.value);
|
|
return(
|
|
<React.Fragment key={field.value.id}>
|
|
<ListSubheader component="div" style={{lineHeight: '1.5em'}}>
|
|
Universe
|
|
</ListSubheader>
|
|
<ListItem button onClick={() => { this.loadPage('Universe', field.id); }}>
|
|
<ListItemText primary={
|
|
<div>
|
|
<i className={this.classColor('Universe') + '-text material-icons left'}>
|
|
{this.classIcon('Universe')}
|
|
</i>
|
|
{ this.state.page_data.universe.name }
|
|
</div>
|
|
} />
|
|
</ListItem>
|
|
</React.Fragment>
|
|
);
|
|
|
|
case "tags":
|
|
return(
|
|
<React.Fragment>
|
|
<ListSubheader component="div" style={{lineHeight: '1.5em'}}>
|
|
Tags
|
|
</ListSubheader>
|
|
<ListItem>
|
|
{field.value.map((tag) => {
|
|
return(
|
|
<Chip
|
|
variant="outlined"
|
|
size="small"
|
|
label={tag.tag}
|
|
component="a"
|
|
href={this.content_page_tag_path(this.state.page_type, tag.slug)}
|
|
style={{marginRight: '0.25em'}}
|
|
clickable
|
|
/>
|
|
);
|
|
})}
|
|
</ListItem>
|
|
</React.Fragment>
|
|
);
|
|
|
|
default:
|
|
return(
|
|
<div>error loading {field.label}</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
pageData() {
|
|
if (this.state.show_data) {
|
|
return (
|
|
<div
|
|
role="presentation"
|
|
>
|
|
<List
|
|
subheader={
|
|
<h5>
|
|
<i className="right"> </i>
|
|
<i className={"material-icons right " + this.classColor(this.state.page_type) + '-text'}>
|
|
{this.classIcon(this.state.page_type)}
|
|
</i>
|
|
{this.state.page_data.name}
|
|
</h5>
|
|
}
|
|
id="page-lookup-list"
|
|
>
|
|
<Divider></Divider>
|
|
<ListSubheader component="div">
|
|
Quick-reference
|
|
</ListSubheader>
|
|
|
|
{this.state.page_data.categories.map((category) => (
|
|
<React.Fragment key={category.id}>
|
|
<ListItem button onClick={() => this.toggleCategoryOpen(category.label)}>
|
|
<i className="material-icons left">
|
|
{ category.icon }
|
|
</i>
|
|
<ListItemText primary={ category.label } />
|
|
{!!this.state.category_open[category.label] ? <ExpandLess /> : <ExpandMore />}
|
|
</ListItem>
|
|
<Collapse in={!!this.state.category_open[category.label]} timeout="auto" unmountOnExit>
|
|
<List component="div" disablePadding>
|
|
{category.fields.map((field) => (
|
|
this.fieldData(field)
|
|
))}
|
|
</List>
|
|
</Collapse>
|
|
</React.Fragment>
|
|
))}
|
|
<Divider />
|
|
<a href={this.content_page_view_path(this.state.page_type, this.state.page_id)}>
|
|
<ListItem button>
|
|
<i className={"blue-text material-icons left"}>
|
|
{ this.classIcon(this.state.page_type) }
|
|
</i>
|
|
<ListItemText primary={"View this " + this.state.page_type} />
|
|
</ListItem>
|
|
</a>
|
|
<a href={this.content_page_edit_path(this.state.page_type, this.state.page_id)}>
|
|
<ListItem button>
|
|
<i className={"green-text material-icons left"}>
|
|
{ this.classIcon(this.state.page_type) }
|
|
</i>
|
|
<ListItemText primary={"Edit this " + this.state.page_type} />
|
|
</ListItem>
|
|
</a>
|
|
<a href={this.link_destroy_path(this.props.document_id, this.state.page_type, this.state.page_id)}>
|
|
<ListItem button>
|
|
<i className={"red-text material-icons left"}>
|
|
remove
|
|
</i>
|
|
<ListItemText primary={"Remove this link"} />
|
|
</ListItem>
|
|
</a>
|
|
</List>
|
|
</div>
|
|
);
|
|
// also add divider + view/edit links
|
|
|
|
} else { // No data to show yet
|
|
return (
|
|
<div
|
|
role="presentation"
|
|
>
|
|
<List
|
|
subheader={
|
|
<ListSubheader component="div">
|
|
Quick-reference
|
|
</ListSubheader>
|
|
}
|
|
>
|
|
<ListItem>
|
|
<ListItemText primary="Loading page..." />
|
|
</ListItem>
|
|
</List>
|
|
<div className="center">
|
|
<div className="preloader-wrapper big active">
|
|
<div className="spinner-layer spinner-blue">
|
|
<div className="circle-clipper left">
|
|
<div className="circle"></div>
|
|
</div><div className="gap-patch">
|
|
<div className="circle"></div>
|
|
</div><div className="circle-clipper right">
|
|
<div className="circle"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="spinner-layer spinner-red">
|
|
<div className="circle-clipper left">
|
|
<div className="circle"></div>
|
|
</div><div className="gap-patch">
|
|
<div className="circle"></div>
|
|
</div><div className="circle-clipper right">
|
|
<div className="circle"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="spinner-layer spinner-yellow">
|
|
<div className="circle-clipper left">
|
|
<div className="circle"></div>
|
|
</div><div className="gap-patch">
|
|
<div className="circle"></div>
|
|
</div><div className="circle-clipper right">
|
|
<div className="circle"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="spinner-layer spinner-green">
|
|
<div className="circle-clipper left">
|
|
<div className="circle"></div>
|
|
</div><div className="gap-patch">
|
|
<div className="circle"></div>
|
|
</div><div className="circle-clipper right">
|
|
<div className="circle"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
};
|
|
|
|
render () {
|
|
return (
|
|
<Drawer anchor='right'
|
|
open={this.state['open']}
|
|
onClose={() => this.setDrawerVisible(false)}
|
|
>
|
|
{this.pageData()}
|
|
</Drawer>
|
|
)
|
|
}
|
|
}
|
|
|
|
PageLookupSidebar.propTypes = {
|
|
document_id: PropTypes.number
|
|
};
|
|
|
|
export default PageLookupSidebar;
|