* use the dropdown initializer in post editor options * use dropdown initializer in comment subs dropdown * use Dropdown component in listings * show the dropdown button when it's focused * update storybook notes and components * add cypress tests for post options dropdown * add comment subscription tests * make sure page is properly initialized before setting button functionality * add jsdoc comments, props types, rely on optional chaining * Update app/javascript/crayons/Dropdown/__stories__/dropdowns.md Co-authored-by: rhymes <github@rhymes.dev> * Update app/javascript/crayons/Dropdown/__stories__/dropdowns.md Co-authored-by: rhymes <github@rhymes.dev> Co-authored-by: rhymes <github@rhymes.dev>
128 lines
2.8 KiB
JavaScript
128 lines
2.8 KiB
JavaScript
import { h, Component } from 'preact';
|
|
import PropTypes from 'prop-types';
|
|
|
|
import { Header } from './Header';
|
|
import { AuthorInfo } from './AuthorInfo';
|
|
import { listingPropTypes } from './listingPropTypes';
|
|
|
|
export class SingleListing extends Component {
|
|
listingContent = (
|
|
listing,
|
|
currentUserId,
|
|
onChangeCategory,
|
|
onOpenModal,
|
|
onAddTag,
|
|
isModal = false,
|
|
) => {
|
|
return (
|
|
<div className="relative">
|
|
<Header
|
|
listing={listing}
|
|
currentUserId={currentUserId}
|
|
onTitleClick={onOpenModal}
|
|
onAddTag={onAddTag}
|
|
isModal={isModal}
|
|
/>
|
|
<div
|
|
className="mb-4"
|
|
dangerouslySetInnerHTML={{ __html: listing.processed_html }} // eslint-disable-line react/no-danger
|
|
/>
|
|
<AuthorInfo listing={listing} onCategoryClick={onChangeCategory} />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
listingInline = (
|
|
listing,
|
|
currentUserId,
|
|
onChangeCategory,
|
|
onOpenModal,
|
|
onAddTag,
|
|
) => {
|
|
return (
|
|
<div
|
|
className="single-listing relative crayons-card"
|
|
id={`single-listing-${listing.id}`}
|
|
data-testid={`single-listing-${listing.id}`}
|
|
>
|
|
<div className="listing-content p-4">
|
|
{this.listingContent(
|
|
listing,
|
|
currentUserId,
|
|
onChangeCategory,
|
|
onOpenModal,
|
|
onAddTag,
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
listingModal = (
|
|
listing,
|
|
currentUserId,
|
|
onChangeCategory,
|
|
onOpenModal,
|
|
onAddTag,
|
|
) => {
|
|
return (
|
|
<div
|
|
className="single-listing relative"
|
|
id={`single-listing-${listing.id}`}
|
|
data-testid={`single-listing-${listing.id}`}
|
|
>
|
|
<div className="listing-content">
|
|
{this.listingContent(
|
|
listing,
|
|
currentUserId,
|
|
onChangeCategory,
|
|
onOpenModal,
|
|
onAddTag,
|
|
true,
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
render() {
|
|
const {
|
|
listing,
|
|
currentUserId,
|
|
onChangeCategory,
|
|
onOpenModal,
|
|
isOpen,
|
|
onAddTag,
|
|
} = this.props;
|
|
return isOpen
|
|
? this.listingModal(
|
|
listing,
|
|
currentUserId,
|
|
onChangeCategory,
|
|
onOpenModal,
|
|
onAddTag,
|
|
)
|
|
: this.listingInline(
|
|
listing,
|
|
currentUserId,
|
|
onChangeCategory,
|
|
onOpenModal,
|
|
onAddTag,
|
|
);
|
|
}
|
|
}
|
|
|
|
SingleListing.propTypes = {
|
|
listing: listingPropTypes.isRequired,
|
|
onOpenModal: PropTypes.func.isRequired,
|
|
onChangeCategory: PropTypes.func.isRequired,
|
|
isOpen: PropTypes.bool.isRequired,
|
|
currentUserId: PropTypes.number,
|
|
onAddTag: PropTypes.func.isRequired,
|
|
};
|
|
|
|
SingleListing.defaultProps = {
|
|
currentUserId: null,
|
|
};
|
|
|
|
SingleListing.displayName = 'SingleListing';
|