Implement talk-plugin-author-menu

This commit is contained in:
Chi Vinh Le
2017-09-01 22:20:49 +07:00
parent 824abcdfa3
commit 692d92f645
16 changed files with 270 additions and 1 deletions
+1
View File
@@ -19,5 +19,6 @@ plugins/*
!plugins/talk-plugin-sort-most-liked
!plugins/talk-plugin-sort-most-loved
!plugins/talk-plugin-sort-most-respected
!plugins/talk-plugin-author-menu
node_modules
+1
View File
@@ -35,5 +35,6 @@ plugins/*
!plugins/talk-plugin-sort-most-liked
!plugins/talk-plugin-sort-most-loved
!plugins/talk-plugin-sort-most-respected
!plugins/talk-plugin-author-menu
**/node_modules/*
@@ -0,0 +1,14 @@
{
"presets": [
"es2015"
],
"plugins": [
"add-module-exports",
"transform-class-properties",
"transform-decorators-legacy",
"transform-object-assign",
"transform-object-rest-spread",
"transform-async-to-generator",
"transform-react-jsx"
]
}
@@ -0,0 +1,23 @@
{
"env": {
"browser": true,
"es6": true,
"mocha": true
},
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true
}
},
"parser": "babel-eslint",
"plugins": [
"react"
],
"rules": {
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"no-console": ["warn", { "allow": ["warn", "error"] }]
}
}
@@ -0,0 +1,10 @@
import {SET_CONTENT_SLOT, RESET_CONTENT_SLOT} from './constants';
export const setContentSlot = (slot) => ({
type: SET_CONTENT_SLOT,
slot,
});
export const resetContentSlot = () => ({
type: RESET_CONTENT_SLOT,
});
@@ -0,0 +1,13 @@
.root {
display: inline-block;
position: relative;
}
.button {
composes: buttonReset from "coral-framework/styles/reset.css";
}
.name {
font-weight: bold;
}
@@ -0,0 +1,30 @@
import React from 'react';
import Menu from './Menu';
import styles from './AuthorName.css';
import {ClickOutside} from 'plugin-api/beta/client/components';
export default ({data, root, asset, comment, contentSlot, menuVisible, toggleMenu, hideMenu}) => {
return (
<ClickOutside onClickOutside={hideMenu}>
<div className={styles.root}>
<button
className={styles.button}
onClick={toggleMenu}
>
<span className={styles.name}>
{comment.user.username}
</span>
</button>
{menuVisible &&
<Menu
data={data}
root={root}
asset={asset}
comment={comment}
contentSlot={contentSlot}
/>
}
</div>
</ClickOutside>
);
};
@@ -0,0 +1,37 @@
.menu {
background-color: white;
border: solid 1px #999;
border-radius: 3px;
padding: 10px;
position: absolute;
-webkit-box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);
z-index: 10;
top: 26px;
left: 0px;
min-width: 20px;
text-align: left;
color: #616161;
}
.menu::before{
content: '';
border: 10px solid transparent;
border-top-color: #999;
position: absolute;
left: 6px;
top: -21px;
transform: rotate(180deg);
}
.menu::after{
content: '';
border: 10px solid transparent;
border-top-color: white;
position: absolute;
left: 6px;
top: -20px;
transform: rotate(180deg);
}
@@ -0,0 +1,18 @@
import React from 'react';
import styles from './Menu.css';
import {Slot} from 'plugin-api/beta/client/components';
export default ({data, root, asset, comment}) => (
<div className={styles.menu}>
<Slot
fill={'authorMenuInfos'}
data={data}
queryData={{asset, root, comment}}
/>
<Slot
fill={'authorMenuActions'}
data={data}
queryData={{asset, root, comment}}
/>
</div>
);
@@ -0,0 +1,5 @@
const prefix = 'TALK_AUTHOR_MENU';
export const SET_CONTENT_SLOT = `${prefix}_SET_CONTENT_SLOT`;
export const RESET_CONTENT_SLOT = `${prefix}_RESET_CONTENT_SLOT`;
@@ -0,0 +1,79 @@
import React from 'react';
import {connect, withFragments} from 'plugin-api/beta/client/hocs';
import {bindActionCreators} from 'redux';
import AuthorName from '../components/AuthorName';
import {setContentSlot, resetContentSlot} from '../actions';
import {compose, gql} from 'react-apollo';
import {getSlotFragmentSpreads} from 'plugin-api/beta/client/utils';
class AuthorNameContainer extends React.Component {
state = {
menuVisible: false
};
toggleMenu = () => {
this.setState({
menuVisible: !this.state.menuVisible,
});
}
hideMenu = () => {
if (this.state.menuVisible) {
this.setState({
menuVisible: false
});
}
}
render() {
return <AuthorName
data={this.props.data}
root={this.props.root}
asset={this.props.asset}
comment={this.props.comment}
menuVisible={this.state.menuVisible}
toggleMenu={this.toggleMenu}
hideMenu={this.hideMenu}
/>;
}
}
const slots = [
'authorMenuInfos',
'authorMenuActions',
];
const mapStateToProps = ({talkPluginAuthorMenu: state}) => ({
contentSlot: state.contentSlot,
});
const mapDispatchToProps = (dispatch) =>
bindActionCreators({setContentSlot, resetContentSlot}, dispatch);
const withAuthorNameFragments = withFragments({
root: gql`
fragment TalkAuthorMenu_AuthorName_root on RootQuery {
__typename
${getSlotFragmentSpreads(slots, 'root')}
}`,
asset: gql`
fragment TalkAuthorMenu_AuthorName_asset on Asset {
__typename
${getSlotFragmentSpreads(slots, 'asset')}
}`,
comment: gql`
fragment TalkAuthorMenu_AuthorName_comment on Comment {
__typename
user {
username
}
${getSlotFragmentSpreads(slots, 'comment')}
}`,
});
const enhance = compose(
connect(mapStateToProps, mapDispatchToProps),
withAuthorNameFragments,
);
export default enhance(AuthorNameContainer);
@@ -0,0 +1,11 @@
import AuthorName from './containers/AuthorName';
import reducer from './reducer';
import translations from './translations.yml';
export default {
reducer,
slots: {
commentAuthorName: [AuthorName]
},
translations
};
@@ -0,0 +1,22 @@
import {SET_CONTENT_SLOT, RESET_CONTENT_SLOT} from './constants';
const initialState = {
contentSlot: null,
};
export default function reducer(state = initialState, action) {
switch (action.type) {
case SET_CONTENT_SLOT:
return {
...state,
contentSlot: action.slot,
};
case RESET_CONTENT_SLOT:
return {
...state,
contentSlot: initialState.contentSlot,
};
default :
return state;
}
}
@@ -0,0 +1,4 @@
en:
talk-plugin-author-menu:
es:
talk-plugin-author-menu:
+1
View File
@@ -0,0 +1 @@
module.exports = {};
+1 -1
View File
@@ -5,5 +5,5 @@ export default {
translations,
slots: {
commentReactions: [LikeButton]
}
},
};