mirror of
https://github.com/wassname/talk.git
synced 2026-07-05 21:24:47 +08:00
Merge pull request #916 from coralproject/author-menu
Author menu, member since, and ignored users
This commit is contained in:
@@ -19,5 +19,8 @@ plugins/*
|
||||
!plugins/talk-plugin-sort-most-liked
|
||||
!plugins/talk-plugin-sort-most-loved
|
||||
!plugins/talk-plugin-sort-most-respected
|
||||
!plugins/talk-plugin-author-menu
|
||||
!plugins/talk-plugin-member-since
|
||||
!plugins/talk-plugin-ignore-user
|
||||
|
||||
node_modules
|
||||
|
||||
@@ -35,5 +35,8 @@ plugins/*
|
||||
!plugins/talk-plugin-sort-most-liked
|
||||
!plugins/talk-plugin-sort-most-loved
|
||||
!plugins/talk-plugin-sort-most-respected
|
||||
!plugins/talk-plugin-author-menu
|
||||
!plugins/talk-plugin-member-since
|
||||
!plugins/talk-plugin-ignore-user
|
||||
|
||||
**/node_modules/*
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import LoadMore from './LoadMore';
|
||||
import IgnoredCommentTombstone from './IgnoredCommentTombstone';
|
||||
import NewCount from './NewCount';
|
||||
import {TransitionGroup} from 'react-transition-group';
|
||||
import {forEachError} from 'coral-framework/utils';
|
||||
@@ -126,7 +125,6 @@ class AllCommentsPane extends React.Component {
|
||||
root,
|
||||
comments,
|
||||
commentClassNames,
|
||||
ignoreUser,
|
||||
setActiveReplyBox,
|
||||
activeReplyBox,
|
||||
notify,
|
||||
@@ -139,7 +137,6 @@ class AllCommentsPane extends React.Component {
|
||||
loadNewReplies,
|
||||
deleteAction,
|
||||
showSignInDialog,
|
||||
commentIsIgnored,
|
||||
charCountEnable,
|
||||
maxCharCount,
|
||||
editComment,
|
||||
@@ -157,9 +154,8 @@ class AllCommentsPane extends React.Component {
|
||||
/>
|
||||
<TransitionGroup component='div' className="embed__stream">
|
||||
{view.map((comment) => {
|
||||
return commentIsIgnored(comment)
|
||||
? <IgnoredCommentTombstone key={comment.id} />
|
||||
: <Comment
|
||||
return (
|
||||
<Comment
|
||||
commentClassNames={commentClassNames}
|
||||
data={data}
|
||||
root={root}
|
||||
@@ -173,8 +169,6 @@ class AllCommentsPane extends React.Component {
|
||||
currentUser={currentUser}
|
||||
postFlag={postFlag}
|
||||
postDontAgree={postDontAgree}
|
||||
ignoreUser={ignoreUser}
|
||||
commentIsIgnored={commentIsIgnored}
|
||||
loadMore={loadNewReplies}
|
||||
deleteAction={deleteAction}
|
||||
showSignInDialog={showSignInDialog}
|
||||
@@ -184,7 +178,8 @@ class AllCommentsPane extends React.Component {
|
||||
maxCharCount={maxCharCount}
|
||||
editComment={editComment}
|
||||
emit={emit}
|
||||
/>;
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</TransitionGroup>
|
||||
<LoadMore
|
||||
|
||||
@@ -66,17 +66,6 @@
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.topRight .popover {
|
||||
margin-top: 1em;
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.topRight .link.active,
|
||||
.topRight .active .link {
|
||||
padding-bottom: 0.125em;
|
||||
border-bottom: 2px solid currentColor;
|
||||
}
|
||||
|
||||
.editCommentForm {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@@ -175,4 +164,4 @@
|
||||
|
||||
.username {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ import mapValues from 'lodash/mapValues';
|
||||
import LoadMore from './LoadMore';
|
||||
import {getEditableUntilDate} from './util';
|
||||
import {findCommentWithId} from '../graphql/utils';
|
||||
import {TopRightMenu} from './TopRightMenu';
|
||||
import CommentContent from './CommentContent';
|
||||
import Slot from 'coral-framework/components/Slot';
|
||||
import IgnoredCommentTombstone from './IgnoredCommentTombstone';
|
||||
@@ -184,12 +183,6 @@ export default class Comment extends React.Component {
|
||||
})
|
||||
}).isRequired,
|
||||
|
||||
// given a comment, return whether it should be rendered as ignored
|
||||
commentIsIgnored: PropTypes.func,
|
||||
|
||||
// dispatch action to ignore another user
|
||||
ignoreUser: PropTypes.func,
|
||||
|
||||
// edit a comment, passed (id, asset_id, { body })
|
||||
editComment: PropTypes.func,
|
||||
|
||||
@@ -216,9 +209,18 @@ export default class Comment extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
commentIsIgnored(comment) {
|
||||
const me = this.props.root.me;
|
||||
return (
|
||||
me &&
|
||||
me.ignoredUsers &&
|
||||
me.ignoredUsers.find((u) => u.id === comment.user.id)
|
||||
);
|
||||
}
|
||||
|
||||
hasIgnoredReplies() {
|
||||
return this.props.comment.replies &&
|
||||
this.props.comment.replies.nodes.some((reply) => this.props.commentIsIgnored(reply));
|
||||
this.props.comment.replies.nodes.some((reply) => this.commentIsIgnored(reply));
|
||||
}
|
||||
|
||||
loadNewReplies = () => {
|
||||
@@ -317,7 +319,6 @@ export default class Comment extends React.Component {
|
||||
comment,
|
||||
postFlag,
|
||||
parentId,
|
||||
ignoreUser,
|
||||
highlighted,
|
||||
postComment,
|
||||
currentUser,
|
||||
@@ -332,12 +333,15 @@ export default class Comment extends React.Component {
|
||||
charCountEnable,
|
||||
showSignInDialog,
|
||||
liveUpdates,
|
||||
commentIsIgnored,
|
||||
animateEnter,
|
||||
emit,
|
||||
commentClassNames = []
|
||||
} = this.props;
|
||||
|
||||
if (this.commentIsIgnored(comment)) {
|
||||
return <IgnoredCommentTombstone />;
|
||||
}
|
||||
|
||||
const view = this.getVisibileReplies();
|
||||
|
||||
// Inactive comments can be viewed by moderators and admins (e.g. using permalinks).
|
||||
@@ -480,16 +484,6 @@ export default class Comment extends React.Component {
|
||||
}
|
||||
</span>
|
||||
}
|
||||
{ isActive && (currentUser && (comment.user.id !== currentUser.id)) &&
|
||||
|
||||
/* TopRightMenu allows currentUser to ignore other users' comments */
|
||||
<span className={cn(styles.topRight, styles.topRightMenu)}>
|
||||
<TopRightMenu
|
||||
comment={comment}
|
||||
ignoreUser={ignoreUser}
|
||||
notify={notify} />
|
||||
</span>
|
||||
}
|
||||
{ !isActive &&
|
||||
<InactiveCommentLabel status={comment.status}/>
|
||||
}
|
||||
@@ -581,9 +575,8 @@ export default class Comment extends React.Component {
|
||||
|
||||
<TransitionGroup>
|
||||
{view.map((reply) => {
|
||||
return commentIsIgnored(reply)
|
||||
? <IgnoredCommentTombstone key={reply.id} />
|
||||
: <CommentContainer
|
||||
return (
|
||||
<CommentContainer
|
||||
data={this.props.data}
|
||||
root={this.props.root}
|
||||
setActiveReplyBox={setActiveReplyBox}
|
||||
@@ -600,17 +593,16 @@ export default class Comment extends React.Component {
|
||||
postFlag={postFlag}
|
||||
deleteAction={deleteAction}
|
||||
loadMore={loadMore}
|
||||
ignoreUser={ignoreUser}
|
||||
charCountEnable={charCountEnable}
|
||||
maxCharCount={maxCharCount}
|
||||
showSignInDialog={showSignInDialog}
|
||||
commentIsIgnored={commentIsIgnored}
|
||||
liveUpdates={liveUpdates}
|
||||
reactKey={reply.id}
|
||||
key={reply.id}
|
||||
comment={reply}
|
||||
emit={emit}
|
||||
/>;
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</TransitionGroup>
|
||||
<div className="talk-load-more-replies">
|
||||
|
||||
@@ -40,15 +40,6 @@ class Stream extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
commentIsIgnored = (comment) => {
|
||||
const me = this.props.root.me;
|
||||
return (
|
||||
me &&
|
||||
me.ignoredUsers &&
|
||||
me.ignoredUsers.find((u) => u.id === comment.user.id)
|
||||
);
|
||||
};
|
||||
|
||||
renderHighlightedComment() {
|
||||
const {
|
||||
data,
|
||||
@@ -64,7 +55,6 @@ class Stream extends React.Component {
|
||||
postDontAgree,
|
||||
deleteAction,
|
||||
showSignInDialog,
|
||||
ignoreUser,
|
||||
loadNewReplies,
|
||||
auth: {user},
|
||||
emit,
|
||||
@@ -90,7 +80,6 @@ class Stream extends React.Component {
|
||||
data={data}
|
||||
root={root}
|
||||
commentClassNames={commentClassNames}
|
||||
ignoreUser={ignoreUser}
|
||||
setActiveReplyBox={setActiveReplyBox}
|
||||
activeReplyBox={activeReplyBox}
|
||||
notify={notify}
|
||||
@@ -106,7 +95,6 @@ class Stream extends React.Component {
|
||||
deleteAction={deleteAction}
|
||||
showSignInDialog={showSignInDialog}
|
||||
key={topLevelComment.id}
|
||||
commentIsIgnored={this.commentIsIgnored}
|
||||
comment={topLevelComment}
|
||||
charCountEnable={asset.settings.charCountEnable}
|
||||
maxCharCount={asset.settings.charCount}
|
||||
@@ -133,7 +121,6 @@ class Stream extends React.Component {
|
||||
postDontAgree,
|
||||
deleteAction,
|
||||
showSignInDialog,
|
||||
ignoreUser,
|
||||
activeStreamTab,
|
||||
setActiveStreamTab,
|
||||
loadNewReplies,
|
||||
@@ -183,7 +170,6 @@ class Stream extends React.Component {
|
||||
root={root}
|
||||
comments={comments}
|
||||
commentClassNames={commentClassNames}
|
||||
ignoreUser={ignoreUser}
|
||||
setActiveReplyBox={setActiveReplyBox}
|
||||
activeReplyBox={activeReplyBox}
|
||||
notify={notify}
|
||||
@@ -197,7 +183,6 @@ class Stream extends React.Component {
|
||||
loadNewReplies={loadNewReplies}
|
||||
deleteAction={deleteAction}
|
||||
showSignInDialog={showSignInDialog}
|
||||
commentIsIgnored={this.commentIsIgnored}
|
||||
charCountEnable={asset.settings.charCountEnable}
|
||||
maxCharCount={asset.settings.charCount}
|
||||
editComment={editComment}
|
||||
@@ -322,9 +307,6 @@ Stream.propTypes = {
|
||||
notify: PropTypes.func.isRequired,
|
||||
postComment: PropTypes.func.isRequired,
|
||||
|
||||
// dispatch action to ignore another user
|
||||
ignoreUser: React.PropTypes.func,
|
||||
|
||||
// edit a comment, passed (id, asset_id, { body })
|
||||
editComment: React.PropTypes.func
|
||||
};
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
import React, {PropTypes} from 'react';
|
||||
import {IgnoreUserWizard} from './IgnoreUserWizard';
|
||||
import Toggleable from './Toggleable';
|
||||
|
||||
// TopRightMenu appears as a dropdown in the top right of the comment.
|
||||
// when you click the down cehvron, it expands and shows IgnoreUserWizard
|
||||
// when you click 'cancel' in the wizard, it closes the menu
|
||||
export class TopRightMenu extends React.Component {
|
||||
static propTypes = {
|
||||
|
||||
// comment on which this menu appears
|
||||
comment: PropTypes.shape({
|
||||
user: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
username: PropTypes.string.isRequired
|
||||
}).isRequired
|
||||
}).isRequired,
|
||||
ignoreUser: PropTypes.func,
|
||||
|
||||
// show notification to the user (e.g. for errors)
|
||||
notify: PropTypes.func.isRequired,
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
timesReset: 0
|
||||
};
|
||||
}
|
||||
render() {
|
||||
const {comment, ignoreUser, notify} = this.props;
|
||||
|
||||
// timesReset is used as Toggleable key so it re-renders on reset (closing the toggleable)
|
||||
const reset = () => this.setState({timesReset: this.state.timesReset + 1});
|
||||
const ignoreUserAndCloseMenuAndNotifyOnError = async ({id}) => {
|
||||
|
||||
// close menu
|
||||
reset();
|
||||
|
||||
// ignore user
|
||||
try {
|
||||
await ignoreUser({id});
|
||||
} catch (error) {
|
||||
notify('error', 'Failed to ignore user');
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Toggleable key={this.state.timesReset} className="talk-stream-comment-chevron">
|
||||
<div style={{position: 'absolute', right: 0, zIndex: 1}}>
|
||||
<IgnoreUserWizard
|
||||
user={comment.user}
|
||||
cancel={reset}
|
||||
ignoreUser={ignoreUserAndCloseMenuAndNotifyOnError}
|
||||
/>
|
||||
</div>
|
||||
</Toggleable>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ const singleCommentFragment = gql`
|
||||
edited
|
||||
editableUntil
|
||||
}
|
||||
${getSlotFragmentSpreads(slots, 'comment')}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -97,6 +98,11 @@ const withCommentFragments = withFragments({
|
||||
}
|
||||
}
|
||||
__typename
|
||||
me {
|
||||
ignoredUsers {
|
||||
id
|
||||
}
|
||||
}
|
||||
${getSlotFragmentSpreads(slots, 'root')}
|
||||
}
|
||||
`,
|
||||
@@ -121,7 +127,6 @@ const withCommentFragments = withFragments({
|
||||
endCursor
|
||||
}
|
||||
`, THREADING_LEVEL)}
|
||||
${getSlotFragmentSpreads(slots, 'comment')}
|
||||
}
|
||||
${singleCommentFragment}
|
||||
`
|
||||
|
||||
@@ -5,7 +5,7 @@ import {bindActionCreators} from 'redux';
|
||||
import {ADDTL_COMMENTS_ON_LOAD_MORE, THREADING_LEVEL} from '../constants/stream';
|
||||
import {
|
||||
withPostComment, withPostFlag, withPostDontAgree,
|
||||
withDeleteAction, withIgnoreUser, withEditComment
|
||||
withDeleteAction, withEditComment
|
||||
} from 'coral-framework/graphql/mutations';
|
||||
|
||||
import * as authActions from 'coral-embed-stream/src/actions/auth';
|
||||
@@ -374,7 +374,6 @@ export default compose(
|
||||
withPostComment,
|
||||
withPostFlag,
|
||||
withPostDontAgree,
|
||||
withIgnoreUser,
|
||||
withDeleteAction,
|
||||
withEditComment,
|
||||
)(StreamContainer);
|
||||
|
||||
@@ -108,33 +108,6 @@ export default {
|
||||
`,
|
||||
},
|
||||
mutations: {
|
||||
IgnoreUser: ({variables}) => ({
|
||||
updateQueries: {
|
||||
CoralEmbedStream_Embed: (previousData) => {
|
||||
const ignoredUserId = variables.id;
|
||||
const updated = update(previousData, {me: {ignoredUsers: {$push: [{
|
||||
id: ignoredUserId,
|
||||
__typename: 'User',
|
||||
}]}}});
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
}),
|
||||
StopIgnoringUser: ({variables}) => ({
|
||||
updateQueries: {
|
||||
CoralEmbedStream_Profile: (previousData) => {
|
||||
const noLongerIgnoredUserId = variables.id;
|
||||
|
||||
// remove noLongerIgnoredUserId from ignoredUsers
|
||||
const updated = update(previousData, {me: {ignoredUsers: {
|
||||
$apply: (ignoredUsers) => {
|
||||
return ignoredUsers.filter((u) => u.id !== noLongerIgnoredUserId);
|
||||
}
|
||||
}}});
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
}),
|
||||
PostComment: ({
|
||||
variables: {comment: {asset_id, body, parent_id, tags = []}},
|
||||
state: {auth},
|
||||
|
||||
@@ -38,7 +38,7 @@ export default class Snackbar {
|
||||
}
|
||||
|
||||
alert(message) {
|
||||
const [type, text] = message.split('|');
|
||||
const {type, text} = JSON.parse(message);
|
||||
this.el.style.transform = 'translate(-50%, 20px)';
|
||||
this.el.style.opacity = 0;
|
||||
this.el.className = `coral-notif-${type}`;
|
||||
|
||||
@@ -293,7 +293,7 @@ export const withIgnoreUser = withMutation(
|
||||
}
|
||||
`, {
|
||||
props: ({mutate}) => ({
|
||||
ignoreUser: ({id}) => {
|
||||
ignoreUser: (id) => {
|
||||
return mutate({
|
||||
variables: {
|
||||
id,
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
*/
|
||||
export function createNotificationService(pym) {
|
||||
return {
|
||||
success(msg) {
|
||||
pym.sendMessage('coral-alert', `success|${msg}`);
|
||||
success(text) {
|
||||
pym.sendMessage('coral-alert', JSON.stringify({kind: 'success', text}));
|
||||
},
|
||||
error(msg) {
|
||||
pym.sendMessage('coral-alert', `error|${msg}`);
|
||||
error(text) {
|
||||
pym.sendMessage('coral-alert', JSON.stringify({kind: 'error', text}));
|
||||
},
|
||||
info(msg) {
|
||||
pym.sendMessage('coral-alert', `info|${msg}`);
|
||||
info(text) {
|
||||
pym.sendMessage('coral-alert', JSON.stringify({kind: 'info', text}));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
.ignoredUser {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.ignoredUserList {
|
||||
display: table;
|
||||
}
|
||||
|
||||
.ignoredUser > * {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.stopListening {
|
||||
color: #D0011B;
|
||||
}
|
||||
|
||||
.link {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stopListening:before {
|
||||
content: '\00a0\00a0\00a0\00a0';
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import React, {Component, PropTypes} from 'react';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
import styles from './IgnoredUsers.css';
|
||||
|
||||
class IgnoredUsers extends Component {
|
||||
static propTypes = {
|
||||
users: PropTypes.arrayOf(PropTypes.shape({
|
||||
username: PropTypes.string,
|
||||
id: PropTypes.string,
|
||||
})).isRequired,
|
||||
|
||||
// accepts { id }
|
||||
stopIgnoring: PropTypes.func.isRequired,
|
||||
}
|
||||
render() {
|
||||
const {users, stopIgnoring} = this.props;
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
users.length
|
||||
? <p>{t('framework.because_you_ignored')}</p>
|
||||
: null
|
||||
}
|
||||
<dl className={styles.ignoredUserList}>
|
||||
{
|
||||
users.map(({username, id}) => (
|
||||
<span className={styles.ignoredUser} key={id}>
|
||||
<dt key={id}>{ username }</dt>
|
||||
<dd className={styles.stopListening}>
|
||||
<a
|
||||
onClick={() => stopIgnoring({id})}
|
||||
className={styles.link}>{t('framework.stop_ignoring')}</a>
|
||||
</dd>
|
||||
</span>
|
||||
))
|
||||
}
|
||||
</dl>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default IgnoredUsers;
|
||||
@@ -3,12 +3,10 @@ import {compose, gql} from 'react-apollo';
|
||||
import React, {Component} from 'react';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {withQuery} from 'coral-framework/hocs';
|
||||
|
||||
import {withStopIgnoringUser} from 'coral-framework/graphql/mutations';
|
||||
import Slot from 'coral-framework/components/Slot';
|
||||
|
||||
import {link} from 'coral-framework/services/pym';
|
||||
import NotLoggedIn from '../components/NotLoggedIn';
|
||||
import IgnoredUsers from '../components/IgnoredUsers';
|
||||
import {Spinner} from 'coral-ui';
|
||||
import CommentHistory from 'talk-plugin-history/CommentHistory';
|
||||
|
||||
@@ -55,7 +53,7 @@ class ProfileContainer extends Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const {auth, auth: {user}, showSignInDialog, stopIgnoringUser, root, data} = this.props;
|
||||
const {auth, auth: {user}, showSignInDialog, root, data} = this.props;
|
||||
const {me} = this.props.root;
|
||||
const loading = this.props.data.loading;
|
||||
|
||||
@@ -77,15 +75,11 @@ class ProfileContainer extends Component {
|
||||
<h2>{user.username}</h2>
|
||||
{emailAddress ? <p>{emailAddress}</p> : null}
|
||||
|
||||
{me.ignoredUsers && me.ignoredUsers.length
|
||||
? <div>
|
||||
<h3>{t('framework.ignored_users')}</h3>
|
||||
<IgnoredUsers
|
||||
users={me.ignoredUsers}
|
||||
stopIgnoring={stopIgnoringUser}
|
||||
/>
|
||||
</div>
|
||||
: null}
|
||||
<Slot
|
||||
fill="profileSections"
|
||||
data={data}
|
||||
queryData={{root}}
|
||||
/>
|
||||
|
||||
<hr />
|
||||
|
||||
@@ -98,8 +92,10 @@ class ProfileContainer extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This Slot should be included in `talk-plugin-history` instead.
|
||||
const slots = [
|
||||
'profileSections',
|
||||
|
||||
// TODO: This Slot should be included in `talk-plugin-history` instead.
|
||||
'commentContent',
|
||||
];
|
||||
|
||||
@@ -143,10 +139,6 @@ const withProfileQuery = withQuery(
|
||||
query CoralEmbedStream_Profile {
|
||||
me {
|
||||
id
|
||||
ignoredUsers {
|
||||
id,
|
||||
username,
|
||||
}
|
||||
comments(query: {limit: 10}) {
|
||||
...TalkSettings_CommentConnectionFragment
|
||||
}
|
||||
@@ -165,6 +157,5 @@ const mapDispatchToProps = (dispatch) =>
|
||||
|
||||
export default compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
withStopIgnoringUser,
|
||||
withProfileQuery
|
||||
)(ProfileContainer);
|
||||
|
||||
@@ -219,7 +219,6 @@ en:
|
||||
framework:
|
||||
banned_account_header: "Your account is currently banned."
|
||||
banned_account_body: "This means that you cannot Like, Report, or write comments."
|
||||
because_you_ignored: "Because you ignored the following commenters, their comments are hidden."
|
||||
comment: comment
|
||||
comment_is_ignored: "This comment is hidden because you ignored this user."
|
||||
comments: comments
|
||||
@@ -230,13 +229,11 @@ en:
|
||||
error: "Usernames can contain letters numbers and _ only"
|
||||
label: "New Username"
|
||||
msg: "Your account is currently suspended because your username has been deemed inappropriate. To restore your account please enter a new username. Please contact us if you have any questions."
|
||||
ignored_users: "Ignored users"
|
||||
my_comments: "My Comments"
|
||||
my_profile: "My profile"
|
||||
new_count: "View {0} new {1}"
|
||||
profile: Profile
|
||||
show_all_comments: "Show all comments"
|
||||
stop_ignoring: "Stop ignoring"
|
||||
success_bio_update: "Your biography has been updated"
|
||||
success_name_update: "Your username has been updated"
|
||||
success_update_settings: "The changes you have made have been applied to the comment stream on this article"
|
||||
|
||||
@@ -227,13 +227,11 @@ es:
|
||||
error: "Nombres de usuarios pueden solamente incluir letras, números y _"
|
||||
label: "Nuevo Nombre"
|
||||
msg: "Tu cuenta está suspendida porque tu nombre de usuario ha sido considerado no apropiado para el espacio. Para recuperar la cuenta, por favor ingresar un nuevo nombre de usuario. Contáctanos si tienes alguna pregunta."
|
||||
ignored_users: "Usuarios ignorados"
|
||||
my_comments: "Mis Comentarios"
|
||||
my_profile: "Mi perfil"
|
||||
new_count: "Ver {0} {1} nuevo"
|
||||
profile: Perfil
|
||||
show_all_comments: "Mostrar todos los comentarios"
|
||||
stop_ignoring: "No ignorar más"
|
||||
success_bio_update: "Tu biografia fue actualizada"
|
||||
success_name_update: "Tu nombre de usuario ha sido actualizado"
|
||||
success_update_settings: "La configuración de este articulo fue actualizada"
|
||||
|
||||
@@ -188,7 +188,6 @@ fr:
|
||||
error: "Les noms d'utilisateur ne peuvent contenir que des chiffres, des lettres et \"_\""
|
||||
label: "Nouveau nom d'utilisateur"
|
||||
msg: "Votre compte est actuellement suspendu car votre nom d'utilisateur a été jugé inapproprié. Pour restaurer votre compte, entrez un nouveau nom d'utilisateur. Contactez-nous si vous avez des questions."
|
||||
ignored_users: "Utilisateurs ignorés"
|
||||
my_comments: "Mes commentaires"
|
||||
my_profile: "Mon profil"
|
||||
new_count: "Voir {0} nouveau {1}"
|
||||
|
||||
@@ -214,7 +214,6 @@ pt_BR:
|
||||
framework:
|
||||
banned_account_header: "Sua conta está atualmente proibida."
|
||||
banned_account_body: "Isso significa que você não pode gostar, informar ou escrever comentários."
|
||||
because_you_ignored: "Porque você ignorou os seguintes comentadores, seus comentários estão ocultos."
|
||||
comment: comentário
|
||||
comment_is_ignored: "Este comentário está oculto porque você ignorou esse usuário."
|
||||
comments: comentários
|
||||
@@ -225,13 +224,11 @@ pt_BR:
|
||||
error: "Nomes de usuários podem conter números de letras e _ somente"
|
||||
label: "Novo usuário"
|
||||
msg: "Sua conta está suspensa porque seu nome de usuário foi considerado inapropriado. Para restaurar sua conta, insira um novo nome de usuário. Entre em contato conosco se você tiver alguma dúvida."
|
||||
ignored_users: "Usuários ignorados"
|
||||
my_comments: "Meus comentários"
|
||||
my_profile: "Meu perfil"
|
||||
new_count: "Ver {0} {1}"
|
||||
profile: Perfil
|
||||
show_all_comments: "Exibir todos os comentários"
|
||||
stop_ignoring: "Pare de ignorar"
|
||||
success_bio_update: "Sua biografia foi atualizada"
|
||||
success_name_update: "Seu nome de usuário foi atualizado"
|
||||
success_update_settings: "As alterações que você fez foram aplicadas no hilo de comentários neste artigo"
|
||||
|
||||
@@ -130,6 +130,7 @@
|
||||
"material-design-lite": "^1.2.1",
|
||||
"metascraper": "^1.0.7",
|
||||
"minimist": "^1.2.0",
|
||||
"moment": "^2.18.1",
|
||||
"mongoose": "^4.11.7",
|
||||
"morgan": "^1.8.2",
|
||||
"ms": "^2.0.0",
|
||||
|
||||
@@ -1 +1 @@
|
||||
export {addNotification} from 'coral-framework/actions/notification';
|
||||
export {notify} from 'coral-framework/actions/notification';
|
||||
|
||||
@@ -5,3 +5,7 @@ export {default as withFragments} from 'coral-framework/hocs/withFragments';
|
||||
export {default as excludeIf} from 'coral-framework/hocs/excludeIf';
|
||||
export {default as connect} from 'coral-framework/hocs/connect';
|
||||
export {default as withEmit} from 'coral-framework/hocs/withEmit';
|
||||
export {
|
||||
withIgnoreUser,
|
||||
withStopIgnoringUser,
|
||||
} from 'coral-framework/graphql/mutations';
|
||||
|
||||
@@ -7,4 +7,5 @@ export {
|
||||
capitalize,
|
||||
getErrorMessages,
|
||||
getDefinitionName,
|
||||
getShallowChanges,
|
||||
} from 'coral-framework/utils';
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
"talk-plugin-sort-newest",
|
||||
"talk-plugin-sort-oldest",
|
||||
"talk-plugin-sort-most-respected",
|
||||
"talk-plugin-sort-most-replied"
|
||||
"talk-plugin-sort-most-replied",
|
||||
"talk-plugin-author-menu",
|
||||
"talk-plugin-member-since",
|
||||
"talk-plugin-ignore-user"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"presets": [
|
||||
"es2015"
|
||||
],
|
||||
"plugins": [
|
||||
"add-module-exports",
|
||||
"transform-class-properties",
|
||||
"transform-decorators-legacy",
|
||||
"transform-object-assign",
|
||||
"transform-object-rest-spread",
|
||||
"transform-async-to-generator",
|
||||
"transform-react-jsx"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true,
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"rules": {
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-uses-vars": "error",
|
||||
"no-console": ["warn", { "allow": ["warn", "error"] }]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import {SET_CONTENT_SLOT, RESET_CONTENT_SLOT, OPEN_MENU, CLOSE_MENU} from './constants';
|
||||
|
||||
export const setContentSlot = (slot) => ({
|
||||
type: SET_CONTENT_SLOT,
|
||||
slot,
|
||||
});
|
||||
|
||||
export const resetContentSlot = () => ({
|
||||
type: RESET_CONTENT_SLOT,
|
||||
});
|
||||
|
||||
export const openMenu = (id) => ({
|
||||
type: OPEN_MENU,
|
||||
id,
|
||||
});
|
||||
|
||||
export const closeMenu = () => ({
|
||||
type: CLOSE_MENU,
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
.root {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.button {
|
||||
composes: buttonReset from "coral-framework/styles/reset.css";
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import Menu from './Menu';
|
||||
import styles from './AuthorName.css';
|
||||
import {ClickOutside} from 'plugin-api/beta/client/components';
|
||||
import cn from 'classnames';
|
||||
|
||||
export default ({data, root, asset, comment, contentSlot, menuVisible, toggleMenu, hideMenu}) => {
|
||||
return (
|
||||
<ClickOutside onClickOutside={hideMenu}>
|
||||
<div className={cn(styles.root, 'talk-plugin-author-menu')}>
|
||||
<button
|
||||
className={cn(styles.button, 'talk-plugin-author-menu-button')}
|
||||
onClick={toggleMenu}
|
||||
>
|
||||
<span className={styles.name}>
|
||||
{comment.user.username}
|
||||
</span>
|
||||
</button>
|
||||
{menuVisible &&
|
||||
<Menu
|
||||
data={data}
|
||||
root={root}
|
||||
asset={asset}
|
||||
comment={comment}
|
||||
contentSlot={contentSlot}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</ClickOutside>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
.menu {
|
||||
background-color: white;
|
||||
border: solid 1px #999;
|
||||
border-radius: 3px;
|
||||
padding: 10px;
|
||||
position: absolute;
|
||||
-webkit-box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);
|
||||
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);
|
||||
z-index: 9;
|
||||
top: 26px;
|
||||
left: 0px;
|
||||
min-width: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.menu::before{
|
||||
content: '';
|
||||
border: 10px solid transparent;
|
||||
border-top-color: #999;
|
||||
position: absolute;
|
||||
left: 6px;
|
||||
top: -21px;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.menu::after{
|
||||
content: '';
|
||||
border: 10px solid transparent;
|
||||
border-top-color: white;
|
||||
position: absolute;
|
||||
left: 6px;
|
||||
top: -20px;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 8px;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import styles from './Menu.css';
|
||||
import {Slot} from 'plugin-api/beta/client/components';
|
||||
import cn from 'classnames';
|
||||
|
||||
export default ({data, root, asset, comment, contentSlot}) => {
|
||||
if (contentSlot) {
|
||||
return (
|
||||
<div className={cn(styles.menu, 'talk-plugin-author-menu-popup')}>
|
||||
<Slot
|
||||
fill={contentSlot}
|
||||
data={data}
|
||||
queryData={{asset, root, comment}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn(styles.menu, 'talk-plugin-author-menu-popup')}>
|
||||
<Slot
|
||||
className={cn('talk-plugin-author-menu-infos')}
|
||||
fill={'authorMenuInfos'}
|
||||
data={data}
|
||||
queryData={{asset, root, comment}}
|
||||
/>
|
||||
<Slot
|
||||
className={cn(styles.actions, 'talk-plugin-author-menu-actions')}
|
||||
fill={'authorMenuActions'}
|
||||
data={data}
|
||||
queryData={{asset, root, comment}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
const prefix = 'TALK_AUTHOR_MENU';
|
||||
|
||||
export const SET_CONTENT_SLOT = `${prefix}_SET_CONTENT_SLOT`;
|
||||
export const RESET_CONTENT_SLOT = `${prefix}_RESET_CONTENT_SLOT`;
|
||||
export const OPEN_MENU = `${prefix}_OPEN_MENU`;
|
||||
export const CLOSE_MENU = `${prefix}_CLOSE_MENU`;
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import React from 'react';
|
||||
import {connect, withFragments} from 'plugin-api/beta/client/hocs';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import AuthorName from '../components/AuthorName';
|
||||
import {setContentSlot, resetContentSlot, openMenu, closeMenu} from '../actions';
|
||||
import {compose, gql} from 'react-apollo';
|
||||
import {getSlotFragmentSpreads, getShallowChanges} from 'plugin-api/beta/client/utils';
|
||||
|
||||
class AuthorNameContainer extends React.Component {
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
|
||||
// Specifically handle `showMenuForComment` if it is the only change.
|
||||
const changes = getShallowChanges(this.props, nextProps);
|
||||
if (changes.length === 1 && changes[0] === 'showMenuForComment') {
|
||||
const commentId = this.props.comment.id;
|
||||
if (
|
||||
commentId !== this.props.showMenuForComment &&
|
||||
commentId !== nextProps.showMenuForComment
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent Slot from rerendering when no props has shallowly changed.
|
||||
return changes.length !== 0;
|
||||
}
|
||||
|
||||
toggleMenu = () => {
|
||||
if (this.props.showMenuForComment === this.props.comment.id) {
|
||||
this.props.closeMenu();
|
||||
} else {
|
||||
this.props.openMenu(this.props.comment.id);
|
||||
}
|
||||
}
|
||||
|
||||
hideMenu = () => {
|
||||
if (this.props.showMenuForComment === this.props.comment.id) {
|
||||
this.props.closeMenu();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <AuthorName
|
||||
data={this.props.data}
|
||||
root={this.props.root}
|
||||
asset={this.props.asset}
|
||||
comment={this.props.comment}
|
||||
contentSlot={this.props.contentSlot}
|
||||
menuVisible={this.props.showMenuForComment === this.props.comment.id}
|
||||
toggleMenu={this.toggleMenu}
|
||||
hideMenu={this.hideMenu}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
|
||||
const slots = [
|
||||
'authorMenuInfos',
|
||||
'authorMenuActions',
|
||||
];
|
||||
|
||||
const mapStateToProps = ({talkPluginAuthorMenu: state}) => ({
|
||||
contentSlot: state.contentSlot,
|
||||
showMenuForComment: state.showMenuForComment,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) =>
|
||||
bindActionCreators({
|
||||
setContentSlot,
|
||||
resetContentSlot,
|
||||
openMenu,
|
||||
closeMenu,
|
||||
}, dispatch);
|
||||
|
||||
const withAuthorNameFragments = withFragments({
|
||||
root: gql`
|
||||
fragment TalkAuthorMenu_AuthorName_root on RootQuery {
|
||||
__typename
|
||||
${getSlotFragmentSpreads(slots, 'root')}
|
||||
}`,
|
||||
asset: gql`
|
||||
fragment TalkAuthorMenu_AuthorName_asset on Asset {
|
||||
__typename
|
||||
${getSlotFragmentSpreads(slots, 'asset')}
|
||||
}`,
|
||||
comment: gql`
|
||||
fragment TalkAuthorMenu_AuthorName_comment on Comment {
|
||||
__typename
|
||||
id
|
||||
user {
|
||||
username
|
||||
}
|
||||
${getSlotFragmentSpreads(slots, 'comment')}
|
||||
}`,
|
||||
});
|
||||
|
||||
const enhance = compose(
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
withAuthorNameFragments,
|
||||
);
|
||||
|
||||
export default enhance(AuthorNameContainer);
|
||||
@@ -0,0 +1,11 @@
|
||||
import AuthorName from './containers/AuthorName';
|
||||
import reducer from './reducer';
|
||||
import translations from './translations.yml';
|
||||
|
||||
export default {
|
||||
reducer,
|
||||
slots: {
|
||||
commentAuthorName: [AuthorName]
|
||||
},
|
||||
translations
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import {SET_CONTENT_SLOT, RESET_CONTENT_SLOT, OPEN_MENU, CLOSE_MENU} from './constants';
|
||||
|
||||
const initialState = {
|
||||
contentSlot: null,
|
||||
showMenuForComment: null,
|
||||
};
|
||||
|
||||
export default function reducer(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case SET_CONTENT_SLOT:
|
||||
return {
|
||||
...state,
|
||||
contentSlot: action.slot,
|
||||
};
|
||||
case RESET_CONTENT_SLOT:
|
||||
return {
|
||||
...state,
|
||||
contentSlot: initialState.contentSlot,
|
||||
};
|
||||
case OPEN_MENU:
|
||||
return {
|
||||
...state,
|
||||
showMenuForComment: action.id,
|
||||
};
|
||||
case CLOSE_MENU:
|
||||
return {
|
||||
...state,
|
||||
showMenuForComment: null,
|
||||
contentSlot: null,
|
||||
};
|
||||
default :
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
en:
|
||||
talk-plugin-author-menu:
|
||||
es:
|
||||
talk-plugin-author-menu:
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = {};
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"presets": [
|
||||
"es2015"
|
||||
],
|
||||
"plugins": [
|
||||
"add-module-exports",
|
||||
"transform-class-properties",
|
||||
"transform-decorators-legacy",
|
||||
"transform-object-assign",
|
||||
"transform-object-rest-spread",
|
||||
"transform-async-to-generator",
|
||||
"transform-react-jsx"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true,
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"rules": {
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-uses-vars": "error",
|
||||
"no-console": ["warn", { "allow": ["warn", "error"] }]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
.root {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.button {
|
||||
composes: buttonReset from "coral-framework/styles/reset.css";
|
||||
border: 1px solid rgba(1, 1, 1, 0.8);
|
||||
border-radius: 1px;
|
||||
padding: 3px 6px;
|
||||
font-size: 12px;
|
||||
transition: color 100ms, background 100ms;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(1, 1, 1, 0.8);
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import styles from './IgnoreUserAction.css';
|
||||
import {t} from 'plugin-api/beta/client/services';
|
||||
import cn from 'classnames';
|
||||
|
||||
export default ({ignoreUser}) => (
|
||||
<button
|
||||
className={cn(styles.button, 'talk-plugin-ignore-user-action')}
|
||||
onClick={ignoreUser}>
|
||||
{t('talk-plugin-ignore-user.ignore_user')}
|
||||
</button>
|
||||
);
|
||||
@@ -0,0 +1,45 @@
|
||||
.root {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.message {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 0;
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.button {
|
||||
composes: buttonReset from "coral-framework/styles/reset.css";
|
||||
border: 1px solid rgba(1, 1, 1, 0.8);
|
||||
border-radius: 1px;
|
||||
padding: 3px 6px;
|
||||
font-size: 12px;
|
||||
transition: color 100ms, background 100ms;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(1, 1, 1, 0.8);
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel {
|
||||
composes: buttonReset from "coral-framework/styles/reset.css";
|
||||
padding: 3px 6px;
|
||||
font-size: 12px;
|
||||
transition: color 100ms;
|
||||
margin-right: 4px;
|
||||
|
||||
&:hover {
|
||||
color: rgba(1, 1, 1, 0.75);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import styles from './IgnoreUserConfirmation.css';
|
||||
import {t} from 'plugin-api/beta/client/services';
|
||||
import cn from 'classnames';
|
||||
|
||||
export default ({ignoreUser, cancel, username}) => (
|
||||
<aside className={cn(styles.root, 'talk-plugin-ignore-user-confirmation')}>
|
||||
<div className={styles.message}>
|
||||
<h1 className={styles.title}>
|
||||
{t('talk-plugin-ignore-user.confirmation_title', username)}
|
||||
</h1>
|
||||
{t('talk-plugin-ignore-user.confirmation')}
|
||||
</div>
|
||||
<div className={cn(styles.actions, 'talk-plugin-ignore-user-confirmation-actions')}>
|
||||
<button className={cn(styles.cancel, 'talk-plugin-ignore-user-confirmation-cancel')} onClick={cancel}>
|
||||
{t('talk-plugin-ignore-user.cancel')}
|
||||
</button>
|
||||
<button className={cn(styles.button, 'talk-plugin-ignore-user-confirmation-button')} onClick={ignoreUser}>
|
||||
{t('talk-plugin-ignore-user.ignore_user')}
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
@@ -0,0 +1,22 @@
|
||||
.list {
|
||||
display: table;
|
||||
list-style-type: none;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.listItem {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.username {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.button {
|
||||
composes: buttonReset from "coral-framework/styles/reset.css";
|
||||
|
||||
margin-left: 16px;
|
||||
color: #D0011B;
|
||||
text-decoration: underline;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import styles from './IgnoredUserSection.css';
|
||||
import {t} from 'plugin-api/beta/client/services';
|
||||
|
||||
export default ({ignoredUsers, stopIgnoringUser}) => (
|
||||
<section className={'talk-plugin-ignore-user-section'}>
|
||||
<h3>{t('talk-plugin-ignore-user.section_title')}</h3>
|
||||
<p>{t('talk-plugin-ignore-user.section_info')}</p>
|
||||
<ul className={styles.list}>
|
||||
{ignoredUsers.map(({username, id}) => (
|
||||
<li className={styles.listItem} key={id}>
|
||||
<span className={styles.username}>{username}</span>
|
||||
<button
|
||||
onClick={() => stopIgnoringUser({id})}
|
||||
className={styles.button}
|
||||
>
|
||||
{t('talk-plugin-ignore-user.stop_ignoring')}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
);
|
||||
@@ -0,0 +1,53 @@
|
||||
import React from 'react';
|
||||
import IgnoreUserAction from '../components/IgnoreUserAction';
|
||||
import {compose, gql} from 'react-apollo';
|
||||
import {connect, withFragments, excludeIf} from 'plugin-api/beta/client/hocs';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {setContentSlot} from 'plugins/talk-plugin-author-menu/client/actions';
|
||||
import IgnoreUserConfirmation from './IgnoreUserConfirmation';
|
||||
import {getDefinitionName} from 'plugin-api/beta/client/utils';
|
||||
|
||||
class IgnoreUserActionContainer extends React.Component {
|
||||
|
||||
ignoreUser = () => {
|
||||
this.props.setContentSlot('ignoreUserConfirmation');
|
||||
};
|
||||
|
||||
render() {
|
||||
return <IgnoreUserAction
|
||||
ignoreUser={this.ignoreUser}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) =>
|
||||
bindActionCreators({
|
||||
setContentSlot,
|
||||
}, dispatch);
|
||||
|
||||
const withIgnoreUserActionFragments = withFragments({
|
||||
root: gql`
|
||||
fragment TalkIgnoreUser_IgnoreUserAction_root on RootQuery {
|
||||
me {
|
||||
id
|
||||
}
|
||||
}
|
||||
`,
|
||||
comment: gql`
|
||||
fragment TalkIgnoreUser_IgnoreUserAction_comment on Comment {
|
||||
user {
|
||||
id
|
||||
}
|
||||
...${getDefinitionName(IgnoreUserConfirmation.fragments.comment)}
|
||||
}
|
||||
${IgnoreUserConfirmation.fragments.comment}
|
||||
`,
|
||||
});
|
||||
|
||||
const enhance = compose(
|
||||
connect(null, mapDispatchToProps),
|
||||
withIgnoreUserActionFragments,
|
||||
excludeIf(({root: {me}, comment}) => !me || me.id === comment.user.id),
|
||||
);
|
||||
|
||||
export default enhance(IgnoreUserActionContainer);
|
||||
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import IgnoreUserConfirmation from '../components/IgnoreUserConfirmation';
|
||||
import {compose, gql} from 'react-apollo';
|
||||
import {connect, withFragments, withIgnoreUser} from 'plugin-api/beta/client/hocs';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {closeMenu} from 'plugins/talk-plugin-author-menu/client/actions';
|
||||
import {notify} from 'plugin-api/beta/client/actions/notification';
|
||||
import {t} from 'plugin-api/beta/client/services';
|
||||
import {getErrorMessages} from 'plugin-api/beta/client/utils';
|
||||
|
||||
class IgnoreUserConfirmationContainer extends React.Component {
|
||||
|
||||
ignoreUser = () => {
|
||||
const {ignoreUser, notify, comment, closeMenu} = this.props;
|
||||
ignoreUser(comment.user.id)
|
||||
.then(() => {
|
||||
notify('success', t('talk-plugin-ignore-user.notify_success', comment.user.username));
|
||||
})
|
||||
.catch((err) => {
|
||||
notify('error', getErrorMessages(err));
|
||||
});
|
||||
closeMenu();
|
||||
};
|
||||
|
||||
cancel = () => {
|
||||
this.props.closeMenu();
|
||||
}
|
||||
|
||||
render() {
|
||||
return <IgnoreUserConfirmation
|
||||
username={this.props.comment.user.username}
|
||||
ignoreUser={this.ignoreUser}
|
||||
cancel={this.cancel}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) =>
|
||||
bindActionCreators({
|
||||
closeMenu,
|
||||
notify,
|
||||
}, dispatch);
|
||||
|
||||
const withIgnoreUserConfirmationFragments = withFragments({
|
||||
comment: gql`
|
||||
fragment TalkIgnoreUser_IgnoreUserConfirmation_comment on Comment {
|
||||
user {
|
||||
id
|
||||
username
|
||||
}
|
||||
}`,
|
||||
});
|
||||
|
||||
const enhance = compose(
|
||||
connect(null, mapDispatchToProps),
|
||||
withIgnoreUserConfirmationFragments,
|
||||
withIgnoreUser,
|
||||
);
|
||||
|
||||
export default enhance(IgnoreUserConfirmationContainer);
|
||||
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import IgnoredUserSection from '../components/IgnoredUserSection';
|
||||
import {compose, gql} from 'react-apollo';
|
||||
import {withFragments, excludeIf, withStopIgnoringUser} from 'plugin-api/beta/client/hocs';
|
||||
|
||||
class IgnoredUserSectionContainer extends React.Component {
|
||||
|
||||
render() {
|
||||
return <IgnoredUserSection
|
||||
stopIgnoringUser={this.props.stopIgnoringUser}
|
||||
ignoredUsers={this.props.root.me.ignoredUsers}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
|
||||
const withIgnoredUserSectionFragments = withFragments({
|
||||
root: gql`
|
||||
fragment TalkIgnoreUser_IgnoredUserSection_root on RootQuery {
|
||||
me {
|
||||
id
|
||||
ignoredUsers {
|
||||
id,
|
||||
username,
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
});
|
||||
|
||||
const enhance = compose(
|
||||
withIgnoredUserSectionFragments,
|
||||
withStopIgnoringUser,
|
||||
excludeIf(({root: {me}}) => me.ignoredUsers.length === 0),
|
||||
);
|
||||
|
||||
export default enhance(IgnoredUserSectionContainer);
|
||||
@@ -0,0 +1,43 @@
|
||||
import IgnoreUserAction from './containers/IgnoreUserAction';
|
||||
import IgnoreUserConfirmation from './containers/IgnoreUserConfirmation';
|
||||
import IgnoredUserSection from './containers/IgnoredUserSection';
|
||||
import translations from './translations.yml';
|
||||
import update from 'immutability-helper';
|
||||
|
||||
export default {
|
||||
slots: {
|
||||
authorMenuActions: [IgnoreUserAction],
|
||||
ignoreUserConfirmation: [IgnoreUserConfirmation],
|
||||
profileSections: [IgnoredUserSection],
|
||||
},
|
||||
translations,
|
||||
mutations: {
|
||||
IgnoreUser: ({variables}) => ({
|
||||
updateQueries: {
|
||||
CoralEmbedStream_Embed: (previousData) => {
|
||||
const ignoredUserId = variables.id;
|
||||
const updated = update(previousData, {me: {ignoredUsers: {$push: [{
|
||||
id: ignoredUserId,
|
||||
__typename: 'User',
|
||||
}]}}});
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
}),
|
||||
StopIgnoringUser: ({variables}) => ({
|
||||
updateQueries: {
|
||||
CoralEmbedStream_Profile: (previousData) => {
|
||||
const noLongerIgnoredUserId = variables.id;
|
||||
|
||||
// remove noLongerIgnoredUserId from ignoredUsers
|
||||
const updated = update(previousData, {me: {ignoredUsers: {
|
||||
$apply: (ignoredUsers) => {
|
||||
return ignoredUsers.filter((u) => u.id !== noLongerIgnoredUserId);
|
||||
}
|
||||
}}});
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
en:
|
||||
talk-plugin-ignore-user:
|
||||
section_title: Ignored users
|
||||
section_info: Because you ignored the following commenters, their comments are hidden.
|
||||
stop_ignoring: Stop ignoring
|
||||
ignore_user: Ignore User
|
||||
cancel: Cancel
|
||||
confirmation: |
|
||||
When you ignore a user, all comments they wrote on the site will be hidden from you. You can
|
||||
undo this later from My Profile.
|
||||
notify_success: |
|
||||
You are now ignoring {0}. You can undo this action from My Profile.
|
||||
confirmation_title: Ignore {0}?
|
||||
es:
|
||||
talk-plugin-ignore-user:
|
||||
section_title: "Usuarios ignorados"
|
||||
stop_ignoring: "No ignorar más"
|
||||
fr:
|
||||
talk-plugin-ignore-user:
|
||||
section_title: "Utilisateurs ignorés"
|
||||
pt_Br:
|
||||
talk-plugin-ignore-user:
|
||||
section_title: "Usuários ignorados"
|
||||
section_info: "Porque você ignorou os seguintes comentadores, seus comentários estão ocultos."
|
||||
stop_ignoring: "Pare de ignorar"
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = {};
|
||||
@@ -5,5 +5,5 @@ export default {
|
||||
translations,
|
||||
slots: {
|
||||
commentReactions: [LikeButton]
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"presets": [
|
||||
"es2015"
|
||||
],
|
||||
"plugins": [
|
||||
"add-module-exports",
|
||||
"transform-class-properties",
|
||||
"transform-decorators-legacy",
|
||||
"transform-object-assign",
|
||||
"transform-object-rest-spread",
|
||||
"transform-async-to-generator",
|
||||
"transform-react-jsx"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true,
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"rules": {
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-uses-vars": "error",
|
||||
"no-console": ["warn", { "allow": ["warn", "error"] }]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
.root {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.root:not(:last-child) {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.memberSince {
|
||||
margin-left: 4px;
|
||||
letter-spacing: 0.2px;
|
||||
font-size: 13px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 18px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import styles from './MemberSinceInfo.css';
|
||||
import {t} from 'plugin-api/beta/client/services';
|
||||
import {Icon} from 'plugin-api/beta/client/components/ui';
|
||||
import cn from 'classnames';
|
||||
import moment from 'moment';
|
||||
|
||||
export default ({memberSinceDate}) => (
|
||||
<div className={cn(styles.root, 'talk-plugin-member-since')}>
|
||||
<Icon name="date_range" className={cn(styles.icon, 'talk-plugin-member-since-icon')} />
|
||||
<span className={cn(styles.memberSince, 'talk-plugin-member-since-date')}>
|
||||
{t('talk-plugin-member-since.member_since')}: {moment(new Date(memberSinceDate)).format('MMM DD, YYYY')}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import MemberSinceInfo from '../components/MemberSinceInfo';
|
||||
import {compose, gql} from 'react-apollo';
|
||||
import {withFragments} from 'plugin-api/beta/client/hocs';
|
||||
|
||||
class MemberSinceInfoContainer extends React.Component {
|
||||
render() {
|
||||
return <MemberSinceInfo
|
||||
memberSinceDate={this.props.comment.user.created_at}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
|
||||
const withMemberSinceInfoFragments = withFragments({
|
||||
comment: gql`
|
||||
fragment TalkAuthorMenu_MemberSinceInfo_comment on Comment {
|
||||
user {
|
||||
username
|
||||
created_at
|
||||
}
|
||||
}`,
|
||||
});
|
||||
|
||||
const enhance = compose(
|
||||
withMemberSinceInfoFragments,
|
||||
);
|
||||
|
||||
export default enhance(MemberSinceInfoContainer);
|
||||
@@ -0,0 +1,9 @@
|
||||
import MemberSinceInfo from './containers/MemberSinceInfo';
|
||||
import translations from './translations.yml';
|
||||
|
||||
export default {
|
||||
slots: {
|
||||
authorMenuInfos: [MemberSinceInfo]
|
||||
},
|
||||
translations
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
en:
|
||||
talk-plugin-member-since:
|
||||
member_since: "Member Since"
|
||||
es:
|
||||
talk-plugin-member-since:
|
||||
member_since: "Miembro desde"
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = {};
|
||||
@@ -63,20 +63,13 @@ abbrev@1, abbrev@1.0.x:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135"
|
||||
|
||||
accepts@^1.3.4:
|
||||
accepts@^1.3.4, accepts@~1.3.3:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f"
|
||||
dependencies:
|
||||
mime-types "~2.1.16"
|
||||
negotiator "0.6.1"
|
||||
|
||||
accepts@~1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
|
||||
dependencies:
|
||||
mime-types "~2.1.11"
|
||||
negotiator "0.6.1"
|
||||
|
||||
acorn-dynamic-import@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4"
|
||||
@@ -356,18 +349,12 @@ async@2.1.4:
|
||||
dependencies:
|
||||
lodash "^4.14.0"
|
||||
|
||||
async@2.4.1:
|
||||
async@2.4.1, async@^2.1.2, async@^2.1.4:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7"
|
||||
dependencies:
|
||||
lodash "^4.14.0"
|
||||
|
||||
async@^2.1.2, async@^2.1.4:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d"
|
||||
dependencies:
|
||||
lodash "^4.14.0"
|
||||
|
||||
async@~0.9.0:
|
||||
version "0.9.2"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
|
||||
@@ -416,15 +403,7 @@ babel-cli@^6.26.0:
|
||||
optionalDependencies:
|
||||
chokidar "^1.6.1"
|
||||
|
||||
babel-code-frame@^6.11.0, babel-code-frame@^6.22.0:
|
||||
version "6.22.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
|
||||
dependencies:
|
||||
chalk "^1.1.0"
|
||||
esutils "^2.0.2"
|
||||
js-tokens "^3.0.0"
|
||||
|
||||
babel-code-frame@^6.26.0:
|
||||
babel-code-frame@^6.11.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
|
||||
dependencies:
|
||||
@@ -465,20 +444,7 @@ babel-eslint@^7.2.1:
|
||||
babel-types "^6.23.0"
|
||||
babylon "^6.17.0"
|
||||
|
||||
babel-generator@^6.18.0:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.1.tgz#e715f486c58ded25649d888944d52aa07c5d9497"
|
||||
dependencies:
|
||||
babel-messages "^6.23.0"
|
||||
babel-runtime "^6.22.0"
|
||||
babel-types "^6.24.1"
|
||||
detect-indent "^4.0.0"
|
||||
jsesc "^1.3.0"
|
||||
lodash "^4.2.0"
|
||||
source-map "^0.5.0"
|
||||
trim-right "^1.0.1"
|
||||
|
||||
babel-generator@^6.26.0:
|
||||
babel-generator@^6.18.0, babel-generator@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5"
|
||||
dependencies:
|
||||
@@ -956,31 +922,14 @@ babel-register@^6.26.0:
|
||||
mkdirp "^0.5.1"
|
||||
source-map-support "^0.4.15"
|
||||
|
||||
babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.6.1:
|
||||
version "6.23.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b"
|
||||
dependencies:
|
||||
core-js "^2.4.0"
|
||||
regenerator-runtime "^0.10.0"
|
||||
|
||||
babel-runtime@^6.26.0:
|
||||
babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0, babel-runtime@^6.6.1:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
|
||||
dependencies:
|
||||
core-js "^2.4.0"
|
||||
regenerator-runtime "^0.11.0"
|
||||
|
||||
babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.3.0:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.24.1.tgz#04ae514f1f93b3a2537f2a0f60a5a45fb8308333"
|
||||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
babel-traverse "^6.24.1"
|
||||
babel-types "^6.24.1"
|
||||
babylon "^6.11.0"
|
||||
lodash "^4.2.0"
|
||||
|
||||
babel-template@^6.26.0:
|
||||
babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0, babel-template@^6.3.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
|
||||
dependencies:
|
||||
@@ -990,21 +939,7 @@ babel-template@^6.26.0:
|
||||
babylon "^6.18.0"
|
||||
lodash "^4.17.4"
|
||||
|
||||
babel-traverse@^6.18.0, babel-traverse@^6.23.1, babel-traverse@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.24.1.tgz#ab36673fd356f9a0948659e7b338d5feadb31695"
|
||||
dependencies:
|
||||
babel-code-frame "^6.22.0"
|
||||
babel-messages "^6.23.0"
|
||||
babel-runtime "^6.22.0"
|
||||
babel-types "^6.24.1"
|
||||
babylon "^6.15.0"
|
||||
debug "^2.2.0"
|
||||
globals "^9.0.0"
|
||||
invariant "^2.2.0"
|
||||
lodash "^4.2.0"
|
||||
|
||||
babel-traverse@^6.26.0:
|
||||
babel-traverse@^6.18.0, babel-traverse@^6.23.1, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
|
||||
dependencies:
|
||||
@@ -1018,16 +953,7 @@ babel-traverse@^6.26.0:
|
||||
invariant "^2.2.2"
|
||||
lodash "^4.17.4"
|
||||
|
||||
babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.23.0, babel-types@^6.24.1:
|
||||
version "6.24.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975"
|
||||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
esutils "^2.0.2"
|
||||
lodash "^4.2.0"
|
||||
to-fast-properties "^1.0.1"
|
||||
|
||||
babel-types@^6.26.0:
|
||||
babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.23.0, babel-types@^6.24.1, babel-types@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
|
||||
dependencies:
|
||||
@@ -1036,11 +962,7 @@ babel-types@^6.26.0:
|
||||
lodash "^4.17.4"
|
||||
to-fast-properties "^1.0.3"
|
||||
|
||||
babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0, babylon@^6.17.0:
|
||||
version "6.17.0"
|
||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.0.tgz#37da948878488b9c4e3c4038893fa3314b3fc932"
|
||||
|
||||
babylon@^6.18.0:
|
||||
babylon@^6.13.0, babylon@^6.17.0, babylon@^6.18.0:
|
||||
version "6.18.0"
|
||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
|
||||
|
||||
@@ -1056,7 +978,7 @@ balanced-match@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.2.1.tgz#7bc658b4bed61eee424ad74f75f5c3e2c4df3cc7"
|
||||
|
||||
balanced-match@^0.4.1, balanced-match@^0.4.2:
|
||||
balanced-match@^0.4.2:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
|
||||
|
||||
@@ -1112,7 +1034,7 @@ bluebird@2.9.24:
|
||||
version "2.9.24"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.9.24.tgz#14a2e75f0548323dc35aa440d92007ca154e967c"
|
||||
|
||||
bluebird@3.5.0, bluebird@^3.3.4:
|
||||
bluebird@3.5.0, bluebird@^3.3.4, bluebird@^3.4.6:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
|
||||
|
||||
@@ -1120,30 +1042,11 @@ bluebird@^2.10.2:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
|
||||
|
||||
bluebird@^3.4.6:
|
||||
version "3.4.7"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3"
|
||||
|
||||
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
|
||||
version "4.11.6"
|
||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
|
||||
|
||||
body-parser@^1.12.2:
|
||||
version "1.17.1"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.1.tgz#75b3bc98ddd6e7e0d8ffe750dfaca5c66993fa47"
|
||||
dependencies:
|
||||
bytes "2.4.0"
|
||||
content-type "~1.0.2"
|
||||
debug "2.6.1"
|
||||
depd "~1.1.0"
|
||||
http-errors "~1.6.1"
|
||||
iconv-lite "0.4.15"
|
||||
on-finished "~2.3.0"
|
||||
qs "6.4.0"
|
||||
raw-body "~2.2.0"
|
||||
type-is "~1.6.14"
|
||||
|
||||
body-parser@^1.17.2:
|
||||
body-parser@^1.12.2, body-parser@^1.17.2:
|
||||
version "1.17.2"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.2.tgz#f8892abc8f9e627d42aedafbca66bf5ab99104ee"
|
||||
dependencies:
|
||||
@@ -1172,13 +1075,6 @@ bowser@^1.7.2:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.7.2.tgz#b94cc6925ba6b5e07c421a58e601ce4611264572"
|
||||
|
||||
brace-expansion@^1.0.0:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
|
||||
dependencies:
|
||||
balanced-match "^0.4.1"
|
||||
concat-map "0.0.1"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
|
||||
@@ -1394,7 +1290,7 @@ chalk@2.0.1:
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^4.0.0"
|
||||
|
||||
chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
|
||||
chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
|
||||
dependencies:
|
||||
@@ -1867,11 +1763,7 @@ core-js@^1.0.0:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
|
||||
|
||||
core-js@^2.4.0:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
|
||||
|
||||
core-js@^2.5.0:
|
||||
core-js@^2.4.0, core-js@^2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.0.tgz#569c050918be6486b3837552028ae0466b717086"
|
||||
|
||||
@@ -2131,9 +2023,9 @@ date-now@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
|
||||
|
||||
debug@*:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.0.0.tgz#1d2feae53349047b08b264ec41906ba17a8516e4"
|
||||
debug@*, debug@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.0.1.tgz#0564c612b521dc92d9f2988f0549e34f9c98db64"
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
@@ -2143,12 +2035,6 @@ debug@2.6.0:
|
||||
dependencies:
|
||||
ms "0.7.2"
|
||||
|
||||
debug@2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351"
|
||||
dependencies:
|
||||
ms "0.7.2"
|
||||
|
||||
debug@2.6.7:
|
||||
version "2.6.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e"
|
||||
@@ -2161,12 +2047,6 @@ debug@2.6.8, debug@^2.2.0, debug@^2.6.8:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.0.1.tgz#0564c612b521dc92d9f2988f0549e34f9c98db64"
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@~0.7.4:
|
||||
version "0.7.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39"
|
||||
@@ -3200,7 +3080,7 @@ glob@7.0.x:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
|
||||
glob@7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
|
||||
dependencies:
|
||||
@@ -3211,7 +3091,7 @@ glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@7.1.2, glob@^7.1.2:
|
||||
glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||
dependencies:
|
||||
@@ -3242,10 +3122,6 @@ glob@^6.0.4:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
globals@^9.0.0:
|
||||
version "9.17.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286"
|
||||
|
||||
globals@^9.17.0, globals@^9.18.0:
|
||||
version "9.18.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
|
||||
@@ -3372,15 +3248,7 @@ graphql-server-module-graphiql@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql-server-module-graphiql/-/graphql-server-module-graphiql-0.6.0.tgz#e37634b05f000731981e8ed13103f9a5861e5da0"
|
||||
|
||||
graphql-subscriptions@^0.4.2:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-0.4.4.tgz#39cff32d08dd3c990113864bab77154403727e9b"
|
||||
dependencies:
|
||||
"@types/graphql" "^0.9.1"
|
||||
es6-promise "^4.0.5"
|
||||
iterall "^1.1.1"
|
||||
|
||||
graphql-subscriptions@^0.4.3:
|
||||
graphql-subscriptions@^0.4.2, graphql-subscriptions@^0.4.3:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-0.4.3.tgz#2aed6ba87551cc747742b793497ff24b22991867"
|
||||
dependencies:
|
||||
@@ -4240,22 +4108,18 @@ js-stringify@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db"
|
||||
|
||||
js-tokens@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
|
||||
|
||||
js-tokens@^3.0.2:
|
||||
js-tokens@^3.0.0, js-tokens@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
|
||||
|
||||
js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.5.2, js-yaml@^3.7.0:
|
||||
js-yaml@3.x, js-yaml@^3.5.2:
|
||||
version "3.8.3"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.3.tgz#33a05ec481c850c8875929166fe1beb61c728766"
|
||||
dependencies:
|
||||
argparse "^1.0.7"
|
||||
esprima "^3.1.1"
|
||||
|
||||
js-yaml@^3.9.1:
|
||||
js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.9.1:
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0"
|
||||
dependencies:
|
||||
@@ -4318,11 +4182,7 @@ jshint@^2.8.0:
|
||||
shelljs "0.3.x"
|
||||
strip-json-comments "1.0.x"
|
||||
|
||||
json-loader@^0.5.4:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.4.tgz#8baa1365a632f58a3c46d20175fc6002c96e37de"
|
||||
|
||||
json-loader@^0.5.7:
|
||||
json-loader@^0.5.4, json-loader@^0.5.7:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d"
|
||||
|
||||
@@ -4954,15 +4814,11 @@ mime-db@~1.12.0:
|
||||
version "1.12.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.12.0.tgz#3d0c63180f458eb10d325aaa37d7c58ae312e9d7"
|
||||
|
||||
mime-db@~1.27.0:
|
||||
version "1.27.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1"
|
||||
|
||||
mime-types@^2.1.10, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7:
|
||||
version "2.1.15"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed"
|
||||
mime-types@^2.1.10, mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.7:
|
||||
version "2.1.16"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.16.tgz#2b858a52e5ecd516db897ac2be87487830698e23"
|
||||
dependencies:
|
||||
mime-db "~1.27.0"
|
||||
mime-db "~1.29.0"
|
||||
|
||||
mime-types@~2.0.3:
|
||||
version "2.0.14"
|
||||
@@ -4970,12 +4826,6 @@ mime-types@~2.0.3:
|
||||
dependencies:
|
||||
mime-db "~1.12.0"
|
||||
|
||||
mime-types@~2.1.16:
|
||||
version "2.1.16"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.16.tgz#2b858a52e5ecd516db897ac2be87487830698e23"
|
||||
dependencies:
|
||||
mime-db "~1.29.0"
|
||||
|
||||
mime@1.3.4, mime@1.3.x, mime@^1.3.4:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
|
||||
@@ -4992,13 +4842,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
|
||||
|
||||
"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
|
||||
dependencies:
|
||||
brace-expansion "^1.0.0"
|
||||
|
||||
minimatch@^3.0.4, minimatch@~3.0.2:
|
||||
"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
dependencies:
|
||||
@@ -5043,7 +4887,7 @@ mocha@^3.1.2:
|
||||
mkdirp "0.5.1"
|
||||
supports-color "3.1.2"
|
||||
|
||||
moment@2.18.1, moment@2.x.x, moment@^2.10.3:
|
||||
moment@2.18.1, moment@2.x.x, moment@^2.10.3, moment@^2.18.1:
|
||||
version "2.18.1"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
|
||||
|
||||
@@ -6429,7 +6273,7 @@ pym.js@^1.1.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pym.js/-/pym.js-1.2.0.tgz#feb1e2c9b396613e5172192b0cdd75408f9c8322"
|
||||
|
||||
q@1.5.0:
|
||||
q@1.5.0, q@^1.1.2:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1"
|
||||
|
||||
@@ -6441,10 +6285,6 @@ q@2.0.3:
|
||||
pop-iterate "^1.0.1"
|
||||
weak-map "^1.0.5"
|
||||
|
||||
q@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.1.2.tgz#6357e291206701d99f197ab84e57e8ad196f2a89"
|
||||
|
||||
qs@6.4.0, qs@~6.4.0:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
|
||||
@@ -6796,10 +6636,6 @@ regenerate@^1.2.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
|
||||
|
||||
regenerator-runtime@^0.10.0:
|
||||
version "0.10.4"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.4.tgz#74cb6598d3ba2eb18694e968a40e2b3b4df9cf93"
|
||||
|
||||
regenerator-runtime@^0.10.5:
|
||||
version "0.10.5"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
|
||||
@@ -7127,7 +6963,7 @@ shelljs@0.3.x:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1"
|
||||
|
||||
shelljs@0.7.8:
|
||||
shelljs@0.7.8, shelljs@^0.7.0:
|
||||
version "0.7.8"
|
||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3"
|
||||
dependencies:
|
||||
@@ -7135,14 +6971,6 @@ shelljs@0.7.8:
|
||||
interpret "^1.0.0"
|
||||
rechoir "^0.6.2"
|
||||
|
||||
shelljs@^0.7.0:
|
||||
version "0.7.7"
|
||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1"
|
||||
dependencies:
|
||||
glob "^7.0.0"
|
||||
interpret "^1.0.0"
|
||||
rechoir "^0.6.2"
|
||||
|
||||
signal-exit@^3.0.0, signal-exit@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
||||
@@ -7275,7 +7103,7 @@ source-map@0.4.x, source-map@^0.4.4:
|
||||
dependencies:
|
||||
amdefine ">=0.0.4"
|
||||
|
||||
source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3:
|
||||
source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3:
|
||||
version "0.5.6"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
|
||||
|
||||
@@ -7648,10 +7476,6 @@ to-capital-case@^1.0.0:
|
||||
dependencies:
|
||||
to-space-case "^1.0.0"
|
||||
|
||||
to-fast-properties@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320"
|
||||
|
||||
to-fast-properties@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
|
||||
@@ -7753,7 +7577,7 @@ type-detect@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea"
|
||||
|
||||
type-is@~1.6.14, type-is@~1.6.15:
|
||||
type-is@~1.6.15:
|
||||
version "1.6.15"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
|
||||
dependencies:
|
||||
@@ -8051,14 +7875,10 @@ word-wrap@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.1.0.tgz#356153d61d10610d600785c5d701288e0ae764a6"
|
||||
|
||||
word-wrap@1.2.3:
|
||||
word-wrap@1.2.3, word-wrap@^1.0.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
||||
|
||||
word-wrap@^1.0.3:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.1.tgz#248f459b465d179a17bc407c854d3151d07e45d8"
|
||||
|
||||
wordwrap@0.0.2, wordwrap@~0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
|
||||
|
||||
Reference in New Issue
Block a user