Merge master

This commit is contained in:
Mendel Konikov
2018-04-10 20:10:21 -04:00
537 changed files with 14237 additions and 4489 deletions
@@ -0,0 +1,12 @@
---
title: talk-plugin-viewing-options
permalink: /plugin/talk-plugin-viewing-options/
layout: plugin
plugin:
name: talk-plugin-viewing-options
default: true
provides:
- Client
---
Pluginizes the sorting/viewing options for a comment stream.
@@ -0,0 +1,16 @@
.label {
display: block;
cursor: pointer;
width: 100%;
padding: 6px 16px 6px 10px;
box-sizing: border-box;
&:hover {
background-color: rgba(0, 0, 0, 0.05);
}
}
.input {
cursor: pointer;
margin-right: 6px;
}
@@ -0,0 +1,37 @@
import React from 'react';
import cn from 'classnames';
import styles from './SortOption.css';
import PropTypes from 'prop-types';
import { PLUGIN_NAME } from '../../constants';
export default class SortOption extends React.Component {
render() {
const className = cn([
styles.label,
`${PLUGIN_NAME}-sort-option`,
{ [`${PLUGIN_NAME}-sort-option-active`]: this.props.active },
]);
return (
<label className={className}>
<input
type="radio"
onChange={this.props.setSort}
checked={this.props.active}
className={styles.input}
/>
{this.props.label}
</label>
);
}
}
SortOption.propTypes = {
// A simple callback to be called when clicking on this sort option.
setSort: PropTypes.func.isRequired,
// Whether or not this sort option is active.
active: PropTypes.bool.isRequired,
// Label to show next to the input control.
label: PropTypes.string.isRequired,
};
@@ -0,0 +1,13 @@
import withSortOption from 'plugin-api/beta/client/hocs/withSortOption';
import SortOption from '../components/SortOption';
/**
* A factory creating a sort option component.
* @param {string|function} label label to display, can be a callback for lazy evaluation.
* @param {Object} sort sort parameters
* @param {string} sort.sortBy
* @param {string} sort.sortOrder
* @return {Object} Component
*/
export const createSortOption = (label, sort) =>
withSortOption({ ...sort, label })(SortOption);
@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from './Category.css';
import { Slot } from 'plugin-api/beta/client/components';
@@ -8,7 +9,7 @@ const childFactory = child => (
</li>
);
const ViewingOptions = ({ slot, title, data, asset, root }) => {
const Category = ({ slot, title, slotPassthrough }) => {
return (
<div className={styles.root}>
<div className={styles.title}>{title}</div>
@@ -17,11 +18,16 @@ const ViewingOptions = ({ slot, title, data, asset, root }) => {
childFactory={childFactory}
className={styles.list}
component={'ul'}
data={data}
queryData={{ asset, root }}
passthrough={slotPassthrough}
/>
</div>
);
};
export default ViewingOptions;
Category.propTypes = {
slot: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
slotPassthrough: PropTypes.object.isRequired,
};
export default Category;
@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import styles from './Menu.css';
import { capitalize } from 'plugin-api/beta/client/utils';
@@ -13,16 +14,19 @@ class Menu extends React.Component {
};
render() {
const { slotPassthrough } = this.props;
return (
<div className={cn([styles.menu, 'talk-plugin-viewing-options-menu'])}>
{Object.keys(this.categories).map(category => (
<IfSlotIsNotEmpty
slot={`viewingOptions${capitalize(category)}`}
key={category}
passthrough={slotPassthrough}
>
<Category
slot={`viewingOptions${capitalize(category)}`}
title={this.categories[category]}
slotPassthrough={slotPassthrough}
/>
</IfSlotIsNotEmpty>
))}
@@ -31,4 +35,8 @@ class Menu extends React.Component {
}
}
Menu.propTypes = {
slotPassthrough: PropTypes.object.isRequired,
};
export default Menu;
@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import styles from './ViewingOptions.css';
import { t } from 'plugin-api/beta/client/services';
@@ -24,7 +25,7 @@ class ViewingOptions extends React.Component {
};
render() {
const { open, data, root, asset } = this.props;
const { open, slotPassthrough } = this.props;
return (
<ClickOutside onClickOutside={this.handleClickOutside}>
<div className={cn([styles.root, 'talk-plugin-viewing-options'])}>
@@ -41,11 +42,18 @@ class ViewingOptions extends React.Component {
)}
</button>
</div>
{open && <Menu data={data} root={root} asset={asset} />}
{open && <Menu slotPassthrough={slotPassthrough} />}
</div>
</ClickOutside>
);
}
}
ViewingOptions.propTypes = {
slotPassthrough: PropTypes.object.isRequired,
open: PropTypes.bool.isRequired,
openMenu: PropTypes.func.isRequired,
closeMenu: PropTypes.func.isRequired,
};
export default ViewingOptions;
@@ -1,4 +1,6 @@
const prefix = 'TALK_VIEWING_OPTIONS';
export const PLUGIN_NAME = 'talk-plugin-viewing-options';
/* Contants for redux actions */
const prefix = 'TALK_VIEWING_OPTIONS';
export const OPEN_MENU = `${prefix}_OPEN_MENU`;
export const CLOSE_MENU = `${prefix}_CLOSE_MENU`;
@@ -4,6 +4,7 @@ import ViewingOptions from '../components/ViewingOptions';
import { openMenu, closeMenu } from '../actions';
import { compose, gql } from 'react-apollo';
import { getSlotFragmentSpreads } from 'plugin-api/beta/client/utils';
import { mapProps } from 'recompose';
const slots = ['viewingOptionsSort', 'viewingOptionsFilter'];
@@ -29,7 +30,14 @@ const withViewingOptionsFragments = withFragments({
const enhance = compose(
connect(mapStateToProps, mapDispatchToProps),
withViewingOptionsFragments
withViewingOptionsFragments,
mapProps(({ root, asset, ...rest }) => ({
slotPassthrough: {
root,
asset,
},
...rest,
}))
);
export default enhance(ViewingOptions);
@@ -1,3 +1,8 @@
ar:
talk-plugin-viewing-options:
viewing_options: "خيارات العرض"
sort: فرز
filter: تصفية
da:
talk-plugin-viewing-options:
viewing_options: "Viewing Options"