@@ -114,7 +114,6 @@ class Comment extends React.Component {
Comment.propTypes = {
comment: PropTypes.object.isRequired,
navigate: PropTypes.func.isRequired,
- data: PropTypes.object.isRequired,
root: PropTypes.object.isRequired,
};
diff --git a/client/coral-embed-stream/src/tabs/profile/components/CommentHistory.js b/client/coral-embed-stream/src/tabs/profile/components/CommentHistory.js
index 64d9e97ae..c15314f29 100644
--- a/client/coral-embed-stream/src/tabs/profile/components/CommentHistory.js
+++ b/client/coral-embed-stream/src/tabs/profile/components/CommentHistory.js
@@ -22,7 +22,7 @@ class CommentHistory extends React.Component {
};
render() {
- const { navigate, comments, data, root } = this.props;
+ const { navigate, comments, root } = this.props;
if (!comments.nodes.length) {
return
;
}
@@ -33,7 +33,6 @@ class CommentHistory extends React.Component {
return (
(
-
-
-
{username}
- {emailAddress ?
{emailAddress}
: null}
+const Profile = ({ username, emailAddress, root, slotPassthrough }) => {
+ return (
+
+
+
{username}
+ {emailAddress ?
{emailAddress}
: null}
+
+
+
-
-
- {t('framework.my_comments')}
- ,
- ]}
- tabPanes={[
-
-
- ,
- ]}
- sub
- />
-
-);
+ );
+};
Profile.propTypes = {
username: PropTypes.string,
emailAddress: PropTypes.string,
- data: PropTypes.object,
root: PropTypes.object,
- activeTab: PropTypes.string.isRequired,
- setActiveTab: PropTypes.func.isRequired,
+ slotPassthrough: PropTypes.object,
};
export default Profile;
diff --git a/client/coral-embed-stream/src/tabs/profile/components/Settings.js b/client/coral-embed-stream/src/tabs/profile/components/Settings.js
new file mode 100644
index 000000000..c61a09a92
--- /dev/null
+++ b/client/coral-embed-stream/src/tabs/profile/components/Settings.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Slot } from 'coral-framework/components';
+
+class Settings extends React.Component {
+ render() {
+ const { root } = this.props;
+ const slotPassthrough = { root };
+ return (
+
+
+
+ );
+ }
+}
+
+Settings.propTypes = {
+ root: PropTypes.object,
+};
+
+export default Settings;
diff --git a/client/coral-embed-stream/src/tabs/profile/components/TabPanel.js b/client/coral-embed-stream/src/tabs/profile/components/TabPanel.js
new file mode 100644
index 000000000..08270bcd8
--- /dev/null
+++ b/client/coral-embed-stream/src/tabs/profile/components/TabPanel.js
@@ -0,0 +1,61 @@
+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 = ({
+ root,
+ activeTab,
+ setActiveTab,
+ showSettingsTab,
+ slotPassthrough,
+}) => {
+ const tabs = [
+
+ {t('framework.my_comments')}
+ ,
+ ];
+
+ if (showSettingsTab) {
+ tabs.push(
+
+ {t('profile_settings')}
+
+ );
+ }
+
+ return (
+
+
+ ,
+
+
+ ,
+ ]}
+ sub
+ />
+ );
+};
+
+TabPanel.propTypes = {
+ root: PropTypes.object,
+ slotPassthrough: PropTypes.object,
+ activeTab: PropTypes.string.isRequired,
+ setActiveTab: PropTypes.func.isRequired,
+ showSettingsTab: PropTypes.bool.isRequired,
+};
+
+export default TabPanel;
diff --git a/client/coral-embed-stream/src/tabs/profile/containers/CommentHistory.js b/client/coral-embed-stream/src/tabs/profile/containers/CommentHistory.js
index a02225939..27727216e 100644
--- a/client/coral-embed-stream/src/tabs/profile/containers/CommentHistory.js
+++ b/client/coral-embed-stream/src/tabs/profile/containers/CommentHistory.js
@@ -4,7 +4,7 @@ import { connect } from 'react-redux';
import { compose, gql } from 'react-apollo';
import CommentHistory from '../components/CommentHistory';
import Comment from './Comment';
-import { withFragments } from 'coral-framework/hocs';
+import { withFragments, withFetchMore } from 'coral-framework/hocs';
import { appendNewNodes } from 'plugin-api/beta/client/utils';
import update from 'immutability-helper';
@@ -16,7 +16,7 @@ class CommentHistoryContainer extends Component {
};
loadMore = () => {
- return this.props.data.fetchMore({
+ return this.props.fetchMore({
query: LOAD_MORE_QUERY,
variables: {
limit: 5,
@@ -43,7 +43,6 @@ class CommentHistoryContainer extends Component {
return (
({
export default compose(
connect(mapStateToProps, null),
- withCommentHistoryFragments
+ withCommentHistoryFragments,
+ withFetchMore
)(CommentHistoryContainer);
diff --git a/client/coral-embed-stream/src/tabs/profile/containers/Profile.js b/client/coral-embed-stream/src/tabs/profile/containers/Profile.js
index 82a0a49eb..30d634d94 100644
--- a/client/coral-embed-stream/src/tabs/profile/containers/Profile.js
+++ b/client/coral-embed-stream/src/tabs/profile/containers/Profile.js
@@ -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 {
@@ -23,7 +22,7 @@ class ProfileContainer extends Component {
}
render() {
- const { currentUser, showSignInDialog, root, data } = this.props;
+ const { currentUser, showSignInDialog, root } = this.props;
const { me } = this.props.root;
const loading = this.props.data.loading;
@@ -41,15 +40,14 @@ class ProfileContainer extends Component {
const localProfile = currentUser.profiles.find(p => p.provider === 'local');
const emailAddress = localProfile && localProfile.id;
+ const slotPassthrough = { root };
return (
);
}
@@ -60,16 +58,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 +69,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 +83,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),
diff --git a/client/coral-embed-stream/src/tabs/profile/containers/Settings.js b/client/coral-embed-stream/src/tabs/profile/containers/Settings.js
new file mode 100644
index 000000000..795a3c10a
--- /dev/null
+++ b/client/coral-embed-stream/src/tabs/profile/containers/Settings.js
@@ -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 ;
+ }
+}
+
+const enhance = compose(
+ withFragments({
+ root: gql`
+ fragment TalkEmbedStream_ProfileSettings_root on RootQuery {
+ __typename
+ ${getSlotFragmentSpreads(slots, 'root')}
+ }
+ `,
+ })
+);
+
+export default enhance(SettingsContainer);
diff --git a/client/coral-embed-stream/src/tabs/profile/containers/TabPanel.js b/client/coral-embed-stream/src/tabs/profile/containers/TabPanel.js
new file mode 100644
index 000000000..46c24227f
--- /dev/null
+++ b/client/coral-embed-stream/src/tabs/profile/containers/TabPanel.js
@@ -0,0 +1,64 @@
+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 (
+ 0}
+ />
+ );
+ }
+}
+
+TabPanelContainer.propTypes = {
+ 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);
diff --git a/client/coral-embed-stream/src/tabs/stream/components/AllCommentsPane.js b/client/coral-embed-stream/src/tabs/stream/components/AllCommentsPane.js
index 3190ab155..9aa2b8a4c 100644
--- a/client/coral-embed-stream/src/tabs/stream/components/AllCommentsPane.js
+++ b/client/coral-embed-stream/src/tabs/stream/components/AllCommentsPane.js
@@ -126,7 +126,6 @@ class AllCommentsPane extends React.Component {
render() {
const {
- data,
root,
comments,
commentClassNames,
@@ -164,7 +163,6 @@ class AllCommentsPane extends React.Component {
return (
{
return (
@@ -573,8 +565,7 @@ export default class Comment extends React.Component {
className={cn(styles.username, 'talk-stream-comment-user-name')}
fill="commentAuthorName"
defaultComponent={CommentAuthorName}
- queryData={queryData}
- {...slotProps}
+ passthrough={slotPassthrough}
/>
@@ -607,9 +597,10 @@ export default class Comment extends React.Component {
fill="commentTimestamp"
defaultComponent={CommentTimestamp}
className={'talk-stream-comment-published-date'}
- created_at={comment.created_at}
- queryData={queryData}
- {...slotProps}
+ passthrough={{
+ created_at: comment.created_at,
+ ...slotPassthrough,
+ }}
/>
{comment.editing && comment.editing.edited ? (
@@ -624,8 +615,7 @@ export default class Comment extends React.Component {
{isActive &&
@@ -665,9 +655,8 @@ export default class Comment extends React.Component {
fill="commentContent"
className="talk-stream-comment-content"
defaultComponent={CommentContent}
- {...slotProps}
- queryData={queryData}
- slotSize={1}
+ size={1}
+ passthrough={slotPassthrough}
/>
)}
@@ -678,8 +667,7 @@ export default class Comment extends React.Component {
- this.props.data.subscribeToMore(config)
+ this.props.subscribeToMore(config)
);
}
@@ -60,4 +61,4 @@ const COMMENT_UNFEATURED_SUBSCRIPTION = gql`
}
`;
-export default ModIndicatorSubscription;
+export default compose(withSubscribeToMore)(ModIndicatorSubscription);
diff --git a/plugins/talk-plugin-featured-comments/client/containers/ModSubscription.js b/plugins/talk-plugin-featured-comments/client/containers/ModSubscription.js
index 6d0fdd811..d91d69304 100644
--- a/plugins/talk-plugin-featured-comments/client/containers/ModSubscription.js
+++ b/plugins/talk-plugin-featured-comments/client/containers/ModSubscription.js
@@ -6,6 +6,11 @@ import { getDefinitionName } from 'coral-framework/utils';
import truncate from 'lodash/truncate';
import t from 'coral-framework/services/i18n';
import { subscriptionFields } from 'coral-admin/src/routes/Moderation/graphql';
+import {
+ compose,
+ withSubscribeToMore,
+ withVariables,
+} from 'plugin-api/beta/client/hocs';
function prepareNotificationText(text) {
return truncate(text, { length: 50 }).replace('\n', ' ');
@@ -19,7 +24,7 @@ class ModSubscription extends React.Component {
{
document: COMMENT_FEATURED_SUBSCRIPTION,
variables: {
- assetId: this.props.data.variables.asset_id,
+ assetId: this.props.variables.asset_id,
},
updateQuery: (
prev,
@@ -39,7 +44,7 @@ class ModSubscription extends React.Component {
{
document: COMMENT_UNFEATURED_SUBSCRIPTION,
variables: {
- assetId: this.props.data.variables.asset_id,
+ assetId: this.props.variables.asset_id,
},
updateQuery: (
prev,
@@ -62,7 +67,7 @@ class ModSubscription extends React.Component {
},
];
this.subscriptions = configs.map(config =>
- this.props.data.subscribeToMore(config)
+ this.props.subscribeToMore(config)
);
}
@@ -111,4 +116,8 @@ const mapStateToProps = state => ({
user: state.auth.user,
});
-export default connect(mapStateToProps, null)(ModSubscription);
+export default compose(
+ connect(mapStateToProps, null),
+ withVariables,
+ withSubscribeToMore
+)(ModSubscription);
diff --git a/plugins/talk-plugin-featured-comments/client/containers/TabPane.js b/plugins/talk-plugin-featured-comments/client/containers/TabPane.js
index 297f5aedf..b3f44b429 100644
--- a/plugins/talk-plugin-featured-comments/client/containers/TabPane.js
+++ b/plugins/talk-plugin-featured-comments/client/containers/TabPane.js
@@ -2,7 +2,12 @@ import React from 'react';
import { bindActionCreators } from 'redux';
import { compose, gql } from 'react-apollo';
import TabPane from '../components/TabPane';
-import { withFragments, connect } from 'plugin-api/beta/client/hocs';
+import {
+ withFragments,
+ connect,
+ withFetchMore,
+ withVariables,
+} from 'plugin-api/beta/client/hocs';
import Comment from '../containers/Comment';
import { viewComment } from 'coral-embed-stream/src/actions/stream';
import {
@@ -13,15 +18,15 @@ import update from 'immutability-helper';
class TabPaneContainer extends React.Component {
loadMore = () => {
- return this.props.data.fetchMore({
+ return this.props.fetchMore({
query: LOAD_MORE_QUERY,
variables: {
limit: 5,
cursor: this.props.asset.featuredComments.endCursor,
asset_id: this.props.asset.id,
- sortOrder: this.props.data.variables.sortOrder,
- sortBy: this.props.data.variables.sortBy,
- excludeIgnored: this.props.data.variables.excludeIgnored,
+ sortOrder: this.props.variables.sortOrder,
+ sortBy: this.props.variables.sortBy,
+ excludeIgnored: this.props.variables.excludeIgnored,
},
updateQuery: (previous, { fetchMoreResult: { comments } }) => {
const updated = update(previous, {
@@ -86,6 +91,8 @@ const mapDispatchToProps = dispatch =>
const enhance = compose(
connect(null, mapDispatchToProps),
+ withFetchMore,
+ withVariables,
withFragments({
root: gql`
fragment TalkFeaturedComments_TabPane_root on RootQuery {
diff --git a/plugins/talk-plugin-flag-details/client/components/FlagDetails.js b/plugins/talk-plugin-flag-details/client/components/FlagDetails.js
index 607ba48a2..7900f5b50 100644
--- a/plugins/talk-plugin-flag-details/client/components/FlagDetails.js
+++ b/plugins/talk-plugin-flag-details/client/components/FlagDetails.js
@@ -10,7 +10,7 @@ import {
class FlagDetails extends Component {
render() {
- const { comment: { actions }, more, data, root, comment } = this.props;
+ const { comment: { actions }, more, root, comment } = this.props;
const flagActions =
actions && actions.filter(a => a.__typename === 'FlagAction');
@@ -26,7 +26,7 @@ class FlagDetails extends Component {
}, {});
const reasons = Object.keys(summaries);
- const queryData = {
+ const slotPassthrough = {
root,
comment,
};
@@ -52,12 +52,11 @@ class FlagDetails extends Component {
{more && (
)}
@@ -68,7 +67,6 @@ class FlagDetails extends Component {
FlagDetails.propTypes = {
more: PropTypes.bool,
- data: PropTypes.object,
root: PropTypes.object,
comment: PropTypes.shape({
actions: PropTypes.arrayOf(
diff --git a/plugins/talk-plugin-member-since/client/index.js b/plugins/talk-plugin-member-since/client/index.js
index 2091e4805..fe0b5b14b 100644
--- a/plugins/talk-plugin-member-since/client/index.js
+++ b/plugins/talk-plugin-member-since/client/index.js
@@ -24,7 +24,7 @@ export default {
createComment: {
comment: {
user: {
- created_at: new Date(),
+ created_at: new Date().toISOString(),
__typename: 'User',
},
__typename: 'Comment',
diff --git a/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js b/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js
index 68abce826..272202d9c 100644
--- a/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js
+++ b/plugins/talk-plugin-moderation-actions/client/components/ModerationActions.js
@@ -16,12 +16,16 @@ export default class ModerationActions extends React.Component {
comment,
root,
asset,
- data,
menuVisible,
toogleMenu,
hideMenu,
} = this.props;
+ const slotPassthrough = {
+ comment,
+ asset,
+ };
+
return (
@@ -67,7 +70,6 @@ ModerationActions.propTypes = {
comment: PropTypes.object,
root: PropTypes.object,
asset: PropTypes.object,
- data: PropTypes.object,
menuVisible: PropTypes.bool,
toogleMenu: PropTypes.func,
hideMenu: PropTypes.func,
diff --git a/plugins/talk-plugin-moderation-actions/client/containers/ModerationActions.js b/plugins/talk-plugin-moderation-actions/client/containers/ModerationActions.js
index 9e0edb9b3..891d248ce 100644
--- a/plugins/talk-plugin-moderation-actions/client/containers/ModerationActions.js
+++ b/plugins/talk-plugin-moderation-actions/client/containers/ModerationActions.js
@@ -42,7 +42,6 @@ class ModerationActionsContainer extends React.Component {
render() {
return (
- props.root.me.notificationSettings.onFeatured;
-
- toggle = () => {
- this.props.updateNotificationSettings({
- onFeatured: !this.getOnFeaturedSetting(),
- });
- };
-
- render() {
- return (
-
- {t('talk-plugin-notifications-category-featured.toggle_description')}
-
- );
- }
-}
-
-ToggleContainer.propTypes = {
- data: PropTypes.object,
- root: PropTypes.object,
- indicateOn: PropTypes.func.isRequired,
- indicateOff: PropTypes.func.isRequired,
- setTurnOffInputFragment: PropTypes.func.isRequired,
- updateNotificationSettings: PropTypes.func.isRequired,
- disabled: PropTypes.bool.isRequired,
-};
-
-const enhance = compose(
- withFragments({
- root: gql`
- fragment TalkNotificationsCategoryFeatured_Toggle_root on RootQuery {
- me {
- notificationSettings {
- onFeatured
- }
- }
- }
- `,
- })
-);
-
-export default enhance(ToggleContainer);
diff --git a/plugins/talk-plugin-notifications-category-featured/client/graphql.js b/plugins/talk-plugin-notifications-category-featured/client/graphql.js
deleted file mode 100644
index 440a6f7fa..000000000
--- a/plugins/talk-plugin-notifications-category-featured/client/graphql.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import { gql } from 'react-apollo';
-
-export default {
- mutations: {
- UpdateNotificationSettings: ({
- variables: { input },
- state: { auth: { user: { id } } },
- }) => ({
- update: proxy => {
- if (input.onFeatured === undefined) {
- return;
- }
-
- const fragment = gql`
- fragment TalkNotificationsCategoryFeatured_User_Fragment on User {
- notificationSettings {
- onFeatured
- }
- }
- `;
- const fragmentId = `User_${id}`;
- const data = {
- __typename: 'User',
- notificationSettings: {
- __typename: 'NotificationSettings',
- onFeatured: input.onFeatured,
- },
- };
- proxy.writeFragment({ fragment, id: fragmentId, data });
- },
- }),
- },
-};
diff --git a/plugins/talk-plugin-notifications-category-featured/client/index.js b/plugins/talk-plugin-notifications-category-featured/client/index.js
index 1e22c3a93..74c0c2aa5 100644
--- a/plugins/talk-plugin-notifications-category-featured/client/index.js
+++ b/plugins/talk-plugin-notifications-category-featured/client/index.js
@@ -1,11 +1,14 @@
-import Toggle from './containers/Toggle';
import translations from './translations.yml';
-import graphql from './graphql';
+import { t } from 'plugin-api/beta/client/services';
+import { createSettingsToggle } from 'talk-plugin-notifications/client/api/factories';
+
+const SettingsToggle = createSettingsToggle('onFeatured', () =>
+ t('talk-plugin-notifications-category-featured.toggle_description')
+);
export default {
slots: {
- notificationSettings: [Toggle],
+ notificationSettings: [SettingsToggle],
},
translations,
- ...graphql,
};
diff --git a/plugins/talk-plugin-notifications-category-reply/client/containers/Toggle.js b/plugins/talk-plugin-notifications-category-reply/client/containers/Toggle.js
deleted file mode 100644
index d261946d0..000000000
--- a/plugins/talk-plugin-notifications-category-reply/client/containers/Toggle.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { compose, gql } from 'react-apollo';
-import Toggle from 'talk-plugin-notifications/client/components/Toggle';
-import { t } from 'plugin-api/beta/client/services';
-import { withFragments } from 'plugin-api/beta/client/hocs';
-
-class ToggleContainer extends React.Component {
- constructor(props) {
- super(props);
- props.setTurnOffInputFragment({ onReply: false });
-
- if (this.getOnReplySetting()) {
- props.indicateOn();
- }
- }
-
- componentWillReceiveProps(nextProps) {
- const prevSetting = this.getOnReplySetting(this.props);
- const nextSetting = this.getOnReplySetting(nextProps);
- if (prevSetting && !nextSetting) {
- nextProps.indicateOff();
- } else if (!prevSetting && nextSetting) {
- nextProps.indicateOn();
- }
- }
-
- getOnReplySetting = (props = this.props) =>
- props.root.me.notificationSettings.onReply;
-
- toggle = () => {
- this.props.updateNotificationSettings({
- onReply: !this.getOnReplySetting(),
- });
- };
-
- render() {
- return (
-
- {t('talk-plugin-notifications-category-reply.toggle_description')}
-
- );
- }
-}
-
-ToggleContainer.propTypes = {
- data: PropTypes.object,
- root: PropTypes.object,
- indicateOn: PropTypes.func.isRequired,
- indicateOff: PropTypes.func.isRequired,
- setTurnOffInputFragment: PropTypes.func.isRequired,
- updateNotificationSettings: PropTypes.func.isRequired,
- disabled: PropTypes.bool.isRequired,
-};
-
-const enhance = compose(
- withFragments({
- root: gql`
- fragment TalkNotificationsCategoryReply_Toggle_root on RootQuery {
- me {
- notificationSettings {
- onReply
- }
- }
- }
- `,
- })
-);
-
-export default enhance(ToggleContainer);
diff --git a/plugins/talk-plugin-notifications-category-reply/client/graphql.js b/plugins/talk-plugin-notifications-category-reply/client/graphql.js
deleted file mode 100644
index 623e72366..000000000
--- a/plugins/talk-plugin-notifications-category-reply/client/graphql.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import { gql } from 'react-apollo';
-
-export default {
- mutations: {
- UpdateNotificationSettings: ({
- variables: { input },
- state: { auth: { user: { id } } },
- }) => ({
- update: proxy => {
- if (input.onReply === undefined) {
- return;
- }
-
- const fragment = gql`
- fragment TalkNotificationsCategoryReply_User_Fragment on User {
- notificationSettings {
- onReply
- }
- }
- `;
- const fragmentId = `User_${id}`;
- const data = {
- __typename: 'User',
- notificationSettings: {
- __typename: 'NotificationSettings',
- onReply: input.onReply,
- },
- };
- proxy.writeFragment({ fragment, id: fragmentId, data });
- },
- }),
- },
-};
diff --git a/plugins/talk-plugin-notifications-category-reply/client/index.js b/plugins/talk-plugin-notifications-category-reply/client/index.js
index 1e22c3a93..098a1397e 100644
--- a/plugins/talk-plugin-notifications-category-reply/client/index.js
+++ b/plugins/talk-plugin-notifications-category-reply/client/index.js
@@ -1,11 +1,14 @@
-import Toggle from './containers/Toggle';
import translations from './translations.yml';
-import graphql from './graphql';
+import { t } from 'plugin-api/beta/client/services';
+import { createSettingsToggle } from 'talk-plugin-notifications/client/api/factories';
+
+const SettingsToggle = createSettingsToggle('onReply', () =>
+ t('talk-plugin-notifications-category-reply.toggle_description')
+);
export default {
slots: {
- notificationSettings: [Toggle],
+ notificationSettings: [SettingsToggle],
},
translations,
- ...graphql,
};
diff --git a/plugins/talk-plugin-notifications-category-staff/client/containers/Toggle.js b/plugins/talk-plugin-notifications-category-staff/client/containers/Toggle.js
deleted file mode 100644
index 62a4cbbce..000000000
--- a/plugins/talk-plugin-notifications-category-staff/client/containers/Toggle.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { compose, gql } from 'react-apollo';
-import Toggle from 'talk-plugin-notifications/client/components/Toggle';
-import { t } from 'plugin-api/beta/client/services';
-import { withFragments } from 'plugin-api/beta/client/hocs';
-
-class ToggleContainer extends React.Component {
- constructor(props) {
- super(props);
- props.setTurnOffInputFragment({ onStaffReply: false });
-
- if (this.getOnReplySetting()) {
- props.indicateOn();
- }
- }
-
- componentWillReceiveProps(nextProps) {
- const prevSetting = this.getOnReplySetting(this.props);
- const nextSetting = this.getOnReplySetting(nextProps);
- if (prevSetting && !nextSetting) {
- nextProps.indicateOff();
- } else if (!prevSetting && nextSetting) {
- nextProps.indicateOn();
- }
- }
-
- getOnReplySetting = (props = this.props) =>
- props.root.me.notificationSettings.onStaffReply;
-
- toggle = () => {
- this.props.updateNotificationSettings({
- onStaffReply: !this.getOnReplySetting(),
- });
- };
-
- render() {
- return (
-
- {t('talk-plugin-notifications-category-staff.toggle_description')}
-
- );
- }
-}
-
-ToggleContainer.propTypes = {
- data: PropTypes.object,
- root: PropTypes.object,
- indicateOn: PropTypes.func.isRequired,
- indicateOff: PropTypes.func.isRequired,
- setTurnOffInputFragment: PropTypes.func.isRequired,
- updateNotificationSettings: PropTypes.func.isRequired,
- disabled: PropTypes.bool.isRequired,
-};
-
-const enhance = compose(
- withFragments({
- root: gql`
- fragment TalkNotificationsCategoryStaffReply_User_Fragment on RootQuery {
- me {
- notificationSettings {
- onStaffReply
- }
- }
- }
- `,
- })
-);
-
-export default enhance(ToggleContainer);
diff --git a/plugins/talk-plugin-notifications-category-staff/client/graphql.js b/plugins/talk-plugin-notifications-category-staff/client/graphql.js
deleted file mode 100644
index 2e8007d4f..000000000
--- a/plugins/talk-plugin-notifications-category-staff/client/graphql.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import { gql } from 'react-apollo';
-
-export default {
- mutations: {
- UpdateNotificationSettings: ({
- variables: { input },
- state: { auth: { user: { id } } },
- }) => ({
- update: proxy => {
- if (input.onStaffReply === undefined) {
- return;
- }
-
- const fragment = gql`
- fragment TalkNotificationsCategoryStaffReply_User_Fragment on User {
- notificationSettings {
- onStaffReply
- }
- }
- `;
- const fragmentId = `User_${id}`;
- const data = {
- __typename: 'User',
- notificationSettings: {
- __typename: 'NotificationSettings',
- onStaffReply: input.onStaffReply,
- },
- };
- proxy.writeFragment({ fragment, id: fragmentId, data });
- },
- }),
- },
-};
diff --git a/plugins/talk-plugin-notifications-category-staff/client/index.js b/plugins/talk-plugin-notifications-category-staff/client/index.js
index 1e22c3a93..e273fceaa 100644
--- a/plugins/talk-plugin-notifications-category-staff/client/index.js
+++ b/plugins/talk-plugin-notifications-category-staff/client/index.js
@@ -1,11 +1,14 @@
-import Toggle from './containers/Toggle';
import translations from './translations.yml';
-import graphql from './graphql';
+import { t } from 'plugin-api/beta/client/services';
+import { createSettingsToggle } from 'talk-plugin-notifications/client/api/factories';
+
+const SettingsToggle = createSettingsToggle('onStaffReply', () =>
+ t('talk-plugin-notifications-category-staff.toggle_description')
+);
export default {
slots: {
- notificationSettings: [Toggle],
+ notificationSettings: [SettingsToggle],
},
translations,
- ...graphql,
};
diff --git a/plugins/talk-plugin-notifications/client/api/components/Toggle.css b/plugins/talk-plugin-notifications/client/api/components/Toggle.css
new file mode 100644
index 000000000..3f5b02705
--- /dev/null
+++ b/plugins/talk-plugin-notifications/client/api/components/Toggle.css
@@ -0,0 +1,20 @@
+.title {
+ display: inline-block;
+ width: 100%;
+ cursor: pointer;
+ user-select: none;
+
+ &.disabled {
+ color: #e5e5e5;
+ cursor: default;
+ }
+}
+
+.toggle {
+ display: flex;
+ align-items: center;
+}
+
+.checkBox {
+ text-align: right;
+}
diff --git a/plugins/talk-plugin-notifications/client/api/components/Toggle.js b/plugins/talk-plugin-notifications/client/api/components/Toggle.js
new file mode 100644
index 000000000..40e7da4e6
--- /dev/null
+++ b/plugins/talk-plugin-notifications/client/api/components/Toggle.js
@@ -0,0 +1,41 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Checkbox } from 'plugin-api/beta/client/components/ui';
+import styles from './Toggle.css';
+import uuid from 'uuid/v4';
+import cn from 'classnames';
+
+class Toggle extends React.Component {
+ id = uuid();
+
+ render() {
+ const { checked, onChange, children, disabled } = this.props;
+ return (
+
+ );
+ }
+}
+
+Toggle.propTypes = {
+ disabled: PropTypes.bool,
+ checked: PropTypes.bool,
+ onChange: PropTypes.func,
+ children: PropTypes.node,
+};
+
+export default Toggle;
diff --git a/plugins/talk-plugin-notifications/client/api/components/index.js b/plugins/talk-plugin-notifications/client/api/components/index.js
new file mode 100644
index 000000000..81e73b58b
--- /dev/null
+++ b/plugins/talk-plugin-notifications/client/api/components/index.js
@@ -0,0 +1 @@
+export { default as Toggle } from './Toggle';
diff --git a/plugins/talk-plugin-notifications/client/api/factories/createSettingsToggle.js b/plugins/talk-plugin-notifications/client/api/factories/createSettingsToggle.js
new file mode 100644
index 000000000..95b7789cb
--- /dev/null
+++ b/plugins/talk-plugin-notifications/client/api/factories/createSettingsToggle.js
@@ -0,0 +1,22 @@
+import React from 'react';
+import Toggle from '../components/Toggle';
+import withSettingsToggle from '../hocs/withSettingsToggle';
+
+/**
+ * createSettingsToggle will add a boolean setting with the
+ * name `settingsName` to notification settings and return
+ * a full Toggle Component.
+ *
+ * You must provide a `label` either as a string or as a callback.
+ * E.g. to provide translations you could do:
+ *
+ * `const SettingsToggle = createSettingsToggle('onReply', () => t('translate'));`
+ */
+const createSettingsToggle = (settingsName, label) => {
+ const SettingsToggle = props => (
+ {typeof label === 'function' ? label() : label}
+ );
+ return withSettingsToggle(settingsName)(SettingsToggle);
+};
+
+export default createSettingsToggle;
diff --git a/plugins/talk-plugin-notifications/client/api/factories/index.js b/plugins/talk-plugin-notifications/client/api/factories/index.js
new file mode 100644
index 000000000..b18ad7679
--- /dev/null
+++ b/plugins/talk-plugin-notifications/client/api/factories/index.js
@@ -0,0 +1 @@
+export { default as createSettingsToggle } from './createSettingsToggle';
diff --git a/plugins/talk-plugin-notifications/client/api/hocs/index.js b/plugins/talk-plugin-notifications/client/api/hocs/index.js
new file mode 100644
index 000000000..c55d371bc
--- /dev/null
+++ b/plugins/talk-plugin-notifications/client/api/hocs/index.js
@@ -0,0 +1 @@
+export { default as withSettingsToggle } from './withSettingsToggle';
diff --git a/plugins/talk-plugin-notifications/client/api/hocs/withSettingsToggle.js b/plugins/talk-plugin-notifications/client/api/hocs/withSettingsToggle.js
new file mode 100644
index 000000000..fc7b1bac6
--- /dev/null
+++ b/plugins/talk-plugin-notifications/client/api/hocs/withSettingsToggle.js
@@ -0,0 +1,121 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { compose, gql } from 'react-apollo';
+import {
+ withFragments,
+ withGraphQLExtension,
+} from 'plugin-api/beta/client/hocs';
+
+const createHOC = settingsName => WrappedComponent => {
+ class WithSettingsToggle extends React.Component {
+ constructor(props) {
+ super(props);
+ props.setTurnOffInputFragment({ [settingsName]: false });
+
+ if (this.isChecked()) {
+ props.indicateOn();
+ }
+ }
+
+ componentWillReceiveProps(nextProps) {
+ const prevSetting = this.isChecked(this.props);
+ const nextSetting = this.isChecked(nextProps);
+ if (prevSetting && !nextSetting) {
+ nextProps.indicateOff();
+ } else if (!prevSetting && nextSetting) {
+ nextProps.indicateOn();
+ }
+ }
+
+ isChecked = (props = this.props) =>
+ props.root.me.notificationSettings[settingsName];
+
+ toggle = () => {
+ this.props.updateNotificationSettings({
+ [settingsName]: !this.isChecked(),
+ });
+ };
+
+ render() {
+ return (
+
+ );
+ }
+ }
+
+ WithSettingsToggle.propTypes = {
+ root: PropTypes.object,
+ indicateOn: PropTypes.func.isRequired,
+ indicateOff: PropTypes.func.isRequired,
+ setTurnOffInputFragment: PropTypes.func.isRequired,
+ updateNotificationSettings: PropTypes.func.isRequired,
+ disabled: PropTypes.bool.isRequired,
+ };
+
+ return WithSettingsToggle;
+};
+
+/**
+ * withSettingsToggle will add a boolean setting with the
+ * name `settingsName` to notification settings and provide
+ * the folliwng props:
+ *
+ * `checked: boolean` Whether setting is on or off
+ * `onChange: () => void` Calling this will toggle the setting
+ * `disabled: boolean` Whether setting is disabled
+ */
+const withSettingsToggle = settingsName => {
+ const extension = {
+ mutations: {
+ UpdateNotificationSettings: ({
+ variables: { input },
+ state: { auth: { user: { id } } },
+ }) => ({
+ update: proxy => {
+ if (input[settingsName] === undefined) {
+ return;
+ }
+
+ const fragment = gql`
+ fragment TalkNotifications_Toggle_${settingsName}_Fragment on User {
+ notificationSettings {
+ ${settingsName}
+ }
+ }
+ `;
+ const fragmentId = `User_${id}`;
+ const data = {
+ __typename: 'User',
+ notificationSettings: {
+ __typename: 'NotificationSettings',
+ [settingsName]: input[settingsName],
+ },
+ };
+ proxy.writeFragment({ fragment, id: fragmentId, data });
+ },
+ }),
+ },
+ };
+
+ return compose(
+ withFragments({
+ root: gql`
+ fragment TalkNotifications_Toggle_${settingsName}_root on RootQuery {
+ me {
+ notificationSettings {
+ ${settingsName}
+ }
+ }
+ }
+ `,
+ }),
+ withGraphQLExtension(extension),
+ createHOC(settingsName)
+ );
+};
+
+export default withSettingsToggle;
diff --git a/plugins/talk-plugin-notifications/client/components/Settings.js b/plugins/talk-plugin-notifications/client/components/Settings.js
index a5c3b4fcd..f71affcbb 100644
--- a/plugins/talk-plugin-notifications/client/components/Settings.js
+++ b/plugins/talk-plugin-notifications/client/components/Settings.js
@@ -37,15 +37,18 @@ class Settings extends React.Component {
onChangeDigestFrequency,
} = this.props;
- const slotProps = {
- queryData: { root },
- setTurnOffInputFragment: setTurnOffInputFragment,
- updateNotificationSettings: updateNotificationSettings,
+ const slotPassthrough = {
+ root,
+ setTurnOffInputFragment,
+ updateNotificationSettings,
disabled: needEmailVerification,
};
return (
-
+
{t('talk-plugin-notifications.settings_title')}
@@ -63,7 +66,7 @@ class Settings extends React.Component {
className={styles.notifcationSettingsSlot}
fill="notificationSettings"
childFactory={this.childFactory}
- {...slotProps}
+ passthrough={slotPassthrough}
/>
{digestFrequencyValues.length > 1 && (
diff --git a/plugins/talk-plugin-notifications/client/containers/Settings.js b/plugins/talk-plugin-notifications/client/containers/Settings.js
index f3e6c7e6d..27af031e8 100644
--- a/plugins/talk-plugin-notifications/client/containers/Settings.js
+++ b/plugins/talk-plugin-notifications/client/containers/Settings.js
@@ -50,7 +50,6 @@ class SettingsContainer extends React.Component {
render() {
return (
{
- return {t('talk-plugin-profile-settings.tab')} ;
-};
-
-export default Tab;
diff --git a/plugins/talk-plugin-profile-settings/client/components/TabPane.js b/plugins/talk-plugin-profile-settings/client/components/TabPane.js
deleted file mode 100644
index c0347a95c..000000000
--- a/plugins/talk-plugin-profile-settings/client/components/TabPane.js
+++ /dev/null
@@ -1,21 +0,0 @@
-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 (
-
-
-
- );
- }
-}
-
-TabPane.propTypes = {
- data: PropTypes.object,
- root: PropTypes.object,
-};
-
-export default TabPane;
diff --git a/plugins/talk-plugin-profile-settings/client/containers/TabPane.js b/plugins/talk-plugin-profile-settings/client/containers/TabPane.js
deleted file mode 100644
index 6384c7160..000000000
--- a/plugins/talk-plugin-profile-settings/client/containers/TabPane.js
+++ /dev/null
@@ -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 ;
- }
-}
-
-const enhance = compose(
- withFragments({
- root: gql`
- fragment TalkProfileSettings_TabPane_root on RootQuery {
- __typename
- ${getSlotFragmentSpreads(slots, 'root')}
- }
- `,
- })
-);
-
-export default enhance(TabPaneContainer);
diff --git a/plugins/talk-plugin-profile-settings/client/index.js b/plugins/talk-plugin-profile-settings/client/index.js
deleted file mode 100644
index 00e37a0f1..000000000
--- a/plugins/talk-plugin-profile-settings/client/index.js
+++ /dev/null
@@ -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,
-};
diff --git a/plugins/talk-plugin-profile-settings/client/translations.yml b/plugins/talk-plugin-profile-settings/client/translations.yml
deleted file mode 100644
index 33805a49b..000000000
--- a/plugins/talk-plugin-profile-settings/client/translations.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-ar:
- talk-plugin-profile-settings:
- tab: إعدادات
-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: 设置
diff --git a/plugins/talk-plugin-profile-settings/index.js b/plugins/talk-plugin-profile-settings/index.js
deleted file mode 100644
index f053ebf79..000000000
--- a/plugins/talk-plugin-profile-settings/index.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = {};
diff --git a/plugins/talk-plugin-rich-text-pell/README.md b/plugins/talk-plugin-rich-text-pell/README.md
deleted file mode 100644
index da70d48d0..000000000
--- a/plugins/talk-plugin-rich-text-pell/README.md
+++ /dev/null
@@ -1,49 +0,0 @@
----
-title: talk-plugin-rich-text-pell
-permalink: /plugin/talk-plugin-rich-text-pell/
-layout: plugin
-plugin:
- name: talk-plugin-rich-text-pell
- depends:
- - name: talk-plugin-rich-text
- provides:
- - Client
----
-
-Enables rich text support client-side by using [Pell](https://github.com/jaredreich/pell).
-
-## Installation
-
-Add `"talk-plugin-rich-text-pell"` to the `plugins.json` in your Talk
-installation. Remember to add this in the `client` property since this plugin
-only covers the client side. To add server support, please use
-[talk-plugin-rich-text](/talk/plugin/talk-plugin-rich-text).
-
-_Note: Ensure that you don't have any other plugins utilizing the
-`commentContent` slot, as it would result in duplicate comments._
-
-## How does this work?
-
-This plugin contains 2 important components:
-
-- The Editor (`./components/Editor.js`)
-- The Comment Content Renderer (`./components/CommentContent.js`)
-
-The editor component contains the rich text editor. For this particular plugin
-we chose [Pell](https://github.com/jaredreich/pell). Pell is the simplest and
-smallest WYSIWYG text editor with no dependencies that we could find.
-
-If you check our `index.js` you will notice that we inject this editor in the
-`commentBox` slot. We do this to replace the core comment box with this one.
-
-Now, in order to render the new styled comments we need a comment renderer. For
-this task we will have to replace our core comment renderer by using the
-`commentContent` slot.
-
-If you are not familiar with GraphQL `client/index.js` will look complicated,
-but fear not! With those functions we specify what to expect from the server
-schema, how to perform optimistic updates and how keep the client store updated
-with the latest changes.
-
-We encourage you to see the files and check how easy is to build plugins! If you
-have any feedback, please let us know.
diff --git a/plugins/talk-plugin-rich-text-pell/client/.eslintrc.json b/plugins/talk-plugin-rich-text-pell/client/.eslintrc.json
deleted file mode 100644
index c8a6db18a..000000000
--- a/plugins/talk-plugin-rich-text-pell/client/.eslintrc.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "extends": "@coralproject/eslint-config-talk/client"
-}
diff --git a/plugins/talk-plugin-rich-text-pell/client/components/CommentContent.js b/plugins/talk-plugin-rich-text-pell/client/components/CommentContent.js
deleted file mode 100644
index 7e4a202bc..000000000
--- a/plugins/talk-plugin-rich-text-pell/client/components/CommentContent.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { pluginName } from '../../package.json';
-
-class CommentContent extends React.Component {
- render() {
- const { comment } = this.props;
- return comment.richTextBody ? (
-
- ) : (
- {comment.body}
- );
- }
-}
-
-CommentContent.propTypes = {
- comment: PropTypes.object.isRequired,
-};
-
-export default CommentContent;
diff --git a/plugins/talk-plugin-rich-text-pell/client/components/Editor.css b/plugins/talk-plugin-rich-text-pell/client/components/Editor.css
deleted file mode 100644
index 4561e7c6b..000000000
--- a/plugins/talk-plugin-rich-text-pell/client/components/Editor.css
+++ /dev/null
@@ -1,41 +0,0 @@
-.content {
- background: #fff;
- border: solid 1px #bbb;
- min-height: 120px;
- box-sizing: border-box;
- outline: 0;
- overflow-y: auto;
- width: 100%;
- padding: 10px;
- font-style: unset;
-}
-
-.button > i {
- vertical-align: middle;
-}
-
-.button {
- background-color: transparent;
- padding: 3px;
- border: none;
- color: #4e4e4e;
- margin-right: 3px;
-}
-
-.button:hover{
- cursor: pointer;
- border-radius: 3px;
- background-color: #eae8e8;
-}
-
-.actionBar {
- user-select: none;
- padding: 5px 10px;
- border-top: 1px solid #bbb;
- border-left: 1px solid #bbb;
- border-right: 1px solid #bbb;
-}
-
-.container {
- box-sizing: border-box;
-}
\ No newline at end of file
diff --git a/plugins/talk-plugin-rich-text-pell/client/components/Editor.js b/plugins/talk-plugin-rich-text-pell/client/components/Editor.js
deleted file mode 100644
index c129e146d..000000000
--- a/plugins/talk-plugin-rich-text-pell/client/components/Editor.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { init } from 'pell';
-import styles from './Editor.css';
-import cn from 'classnames';
-import { pluginName } from '../../package.json';
-import { htmlNormalizer } from '../utils';
-
-class Editor extends React.Component {
- ref = null;
-
- handleRef = ref => (this.ref = ref);
-
- componentDidMount() {
- const { onChange, actions, classNames, isReply } = this.props;
-
- init({
- element: this.ref,
- onChange: richTextBody => {
- // We want to save the original comment body
- const originalBody = this.ref.childNodes[1].innerText;
- onChange(originalBody, { richTextBody: htmlNormalizer(richTextBody) });
- },
- actions,
- classes: {
- actionbar: cn(
- styles.actionBar,
- classNames.actionbar,
- `${pluginName}-action-bar`
- ),
- content: cn(
- styles.content,
- classNames.content,
- `${pluginName}-content`
- ),
- button: cn(styles.button, classNames.button, `${pluginName}-button`),
- },
- });
-
- // To edit comments and have the previous html comment
- if (this.props.comment && this.props.comment.richTextBody && !isReply) {
- this.ref.content.innerHTML = this.props.comment.richTextBody;
- }
-
- if (this.props.registerHook) {
- this.clearInputHook = this.props.registerHook(
- 'postSubmit',
- (res, handleBodyChange) => {
- this.ref.content.innerHTML = '';
- handleBodyChange('', { richTextBody: '' });
- }
- );
- }
- }
-
- componentWillUnmount() {
- this.props.unregisterHook(this.clearInputHook);
- }
-
- render() {
- const { id, classNames } = this.props;
-
- return (
-
- );
- }
-}
-
-Editor.defaultProps = {
- defaultContent: '',
- styleWithCSS: false,
- actions: [
- { name: 'bold', icon: 'format_bold ' },
- { name: 'italic', icon: 'format_italic ' },
- { name: 'quote', icon: 'format_quote ' },
- ],
- classNames: {
- button: '',
- content: '',
- actionbar: '',
- container: '',
- },
-};
-
-Editor.propTypes = {
- id: PropTypes.string,
- value: PropTypes.string,
- placeholder: PropTypes.string,
- onChange: PropTypes.func,
- disabled: PropTypes.bool,
- rows: PropTypes.number,
- comment: PropTypes.object,
- classNames: PropTypes.object,
- actions: PropTypes.array,
- registerHook: PropTypes.func,
- unregisterHook: PropTypes.func,
- isReply: PropTypes.bool,
-};
-
-export default Editor;
diff --git a/plugins/talk-plugin-rich-text-pell/client/containers/CommentContent.js b/plugins/talk-plugin-rich-text-pell/client/containers/CommentContent.js
deleted file mode 100644
index 8bd36da23..000000000
--- a/plugins/talk-plugin-rich-text-pell/client/containers/CommentContent.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { gql } from 'react-apollo';
-import { withFragments } from 'plugin-api/beta/client/hocs';
-import CommentContent from '../components/CommentContent';
-
-export default withFragments({
- comment: gql`
- fragment TalkPluginRTE_CommentContent_comment on Comment {
- body
- richTextBody
- }
- `,
-})(CommentContent);
diff --git a/plugins/talk-plugin-rich-text-pell/client/containers/Editor.js b/plugins/talk-plugin-rich-text-pell/client/containers/Editor.js
deleted file mode 100644
index 2bdc3490f..000000000
--- a/plugins/talk-plugin-rich-text-pell/client/containers/Editor.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { gql } from 'react-apollo';
-import { withFragments } from 'plugin-api/beta/client/hocs';
-import Editor from '../components/Editor';
-
-export default withFragments({
- comment: gql`
- fragment TalkPluginRTE_Editor_comment on Comment {
- body
- richTextBody
- }
- `,
-})(Editor);
diff --git a/plugins/talk-plugin-rich-text-pell/client/index.js b/plugins/talk-plugin-rich-text-pell/client/index.js
deleted file mode 100644
index cf9eb11cd..000000000
--- a/plugins/talk-plugin-rich-text-pell/client/index.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import Editor from './containers/Editor';
-import CommentContent from './containers/CommentContent';
-import { gql } from 'react-apollo';
-
-export default {
- slots: {
- draftArea: [Editor],
- commentContent: [CommentContent],
- adminCommentContent: [CommentContent],
- userDetailCommentContent: [CommentContent],
- },
- fragments: {
- CreateCommentResponse: gql`
- fragment TalkRTE_CreateCommentResponse on CreateCommentResponse {
- comment {
- richTextBody
- }
- }
- `,
- EditCommentResponse: gql`
- fragment TalkRTE_EditCommentResponse on EditCommentResponse {
- comment {
- richTextBody
- }
- }
- `,
- },
- mutations: {
- PostComment: ({ variables: { input } }) => {
- return {
- optimisticResponse: {
- createComment: {
- comment: {
- richTextBody: input.richTextBody,
- },
- },
- },
- };
- },
- EditComment: ({ variables: { id, edit } }) => {
- return {
- optimisticResponse: {
- editComment: {
- comment: {
- richTextBody: edit.richTextBody,
- },
- },
- },
- update: proxy => {
- const editCommentFragment = gql`
- fragment Talk_EditComment on Comment {
- richTextBody
- }
- `;
-
- const fragmentId = `Comment_${id}`;
-
- proxy.writeFragment({
- fragment: editCommentFragment,
- id: fragmentId,
- data: {
- __typename: 'Comment',
- richTextBody: edit.richTextBody,
- },
- });
- },
- };
- },
- },
-};
diff --git a/plugins/talk-plugin-rich-text-pell/client/utils.js b/plugins/talk-plugin-rich-text-pell/client/utils.js
deleted file mode 100644
index 6155fbfb2..000000000
--- a/plugins/talk-plugin-rich-text-pell/client/utils.js
+++ /dev/null
@@ -1,20 +0,0 @@
-export function htmlNormalizer(htmlInput) {
- let str = htmlInput;
- // We are normalizing the input from contenteditable of each browser, also removing unnecesary html tags
- // https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content#Differences_in_markup_generation
-
- // Old browsers uses `p` normalize to `div` instead.
- str = str
- .replace(//g, '
') // IE and old browsers outputs
instead of
s
- .replace(/<\/p>/g, '
'); // IE and old browsers outputs
instead of
s
-
- // Remove first opening tag, otherwise
- // with the following transformation below
- // we might add an unintended first empty line.
- if (str.startsWith('
')) {
- str = str.replace('
', '');
- }
-
- // Normalize
s to
.
- return str.replace(/
/g, '
').replace(/<\/div>/g, '');
-}
diff --git a/plugins/talk-plugin-rich-text-pell/index.js b/plugins/talk-plugin-rich-text-pell/index.js
deleted file mode 100644
index f053ebf79..000000000
--- a/plugins/talk-plugin-rich-text-pell/index.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = {};
diff --git a/plugins/talk-plugin-rich-text-pell/package.json b/plugins/talk-plugin-rich-text-pell/package.json
deleted file mode 100644
index 65543a89a..000000000
--- a/plugins/talk-plugin-rich-text-pell/package.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "@coralproject/talk-plugin-rich-text-pell",
- "pluginName": "talk-plugin-rich-text-pell",
- "version": "0.0.1",
- "description": "Pell's Rich Text Editor for Talk",
- "main": "index.js",
- "author": "The Coral Project Team
",
- "license": "Apache-2.0",
- "dependencies": {
- "pell": "^1.0.1"
- }
-}
diff --git a/plugins/talk-plugin-viewing-options/client/components/Category.js b/plugins/talk-plugin-viewing-options/client/components/Category.js
index 0fc13d16f..78ce4dae3 100644
--- a/plugins/talk-plugin-viewing-options/client/components/Category.js
+++ b/plugins/talk-plugin-viewing-options/client/components/Category.js
@@ -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 => (
);
-const ViewingOptions = ({ slot, title, data, asset, root }) => {
+const Category = ({ slot, title, slotPassthrough }) => {
return (
{title}
@@ -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}
/>
);
};
-export default ViewingOptions;
+Category.propTypes = {
+ slot: PropTypes.string.isRequired,
+ title: PropTypes.string.isRequired,
+ slotPassthrough: PropTypes.object.isRequired,
+};
+
+export default Category;
diff --git a/plugins/talk-plugin-viewing-options/client/components/Menu.js b/plugins/talk-plugin-viewing-options/client/components/Menu.js
index 7ff5ac316..c3ea40fe1 100644
--- a/plugins/talk-plugin-viewing-options/client/components/Menu.js
+++ b/plugins/talk-plugin-viewing-options/client/components/Menu.js
@@ -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 (
{Object.keys(this.categories).map(category => (
))}
@@ -31,4 +35,8 @@ class Menu extends React.Component {
}
}
+Menu.propTypes = {
+ slotPassthrough: PropTypes.object.isRequired,
+};
+
export default Menu;
diff --git a/plugins/talk-plugin-viewing-options/client/components/ViewingOptions.js b/plugins/talk-plugin-viewing-options/client/components/ViewingOptions.js
index 8a0c09f61..40aa96d1e 100644
--- a/plugins/talk-plugin-viewing-options/client/components/ViewingOptions.js
+++ b/plugins/talk-plugin-viewing-options/client/components/ViewingOptions.js
@@ -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 (
@@ -41,11 +42,18 @@ class ViewingOptions extends React.Component {
)}
- {open && }
+ {open && }
);
}
}
+ViewingOptions.propTypes = {
+ slotPassthrough: PropTypes.object.isRequired,
+ open: PropTypes.bool.isRequired,
+ openMenu: PropTypes.func.isRequired,
+ closeMenu: PropTypes.func.isRequired,
+};
+
export default ViewingOptions;
diff --git a/plugins/talk-plugin-viewing-options/client/containers/ViewingOptions.js b/plugins/talk-plugin-viewing-options/client/containers/ViewingOptions.js
index b30721346..0e1919383 100644
--- a/plugins/talk-plugin-viewing-options/client/containers/ViewingOptions.js
+++ b/plugins/talk-plugin-viewing-options/client/containers/ViewingOptions.js
@@ -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);
diff --git a/views/admin.ejs b/views/admin.ejs
index 939da0dcf..1ecca390e 100644
--- a/views/admin.ejs
+++ b/views/admin.ejs
@@ -3,8 +3,6 @@
Talk - Coral Admin
-
-
+
+
+
+
+
<%- include partials/head %>
-
+