mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-08 01:02:51 +00:00
Merge branch 'master' into Language-Attribute
This commit is contained in:
@@ -4,18 +4,24 @@ const React = require('react');
|
||||
const createClass = require('create-react-class');
|
||||
const _ = require('lodash');
|
||||
const cx = require('classnames');
|
||||
const request = require('superagent');
|
||||
const request = require('../../utils/request-middleware.js');
|
||||
const Nav = require('naturalcrit/nav/nav.jsx');
|
||||
const Combobox = require('client/components/combobox.jsx');
|
||||
const StringArrayEditor = require('../stringArrayEditor/stringArrayEditor.jsx');
|
||||
|
||||
const Themes = require('themes/themes.json');
|
||||
const validations = require('./validations.js')
|
||||
const validations = require('./validations.js');
|
||||
|
||||
const SYSTEMS = ['5e', '4e', '3.5e', 'Pathfinder'];
|
||||
|
||||
const homebreweryThumbnail = require('../../thumbnail.png');
|
||||
|
||||
const callIfExists = (val, fn, ...args)=>{
|
||||
if(val[fn]) {
|
||||
val[fn](...args);
|
||||
}
|
||||
};
|
||||
|
||||
const MetadataEditor = createClass({
|
||||
displayName : 'MetadataEditor',
|
||||
getDefaultProps : function() {
|
||||
@@ -33,7 +39,8 @@ const MetadataEditor = createClass({
|
||||
theme : '5ePHB',
|
||||
lang : 'en'
|
||||
},
|
||||
onChange : ()=>{}
|
||||
onChange : ()=>{},
|
||||
reportError : ()=>{}
|
||||
};
|
||||
},
|
||||
|
||||
@@ -55,15 +62,13 @@ const MetadataEditor = createClass({
|
||||
},
|
||||
|
||||
handleFieldChange : function(name, e){
|
||||
e.persist();
|
||||
|
||||
// load validation rules, and check input value against them
|
||||
const inputRules = validations[name] ?? [];
|
||||
const validationErr = inputRules.map((rule)=>rule(e.target.value)).filter(Boolean);
|
||||
|
||||
// if no validation rules, save to props
|
||||
if(validationErr.length === 0){
|
||||
e.target.setCustomValidity('');
|
||||
callIfExists(e.target, 'setCustomValidity', '');
|
||||
this.props.onChange({
|
||||
...this.props.metadata,
|
||||
[name] : e.target.value
|
||||
@@ -73,10 +78,14 @@ const MetadataEditor = createClass({
|
||||
const errMessage = validationErr.map((err)=>{
|
||||
return `- ${err}`;
|
||||
}).join('\n');
|
||||
console.log(`Input error ${errMessage}`);
|
||||
e.target.setCustomValidity(errMessage);
|
||||
e.target.reportValidity();
|
||||
};
|
||||
|
||||
// console.log(`Input error ${errMessage}`);
|
||||
// e.target.setCustomValidity(errMessage);
|
||||
// e.target.reportValidity();
|
||||
// };
|
||||
callIfExists(e.target, 'setCustomValidity', errMessage);
|
||||
callIfExists(e.target, 'reportValidity');
|
||||
}
|
||||
},
|
||||
|
||||
handleSystem : function(system, e){
|
||||
@@ -125,8 +134,12 @@ const MetadataEditor = createClass({
|
||||
|
||||
request.delete(`/api/${this.props.metadata.googleId ?? ''}${this.props.metadata.editId}`)
|
||||
.send()
|
||||
.end(function(err, res){
|
||||
window.location.href = '/';
|
||||
.end((err, res)=>{
|
||||
if(err) {
|
||||
this.props.reportError(err);
|
||||
} else {
|
||||
window.location.href = '/';
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -188,6 +201,10 @@ const MetadataEditor = createClass({
|
||||
return <div className='item' key={''} onClick={()=>this.handleTheme(theme)} title={''}>
|
||||
{`${theme.renderer} : ${theme.name}`}
|
||||
<img src={`/themes/${theme.renderer}/${theme.path}/dropdownTexture.png`}/>
|
||||
<div className='preview'>
|
||||
<h6>{`${theme.name}`} preview</h6>
|
||||
<img src={`/themes/${theme.renderer}/${theme.path}/dropdownPreview.png`}/>
|
||||
</div>
|
||||
</div>;
|
||||
});
|
||||
};
|
||||
@@ -197,14 +214,14 @@ const MetadataEditor = createClass({
|
||||
|
||||
if(this.props.metadata.renderer == 'legacy') {
|
||||
dropdown =
|
||||
<Nav.dropdown className='disabled' trigger='disabled'>
|
||||
<Nav.dropdown className='disabled value' trigger='disabled'>
|
||||
<div>
|
||||
{`Themes are not supported in the Legacy Renderer`} <i className='fas fa-caret-down'></i>
|
||||
</div>
|
||||
</Nav.dropdown>;
|
||||
} else {
|
||||
dropdown =
|
||||
<Nav.dropdown trigger='click'>
|
||||
<Nav.dropdown className='value' trigger='click'>
|
||||
<div>
|
||||
{`${_.upperFirst(currentTheme.renderer)} : ${currentTheme.name}`} <i className='fas fa-caret-down'></i>
|
||||
</div>
|
||||
@@ -290,6 +307,8 @@ const MetadataEditor = createClass({
|
||||
|
||||
render : function(){
|
||||
return <div className='metadataEditor'>
|
||||
<h1 className='sectionHead'>Brew</h1>
|
||||
|
||||
<div className='field title'>
|
||||
<label>title</label>
|
||||
<input type='text' className='value'
|
||||
@@ -323,8 +342,6 @@ const MetadataEditor = createClass({
|
||||
values={this.props.metadata.tags}
|
||||
onChange={(e)=>this.handleFieldChange('tags', e)}/>
|
||||
|
||||
{this.renderAuthors()}
|
||||
|
||||
<div className='field systems'>
|
||||
<label>systems</label>
|
||||
<div className='value'>
|
||||
@@ -338,6 +355,23 @@ const MetadataEditor = createClass({
|
||||
|
||||
{this.renderRenderOptions()}
|
||||
|
||||
<hr/>
|
||||
|
||||
<h1 className='sectionHead'>Authors</h1>
|
||||
|
||||
{this.renderAuthors()}
|
||||
|
||||
<StringArrayEditor label='invited authors' valuePatterns={[/.+/]}
|
||||
validators={[(v)=>!this.props.metadata.authors?.includes(v)]}
|
||||
placeholder='invite author' unique={true}
|
||||
values={this.props.metadata.invitedAuthors}
|
||||
notes={['Invited authors 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)}/>
|
||||
|
||||
<hr/>
|
||||
|
||||
<h1 className='sectionHead'>Privacy</h1>
|
||||
|
||||
<div className='field publish'>
|
||||
<label>publish</label>
|
||||
<div className='value'>
|
||||
|
||||
@@ -10,6 +10,15 @@
|
||||
height : calc(100vh - 54px); // 54px is the height of the navbar + snippet bar. probably a better way to dynamic get this.
|
||||
overflow-y : auto;
|
||||
|
||||
.sectionHead {
|
||||
font-weight: 1000;
|
||||
margin: 20px 0;
|
||||
|
||||
&:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
& > div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@@ -26,13 +35,13 @@
|
||||
flex-direction: column;
|
||||
flex: 5 0 200px;
|
||||
gap: 10px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.field{
|
||||
display : flex;
|
||||
flex-wrap : wrap;
|
||||
width : 100%;
|
||||
min-width : 200px;
|
||||
position : relative;
|
||||
@@ -89,6 +98,10 @@
|
||||
&.language .language-dropdown {
|
||||
max-width:150px;
|
||||
}
|
||||
small {
|
||||
font-size : 0.6em;
|
||||
font-style : italic;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,10 +152,6 @@
|
||||
button.unpublish{
|
||||
.button(@silver);
|
||||
}
|
||||
small{
|
||||
font-size : 0.6em;
|
||||
font-style : italic;
|
||||
}
|
||||
}
|
||||
|
||||
.delete.field .value{
|
||||
@@ -159,7 +168,6 @@
|
||||
font-size : 13.33px;
|
||||
.navDropdownContainer {
|
||||
background-color : white;
|
||||
width : 100%;
|
||||
position : relative;
|
||||
z-index : 500;
|
||||
&.disabled {
|
||||
@@ -182,24 +190,51 @@
|
||||
}
|
||||
.navDropdown {
|
||||
box-shadow : 0px 5px 10px rgba(0, 0, 0, 0.3);
|
||||
position : absolute;
|
||||
width : 100%;
|
||||
position : absolute;
|
||||
width : 100%;
|
||||
.item {
|
||||
padding : 3px 3px;
|
||||
border-top : 1px solid rgb(118, 118, 118);
|
||||
position : relative;
|
||||
overflow : hidden;
|
||||
padding : 3px 3px;
|
||||
border-top : 1px solid rgb(118, 118, 118);
|
||||
position : relative;
|
||||
overflow : visible;
|
||||
background-color : white;
|
||||
.preview {
|
||||
display : flex;
|
||||
flex-direction: column;
|
||||
background : #ccc;
|
||||
border-radius : 5px;
|
||||
box-shadow : 0 0 5px black;
|
||||
width : 200px;
|
||||
color :black;
|
||||
position : absolute;
|
||||
top : 0;
|
||||
right : 0;
|
||||
opacity : 0;
|
||||
transition : opacity 250ms ease;
|
||||
z-index : 1;
|
||||
overflow :hidden;
|
||||
h6 {
|
||||
font-weight : 900;
|
||||
padding-inline:1em;
|
||||
padding-block :.5em;
|
||||
border-bottom :2px solid hsl(0,0%,40%);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color : @blue;
|
||||
color : white;
|
||||
color : white;
|
||||
}
|
||||
img {
|
||||
mask-image : linear-gradient(90deg, transparent, black 20%);
|
||||
&:hover > .preview {
|
||||
opacity: 1;
|
||||
}
|
||||
>img {
|
||||
mask-image : linear-gradient(90deg, transparent, black 20%);
|
||||
-webkit-mask-image : linear-gradient(90deg, transparent, black 20%);
|
||||
position : absolute;
|
||||
left : ~"max(100px, 100% - 300px)";
|
||||
top : 0px;
|
||||
position : absolute;
|
||||
right : 0;
|
||||
top : 0px;
|
||||
width : 50%;
|
||||
height : 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,6 +242,7 @@
|
||||
}
|
||||
.field .list {
|
||||
display: flex;
|
||||
flex: 1 0;
|
||||
flex-wrap: wrap;
|
||||
|
||||
> * {
|
||||
|
||||
Reference in New Issue
Block a user