mirror of
https://github.com/wassname/talk.git
synced 2026-07-26 13:37:38 +08:00
Implement profile settings
This commit is contained in:
+2
-1
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 = {};
|
||||
Reference in New Issue
Block a user