diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 7268e4b34..818445714 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -55,9 +55,9 @@ const BrewRenderer = (props)=>{ theme : '5ePHB', lang : '', errors : [], - currentEditorCursorPageNum : 0, - currentEditorViewPageNum : 0, - currentBrewRendererPageNum : 0, + currentEditorCursorPageNum : 1, + currentEditorViewPageNum : 1, + currentBrewRendererPageNum : 1, themeBundle : {}, onPageChange : ()=>{}, ...props diff --git a/client/homebrew/brewRenderer/brewRenderer.less b/client/homebrew/brewRenderer/brewRenderer.less index dca64c455..2787c8103 100644 --- a/client/homebrew/brewRenderer/brewRenderer.less +++ b/client/homebrew/brewRenderer/brewRenderer.less @@ -39,6 +39,7 @@ overflow-y : unset; .pages { margin : 0px; + zoom: 100% !important; & > .page { box-shadow : unset; } } } diff --git a/client/homebrew/editor/metadataEditor/metadataEditor.jsx b/client/homebrew/editor/metadataEditor/metadataEditor.jsx index 0f1f6ad54..e66fa64e2 100644 --- a/client/homebrew/editor/metadataEditor/metadataEditor.jsx +++ b/client/homebrew/editor/metadataEditor/metadataEditor.jsx @@ -304,17 +304,14 @@ const MetadataEditor = createClass({ onChange={(e)=>this.handleRenderer('V3', e)} /> V3 - - - Click here to see the demo page for the old Legacy renderer! - + Click here to see the demo page for the old Legacy renderer! ; }, render : function(){ return
-

Brew

+

Properties Editor

@@ -362,9 +359,7 @@ const MetadataEditor = createClass({ {this.renderRenderOptions()} -
- -

Authors

+

Authors

{this.renderAuthors()} @@ -375,15 +370,13 @@ const MetadataEditor = createClass({ notes={['Invited author usernames are case sensitive.', 'After adding an invited author, send them the edit link. There, they can choose to accept or decline the invitation.']} onChange={(e)=>this.handleFieldChange('invitedAuthors', e)}/> -
- -

Privacy

+

Privacy

{this.renderPublish()} - Published homebrews will be publicly viewable and searchable (eventually...) + Published brews are searchable in the Vault and visible on your user page. Unpublished brews are not indexed in the Vault or visible on your user page, but can still be shared and indexed by search engines. You can unpublish a brew any time.
diff --git a/client/homebrew/editor/metadataEditor/metadataEditor.less b/client/homebrew/editor/metadataEditor/metadataEditor.less index 27ebd88c2..62ec6b37b 100644 --- a/client/homebrew/editor/metadataEditor/metadataEditor.less +++ b/client/homebrew/editor/metadataEditor/metadataEditor.less @@ -1,5 +1,6 @@ @import 'naturalcrit/styles/colors.less'; + .metadataEditor { position : absolute; z-index : 5; @@ -9,12 +10,19 @@ padding : 25px; overflow-y : auto; background-color : #999999; + font-size : 13px; - .sectionHead { + h1 { + margin: 0 0 40px; + font-weight: bold; + text-transform: uppercase; + } + + h2 { margin : 20px 0; - font-weight : 1000; - - &:first-of-type { margin-top : 0; } + font-weight : bold; + border-bottom: 2px solid gray; + color: #555; } & > div { margin-bottom : 10px; } @@ -43,15 +51,21 @@ min-width : 200px; & > label { width : 80px; - font-size : 11px; font-weight : 800; line-height : 1.8em; text-transform : uppercase; + font-size: .9em; } & > .value { flex : 1 1 auto; width : 50px; &:invalid { background : #FFB9B9; } + small { + display : block; + font-size : 0.9em; + font-style : italic; + line-height : 1.4em; + } } input[type='text'], textarea { border : 1px solid gray; @@ -78,7 +92,6 @@ textarea.value { height : auto; font-family : 'Open Sans', sans-serif; - font-size : 0.8em; resize : none; } } @@ -87,12 +100,6 @@ z-index : 200; max-width : 150px; } - small { - display : inline-block; - font-size : 0.6em; - font-style : italic; - line-height : 1.4em; - } } @@ -113,18 +120,13 @@ display : inline-flex; align-items : center; margin-right : 15px; - font-size : 0.7em; + font-size : 0.9em; font-weight : 800; white-space : nowrap; vertical-align : middle; cursor : pointer; user-select : none; } - a { - display : inline-flex; - font-size : 0.7em; - font-weight : 800; - } input { margin : 3px; vertical-align : middle; @@ -149,12 +151,10 @@ } } .authors.field .value { - font-size : 0.8em; line-height : 1.5em; } .themes.field { - font-size : 13.33px; .navDropdownContainer { position : relative; z-index : 100; @@ -165,9 +165,9 @@ background-color : darkgray; } & > div:first-child { - padding : 6px 3px; + padding : 3px 3px; background-color : inherit; - border : 2px solid rgb(118,118,118); + border : 1px solid gray; i { float : right; } &:hover { color : white; @@ -240,6 +240,7 @@ } } } + .field .list { display : flex; flex : 1 0; @@ -258,15 +259,15 @@ color : white; text-align : center; cursor : pointer; - + i { position : relative; top : 50%; transform : translateY(-50%); } - + &:not(:last-child) { border-right : 1px solid black; } - + &:last-child { border-radius : 0 0.5em 0.5em 0; } } @@ -277,8 +278,7 @@ background-color : #DDDDDD; border-radius : 0.5em; - .icon { - #groupedIcon; } + .icon { #groupedIcon; } } .input-group { @@ -294,17 +294,30 @@ height : 100%; } - .invalid:focus { background-color : pink; } + .input-group { + height : ~'calc(.9em + 4px + .6em)'; - .icon { - #groupedIcon; - top : -0.54em; - right : 1px; - height : 97%; - font-size : 0.8em; + input { border-radius : 0.5em 0 0 0.5em; } - i { font-size : 1.125em; } + input:last-child { border-radius : 0.5em; } + + .value { + width : 7.5vw; + min-width : 75px; + height : 100%; + } + + .invalid:focus { background-color : pink; } + + .icon { + #groupedIcon; + top : -0.54em; + right : 1px; + height : 97%; + + i { font-size : 1.125em; } + } } } } -} +} \ No newline at end of file diff --git a/client/homebrew/editor/stringArrayEditor/stringArrayEditor.jsx b/client/homebrew/editor/stringArrayEditor/stringArrayEditor.jsx index 8f06ae561..47ab038cc 100644 --- a/client/homebrew/editor/stringArrayEditor/stringArrayEditor.jsx +++ b/client/homebrew/editor/stringArrayEditor/stringArrayEditor.jsx @@ -128,7 +128,7 @@ const StringArrayEditor = createClass({ return
-
+
{valueElements}
diff --git a/client/homebrew/navbar/editTitle.navitem.jsx b/client/homebrew/navbar/editTitle.navitem.jsx deleted file mode 100644 index 94ae5d0b0..000000000 --- a/client/homebrew/navbar/editTitle.navitem.jsx +++ /dev/null @@ -1,34 +0,0 @@ -const React = require('react'); -const createClass = require('create-react-class'); -const cx = require('classnames'); -const Nav = require('naturalcrit/nav/nav.jsx'); - -const MAX_TITLE_LENGTH = 50; - - -const EditTitle = createClass({ - displayName : 'EditTitleNavItem', - getDefaultProps : function() { - return { - title : '', - onChange : function(){} - }; - }, - - handleChange : function(e){ - if(e.target.value.length > MAX_TITLE_LENGTH) return; - this.props.onChange(e.target.value); - }, - render : function(){ - return - - -
= MAX_TITLE_LENGTH })}> - {this.props.title.length}/{MAX_TITLE_LENGTH} -
-
; - }, - -}); - -module.exports = EditTitle; diff --git a/client/homebrew/navbar/recent.navitem.jsx b/client/homebrew/navbar/recent.navitem.jsx index 431bdd8df..a6cbbf406 100644 --- a/client/homebrew/navbar/recent.navitem.jsx +++ b/client/homebrew/navbar/recent.navitem.jsx @@ -36,7 +36,7 @@ const RecentItems = createClass({ //== Add current brew to appropriate recent items list (depending on storageKey) ==// if(this.props.storageKey == 'edit'){ let editId = this.props.brew.editId; - if(this.props.brew.googleId){ + if(this.props.brew.googleId && !this.props.brew.stubbed){ editId = `${this.props.brew.googleId}${this.props.brew.editId}`; } edited = _.filter(edited, (brew)=>{ @@ -51,7 +51,7 @@ const RecentItems = createClass({ } if(this.props.storageKey == 'view'){ let shareId = this.props.brew.shareId; - if(this.props.brew.googleId){ + if(this.props.brew.googleId && !this.props.brew.stubbed){ shareId = `${this.props.brew.googleId}${this.props.brew.shareId}`; } viewed = _.filter(viewed, (brew)=>{ @@ -83,7 +83,7 @@ const RecentItems = createClass({ let edited = JSON.parse(localStorage.getItem(EDIT_KEY) || '[]'); if(this.props.storageKey == 'edit') { let prevEditId = prevProps.brew.editId; - if(prevProps.brew.googleId){ + if(prevProps.brew.googleId && !this.props.brew.stubbed){ prevEditId = `${prevProps.brew.googleId}${prevProps.brew.editId}`; } @@ -91,7 +91,7 @@ const RecentItems = createClass({ return brew.id !== prevEditId; }); let editId = this.props.brew.editId; - if(this.props.brew.googleId){ + if(this.props.brew.googleId && !this.props.brew.stubbed){ editId = `${this.props.brew.googleId}${this.props.brew.editId}`; } edited.unshift({ diff --git a/client/homebrew/navbar/reddit.navitem.jsx b/client/homebrew/navbar/reddit.navitem.jsx deleted file mode 100644 index 1d9f95604..000000000 --- a/client/homebrew/navbar/reddit.navitem.jsx +++ /dev/null @@ -1,44 +0,0 @@ -const React = require('react'); -const createClass = require('create-react-class'); -const Nav = require('naturalcrit/nav/nav.jsx'); - -const MAIN_URL = 'https://www.reddit.com/r/UnearthedArcana/submit?selftext=true'; - - -const RedditShare = createClass({ - displayName : 'RedditShareNavItem', - getDefaultProps : function() { - return { - brew : { - title : '', - sharedId : '', - text : '' - } - }; - }, - - getText : function(){ - - }, - - - handleClick : function(){ - const url = [ - MAIN_URL, - `title=${encodeURIComponent(this.props.brew.title ? this.props.brew.title : 'Check out my brew!')}`, - `text=${encodeURIComponent(this.props.brew.text)}` - ].join('&'); - - window.open(url, '_blank'); - }, - - - render : function(){ - return - share on reddit - ; - }, - -}); - -module.exports = RedditShare; diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 18cfb2d41..79bb01aa2 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -32,7 +32,7 @@ import { updateHistory, versionHistoryGarbageCollection } from '../../utils/vers const googleDriveIcon = require('../../googleDrive.svg'); -const SAVE_TIMEOUT = 3000; +const SAVE_TIMEOUT = 10000; const EditPage = createClass({ displayName : 'EditPage', diff --git a/client/homebrew/pages/sharePage/sharePage.jsx b/client/homebrew/pages/sharePage/sharePage.jsx index 9b4f9b73d..2d96e1ce6 100644 --- a/client/homebrew/pages/sharePage/sharePage.jsx +++ b/client/homebrew/pages/sharePage/sharePage.jsx @@ -25,7 +25,8 @@ const SharePage = createClass({ getInitialState : function() { return { - themeBundle : {} + themeBundle : {}, + currentBrewRendererPageNum : 1 }; }, @@ -39,6 +40,10 @@ const SharePage = createClass({ document.removeEventListener('keydown', this.handleControlKeys); }, + handleBrewRendererPageChange : function(pageNumber){ + this.setState({ currentBrewRendererPageNum: pageNumber }); + }, + handleControlKeys : function(e){ if(!(e.ctrlKey || e.metaKey)) return; const P_KEY = 80; @@ -114,9 +119,12 @@ const SharePage = createClass({
diff --git a/client/homebrew/pages/vaultPage/vaultPage.jsx b/client/homebrew/pages/vaultPage/vaultPage.jsx index bad1fbd57..a51039345 100644 --- a/client/homebrew/pages/vaultPage/vaultPage.jsx +++ b/client/homebrew/pages/vaultPage/vaultPage.jsx @@ -1,3 +1,5 @@ +/*eslint max-lines: ["warn", {"max": 400, "skipBlankLines": true, "skipComments": true}]*/ +/*eslint max-params:["warn", { max: 10 }], */ require('./vaultPage.less'); const React = require('react'); @@ -18,13 +20,15 @@ const request = require('../../utils/request-middleware.js'); const VaultPage = (props)=>{ const [pageState, setPageState] = useState(parseInt(props.query.page) || 1); + const [sortState, setSort] = useState(props.query.sort || 'title'); + const [dirState, setdir] = useState(props.query.dir || 'asc'); + //Response state const [brewCollection, setBrewCollection] = useState(null); const [totalBrews, setTotalBrews] = useState(null); const [searching, setSearching] = useState(false); const [error, setError] = useState(null); - const titleRef = useRef(null); const authorRef = useRef(null); const countRef = useRef(null); @@ -34,7 +38,7 @@ const VaultPage = (props)=>{ useEffect(()=>{ disableSubmitIfFormInvalid(); - loadPage(pageState, true); + loadPage(pageState, true, props.query.sort, props.query.dir); }, []); const updateStateWithBrews = (brews, page)=>{ @@ -43,7 +47,7 @@ const VaultPage = (props)=>{ setSearching(false); }; - const updateUrl = (titleValue, authorValue, countValue, v3Value, legacyValue, page)=>{ + const updateUrl = (titleValue, authorValue, countValue, v3Value, legacyValue, page, sort, dir)=>{ const url = new URL(window.location.href); const urlParams = new URLSearchParams(url.search); @@ -53,21 +57,23 @@ const VaultPage = (props)=>{ urlParams.set('v3', v3Value); urlParams.set('legacy', legacyValue); urlParams.set('page', page); + urlParams.set('sort', sort); + urlParams.set('dir', dir); url.search = urlParams.toString(); window.history.replaceState(null, '', url.toString()); }; - const performSearch = async (title, author, count, v3, legacy, page)=>{ - updateUrl(title, author, count, v3, legacy, page); + const performSearch = async (title, author, count, v3, legacy, page, sort, dir)=>{ + updateUrl(title, author, count, v3, legacy, page, sort, dir); - const response = await request.get( - `/api/vault?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}&count=${count}&page=${page}` - ).catch((error)=>{ - console.log('error at loadPage: ', error); - setError(error); - updateStateWithBrews([], 1); - }); + const response = await request + .get(`/api/vault?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}&count=${count}&page=${page}&sort=${sort}&dir=${dir}`) + .catch((error)=>{ + console.log('error at loadPage: ', error); + setError(error); + updateStateWithBrews([], 1); + }); if(response.ok) updateStateWithBrews(response.body.brews, page); @@ -76,9 +82,8 @@ const VaultPage = (props)=>{ const loadTotal = async (title, author, v3, legacy)=>{ setTotalBrews(null); - const response = await request.get( - `/api/vault/total?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}` - ).catch((error)=>{ + const response = await request.get(`/api/vault/total?title=${title}&author=${author}&v3=${v3}&legacy=${legacy}`) + .catch((error)=>{ console.log('error at loadTotal: ', error); setError(error); updateStateWithBrews([], 1); @@ -88,9 +93,8 @@ const VaultPage = (props)=>{ setTotalBrews(response.body.totalBrews); }; - const loadPage = async (page, updateTotal)=>{ - if(!validateForm()) - return; + const loadPage = async (page, updateTotal, sort, dir)=>{ + if(!validateForm()) return; setSearching(true); setError(null); @@ -100,8 +104,14 @@ const VaultPage = (props)=>{ const count = countRef.current.value || 10; const v3 = v3Ref.current.checked != false; const legacy = legacyRef.current.checked != false; + const sortOption = sort || 'title'; + const dirOption = dir || 'asc'; + const pageProp = page || 1; - performSearch(title, author, count, v3, legacy, page); + setSort(sortOption); + setdir(dirOption); + + performSearch(title, author, count, v3, legacy, pageProp, sortOption, dirOption); if(updateTotal) loadTotal(title, author, v3, legacy); @@ -248,6 +258,33 @@ const VaultPage = (props)=>{
); + const renderSortOption = (optionTitle, optionValue)=>{ + const oppositeDir = dirState === 'asc' ? 'desc' : 'asc'; + + return ( +
+ + {sortState === optionValue && ( + + )} +
+ ); + }; + + const renderSortBar = ()=>{ + + return ( +
+ {renderSortOption('Title', 'title', props.query.dir)} + {renderSortOption('Created Date', 'createdAt', props.query.dir)} + {renderSortOption('Updated Date', 'updatedAt', props.query.dir)} + {renderSortOption('Views', 'views', props.query.dir)} +
+ ); + }; + const renderPaginationControls = ()=>{ if(!totalBrews) return null; @@ -271,10 +308,8 @@ const VaultPage = (props)=>{ .map((_, index)=>( loadPage(startPage + index, false)} + className={`pageNumber ${pageState === startPage + index ? 'currentPage' : ''}`} + onClick={()=>loadPage(startPage + index, false, sortState, dirState)} > {startPage + index} @@ -284,7 +319,7 @@ const VaultPage = (props)=>{