Move profile settings to core

This commit is contained in:
Chi Vinh Le
2018-03-13 17:48:54 +01:00
parent 5bb5f98b17
commit 9ad92e38c0
23 changed files with 190 additions and 152 deletions
@@ -1,24 +1,10 @@
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';
import TabPanel from '../containers/TabPanel';
const Profile = ({
username,
emailAddress,
data,
root,
activeTab,
setActiveTab,
}) => {
const slotPassthrough = {
data,
root,
};
const Profile = ({ username, emailAddress, data, root, slotPassthrough }) => {
return (
<div className="talk-my-profile talk-profile-container">
<div className={styles.userInfo}>
@@ -26,26 +12,7 @@ const Profile = ({
{emailAddress ? <p className={styles.email}>{emailAddress}</p> : null}
</div>
<Slot fill="profileSections" passthrough={slotPassthrough} />
<ExtendableTabPanel
activeTab={activeTab}
setActiveTab={setActiveTab}
fallbackTab="comments"
tabSlot="profileTabs"
tabSlotPrepend="profileTabsPrepend"
tabPaneSlot="profileTabPanes"
slotPassthrough={slotPassthrough}
tabs={[
<Tab key="comments" tabId="comments">
{t('framework.my_comments')}
</Tab>,
]}
tabPanes={[
<TabPane key="comments" tabId="comments">
<CommentHistory data={data} root={root} />
</TabPane>,
]}
sub
/>
<TabPanel data={data} root={root} slotPassthrough={slotPassthrough} />
</div>
);
};
@@ -55,8 +22,7 @@ Profile.propTypes = {
emailAddress: PropTypes.string,
data: PropTypes.object,
root: PropTypes.object,
activeTab: PropTypes.string.isRequired,
setActiveTab: PropTypes.func.isRequired,
slotPassthrough: PropTypes.object,
};
export default Profile;
@@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Slot } from 'plugin-api/beta/client/components';
import { Slot } from 'coral-framework/components';
class TabPane extends React.Component {
class Settings extends React.Component {
render() {
const { data, root } = this.props;
const slotPassthrough = { data, root };
@@ -14,9 +14,9 @@ class TabPane extends React.Component {
}
}
TabPane.propTypes = {
Settings.propTypes = {
data: PropTypes.object,
root: PropTypes.object,
};
export default TabPane;
export default Settings;
@@ -0,0 +1,63 @@
import React from 'react';
import PropTypes from 'prop-types';
import CommentHistory from '../containers/CommentHistory';
import ExtendableTabPanel from '../../../containers/ExtendableTabPanel';
import { Tab, TabPane } from 'coral-ui';
import t from 'coral-framework/services/i18n';
import Settings from '../containers/Settings';
const TabPanel = ({
data,
root,
activeTab,
setActiveTab,
showSettingsTab,
slotPassthrough,
}) => {
const tabs = [
<Tab key="comments" tabId="comments">
{t('framework.my_comments')}
</Tab>,
];
if (showSettingsTab) {
tabs.push(
<Tab key="settings" tabId="settings">
{t('profile_settings')}
</Tab>
);
}
return (
<ExtendableTabPanel
activeTab={activeTab}
setActiveTab={setActiveTab}
fallbackTab="comments"
tabSlot="profileTabs"
tabSlotPrepend="profileTabsPrepend"
tabPaneSlot="profileTabPanes"
slotPassthrough={slotPassthrough}
tabs={tabs}
tabPanes={[
<TabPane key="comments" tabId="comments">
<CommentHistory data={data} root={root} />
</TabPane>,
<TabPane key="settings" tabId="settings">
<Settings data={data} root={root} />
</TabPane>,
]}
sub
/>
);
};
TabPanel.propTypes = {
data: PropTypes.object,
root: PropTypes.object,
slotPassthrough: PropTypes.object,
activeTab: PropTypes.string.isRequired,
setActiveTab: PropTypes.func.isRequired,
showSettingsTab: PropTypes.bool.isRequired,
};
export default TabPanel;
@@ -7,11 +7,10 @@ import { withQuery } from 'coral-framework/hocs';
import NotLoggedIn from '../components/NotLoggedIn';
import { Spinner } from 'coral-ui';
import Profile from '../components/Profile';
import CommentHistory from './CommentHistory';
import TabPanel from './TabPanel';
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 {
@@ -41,6 +40,7 @@ class ProfileContainer extends Component {
const localProfile = currentUser.profiles.find(p => p.provider === 'local');
const emailAddress = localProfile && localProfile.id;
const slotPassthrough = { data, root };
return (
<Profile
@@ -48,8 +48,7 @@ class ProfileContainer extends Component {
emailAddress={emailAddress}
data={data}
root={root}
activeTab={this.props.activeTab}
setActiveTab={this.props.setActiveTab}
slotPassthrough={slotPassthrough}
/>
);
}
@@ -60,16 +59,9 @@ ProfileContainer.propTypes = {
root: PropTypes.object,
currentUser: PropTypes.object,
showSignInDialog: PropTypes.func,
activeTab: PropTypes.string.isRequired,
setActiveTab: PropTypes.func.isRequired,
};
const slots = [
'profileSections',
'profileTabs',
'profileTabsPrepend',
'profileTabPanes',
];
const slots = ['profileSections'];
const withProfileQuery = withQuery(
gql`
@@ -78,10 +70,10 @@ const withProfileQuery = withQuery(
id
username
}
...${getDefinitionName(CommentHistory.fragments.root)}
...${getDefinitionName(TabPanel.fragments.root)}
${getSlotFragmentSpreads(slots, 'root')}
}
${CommentHistory.fragments.root}
${TabPanel.fragments.root}
`,
{
options: {
@@ -92,11 +84,10 @@ const withProfileQuery = withQuery(
const mapStateToProps = state => ({
currentUser: state.auth.user,
activeTab: state.profile.activeTab,
});
const mapDispatchToProps = dispatch =>
bindActionCreators({ showSignInDialog, setActiveTab }, dispatch);
bindActionCreators({ showSignInDialog }, dispatch);
export default compose(
connect(mapStateToProps, mapDispatchToProps),
@@ -0,0 +1,26 @@
import React from 'react';
import { compose, gql } from 'react-apollo';
import Settings from '../components/Settings';
import { withFragments } from 'coral-framework/hocs';
import { getSlotFragmentSpreads } from 'coral-framework/utils';
const slots = ['profileSettings'];
class SettingsContainer extends React.Component {
render() {
return <Settings {...this.props} />;
}
}
const enhance = compose(
withFragments({
root: gql`
fragment TalkEmbedStream_ProfileSettings_root on RootQuery {
__typename
${getSlotFragmentSpreads(slots, 'root')}
}
`,
})
);
export default enhance(SettingsContainer);
@@ -0,0 +1,66 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { compose, gql } from 'react-apollo';
import { bindActionCreators } from 'redux';
import { withSlotElements, withFragments } from 'coral-framework/hocs';
import Settings from './Settings';
import CommentHistory from './CommentHistory';
import { getDefinitionName } from 'coral-framework/utils';
import TabPanel from '../components/TabPanel';
import { setActiveTab } from '../../../actions/profile';
import { getSlotFragmentSpreads } from 'coral-framework/utils';
class TabPanelContainer extends Component {
render() {
return (
<TabPanel
data={this.props.data}
root={this.props.root}
slotPassthrough={this.props.slotPassthrough}
activeTab={this.props.activeTab}
setActiveTab={this.props.setActiveTab}
showSettingsTab={this.props.profileSettingsSlotElements.length > 0}
/>
);
}
}
TabPanelContainer.propTypes = {
data: PropTypes.object,
root: PropTypes.object,
slotPassthrough: PropTypes.object,
activeTab: PropTypes.string.isRequired,
setActiveTab: PropTypes.func.isRequired,
profileSettingsSlotElements: PropTypes.array.isRequired,
};
const slots = ['profileTabs', 'profileTabsPrepend', 'profileTabPanes'];
const mapStateToProps = state => ({
activeTab: state.profile.activeTab,
});
const mapDispatchToProps = dispatch =>
bindActionCreators({ setActiveTab }, dispatch);
export default compose(
withFragments({
root: gql`
fragment TalkEmbedStream_ProfileTabPanel_root on RootQuery {
__typename
...${getDefinitionName(CommentHistory.fragments.root)}
...${getDefinitionName(Settings.fragments.root)}
${getSlotFragmentSpreads(slots, 'root')}
}
${CommentHistory.fragments.root}
${Settings.fragments.root}
`,
}),
connect(mapStateToProps, mapDispatchToProps),
withSlotElements({
slot: 'profileSettings',
propName: 'profileSettingsSlotElements',
passthroughPropName: 'slotPassthrough',
})
)(TabPanelContainer);
@@ -19,6 +19,7 @@ const createHOC = ({
defaultComponent = null,
passthroughPropName = 'passthrough',
size = null,
propName = 'slotElements',
}) =>
hoistStatics(WrappedComponent => {
return class withSlotElements extends React.Component {
@@ -140,7 +141,7 @@ const createHOC = ({
const { reduxState: _a, ...rest } = this.props;
const slotElements = this.getSlotElements();
const props = {
slotElements,
[propName]: slotElements,
...rest,
};
return <WrappedComponent {...props} />;
@@ -159,9 +160,11 @@ const mapStateToProps = state => ({
* @param {element|array} [options.defaultComponent] Default Components or Array of such
* @param {number|array} [options.size] Slot size or an Array of slot size
* @param {string} [options.passthroughPropName] The property to find the passthrough prop
* @param {string} [options.propName] New property name, defaults to `slotElements`
*
* @return {func} Returns a HOC that provides the property `slotElements` with an Array of
* Slot Elements or in case of multiple slots, an Array of Slot Element Arrays.
* @return {func} Returns a HOC that per default provides the property `slotElements` with an
* Array of Slot Elements or in case of multiple slots, an Array of Slot Element
* Arrays.
*
* Example:
* withSlotElements({
+3 -3
View File
@@ -16,7 +16,7 @@ da:
send: "Send"
notify_ban_headline: "Notify the user of ban"
notify_ban_description: "This will notify the user by email that they have been banned from the community"
email_message_ban: "Dear {0},\n\nSomeone with access to your account has violated our community guidelines. As a result, your account has been banned. You will no longer be able to comment, like or report comments. if you think this has been done in error, please contact our community team."
email_message_ban: "Dear {0},\n\nSomeone with access to your account has violated our community guidelines. As a result, your account has been banned. You will no longer be able to comment, like or report comments. if you think this has been done in error, please contact our community team."
bio_offensive: "Denne biografi er stødende"
cancel: "Afbryd"
confirm_email:
@@ -256,7 +256,7 @@ da:
label: "Nyt brugernavn"
msg: "Din konto er midlertidigt suspenderet, fordi dit brugernavn er blevet anset for upassende. For at gendanne din konto skal du indtaste et nyt brugernavn. Kontakt os venligst, hvis du har spørgsmål."
changed_name:
msg: "Your username change is under review by our moderation team."
msg: "Your username change is under review by our moderation team."
my_comments: "Mine kommentarer"
my_profile: "Min profil"
new_count: "Se {0} mere {1}"
@@ -350,7 +350,7 @@ da:
personal_info: "Denne kommentar afslører personligt identificerbare oplysninger"
post: "Post"
profile: "Profil"
profile_settings: "Profilindstillinger"
profile_settings: "Indstillinger"
reply: "Svar"
report: "Rapporter"
report_notif: "Tak fordi du rapporterede denne kommentar. Vores modereringsteam har fået besked, og vil gennemgå det inden for kort tid."
+2 -2
View File
@@ -349,7 +349,7 @@ de:
personal_info: "Dieser Kommentar enthält zu viel personenbezogene Daten"
post: Post # Kontext?
profile: Profil
profile_settings: "Profil-Einstellungen"
profile_settings: "Einstellungen"
reply: Antworten
report: Melden
report_notif: "Vielen Dank für Ihre Meldung. Unsere Moderatoren wurden informiert und werden sich in Kürze darum kümmern."
@@ -397,7 +397,7 @@ de:
suspend_user: "Nutzer vorübergehend sperren"
email_message_suspend: "Sehr geehrte/r {0}, entsprechend der Community-Richtlinien von {1} wurde Ihr Konto vorübergehend gesperrt. Während der Sperrung können Sie weder kommentieren noch andere Aktionen ausführen. Nehmen Sie {2} wieder an der Diskussion teil."
title_notify: "Den Nutzer über die vorübergehende Kontosperrung informieren"
notify_suspend_until: "Nutzer {0} wurde vorübergehend gesperrt. Diese Sperrung endet automatisch {1}."
notify_suspend_until: "Nutzer {0} wurde vorübergehend gesperrt. Diese Sperrung endet automatisch {1}."
description_notify: "Während der Sperrung hat der Nutzer keinen Zugriff auf das Konto."
write_message: "Nachricht verfassen"
send: Senden
+1 -1
View File
@@ -352,7 +352,7 @@ en:
personal_info: "This comment reveals personally identifiable information"
post: Post
profile: Profile
profile_settings: "Profile Settings"
profile_settings: "Settings"
reply: Reply
report: Report
report_notif: "Thank you for reporting this comment. Our moderation team has been notified and will review it shortly."
+1 -1
View File
@@ -351,7 +351,7 @@ es:
personal_info: "Este comentario muestra información personal"
post: Publicar
profile: Perfil
profile_settings: "Configuración del Perfil"
profile_settings: "Configuración"
reply: Responder
report: Reportar
report_notif: "Gracias por reportar este comentario. Nuestro equipo de moderación ha sido notificado y muy pronto lo va a revisar."
+1 -1
View File
@@ -351,7 +351,7 @@ fr:
personal_info: "Ce commentaire révèle des informations personnelles identifiables"
post: Publier
profile: Profil
profile_settings: "Paramètres du profil"
profile_settings: "Paramètres"
reply: Répondre
report: Signaler
report_notif: "Merci de signaler ce commentaire. Notre équipe de modération a é té informée."
+2 -2
View File
@@ -65,7 +65,7 @@ nl_NL:
notify_approved: '{0} heeft gebruikersnaam {1} goedgekeurd'
notify_rejected: '{0} heeft gebruikersnaam {1} afgekeurd'
notify_flagged: '{0} heeft gebruikersnaam {1} gerapporteerd'
notify_changed: 'gebruiker {0} heeft zijn/haar gebruikersnaam veranderd naar {1}'
notify_changed: 'gebruiker {0} heeft zijn/haar gebruikersnaam veranderd naar {1}'
community:
account_creation_date: "Aanmaakdatum account"
active: Actief
@@ -350,7 +350,7 @@ nl_NL:
personal_info: "Deze reactie onthult persoonlijk identificeerbare gegevens."
post: Plaats
profile: Profiel
profile_settings: "Profiel instellingen"
profile_settings: "Instellingen"
reply: Beantwoord
report: Rapporteer
report_notif: "Dank voor het rapporteren van deze reactie. Deze wordt zo snel mogelijk gemodereerd."
+1 -1
View File
@@ -349,7 +349,7 @@ pt_BR:
personal_info: "Este comentário revela informações de identificação pessoal"
post: Publicar
profile: Perfil
profile_settings: "Configurações de perfil"
profile_settings: "Configurações"
reply: Responder
report: Denunciar
report_notif: "Obrigado por denunciar este comentário. Nossa equipe de moderação foi notificada e irá revisá-la em breve."
+1 -1
View File
@@ -351,7 +351,7 @@ zh_CN:
personal_info: "这个评论透露了可确定个人身份的信息"
post: "发表"
profile: "资料"
profile_settings: "资料设定"
profile_settings: "设置"
reply: "回复"
report: "举报"
report_notif: "感谢您举报此评论。我们的审核小组已经收到通知,并会很快进行审查。"
+1 -1
View File
@@ -351,7 +351,7 @@ zh_TW:
personal_info: "該評論洩露了個人身份資訊"
post: 帖子
profile: 概況
profile_settings: "概況設置"
profile_settings: "設置"
reply: 回覆
report: 舉報
report_notif: "感謝您舉報此評論。我們的審核小組已經收到通知,並會很快進行審查。"
+1 -2
View File
@@ -21,7 +21,6 @@
"talk-plugin-sort-most-respected",
"talk-plugin-sort-newest",
"talk-plugin-sort-oldest",
"talk-plugin-viewing-options",
"talk-plugin-profile-settings"
"talk-plugin-viewing-options"
]
}
@@ -1,3 +0,0 @@
{
"extends": "@coralproject/eslint-config-talk/client"
}
@@ -1,8 +0,0 @@
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;
@@ -1,26 +0,0 @@
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);
@@ -1,11 +0,0 @@
import Tab from './components/Tab';
import TabPane from './containers/TabPane';
import translations from './translations.yml';
export default {
slots: {
profileTabs: [Tab],
profileTabPanes: [TabPane],
},
translations,
};
@@ -1,27 +0,0 @@
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: 设置
@@ -1 +0,0 @@
module.exports = {};