0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-07 14:12:43 +00:00

initial commit

This commit is contained in:
Víctor Losada Hernández
2024-10-23 12:45:13 +02:00
parent c723f820f7
commit 68831c759f

View File

@@ -1,6 +1,6 @@
require('./brewItem.less'); require('./brewItem.less');
const React = require('react'); const React = require('react');
const createClass = require('create-react-class'); const { useCallback } = React;
const moment = require('moment'); const moment = require('moment');
const request = require('../../../../utils/request-middleware.js'); const request = require('../../../../utils/request-middleware.js');
@@ -8,176 +8,172 @@ const googleDriveIcon = require('../../../../googleDrive.svg');
const homebreweryIcon = require('../../../../thumbnail.png'); const homebreweryIcon = require('../../../../thumbnail.png');
const dedent = require('dedent-tabs').default; const dedent = require('dedent-tabs').default;
const BrewItem = createClass({ const BrewItem = ({
displayName : 'BrewItem', brew = {
getDefaultProps : function() { title : '',
return { description : '',
brew : { authors : [],
title : '', stubbed : true,
description : '',
authors : [],
stubbed : true
},
updateListFilter : ()=>{},
reportError : ()=>{},
renderStorage : true
};
}, },
updateListFilter = ()=>{},
reportError = ()=>{},
renderStorage = true,
})=>{
deleteBrew : function(){ const deleteBrew = useCallback(()=>{
if(this.props.brew.authors.length <= 1){ if(brew.authors.length <= 1) {
if(!confirm('Are you sure you want to delete this brew? Because you are the only owner of this brew, the document will be deleted permanently.')) return; if(!window.confirm('Are you sure you want to delete this brew? Because you are the only owner of this brew, the document will be deleted permanently.')) return;
if(!confirm('Are you REALLY sure? You will not be able to recover the document.')) return; if(!window.confirm('Are you REALLY sure? You will not be able to recover the document.')) return;
} else { } else {
if(!confirm('Are you sure you want to remove this brew from your collection? This will remove you as an editor, but other owners will still be able to access the document.')) return; if(!window.confirm('Are you sure you want to remove this brew from your collection? This will remove you as an editor, but other owners will still be able to access the document.')) return;
if(!confirm('Are you REALLY sure? You will lose editor access to this document.')) return; if(!window.confirm('Are you REALLY sure? You will lose editor access to this document.')) return;
} }
request.delete(`/api/${this.props.brew.googleId ?? ''}${this.props.brew.editId}`) request.delete(`/api/${brew.googleId ?? ''}${brew.editId}`).send().end((err, res)=>{
.send() if (err) reportError(err); else window.location.reload();
.end((err, res)=>{ });
if(err) { }, [brew, reportError]);
this.props.reportError(err);
} else {
location.reload();
}
});
},
updateFilter : function(type, term){ const updateFilter = useCallback((type, term)=> updateListFilter(type, term), [updateListFilter]);
this.props.updateListFilter(type, term);
},
renderDeleteBrewLink : function(){ const renderDeleteBrewLink = ()=>{
if(!this.props.brew.editId) return; if(!brew.editId) return null;
return <a className='deleteLink' onClick={this.deleteBrew}> return (
<i className='fas fa-trash-alt' title='Delete' /> <a className='deleteLink' onClick={deleteBrew}>
</a>; <i className='fas fa-trash-alt' title='Delete' />
}, </a>
);
};
renderEditLink : function(){ const renderEditLink = ()=>{
if(!this.props.brew.editId) return; if(!brew.editId) return null;
let editLink = this.props.brew.editId; let editLink = brew.editId;
if(this.props.brew.googleId && !this.props.brew.stubbed) { if(brew.googleId && !brew.stubbed) editLink = brew.googleId + editLink;
editLink = this.props.brew.googleId + editLink;
return (
<a className='editLink' href={`/edit/${editLink}`} target='_blank' rel='noopener noreferrer'>
<i className='fas fa-pencil-alt' title='Edit' />
</a>
);
};
const renderShareLink = ()=>{
if(!brew.shareId) return null;
let shareLink = brew.shareId;
if(brew.googleId && !brew.stubbed) {
shareLink = brew.googleId + shareLink;
} }
return <a className='editLink' href={`/edit/${editLink}`} target='_blank' rel='noopener noreferrer'> return (
<i className='fas fa-pencil-alt' title='Edit' /> <a className='shareLink' href={`/share/${shareLink}`} target='_blank' rel='noopener noreferrer'>
</a>; <i className='fas fa-share-alt' title='Share' />
}, </a>
);
};
renderShareLink : function(){ const renderDownloadLink = ()=>{
if(!this.props.brew.shareId) return; if(!brew.shareId) return null;
let shareLink = this.props.brew.shareId; let shareLink = brew.shareId;
if(this.props.brew.googleId && !this.props.brew.stubbed) { if(brew.googleId && !brew.stubbed) {
shareLink = this.props.brew.googleId + shareLink; shareLink = brew.googleId + shareLink;
} }
return <a className='shareLink' href={`/share/${shareLink}`} target='_blank' rel='noopener noreferrer'> return (
<i className='fas fa-share-alt' title='Share' /> <a className='downloadLink' href={`/download/${shareLink}`}>
</a>; <i className='fas fa-download' title='Download' />
}, </a>
);
};
renderDownloadLink : function(){ const renderStorageIcon = ()=>{
if(!this.props.brew.shareId) return; if(!renderStorage) return null;
if(brew.googleId) {
let shareLink = this.props.brew.shareId; return (
if(this.props.brew.googleId && !this.props.brew.stubbed) { <span title={brew.webViewLink ? 'Your Google Drive Storage' : 'Another User\'s Google Drive Storage'}>
shareLink = this.props.brew.googleId + shareLink; <a href={brew.webViewLink} target='_blank'>
<img className='googleDriveIcon' src={googleDriveIcon} alt='googleDriveIcon' />
</a>
</span>
);
} }
return <a className='downloadLink' href={`/download/${shareLink}`}> return (
<i className='fas fa-download' title='Download' /> <span title='Homebrewery Storage'>
</a>; <img className='homebreweryIcon' src={homebreweryIcon} alt='homebreweryIcon' />
}, </span>
);
};
renderStorageIcon : function(){ if(Array.isArray(brew.tags)) {
if(!this.props.renderStorage) return; brew.tags = brew.tags?.filter((tag)=>tag); // remove tags that are empty strings
if(this.props.brew.googleId) { brew.tags.sort((a, b)=>{
return <span title={this.props.brew.webViewLink ? 'Your Google Drive Storage': 'Another User\'s Google Drive Storage'}> return a.indexOf(':') - b.indexOf(':') !== 0 ? a.indexOf(':') - b.indexOf(':') : a.toLowerCase().localeCompare(b.toLowerCase());
<a href={this.props.brew.webViewLink} target='_blank'> });
<img className='googleDriveIcon' src={googleDriveIcon} alt='googleDriveIcon' /> }
</a>
</span>;
}
return <span title='Homebrewery Storage'> const dateFormatString = 'YYYY-MM-DD HH:mm:ss';
<img className='homebreweryIcon' src={homebreweryIcon} alt='homebreweryIcon' />
</span>;
},
render : function(){ return (
const brew = this.props.brew; <div className='brewItem'>
if(Array.isArray(brew.tags)) { // temporary fix until dud tags are cleaned {brew.thumbnail && <div className='thumbnail' style={{ backgroundImage: `url(${brew.thumbnail})` }}></div>}
brew.tags = brew.tags?.filter((tag)=>tag); //remove tags that are empty strings
brew.tags.sort((a, b)=>{
return a.indexOf(':') - b.indexOf(':') != 0 ? a.indexOf(':') - b.indexOf(':') : a.toLowerCase().localeCompare(b.toLowerCase());
});
}
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'> <div className='text'>
<h2>{brew.title}</h2> <h2>{brew.title}</h2>
<p className='description'>{brew.description}</p> <p className='description'>{brew.description}</p>
</div> </div>
<hr /> <hr />
<div className='info'> <div className='info'>
{brew.tags?.length ? (
{brew.tags?.length ? <>
<div className='brewTags' title={`${brew.tags.length} tags:\n${brew.tags.join('\n')}`}> <div className='brewTags' title={`${brew.tags.length} tags:\n${brew.tags.join('\n')}`}>
<i className='fas fa-tags'/> <i className='fas fa-tags' />
{brew.tags.map((tag, idx)=>{ {brew.tags.map((tag, idx)=>{
const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/); const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/);
return <span key={idx} className={matches[1]} onClick={()=>{this.updateFilter(tag);}}>{matches[2]}</span>; return <span key={idx} className={matches[1]} onClick={()=>updateFilter(tag)}>{matches[2]}</span>;
})} })}
</div> </div>
</> : <></> ) : null}
}
<span title={`Authors:\n${brew.authors?.join('\n')}`}> <span title={`Authors:\n${brew.authors?.join('\n')}`}>
<i className='fas fa-user'/> {brew.authors?.map((author, index)=>( <i className='fas fa-user' />{' '}
{brew.authors?.map((author, index)=>(
<React.Fragment key={index}> <React.Fragment key={index}>
{author === 'hidden' {author === 'hidden' ? (
? <span title="Username contained an email address; hidden to protect user's privacy">{author}</span> <span title="Username contained an email address; hidden to protect user's privacy">
: <a href={`/user/${author}`}>{author}</a> {author}
} </span>
) : (<a href={`/user/${author}`}>{author}</a>)}
{index < brew.authors.length - 1 && ', '} {index < brew.authors.length - 1 && ', '}
</React.Fragment> </React.Fragment>
))} ))}
</span> </span>
<br /> <br />
<span title={`Last viewed: ${moment(brew.lastViewed).local().format(dateFormatString)}`}> <span title={`Last viewed: ${moment(brew.lastViewed).local().format(dateFormatString)}`}>
<i className='fas fa-eye'/> {brew.views} <i className='fas fa-eye' /> {brew.views}
</span> </span>
{brew.pageCount && {brew.pageCount && (
<span title={`Page count: ${brew.pageCount}`}> <span title={`Page count: ${brew.pageCount}`}>
<i className='far fa-file' /> {brew.pageCount} <i className='far fa-file' /> {brew.pageCount}
</span> </span>
} )}
<span title={dedent` <span
Created: ${moment(brew.createdAt).local().format(dateFormatString)} title={dedent` Created: ${moment(brew.createdAt).local().format(dateFormatString)}
Last updated: ${moment(brew.updatedAt).local().format(dateFormatString)}`}> Last updated: ${moment(brew.updatedAt).local().format(dateFormatString)}`}
>
<i className='fas fa-sync-alt' /> {moment(brew.updatedAt).fromNow()} <i className='fas fa-sync-alt' /> {moment(brew.updatedAt).fromNow()}
</span> </span>
{this.renderStorageIcon()} {renderStorageIcon()}
</div> </div>
<div className='links'> <div className='links'>
{this.renderShareLink()} {renderShareLink()}
{this.renderEditLink()} {renderEditLink()}
{this.renderDownloadLink()} {renderDownloadLink()}
{this.renderDeleteBrewLink()} {renderDeleteBrewLink()}
</div> </div>
</div>; </div>
} );
}); };
module.exports = BrewItem; module.exports = BrewItem;