mirror of
https://github.com/wassname/talk.git
synced 2026-07-04 21:05:27 +08:00
Merge branch 'master' into translations-de-4.4.1
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
"https://nodesecurity.io/advisories/594",
|
||||
"https://nodesecurity.io/advisories/603",
|
||||
"https://nodesecurity.io/advisories/611",
|
||||
"https://nodesecurity.io/advisories/612"
|
||||
"https://nodesecurity.io/advisories/612",
|
||||
"https://nodesecurity.io/advisories/654"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
.external {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.separator h5 {
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.slot > * {
|
||||
margin-bottom: 8px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styles from './External.css';
|
||||
import Slot from 'coral-framework/components/Slot';
|
||||
import IfSlotIsNotEmpty from 'coral-framework/components/IfSlotIsNotEmpty';
|
||||
|
||||
const External = ({ slot }) => (
|
||||
<IfSlotIsNotEmpty slot={slot}>
|
||||
<div>
|
||||
<div className={styles.external}>
|
||||
<Slot fill={slot} className={styles.slot} />
|
||||
</div>
|
||||
<div className={styles.separator}>
|
||||
<h5>Or</h5>
|
||||
</div>
|
||||
</div>
|
||||
</IfSlotIsNotEmpty>
|
||||
);
|
||||
|
||||
External.propTypes = {
|
||||
slot: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default External;
|
||||
@@ -4,6 +4,7 @@ import styles from './SignIn.css';
|
||||
import { Button, TextField, Alert } from 'coral-ui';
|
||||
import cn from 'classnames';
|
||||
import Recaptcha from 'coral-framework/components/Recaptcha';
|
||||
import External from './External';
|
||||
|
||||
class SignIn extends React.Component {
|
||||
recaptcha = null;
|
||||
@@ -33,48 +34,55 @@ class SignIn extends React.Component {
|
||||
render() {
|
||||
const { email, password, errorMessage, requireRecaptcha } = this.props;
|
||||
return (
|
||||
<form className="talk-admin-login-sign-in" onSubmit={this.handleSubmit}>
|
||||
{errorMessage && <Alert>{errorMessage}</Alert>}
|
||||
<TextField
|
||||
id="email"
|
||||
label="Email Address"
|
||||
value={email}
|
||||
onChange={this.handleEmailChange}
|
||||
/>
|
||||
<TextField
|
||||
id="password"
|
||||
label="Password"
|
||||
value={password}
|
||||
onChange={this.handlePasswordChange}
|
||||
type="password"
|
||||
/>
|
||||
{requireRecaptcha && (
|
||||
<div className={styles.recaptcha}>
|
||||
<Recaptcha
|
||||
ref={this.handleRecaptchaRef}
|
||||
onVerify={this.props.onRecaptchaVerify}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<Button
|
||||
className={cn(styles.signInButton, 'talk-admin-login-sign-in-button')}
|
||||
type="submit"
|
||||
cStyle="black"
|
||||
full
|
||||
>
|
||||
Sign In
|
||||
</Button>
|
||||
<p className={styles.forgotPasswordCTA}>
|
||||
Forgot your password?{' '}
|
||||
<a
|
||||
href="#"
|
||||
className={styles.forgotPasswordLink}
|
||||
onClick={this.handleForgotPasswordLink}
|
||||
<div className="talk-admin-login-sign-in">
|
||||
<External slot="authExternalAdminSignIn" />
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
{errorMessage && <Alert>{errorMessage}</Alert>}
|
||||
<TextField
|
||||
id="email"
|
||||
label="Email Address"
|
||||
value={email}
|
||||
onChange={this.handleEmailChange}
|
||||
/>
|
||||
<TextField
|
||||
id="password"
|
||||
label="Password"
|
||||
value={password}
|
||||
onChange={this.handlePasswordChange}
|
||||
type="password"
|
||||
/>
|
||||
{requireRecaptcha && (
|
||||
<div className={styles.recaptcha}>
|
||||
<Recaptcha
|
||||
ref={this.handleRecaptchaRef}
|
||||
onVerify={this.props.onRecaptchaVerify}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<Button
|
||||
className={cn(
|
||||
styles.signInButton,
|
||||
'talk-admin-login-sign-in-button'
|
||||
)}
|
||||
type="submit"
|
||||
cStyle="black"
|
||||
full
|
||||
>
|
||||
Request a new one.
|
||||
</a>
|
||||
</p>
|
||||
</form>
|
||||
Sign In
|
||||
</Button>
|
||||
<p className={styles.forgotPasswordCTA}>
|
||||
{/* TODO: translate */}
|
||||
Forgot your password?{' '}
|
||||
<a
|
||||
href="#"
|
||||
className={styles.forgotPasswordLink}
|
||||
onClick={this.handleForgotPasswordLink}
|
||||
>
|
||||
Request a new one.
|
||||
</a>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withSignIn } from 'coral-framework/hocs';
|
||||
import { withSignIn, withPopupAuthHandler } from 'coral-framework/hocs';
|
||||
import { compose } from 'recompose';
|
||||
import SignIn from '../components/SignIn';
|
||||
|
||||
@@ -55,4 +55,4 @@ SignInContainer.propTypes = {
|
||||
requireRecaptcha: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default compose(withSignIn)(SignInContainer);
|
||||
export default compose(withSignIn, withPopupAuthHandler)(SignInContainer);
|
||||
|
||||
@@ -82,6 +82,20 @@ class StreamSettings extends React.Component {
|
||||
this.props.updatePending({ updater });
|
||||
};
|
||||
|
||||
updateDisableCommenting = () => {
|
||||
const updater = {
|
||||
disableCommenting: {
|
||||
$set: !this.props.settings.disableCommenting,
|
||||
},
|
||||
};
|
||||
this.props.updatePending({ updater });
|
||||
};
|
||||
|
||||
updateDisableCommentingMessage = value => {
|
||||
const updater = { disableCommentingMessage: { $set: value } };
|
||||
this.props.updatePending({ updater });
|
||||
};
|
||||
|
||||
updateAutoClose = () => {
|
||||
const updater = {
|
||||
autoCloseStream: { $set: !this.props.settings.autoCloseStream },
|
||||
@@ -192,6 +206,25 @@ class StreamSettings extends React.Component {
|
||||
|
||||
{t('configure.edit_comment_timeframe_text_post')}
|
||||
</ConfigureCard>
|
||||
<ConfigureCard
|
||||
checked={settings.disableCommenting}
|
||||
onCheckbox={this.updateDisableCommenting}
|
||||
title={t('configure.disable_commenting_title')}
|
||||
>
|
||||
<p>{t('configure.disable_commenting_desc')}</p>
|
||||
<div
|
||||
className={cn(
|
||||
styles.configSettingDisableCommenting,
|
||||
settings.disableCommenting ? null : styles.hidden
|
||||
)}
|
||||
>
|
||||
<MarkdownEditor
|
||||
className={styles.descriptionBox}
|
||||
onChange={this.updateDisableCommentingMessage}
|
||||
value={settings.disableCommentingMessage}
|
||||
/>
|
||||
</div>
|
||||
</ConfigureCard>
|
||||
<ConfigureCard
|
||||
checked={settings.autoCloseStream}
|
||||
onCheckbox={this.updateAutoClose}
|
||||
|
||||
@@ -39,6 +39,8 @@ export default compose(
|
||||
autoCloseStream
|
||||
closedTimeout
|
||||
closedMessage
|
||||
disableCommenting
|
||||
disableCommentingMessage
|
||||
${getSlotFragmentSpreads(slots, 'settings')}
|
||||
}
|
||||
`,
|
||||
|
||||
@@ -3,32 +3,36 @@ import { getStaticConfiguration } from 'coral-framework/services/staticConfigura
|
||||
import { createPostMessage } from 'coral-framework/services/postMessage';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
try {
|
||||
const staticConfig = getStaticConfiguration();
|
||||
const { STATIC_ORIGIN: origin } = staticConfig;
|
||||
const postMessage = createPostMessage(origin);
|
||||
const staticConfig = getStaticConfiguration();
|
||||
const { STATIC_ORIGIN: origin } = staticConfig;
|
||||
const postMessage = createPostMessage(origin);
|
||||
|
||||
// Get the auth element and parse it as JSON by decoding it.
|
||||
const auth = document.getElementById('auth');
|
||||
const doc = document.implementation.createHTMLDocument('');
|
||||
doc.body.innerHTML = auth.innerText;
|
||||
// Get the auth element and parse it as JSON by decoding it.
|
||||
const auth = document.getElementById('auth');
|
||||
const doc = document.implementation.createHTMLDocument('');
|
||||
doc.body.innerHTML = auth.innerText;
|
||||
|
||||
// Auth state is contained within the node.
|
||||
const { err, data } = JSON.parse(doc.body.textContent);
|
||||
if (err) {
|
||||
// TODO: send back the error message.
|
||||
console.error(err);
|
||||
// Auth state is contained within the node.
|
||||
const { err, data } = JSON.parse(doc.body.textContent);
|
||||
if (err) {
|
||||
const errDiv = document.createElement('div');
|
||||
if (err.message) {
|
||||
errDiv.innerText = `${err.name}: ${err.message}`;
|
||||
} else {
|
||||
// The data will contain a user and a token.
|
||||
const { user, token } = data;
|
||||
|
||||
// Send the state back.
|
||||
postMessage.post(HANDLE_SUCCESSFUL_LOGIN, { user, token });
|
||||
errDiv.innerText = JSON.stringify(err);
|
||||
}
|
||||
} finally {
|
||||
// Always close the window.
|
||||
setTimeout(() => {
|
||||
window.close();
|
||||
}, 50);
|
||||
document.body.appendChild(errDiv);
|
||||
throw err;
|
||||
}
|
||||
|
||||
// The data will contain a user and a token.
|
||||
const { user, token } = data;
|
||||
|
||||
// Send the state back.
|
||||
postMessage.post(HANDLE_SUCCESSFUL_LOGIN, { user, token });
|
||||
|
||||
// Close the window when all went well.
|
||||
setTimeout(() => {
|
||||
window.close();
|
||||
}, 50);
|
||||
});
|
||||
|
||||
@@ -745,10 +745,21 @@ export default class Comment extends React.Component {
|
||||
|
||||
const id = `c_${comment.id}`;
|
||||
|
||||
// props that are passed down the slots.
|
||||
const slotPassthrough = {
|
||||
action: 'deleted',
|
||||
comment,
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={rootClassName} id={id}>
|
||||
{isCommentDeleted(comment) ? (
|
||||
<CommentTombstone action="deleted" />
|
||||
<Slot
|
||||
fill="commentTombstone"
|
||||
defaultComponent={CommentTombstone}
|
||||
size={1}
|
||||
passthrough={slotPassthrough}
|
||||
/>
|
||||
) : (
|
||||
<div>
|
||||
{this.renderComment()}
|
||||
|
||||
@@ -39,6 +39,7 @@ class CommentTombstone extends React.Component {
|
||||
|
||||
CommentTombstone.propTypes = {
|
||||
action: PropTypes.string,
|
||||
comment: PropTypes.object,
|
||||
onUndo: PropTypes.func,
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import StreamError from './StreamError';
|
||||
import Comment from '../containers/Comment';
|
||||
import BannedAccount from '../../../components/BannedAccount';
|
||||
import ChangeUsername from '../containers/ChangeUsername';
|
||||
import Markdown from 'coral-framework/components/Markdown';
|
||||
import Slot from 'coral-framework/components/Slot';
|
||||
import InfoBox from './InfoBox';
|
||||
import { can } from 'coral-framework/services/perms';
|
||||
@@ -181,7 +182,9 @@ class Stream extends React.Component {
|
||||
setActiveReplyBox={setActiveReplyBox}
|
||||
activeReplyBox={activeReplyBox}
|
||||
notify={notify}
|
||||
disableReply={asset.isClosed}
|
||||
disableReply={
|
||||
asset.isClosed || asset.settings.disableCommenting
|
||||
}
|
||||
postComment={postComment}
|
||||
currentUser={currentUser}
|
||||
postFlag={postFlag}
|
||||
@@ -215,7 +218,7 @@ class Stream extends React.Component {
|
||||
currentUser,
|
||||
} = this.props;
|
||||
const { keepCommentBox } = this.state;
|
||||
const open = !asset.isClosed;
|
||||
const open = !(asset.isClosed || asset.settings.disableCommenting);
|
||||
|
||||
const banned = get(currentUser, 'status.banned.status');
|
||||
const suspensionUntil = get(currentUser, 'status.suspension.until');
|
||||
@@ -293,7 +296,13 @@ class Stream extends React.Component {
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<p>{asset.settings.closedMessage}</p>
|
||||
<div>
|
||||
{asset.isClosed ? (
|
||||
<p>{asset.settings.closedMessage}</p>
|
||||
) : (
|
||||
<Markdown content={asset.settings.disableCommentingMessage} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Slot fill="stream" passthrough={slotPassthrough} />
|
||||
|
||||
@@ -24,6 +24,7 @@ const slots = [
|
||||
'commentAuthorName',
|
||||
'commentAuthorTags',
|
||||
'commentTimestamp',
|
||||
'commentTombstone',
|
||||
'commentContent',
|
||||
];
|
||||
|
||||
|
||||
@@ -434,6 +434,8 @@ const fragments = {
|
||||
questionBoxIcon
|
||||
closedTimeout
|
||||
closedMessage
|
||||
disableCommenting
|
||||
disableCommentingMessage
|
||||
charCountEnable
|
||||
charCount
|
||||
requireEmailConfirmation
|
||||
|
||||
@@ -116,7 +116,7 @@ export const withRemoveTag = withMutation(
|
||||
asset_id: assetId,
|
||||
item_type: itemType,
|
||||
},
|
||||
o3timisticResponse: {
|
||||
optimisticResponse: {
|
||||
removeTag: {
|
||||
__typename: 'ModifyTagResponse',
|
||||
errors: null,
|
||||
|
||||
@@ -56,10 +56,10 @@ export function createPostMessage(origin, scope = 'client') {
|
||||
// Send the message.
|
||||
target.postMessage(msg, origin);
|
||||
},
|
||||
subscribe: (handler, target = window) => {
|
||||
subscribe(handler, target = window) {
|
||||
// If this handler is already attached to the target, detach it.
|
||||
if (has(listeners, [target, handler])) {
|
||||
this.unsubscribeFromMessages(handler, target);
|
||||
this.unsubscribe(handler, target);
|
||||
}
|
||||
|
||||
// Wrap the listener with a origin check.
|
||||
@@ -71,7 +71,7 @@ export function createPostMessage(origin, scope = 'client') {
|
||||
// Attach the listener to the target.
|
||||
target.addEventListener('message', listener);
|
||||
},
|
||||
unsubscribe: (handler, target = window) => {
|
||||
unsubscribe(handler, target = window) {
|
||||
if (!has(listeners, [target, handler])) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -273,3 +273,23 @@ export function translateError(error) {
|
||||
}
|
||||
return error.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* handlePopupAuth will optionally open a popup with the requested uri if the
|
||||
* window is not already a popup.
|
||||
*
|
||||
* @param {String} uri the url to open the window? to
|
||||
* @param {String} title the title of the new window? to open
|
||||
* @param {String} features the features to use when opening a window?
|
||||
*/
|
||||
export function handlePopupAuth(
|
||||
uri,
|
||||
title = 'Login', // TODO: translate
|
||||
features = 'menubar=0,resizable=0,width=500,height=550,top=200,left=500'
|
||||
) {
|
||||
if (window.opener) {
|
||||
window.location = uri;
|
||||
} else {
|
||||
window.open(uri, title, features);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ You won't have to use this to build plugins, but it's helpful to find where to e
|
||||
* `commentReactions`
|
||||
* `commentActions`
|
||||
* `commentInputArea`
|
||||
* `commentTombstone`
|
||||
|
||||
* `draftArea`
|
||||
* `streamSettings`
|
||||
|
||||
@@ -161,6 +161,24 @@ class ErrAssetCommentingClosed extends TalkError {
|
||||
}
|
||||
}
|
||||
|
||||
// ErrCommentingDisabled is returned when a comment or action is attempted while
|
||||
// commenting has been disabled site-wide.
|
||||
class ErrCommentingDisabled extends TalkError {
|
||||
constructor(message = null) {
|
||||
super(
|
||||
'asset commenting is closed',
|
||||
{
|
||||
status: 400,
|
||||
translation_key: 'COMMENTING_DISABLED',
|
||||
},
|
||||
{
|
||||
// Include the closedMessage in the metadata piece of the error.
|
||||
message,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ErrAuthentication is returned when there is an error authenticating and the
|
||||
* message is provided.
|
||||
@@ -387,6 +405,7 @@ module.exports = {
|
||||
ErrAuthentication,
|
||||
ErrCannotIgnoreStaff,
|
||||
ErrCommentTooShort,
|
||||
ErrCommentingDisabled,
|
||||
ErrContainsProfanity,
|
||||
ErrEditWindowHasEnded,
|
||||
ErrEmailAlreadyVerified,
|
||||
|
||||
@@ -837,6 +837,13 @@ type Settings {
|
||||
# closed.
|
||||
closedMessage: String
|
||||
|
||||
# disableCommenting will disable commenting site-wide.
|
||||
disableCommenting: Boolean
|
||||
|
||||
# disableCommentingMessage will be shown above the comment stream while
|
||||
# commenting is disabled site-wide.
|
||||
disableCommentingMessage: String
|
||||
|
||||
# editCommentWindowLength is the length of time (in milliseconds) after a
|
||||
# comment is posted that it can still be edited by the author.
|
||||
editCommentWindowLength: Int
|
||||
@@ -1300,6 +1307,13 @@ input UpdateSettingsInput {
|
||||
# closed.
|
||||
closedMessage: String
|
||||
|
||||
# disableCommenting will disable commenting site-wide.
|
||||
disableCommenting: Boolean
|
||||
|
||||
# disableCommentingMessage will be shown above the comment stream while
|
||||
# commenting is disabled site-wide.
|
||||
disableCommentingMessage: String
|
||||
|
||||
# charCountEnable is true when the character count restriction is enabled.
|
||||
charCountEnable: Boolean
|
||||
|
||||
|
||||
@@ -124,6 +124,8 @@ de:
|
||||
custom_css_url_desc: "URL eines CSS-Stylesheets zum Überschreiben des Standard-Designs"
|
||||
days: Tage
|
||||
description: "Ändern Sie die Einstellungen für den Kommentarbereich dieses Artikels."
|
||||
disable_commenting_title: "Kommentieren global deaktivieren"
|
||||
disable_commenting_desc: "Verfassen Sie eine Nachricht, die angezeigt wird, solange das Kommentieren deaktiviert ist."
|
||||
domain_list_text: "Geben Sie Domains an, für die diese Talk-Instanz freigegeben werden soll, z.B. für lokale Test- oder Produktionsumgebungen (Bsp.: localhost:3000 staging.domain.com domain.com)."
|
||||
domain_list_title: "Zugelassene Domains"
|
||||
edit_info: "Information bearbeiten"
|
||||
@@ -247,6 +249,7 @@ de:
|
||||
LOGIN_MAXIMUM_EXCEEDED: "Sie haben zu häufig erfolglos versucht, sich anzumelden. Bitte warten Sie."
|
||||
PASSWORD_REQUIRED: "Passwort ist erforderlich"
|
||||
COMMENTING_CLOSED: "Kommentarbereich ist bereits geschlossen"
|
||||
COMMENTING_DISABLED: "Die Kommentarfunktion ist derzeit abgeschaltet"
|
||||
NOT_FOUND: "Ressource nicht gefunden"
|
||||
ALREADY_EXISTS: "Ressource existiert bereits"
|
||||
INVALID_ASSET_URL: "Asset-URL ist ungültig"
|
||||
|
||||
@@ -124,6 +124,8 @@ en:
|
||||
custom_css_url_desc: "URL of a CSS stylesheet that will override default Embed Stream styles. Can be internal or external."
|
||||
days: Days
|
||||
description: "Change the comment settings on this story."
|
||||
disable_commenting_title: "Deactivate commenting site-wide"
|
||||
disable_commenting_desc: "Write a message that will be displayed while commenting is deactivated."
|
||||
domain_list_text: "Enter the domains you would like to permit for Talk e.g. your local staging and production environments (ex. localhost:3000 staging.domain.com domain.com)."
|
||||
domain_list_title: "Permitted Domains"
|
||||
edit_info: "Edit Info"
|
||||
@@ -247,6 +249,7 @@ en:
|
||||
LOGIN_MAXIMUM_EXCEEDED: "You have made too many unsuccessful password attempts. Please wait."
|
||||
PASSWORD_REQUIRED: "Must input a password"
|
||||
COMMENTING_CLOSED: "Commenting is already closed"
|
||||
COMMENTING_DISABLED: "Commenting is currently disabled on this site"
|
||||
NOT_FOUND: "Resource not found"
|
||||
ALREADY_EXISTS: "Resource already exists"
|
||||
INVALID_ASSET_URL: "Assert URL is invalid"
|
||||
|
||||
@@ -68,6 +68,14 @@ const Setting = new Schema(
|
||||
type: String,
|
||||
default: 'Expired',
|
||||
},
|
||||
disableCommenting: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disableCommentingMessage: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
wordlist: {
|
||||
banned: {
|
||||
type: Array,
|
||||
|
||||
@@ -339,6 +339,11 @@ User.virtual('banned')
|
||||
})
|
||||
.set(function(status) {
|
||||
this.status.banned.status = status;
|
||||
|
||||
if (!this.status.banned.history) {
|
||||
this.status.banned.history = [];
|
||||
}
|
||||
|
||||
this.status.banned.history.push({
|
||||
status,
|
||||
created_at: new Date(),
|
||||
@@ -357,6 +362,11 @@ User.virtual('suspended')
|
||||
})
|
||||
.set(function(until) {
|
||||
this.status.suspension.until = until;
|
||||
|
||||
if (!this.status.suspension.history) {
|
||||
this.status.suspension.history = [];
|
||||
}
|
||||
|
||||
this.status.suspension.history.push({
|
||||
until,
|
||||
created_at: new Date(),
|
||||
|
||||
+2
-2
@@ -149,7 +149,7 @@
|
||||
"metascraper-title": "^3.9.2",
|
||||
"minimist": "^1.2.0",
|
||||
"moment": "^2.18.1",
|
||||
"mongoose": "^4.12.3",
|
||||
"mongoose": "^5.1.1",
|
||||
"ms": "^2.0.0",
|
||||
"murmurhash-js": "^1.0.0",
|
||||
"name-all-modules-plugin": "^1.0.1",
|
||||
@@ -231,7 +231,7 @@
|
||||
"husky": "^0.14.3",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest-junit": "^3.6.0",
|
||||
"lint-staged": "^7.0.0",
|
||||
"lint-staged": "^7.1.0",
|
||||
"mocha": "^3.1.2",
|
||||
"mocha-junit-reporter": "^1.12.1",
|
||||
"nightwatch": "^0.9.16",
|
||||
|
||||
@@ -9,4 +9,5 @@ export {
|
||||
getDefinitionName,
|
||||
getShallowChanges,
|
||||
createDefaultResponseFragments,
|
||||
handlePopupAuth,
|
||||
} from 'coral-framework/utils';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { handlePopupAuth } from 'plugin-api/beta/client/utils';
|
||||
|
||||
export const loginWithFacebook = () => (dispatch, _, { rest }) => {
|
||||
window.location = `${rest.uri}/auth/facebook`;
|
||||
handlePopupAuth(`${rest.uri}/auth/facebook`);
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import translations from './translations.yml';
|
||||
export default {
|
||||
translations,
|
||||
slots: {
|
||||
authExternalAdminSignIn: [SignIn],
|
||||
authExternalSignIn: [SignIn],
|
||||
authExternalSignUp: [SignUp],
|
||||
},
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { handlePopupAuth } from 'plugin-api/beta/client/utils';
|
||||
|
||||
export const loginWithGoogle = () => (dispatch, _, { rest }) => {
|
||||
window.location = `${rest.uri}/auth/google`;
|
||||
handlePopupAuth(`${rest.uri}/auth/google`);
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import translations from './translations.yml';
|
||||
export default {
|
||||
translations,
|
||||
slots: {
|
||||
authExternalAdminSignIn: [SignIn],
|
||||
authExternalSignIn: [SignIn],
|
||||
authExternalSignUp: [SignUp],
|
||||
},
|
||||
|
||||
@@ -223,11 +223,21 @@ class Profile extends React.Component {
|
||||
disabled={!usernameCanBeUpdated}
|
||||
columnDisplay
|
||||
>
|
||||
<span className={styles.bottomText}>
|
||||
{t(
|
||||
'talk-plugin-local-auth.change_username.change_username_note'
|
||||
<div className={styles.bottomText}>
|
||||
<span>
|
||||
{t(
|
||||
'talk-plugin-local-auth.change_username.change_username_note'
|
||||
)}
|
||||
</span>
|
||||
{!usernameCanBeUpdated && (
|
||||
<b>
|
||||
{' '}
|
||||
{t(
|
||||
'talk-plugin-local-auth.change_username.is_not_eligible'
|
||||
)}
|
||||
</b>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</InputField>
|
||||
<InputField
|
||||
icon="email"
|
||||
|
||||
@@ -19,7 +19,8 @@ en:
|
||||
changed_password_msg: "Changed Password - Your password has been successfully changed"
|
||||
forgot_password_sent: "Forgot Password - We sent you an email to recover your password"
|
||||
change_username:
|
||||
change_username_note: "Usernames can only be changed once every 14 days. Your username is not currently eligible to be updated."
|
||||
change_username_note: "Usernames can only be changed once every 14 days."
|
||||
is_not_eligible: "You cannot currently change your username."
|
||||
save: "Save"
|
||||
edit_profile: "Edit Profile"
|
||||
cancel: "Cancel"
|
||||
@@ -151,7 +152,8 @@ es:
|
||||
changed_password_msg: "Contraseña Actualizada - Tu contraseña ha sido exitosamente actualizada"
|
||||
forgot_password_sent: "Contraseña Olvidada - Te enviamos un email para recuperar tu contraseña"
|
||||
change_username:
|
||||
change_username_note: "El usuario puede ser cambiado cada 14 días"
|
||||
change_username_note: "El usuario puede ser cambiado cada 14 días."
|
||||
is_not_eligible: "Ahora mismo no se puede cambiar su nombre de usuario."
|
||||
save: "Guardar"
|
||||
edit_profile: "Editar Perfil"
|
||||
cancel: "Cancelar"
|
||||
|
||||
@@ -63,17 +63,18 @@ class DeleteMyAccount extends React.Component {
|
||||
<p className="talk-plugin-auth--delete-my-account-description">
|
||||
{t('delete_request.delete_my_account_description')}
|
||||
</p>
|
||||
<p className="talk-plugin-auth--delete-my-account-description">
|
||||
{scheduledDeletionDate &&
|
||||
t(
|
||||
'delete_request.already_submitted_request_description',
|
||||
moment(scheduledDeletionDate).format('MMM Do YYYY, h:mm:ss a')
|
||||
)}
|
||||
</p>
|
||||
{scheduledDeletionDate ? (
|
||||
<Button onClick={this.cancelAccountDeletion}>
|
||||
{t('delete_request.cancel_account_deletion_request')}
|
||||
</Button>
|
||||
<div>
|
||||
<p className="talk-plugin-auth--delete-my-account-description">
|
||||
{t(
|
||||
'delete_request.already_submitted_request_description',
|
||||
moment(scheduledDeletionDate).format('MMM Do YYYY, h:mm:ss a')
|
||||
)}
|
||||
</p>
|
||||
<Button onClick={this.cancelAccountDeletion}>
|
||||
{t('delete_request.cancel_account_deletion_request')}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<Button icon="delete" onClick={this.showDialog}>
|
||||
{t('delete_request.delete_my_account')}
|
||||
|
||||
@@ -7,21 +7,17 @@ class Button extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
className,
|
||||
title,
|
||||
onClick,
|
||||
children,
|
||||
active,
|
||||
activeClassName,
|
||||
disabled,
|
||||
...rest
|
||||
} = this.props;
|
||||
return (
|
||||
<button
|
||||
className={cn(className, styles.button, {
|
||||
[cn(styles.active, activeClassName)]: active,
|
||||
})}
|
||||
title={title}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
@@ -32,11 +28,8 @@ class Button extends React.Component {
|
||||
Button.propTypes = {
|
||||
className: PropTypes.string,
|
||||
activeClassName: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
children: PropTypes.node,
|
||||
active: PropTypes.bool,
|
||||
disabled: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default Button;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Button from '../components/Button';
|
||||
import bowser from 'bowser';
|
||||
|
||||
/**
|
||||
* createToggle creates a button that can be active, inactive or disabled
|
||||
@@ -32,7 +33,17 @@ const createToggle = (
|
||||
this.execCommand();
|
||||
};
|
||||
|
||||
// Detect whether there was focus on the RTE before the click.
|
||||
hadFocusBeforeClick = false;
|
||||
handleMouseDown = () => (this.hadFocusBeforeClick = this.props.api.focused);
|
||||
|
||||
handleClick = () => {
|
||||
// Skip IOS when the focus was not there before.
|
||||
// IOS fails to focus to the RTE correctly and scrolls to nirvana.
|
||||
// See https://www.pivotaltracker.com/story/show/157607216
|
||||
if (!this.hadFocusBeforeClick && bowser.ios) {
|
||||
return;
|
||||
}
|
||||
this.props.api.focus();
|
||||
this.formatToggle();
|
||||
this.props.api.focus();
|
||||
@@ -62,6 +73,7 @@ const createToggle = (
|
||||
<Button
|
||||
className={className}
|
||||
title={title}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onClick={this.handleClick}
|
||||
active={this.state.active}
|
||||
disabled={disabled || this.state.disabled}
|
||||
|
||||
@@ -381,9 +381,13 @@ export function isBogusBR(node) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all nodes after `node`.
|
||||
* Returns an array of all nodes after `node` in a _line_.
|
||||
*/
|
||||
export function getRightOfNode(node) {
|
||||
if (node.tagName === 'BR') {
|
||||
return [];
|
||||
}
|
||||
|
||||
let result = [];
|
||||
let cur = node;
|
||||
while (
|
||||
@@ -515,10 +519,10 @@ export function outdentBlock(node, changeSelection) {
|
||||
|
||||
// A new lines to substitute the missing block element.
|
||||
const needLineAfter =
|
||||
node.nextSibling &&
|
||||
!isBlockElement(node.nextSibling) &&
|
||||
node.lastChild &&
|
||||
!isBlockElement(node.lastChild);
|
||||
!node.lastChild ||
|
||||
(node.nextSibling &&
|
||||
!isBlockElement(node.nextSibling) &&
|
||||
!isBlockElement(node.lastChild));
|
||||
const needLineBefore =
|
||||
node.previousSibling &&
|
||||
!isBlockElement(node.previousSibling) &&
|
||||
|
||||
+22
-27
@@ -2,7 +2,7 @@ const ActionModel = require('../models/action');
|
||||
const CommentModel = require('../models/comment');
|
||||
const UserModel = require('../models/user');
|
||||
const _ = require('lodash');
|
||||
const errors = require('../errors');
|
||||
const { ErrAlreadyExists } = require('../errors');
|
||||
|
||||
const incrActionCounts = async (action, value) => {
|
||||
const ACTION_TYPE = action.action_type.toLowerCase();
|
||||
@@ -41,35 +41,30 @@ const incrActionCounts = async (action, value) => {
|
||||
* @param {object} update the update operation for the mongo findOneAndUpdate op
|
||||
* @param {object} options the options operation for the mongo findOneAndUpdate op
|
||||
*/
|
||||
const findOnlyOneAndUpdate = async (query, update, options = {}) =>
|
||||
new Promise((resolve, reject) => {
|
||||
ActionModel.findOneAndUpdate(
|
||||
query,
|
||||
update,
|
||||
Object.assign({}, options, {
|
||||
// Use raw result to get `updatedExisting`.
|
||||
passRawResult: true,
|
||||
const findOnlyOneAndUpdate = async (query, update, options = {}) => {
|
||||
const raw = await ActionModel.findOneAndUpdate(
|
||||
query,
|
||||
update,
|
||||
Object.assign({}, options, {
|
||||
// Use raw result to get `updatedExisting`.
|
||||
rawResult: true,
|
||||
|
||||
// Ensure that if it's new, we return the new object created.
|
||||
new: true,
|
||||
// Ensure that if it's new, we return the new object created.
|
||||
new: true,
|
||||
|
||||
// Perform an upsert in the event that this doesn't exist.
|
||||
upsert: true,
|
||||
// Perform an upsert in the event that this doesn't exist.
|
||||
upsert: true,
|
||||
|
||||
// Set the default values if not provided based on the mongoose models.
|
||||
setDefaultsOnInsert: true,
|
||||
}),
|
||||
(err, doc, raw) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
if (raw.lastErrorObject.updatedExisting) {
|
||||
return reject(new errors.ErrAlreadyExists(raw.value));
|
||||
}
|
||||
return resolve(raw.value);
|
||||
}
|
||||
);
|
||||
});
|
||||
// Set the default values if not provided based on the mongoose models.
|
||||
setDefaultsOnInsert: true,
|
||||
})
|
||||
);
|
||||
if (raw.lastErrorObject.updatedExisting) {
|
||||
throw new ErrAlreadyExists(raw.value);
|
||||
}
|
||||
|
||||
return raw.value;
|
||||
};
|
||||
|
||||
module.exports = class ActionsService {
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ const {
|
||||
wordlist,
|
||||
commentLength,
|
||||
assetClosed,
|
||||
commentingDisabled,
|
||||
karma,
|
||||
staff,
|
||||
links,
|
||||
@@ -36,6 +37,7 @@ const applyStatus = status => () => ({ status });
|
||||
const phases = [
|
||||
commentLength,
|
||||
assetClosed,
|
||||
commentingDisabled,
|
||||
wordlist,
|
||||
staff,
|
||||
links,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
const { ErrCommentingDisabled } = require('../../../errors');
|
||||
|
||||
// This phase checks to see if commenting is site-wide disabled.
|
||||
module.exports = (ctx, comment, { asset }) => {
|
||||
// Check to see if the asset has closed commenting...
|
||||
if (asset.settings.disableCommenting) {
|
||||
throw new ErrCommentingDisabled(asset.settings.disableCommentingMessage);
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
module.exports.wordlist = require('./wordlist');
|
||||
module.exports.commentLength = require('./commentLength');
|
||||
module.exports.assetClosed = require('./assetClosed');
|
||||
module.exports.commentingDisabled = require('./commentingDisabled');
|
||||
module.exports.karma = require('./karma');
|
||||
module.exports.staff = require('./staff');
|
||||
module.exports.links = require('./links');
|
||||
|
||||
@@ -45,7 +45,6 @@ if (WEBPACK) {
|
||||
// Connect to the Mongo instance.
|
||||
mongoose
|
||||
.connect(MONGO_URL, {
|
||||
useMongoClient: true,
|
||||
config: {
|
||||
autoIndex: CREATE_MONGO_INDEXES,
|
||||
},
|
||||
|
||||
@@ -179,6 +179,54 @@ describe('graph.mutations.createComment', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('assets while commenting is disabled', () => {
|
||||
[
|
||||
{
|
||||
disabled: false,
|
||||
error: null,
|
||||
},
|
||||
{
|
||||
disabled: true,
|
||||
error: 'COMMENTING_DISABLED',
|
||||
},
|
||||
].forEach(({ disabled, error }) => {
|
||||
describe(`commentingDisabled=${disabled}`, () => {
|
||||
beforeEach(() =>
|
||||
AssetModel.create({
|
||||
id: '123',
|
||||
settings: { disableCommenting: disabled },
|
||||
})
|
||||
);
|
||||
|
||||
it(
|
||||
error ? 'does not create the comment' : 'creates the comment',
|
||||
() => {
|
||||
const context = new Context({ user: new UserModel({}) });
|
||||
|
||||
return graphql(schema, query, {}, context).then(
|
||||
({ data, errors }) => {
|
||||
expect(errors).to.be.undefined;
|
||||
if (error) {
|
||||
expect(data.createComment).to.have.property('comment').null;
|
||||
expect(data.createComment).to.have.property('errors').not
|
||||
.null;
|
||||
expect(data.createComment.errors[0]).to.have.property(
|
||||
'translation_key',
|
||||
error
|
||||
);
|
||||
} else {
|
||||
expect(data.createComment).to.have.property('comment').not
|
||||
.null;
|
||||
expect(data.createComment).to.have.property('errors').null;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('comments made with different asset moderation settings', () => {
|
||||
[
|
||||
{ moderation: 'PRE', status: 'PREMOD' },
|
||||
|
||||
@@ -1644,6 +1644,10 @@ bson@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/bson/-/bson-1.0.4.tgz#93c10d39eaa5b58415cbc4052f3e53e562b0b72c"
|
||||
|
||||
bson@~1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/bson/-/bson-1.0.6.tgz#444db59ddd4c24f0cb063aabdc5c8c7b0ceca912"
|
||||
|
||||
buffer-crc32@^0.2.1, buffer-crc32@~0.2.3:
|
||||
version "0.2.13"
|
||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||
@@ -1652,10 +1656,6 @@ buffer-equal-constant-time@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||
|
||||
buffer-shims@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
|
||||
|
||||
buffer-xor@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
|
||||
@@ -3353,10 +3353,6 @@ es6-map@^0.1.3:
|
||||
es6-symbol "~3.1.1"
|
||||
event-emitter "~0.3.5"
|
||||
|
||||
es6-promise@3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4"
|
||||
|
||||
es6-promise@^4.0.5:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.1.tgz#8811e90915d9a0dba36274f0b242dbda78f9c92a"
|
||||
@@ -4890,10 +4886,6 @@ home-or-tmp@^2.0.0:
|
||||
os-homedir "^1.0.0"
|
||||
os-tmpdir "^1.0.1"
|
||||
|
||||
hooks-fixed@2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hooks-fixed/-/hooks-fixed-2.0.2.tgz#20076daa07e77d8a6106883ce3f1722e051140b0"
|
||||
|
||||
hosted-git-info@^2.1.4:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
|
||||
@@ -6399,9 +6391,9 @@ jxLoader@*:
|
||||
promised-io "*"
|
||||
walker "1.x"
|
||||
|
||||
kareem@1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/kareem/-/kareem-1.5.0.tgz#e3e4101d9dcfde299769daf4b4db64d895d17448"
|
||||
kareem@2.0.7:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.0.7.tgz#8d260366a4df4236ceccec318fcf10c17c5beb22"
|
||||
|
||||
keymaster@^1.6.2:
|
||||
version "1.6.2"
|
||||
@@ -6528,9 +6520,9 @@ linkifyjs@^2.1.5:
|
||||
react ">=0.14.0"
|
||||
react-dom ">=0.14.0"
|
||||
|
||||
lint-staged@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-7.0.0.tgz#57926c63201e7bd38ca0576d74391efa699b4a9d"
|
||||
lint-staged@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-7.1.0.tgz#1514a5b71b8d9492ca0c3d2a44769cbcbc8bcc79"
|
||||
dependencies:
|
||||
app-root-path "^2.0.1"
|
||||
chalk "^2.3.1"
|
||||
@@ -6541,6 +6533,7 @@ lint-staged@^7.0.0:
|
||||
execa "^0.9.0"
|
||||
find-parent-dir "^0.3.0"
|
||||
is-glob "^4.0.0"
|
||||
is-windows "^1.0.2"
|
||||
jest-validate "^22.4.0"
|
||||
listr "^0.13.0"
|
||||
lodash "^4.17.5"
|
||||
@@ -6550,8 +6543,9 @@ lint-staged@^7.0.0:
|
||||
p-map "^1.1.1"
|
||||
path-is-inside "^1.0.2"
|
||||
pify "^3.0.0"
|
||||
please-upgrade-node "^3.0.1"
|
||||
staged-git-files "1.1.0"
|
||||
please-upgrade-node "^3.0.2"
|
||||
staged-git-files "1.1.1"
|
||||
string-argv "^0.0.2"
|
||||
stringify-object "^3.2.2"
|
||||
|
||||
listr-silent-renderer@^1.1.1:
|
||||
@@ -7451,36 +7445,36 @@ moment@^2.15.2:
|
||||
version "2.22.1"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.1.tgz#529a2e9bf973f259c9643d237fda84de3a26e8ad"
|
||||
|
||||
mongodb-core@2.1.17:
|
||||
version "2.1.17"
|
||||
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.17.tgz#a418b337a14a14990fb510b923dee6a813173df8"
|
||||
mongodb-core@3.0.8:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-3.0.8.tgz#8d401f4eab6056c0d874a3d5844a4844f761d4d7"
|
||||
dependencies:
|
||||
bson "~1.0.4"
|
||||
require_optional "~1.0.0"
|
||||
require_optional "^1.0.1"
|
||||
|
||||
mongodb@2.2.33:
|
||||
version "2.2.33"
|
||||
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.33.tgz#b537c471d34a6651b48f36fdbf29750340e08b50"
|
||||
mongodb@3.0.8:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.0.8.tgz#2c1daecac9a0ec2de2f2aea4dc97d76ae70f8951"
|
||||
dependencies:
|
||||
es6-promise "3.2.1"
|
||||
mongodb-core "2.1.17"
|
||||
readable-stream "2.2.7"
|
||||
mongodb-core "3.0.8"
|
||||
|
||||
mongoose@^4.12.3:
|
||||
version "4.13.7"
|
||||
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.13.7.tgz#f760c770e6c8cdf34a6fe8b7443882b5fced1032"
|
||||
mongoose-legacy-pluralize@1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4"
|
||||
|
||||
mongoose@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.1.1.tgz#a7e925607e76032e5ef20b3035a357bc8581b45e"
|
||||
dependencies:
|
||||
async "2.1.4"
|
||||
bson "~1.0.4"
|
||||
hooks-fixed "2.0.2"
|
||||
kareem "1.5.0"
|
||||
bson "~1.0.5"
|
||||
kareem "2.0.7"
|
||||
lodash.get "4.4.2"
|
||||
mongodb "2.2.33"
|
||||
mpath "0.3.0"
|
||||
mpromise "0.5.5"
|
||||
mquery "2.3.3"
|
||||
mongodb "3.0.8"
|
||||
mongoose-legacy-pluralize "1.0.2"
|
||||
mpath "0.4.1"
|
||||
mquery "3.0.0"
|
||||
ms "2.0.0"
|
||||
muri "1.3.0"
|
||||
regexp-clone "0.0.1"
|
||||
sliced "1.0.1"
|
||||
|
||||
@@ -7509,17 +7503,13 @@ move-concurrently@^1.0.1:
|
||||
rimraf "^2.5.4"
|
||||
run-queue "^1.0.3"
|
||||
|
||||
mpath@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.3.0.tgz#7a58f789e9b5fd3c94520634157960f26bd5ef44"
|
||||
mpath@0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.4.1.tgz#ed10388430380bf7bbb5be1391e5d6969cb08e89"
|
||||
|
||||
mpromise@0.5.5:
|
||||
version "0.5.5"
|
||||
resolved "https://registry.yarnpkg.com/mpromise/-/mpromise-0.5.5.tgz#f5b24259d763acc2257b0a0c8c6d866fd51732e6"
|
||||
|
||||
mquery@2.3.3:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/mquery/-/mquery-2.3.3.tgz#221412e5d4e7290ca5582dd16ea8f190a506b518"
|
||||
mquery@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mquery/-/mquery-3.0.0.tgz#e5f387dbabc0b9b69859e550e810faabe0ceabb0"
|
||||
dependencies:
|
||||
bluebird "3.5.0"
|
||||
debug "2.6.9"
|
||||
@@ -7538,10 +7528,6 @@ ms@^2.0.0, ms@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
||||
|
||||
muri@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/muri/-/muri-1.3.0.tgz#aeccf3db64c56aa7c5b34e00f95b7878527a4721"
|
||||
|
||||
murmurhash-js@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/murmurhash-js/-/murmurhash-js-1.0.0.tgz#b06278e21fc6c37fa5313732b0412bcb6ae15f51"
|
||||
@@ -8556,9 +8542,11 @@ platform@1.3.4:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.4.tgz#6f0fb17edaaa48f21442b3a975c063130f1c3ebd"
|
||||
|
||||
please-upgrade-node@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.0.1.tgz#0a681f2c18915e5433a5ca2cd94e0b8206a782db"
|
||||
please-upgrade-node@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.0.2.tgz#7b9eaeca35aa4a43d6ebdfd10616c042f9a83acc"
|
||||
dependencies:
|
||||
semver-compare "^1.0.0"
|
||||
|
||||
pluralize@^1.2.1:
|
||||
version "1.2.1"
|
||||
@@ -9717,18 +9705,6 @@ readable-stream@2, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stre
|
||||
string_decoder "~1.0.3"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@2.2.7:
|
||||
version "2.2.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1"
|
||||
dependencies:
|
||||
buffer-shims "~1.0.0"
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.1"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~1.0.6"
|
||||
string_decoder "~1.0.0"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readdirp@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
|
||||
@@ -10034,7 +10010,7 @@ require-uncached@^1.0.3:
|
||||
caller-path "^0.1.0"
|
||||
resolve-from "^1.0.0"
|
||||
|
||||
require_optional@~1.0.0:
|
||||
require_optional@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e"
|
||||
dependencies:
|
||||
@@ -10285,6 +10261,10 @@ selenium-standalone@^6.11.0:
|
||||
which "^1.2.12"
|
||||
yauzl "^2.5.0"
|
||||
|
||||
semver-compare@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||
|
||||
semver-diff@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
|
||||
@@ -10762,9 +10742,9 @@ stack-utils@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620"
|
||||
|
||||
staged-git-files@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.1.0.tgz#1a9bb131c1885601023c7aaddd3d54c22142c526"
|
||||
staged-git-files@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.1.1.tgz#37c2218ef0d6d26178b1310719309a16a59f8f7b"
|
||||
|
||||
static-extend@^0.1.1:
|
||||
version "0.1.2"
|
||||
@@ -10841,6 +10821,10 @@ strict-uri-encode@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
|
||||
|
||||
string-argv@^0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.0.2.tgz#dac30408690c21f3c3630a3ff3a05877bdcbd736"
|
||||
|
||||
string-hash@^1.1.0:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
|
||||
@@ -10875,7 +10859,7 @@ string.prototype.padend@^3.0.0:
|
||||
es-abstract "^1.4.3"
|
||||
function-bind "^1.0.2"
|
||||
|
||||
string_decoder@^1.0.0, string_decoder@~1.0.0, string_decoder@~1.0.3:
|
||||
string_decoder@^1.0.0, string_decoder@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user