Implement profile settings

This commit is contained in:
Chi Vinh Le
2018-02-20 13:21:02 +01:00
parent 45dde4636d
commit 0ca8b978a1
21 changed files with 200 additions and 20 deletions
+2 -1
View File
@@ -31,4 +31,5 @@ public
!plugins/talk-plugin-sort-oldest
!plugins/talk-plugin-subscriber
!plugins/talk-plugin-toxic-comments
!plugins/talk-plugin-viewing-options
!plugins/talk-plugin-viewing-options
!plugins/talk-plugin-profile-settings
+1
View File
@@ -52,6 +52,7 @@ plugins/*
!plugins/talk-plugin-subscriber
!plugins/talk-plugin-flag-details
!plugins/talk-plugin-slack-notifications
!plugins/talk-plugin-profile-settings
**/node_modules/*
yarn-error.log
@@ -0,0 +1,3 @@
import * as actions from '../constants/profile';
export const setActiveTab = tab => ({ type: actions.SET_ACTIVE_TAB, tab });
@@ -15,10 +15,6 @@ import IfSlotIsNotEmpty from 'coral-framework/components/IfSlotIsNotEmpty';
import cn from 'classnames';
export default class Embed extends React.Component {
changeTab = tab => {
this.props.setActiveTab(tab);
};
getTabs() {
const tabs = [
<Tab
@@ -53,6 +49,7 @@ export default class Embed extends React.Component {
render() {
const {
activeTab,
setActiveTab,
commentId,
root,
root: { asset },
@@ -65,6 +62,7 @@ export default class Embed extends React.Component {
parentUrl,
} = this.props;
const hasHighlightedComment = !!commentId;
const popupUrl = `login?parentUrl=${encodeURIComponent(parentUrl)}`;
return (
<div
@@ -75,7 +73,7 @@ export default class Embed extends React.Component {
<AutomaticAssetClosure asset={asset} />
<IfSlotIsNotEmpty slot="login">
<Popup
href={`login?parentUrl=${encodeURIComponent(parentUrl)}`}
href={popupUrl}
title="Login"
features="menubar=0,resizable=0,width=500,height=550,top=200,left=500"
open={showSignInDialog}
@@ -91,7 +89,7 @@ export default class Embed extends React.Component {
<ExtendableTabPanel
className="talk-embed-stream-tab-bar"
activeTab={activeTab}
setActiveTab={this.changeTab}
setActiveTab={setActiveTab}
fallbackTab="stream"
tabSlot="embedStreamTabs"
tabSlotPrepend="embedStreamTabsPrepend"
@@ -0,0 +1,2 @@
const prefix = 'TALK_EMBED_STREAM';
export const SET_ACTIVE_TAB = `${prefix}_SET_ACTIVE_TAB`;
@@ -3,6 +3,7 @@ import asset from './asset';
import embed from './embed';
import configure from './configure';
import stream from './stream';
import profile from './profile';
export default {
login,
@@ -10,4 +11,5 @@ export default {
embed,
configure,
stream,
profile,
};
@@ -0,0 +1,19 @@
import * as actions from '../constants/profile';
const initialState = {
activeTab: 'comments',
previousTab: '',
};
export default function stream(state = initialState, action) {
switch (action.type) {
case actions.SET_ACTIVE_TAB:
return {
...state,
activeTab: action.tab,
previousTab: state.activeTab,
};
default:
return state;
}
}
@@ -0,0 +1,11 @@
.userInfo {
margin-bottom: 20px;
}
.email {
margin: 0;
}
.username {
margin-bottom: 4px;
}
@@ -2,17 +2,46 @@ import React from 'react';
import PropTypes from 'prop-types';
import Slot from 'coral-framework/components/Slot';
import CommentHistory from '../containers/CommentHistory';
import ExtendableTabPanel from '../../../containers/ExtendableTabPanel';
import { Tab, TabPane } from 'coral-ui';
import styles from './Profile.css';
import t from 'coral-framework/services/i18n';
const Profile = ({ username, emailAddress, data, root }) => (
<div className="talk-my-profile talk-embed-stream-profile-container">
<h2>{username}</h2>
{emailAddress ? <p>{emailAddress}</p> : null}
const Profile = ({
username,
emailAddress,
data,
root,
activeTab,
setActiveTab,
}) => (
<div className="talk-my-profile talk-profile-container">
<div className={styles.userInfo}>
<h2 className={styles.username}>{username}</h2>
{emailAddress ? <p className={styles.email}>{emailAddress}</p> : null}
</div>
<Slot fill="profileSections" data={data} queryData={{ root }} />
<hr />
<h3>{t('framework.my_comments')}</h3>
<CommentHistory data={data} root={root} />
<ExtendableTabPanel
activeTab={activeTab}
setActiveTab={setActiveTab}
fallbackTab="comments"
tabSlot="profileTabs"
tabSlotPrepend="profileTabsPrepend"
tabPaneSlot="profileTabPanes"
slotProps={{ data }}
queryData={{ root }}
tabs={[
<Tab key="comments" tabId="comments">
{t('framework.my_comments')}
</Tab>,
]}
tabPanes={[
<TabPane key="comments" tabId="comments">
<CommentHistory data={data} root={root} />
</TabPane>,
]}
sub
/>
</div>
);
@@ -21,6 +50,8 @@ Profile.propTypes = {
emailAddress: PropTypes.string,
data: PropTypes.object,
root: PropTypes.object,
activeTab: PropTypes.string.isRequired,
setActiveTab: PropTypes.func.isRequired,
};
export default Profile;
@@ -7,7 +7,7 @@ const slots = ['commentContent', 'historyCommentTimestamp'];
const withCommentFragments = withFragments({
comment: gql`
fragment TalkEmbedStream_Comment_Fragment on Comment {
fragment TalkEmbedStream_ProfileComment_comment on Comment {
id
body
replyCount
@@ -11,6 +11,7 @@ import CommentHistory from './CommentHistory';
import { getDefinitionName } from 'coral-framework/utils';
import { showSignInDialog } from 'coral-embed-stream/src/actions/login';
import { setActiveTab } from '../../../actions/profile';
import { getSlotFragmentSpreads } from 'coral-framework/utils';
class ProfileContainer extends Component {
@@ -47,6 +48,8 @@ class ProfileContainer extends Component {
emailAddress={emailAddress}
data={data}
root={root}
activeTab={this.props.activeTab}
setActiveTab={this.props.setActiveTab}
/>
);
}
@@ -57,9 +60,16 @@ ProfileContainer.propTypes = {
root: PropTypes.object,
currentUser: PropTypes.object,
showSignInDialog: PropTypes.func,
activeTab: PropTypes.string.isRequired,
setActiveTab: PropTypes.func.isRequired,
};
const slots = ['profileSections'];
const slots = [
'profileSections',
'profileTabs',
'profileTabsPrepend',
'profileTabPanes',
];
const withProfileQuery = withQuery(
gql`
@@ -82,10 +92,11 @@ const withProfileQuery = withQuery(
const mapStateToProps = state => ({
currentUser: state.auth.user,
activeTab: state.profile.activeTab,
});
const mapDispatchToProps = dispatch =>
bindActionCreators({ showSignInDialog }, dispatch);
bindActionCreators({ showSignInDialog, setActiveTab }, dispatch);
export default compose(
connect(mapStateToProps, mapDispatchToProps),
+2 -1
View File
@@ -21,6 +21,7 @@
"talk-plugin-sort-most-respected",
"talk-plugin-sort-newest",
"talk-plugin-sort-oldest",
"talk-plugin-viewing-options"
"talk-plugin-viewing-options",
"talk-plugin-profile-settings"
]
}
@@ -8,7 +8,7 @@ export default {
slots: {
authorMenuActions: [IgnoreUserAction],
ignoreUserConfirmation: [IgnoreUserConfirmation],
profileSections: [IgnoredUserSection],
profileSettings: [IgnoredUserSection],
},
translations,
mutations: {
@@ -0,0 +1,3 @@
{
"extends": "@coralproject/eslint-config-talk"
}
@@ -0,0 +1,3 @@
{
"extends": "@coralproject/eslint-config-talk/client"
}
@@ -0,0 +1,8 @@
import React from 'react';
import { t } from 'plugin-api/beta/client/services';
const Tab = () => {
return <span>{t('talk-plugin-profile-settings.tab')}</span>;
};
export default Tab;
@@ -0,0 +1,21 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Slot } from 'plugin-api/beta/client/components';
class TabPane extends React.Component {
render() {
const { data, root } = this.props;
return (
<div>
<Slot fill="profileSettings" data={data} queryData={{ root }} />
</div>
);
}
}
TabPane.propTypes = {
data: PropTypes.object,
root: PropTypes.object,
};
export default TabPane;
@@ -0,0 +1,26 @@
import React from 'react';
import { compose, gql } from 'react-apollo';
import TabPane from '../components/TabPane';
import { withFragments } from 'plugin-api/beta/client/hocs';
import { getSlotFragmentSpreads } from 'plugin-api/beta/client/utils';
const slots = ['profileSettings'];
class TabPaneContainer extends React.Component {
render() {
return <TabPane {...this.props} />;
}
}
const enhance = compose(
withFragments({
root: gql`
fragment TalkProfileSettings_TabPane_root on RootQuery {
__typename
${getSlotFragmentSpreads(slots, 'root')}
}
`,
})
);
export default enhance(TabPaneContainer);
@@ -0,0 +1,11 @@
import Tab from './components/Tab';
import TabPane from './containers/TabPane';
import translations from './translations.yml';
export default {
slots: {
profileTabs: [Tab],
profileTabPanes: [TabPane],
},
translations,
};
@@ -0,0 +1,27 @@
en:
talk-plugin-profile-settings:
tab: Settings
de:
talk-plugin-profile-settings:
tab: Einstellungen
es:
talk-plugin-profile-settings:
tab: Configuración
fr:
talk-plugin-profile-settings:
tab: Paramètres
nl_NL:
talk-plugin-profile-settings:
tab: Instellingen
da:
talk-plugin-profile-settings:
tab: Indstillinger
pt_PR:
talk-plugin-profile-settings:
tab: Configurações
zh_TW:
talk-plugin-profile-settings:
tab: 設置
zh_CN:
talk-plugin-profile-settings:
tab: 设置
@@ -0,0 +1 @@
module.exports = {};