mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-18 07:52:41 +00:00
Merge branch 'master' into createUIBasePage
This commit is contained in:
@@ -16,8 +16,8 @@ const BrewItem = createClass({
|
||||
brew : {
|
||||
title : '',
|
||||
description : '',
|
||||
|
||||
authors : []
|
||||
authors : [],
|
||||
stubbed : true
|
||||
}
|
||||
};
|
||||
},
|
||||
@@ -50,7 +50,7 @@ const BrewItem = createClass({
|
||||
if(!this.props.brew.editId) return;
|
||||
|
||||
let editLink = this.props.brew.editId;
|
||||
if(this.props.brew.googleId) {
|
||||
if(this.props.brew.googleId && !this.props.brew.stubbed) {
|
||||
editLink = this.props.brew.googleId + editLink;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ const BrewItem = createClass({
|
||||
if(!this.props.brew.shareId) return;
|
||||
|
||||
let shareLink = this.props.brew.shareId;
|
||||
if(this.props.brew.googleId) {
|
||||
if(this.props.brew.googleId && !this.props.brew.stubbed) {
|
||||
shareLink = this.props.brew.googleId + shareLink;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ const BrewItem = createClass({
|
||||
if(!this.props.brew.shareId) return;
|
||||
|
||||
let shareLink = this.props.brew.shareId;
|
||||
if(this.props.brew.googleId) {
|
||||
if(this.props.brew.googleId && !this.props.brew.stubbed) {
|
||||
shareLink = this.props.brew.googleId + shareLink;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ const BrewItem = createClass({
|
||||
},
|
||||
|
||||
renderGoogleDriveIcon : function(){
|
||||
if(!this.props.brew.gDrive) return;
|
||||
if(!this.props.brew.googleId) return;
|
||||
|
||||
return <span>
|
||||
<img className='googleDriveIcon' src={googleDriveIcon} alt='googleDriveIcon' />
|
||||
@@ -95,17 +95,35 @@ const BrewItem = createClass({
|
||||
|
||||
render : function(){
|
||||
const brew = this.props.brew;
|
||||
if(Array.isArray(brew.tags)) { // temporary fix until dud tags are cleaned
|
||||
brew.tags = brew.tags?.filter((tag)=>tag); //remove tags that are empty strings
|
||||
}
|
||||
const dateFormatString = 'YYYY-MM-DD HH:mm:ss';
|
||||
|
||||
return <div className='brewItem'>
|
||||
{brew.thumbnail &&
|
||||
<div className='thumbnail' style={{ backgroundImage: `url(${brew.thumbnail})` }} >
|
||||
</div>
|
||||
}
|
||||
<div className='text'>
|
||||
<h2>{brew.title}</h2>
|
||||
<p className='description'>{brew.description}</p>
|
||||
</div>
|
||||
<hr />
|
||||
<div className='info'>
|
||||
<span title={`Authors:\n${brew.authors.join('\n')}`}>
|
||||
<i className='fas fa-user'/> {brew.authors.join(', ')}
|
||||
|
||||
{brew.tags?.length ? <>
|
||||
<div className='brewTags' title={`Tags:\n${brew.tags.join('\n')}`}>
|
||||
<i className='fas fa-tags'/>
|
||||
{brew.tags.map((tag, idx)=>{
|
||||
const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/);
|
||||
return <span className={matches[1]}>{matches[2]}</span>;
|
||||
})}
|
||||
</div>
|
||||
</> : <></>
|
||||
}
|
||||
<span title={`Authors:\n${brew.authors?.join('\n')}`}>
|
||||
<i className='fas fa-user'/> {brew.authors?.join(', ')}
|
||||
</span>
|
||||
<br />
|
||||
<span title={`Last viewed: ${moment(brew.lastViewed).local().format(dateFormatString)}`}>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
min-height : 105px;
|
||||
margin-right : 15px;
|
||||
margin-bottom : 15px;
|
||||
padding : 5px 15px 2px 8px;
|
||||
padding : 5px 15px 2px 6px;
|
||||
padding-right : 15px;
|
||||
border : 1px solid #c9ad6a;
|
||||
border-radius : 5px;
|
||||
@@ -19,6 +19,20 @@
|
||||
break-inside : avoid;
|
||||
box-shadow : 0px 4px 5px 0px #333;
|
||||
background-color : #cab2802e;
|
||||
.thumbnail {
|
||||
position: absolute;
|
||||
width: 150px;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: -1;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right top;
|
||||
mask-image: linear-gradient(80deg, #0000 20%, #050 40%);
|
||||
-webkit-mask-image: linear-gradient(80deg, #0000 20%, #050 40%);
|
||||
opacity: 50%;
|
||||
}
|
||||
.text {
|
||||
min-height : 54px;
|
||||
h4{
|
||||
@@ -29,13 +43,23 @@
|
||||
.info{
|
||||
position: initial;
|
||||
bottom: 2px;
|
||||
font-family : ScalySans;
|
||||
font-family : ScalySansRemake;
|
||||
font-size : 1.2em;
|
||||
&>span{
|
||||
margin-right : 12px;
|
||||
line-height : 1.5em;
|
||||
}
|
||||
}
|
||||
.brewTags span {
|
||||
background-color: #c8ac6e3b;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
border: 1px solid #c8ac6e;
|
||||
border-radius: 4px;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
}
|
||||
&:hover{
|
||||
.links{
|
||||
opacity : 1;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/
|
||||
require('./listPage.less');
|
||||
const React = require('react');
|
||||
const createClass = require('create-react-class');
|
||||
@@ -6,6 +7,11 @@ const moment = require('moment');
|
||||
|
||||
const BrewItem = require('./brewItem/brewItem.jsx');
|
||||
|
||||
const USERPAGE_KEY_PREFIX = 'HOMEBREWERY-LISTPAGE';
|
||||
|
||||
const DEFAULT_SORT_TYPE = 'alpha';
|
||||
const DEFAULT_SORT_DIR = 'asc';
|
||||
|
||||
const ListPage = createClass({
|
||||
displayName : 'ListPage',
|
||||
getDefaultProps : function() {
|
||||
@@ -21,14 +27,56 @@ const ListPage = createClass({
|
||||
};
|
||||
},
|
||||
getInitialState : function() {
|
||||
// HIDE ALL GROUPS UNTIL LOADED
|
||||
const brewCollection = this.props.brewCollection.map((brewGroup)=>{
|
||||
brewGroup.visible = false;
|
||||
return brewGroup;
|
||||
});
|
||||
|
||||
return {
|
||||
sortType : 'alpha',
|
||||
sortDir : 'asc',
|
||||
filterString : this.props.query?.filter || '',
|
||||
query : this.props.query
|
||||
filterString : this.props.query?.filter || '',
|
||||
sortType : this.props.query?.sort || null,
|
||||
sortDir : this.props.query?.dir || null,
|
||||
query : this.props.query,
|
||||
brewCollection : brewCollection
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount : function() {
|
||||
// SAVE TO LOCAL STORAGE WHEN LEAVING PAGE
|
||||
window.onbeforeunload = this.saveToLocalStorage;
|
||||
|
||||
// LOAD FROM LOCAL STORAGE
|
||||
if(typeof window !== 'undefined') {
|
||||
const newSortType = (this.state.sortType ?? (localStorage.getItem(`${USERPAGE_KEY_PREFIX}-SORTTYPE`) || DEFAULT_SORT_TYPE));
|
||||
const newSortDir = (this.state.sortDir ?? (localStorage.getItem(`${USERPAGE_KEY_PREFIX}-SORTDIR`) || DEFAULT_SORT_DIR));
|
||||
this.updateUrl(this.state.filterString, newSortType, newSortDir);
|
||||
|
||||
const brewCollection = this.props.brewCollection.map((brewGroup)=>{
|
||||
brewGroup.visible = (localStorage.getItem(`${USERPAGE_KEY_PREFIX}-VISIBILITY-${brewGroup.class}`) ?? 'true')=='true';
|
||||
return brewGroup;
|
||||
});
|
||||
|
||||
this.setState({
|
||||
brewCollection : brewCollection,
|
||||
sortType : newSortType,
|
||||
sortDir : newSortDir
|
||||
});
|
||||
};
|
||||
},
|
||||
|
||||
componentWillUnmount : function() {
|
||||
window.onbeforeunload = function(){};
|
||||
},
|
||||
|
||||
saveToLocalStorage : function() {
|
||||
this.state.brewCollection.map((brewGroup)=>{
|
||||
localStorage.setItem(`${USERPAGE_KEY_PREFIX}-VISIBILITY-${brewGroup.class}`, `${brewGroup.visible}`);
|
||||
});
|
||||
localStorage.setItem(`${USERPAGE_KEY_PREFIX}-SORTTYPE`, this.state.sortType);
|
||||
localStorage.setItem(`${USERPAGE_KEY_PREFIX}-SORTDIR`, this.state.sortDir);
|
||||
},
|
||||
|
||||
renderBrews : function(brews){
|
||||
if(!brews || !brews.length) return <div className='noBrews'>No Brews.</div>;
|
||||
|
||||
@@ -50,14 +98,18 @@ const ListPage = createClass({
|
||||
},
|
||||
|
||||
handleSortOptionChange : function(event){
|
||||
this.updateUrl(this.state.filterString, event.target.value, this.state.sortDir);
|
||||
this.setState({
|
||||
sortType : event.target.value
|
||||
});
|
||||
},
|
||||
|
||||
handleSortDirChange : function(event){
|
||||
const newDir = this.state.sortDir == 'asc' ? 'desc' : 'asc';
|
||||
|
||||
this.updateUrl(this.state.filterString, this.state.sortType, newDir);
|
||||
this.setState({
|
||||
sortDir : `${(this.state.sortDir == 'asc' ? 'desc' : 'asc')}`
|
||||
sortDir : newDir
|
||||
});
|
||||
},
|
||||
|
||||
@@ -77,19 +129,22 @@ const ListPage = createClass({
|
||||
this.setState({
|
||||
filterString : e.target.value,
|
||||
});
|
||||
this.updateUrl(e.target.value);
|
||||
this.updateUrl(e.target.value, this.state.sortType, this.state.sortDir);
|
||||
return;
|
||||
},
|
||||
|
||||
updateUrl : function(filterTerm){
|
||||
updateUrl : function(filterTerm, sortType, sortDir){
|
||||
const url = new URL(window.location.href);
|
||||
const urlParams = new URLSearchParams(url.search);
|
||||
if(urlParams.get('filter') == filterTerm)
|
||||
return;
|
||||
|
||||
urlParams.set('sort', sortType);
|
||||
urlParams.set('dir', sortDir);
|
||||
|
||||
if(!filterTerm)
|
||||
urlParams.delete('filter');
|
||||
else
|
||||
urlParams.set('filter', filterTerm);
|
||||
|
||||
url.search = urlParams;
|
||||
window.history.replaceState(null, null, url);
|
||||
},
|
||||
@@ -100,7 +155,6 @@ const ListPage = createClass({
|
||||
<i className='fas fa-search'></i>
|
||||
<input
|
||||
type='search'
|
||||
autoFocus={true}
|
||||
placeholder='filter title/description'
|
||||
onChange={this.handleFilterTextChange}
|
||||
value={this.state.filterString}
|
||||
@@ -142,32 +196,48 @@ const ListPage = createClass({
|
||||
|
||||
getSortedBrews : function(brews){
|
||||
const testString = _.deburr(this.state.filterString).toLowerCase();
|
||||
brews = _.filter(brews, (brew)=>{
|
||||
return (_.deburr(brew.title).toLowerCase().includes(testString)) ||
|
||||
(_.deburr(brew.description).toLowerCase().includes(testString));
|
||||
});
|
||||
|
||||
brews = _.filter(brews, (brew)=>{
|
||||
const brewStrings = _.deburr([
|
||||
brew.title,
|
||||
brew.description,
|
||||
brew.tags].join('\n')
|
||||
.toLowerCase());
|
||||
|
||||
return brewStrings.includes(testString);
|
||||
});
|
||||
return _.orderBy(brews, (brew)=>{ return this.sortBrewOrder(brew); }, this.state.sortDir);
|
||||
},
|
||||
|
||||
toggleBrewCollectionState : function(brewGroupClass) {
|
||||
this.setState((prevState)=>({
|
||||
brewCollection : prevState.brewCollection.map(
|
||||
(brewGroup)=>brewGroup.class === brewGroupClass ? { ...brewGroup, visible: !brewGroup.visible } : brewGroup
|
||||
)
|
||||
}));
|
||||
},
|
||||
|
||||
renderBrewCollection : function(brewCollection){
|
||||
if(brewCollection == []) return <div className='brewCollection'>
|
||||
<h1>No Brews</h1>
|
||||
</div>;
|
||||
return _.map(brewCollection, (brewGroup, idx)=>{
|
||||
return <div key={idx} className={`brewCollection ${brewGroup.class ?? ''}`}>
|
||||
<h1>{brewGroup.title || 'No Title'}</h1>
|
||||
{this.renderBrews(this.getSortedBrews(brewGroup.brews))}
|
||||
<h1 className={brewGroup.visible ? 'active' : 'inactive'} onClick={()=>{this.toggleBrewCollectionState(brewGroup.class);}}>{brewGroup.title || 'No Title'}</h1>
|
||||
{brewGroup.visible ? this.renderBrews(this.getSortedBrews(brewGroup.brews)) : <></>}
|
||||
</div>;
|
||||
});
|
||||
},
|
||||
|
||||
render : function(){
|
||||
return <div className='listPage sitePage'>
|
||||
<link href='/themes/5ePhbLegacy.style.css' rel='stylesheet'/>
|
||||
<link href='/themes/V3/5ePHB/style.css' rel='stylesheet'/>
|
||||
{this.props.navItems}
|
||||
|
||||
<div className='content V3'>
|
||||
<div className='phb'>
|
||||
<div className='phb page'>
|
||||
{this.renderSortOptions()}
|
||||
{this.renderBrewCollection(this.props.brewCollection)}
|
||||
{this.renderBrewCollection(this.state.brewCollection)}
|
||||
</div>
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
.listPage{
|
||||
.content{
|
||||
overflow-y : scroll;
|
||||
overflow-y : overlay;
|
||||
.phb{
|
||||
.noColumns();
|
||||
height : auto;
|
||||
@@ -34,7 +34,7 @@
|
||||
font-family : 'Open Sans', sans-serif;
|
||||
position : fixed;
|
||||
top : 35px;
|
||||
left : calc(50vw - 408px);
|
||||
left : calc(50vw - 400px);
|
||||
border : 2px solid #58180D;
|
||||
width : 800px;
|
||||
background-color : #EEE5CE;
|
||||
@@ -74,4 +74,26 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
h1 {
|
||||
cursor: pointer;
|
||||
&.active {
|
||||
color: #58180D;
|
||||
}
|
||||
&.inactive {
|
||||
color: #707070;
|
||||
|
||||
}
|
||||
&.active::before, &.inactive::before {
|
||||
font-family: 'Font Awesome 5 Free';
|
||||
font-weight: 900;
|
||||
font-size: 0.6cm;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
&.active::before {
|
||||
content: '\f107';
|
||||
}
|
||||
&.inactive::before {
|
||||
content: '\f105';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user