From d4a052a2ee8297fb0c03656c396211116b64f14b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Sat, 21 Jul 2018 00:21:14 +0200 Subject: [PATCH 001/124] [WIP] Add thread creation to home screen --- .meteor/packages | 2 + .meteor/versions | 1 + package-lock.json | 2 +- .../views/creationDialog/CreateThread.html | 54 +++ .../views/creationDialog/CreateThread.js | 389 ++++++++++++++++++ .../CreateThreadAutocomplete.html | 5 + .../CreateThreadInputError.html | 8 + packages/assistify-threading/config.js | 9 + packages/assistify-threading/package.js | 49 +++ .../server/methods/createThread.js | 142 +++++++ .../rocketchat-ui/client/views/app/home.html | 3 + .../rocketchat-ui/client/views/app/home.js | 3 + 12 files changed, 666 insertions(+), 1 deletion(-) create mode 100644 packages/assistify-threading/client/views/creationDialog/CreateThread.html create mode 100755 packages/assistify-threading/client/views/creationDialog/CreateThread.js create mode 100644 packages/assistify-threading/client/views/creationDialog/CreateThreadAutocomplete.html create mode 100644 packages/assistify-threading/client/views/creationDialog/CreateThreadInputError.html create mode 100644 packages/assistify-threading/config.js create mode 100644 packages/assistify-threading/package.js create mode 100644 packages/assistify-threading/server/methods/createThread.js diff --git a/.meteor/packages b/.meteor/packages index bbe5d3bd8b7b0..4a833faca47e3 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -194,3 +194,5 @@ chatpal:search rocketchat:lazy-load tap:i18n underscore + +assistify:threading diff --git a/.meteor/versions b/.meteor/versions index a9bb91cf018ea..1f4fb2c280fbe 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -8,6 +8,7 @@ accounts-password@1.5.1 accounts-twitter@1.4.1 aldeed:simple-schema@1.5.4 allow-deny@1.1.0 +assistify:threading@0.1.0 autoupdate@1.4.0 babel-compiler@7.0.9 babel-runtime@1.2.2 diff --git a/package-lock.json b/package-lock.json index bcecc3b632dcb..bec203b3a51d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3364,7 +3364,7 @@ }, "compression": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/compression/-/compression-1.5.2.tgz", "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", "requires": { "accepts": "1.2.13", diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.html b/packages/assistify-threading/client/views/creationDialog/CreateThread.html new file mode 100644 index 0000000000000..67bf1a78142cd --- /dev/null +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.html @@ -0,0 +1,54 @@ + diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.js b/packages/assistify-threading/client/views/creationDialog/CreateThread.js new file mode 100755 index 0000000000000..d387d5062e0d9 --- /dev/null +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.js @@ -0,0 +1,389 @@ +/* globals TAPi18n, AutoComplete */ +/* globals _ */ +import {RocketChat} from 'meteor/rocketchat:lib'; +import {FlowRouter} from 'meteor/kadira:flow-router'; +import {ReactiveVar} from 'meteor/reactive-var'; + +const acEvents = { + 'click .rc-popup-list__item'(e, t) { + t.ac.onItemClick(this, e); + t.debounceValidateExpertise(this.item.name); + }, + 'click .rc-input__icon-svg--book-alt'(e, t) { + e.preventDefault(); + t.channelSelectionEnabled.set(true); + }, + 'click #more-topics'(e, t) { + e.preventDefault(); + t.channelSelectionEnabled.set(true); + }, + 'keydown [name="expertise"]'(e, t) { + t.ac.onKeyDown(e); + }, + 'keyup [name="expertise"]'(e, t) { + t.ac.onKeyUp(e); + }, + 'focus [name="expertise"]'(e, t) { + if (t.expertise.get() === '' && t.showDropDown.get() === '') { + t.showDropDown.set('isShowing'); + } + t.ac.onFocus(e); + }, + 'blur [name="expertise"]'(e, t) { + t.ac.onBlur(e); + t.debounceValidateExpertise(e.target.value); + t.debounceDropDown(); + } +}; + + +Template.CreateThread.helpers({ + autocomplete(key) { + const instance = Template.instance(); + const param = instance.ac[key]; + if (!Template.instance().expertise.get() && Template.instance().showDropDown.get() === 'isShowing') { + return true; // show the expertise auto complete drop down + } + return typeof param === 'function' ? param.apply(instance.ac) : param; + }, + items() { + const instance = Template.instance(); + if (instance.expertise.get() === '') { + if (instance.expertisesList.get() && instance.expertisesList.get().length <= 10) { + return instance.expertisesList.get(); + } + // instance.showDropDown.set(''); + } + return instance.ac.filteredList(); + }, + config() { + const filter = Template.instance().expertise; + return { + filter: filter.get(), + template_item: 'CreateThreadAutocomplete', + noMatchTemplate: 'AssistifyTopicSearchEmpty', + modifier(text) { + const f = filter.get(); + return `#${ f.length === 0 ? text : text.replace(new RegExp(filter.get()), function(part) { + return `${ part }`; + }) }`; + } + }; + }, + manuallySelectParent() { + return false; // TODO: Add logic to overwrite proposed parent Room + }, + createIsDisabled() { + const instance = Template.instance(); + if (instance.validExpertise.get() && !instance.titleError.get()) { + return ''; + } else { + return 'disabled'; + } + }, + parentChannelError() { + const instance = Template.instance(); + return instance.parentChannelError.get(); + }, + expertise() { + const instance = Template.instance(); + return instance.expertise.get(); + }, + titleError() { + const instance = Template.instance(); + return instance.titleError.get(); + }, + channelSelectionEnabled() { + const instance = Template.instance(); + return instance.channelSelectionEnabled.get(); + }, + getWordcloudProperties() { + const instance = Template.instance(); + const expertises = instance.expertisesList.get(); + + function getRandomArbitrary(min, max) { + return Math.random() * (max - min) + min; + } + + function getWordList() { + const list = []; + expertises.forEach(function(expertise) { + list.push([expertise.name, getRandomArbitrary(4, 10)]); + }); + return list; + } + + function setExpertise() { + return function(selectedExpertise) { + const expertise = expertises.find(expertise => expertise.name === selectedExpertise[0]); + if (expertise) { + instance.debounceWordCloudSelect(expertise); + } + instance.channelSelectionEnabled.set(''); //Search completed. + }; + } + + function onWordHover() { + return function(item) { + // To Do + return item; + + }; + } + + function setFlatness() { + return 0.5; + } + + return { + clearCanvas: true, + weightFactor: 8, + fontWeight: 'normal', + gridSize: 55, + shape: 'square', + rotateRatio: 0, + rotationSteps: 0, + drawOutOfBound: true, + shuffle: true, + ellipticity: setFlatness(), + list: getWordList(), + click: setExpertise(), + hover: onWordHover() + //setCanvas: getCanvas + }; + } + +}); + +Template.CreateThread.events({ + ...acEvents, + 'input #expertise-search'(e, t) { + const input = e.target; + const position = input.selectionEnd || input.selectionStart; + const length = input.value.length; + document.activeElement === input && e && /input/i.test(e.type) && (input.selectionEnd = position + input.value.length - length);t.expertise.set(input.value); + t.validExpertise.set(false); + t.parentChannelError.set(''); + }, + 'input #request_title'(e, t) { + const input = e.target; + t.requestTitle.set(input.value); + if (!input.value) { + t.titleError.set(''); + } else { + t.debounceValidateRequestName(input.value); + } + }, + 'input #first_question'(e, t) { + const input = e.target; + if (input.value) { + t.openingQuestion.set(input.value); + } else { + t.openingQuestion.set(''); + } + }, + 'submit create-channel__content, click .js-save-thread'(event, instance) { + event.preventDefault(); + const expertise = instance.expertise.get(); + const requestTitle = instance.requestTitle.get(); + const openingQuestion = instance.openingQuestion.get(); + if (expertise) { + instance.titleError.set(null); + Meteor.call('createRequestFromExpertise', requestTitle, expertise, openingQuestion, (err, result) => { + if (err) { + console.log(err); + switch (err.error) { + case 'error-invalid-name': + instance.titleError.set(TAPi18n.__('Invalid_room_name', `${ expertise }...`)); + return; + case 'error-duplicate-channel-name': + instance.titleError.set(TAPi18n.__('Request_already_exists')); + return; + case 'error-archived-duplicate-name': + instance.titleError.set(TAPi18n.__('Duplicate_archived_channel_name', name)); + return; + case 'error-invalid-room-name': + console.log('room name slug error'); + // toastr.error(TAPi18n.__('Duplicate_archived_channel_name', name)); + instance.titleError.set(TAPi18n.__('Invalid_room_name', err.details.channel_name)); + return; + default: + return handleError(err); + } + } + // toastr.success(TAPi18n.__('New_request_created')); + const roomCreated = RocketChat.models.Rooms.findOne({_id: result.rid}); + FlowRouter.go('request', {name: roomCreated.name}, FlowRouter.current().queryParams); + }); + } + } +}); + +Template.CreateThread.onRendered(function() { + const instance = this; + const expertiseElement = this.find('#expertise-search'); + const titleElement = this.find('#request_title'); + const questionElement = this.find('#first_question'); + + instance.ac.element = expertiseElement; + instance.ac.$element = $(instance.ac.element); + instance.ac.$element.on('autocompleteselect', function(e, {item}) { + instance.expertise.set(item.name); + $('input[name="expertise"]').val(item.name); + instance.debounceValidateExpertise(item.name); + return instance.find('.js-save-thread').focus(); + }); + if (instance.requestTitle.get()) { + titleElement.value = instance.requestTitle.get(); + } + + if (instance.openingQuestion.get()) { + questionElement.value = instance.openingQuestion.get(); + } + + // strategy for setting the focus (yac!) + if (!expertiseElement.value) { + Meteor.setTimeout(()=>{ + expertiseElement.focus(); + }, 1500); + } else if (!questionElement.value) { + questionElement.focus(); + } else if (!titleElement.value) { + titleElement.focus(); + } else { + questionElement.focus(); + } + this.autorun(() => { + instance.debounceWordCloudSelect = _.debounce((expertise) => { + /* + * Update the expertise html reference to autocomplete + */ + instance.ac.element = this.find('#expertise-search'); + instance.ac.$element = $(instance.ac.element); + $('input[name="expertise"]').val(expertise.name); // copy the selected value to screen field + instance.ac.$element.on('autocompleteselect', function(e, {item}) { + instance.expertise.set(item.name); + $('input[name="expertise"]').val(item.name); + instance.debounceValidateExpertise(item.name); + + return instance.find('.js-save-thread').focus(); + }); + instance.expertise.set(expertise.name); + instance.debounceValidateExpertise(expertise.name); // invoke validation*/ + }, 200); + }); +}); + +Template.CreateThread.onCreated(function() { + const instance = this; + instance.expertise = new ReactiveVar(''); //the value of the text field + instance.validExpertise = new ReactiveVar(false); + instance.parentChannelError = new ReactiveVar(null); + instance.titleError = new ReactiveVar(null); + instance.requestTitle = new ReactiveVar(''); + instance.openingQuestion = new ReactiveVar(''); + instance.channelSelectionEnabled = new ReactiveVar(''); + instance.showDropDown = new ReactiveVar(''); + instance.expertisesList = new ReactiveVar(''); + instance.debounceDropDown = _.debounce(() => { + instance.showDropDown.set(''); + }, 200); + + instance.debounceValidateExpertise = _.debounce((expertise) => { + if (!expertise) { + return false; //expertise is mandatory + } + return Meteor.call('assistify:isValidExpertise', expertise, (error, result) => { + if (error) { + instance.validExpertise.set(false); + } else { + instance.validExpertise.set(result); + if (!result) { + instance.parentChannelError.set('Expertise_does_not_exist'); + } else { + instance.parentChannelError.set(''); + } + } + }); + }, 500); + + instance.debounceValidateRequestName = _.debounce((name) => { + instance.titleError.set(''); + if (!name) { + return; //"none" is a valid name + } + if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) { + Meteor.call('roomDisplayNameExists', name, (error, result) => { + if (error) { + return; + } + if (result) { + instance.titleError.set('Request_already_exists'); + } + }); + } else { + const reg = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`); + const passesRegex = name.length === 0 || reg.test(name); + if (!passesRegex) { + instance.titleError.set('Request_no_special_char'); + } else { + Meteor.call('roomNameExists', name, (error, result) => { + if (error) { + return; + } + if (result) { + instance.titleError.set('Request_already_exists'); + } + }); + } + } + }, 500); + this.ac = new AutoComplete({ + selector: { + item: '.rc-popup-list__item', + container: '.rc-popup-list__list' + }, + limit: 10, + inputDelay: 300, + rules: [ + { + // @TODO maybe change this 'collection' and/or template + collection: 'expertiseSearch', + subscription: 'autocompleteExpertise', // TODO: Provide another subscription exposing `c` and `p` + field: 'name', + matchAll: true, + doNotChangeWidth: false, + selector(match) { + return {term: match}; + }, + sort: 'name' + } + ] + + }); + this.ac.tmplInst = this; + + //pre-fill form based on query parameters if passed + if (FlowRouter.current().queryParams) { + const expertise = FlowRouter.getQueryParam('topic') || FlowRouter.getQueryParam('expertise'); + if (expertise) { + instance.expertise.set(expertise); + instance.debounceValidateExpertise(expertise); + } + + const title = FlowRouter.getQueryParam('title'); + if (title) { + instance.requestTitle.set(title); + } + + const question = FlowRouter.getQueryParam('question'); + if (question) { + instance.openingQuestion.set(question); + } + } + Meteor.call('expertiseList', {sort: 'name'}, function(err, result) { + if (result) { + instance.expertisesList.set(result.channels); + } + }); +}); diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThreadAutocomplete.html b/packages/assistify-threading/client/views/creationDialog/CreateThreadAutocomplete.html new file mode 100644 index 0000000000000..585dff310d1c0 --- /dev/null +++ b/packages/assistify-threading/client/views/creationDialog/CreateThreadAutocomplete.html @@ -0,0 +1,5 @@ + diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThreadInputError.html b/packages/assistify-threading/client/views/creationDialog/CreateThreadInputError.html new file mode 100644 index 0000000000000..f29f7a3f65f53 --- /dev/null +++ b/packages/assistify-threading/client/views/creationDialog/CreateThreadInputError.html @@ -0,0 +1,8 @@ + diff --git a/packages/assistify-threading/config.js b/packages/assistify-threading/config.js new file mode 100644 index 0000000000000..d63e88e76191e --- /dev/null +++ b/packages/assistify-threading/config.js @@ -0,0 +1,9 @@ +Meteor.startup(() => { + RocketChat.settings.add('Thread_Count', 1, { + group: 'General', + i18nLabel: 'Thread_count', + type: 'int', + public: true, + section: 'General' + }); +}); diff --git a/packages/assistify-threading/package.js b/packages/assistify-threading/package.js new file mode 100644 index 0000000000000..cb5f1cfdb06a0 --- /dev/null +++ b/packages/assistify-threading/package.js @@ -0,0 +1,49 @@ +Package.describe({ + name: 'assistify:threading', + version: '0.1.0', + summary: 'Adds heavy-weight threading to Rocket.Chat', + git: 'http://github.com/assistify/Rocket.Chat', + // By default, Meteor will default to using README.md for documentation. + // To avoid submitting documentation, set this field to null. + documentation: 'README.md' +}); + +Package.onUse(function(api) { + api.versionsFrom('1.2.1'); + api.use(['ecmascript']); + api.use('rocketchat:authorization'); //In order to create custom permissions + api.use('templating', 'client'); + // api.use('meteorhacks:inject-initial'); //for provisioning of svg-icons + + api.addFiles('config.js', 'server'); + // api.addFiles('lib/messageTypes/threadMessage.js'); // TODO: Decide what to do with the rendered message types. They are less usable on mobile,but provide good experience on browser. + + // Libraries + // api.addFiles('server/inject.js', 'server'); + + //Methods + api.addFiles('server/methods/createThread.js', 'server'); + // api.addFiles('server/methods/requestsList.js', 'server'); + // api.addFiles('server/methods/isValidExpertise.js', 'server'); + // api.addFiles('server/methods/expertiseList.js', 'server'); + + // we have all migrations in one single file + // api.addFiles('server/migrations.js', 'server'); + + // UI artifacts which are pre-processed or packaged by the server + // api.addAssets('client/public/icons.svg', 'server'); + + ///////// Client + + //Templates + api.addFiles('client/views/creationDialog/CreateThread.html', 'client'); + api.addFiles('client/views/creationDialog/CreateThread.js', 'client'); + api.addFiles('client/views/creationDialog/CreateThreadInputError.html', 'client'); + // api.addFiles('client/views/creationDialog/AssistifyWordCloud.html', 'client'); // TODO: add wordcloud - but when doing this, ensure the sizes are based on the member-count (non-linear!) + // api.addFiles('client/views/creationDialog/AssistifyWordCloud.js', 'client'); + api.addFiles('client/views/creationDialog/CreateThreadAutocomplete.html', 'client'); + // api.addFiles('client/views/creationDialog/AssistifyTopicSearchEmpty.html', 'client'); + // api.addFiles('client/views/creationDialog/AssistifyTopicSearchEmpty.js', 'client'); + // api.addFiles('client/views/messageActions/ThreadMessageAction.js', 'client'); // TODO: Re-add + +}); diff --git a/packages/assistify-threading/server/methods/createThread.js b/packages/assistify-threading/server/methods/createThread.js new file mode 100644 index 0000000000000..eb484ae60c188 --- /dev/null +++ b/packages/assistify-threading/server/methods/createThread.js @@ -0,0 +1,142 @@ +/* globals RocketChat */ +import { RocketChat } from 'meteor/rocketchat:lib'; +import { FlowRouter } from 'meteor/kadira:flow-router'; + +/* + * When a message is eligible to be answered as a independent question then it can be threaded into a new channel. + * When threading, the question is re-posted into a new room. To leave origin traces between the messages we update + * the original message with system message to allow user to navigate to the message created in the new Room and vice verse. + */ +export class ThreadBuilder { + constructor(parentRoomId, openingQuestion) { + this._openingQuestion = openingQuestion; + this._parentRoomId = parentRoomId; + } + + static getNextId() { + const settingsRaw = RocketChat.models.Settings.model.rawCollection(); + const findAndModify = Meteor.wrapAsync(settingsRaw.findAndModify, settingsRaw); + + const query = { + _id: 'Thread_Count' + }; + const update = { + $inc: { + value: 1 + } + }; + const findAndModifyResult = findAndModify(query, null, update); + return findAndModifyResult.value.value; + } + + static getRoom(roomId) { + return RocketChat.models.Rooms.findOne(roomId); + } + + _postMessage(room, user, message, attachments) { + attachments = attachments || []; + + //sendMessage expects the attachments timestamp to be a string, => serialize it + attachments.forEach(attachment => + attachment.ts = attachment.ts ? attachment.ts.toISOString() : '' + ); + const newMessage = { _id: Random.id(), rid: room.rid, msg: message, attachments }; + return RocketChat.sendMessage(user, newMessage, room); + } + + _getMessageUrl(msgId) { + return FlowRouter.path('message', { id: msgId }); + } + + _linkMessages(roomCreated, parentRoom) { + const rocketCatUser = RocketChat.models.Users.findOneByUsername('rocket.cat'); + if (rocketCatUser && Meteor.userId()) { + /** + * Parent Room + */ + RocketChat.models.Messages.updateMsgWithThreadMessage( + Meteor.user().username === this._openingQuestion.u.username ? 'thread-started-message-self' : 'thread-started-message', + this._openingQuestion._id, + '', + Meteor.user(), + { + mentions: [ + { + _id: Meteor.user()._id, // Thread Initiator + name: Meteor.user().username + }] + } + ); + + // The follwing lines would have the attachment remain at the original message. + // if (this._openingQuestion.attachments) { + // RocketChat.models.Messages.addMessageAttachments(this._openingQuestion._id, this._openingQuestion.attachments); + // } + + /* + * Child Room + */ + RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser('thread-welcome-message', roomCreated._id, this._getMessageUrl(this._openingQuestion._id), rocketCatUser, + { + mentions: [{ + _id: Meteor.user()._id, // Thread Initiator + name: Meteor.user().username // Use @Name field for navigation + }], + channels: [{ + _id: parentRoom._id // Parent Room ID + }] + }); + // Re-post message in the new room + const msgAuthor = RocketChat.models.Users.findOneByUsername(this._openingQuestion.u.username); // Search with the technical username + const msgRePosted = this._postMessage( + roomCreated, + msgAuthor, + this._openingQuestion.msg, + this._openingQuestion.attachments ? this._openingQuestion.attachments.filter(attachment => attachment.type && attachment.type === 'file') : [] + ); + + if (msgRePosted) { + /* Add a reference to the original message which can be rendered for navigation */ + RocketChat.models.Messages.setMessageAttachments(this._openingQuestion._id, [{ + author_name: this._openingQuestion.u.username || this._openingQuestion.u.name, + author_icon: `/avatar/${ this._openingQuestion.u.username }?_dc=0`, + ts: this._openingQuestion.ts, + fields: [{ + type: 'threadReference', + value: this._openingQuestion.msg, + threadUrl: this._getMessageUrl(msgRePosted._id) + }] + }]); + } + } + } + + create() { + const parentRoom = ThreadBuilder.getRoom(this._parentRoomId); + // Generate RoomName for the new room to be created. + this.name = `${ parentRoom.name }-${ ThreadBuilder.getNextId() }`; + const roomCreateResult = RocketChat.createRoom(parentRoom.t, this.name, Meteor.user() && Meteor.user().username, parentRoom.usernames, false, { parentRoomId: this._parentRoomId }); + + if (parentRoom.name) { + RocketChat.saveRoomTopic(roomCreateResult.rid, parentRoom.name, Meteor.user()); + } + + // Create messages in the newly created thread and it's parent which link the two rooms + const room = RocketChat.models.Rooms.findOneById(roomCreateResult.rid); + if (room && parentRoom) { + this._linkMessages(room, parentRoom); + } + + return roomCreateResult; + } +} + +Meteor.methods({ + ThreadCreation(parentRoomId, openingQuestion) { + if (!Meteor.userId()) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'ThreadCreation' }); + } + + return new ThreadBuilder(parentRoomId, openingQuestion).create(); + } +}); diff --git a/packages/rocketchat-ui/client/views/app/home.html b/packages/rocketchat-ui/client/views/app/home.html index dfcf2fea12430..89c38c9074cdc 100644 --- a/packages/rocketchat-ui/client/views/app/home.html +++ b/packages/rocketchat-ui/client/views/app/home.html @@ -1,6 +1,9 @@ \ No newline at end of file diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.js b/packages/assistify-threading/client/views/creationDialog/CreateThread.js index 797b515ac269d..4581fb7e1adbf 100755 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.js +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.js @@ -1,6 +1,5 @@ /* globals TAPi18n, AutoComplete */ /* globals _ */ -import { RocketChat } from 'meteor/rocketchat:lib'; import { FlowRouter } from 'meteor/kadira:flow-router'; import { ReactiveVar } from 'meteor/reactive-var'; @@ -15,7 +14,7 @@ const acEvents = { }, 'click #more-topics'(e, t) { e.preventDefault(); - t.channelSelectionEnabled.set(true); + t.showChannelSelection.set(true); }, 'keydown [name="parentChannel"]'(e, t) { t.ac.onKeyDown(e); @@ -61,7 +60,7 @@ Template.CreateThread.helpers({ return { filter: filter.get(), template_item: 'CreateThreadAutocomplete', - noMatchTemplate: 'AssistifyTopicSearchEmpty', + noMatchTemplate: 'ChannelNotFound', modifier(text) { const f = filter.get(); return `#${ f.length === 0 ? text : text.replace(new RegExp(filter.get()), function(part) { @@ -70,7 +69,7 @@ Template.CreateThread.helpers({ } }; }, - manuallySelectParent() { + selectParent() { return Template.instance().selectParent.get(); }, targetChannelText() { @@ -79,7 +78,7 @@ Template.CreateThread.helpers({ }, createIsDisabled() { const instance = Template.instance(); - if (instance.openingQuestion.get() && instance.parentChannelId.get() && !instance.error.get()) { + if (instance.openingQuestion.get() && instance.parentChannel.get() && !instance.error.get()) { return ''; } else { return 'disabled'; @@ -97,9 +96,9 @@ Template.CreateThread.helpers({ const instance = Template.instance(); return instance.error.get(); }, - channelSelectionEnabled() { + showChannelSelection() { const instance = Template.instance(); - return instance.channelSelectionEnabled.get(); + return instance.showChannelSelection.get(); }, getWordcloudProperties() { const instance = Template.instance(); @@ -156,7 +155,6 @@ Template.CreateThread.helpers({ //setCanvas: getCanvas }; } - }); Template.CreateThread.events({ @@ -168,7 +166,8 @@ Template.CreateThread.events({ const input = e.target; const position = input.selectionEnd || input.selectionStart; const length = input.value.length; - document.activeElement === input && e && /input/i.test(e.type) && (input.selectionEnd = position + input.value.length - length); t.parentChannel.set(input.value); + document.activeElement === input && e && /input/i.test(e.type) && (input.selectionEnd = position + input.value.length - length); + t.parentChannel.set(input.value); t.parentChannelId.set(''); t.parentChannelError.set(''); }, @@ -187,7 +186,9 @@ Template.CreateThread.events({ const openingQuestion = instance.openingQuestion.get(); if (parentChannelId) { instance.error.set(null); - Meteor.call('createThread', parentChannelId, {msg: openingQuestion}, (err, result) => { + Meteor.call('createThread', parentChannelId, { + msg: openingQuestion + }, (err, result) => { if (err) { console.log(err); switch (err.error) { @@ -256,15 +257,15 @@ Template.CreateThread.onRendered(function() { Template.CreateThread.onCreated(function() { const instance = this; - instance.parentChannel = new ReactiveVar('general'); // TODO: determine parent Channel from setting and allow to oeverwerite - instance.selectParent = new ReactiveVar(false); + instance.parentChannel = new ReactiveVar(RocketChat.settings.get('Parent_Channel')); // TODO: determine parent Channel from setting and allow to overwrite instance.parentChannelId = new ReactiveVar(''); instance.parentChannelError = new ReactiveVar(null); + instance.selectParent = new ReactiveVar(RocketChat.settings.get('Select_Parent')); + instance.parentChannelsList = new ReactiveVar(''); instance.error = new ReactiveVar(null); instance.openingQuestion = new ReactiveVar(''); - instance.channelSelectionEnabled = new ReactiveVar(''); instance.showDropDown = new ReactiveVar(''); - instance.parentChannelsList = new ReactiveVar(''); + instance.showChannelSelection = new ReactiveVar(false); instance.debounceDropDown = _.debounce(() => { instance.showDropDown.set(''); }, 200); @@ -274,15 +275,12 @@ Template.CreateThread.onCreated(function() { return false; //parentChannel is mandatory } return Meteor.call('assistify:getParentChannelId', parentChannel, (error, result) => { - if (error) { + if (!result) { instance.parentChannelId.set(false); + instance.parentChannelError.set('Parent_channel_doesnt_exist'); } else { - instance.parentChannelId.set(result); - if (!result) { - instance.error.set('parentChannel_does_not_exist'); - } else { - instance.error.set(''); - } + instance.parentChannelError.set(''); + instance.parentChannelId.set(result); //assign parent channel Id } }); }, 500); @@ -297,20 +295,19 @@ Template.CreateThread.onCreated(function() { }, limit: 10, inputDelay: 300, - rules: [ - { - collection: 'parentChannelSearch', // TODO: check for proper collection - subscription: 'autocompleteparentChannel', // TODO: Provide another subscription exposing `c` and `p` - field: 'name', - matchAll: true, - doNotChangeWidth: false, - selector(match) { - return { term: match }; - }, - sort: 'name' - } - ] - + rules: [{ + collection: 'CachedChannelList', // TODO: check for proper collection + subscription: 'channelAndPrivateAutocomplete', // TODO: Provide another subscription exposing `c` and `p` + field: 'name', + matchAll: true, + doNotChangeWidth: false, + selector(match) { + return { + name: match + }; + }, + sort: 'name' + }] }); this.ac.tmplInst = this; @@ -328,9 +325,11 @@ Template.CreateThread.onCreated(function() { // } // } - // Meteor.call('parentChannelList', { sort: 'name' }, function(err, result) { // TODO: Provide analogous methods - // if (result) { - // instance.parentChannelsList.set(result.channels); - // } - // }); + Meteor.call('getParentChannelList', { + sort: 'name' + }, function(err, result) { // TODO: Provide analogous methods + if (result) { + instance.parentChannelsList.set(result.channels); + } + }); }); diff --git a/packages/assistify-threading/config.js b/packages/assistify-threading/config.js index d63e88e76191e..0da4f7d04d682 100644 --- a/packages/assistify-threading/config.js +++ b/packages/assistify-threading/config.js @@ -6,4 +6,23 @@ Meteor.startup(() => { public: true, section: 'General' }); + RocketChat.settings.add('Select_Parent', false, { + group: 'General', + i18nLabel: 'Select_Parent', + type: 'boolean', + public: true, + section: 'General' + }); + RocketChat.settings.add('Parent_Channel', 'general', { + group: 'General', + i18nLabel: 'Parent_Channel', + type: 'select', + values: [{ + key: 'general', + i18nLabel: 'General' + }], + public: true, + section: 'General', + enableQuery: { _id: 'Select_Parent', value : false } + }); }); diff --git a/packages/assistify-threading/lib/messageTypes/threadMessage.js b/packages/assistify-threading/lib/messageTypes/threadMessage.js new file mode 100644 index 0000000000000..54bbe9ec13a28 --- /dev/null +++ b/packages/assistify-threading/lib/messageTypes/threadMessage.js @@ -0,0 +1,16 @@ +import {RocketChat} from 'meteor/rocketchat:lib'; + +Meteor.startup(function() { + RocketChat.MessageTypes.registerType({ + id: 'create-thread', + system: true, + message: 'thread-created', + data(message) { + return { + message: `Message`, + username: `@${ message.mentions[0].name }` + }; + } + }); +}); + diff --git a/packages/assistify-threading/package.js b/packages/assistify-threading/package.js index de45a2c83156b..da650a9398147 100644 --- a/packages/assistify-threading/package.js +++ b/packages/assistify-threading/package.js @@ -16,7 +16,7 @@ Package.onUse(function(api) { // api.use('meteorhacks:inject-initial'); //for provisioning of svg-icons api.addFiles('config.js', 'server'); - // api.addFiles('lib/messageTypes/threadMessage.js'); // TODO: Decide what to do with the rendered message types. They are less usable on mobile,but provide good experience on browser. + api.addFiles('lib/messageTypes/threadMessage.js'); // TODO: Decide what to do with the rendered message types. They are less usable on mobile,but provide good experience on browser. // Libraries // api.addFiles('server/inject.js', 'server'); @@ -24,6 +24,7 @@ Package.onUse(function(api) { //Methods api.addFiles('server/methods/createThread.js', 'server'); api.addFiles('server/methods/getParentChannelId.js', 'server'); + api.addFiles('server/methods/getParentChannelList.js', 'server'); // api.addFiles('server/methods/expertiseList.js', 'server'); // we have all migrations in one single file @@ -38,11 +39,11 @@ Package.onUse(function(api) { api.addFiles('client/views/creationDialog/CreateThread.html', 'client'); api.addFiles('client/views/creationDialog/CreateThread.js', 'client'); api.addFiles('client/views/creationDialog/CreateThreadInputError.html', 'client'); - // api.addFiles('client/views/creationDialog/AssistifyWordCloud.html', 'client'); // TODO: add wordcloud - but when doing this, ensure the sizes are based on the member-count (non-linear!) - // api.addFiles('client/views/creationDialog/AssistifyWordCloud.js', 'client'); api.addFiles('client/views/creationDialog/CreateThreadAutocomplete.html', 'client'); - // api.addFiles('client/views/creationDialog/AssistifyTopicSearchEmpty.html', 'client'); - // api.addFiles('client/views/creationDialog/AssistifyTopicSearchEmpty.js', 'client'); + api.addFiles('client/views/creationDialog/ChannelNotFound.html', 'client'); + api.addFiles('client/views/creationDialog/ChannelNotFound.js', 'client'); + api.addFiles('client/views/creationDialog/ChannelSelection.html', 'client'); // TODO: add wordcloud - but when doing this, ensure the sizes are based on the member-count (non-linear!) + api.addFiles('client/views/creationDialog/ChannelSelection.js', 'client'); // api.addFiles('client/views/messageActions/ThreadMessageAction.js', 'client'); // TODO: Re-add //styling diff --git a/packages/assistify-threading/server/methods/createThread.js b/packages/assistify-threading/server/methods/createThread.js index 4c5e6a5b3a28d..3d732d10ce041 100644 --- a/packages/assistify-threading/server/methods/createThread.js +++ b/packages/assistify-threading/server/methods/createThread.js @@ -1,6 +1,6 @@ -/* globals RocketChat */ -import { RocketChat } from 'meteor/rocketchat:lib'; -import { FlowRouter } from 'meteor/kadira:flow-router'; +/* UserRoles RoomRoles*/ +import {RocketChat} from 'meteor/rocketchat:lib'; +import {FlowRouter} from 'meteor/kadira:flow-router'; /* * When a message is eligible to be answered as a independent question then it can be threaded into a new channel. @@ -36,27 +36,40 @@ export class ThreadBuilder { return RocketChat.models.Rooms.findOne(roomId); } - _postMessage(room, user, message, attachments) { + _postMessage(room, user, message, attachments, channels, mentions) { attachments = attachments || []; //sendMessage expects the attachments timestamp to be a string, => serialize it attachments.forEach(attachment => attachment.ts = attachment.ts ? attachment.ts.toISOString() : '' ); - const newMessage = { _id: Random.id(), rid: room.rid, msg: message, attachments }; + const newMessage = {_id: Random.id(), rid: room.rid, msg: message, attachments, channels, mentions}; return RocketChat.sendMessage(user, newMessage, room); } _getMessageUrl(msgId) { - return FlowRouter.path('message', { id: msgId }); + return FlowRouter.path('message', {id: msgId}); } - _linkMessages(roomCreated, parentRoom) { + _linkMessages(roomCreated, parentRoom, message) { const rocketCatUser = RocketChat.models.Users.findOneByUsername('rocket.cat'); if (rocketCatUser && Meteor.userId()) { - // /** //TODO: Add link in parent Room - // * Parent Room - // */ + //TODO: Add link in parent Room + + /* Parent Room + */ + RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser('create-thread', parentRoom._id, this._getMessageUrl(message._id), rocketCatUser, + { + mentions: [{ + _id: Meteor.user()._id, // Thread Initiator + name: Meteor.user().username // Use @Name field for navigation + }], + channels: [{ + _id: roomCreated._id, // Parent Room ID + name: roomCreated.name + }] + }); + // RocketChat.models.Messages.updateMsgWithThreadMessage( // Meteor.user().username === this._openingQuestion.u.username ? 'thread-started-message-self' : 'thread-started-message', // this._openingQuestion._id, @@ -90,51 +103,75 @@ export class ThreadBuilder { // }] // }); // Re-post message in the new room - const msgAuthor = RocketChat.models.Users.findOneByUsername(this._openingQuestion.u.username); - const msgRePosted = this._postMessage( - roomCreated, - msgAuthor, - this._openingQuestion.msg, - this._openingQuestion.attachments ? this._openingQuestion.attachments.filter(attachment => attachment.type && attachment.type === 'file') : [] - ); - - if (msgRePosted) { - if (!this._openingQuestion._id) { - // TODO: If the thread was created without selecting a message in the parent, we need to create a message first - return; - } - /* Add a reference to the original message which can be rendered for navigation */ - RocketChat.models.Messages.setMessageAttachments(this._openingQuestion._id, [{ - author_name: this._openingQuestion.u.username || this._openingQuestion.u.name, - author_icon: `/avatar/${ this._openingQuestion.u.username }?_dc=0`, - ts: this._openingQuestion.ts, - fields: [{ - type: 'threadReference', - value: this._openingQuestion.msg, - threadUrl: this._getMessageUrl(msgRePosted._id) - }] - }]); - } + //Post message + + /* const msgAuthor = RocketChat.models.Users.findOneByUsername(this._openingQuestion.u.username); + const msgRePosted = this._postMessage( + roomCreated, + msgAuthor, + this._openingQuestion.msg, + this._openingQuestion.attachments ? this._openingQuestion.attachments.filter(attachment => attachment.type && attachment.type === 'file') : [] + ); + + if (msgRePosted) { + if (!this._openingQuestion._id) { + // TODO: If the thread was created without selecting a message in the parent, we need to create a message first + return; + } + /!* Add a reference to the original message which can be rendered for navigation *!/ + RocketChat.models.Messages.setMessageAttachments(this._openingQuestion._id, [{ + author_name: this._openingQuestion.u.username || this._openingQuestion.u.name, + author_icon: `/avatar/${ this._openingQuestion.u.username }?_dc=0`, + ts: this._openingQuestion.ts, + fields: [{ + type: 'threadReference', + value: this._openingQuestion.msg, + threadUrl: this._getMessageUrl(msgRePosted._id) + }] + }]); + }*/ } } _getMembers() { - const members = RocketChat.models.Subscriptions.findByRoomIdWhenUsernameExists(this._parentRoomId, { + const checkRoles = ['owner', 'moderator']; + const members = []; + const users = RocketChat.models.Subscriptions.findByRoomIdWhenUsernameExists(this._parentRoomId, { fields: { + 'u._id': 1, 'u.username': 1 } - }).fetch().map(s => s.u.username); - + }).fetch().map(s => { + return { + id: s.u._id, + username: s.u.username + }; + }); // TODO: filter on owner, moderators and those online (see @here-implementation) + for (const user of users) { + if (!RocketChat.authz.hasRole(user.id, checkRoles)) { + RocketChat.models.Users.findOne({ + _id: user.id, + status: { + $in: ['online', 'away', 'busy'] + } + }); + if (!user) { + continue; + // user.splice(users.indexOf(user), 1); //remove offline user + } + } + members.push(user.username); + } return members; } create() { const parentRoom = ThreadBuilder.getRoom(this._parentRoomId); - // Generate RoomName for the new room to be created. + // Generate RoomName for xthe new room to be created. this.name = `${ parentRoom.name }-${ ThreadBuilder.getNextId() }`; - const roomCreateResult = RocketChat.createRoom(parentRoom.t, this.name, Meteor.user() && Meteor.user().username, this._getMembers(), false, { parentRoomId: this._parentRoomId }); + const roomCreateResult = RocketChat.createRoom(parentRoom.t, this.name, Meteor.user() && Meteor.user().username, this._getMembers(), false, {parentRoomId: this._parentRoomId}); if (parentRoom.name) { RocketChat.saveRoomTopic(roomCreateResult.rid, parentRoom.name, Meteor.user()); @@ -143,7 +180,15 @@ export class ThreadBuilder { // Create messages in the newly created thread and it's parent which link the two rooms const room = RocketChat.models.Rooms.findOneById(roomCreateResult.rid); if (room && parentRoom) { - this._linkMessages(room, parentRoom); // TODO: post links + // Post message + const message = this._postMessage( + room, + this._openingQuestion.u, + this._openingQuestion.msg, + this._openingQuestion.attachments ? this._openingQuestion.attachments.filter(attachment => attachment.type && attachment.type === 'file') : [] + ); + // TODO: post links + this._linkMessages(room, parentRoom, message); } return roomCreateResult; @@ -154,7 +199,7 @@ export class ThreadBuilder { Meteor.methods({ createThread(parentRoomId, openingQuestion) { if (!Meteor.userId()) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'ThreadCreation' }); + throw new Meteor.Error('error-invalid-user', 'Invalid user', {method: 'ThreadCreation'}); } return new ThreadBuilder(parentRoomId, openingQuestion).create(); diff --git a/packages/assistify-threading/server/methods/getParentChannelId.js b/packages/assistify-threading/server/methods/getParentChannelId.js index a9bf53df409e6..6db888f9a8965 100644 --- a/packages/assistify-threading/server/methods/getParentChannelId.js +++ b/packages/assistify-threading/server/methods/getParentChannelId.js @@ -9,9 +9,10 @@ Meteor.methods({ }; const cursorHandle = RocketChat.models.Rooms.findByNameAndTypesNotInIds(channelName, ['c', 'p'], '', options); - const rooms = cursorHandle.fetch(); - if (rooms.length) { - return rooms[0]; + const room = cursorHandle.fetch(); + if (!room.length) { + throw new Meteor.Error('invalid-channel', 'Invalid channel', { method: 'assistify:getParentChannelId' }); } + return room[0]._id; } }); diff --git a/packages/assistify-threading/server/methods/getParentChannelList.js b/packages/assistify-threading/server/methods/getParentChannelList.js new file mode 100644 index 0000000000000..3637bbd8bcd68 --- /dev/null +++ b/packages/assistify-threading/server/methods/getParentChannelList.js @@ -0,0 +1,50 @@ +/* globals _ */ +Meteor.methods({ + 'getParentChannelList'({sort, limit}) { + this.unblock(); + check(sort, Match.Optional(String)); + check(limit, Match.Optional(Number)); + + if (!Meteor.userId()) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { + method: 'requestsList' + }); + } + + const options = { + fields: { + name: 1, + t: 1 + }, + sort: { + msgs: -1 + } + }; + + if (_.isNumber(limit)) { + options.limit = limit; + } + + if (sort.trim) { + switch (sort) { + case 'name': + options.sort = { + name: 1 + }; + break; + case 'msgs': + options.sort = { + msgs: -1 + }; + } + } + + return { + channels: RocketChat.models.Rooms.find({ + t: { + $in: ['p', 'c'] + } + }, options).fetch() + }; + } +}); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 89158993af225..1db1f9cb8ba82 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1922,6 +1922,7 @@ "Override_URL_to_which_files_are_uploaded_This_url_also_used_for_downloads_unless_a_CDN_is_given": "Override URL to which files are uploaded. This url also used for downloads unless a CDN is given", "Page_title": "Page title", "Page_URL": "Page URL", + "Parent_channel_doesnt_exist": "Channel does not exist.", "Password": "Password", "Password_Change_Disabled": "Your Rocket.Chat administrator has disabled the changing of passwords", "Password_changed_successfully": "Password changed successfully", @@ -2438,6 +2439,7 @@ "This_is_a_push_test_messsage": "This is a push test message", "This_room_has_been_archived_by__username_": "This room has been archived by __username__", "This_room_has_been_unarchived_by__username_": "This room has been unarchived by __username__", + "thread-created" : "__username__ has started a new __message__ thread.", "Thursday": "Thursday", "Time_in_seconds": "Time in seconds", "Title": "Title", diff --git a/packages/rocketchat-ui-message/client/message.html b/packages/rocketchat-ui-message/client/message.html index c5dd433820c24..eba37ae315799 100644 --- a/packages/rocketchat-ui-message/client/message.html +++ b/packages/rocketchat-ui-message/client/message.html @@ -1,5 +1,5 @@ From 9994302e56642fce63832f7cbb0f32beadac8656 Mon Sep 17 00:00:00 2001 From: vickyokrm Date: Tue, 7 Aug 2018 15:41:22 +0200 Subject: [PATCH 006/124] world cloud integration fix --- .../views/creationDialog/CreateThread.js | 51 ++++--- .../server/methods/createThread.js | 133 +++++++++--------- 2 files changed, 91 insertions(+), 93 deletions(-) diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.js b/packages/assistify-threading/client/views/creationDialog/CreateThread.js index 4581fb7e1adbf..616e8c16eaffb 100755 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.js +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.js @@ -1,7 +1,7 @@ /* globals TAPi18n, AutoComplete */ /* globals _ */ -import { FlowRouter } from 'meteor/kadira:flow-router'; -import { ReactiveVar } from 'meteor/reactive-var'; +import {FlowRouter} from 'meteor/kadira:flow-router'; +import {ReactiveVar} from 'meteor/reactive-var'; const acEvents = { 'click .rc-popup-list__item'(e, t) { @@ -122,7 +122,7 @@ Template.CreateThread.helpers({ if (parentChannel) { instance.debounceWordCloudSelect(parentChannel); } - instance.channelSelectionEnabled.set(''); //Search completed. + instance.showChannelSelection.set(false); //Search completed. }; } @@ -223,7 +223,7 @@ Template.CreateThread.onRendered(function() { instance.ac.element = parentChannelElement; instance.ac.$element = $(instance.ac.element); - instance.ac.$element.on('autocompleteselect', function(e, { item }) { + instance.ac.$element.on('autocompleteselect', function(e, {item}) { instance.parentChannel.set(item.name); $('input[name="parentChannel"]').val(item.name); instance.debounceValidateParentChannel(item.name); @@ -234,30 +234,29 @@ Template.CreateThread.onRendered(function() { questionElement.value = instance.openingQuestion.get(); } - // this.autorun(() => { - // instance.debounceWordCloudSelect = _.debounce((parentChannel) => { // TODO: integrate Wordcloud - // /* - // * Update the parentChannel html reference to autocomplete - // */ - // instance.ac.element = this.find('#parentChannel-search'); - // instance.ac.$element = $(instance.ac.element); - // $('input[name="parentChannel"]').val(parentChannel.name); // copy the selected value to screen field - // instance.ac.$element.on('autocompleteselect', function(e, { item }) { - // instance.parentChannel.set(item.name); - // $('input[name="parentChannel"]').val(item.name); - // instance.debounceValidateParentChannel(item.name); - - // return instance.find('.js-save-thread').focus(); - // }); - // instance.parentChannel.set(parentChannel.name); - // instance.debounceValidateParentChannel(parentChannel.name); // invoke validation*/ - // }, 200); - // }); + this.autorun(() => { + instance.debounceWordCloudSelect = _.debounce((parentChannel) => { // integrate Wordcloud + /* + * Update the parentChannel html reference to autocomplete + */ + instance.ac.element = this.find('#parentChannel-search'); + instance.ac.$element = $(instance.ac.element); + $('input[name="parentChannel-search"]').val(parentChannel.name); // copy the selected value to screen field + instance.ac.$element.on('autocompleteselect', function(e, {item}) { + instance.parentChannel.set(item.name); + $('input[name="parentChannel-search"]').val(item.name); + instance.debounceValidateParentChannel(item.name); + return instance.find('.js-save-thread').focus(); + }); + instance.parentChannel.set(parentChannel.name); + instance.debounceValidateParentChannel(parentChannel.name); // invoke validation*/ + }, 200); + }); }); Template.CreateThread.onCreated(function() { const instance = this; - instance.parentChannel = new ReactiveVar(RocketChat.settings.get('Parent_Channel')); // TODO: determine parent Channel from setting and allow to overwrite + instance.parentChannel = new ReactiveVar(RocketChat.settings.get('Parent_Channel')); //determine parent Channel from setting and allow to overwrite instance.parentChannelId = new ReactiveVar(''); instance.parentChannelError = new ReactiveVar(null); instance.selectParent = new ReactiveVar(RocketChat.settings.get('Select_Parent')); @@ -296,8 +295,8 @@ Template.CreateThread.onCreated(function() { limit: 10, inputDelay: 300, rules: [{ - collection: 'CachedChannelList', // TODO: check for proper collection - subscription: 'channelAndPrivateAutocomplete', // TODO: Provide another subscription exposing `c` and `p` + collection: 'CachedChannelList', // check for proper collection + subscription: 'channelAndPrivateAutocomplete', // Provide another subscription exposing `c` and `p` field: 'name', matchAll: true, doNotChangeWidth: false, diff --git a/packages/assistify-threading/server/methods/createThread.js b/packages/assistify-threading/server/methods/createThread.js index 3d732d10ce041..f4777af2dc828 100644 --- a/packages/assistify-threading/server/methods/createThread.js +++ b/packages/assistify-threading/server/methods/createThread.js @@ -54,9 +54,7 @@ export class ThreadBuilder { _linkMessages(roomCreated, parentRoom, message) { const rocketCatUser = RocketChat.models.Users.findOneByUsername('rocket.cat'); if (rocketCatUser && Meteor.userId()) { - //TODO: Add link in parent Room - - /* Parent Room + /* Add link in parent Room */ RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser('create-thread', parentRoom._id, this._getMessageUrl(message._id), rocketCatUser, { @@ -69,68 +67,6 @@ export class ThreadBuilder { name: roomCreated.name }] }); - - // RocketChat.models.Messages.updateMsgWithThreadMessage( - // Meteor.user().username === this._openingQuestion.u.username ? 'thread-started-message-self' : 'thread-started-message', - // this._openingQuestion._id, - // '', - // Meteor.user(), - // { - // mentions: [ - // { - // _id: Meteor.user()._id, // Thread Initiator - // name: Meteor.user().username - // }] - // } - // ); - - // The following lines would have the attachment remain at the original message. - // if (this._openingQuestion.attachments) { - // RocketChat.models.Messages.addMessageAttachments(this._openingQuestion._id, this._openingQuestion.attachments); - // } - - /* - * Child Room - */ - // RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser('thread-welcome-message', roomCreated._id, this._getMessageUrl(this._openingQuestion._id), rocketCatUser, - // { - // mentions: [{ - // _id: Meteor.user()._id, // Thread Initiator - // name: Meteor.user().username // Use @Name field for navigation - // }], - // channels: [{ - // _id: parentRoom._id // Parent Room ID - // }] - // }); - // Re-post message in the new room - - //Post message - - /* const msgAuthor = RocketChat.models.Users.findOneByUsername(this._openingQuestion.u.username); - const msgRePosted = this._postMessage( - roomCreated, - msgAuthor, - this._openingQuestion.msg, - this._openingQuestion.attachments ? this._openingQuestion.attachments.filter(attachment => attachment.type && attachment.type === 'file') : [] - ); - - if (msgRePosted) { - if (!this._openingQuestion._id) { - // TODO: If the thread was created without selecting a message in the parent, we need to create a message first - return; - } - /!* Add a reference to the original message which can be rendered for navigation *!/ - RocketChat.models.Messages.setMessageAttachments(this._openingQuestion._id, [{ - author_name: this._openingQuestion.u.username || this._openingQuestion.u.name, - author_icon: `/avatar/${ this._openingQuestion.u.username }?_dc=0`, - ts: this._openingQuestion.ts, - fields: [{ - type: 'threadReference', - value: this._openingQuestion.msg, - threadUrl: this._getMessageUrl(msgRePosted._id) - }] - }]); - }*/ } } @@ -148,7 +84,7 @@ export class ThreadBuilder { username: s.u.username }; }); - // TODO: filter on owner, moderators and those online (see @here-implementation) + // filter on owner, moderators and those online (see @here-implementation) for (const user of users) { if (!RocketChat.authz.hasRole(user.id, checkRoles)) { RocketChat.models.Users.findOne({ @@ -187,7 +123,7 @@ export class ThreadBuilder { this._openingQuestion.msg, this._openingQuestion.attachments ? this._openingQuestion.attachments.filter(attachment => attachment.type && attachment.type === 'file') : [] ); - // TODO: post links + // Link messages this._linkMessages(room, parentRoom, message); } @@ -205,3 +141,66 @@ Meteor.methods({ return new ThreadBuilder(parentRoomId, openingQuestion).create(); } }); + + +// RocketChat.models.Messages.updateMsgWithThreadMessage( +// Meteor.user().username === this._openingQuestion.u.username ? 'thread-started-message-self' : 'thread-started-message', +// this._openingQuestion._id, +// '', +// Meteor.user(), +// { +// mentions: [ +// { +// _id: Meteor.user()._id, // Thread Initiator +// name: Meteor.user().username +// }] +// } +// ); + +// The following lines would have the attachment remain at the original message. +// if (this._openingQuestion.attachments) { +// RocketChat.models.Messages.addMessageAttachments(this._openingQuestion._id, this._openingQuestion.attachments); +// } + +/* + * Child Room + */ +// RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser('thread-welcome-message', roomCreated._id, this._getMessageUrl(this._openingQuestion._id), rocketCatUser, +// { +// mentions: [{ +// _id: Meteor.user()._id, // Thread Initiator +// name: Meteor.user().username // Use @Name field for navigation +// }], +// channels: [{ +// _id: parentRoom._id // Parent Room ID +// }] +// }); +// Re-post message in the new room + +//Post message + +/* const msgAuthor = RocketChat.models.Users.findOneByUsername(this._openingQuestion.u.username); + const msgRePosted = this._postMessage( + roomCreated, + msgAuthor, + this._openingQuestion.msg, + this._openingQuestion.attachments ? this._openingQuestion.attachments.filter(attachment => attachment.type && attachment.type === 'file') : [] + ); + + if (msgRePosted) { + if (!this._openingQuestion._id) { + // TODO: If the thread was created without selecting a message in the parent, we need to create a message first + return; + } + /!* Add a reference to the original message which can be rendered for navigation *!/ + RocketChat.models.Messages.setMessageAttachments(this._openingQuestion._id, [{ + author_name: this._openingQuestion.u.username || this._openingQuestion.u.name, + author_icon: `/avatar/${ this._openingQuestion.u.username }?_dc=0`, + ts: this._openingQuestion.ts, + fields: [{ + type: 'threadReference', + value: this._openingQuestion.msg, + threadUrl: this._getMessageUrl(msgRePosted._id) + }] + }]); + }*/ From e1f27ca0200b439645f36f8e4eeb66b51fdf2f9c Mon Sep 17 00:00:00 2001 From: vickyokrm Date: Wed, 8 Aug 2018 13:58:31 +0200 Subject: [PATCH 007/124] fix circleci out of memory --- package.json | 2 +- .../client/views/creationDialog/CreateThread.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 00a777e2daf4f..9f5bd7e56ea68 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "atlassian-crowd": "^0.5.0", "autolinker": "^1.7.0", "aws-sdk": "^2.283.1", - "bad-words": "^1.6.1", + "bad-words": "^1.6.3", "bcrypt": "^2.0.1", "bson": "^2.0.8", "bugsnag": "^2.4.3", diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.js b/packages/assistify-threading/client/views/creationDialog/CreateThread.js index 616e8c16eaffb..fc61e145f9cc1 100755 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.js +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.js @@ -326,7 +326,7 @@ Template.CreateThread.onCreated(function() { Meteor.call('getParentChannelList', { sort: 'name' - }, function(err, result) { // TODO: Provide analogous methods + }, function(err, result) { if (result) { instance.parentChannelsList.set(result.channels); } From 85a327977b85e9bbe96a6c1e671085c639f94b18 Mon Sep 17 00:00:00 2001 From: vickyokrm Date: Wed, 8 Aug 2018 14:14:54 +0200 Subject: [PATCH 008/124] fix circleci --- .meteor/versions | 1 + package.json | 56 ++++++++++++++++++++++-------------------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/.meteor/versions b/.meteor/versions index 1f4fb2c280fbe..7e310efe5fdc4 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -110,6 +110,7 @@ oauth2@1.2.0 observe-sequence@1.0.16 ordered-dict@1.1.0 ostrio:cookies@2.2.4 +overture8:wordcloud2@1.0.0 pauli:accounts-linkedin@2.1.5 pauli:linkedin-oauth@1.2.0 percolate:synced-cron@1.3.2 diff --git a/package.json b/package.json index 9f5bd7e56ea68..1d369b2de64f2 100644 --- a/package.json +++ b/package.json @@ -88,12 +88,12 @@ "email": "support@rocket.chat" }, "devDependencies": { - "@octokit/rest": "^15.9.4", - "autoprefixer": "^8.6.5", + "@octokit/rest": "^15.8.1", + "autoprefixer": "^8.6.0", "babel-mocha-es6-compiler": "^0.1.0", "babel-plugin-array-includes": "^2.0.3", "chimp": "^0.51.1", - "conventional-changelog-cli": "^2.0.1", + "conventional-changelog-cli": "^2.0.0", "eslint": "^4.19.1", "mocha": "^5.2.0", "mock-require": "^3.0.2", @@ -104,46 +104,44 @@ "postcss-selector-not": "^3.0.1", "progress": "^2.0.0", "proxyquire": "^2.0.1", - "simple-git": "^1.96.0", - "stylelint": "^9.4.0", + "simple-git": "^1.95.1", + "stylelint": "^9.2.1", "stylelint-order": "^0.8.1", "supertest": "^3.1.0" }, "dependencies": { - "@babel/runtime": "^7.0.0-beta.55", + "@babel/runtime": "^7.0.0-beta.49", "@google-cloud/language": "^1.2.0", "@google-cloud/storage": "^1.7.0", "@google-cloud/vision": "^0.19.0", - "@slack/client": "^4.3.1", + "@slack/client": "^4.2.2", "adm-zip": "^0.4.11", "archiver": "^2.1.1", "atlassian-crowd": "^0.5.0", - "autolinker": "^1.7.0", - "aws-sdk": "^2.283.1", - "bad-words": "^1.6.3", + "autolinker": "^1.6.2", + "aws-sdk": "^2.250.1", + "bad-words": "^1.6.1", "bcrypt": "^2.0.1", - "bson": "^2.0.8", - "bugsnag": "^2.4.3", + "bson": "^2.0.7", + "bugsnag": "^2.4.0", "bunyan": "^1.8.12", "busboy": "^0.2.14", "cas": "https://github.com/kcbanner/node-cas/tarball/fcd27dad333223b3b75a048bce27973fb3ca0f62", - "chai": "^2.1.2", - "chai-as-promised": "^6.0.0", "clipboard": "^2.0.1", - "codemirror": "^5.39.2", + "codemirror": "^5.38.0", "coffeescript": "^1.12.7", "connect": "^2.7.10", "core-js": "^2.5.7", - "csv-parse": "^2.5.0", + "csv-parse": "^2.4.0", "emailreplyparser": "^0.0.5", - "file-type": "^8.1.0", + "file-type": "^8.0.0", "filesize": "^3.6.1", "grapheme-splitter": "^1.0.2", "gridfs-stream": "^1.1.1", "he": "^1.1.1", "highlight.js": "^9.12.0", "iconv-lite": "^0.4.23", - "image-size": "^0.6.3", + "image-size": "^0.6.2", "imap": "^0.8.19", "ip-range-check": "^0.0.2", "jquery": "^3.3.1", @@ -151,38 +149,36 @@ "ldapjs": "^1.0.2", "less": "https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6", "less-plugin-autoprefix": "^1.5.1", - "localforage": "^1.7.2", + "localforage": "^1.7.1", "lokijs": "^1.5.5", "lru-cache": "^4.1.3", - "mailparser": "^2.3.2", + "mailparser": "^2.2.0", "marked": "^0.4.0", - "mime-db": "^1.35.0", + "mime-db": "^1.34.0", "mime-type": "^3.0.5", "mkdirp": "^0.5.1", "moment": "^2.22.2", - "moment-timezone": "^0.5.21", + "moment-timezone": "^0.5.17", "node-dogstatsd": "^0.0.7", "object-path": "^0.11.4", "photoswipe": "^4.1.2", "poplib": "^0.1.7", - "postcss-html": "^0.31.0", - "postcss-syntax": "^0.31.0", - "prom-client": "^11.1.1", + "prom-client": "^11.0.0", "querystring": "^0.2.0", "queue-fifo": "^0.2.4", "redis": "^2.8.0", "semver": "^5.5.0", - "sharp": "^0.20.5", + "sharp": "^0.20.3", "speakeasy": "^2.0.0", "tar-stream": "^1.6.1", "toastr": "^2.1.4", - "twilio": "^3.18.0", - "twit": "^2.2.11", + "twilio": "^3.17.1", + "twit": "^2.2.10", "ua-parser-js": "^0.7.18", "underscore": "^1.9.1", "underscore.string": "^3.3.4", - "webdav": "^1.5.3", - "wolfy87-eventemitter": "^5.2.5", + "webdav": "^1.5.2", + "wolfy87-eventemitter": "^5.2.4", "xml-crypto": "^0.10.1", "xml2js": "^0.4.19", "xmlbuilder": "^10.0.0", From 59491423425fd791a4ef072fffdf8f1933b53a85 Mon Sep 17 00:00:00 2001 From: vickyokrm Date: Wed, 8 Aug 2018 15:52:13 +0200 Subject: [PATCH 009/124] update npm --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 1d369b2de64f2..489ed228c8b73 100644 --- a/package.json +++ b/package.json @@ -160,6 +160,7 @@ "moment": "^2.22.2", "moment-timezone": "^0.5.17", "node-dogstatsd": "^0.0.7", + "npm": "^6.3.0", "object-path": "^0.11.4", "photoswipe": "^4.1.2", "poplib": "^0.1.7", From 8770ce3b6cf18f72c6c1d40e691cd03c33cb856f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Fri, 10 Aug 2018 13:55:07 +0200 Subject: [PATCH 010/124] Add translations --- .../client/views/creationDialog/CreateThread.html | 4 ++-- packages/rocketchat-i18n/i18n/de.i18n.json | 9 ++++++++- packages/rocketchat-i18n/i18n/en.i18n.json | 8 ++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.html b/packages/assistify-threading/client/views/creationDialog/CreateThread.html index 41ae350cb71af..f641d73952e86 100644 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.html +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.html @@ -35,7 +35,7 @@

{{_ "Thread"}}

+ "Thread_target_channel_description"}} autocomplete=off value={{parentChannel}}>

{{_ "Thread"}}

- \ No newline at end of file + diff --git a/packages/rocketchat-i18n/i18n/de.i18n.json b/packages/rocketchat-i18n/i18n/de.i18n.json index a73a53b14a8ff..954e2de31b8c7 100644 --- a/packages/rocketchat-i18n/i18n/de.i18n.json +++ b/packages/rocketchat-i18n/i18n/de.i18n.json @@ -1804,6 +1804,7 @@ "Confirm_New_Password_Placeholder": "Bitte gib ein neues Passwort ein ...", "New_role": "Neue Rolle", "New_Room_Notification": "Neuer-Raum-Benachrichtigung", + "New_thread_first_message": "Üblicherweise beginn ein Thread mit einer Frage, bspw. \"Wie lade ich ein Bild hoch?\"", "New_Trigger": "Neuer Trigger", "New_version_available_(s)": "Neue Version verfügbar (%s)", "New_videocall_request": "Neuer Video-Anruf", @@ -2419,6 +2420,11 @@ "This_is_a_push_test_messsage": "Dies ist eine Test-Push-Nachricht", "This_room_has_been_archived_by__username_": "Dieser Raum wurde von __username__ archiviert", "This_room_has_been_unarchived_by__username_": "Dieser Raum wurde von __username__ aus dem Archiv geholt", + "Thread": "Einen neuen Thread anlegen", + "Threading_description": "Hilf dabei, die Übersicht zu behalten! Indem Du einen Thread anlegst, wird ein Unterkanal mit passenden Mitgliedern erstellt.", + "Thread_select_different_parent": "- wähle einen anderen übergeordneten Kanal aus", + "Thread_target_channel": "Übergeordneter Kanal oder Gruppe", + "Thread_target_channel_description": "Wähle einen Kanal oder eine Gruppe aus, die zu Deinem Anliegen passt", "Thursday": "Donnerstag", "Time_in_seconds": "Zeit in Sekunden", "Title": "Titel", @@ -2736,6 +2742,7 @@ "your_message_optional": "Ihre optionale Nachricht", "Your_password_is_wrong": "Falsches Passwort", "Your_push_was_sent_to_s_devices": "Eine Push-Nachricht wurde an %s Geräte gesendet.", + "Your_question": "Deine Frage", "Your_server_link": "Ihre Serververbindung", "Your_workspace_is_ready": "Ihr Arbeitsbereich ist einsatzbereit 🎉" -} \ No newline at end of file +} diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 1db1f9cb8ba82..8b321eff8707a 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1810,6 +1810,7 @@ "Confirm_New_Password_Placeholder": "Please re-enter new password...", "New_role": "New role", "New_Room_Notification": "New Room Notification", + "New_thread_first_message": "Usually, a thread starts with a question, like \"How do I upload a picture?\"", "New_Trigger": "New Trigger", "New_version_available_(s)": "New version available (%s)", "New_videocall_request": "New Video Call Request", @@ -2362,6 +2363,7 @@ "Sync_Users": "Sync Users", "System_messages": "System Messages", "Tag": "Tag", + "Target_channel_prefix": "You are asking the members of", "Take_it": "Take it!", "TargetRoom": "Target Room", "TargetRoom_Description": "The room where messages will be sent which are a result of this event being fired. Only one target room is allowed and it must exist.", @@ -2440,6 +2442,11 @@ "This_room_has_been_archived_by__username_": "This room has been archived by __username__", "This_room_has_been_unarchived_by__username_": "This room has been unarchived by __username__", "thread-created" : "__username__ has started a new __message__ thread.", + "Thread": "Create a new thread", + "Threading_description": "Help keeping an overview about what's going on! By creating a thread, a sub-channel of the one you selected is created and both are linked.", + "Thread_select_different_parent": "- select a different parent channel", + "Thread_target_channel": "Parent channel or group", + "Thread_target_channel_description": "Select a channel which is related to what you want to ask", "Thursday": "Thursday", "Time_in_seconds": "Time in seconds", "Title": "Title", @@ -2757,6 +2764,7 @@ "your_message_optional": "your message (optional)", "Your_password_is_wrong": "Your password is wrong!", "Your_push_was_sent_to_s_devices": "Your push was sent to %s devices", + "Your_question": "Your question", "Your_server_link": "Your server link", "Your_workspace_is_ready": "Your workspace is ready to use 🎉" } From 34248e744d8a2b444d2466c0855e841d004bb83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Fri, 10 Aug 2018 13:58:23 +0200 Subject: [PATCH 011/124] Role-Check needs roomas context --- package-lock.json | 3214 +++++++++++++++-- .../server/methods/createThread.js | 2 +- packages/rocketchat-katex/package-lock.json | 2 +- 3 files changed, 2985 insertions(+), 233 deletions(-) diff --git a/package-lock.json b/package-lock.json index bec203b3a51d0..96c781ccf19a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4481,7 +4481,6 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "optional": true, "requires": { "prr": "1.0.1" } @@ -9491,8 +9490,7 @@ "natives": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.4.tgz", - "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==", - "optional": true + "integrity": "sha512-Q29yeg9aFKwhLVdkTAejM/HvYG0Y1Am1+HUkFQGn5k2j8GS+v60TVmZh6nujpEAj/qql+wGUrlryO8bF+b1jEg==" }, "natural-compare": { "version": "1.4.0", @@ -9607,240 +9605,2995 @@ "sort-keys": "2.0.0" } }, - "npm-install-package": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz", - "integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=", - "dev": true - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "1.1.5", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "requires": { - "boolbase": "1.0.0" - } - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "npm": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-6.3.0.tgz", + "integrity": "sha512-oDtLFo3wXue/xe3pU/oks9VHS5501OAWlYrZrApZkFv7l2LXk+9CfPMbjbfZWK7Jqlc1jbNcJMkB6KZC7K/vEA==", "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" + "JSONStream": "1.3.3", + "abbrev": "1.1.1", + "ansicolors": "0.3.2", + "ansistyles": "0.1.3", + "aproba": "1.2.0", + "archy": "1.0.0", + "bin-links": "1.1.2", + "bluebird": "3.5.1", + "byte-size": "4.0.3", + "cacache": "11.1.0", + "call-limit": "1.1.0", + "chownr": "1.0.1", + "cli-columns": "3.1.2", + "cli-table3": "0.5.0", + "cmd-shim": "2.0.2", + "columnify": "1.5.4", + "config-chain": "1.1.11", + "debuglog": "1.0.1", + "detect-indent": "5.0.0", + "detect-newline": "2.1.0", + "dezalgo": "1.0.3", + "editor": "1.0.0", + "figgy-pudding": "3.2.0", + "find-npm-prefix": "1.0.2", + "fs-vacuum": "1.2.10", + "fs-write-stream-atomic": "1.0.10", + "gentle-fs": "2.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "has-unicode": "2.0.1", + "hosted-git-info": "2.6.0", + "iferr": "1.0.0", + "imurmurhash": "0.1.4", + "inflight": "1.0.6", + "inherits": "2.0.3", + "ini": "1.3.5", + "init-package-json": "1.10.3", + "is-cidr": "2.0.6", + "json-parse-better-errors": "1.0.2", + "lazy-property": "1.0.0", + "libcipm": "2.0.0", + "libnpmhook": "4.0.1", + "libnpx": "10.2.0", + "lock-verify": "2.0.2", + "lockfile": "1.0.4", + "lodash._baseindexof": "3.1.0", + "lodash._baseuniq": "4.6.0", + "lodash._bindcallback": "3.0.1", + "lodash._cacheindexof": "3.0.2", + "lodash._createcache": "3.1.2", + "lodash._getnative": "3.9.1", + "lodash.clonedeep": "4.5.0", + "lodash.restparam": "3.6.1", + "lodash.union": "4.6.0", + "lodash.uniq": "4.5.0", + "lodash.without": "4.4.0", + "lru-cache": "4.1.3", + "meant": "1.0.1", + "mississippi": "3.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "node-gyp": "3.7.0", + "nopt": "4.0.1", + "normalize-package-data": "2.4.0", + "npm-audit-report": "1.3.1", + "npm-cache-filename": "1.0.2", + "npm-install-checks": "3.0.0", + "npm-lifecycle": "2.0.3", + "npm-package-arg": "6.1.0", + "npm-packlist": "1.1.10", + "npm-pick-manifest": "2.1.0", + "npm-profile": "3.0.2", + "npm-registry-client": "8.5.1", + "npm-registry-fetch": "1.1.0", + "npm-user-validate": "1.0.0", + "npmlog": "4.1.2", + "once": "1.4.0", + "opener": "1.4.3", + "osenv": "0.1.5", + "pacote": "8.1.6", + "path-is-inside": "1.0.2", + "promise-inflight": "1.0.1", + "qrcode-terminal": "0.12.0", + "query-string": "6.1.0", + "qw": "1.0.1", + "read": "1.0.7", + "read-cmd-shim": "1.0.1", + "read-installed": "4.0.3", + "read-package-json": "2.0.13", + "read-package-tree": "5.2.1", + "readable-stream": "2.3.6", + "readdir-scoped-modules": "1.0.2", + "request": "2.81.0", + "retry": "0.12.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "sha": "2.0.1", + "slide": "1.1.6", + "sorted-object": "2.0.1", + "sorted-union-stream": "2.1.3", + "ssri": "6.0.0", + "stringify-package": "1.0.0", + "tar": "4.4.4", + "text-table": "0.2.0", + "tiny-relative-date": "1.3.0", + "uid-number": "0.0.6", + "umask": "1.1.0", + "unique-filename": "1.1.0", + "unpipe": "1.0.0", + "update-notifier": "2.5.0", + "uuid": "3.3.2", + "validate-npm-package-license": "3.0.3", + "validate-npm-package-name": "3.0.0", + "which": "1.3.1", + "worker-farm": "1.6.0", + "write-file-atomic": "2.3.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "JSONStream": { + "version": "1.3.3", + "bundled": true, "requires": { - "is-descriptor": "0.1.6" + "jsonparse": "1.3.1", + "through": "2.3.8" } }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "agent-base": { + "version": "4.2.0", + "bundled": true, "requires": { - "is-buffer": "1.1.6" + "es6-promisify": "5.0.0" } - } - } - }, - "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" - }, - "object-path": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", - "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=" - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "3.0.1" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.1", - "has-symbols": "1.0.0", - "object-keys": "1.0.11" - } - }, - "object.entries": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", - "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.12.0", - "function-bind": "1.1.1", - "has": "1.0.2" - } - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.12.0" - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "requires": { - "isobject": "3.0.1" - } - }, - "object.values": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", - "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.12.0", - "function-bind": "1.1.1", - "has": "1.0.2" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "1.2.0" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" - }, - "dependencies": { - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - } - } - }, - "optjs": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", - "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + }, + "agentkeepalive": { + "version": "3.4.1", + "bundled": true, + "requires": { + "humanize-ms": "1.2.1" + } + }, + "ansi-align": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "2.1.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "ansicolors": { + "version": "0.3.2", + "bundled": true + }, + "ansistyles": { + "version": "0.1.3", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "archy": { + "version": "1.0.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "asap": { + "version": "2.0.6", + "bundled": true + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.7.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "bin-links": { + "version": "1.1.2", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "cmd-shim": "2.0.2", + "gentle-fs": "2.0.1", + "graceful-fs": "4.1.11", + "write-file-atomic": "2.3.0" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + }, + "bluebird": { + "version": "3.5.1", + "bundled": true + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "boxen": { + "version": "1.3.0", + "bundled": true, + "requires": { + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.4.1", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer-from": { + "version": "1.0.0", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "builtins": { + "version": "1.0.3", + "bundled": true + }, + "byline": { + "version": "5.0.0", + "bundled": true + }, + "byte-size": { + "version": "4.0.3", + "bundled": true + }, + "cacache": { + "version": "11.1.0", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "chownr": "1.0.1", + "figgy-pudding": "3.2.0", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "6.0.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" + } + }, + "call-limit": { + "version": "1.1.0", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "chalk": { + "version": "2.4.1", + "bundled": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true + }, + "ci-info": { + "version": "1.1.3", + "bundled": true + }, + "cidr-regex": { + "version": "2.0.9", + "bundled": true, + "requires": { + "ip-regex": "2.1.0" + } + }, + "cli-boxes": { + "version": "1.0.0", + "bundled": true + }, + "cli-columns": { + "version": "3.1.2", + "bundled": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "3.0.1" + } + }, + "cli-table3": { + "version": "0.5.0", + "bundled": true, + "requires": { + "colors": "1.3.0", + "object-assign": "4.1.1", + "string-width": "2.1.1" + } + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "bundled": true + }, + "cmd-shim": { + "version": "2.0.2", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1" + } + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "color-convert": { + "version": "1.9.1", + "bundled": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.3.0", + "bundled": true, + "optional": true + }, + "columnify": { + "version": "1.5.4", + "bundled": true, + "requires": { + "strip-ansi": "3.0.1", + "wcwidth": "1.0.1" + } + }, + "combined-stream": { + "version": "1.0.6", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "concat-stream": { + "version": "1.6.2", + "bundled": true, + "requires": { + "buffer-from": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, + "config-chain": { + "version": "1.1.11", + "bundled": true, + "requires": { + "ini": "1.3.5", + "proto-list": "1.2.4" + } + }, + "configstore": { + "version": "3.1.2", + "bundled": true, + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.3.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + } + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "copy-concurrently": { + "version": "1.0.5", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "fs-write-stream-atomic": "1.0.10", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "create-error-class": { + "version": "3.0.2", + "bundled": true, + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.10.1" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "bundled": true + }, + "cyclist": { + "version": "0.2.2", + "bundled": true + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "debug": { + "version": "3.1.0", + "bundled": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "bundled": true + } + } + }, + "debuglog": { + "version": "1.0.1", + "bundled": true + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "decode-uri-component": { + "version": "0.2.0", + "bundled": true + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true + }, + "defaults": { + "version": "1.0.3", + "bundled": true, + "requires": { + "clone": "1.0.4" + } + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-indent": { + "version": "5.0.0", + "bundled": true + }, + "detect-newline": { + "version": "2.1.0", + "bundled": true + }, + "dezalgo": { + "version": "1.0.3", + "bundled": true, + "requires": { + "asap": "2.0.6", + "wrappy": "1.0.2" + } + }, + "dot-prop": { + "version": "4.2.0", + "bundled": true, + "requires": { + "is-obj": "1.0.1" + } + }, + "dotenv": { + "version": "5.0.1", + "bundled": true + }, + "duplexer3": { + "version": "0.1.4", + "bundled": true + }, + "duplexify": { + "version": "3.6.0", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "editor": { + "version": "1.0.0", + "bundled": true + }, + "encoding": { + "version": "0.1.12", + "bundled": true, + "requires": { + "iconv-lite": "0.4.23" + } + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "1.4.0" + } + }, + "err-code": { + "version": "1.1.2", + "bundled": true + }, + "errno": { + "version": "0.1.7", + "bundled": true, + "requires": { + "prr": "1.0.1" + } + }, + "es6-promise": { + "version": "4.2.4", + "bundled": true + }, + "es6-promisify": { + "version": "5.0.0", + "bundled": true, + "requires": { + "es6-promise": "4.2.4" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "figgy-pudding": { + "version": "3.2.0", + "bundled": true + }, + "find-npm-prefix": { + "version": "1.0.2", + "bundled": true + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "flush-write-stream": { + "version": "1.0.3", + "bundled": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "from2": { + "version": "2.3.0", + "bundled": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "requires": { + "minipass": "2.3.3" + } + }, + "fs-vacuum": { + "version": "1.2.10", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "path-is-inside": "1.0.2", + "rimraf": "2.6.2" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "imurmurhash": "0.1.4", + "readable-stream": "2.3.6" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "genfun": { + "version": "4.0.1", + "bundled": true + }, + "gentle-fs": { + "version": "2.0.1", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "fs-vacuum": "1.2.10", + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "path-is-inside": "1.0.2", + "read-cmd-shim": "1.0.1", + "slide": "1.1.6" + }, + "dependencies": { + "iferr": { + "version": "0.1.5", + "bundled": true + } + } + }, + "get-caller-file": { + "version": "1.0.2", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "bundled": true, + "requires": { + "ini": "1.3.5" + } + }, + "got": { + "version": "6.7.1", + "bundled": true, + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "bundled": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + } + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "hosted-git-info": { + "version": "2.6.0", + "bundled": true + }, + "http-cache-semantics": { + "version": "3.8.1", + "bundled": true + }, + "http-proxy-agent": { + "version": "2.1.0", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + } + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "debug": "3.1.0" + } + }, + "humanize-ms": { + "version": "1.2.1", + "bundled": true, + "requires": { + "ms": "2.1.1" + } + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "iferr": { + "version": "1.0.0", + "bundled": true + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "import-lazy": { + "version": "2.1.0", + "bundled": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "init-package-json": { + "version": "1.10.3", + "bundled": true, + "requires": { + "glob": "7.1.2", + "npm-package-arg": "6.1.0", + "promzard": "0.3.0", + "read": "1.0.7", + "read-package-json": "2.0.13", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3", + "validate-npm-package-name": "3.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "ip": { + "version": "1.1.5", + "bundled": true + }, + "ip-regex": { + "version": "2.1.0", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-ci": { + "version": "1.1.0", + "bundled": true, + "requires": { + "ci-info": "1.1.3" + } + }, + "is-cidr": { + "version": "2.0.6", + "bundled": true, + "requires": { + "cidr-regex": "2.0.9" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "bundled": true, + "requires": { + "global-dirs": "0.1.1", + "is-path-inside": "1.0.1" + } + }, + "is-npm": { + "version": "1.0.0", + "bundled": true + }, + "is-obj": { + "version": "1.0.1", + "bundled": true + }, + "is-path-inside": { + "version": "1.0.1", + "bundled": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-redirect": { + "version": "1.0.0", + "bundled": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "bundled": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true + }, + "jsonparse": { + "version": "1.3.1", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "latest-version": { + "version": "3.1.0", + "bundled": true, + "requires": { + "package-json": "4.0.1" + } + }, + "lazy-property": { + "version": "1.0.0", + "bundled": true + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "libcipm": { + "version": "2.0.0", + "bundled": true, + "requires": { + "bin-links": "1.1.2", + "bluebird": "3.5.1", + "find-npm-prefix": "1.0.2", + "graceful-fs": "4.1.11", + "lock-verify": "2.0.2", + "npm-lifecycle": "2.0.3", + "npm-logical-tree": "1.2.1", + "npm-package-arg": "6.1.0", + "pacote": "8.1.6", + "protoduck": "5.0.0", + "read-package-json": "2.0.13", + "rimraf": "2.6.2", + "worker-farm": "1.6.0" + } + }, + "libnpmhook": { + "version": "4.0.1", + "bundled": true, + "requires": { + "figgy-pudding": "3.2.0", + "npm-registry-fetch": "3.1.1" + }, + "dependencies": { + "npm-registry-fetch": { + "version": "3.1.1", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "figgy-pudding": "3.2.0", + "lru-cache": "4.1.3", + "make-fetch-happen": "4.0.1", + "npm-package-arg": "6.1.0" + } + } + } + }, + "libnpx": { + "version": "10.2.0", + "bundled": true, + "requires": { + "dotenv": "5.0.1", + "npm-package-arg": "6.1.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "update-notifier": "2.5.0", + "which": "1.3.1", + "y18n": "4.0.0", + "yargs": "11.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lock-verify": { + "version": "2.0.2", + "bundled": true, + "requires": { + "npm-package-arg": "6.1.0", + "semver": "5.5.0" + } + }, + "lockfile": { + "version": "1.0.4", + "bundled": true, + "requires": { + "signal-exit": "3.0.2" + } + }, + "lodash._baseindexof": { + "version": "3.1.0", + "bundled": true + }, + "lodash._baseuniq": { + "version": "4.6.0", + "bundled": true, + "requires": { + "lodash._createset": "4.0.3", + "lodash._root": "3.0.1" + } + }, + "lodash._bindcallback": { + "version": "3.0.1", + "bundled": true + }, + "lodash._cacheindexof": { + "version": "3.0.2", + "bundled": true + }, + "lodash._createcache": { + "version": "3.1.2", + "bundled": true, + "requires": { + "lodash._getnative": "3.9.1" + } + }, + "lodash._createset": { + "version": "4.0.3", + "bundled": true + }, + "lodash._getnative": { + "version": "3.9.1", + "bundled": true + }, + "lodash._root": { + "version": "3.0.1", + "bundled": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "bundled": true + }, + "lodash.restparam": { + "version": "3.6.1", + "bundled": true + }, + "lodash.union": { + "version": "4.6.0", + "bundled": true + }, + "lodash.uniq": { + "version": "4.5.0", + "bundled": true + }, + "lodash.without": { + "version": "4.4.0", + "bundled": true + }, + "lowercase-keys": { + "version": "1.0.1", + "bundled": true + }, + "lru-cache": { + "version": "4.1.3", + "bundled": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "bundled": true, + "requires": { + "pify": "3.0.0" + } + }, + "make-fetch-happen": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agentkeepalive": "3.4.1", + "cacache": "11.1.0", + "http-cache-semantics": "3.8.1", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "node-fetch-npm": "2.0.2", + "promise-retry": "1.1.1", + "socks-proxy-agent": "4.0.1", + "ssri": "6.0.0" + } + }, + "meant": { + "version": "1.0.1", + "bundled": true + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "mime-db": { + "version": "1.33.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.18", + "bundled": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.3.3", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "requires": { + "minipass": "2.3.3" + } + }, + "mississippi": { + "version": "3.0.0", + "bundled": true, + "requires": { + "concat-stream": "1.6.2", + "duplexify": "3.6.0", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "3.0.0", + "pumpify": "1.5.1", + "stream-each": "1.2.2", + "through2": "2.0.3" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true + }, + "mute-stream": { + "version": "0.0.7", + "bundled": true + }, + "node-fetch-npm": { + "version": "2.0.2", + "bundled": true, + "requires": { + "encoding": "0.1.12", + "json-parse-better-errors": "1.0.2", + "safe-buffer": "5.1.2" + } + }, + "node-gyp": { + "version": "3.7.0", + "bundled": true, + "requires": { + "fstream": "1.0.11", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.5", + "request": "2.81.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.3.1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "bundled": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "semver": { + "version": "5.3.0", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + } + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "requires": { + "hosted-git-info": "2.6.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" + } + }, + "npm-audit-report": { + "version": "1.3.1", + "bundled": true, + "requires": { + "cli-table3": "0.5.0", + "console-control-strings": "1.1.0" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true + }, + "npm-cache-filename": { + "version": "1.0.2", + "bundled": true + }, + "npm-install-checks": { + "version": "3.0.0", + "bundled": true, + "requires": { + "semver": "5.5.0" + } + }, + "npm-lifecycle": { + "version": "2.0.3", + "bundled": true, + "requires": { + "byline": "5.0.0", + "graceful-fs": "4.1.11", + "node-gyp": "3.7.0", + "resolve-from": "4.0.0", + "slide": "1.1.6", + "uid-number": "0.0.6", + "umask": "1.1.0", + "which": "1.3.1" + } + }, + "npm-logical-tree": { + "version": "1.2.1", + "bundled": true + }, + "npm-package-arg": { + "version": "6.1.0", + "bundled": true, + "requires": { + "hosted-git-info": "2.6.0", + "osenv": "0.1.5", + "semver": "5.5.0", + "validate-npm-package-name": "3.0.0" + } + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npm-pick-manifest": { + "version": "2.1.0", + "bundled": true, + "requires": { + "npm-package-arg": "6.1.0", + "semver": "5.5.0" + } + }, + "npm-profile": { + "version": "3.0.2", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "make-fetch-happen": "4.0.1" + } + }, + "npm-registry-client": { + "version": "8.5.1", + "bundled": true, + "requires": { + "concat-stream": "1.6.2", + "graceful-fs": "4.1.11", + "normalize-package-data": "2.4.0", + "npm-package-arg": "6.1.0", + "npmlog": "4.1.2", + "once": "1.4.0", + "request": "2.81.0", + "retry": "0.10.1", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "slide": "1.1.6", + "ssri": "5.3.0" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "bundled": true + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, + "npm-registry-fetch": { + "version": "1.1.0", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "figgy-pudding": "2.0.1", + "lru-cache": "4.1.3", + "make-fetch-happen": "3.0.0", + "npm-package-arg": "6.1.0", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "cacache": { + "version": "10.0.4", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "chownr": "1.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.3", + "mississippi": "2.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "5.3.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" + }, + "dependencies": { + "mississippi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "concat-stream": "1.6.2", + "duplexify": "3.6.0", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "2.0.1", + "pumpify": "1.5.1", + "stream-each": "1.2.2", + "through2": "2.0.3" + } + } + } + }, + "figgy-pudding": { + "version": "2.0.1", + "bundled": true + }, + "make-fetch-happen": { + "version": "3.0.0", + "bundled": true, + "requires": { + "agentkeepalive": "3.4.1", + "cacache": "10.0.4", + "http-cache-semantics": "3.8.1", + "http-proxy-agent": "2.1.0", + "https-proxy-agent": "2.2.1", + "lru-cache": "4.1.3", + "mississippi": "3.0.0", + "node-fetch-npm": "2.0.2", + "promise-retry": "1.1.1", + "socks-proxy-agent": "3.0.1", + "ssri": "5.3.0" + } + }, + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "smart-buffer": { + "version": "1.1.15", + "bundled": true + }, + "socks": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + } + }, + "socks-proxy-agent": { + "version": "3.0.1", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "socks": "1.1.10" + } + }, + "ssri": { + "version": "5.3.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "2.0.1" + } + }, + "npm-user-validate": { + "version": "1.0.0", + "bundled": true + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "opener": { + "version": "1.4.3", + "bundled": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.2.0", + "bundled": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "package-json": { + "version": "4.0.1", + "bundled": true, + "requires": { + "got": "6.7.1", + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0", + "semver": "5.5.0" + } + }, + "pacote": { + "version": "8.1.6", + "bundled": true, + "requires": { + "bluebird": "3.5.1", + "cacache": "11.1.0", + "get-stream": "3.0.0", + "glob": "7.1.2", + "lru-cache": "4.1.3", + "make-fetch-happen": "4.0.1", + "minimatch": "3.0.4", + "minipass": "2.3.3", + "mississippi": "3.0.0", + "mkdirp": "0.5.1", + "normalize-package-data": "2.4.0", + "npm-package-arg": "6.1.0", + "npm-packlist": "1.1.10", + "npm-pick-manifest": "2.1.0", + "osenv": "0.1.5", + "promise-inflight": "1.0.1", + "promise-retry": "1.1.1", + "protoduck": "5.0.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.2", + "semver": "5.5.0", + "ssri": "6.0.0", + "tar": "4.4.4", + "unique-filename": "1.1.0", + "which": "1.3.1" + } + }, + "parallel-transform": { + "version": "1.1.0", + "bundled": true, + "requires": { + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-is-inside": { + "version": "1.0.2", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "pify": { + "version": "3.0.0", + "bundled": true + }, + "prepend-http": { + "version": "1.0.4", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "promise-inflight": { + "version": "1.0.1", + "bundled": true + }, + "promise-retry": { + "version": "1.1.1", + "bundled": true, + "requires": { + "err-code": "1.1.2", + "retry": "0.10.1" + }, + "dependencies": { + "retry": { + "version": "0.10.1", + "bundled": true + } + } + }, + "promzard": { + "version": "0.3.0", + "bundled": true, + "requires": { + "read": "1.0.7" + } + }, + "proto-list": { + "version": "1.2.4", + "bundled": true + }, + "protoduck": { + "version": "5.0.0", + "bundled": true, + "requires": { + "genfun": "4.0.1" + } + }, + "prr": { + "version": "1.0.1", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.5.1", + "bundled": true, + "requires": { + "duplexify": "3.6.0", + "inherits": "2.0.3", + "pump": "2.0.1" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qrcode-terminal": { + "version": "0.12.0", + "bundled": true + }, + "qs": { + "version": "6.4.0", + "bundled": true + }, + "query-string": { + "version": "6.1.0", + "bundled": true, + "requires": { + "decode-uri-component": "0.2.0", + "strict-uri-encode": "2.0.0" + } + }, + "qw": { + "version": "1.0.1", + "bundled": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, + "read": { + "version": "1.0.7", + "bundled": true, + "requires": { + "mute-stream": "0.0.7" + } + }, + "read-cmd-shim": { + "version": "1.0.1", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "read-installed": { + "version": "4.0.3", + "bundled": true, + "requires": { + "debuglog": "1.0.1", + "graceful-fs": "4.1.11", + "read-package-json": "2.0.13", + "readdir-scoped-modules": "1.0.2", + "semver": "5.5.0", + "slide": "1.1.6", + "util-extend": "1.0.3" + } + }, + "read-package-json": { + "version": "2.0.13", + "bundled": true, + "requires": { + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "json-parse-better-errors": "1.0.2", + "normalize-package-data": "2.4.0", + "slash": "1.0.0" + } + }, + "read-package-tree": { + "version": "5.2.1", + "bundled": true, + "requires": { + "debuglog": "1.0.1", + "dezalgo": "1.0.3", + "once": "1.4.0", + "read-package-json": "2.0.13", + "readdir-scoped-modules": "1.0.2" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "readdir-scoped-modules": { + "version": "1.0.2", + "bundled": true, + "requires": { + "debuglog": "1.0.1", + "dezalgo": "1.0.3", + "graceful-fs": "4.1.11", + "once": "1.4.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "bundled": true, + "requires": { + "rc": "1.2.7", + "safe-buffer": "5.1.2" + } + }, + "registry-url": { + "version": "3.1.0", + "bundled": true, + "requires": { + "rc": "1.2.7" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.2", + "stringstream": "0.0.6", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "resolve-from": { + "version": "4.0.0", + "bundled": true + }, + "retry": { + "version": "0.12.0", + "bundled": true + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "run-queue": { + "version": "1.0.3", + "bundled": true, + "requires": { + "aproba": "1.2.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "semver-diff": { + "version": "2.1.0", + "bundled": true, + "requires": { + "semver": "5.5.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "sha": { + "version": "2.0.1", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "readable-stream": "2.3.6" + } + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "slash": { + "version": "1.0.0", + "bundled": true + }, + "slide": { + "version": "1.1.6", + "bundled": true + }, + "smart-buffer": { + "version": "4.0.1", + "bundled": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "socks": { + "version": "2.2.0", + "bundled": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "4.0.1" + } + }, + "socks-proxy-agent": { + "version": "4.0.1", + "bundled": true, + "requires": { + "agent-base": "4.2.0", + "socks": "2.2.0" + } + }, + "sorted-object": { + "version": "2.0.1", + "bundled": true + }, + "sorted-union-stream": { + "version": "2.1.3", + "bundled": true, + "requires": { + "from2": "1.3.0", + "stream-iterate": "1.2.0" + }, + "dependencies": { + "from2": { + "version": "1.3.0", + "bundled": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "1.1.14" + } + }, + "isarray": { + "version": "0.0.1", + "bundled": true + }, + "readable-stream": { + "version": "1.1.14", + "bundled": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "bundled": true + } + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true + }, + "sshpk": { + "version": "1.14.2", + "bundled": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "ssri": { + "version": "6.0.0", + "bundled": true + }, + "stream-each": { + "version": "1.2.2", + "bundled": true, + "requires": { + "end-of-stream": "1.4.1", + "stream-shift": "1.0.0" + } + }, + "stream-iterate": { + "version": "1.2.0", + "bundled": true, + "requires": { + "readable-stream": "2.3.6", + "stream-shift": "1.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "bundled": true + }, + "strict-uri-encode": { + "version": "2.0.0", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "stringify-package": { + "version": "1.0.0", + "bundled": true + }, + "stringstream": { + "version": "0.0.6", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "supports-color": { + "version": "5.4.0", + "bundled": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "tar": { + "version": "4.4.4", + "bundled": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.3.3", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "term-size": { + "version": "1.2.0", + "bundled": true, + "requires": { + "execa": "0.7.0" + } + }, + "text-table": { + "version": "0.2.0", + "bundled": true + }, + "through": { + "version": "2.3.8", + "bundled": true + }, + "through2": { + "version": "2.0.3", + "bundled": true, + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "timed-out": { + "version": "4.0.1", + "bundled": true + }, + "tiny-relative-date": { + "version": "1.3.0", + "bundled": true + }, + "tough-cookie": { + "version": "2.3.4", + "bundled": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "bundled": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "umask": { + "version": "1.1.0", + "bundled": true + }, + "unique-filename": { + "version": "1.1.0", + "bundled": true, + "requires": { + "unique-slug": "2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "bundled": true, + "requires": { + "imurmurhash": "0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "bundled": true, + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "bundled": true + }, + "unzip-response": { + "version": "2.0.1", + "bundled": true + }, + "update-notifier": { + "version": "2.5.0", + "bundled": true, + "requires": { + "boxen": "1.3.0", + "chalk": "2.4.1", + "configstore": "3.1.2", + "import-lazy": "2.1.0", + "is-ci": "1.1.0", + "is-installed-globally": "0.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "bundled": true, + "requires": { + "prepend-http": "1.0.4" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "util-extend": { + "version": "1.0.3", + "bundled": true + }, + "uuid": { + "version": "3.3.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.3", + "bundled": true, + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "bundled": true, + "requires": { + "builtins": "1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "wcwidth": { + "version": "1.0.1", + "bundled": true, + "requires": { + "defaults": "1.0.3" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "1.0.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "widest-line": { + "version": "2.0.0", + "bundled": true, + "requires": { + "string-width": "2.1.1" + } + }, + "worker-farm": { + "version": "1.6.0", + "bundled": true, + "requires": { + "errno": "0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "2.3.0", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "bundled": true + }, + "xtend": { + "version": "4.0.1", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "11.0.0", + "bundled": true, + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" + }, + "dependencies": { + "y18n": { + "version": "3.2.1", + "bundled": true + } + } + }, + "yargs-parser": { + "version": "9.0.2", + "bundled": true, + "requires": { + "camelcase": "4.1.0" + } + } + } + }, + "npm-install-package": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz", + "integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=", + "dev": true + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "requires": { + "boolbase": "1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object-path": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", + "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "3.0.1" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.11" + } + }, + "object.entries": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", + "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.12.0", + "function-bind": "1.1.1", + "has": "1.0.2" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.12.0" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "3.0.1" + } + }, + "object.values": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", + "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.12.0", + "function-bind": "1.1.1", + "has": "1.0.2" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, @@ -11224,8 +13977,7 @@ "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "optional": true + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" }, "pseudomap": { "version": "1.0.2", diff --git a/packages/assistify-threading/server/methods/createThread.js b/packages/assistify-threading/server/methods/createThread.js index f4777af2dc828..50752274a4db7 100644 --- a/packages/assistify-threading/server/methods/createThread.js +++ b/packages/assistify-threading/server/methods/createThread.js @@ -86,7 +86,7 @@ export class ThreadBuilder { }); // filter on owner, moderators and those online (see @here-implementation) for (const user of users) { - if (!RocketChat.authz.hasRole(user.id, checkRoles)) { + if (!RocketChat.authz.hasRole(user.id, checkRoles, this._parentRoomId)) { RocketChat.models.Users.findOne({ _id: user.id, status: { diff --git a/packages/rocketchat-katex/package-lock.json b/packages/rocketchat-katex/package-lock.json index ffa8c00dc2f83..72332574d8de7 100644 --- a/packages/rocketchat-katex/package-lock.json +++ b/packages/rocketchat-katex/package-lock.json @@ -9,7 +9,7 @@ "resolved": "https://registry.npmjs.org/katex/-/katex-0.9.0.tgz", "integrity": "sha512-lp3x90LT1tDZBW2tjLheJ98wmRMRjUHwk4QpaswT9bhqoQZ+XA4cPcjcQBxgOQNwaOSt6ZeL/a6GKQ1of3LFxQ==", "requires": { - "match-at": "0.1.1" + "match-at": "^0.1.1" } }, "match-at": { From fbfa4e5323d492e1c0b20eec0e0b6b60548e8dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Fri, 10 Aug 2018 14:56:59 +0200 Subject: [PATCH 012/124] Adapt thread-created message to display the quoted message --- .../assistify-threading/lib/messageTypes/threadMessage.js | 2 +- packages/assistify-threading/server/methods/createThread.js | 4 +++- packages/rocketchat-i18n/i18n/de.i18n.json | 1 + packages/rocketchat-i18n/i18n/en.i18n.json | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/assistify-threading/lib/messageTypes/threadMessage.js b/packages/assistify-threading/lib/messageTypes/threadMessage.js index 54bbe9ec13a28..c36f2eccbf2d8 100644 --- a/packages/assistify-threading/lib/messageTypes/threadMessage.js +++ b/packages/assistify-threading/lib/messageTypes/threadMessage.js @@ -7,7 +7,7 @@ Meteor.startup(function() { message: 'thread-created', data(message) { return { - message: `Message`, + message: `"${ message.channels[0].initialMessage }"`, username: `@${ message.mentions[0].name }` }; } diff --git a/packages/assistify-threading/server/methods/createThread.js b/packages/assistify-threading/server/methods/createThread.js index 50752274a4db7..b16f312adde39 100644 --- a/packages/assistify-threading/server/methods/createThread.js +++ b/packages/assistify-threading/server/methods/createThread.js @@ -64,7 +64,8 @@ export class ThreadBuilder { }], channels: [{ _id: roomCreated._id, // Parent Room ID - name: roomCreated.name + name: roomCreated.name, + initialMessage: message.msg }] }); } @@ -87,6 +88,7 @@ export class ThreadBuilder { // filter on owner, moderators and those online (see @here-implementation) for (const user of users) { if (!RocketChat.authz.hasRole(user.id, checkRoles, this._parentRoomId)) { + // TODO: Use a mass-read-access: Filter the non-owner/moderators and use them in an $in-query. Afterwards, add them all RocketChat.models.Users.findOne({ _id: user.id, status: { diff --git a/packages/rocketchat-i18n/i18n/de.i18n.json b/packages/rocketchat-i18n/i18n/de.i18n.json index 954e2de31b8c7..3fd872683191b 100644 --- a/packages/rocketchat-i18n/i18n/de.i18n.json +++ b/packages/rocketchat-i18n/i18n/de.i18n.json @@ -2421,6 +2421,7 @@ "This_room_has_been_archived_by__username_": "Dieser Raum wurde von __username__ archiviert", "This_room_has_been_unarchived_by__username_": "Dieser Raum wurde von __username__ aus dem Archiv geholt", "Thread": "Einen neuen Thread anlegen", + "thread-created" : "__username__ hat einen neuen Thread angelegt: __message__.", "Threading_description": "Hilf dabei, die Übersicht zu behalten! Indem Du einen Thread anlegst, wird ein Unterkanal mit passenden Mitgliedern erstellt.", "Thread_select_different_parent": "- wähle einen anderen übergeordneten Kanal aus", "Thread_target_channel": "Übergeordneter Kanal oder Gruppe", diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 8b321eff8707a..9feb4db2e9b05 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -2441,8 +2441,8 @@ "This_is_a_push_test_messsage": "This is a push test message", "This_room_has_been_archived_by__username_": "This room has been archived by __username__", "This_room_has_been_unarchived_by__username_": "This room has been unarchived by __username__", - "thread-created" : "__username__ has started a new __message__ thread.", "Thread": "Create a new thread", + "thread-created" : "__username__ has started a new thread: __message__.", "Threading_description": "Help keeping an overview about what's going on! By creating a thread, a sub-channel of the one you selected is created and both are linked.", "Thread_select_different_parent": "- select a different parent channel", "Thread_target_channel": "Parent channel or group", From 4a0c5e9b807a86704ce8d45bfd75a993f8f521ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Fri, 10 Aug 2018 19:51:30 +0200 Subject: [PATCH 013/124] Fix channel attachments not being navigateable as mentions --- .../rocketchat-ui/client/views/app/room.js | 24 +++++++++++-------- server/methods/getRoomIdByNameOrId.js | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/rocketchat-ui/client/views/app/room.js b/packages/rocketchat-ui/client/views/app/room.js index c68679bc7b23c..ab48bf08c21ac 100644 --- a/packages/rocketchat-ui/client/views/app/room.js +++ b/packages/rocketchat-ui/client/views/app/room.js @@ -626,19 +626,23 @@ Template.room.events({ if (!Meteor.userId()) { return; } - const channel = $(e.currentTarget).data('channel'); - if (channel != null) { - if (RocketChat.Layout.isEmbedded()) { - fireGlobalEvent('click-mention-link', { path: FlowRouter.path('channel', { name: channel }), channel }); - } + const roomName = $(e.currentTarget).data('channel'); - FlowRouter.go('channel', { name: channel }, FlowRouter.current().queryParams); - return; - } + if (roomName) { + const room = ChatRoom.findOne({name: roomName}); + if (room) { + if (RocketChat.Layout.isEmbedded()) { + fireGlobalEvent('click-mention-link', { path: RocketChat.roomTypes.getRouteLink(room.t, { name: roomName }), roomName }); + } - const username = $(e.currentTarget).data('username'); + FlowRouter.goToRoomById(room._id); + } + return; + } else { + const username = $(e.currentTarget).data('username'); - openProfileTabOrOpenDM(e, instance, username); + openProfileTabOrOpenDM(e, instance, username); + } }, 'click .image-to-download'(event) { diff --git a/server/methods/getRoomIdByNameOrId.js b/server/methods/getRoomIdByNameOrId.js index 67f6baff54c35..e89a0efa0ab0c 100644 --- a/server/methods/getRoomIdByNameOrId.js +++ b/server/methods/getRoomIdByNameOrId.js @@ -17,7 +17,7 @@ Meteor.methods({ }); } - if (room.t !== 'c' || RocketChat.authz.hasPermission(Meteor.userId(), 'view-c-room') !== true) { + if (RocketChat.authz.hasPermission(Meteor.userId(), `view-${ room.t }-room`) !== true) { throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'getRoomIdByNameOrId' }); From 1324c37237c991787a7b35c92f06d329adb9da83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Fri, 10 Aug 2018 19:54:05 +0200 Subject: [PATCH 014/124] Add threading from context menu --- packages/assistify-threading/auth.js | 17 ++++++++ .../client/public/icons.svg | 11 +++++ .../client/views/createThreadMessageAction.js | 43 +++++++++++++++++++ .../views/creationDialog/CreateThread.html | 2 +- packages/assistify-threading/package.js | 5 ++- .../server/methods/createThread.js | 27 ++++++++---- .../server/models/MessageExtension.js | 21 +++++++++ packages/rocketchat-i18n/i18n/de.i18n.json | 3 +- packages/rocketchat-i18n/i18n/en.i18n.json | 3 +- 9 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 packages/assistify-threading/auth.js create mode 100644 packages/assistify-threading/client/public/icons.svg create mode 100644 packages/assistify-threading/client/views/createThreadMessageAction.js create mode 100644 packages/assistify-threading/server/models/MessageExtension.js diff --git a/packages/assistify-threading/auth.js b/packages/assistify-threading/auth.js new file mode 100644 index 0000000000000..6cc0f3473b5c6 --- /dev/null +++ b/packages/assistify-threading/auth.js @@ -0,0 +1,17 @@ +/* globals RocketChat */ +import { RocketChat } from 'meteor/rocketchat:lib'; + +Meteor.startup(() => { + + //Add permissions for threading + const permissions = [ + { _id: 'start-thread', roles: ['admin', 'user', 'expert', 'guest'] }, + { _id: 'start-thread-other-user', roles: ['admin', 'user', 'expert', 'owner'] } + ]; + + for (const permission of permissions) { + if (!RocketChat.models.Permissions.findOneById(permission._id)) { + RocketChat.models.Permissions.upsert(permission._id, { $set: permission }); + } + } +}); diff --git a/packages/assistify-threading/client/public/icons.svg b/packages/assistify-threading/client/public/icons.svg new file mode 100644 index 0000000000000..25003ce69f3b6 --- /dev/null +++ b/packages/assistify-threading/client/public/icons.svg @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/packages/assistify-threading/client/views/createThreadMessageAction.js b/packages/assistify-threading/client/views/createThreadMessageAction.js new file mode 100644 index 0000000000000..00d354b997069 --- /dev/null +++ b/packages/assistify-threading/client/views/createThreadMessageAction.js @@ -0,0 +1,43 @@ +import {RocketChat} from 'meteor/rocketchat:lib'; +import {FlowRouter} from 'meteor/kadira:flow-router'; +import {ReactiveVar} from 'meteor/reactive-var'; + +Meteor.startup(function() { + const instance = this; + instance.room = new ReactiveVar(''); + RocketChat.MessageAction.addButton({ + id: 'start-thread', + icon: 'thread', + label: 'Thread_start', + context: ['message', 'message-mobile'], + action() { + const message = this._arguments[1]; + Meteor.call('createThreadFromMessage', message, function(error, result) { + if (result) { + // remove the hidden message from the UI - the message list is not reactive + Tracker.nonreactive(function() { + ChatMessage.remove({ + _id: message._id, + 'u._id': Meteor.userId() + }); + }); + + // navigate to the newly created room + FlowRouter.goToRoomById(result.rid); + } + }); + }, + condition(message) { + if (RocketChat.models.Subscriptions.findOne({rid: message.rid}) == null) { + return false; + } + if (message.u._id !== Meteor.userId()) { + return RocketChat.authz.hasAtLeastOnePermission('start-thread-other-user'); + } else { + return RocketChat.authz.hasAtLeastOnePermission('start-thread'); + } + }, + order: 0, + group: 'menu' + }); +}); diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.html b/packages/assistify-threading/client/views/creationDialog/CreateThread.html index f641d73952e86..8a16c87333fda 100644 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.html +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.html @@ -6,7 +6,7 @@
-

{{_ "Thread"}}

+

{{_ "Threading_title"}}

{{_ "Threading_description"}}

diff --git a/packages/assistify-threading/package.js b/packages/assistify-threading/package.js index da650a9398147..491d0f7f36f3d 100644 --- a/packages/assistify-threading/package.js +++ b/packages/assistify-threading/package.js @@ -16,6 +16,7 @@ Package.onUse(function(api) { // api.use('meteorhacks:inject-initial'); //for provisioning of svg-icons api.addFiles('config.js', 'server'); + api.addFiles('auth.js', 'server'); api.addFiles('lib/messageTypes/threadMessage.js'); // TODO: Decide what to do with the rendered message types. They are less usable on mobile,but provide good experience on browser. // Libraries @@ -31,7 +32,7 @@ Package.onUse(function(api) { // api.addFiles('server/migrations.js', 'server'); // UI artifacts which are pre-processed or packaged by the server - // api.addAssets('client/public/icons.svg', 'server'); + api.addAssets('client/public/icons.svg', 'server'); ///////// Client @@ -44,7 +45,7 @@ Package.onUse(function(api) { api.addFiles('client/views/creationDialog/ChannelNotFound.js', 'client'); api.addFiles('client/views/creationDialog/ChannelSelection.html', 'client'); // TODO: add wordcloud - but when doing this, ensure the sizes are based on the member-count (non-linear!) api.addFiles('client/views/creationDialog/ChannelSelection.js', 'client'); - // api.addFiles('client/views/messageActions/ThreadMessageAction.js', 'client'); // TODO: Re-add + api.addFiles('client/views/createThreadMessageAction.js', 'client'); //styling api.addFiles('client/public/stylesheets/threading.css', 'client'); diff --git a/packages/assistify-threading/server/methods/createThread.js b/packages/assistify-threading/server/methods/createThread.js index b16f312adde39..29dee8addf90f 100644 --- a/packages/assistify-threading/server/methods/createThread.js +++ b/packages/assistify-threading/server/methods/createThread.js @@ -1,6 +1,7 @@ /* UserRoles RoomRoles*/ -import {RocketChat} from 'meteor/rocketchat:lib'; -import {FlowRouter} from 'meteor/kadira:flow-router'; +import { RocketChat } from 'meteor/rocketchat:lib'; +import { FlowRouter } from 'meteor/kadira:flow-router'; +import { Meteor } from 'meteor/meteor'; /* * When a message is eligible to be answered as a independent question then it can be threaded into a new channel. @@ -43,12 +44,12 @@ export class ThreadBuilder { attachments.forEach(attachment => attachment.ts = attachment.ts ? attachment.ts.toISOString() : '' ); - const newMessage = {_id: Random.id(), rid: room.rid, msg: message, attachments, channels, mentions}; + const newMessage = { _id: Random.id(), rid: room.rid, msg: message, attachments, channels, mentions }; return RocketChat.sendMessage(user, newMessage, room); } _getMessageUrl(msgId) { - return FlowRouter.path('message', {id: msgId}); + return FlowRouter.path('message', { id: msgId }); } _linkMessages(roomCreated, parentRoom, message) { @@ -109,14 +110,14 @@ export class ThreadBuilder { const parentRoom = ThreadBuilder.getRoom(this._parentRoomId); // Generate RoomName for xthe new room to be created. this.name = `${ parentRoom.name }-${ ThreadBuilder.getNextId() }`; - const roomCreateResult = RocketChat.createRoom(parentRoom.t, this.name, Meteor.user() && Meteor.user().username, this._getMembers(), false, {parentRoomId: this._parentRoomId}); + const threadRoom = RocketChat.createRoom(parentRoom.t, this.name, Meteor.user() && Meteor.user().username, this._getMembers(), false, { parentRoomId: this._parentRoomId }); if (parentRoom.name) { - RocketChat.saveRoomTopic(roomCreateResult.rid, parentRoom.name, Meteor.user()); + RocketChat.saveRoomTopic(threadRoom.rid, parentRoom.name, Meteor.user()); } // Create messages in the newly created thread and it's parent which link the two rooms - const room = RocketChat.models.Rooms.findOneById(roomCreateResult.rid); + const room = RocketChat.models.Rooms.findOneById(threadRoom.rid); if (room && parentRoom) { // Post message const message = this._postMessage( @@ -129,7 +130,7 @@ export class ThreadBuilder { this._linkMessages(room, parentRoom, message); } - return roomCreateResult; + return threadRoom; } } @@ -137,10 +138,18 @@ export class ThreadBuilder { Meteor.methods({ createThread(parentRoomId, openingQuestion) { if (!Meteor.userId()) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', {method: 'ThreadCreation'}); + throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'ThreadCreation' }); } return new ThreadBuilder(parentRoomId, openingQuestion).create(); + }, + createThreadFromMessage(message) { + const thread = Meteor.call('createThread', message.rid, message); + if (thread) { + //remove the original message from the display + RocketChat.models.Messages.setHiddenById(message._id); + return thread; + } } }); diff --git a/packages/assistify-threading/server/models/MessageExtension.js b/packages/assistify-threading/server/models/MessageExtension.js new file mode 100644 index 0000000000000..49232531fbd02 --- /dev/null +++ b/packages/assistify-threading/server/models/MessageExtension.js @@ -0,0 +1,21 @@ +Object.assign(RocketChat.models.Messages, { + //Update + updateMsgWithThreadMessage(type, _id, message, user, extraData) { + const query = {_id}; + const update = { + $set: { + msg: message, + t: type, + editedAt: new Date(), + editedBy: { + _id: user._id, + username: user.username + } + } + }; + Object.assign(update.$set, extraData); + return this.update(query, update); + } +}); + + diff --git a/packages/rocketchat-i18n/i18n/de.i18n.json b/packages/rocketchat-i18n/i18n/de.i18n.json index 3fd872683191b..90b4a2c2f4291 100644 --- a/packages/rocketchat-i18n/i18n/de.i18n.json +++ b/packages/rocketchat-i18n/i18n/de.i18n.json @@ -2420,7 +2420,8 @@ "This_is_a_push_test_messsage": "Dies ist eine Test-Push-Nachricht", "This_room_has_been_archived_by__username_": "Dieser Raum wurde von __username__ archiviert", "This_room_has_been_unarchived_by__username_": "Dieser Raum wurde von __username__ aus dem Archiv geholt", - "Thread": "Einen neuen Thread anlegen", + "Threading_title": "Einen neuen Thread anlegen", + "Thread_start": "Thread starten", "thread-created" : "__username__ hat einen neuen Thread angelegt: __message__.", "Threading_description": "Hilf dabei, die Übersicht zu behalten! Indem Du einen Thread anlegst, wird ein Unterkanal mit passenden Mitgliedern erstellt.", "Thread_select_different_parent": "- wähle einen anderen übergeordneten Kanal aus", diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 9feb4db2e9b05..a1d4b8b35a188 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -2441,7 +2441,8 @@ "This_is_a_push_test_messsage": "This is a push test message", "This_room_has_been_archived_by__username_": "This room has been archived by __username__", "This_room_has_been_unarchived_by__username_": "This room has been unarchived by __username__", - "Thread": "Create a new thread", + "Threading_title": "Create a new thread", + "Thread_start": "Start a thread", "thread-created" : "__username__ has started a new thread: __message__.", "Threading_description": "Help keeping an overview about what's going on! By creating a thread, a sub-channel of the one you selected is created and both are linked.", "Thread_select_different_parent": "- select a different parent channel", From 66e3f8e6d2d58be9652298eb8dbe4fbb17fa8187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Fri, 10 Aug 2018 23:19:28 +0200 Subject: [PATCH 015/124] Add icon for threading --- packages/assistify-threading/package.js | 4 ++-- packages/assistify-threading/server/inject.js | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 packages/assistify-threading/server/inject.js diff --git a/packages/assistify-threading/package.js b/packages/assistify-threading/package.js index 491d0f7f36f3d..d92500040c6ff 100644 --- a/packages/assistify-threading/package.js +++ b/packages/assistify-threading/package.js @@ -13,14 +13,14 @@ Package.onUse(function(api) { api.use(['ecmascript']); api.use('rocketchat:authorization'); //In order to create custom permissions api.use('templating', 'client'); - // api.use('meteorhacks:inject-initial'); //for provisioning of svg-icons + api.use('meteorhacks:inject-initial'); //for provisioning of svg-icons api.addFiles('config.js', 'server'); api.addFiles('auth.js', 'server'); api.addFiles('lib/messageTypes/threadMessage.js'); // TODO: Decide what to do with the rendered message types. They are less usable on mobile,but provide good experience on browser. // Libraries - // api.addFiles('server/inject.js', 'server'); + api.addFiles('server/inject.js', 'server'); //Methods api.addFiles('server/methods/createThread.js', 'server'); diff --git a/packages/assistify-threading/server/inject.js b/packages/assistify-threading/server/inject.js new file mode 100644 index 0000000000000..b16cbc6087e87 --- /dev/null +++ b/packages/assistify-threading/server/inject.js @@ -0,0 +1,2 @@ +/* globals Inject */ +Inject.rawBody('custom-icons', Assets.getText('client/public/icons.svg')); From adf12549842464674aedbf58f0a916987ce348b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Fri, 10 Aug 2018 23:33:35 +0200 Subject: [PATCH 016/124] Support renamed rooms in thread message --- packages/assistify-threading/lib/messageTypes/threadMessage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/assistify-threading/lib/messageTypes/threadMessage.js b/packages/assistify-threading/lib/messageTypes/threadMessage.js index c36f2eccbf2d8..ea1a5c0ae59e4 100644 --- a/packages/assistify-threading/lib/messageTypes/threadMessage.js +++ b/packages/assistify-threading/lib/messageTypes/threadMessage.js @@ -7,7 +7,7 @@ Meteor.startup(function() { message: 'thread-created', data(message) { return { - message: `"${ message.channels[0].initialMessage }"`, + message: `"${ message.channels[0].initialMessage }"`, username: `@${ message.mentions[0].name }` }; } From ee22f80373b1950df1c29f12c8c2cf7a4e936864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Fri, 10 Aug 2018 23:34:22 +0200 Subject: [PATCH 017/124] Support usage of channel-ID in mentions for renaming-safe linking if necessary --- packages/rocketchat-ui/client/views/app/room.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/rocketchat-ui/client/views/app/room.js b/packages/rocketchat-ui/client/views/app/room.js index ab48bf08c21ac..55419cce6190d 100644 --- a/packages/rocketchat-ui/client/views/app/room.js +++ b/packages/rocketchat-ui/client/views/app/room.js @@ -626,13 +626,13 @@ Template.room.events({ if (!Meteor.userId()) { return; } - const roomName = $(e.currentTarget).data('channel'); + const roomNameOrId = $(e.currentTarget).data('channel'); - if (roomName) { - const room = ChatRoom.findOne({name: roomName}); + if (roomNameOrId) { + const room = ChatRoom.findOne({name: roomNameOrId}) || ChatRoom.findOne({_id: roomNameOrId}); if (room) { if (RocketChat.Layout.isEmbedded()) { - fireGlobalEvent('click-mention-link', { path: RocketChat.roomTypes.getRouteLink(room.t, { name: roomName }), roomName }); + fireGlobalEvent('click-mention-link', { path: RocketChat.roomTypes.getRouteLink(room.t, { name: room.name }), roomNameOrId }); } FlowRouter.goToRoomById(room._id); From eac4147648266995b72e8cf67a8755a435b66248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Sat, 11 Aug 2018 00:45:10 +0200 Subject: [PATCH 018/124] Move threading setting to separate group to allow stable automated tests --- packages/assistify-threading/config.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/assistify-threading/config.js b/packages/assistify-threading/config.js index 0da4f7d04d682..461551ce48d16 100644 --- a/packages/assistify-threading/config.js +++ b/packages/assistify-threading/config.js @@ -1,28 +1,28 @@ Meteor.startup(() => { + RocketChat.settings.addGroup('Threading'); + RocketChat.settings.add('Thread_Count', 1, { - group: 'General', + group: 'Threading', i18nLabel: 'Thread_count', type: 'int', - public: true, - section: 'General' + public: true }); RocketChat.settings.add('Select_Parent', false, { - group: 'General', + group: 'Threading', i18nLabel: 'Select_Parent', type: 'boolean', - public: true, - section: 'General' + public: true }); - RocketChat.settings.add('Parent_Channel', 'general', { - group: 'General', + + RocketChat.settings.add('Parent_Channel', '', { + group: 'Threading', i18nLabel: 'Parent_Channel', type: 'select', - values: [{ - key: 'general', - i18nLabel: 'General' + values: [{ // TODO: generate select based on rooms available + key: 'Threading', + i18nLabel: 'Threading' }], public: true, - section: 'General', enableQuery: { _id: 'Select_Parent', value : false } }); }); From ed10759f4e333ed76ec33ccc02d08f9a7105e712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Mon, 13 Aug 2018 07:59:37 +0200 Subject: [PATCH 019/124] Adapt circle-ci configuration for Assistify --- .circleci/config.yml | 72 ++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 55c71b9fd7eb3..2f265a3b522ce 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -285,27 +285,27 @@ jobs: echo "Build official Docker image" cp ~/repo/.docker/Dockerfile . - docker build -t rocketchat/rocket.chat:$CIRCLE_TAG . - docker push rocketchat/rocket.chat:$CIRCLE_TAG - - echo "Build preview Docker image" - cp ~/repo/.docker-mongo/Dockerfile . - cp ~/repo/.docker-mongo/entrypoint.sh . - docker build -t rocketchat/rocket.chat.preview:$CIRCLE_TAG . - docker push rocketchat/rocket.chat.preview:$CIRCLE_TAG - - if echo "$CIRCLE_TAG" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' ; then - docker tag rocketchat/rocket.chat:$CIRCLE_TAG rocketchat/rocket.chat:latest - docker push rocketchat/rocket.chat:latest - - docker tag rocketchat/rocket.chat.preview:$CIRCLE_TAG rocketchat/rocket.chat.preview:latest - docker push rocketchat/rocket.chat.preview:latest - elif echo "$CIRCLE_TAG" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$' ; then - docker tag rocketchat/rocket.chat:$CIRCLE_TAG rocketchat/rocket.chat:release-candidate - docker push rocketchat/rocket.chat:release-candidate - - docker tag rocketchat/rocket.chat.preview:$CIRCLE_TAG rocketchat/rocket.chat.preview:release-candidate - docker push rocketchat/rocket.chat.preview:release-candidate + docker build -t assistify/chat:$CIRCLE_TAG . + docker push assistify/chat:$CIRCLE_TAG + + # echo "Build preview Docker image" + # cp ~/repo/.docker-mongo/Dockerfile . + # cp ~/repo/.docker-mongo/entrypoint.sh . + # docker build -t assistify/chat.preview:$CIRCLE_TAG . + # docker push assistify/chat.preview:$CIRCLE_TAG + + if echo "$CIRCLE_TAG" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]-[0-9]+\.[0-9]+\.[0-9]+$' ; then + docker tag assistify/chat:$CIRCLE_TAG assistify/chat:latest + docker push assistify/chat:latest + + docker tag assistify/chat.preview:$CIRCLE_TAG assistify/chat.preview:latest + docker push assistify/chat.preview:latest + elif echo "$CIRCLE_TAG" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]-[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$' ; then + docker tag assistify/chat:$CIRCLE_TAG assistify/chat:release-candidate + docker push assistify/chat:release-candidate + + docker tag assistify/chat.preview:$CIRCLE_TAG assistify/chat.preview:release-candidate + docker push assistify/chat.preview:release-candidate fi exit 0 @@ -316,14 +316,14 @@ jobs: echo "Build official Docker image" cp ~/repo/.docker/Dockerfile . - docker build -t rocketchat/rocket.chat:develop . - docker push rocketchat/rocket.chat:develop + docker build -t assistify/chat:develop . + docker push assistify/chat:develop - echo "Build preview Docker image" - cp ~/repo/.docker-mongo/Dockerfile . - cp ~/repo/.docker-mongo/entrypoint.sh . - docker build -t rocketchat/rocket.chat.preview:develop . - docker push rocketchat/rocket.chat.preview:develop + # echo "Build preview Docker image" + # cp ~/repo/.docker-mongo/Dockerfile . + # cp ~/repo/.docker-mongo/entrypoint.sh . + # docker build -t assistify/chat.preview:develop . + # docker push assistify/chat.preview:develop exit 0 fi; @@ -358,14 +358,14 @@ jobs: echo "Build official Docker image" cp ~/repo/.docker/Dockerfile . - docker build -t rocketchat/rocket.chat:pr-$CIRCLE_PR_NUMBER . - docker push rocketchat/rocket.chat:pr-$CIRCLE_PR_NUMBER - - echo "Build preview Docker image" - cp ~/repo/.docker-mongo/Dockerfile . - cp ~/repo/.docker-mongo/entrypoint.sh . - docker build -t rocketchat/rocket.chat.preview:pr-$CIRCLE_PR_NUMBER . - docker push rocketchat/rocket.chat.preview:pr-$CIRCLE_PR_NUMBER + docker build -t assistify/chat:pr-$CIRCLE_PR_NUMBER . + docker push assistify/chat:pr-$CIRCLE_PR_NUMBER + + # echo "Build preview Docker image" + # cp ~/repo/.docker-mongo/Dockerfile . + # cp ~/repo/.docker-mongo/entrypoint.sh . + # docker build -t assistify/chat.preview:pr-$CIRCLE_PR_NUMBER . + # docker push assistify/chat.preview:pr-$CIRCLE_PR_NUMBER workflows: version: 2 From 8e1fbbff46b679a6865b1710217f2def2ff773ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Mon, 13 Aug 2018 13:57:31 +0200 Subject: [PATCH 020/124] Verticall align thread creation on home screen --- .../client/public/stylesheets/threading.css | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/assistify-threading/client/public/stylesheets/threading.css b/packages/assistify-threading/client/public/stylesheets/threading.css index 064b53cab10cc..2d0ad8431eabe 100644 --- a/packages/assistify-threading/client/public/stylesheets/threading.css +++ b/packages/assistify-threading/client/public/stylesheets/threading.css @@ -1,9 +1,5 @@ -.create-thread { - margin-top: 15%; - - max-width: 100%; - - padding: 0.25rem 2rem; +.create-thread .create-channel__title { + padding: 25% 0 1rem; } .create-thread header.create-channel__header { From 41ee70b37822be2c3e1d8857a34c01c0e153fa18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Mon, 13 Aug 2018 13:57:49 +0200 Subject: [PATCH 021/124] Fix book-icon for wordcloud --- .../client/views/creationDialog/CreateThread.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.js b/packages/assistify-threading/client/views/creationDialog/CreateThread.js index fc61e145f9cc1..8050da26243aa 100755 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.js +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.js @@ -10,7 +10,7 @@ const acEvents = { }, 'click .rc-input__icon-svg--book-alt'(e, t) { e.preventDefault(); - t.channelSelectionEnabled.set(true); + t.showChannelSelection.set(true); }, 'click #more-topics'(e, t) { e.preventDefault(); From ab5b300f03d7b0774d36f017c4ce45a1b3da1db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Tue, 14 Aug 2018 11:22:36 +0200 Subject: [PATCH 022/124] Provide back button from wordcloud --- .../creationDialog/ChannelSelection.html | 14 ++++++++--- .../views/creationDialog/ChannelSelection.js | 6 +++-- .../views/creationDialog/CreateThread.html | 4 +++- .../views/creationDialog/CreateThread.js | 24 +++++++++++++------ .../server/methods/getParentChannelList.js | 11 +++++++-- 5 files changed, 44 insertions(+), 15 deletions(-) diff --git a/packages/assistify-threading/client/views/creationDialog/ChannelSelection.html b/packages/assistify-threading/client/views/creationDialog/ChannelSelection.html index 54a9190638415..bd0f0a4108697 100644 --- a/packages/assistify-threading/client/views/creationDialog/ChannelSelection.html +++ b/packages/assistify-threading/client/views/creationDialog/ChannelSelection.html @@ -1,5 +1,13 @@ \ No newline at end of file + diff --git a/packages/assistify-threading/client/views/creationDialog/ChannelSelection.js b/packages/assistify-threading/client/views/creationDialog/ChannelSelection.js index 96640e8d22643..e784b6bf292b5 100644 --- a/packages/assistify-threading/client/views/creationDialog/ChannelSelection.js +++ b/packages/assistify-threading/client/views/creationDialog/ChannelSelection.js @@ -11,11 +11,13 @@ function drawWords() { } Template.ChannelSelection.events({ -// To Do + 'click .full-modal__back-button'(event, instance) { + instance.data.hideMe(); + } }); Template.ChannelSelection.helpers({ -// To Do + // To Do }); Template.ChannelSelection.onRendered(function() { diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.html b/packages/assistify-threading/client/views/creationDialog/CreateThread.html index 8a16c87333fda..eae5ffa3c851e 100644 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.html +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.html @@ -60,7 +60,9 @@

{{_ "Threading_title"}}

- {{else}} {{> ChannelSelection properties=getWordcloudProperties}} {{/unless}} + {{else}} + {{> ChannelSelection properties=getWordcloudProperties hideMe=hideWordcloud}} + {{/unless}} diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.js b/packages/assistify-threading/client/views/creationDialog/CreateThread.js index 8050da26243aa..e61a4ac646e58 100755 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.js +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.js @@ -1,7 +1,7 @@ /* globals TAPi18n, AutoComplete */ /* globals _ */ -import {FlowRouter} from 'meteor/kadira:flow-router'; -import {ReactiveVar} from 'meteor/reactive-var'; +import { FlowRouter } from 'meteor/kadira:flow-router'; +import { ReactiveVar } from 'meteor/reactive-var'; const acEvents = { 'click .rc-popup-list__item'(e, t) { @@ -104,14 +104,14 @@ Template.CreateThread.helpers({ const instance = Template.instance(); const parentChannels = instance.parentChannelsList.get(); - function getRandomArbitrary(min, max) { - return Math.random() * (max - min) + min; + function getSize(channel) { + return Math.random() * (4 - 10) + 4; } function getWordList() { const list = []; parentChannels.forEach(function(parentChannel) { - list.push([parentChannel.name, getRandomArbitrary(4, 10)]); + list.push([parentChannel.name, getSize(parentChannel)]); }); return list; } @@ -154,6 +154,16 @@ Template.CreateThread.helpers({ hover: onWordHover() //setCanvas: getCanvas }; + }, + + hideWordcloud() { + const instance = Template.instance(); + + const hideMe = function() { + instance.showChannelSelection.set(false); + }; + + return hideMe; } }); @@ -223,7 +233,7 @@ Template.CreateThread.onRendered(function() { instance.ac.element = parentChannelElement; instance.ac.$element = $(instance.ac.element); - instance.ac.$element.on('autocompleteselect', function(e, {item}) { + instance.ac.$element.on('autocompleteselect', function(e, { item }) { instance.parentChannel.set(item.name); $('input[name="parentChannel"]').val(item.name); instance.debounceValidateParentChannel(item.name); @@ -242,7 +252,7 @@ Template.CreateThread.onRendered(function() { instance.ac.element = this.find('#parentChannel-search'); instance.ac.$element = $(instance.ac.element); $('input[name="parentChannel-search"]').val(parentChannel.name); // copy the selected value to screen field - instance.ac.$element.on('autocompleteselect', function(e, {item}) { + instance.ac.$element.on('autocompleteselect', function(e, { item }) { instance.parentChannel.set(item.name); $('input[name="parentChannel-search"]').val(item.name); instance.debounceValidateParentChannel(item.name); diff --git a/packages/assistify-threading/server/methods/getParentChannelList.js b/packages/assistify-threading/server/methods/getParentChannelList.js index 3637bbd8bcd68..3612fe0a2e2b5 100644 --- a/packages/assistify-threading/server/methods/getParentChannelList.js +++ b/packages/assistify-threading/server/methods/getParentChannelList.js @@ -1,4 +1,3 @@ -/* globals _ */ Meteor.methods({ 'getParentChannelList'({sort, limit}) { this.unblock(); @@ -14,6 +13,8 @@ Meteor.methods({ const options = { fields: { name: 1, + usersCount: 1, + msgs: 1, t: 1 }, sort: { @@ -21,7 +22,7 @@ Meteor.methods({ } }; - if (_.isNumber(limit)) { + if (Number.isInteger(limit)) { options.limit = limit; } @@ -36,6 +37,12 @@ Meteor.methods({ options.sort = { msgs: -1 }; + break; + case 'members': + options.sort = { + usersCount: -1 + }; + break; } } From 731f33eb779079f77f7c06d785813e6f60ccdf98 Mon Sep 17 00:00:00 2001 From: vickyokrm Date: Tue, 14 Aug 2018 11:24:20 +0200 Subject: [PATCH 023/124] show all channels in thread settings --- packages/assistify-threading/config.js | 27 +++++++++++++++---- .../server/methods/getParentChannelList.js | 6 ----- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/packages/assistify-threading/config.js b/packages/assistify-threading/config.js index 461551ce48d16..0519078d1c5e8 100644 --- a/packages/assistify-threading/config.js +++ b/packages/assistify-threading/config.js @@ -1,3 +1,21 @@ +function getParentChannels() { + const result = Meteor.call('getParentChannelList', {sort: 'name'}); + if (!result) { + return [{ + key: 'general', + i18nLabel: 'general' + }]; + } + return result.channels.map((channel) => { + if (channel.name !== null) { + return { + key: channel.name, + i18nLabel: channel.name + }; + } + }); +} + Meteor.startup(() => { RocketChat.settings.addGroup('Threading'); @@ -18,11 +36,10 @@ Meteor.startup(() => { group: 'Threading', i18nLabel: 'Parent_Channel', type: 'select', - values: [{ // TODO: generate select based on rooms available - key: 'Threading', - i18nLabel: 'Threading' - }], + values: getParentChannels(), // load parent channels public: true, - enableQuery: { _id: 'Select_Parent', value : false } + enableQuery: {_id: 'Select_Parent', value: true} }); }); + + diff --git a/packages/assistify-threading/server/methods/getParentChannelList.js b/packages/assistify-threading/server/methods/getParentChannelList.js index 3637bbd8bcd68..57bd37e541c07 100644 --- a/packages/assistify-threading/server/methods/getParentChannelList.js +++ b/packages/assistify-threading/server/methods/getParentChannelList.js @@ -5,12 +5,6 @@ Meteor.methods({ check(sort, Match.Optional(String)); check(limit, Match.Optional(Number)); - if (!Meteor.userId()) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { - method: 'requestsList' - }); - } - const options = { fields: { name: 1, From a53bfba2f582cb1960d0ba9c2f53d87f9fdd800c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Tue, 14 Aug 2018 11:26:34 +0200 Subject: [PATCH 024/124] Don't show wordcloud for the time being --- .../client/views/creationDialog/CreateThread.html | 4 +++- .../client/views/creationDialog/CreateThread.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.html b/packages/assistify-threading/client/views/creationDialog/CreateThread.html index eae5ffa3c851e..1190623265064 100644 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.html +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.html @@ -36,11 +36,13 @@

{{_ "Threading_title"}}

-
+ + +
{{#unless autocomplete 'isShowing'}} {{#if parentChannel}} {{#if parentChannelError}} {{> CreateThreadInputError text=parentChannelError}} {{/if}} {{/if}} {{/unless}} {{#with config}} {{#if autocomplete 'isShowing'}} diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.js b/packages/assistify-threading/client/views/creationDialog/CreateThread.js index e61a4ac646e58..d97a11b0da657 100755 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.js +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.js @@ -104,7 +104,7 @@ Template.CreateThread.helpers({ const instance = Template.instance(); const parentChannels = instance.parentChannelsList.get(); - function getSize(channel) { + function getSize(/*channel*/) { return Math.random() * (4 - 10) + 4; } From bb64b24f6856b61fe362acfccafa22f5a6599bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Tue, 14 Aug 2018 13:07:47 +0200 Subject: [PATCH 025/124] update circleci config to our tagnames --- .circleci/config.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2f265a3b522ce..2dcf6675e78da 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -374,19 +374,19 @@ workflows: - build: filters: tags: - only: /^[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$/ + only: /^v[0-9]+\.[0-9]+\.[0-9]-[0-9]+\.[0-9]+\.[0-9]+$/ - test-with-oplog: requires: - build filters: tags: - only: /^[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$/ + only: /^v[0-9]+\.[0-9]+\.[0-9]-[0-9]+\.[0-9]+\.[0-9]+$/ - test-without-oplog: requires: - build filters: tags: - only: /^[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$/ + only: /^v[0-9]+\.[0-9]+\.[0-9]-[0-9]+\.[0-9]+\.[0-9]+$/ - deploy: requires: - test-with-oplog @@ -395,7 +395,7 @@ workflows: branches: only: develop tags: - only: /^[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$/ + only: /^v[0-9]+\.[0-9]+\.[0-9]-[0-9]+\.[0-9]+\.[0-9]+$/ - image-build: requires: - deploy @@ -403,7 +403,7 @@ workflows: branches: only: develop tags: - only: /^[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$/ + only: /^v[0-9]+\.[0-9]+\.[0-9]-[0-9]+\.[0-9]+\.[0-9]+$/ - hold: type: approval requires: @@ -412,7 +412,7 @@ workflows: branches: ignore: develop tags: - only: /^[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$/ + only: /^v[0-9]+\.[0-9]+\.[0-9]-[0-9]+\.[0-9]+\.[0-9]+$/ - pr-image-build: requires: - hold @@ -420,5 +420,5 @@ workflows: branches: ignore: develop tags: - only: /^[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$/ + only: /^v[0-9]+\.[0-9]+\.[0-9]-[0-9]+\.[0-9]+\.[0-9]+$/ From 11c4005db28b1ecc59beec8b8f46ad8e15a6dd19 Mon Sep 17 00:00:00 2001 From: vickyokrm Date: Tue, 14 Aug 2018 14:13:24 +0200 Subject: [PATCH 026/124] Fix autocomplete for parent channel --- .../client/views/creationDialog/CreateThread.html | 5 ++--- .../client/views/creationDialog/CreateThread.js | 8 +++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.html b/packages/assistify-threading/client/views/creationDialog/CreateThread.html index 1190623265064..071f541ea1055 100644 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.html +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.html @@ -24,8 +24,8 @@

{{_ "Threading_title"}}

{{ targetChannelText }} {{_ "Thread_select_different_parent"}} - {{else}} -
+ {{/unless}} +
diff --git a/packages/rocketchat-ui-account/client/accountPreferences.js b/packages/rocketchat-ui-account/client/accountPreferences.js index 23972e48cb92e..a4eb2059b2422 100644 --- a/packages/rocketchat-ui-account/client/accountPreferences.js +++ b/packages/rocketchat-ui-account/client/accountPreferences.js @@ -160,6 +160,7 @@ Template.accountPreferences.onCreated(function() { data.desktopNotifications = $('#desktopNotifications').find('select').val(); data.mobileNotifications = $('#mobileNotifications').find('select').val(); data.unreadAlert = JSON.parse($('#unreadAlert').find('input:checked').val()); + data.sidebarShowThreads = JSON.parse($('#sidebarShowThreads').find('input:checked').val()); data.notificationsSoundVolume = parseInt($('#notificationsSoundVolume').val()); data.roomCounterSidebar = JSON.parse($('#roomCounterSidebar').find('input:checked').val()); data.highlights = _.compact(_.map($('[name=highlights]').val().split(/,|\n/), function(e) { diff --git a/packages/rocketchat-ui-sidenav/client/roomList.js b/packages/rocketchat-ui-sidenav/client/roomList.js index 928d6683aca06..c55b4678fc3ac 100644 --- a/packages/rocketchat-ui-sidenav/client/roomList.js +++ b/packages/rocketchat-ui-sidenav/client/roomList.js @@ -45,6 +45,11 @@ Template.roomList.helpers({ types = ['c', 'p', 'd']; } + if (this.identifier === 'thread') { + types = ['c', 'p', 'd']; + query.parentRoomId = {$exists: true}; + } + if (this.identifier === 'unread' || this.identifier === 'tokens') { types = ['c', 'p']; } @@ -55,6 +60,11 @@ Template.roomList.helpers({ query.tokens = { $exists: true }; } + // if we display threads as a separate group, we should hide them from the other lists + if (RocketChat.getUserPreference(user, 'sidebarShowThreads')) { + query.parentRoomId = {$exists: false}; + } + if (RocketChat.getUserPreference(user, 'sidebarShowUnread')) { query.$or = [ {alert: {$ne: true}}, diff --git a/server/publications/subscription.js b/server/publications/subscription.js index 2ab526a6775b0..44a3b16e134b8 100644 --- a/server/publications/subscription.js +++ b/server/publications/subscription.js @@ -12,6 +12,7 @@ const fields = { alert: 1, roles: 1, unread: 1, + parentRoomId: 1, userMentions: 1, groupMentions: 1, archived: 1, From dc6bcdc1c27f01ebcb0579c97c1571ba992aabd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Wed, 15 Aug 2018 00:18:01 +0200 Subject: [PATCH 028/124] Explicit route for create-thread --- packages/assistify-threading/client/router.js | 12 ++++++++++++ .../assistify-threading/client/views/threadList.js | 4 +++- packages/assistify-threading/package.js | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 packages/assistify-threading/client/router.js diff --git a/packages/assistify-threading/client/router.js b/packages/assistify-threading/client/router.js new file mode 100644 index 0000000000000..fd751e23aab4f --- /dev/null +++ b/packages/assistify-threading/client/router.js @@ -0,0 +1,12 @@ +import { FlowRouter } from 'meteor/kadira:flow-router'; + +FlowRouter.route('/create-thread', { + name: 'create-thread', + + action() { + return BlazeLayout.render('main', {center: 'CreateThread'}); + }, + triggersExit: [function() { + $('.main-content').addClass('rc-old'); + }] +}); diff --git a/packages/assistify-threading/client/views/threadList.js b/packages/assistify-threading/client/views/threadList.js index 1ee9e3e57757c..670a97edd0482 100644 --- a/packages/assistify-threading/client/views/threadList.js +++ b/packages/assistify-threading/client/views/threadList.js @@ -1,6 +1,8 @@ +import { FlowRouter } from 'meteor/kadira:flow-router'; + Template.ThreadList.events({ 'click .js-create-thread'() { - return FlowRouter.go('home'); + return FlowRouter.go('create-thread'); } }); diff --git a/packages/assistify-threading/package.js b/packages/assistify-threading/package.js index 97e728cca92b2..0e6f018e1e801 100644 --- a/packages/assistify-threading/package.js +++ b/packages/assistify-threading/package.js @@ -49,6 +49,8 @@ Package.onUse(function(api) { api.addFiles('client/views/createThreadMessageAction.js', 'client'); api.addFiles('client/views/threadList.html', 'client'); api.addFiles('client/views/threadList.js', 'client'); + api.addFiles('client/router.js', 'client'); + //styling api.addFiles('client/public/stylesheets/threading.css', 'client'); From 8e2e8f6e3f5f02d45ddd9bb89edd93541ad48439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Wed, 15 Aug 2018 00:35:50 +0200 Subject: [PATCH 029/124] Fix configuration andselect proper default channel --- .../views/creationDialog/CreateThread.js | 4 +-- packages/assistify-threading/config.js | 25 ++++++------------- .../server/methods/getParentChannelList.js | 1 + packages/rocketchat-i18n/i18n/de.i18n.json | 1 + packages/rocketchat-i18n/i18n/en.i18n.json | 1 + 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.js b/packages/assistify-threading/client/views/creationDialog/CreateThread.js index 09ac33fb7789e..bc24825aec14d 100755 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.js +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.js @@ -272,10 +272,10 @@ Template.CreateThread.onRendered(function() { Template.CreateThread.onCreated(function() { const instance = this; - instance.parentChannel = new ReactiveVar(RocketChat.settings.get('Parent_Channel')); //determine parent Channel from setting and allow to overwrite + instance.parentChannel = new ReactiveVar(RocketChat.settings.get('Thread_default_parent_Channel')); //determine parent Channel from setting and allow to overwrite instance.parentChannelId = new ReactiveVar(''); instance.parentChannelError = new ReactiveVar(null); - instance.selectParent = new ReactiveVar(RocketChat.settings.get('Select_Parent')); + instance.selectParent = new ReactiveVar(false); instance.parentChannelsList = new ReactiveVar(''); instance.error = new ReactiveVar(null); instance.openingQuestion = new ReactiveVar(''); diff --git a/packages/assistify-threading/config.js b/packages/assistify-threading/config.js index 24547ca3ef2d3..f6deafa5f2b3d 100644 --- a/packages/assistify-threading/config.js +++ b/packages/assistify-threading/config.js @@ -1,11 +1,6 @@ function getParentChannels() { - const result = Meteor.call('getParentChannelList', {sort: 'name'}); - if (!result) { - return [{ - key: 'general', - i18nLabel: 'general' - }]; - } + const result = Meteor.call('getParentChannelList', {sort: 'name', default: -1}); + return result.channels.map((channel) => { if (channel.name !== null) { return { @@ -25,20 +20,14 @@ Meteor.startup(() => { type: 'int', public: true }); - RocketChat.settings.add('Select_Parent', false, { - group: 'Threading', - i18nLabel: 'Select_Parent', - type: 'boolean', - public: true - }); - RocketChat.settings.add('Parent_Channel', '', { + const potentialParentChannels = getParentChannels(); + RocketChat.settings.add('Thread_default_parent_Channel', potentialParentChannels[0].name, { group: 'Threading', - i18nLabel: 'Parent_Channel', + i18nLabel: 'Thread_default_parent_Channel', type: 'select', - values: getParentChannels(), // load parent channels - public: true, - enableQuery: {_id: 'Select_Parent', value: true} + values: potentialParentChannels, // load parent channels + public: true }); RocketChat.settings.add('Accounts_Default_User_Preferences_sidebarShowThreads', true, { diff --git a/packages/assistify-threading/server/methods/getParentChannelList.js b/packages/assistify-threading/server/methods/getParentChannelList.js index f4c5c78166590..7e0b9e11b7620 100644 --- a/packages/assistify-threading/server/methods/getParentChannelList.js +++ b/packages/assistify-threading/server/methods/getParentChannelList.js @@ -8,6 +8,7 @@ Meteor.methods({ fields: { name: 1, usersCount: 1, + default: 1, msgs: 1, t: 1 }, diff --git a/packages/rocketchat-i18n/i18n/de.i18n.json b/packages/rocketchat-i18n/i18n/de.i18n.json index 31381717d1e97..f2fcfe2e25194 100644 --- a/packages/rocketchat-i18n/i18n/de.i18n.json +++ b/packages/rocketchat-i18n/i18n/de.i18n.json @@ -2424,6 +2424,7 @@ "Thread_start": "Thread starten", "thread-created" : "__username__ hat einen neuen Thread angelegt: __message__.", "Threading_description": "Hilf dabei, die Übersicht zu behalten! Indem Du einen Thread anlegst, wird ein Unterkanal mit passenden Mitgliedern erstellt.", + "Thread_default_parent_Channel": "Standard-Kanal für neue Threads", "Thread_select_different_parent": "- wähle einen anderen übergeordneten Kanal aus", "Thread_target_channel": "Übergeordneter Kanal oder Gruppe", "Thread_target_channel_description": "Wähle einen Kanal oder eine Gruppe aus, die zu Deinem Anliegen passt", diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 96b79591e9048..e5ab68495d43e 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -2445,6 +2445,7 @@ "Thread_start": "Start a thread", "thread-created" : "__username__ has started a new thread: __message__.", "Threading_description": "Help keeping an overview about what's going on! By creating a thread, a sub-channel of the one you selected is created and both are linked.", + "Thread_default_parent_Channel": "Default channel for new Threads", "Thread_select_different_parent": "- select a different parent channel", "Thread_target_channel": "Parent channel or group", "Thread_target_channel_description": "Select a channel which is related to what you want to ask", From 65bb74810e04a352368914f84808fd210f600b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Wed, 15 Aug 2018 08:33:16 +0200 Subject: [PATCH 030/124] minor UI fixes --- .../views/creationDialog/CreateThread.html | 2 +- .../views/creationDialog/CreateThread.js | 2 +- .../client/views/threadList.html | 22 +++++++++---------- packages/rocketchat-i18n/i18n/de.i18n.json | 4 +++- packages/rocketchat-i18n/i18n/en.i18n.json | 5 +++-- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.html b/packages/assistify-threading/client/views/creationDialog/CreateThread.html index 071f541ea1055..f47d4d7b2a4d7 100644 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.html +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.html @@ -22,7 +22,7 @@

{{_ "Threading_title"}}

{{#unless selectParent}}
{{ targetChannelText }} - {{_ "Thread_select_different_parent"}} + {{_ "Thread_target_channel_suffix"}}
{{/unless}}
diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.js b/packages/assistify-threading/client/views/creationDialog/CreateThread.js index bc24825aec14d..1826081f19ccd 100755 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.js +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.js @@ -74,7 +74,7 @@ Template.CreateThread.helpers({ }, targetChannelText() { const instance = Template.instance(); - return `${ TAPi18n.__('Target_channel_prefix') } "${ instance.parentChannel.get() }"`; + return `${ TAPi18n.__('Thread_target_channel_prefix') } "${ instance.parentChannel.get() }"`; }, createIsDisabled() { const instance = Template.instance(); diff --git a/packages/assistify-threading/client/views/threadList.html b/packages/assistify-threading/client/views/threadList.html index ef17425ec315e..97b93e5e2d21c 100644 --- a/packages/assistify-threading/client/views/threadList.html +++ b/packages/assistify-threading/client/views/threadList.html @@ -1,17 +1,17 @@ diff --git a/packages/rocketchat-i18n/i18n/de.i18n.json b/packages/rocketchat-i18n/i18n/de.i18n.json index f2fcfe2e25194..0a9aae2b5038c 100644 --- a/packages/rocketchat-i18n/i18n/de.i18n.json +++ b/packages/rocketchat-i18n/i18n/de.i18n.json @@ -1826,6 +1826,7 @@ "No_results_found_for": "Keine Ergebnisse gefunden für:", "No_snippet_messages": "Keine Snippets vorhanden", "No_starred_messages": "Es wurden bisher keine Nachrichten favorisiert", + "No_threads_yet": "Keine Threads vorhanden", "No_such_command": "Es gibt keinen Befehl '/__command__'", "No_user_with_username_%s_was_found": "Es wurde kein Benutzer mit dem Namen \"%s\" gefunden!", "Nobody_available": "Es ist niemand verfügbar", @@ -2425,9 +2426,10 @@ "thread-created" : "__username__ hat einen neuen Thread angelegt: __message__.", "Threading_description": "Hilf dabei, die Übersicht zu behalten! Indem Du einen Thread anlegst, wird ein Unterkanal mit passenden Mitgliedern erstellt.", "Thread_default_parent_Channel": "Standard-Kanal für neue Threads", - "Thread_select_different_parent": "- wähle einen anderen übergeordneten Kanal aus", "Thread_target_channel": "Übergeordneter Kanal oder Gruppe", "Thread_target_channel_description": "Wähle einen Kanal oder eine Gruppe aus, die zu Deinem Anliegen passt", + "Thread_target_channel_prefix": "Du erstellst einen Thread in", + "Thread_target_channel_suffix": "- wähle einen anderen übergeordneten Kanal aus", "Threads": "Threads", "Threads_in_sidebar": "Threads in Seitenleiste", "Threads_in_sidebar_description": "Threads in Seitenleiste gruppieren", diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index e5ab68495d43e..61442b0eeff73 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1833,6 +1833,7 @@ "No_snippet_messages": "No snippet", "No_starred_messages": "No starred messages", "No_such_command": "No such command: `/__command__`", + "No_threads_yet": "No threads yet", "No_user_with_username_%s_was_found": "No user with username \"%s\" was found!", "Nobody_available": "Nobody available", "Node_version": "Node Version", @@ -2363,7 +2364,6 @@ "Sync_Users": "Sync Users", "System_messages": "System Messages", "Tag": "Tag", - "Target_channel_prefix": "You are asking the members of", "Take_it": "Take it!", "TargetRoom": "Target Room", "TargetRoom_Description": "The room where messages will be sent which are a result of this event being fired. Only one target room is allowed and it must exist.", @@ -2446,9 +2446,10 @@ "thread-created" : "__username__ has started a new thread: __message__.", "Threading_description": "Help keeping an overview about what's going on! By creating a thread, a sub-channel of the one you selected is created and both are linked.", "Thread_default_parent_Channel": "Default channel for new Threads", - "Thread_select_different_parent": "- select a different parent channel", "Thread_target_channel": "Parent channel or group", "Thread_target_channel_description": "Select a channel which is related to what you want to ask", + "Thread_target_channel_prefix": "You are creating a thread in", + "Thread_target_channel_suffix": "- select a different parent channel", "Threads": "Threads", "Threads_in_sidebar": "Threads in channel list", "Threads_in_sidebar_description": "Group threads in sidebar", From 06a1b190a28cb3eeb5458c9a79cc5a034e53d346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Wed, 15 Aug 2018 08:33:46 +0200 Subject: [PATCH 031/124] Add parentRoom index to rooms and subscriptions --- packages/rocketchat-lib/server/models/Rooms.js | 1 + packages/rocketchat-lib/server/models/Subscriptions.js | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/rocketchat-lib/server/models/Rooms.js b/packages/rocketchat-lib/server/models/Rooms.js index b714069c78fc8..139150966ac8c 100644 --- a/packages/rocketchat-lib/server/models/Rooms.js +++ b/packages/rocketchat-lib/server/models/Rooms.js @@ -9,6 +9,7 @@ class ModelRooms extends RocketChat.models._Base { this.tryEnsureIndex({ 'default': 1 }); this.tryEnsureIndex({ 't': 1 }); this.tryEnsureIndex({ 'u._id': 1 }); + this.tryEnsureIndex({ 'parentRoomId': 1 }); } findOneByIdOrName(_idOrName, options) { diff --git a/packages/rocketchat-lib/server/models/Subscriptions.js b/packages/rocketchat-lib/server/models/Subscriptions.js index 6e3e7610cf608..3f88728b6da2e 100644 --- a/packages/rocketchat-lib/server/models/Subscriptions.js +++ b/packages/rocketchat-lib/server/models/Subscriptions.js @@ -21,6 +21,7 @@ class ModelSubscriptions extends RocketChat.models._Base { this.tryEnsureIndex({ 'autoTranslate': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'autoTranslateLanguage': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'userHighlights.0': 1 }, { sparse: 1 }); + this.tryEnsureIndex({ 'parentRoomId': 1 }); } From 89c781ebfda73e8465a2de66b8dae23c2fbaddb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Wed, 15 Aug 2018 08:36:33 +0200 Subject: [PATCH 032/124] create threads in direct messages as private groups --- packages/assistify-threading/server/methods/createThread.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/assistify-threading/server/methods/createThread.js b/packages/assistify-threading/server/methods/createThread.js index 29dee8addf90f..23e8425ea1d80 100644 --- a/packages/assistify-threading/server/methods/createThread.js +++ b/packages/assistify-threading/server/methods/createThread.js @@ -110,7 +110,8 @@ export class ThreadBuilder { const parentRoom = ThreadBuilder.getRoom(this._parentRoomId); // Generate RoomName for xthe new room to be created. this.name = `${ parentRoom.name }-${ ThreadBuilder.getNextId() }`; - const threadRoom = RocketChat.createRoom(parentRoom.t, this.name, Meteor.user() && Meteor.user().username, this._getMembers(), false, { parentRoomId: this._parentRoomId }); + const threadRoomType = parentRoom.t === 'd' ? 'p' : parentRoom.t; + const threadRoom = RocketChat.createRoom(threadRoomType, this.name, Meteor.user() && Meteor.user().username, this._getMembers(), false, { parentRoomId: this._parentRoomId }); if (parentRoom.name) { RocketChat.saveRoomTopic(threadRoom.rid, parentRoom.name, Meteor.user()); From 137e10afa1c95500c85f4d917cbfa5505034fdd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Wed, 15 Aug 2018 12:50:03 +0200 Subject: [PATCH 033/124] Create thread from direct message with better name --- packages/assistify-threading/config.js | 31 +++++++++++-------- .../server/methods/createThread.js | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/packages/assistify-threading/config.js b/packages/assistify-threading/config.js index f6deafa5f2b3d..41551a1f689e2 100644 --- a/packages/assistify-threading/config.js +++ b/packages/assistify-threading/config.js @@ -1,5 +1,5 @@ function getParentChannels() { - const result = Meteor.call('getParentChannelList', {sort: 'name', default: -1}); + const result = Meteor.call('getParentChannelList', { sort: 'name', default: -1 }); return result.channels.map((channel) => { if (channel.name !== null) { @@ -14,22 +14,21 @@ function getParentChannels() { Meteor.startup(() => { RocketChat.settings.addGroup('Threading'); - RocketChat.settings.add('Thread_Count', 1, { - group: 'Threading', - i18nLabel: 'Thread_count', - type: 'int', - public: true - }); - + // the channel for which threads are created if none is explicitly chosen const potentialParentChannels = getParentChannels(); - RocketChat.settings.add('Thread_default_parent_Channel', potentialParentChannels[0].name, { + const defaultChannel = potentialParentChannels[0] ? potentialParentChannels[0].key : ''; + RocketChat.settings.add('Thread_default_parent_Channel', defaultChannel, { group: 'Threading', i18nLabel: 'Thread_default_parent_Channel', - type: 'select', - values: potentialParentChannels, // load parent channels + type: 'string', public: true }); + // Set the default channel on each restart if unset + if (!RocketChat.settings.get('Thread_default_parent_Channel')) { + RocketChat.models.Settings.updateValueById('Thread_default_parent_Channel', defaultChannel); + } + RocketChat.settings.add('Accounts_Default_User_Preferences_sidebarShowThreads', true, { group: 'Accounts', section: 'Accounts_Default_User_Preferences', @@ -37,6 +36,12 @@ Meteor.startup(() => { 'public': true, i18nLabel: 'Threads_in_sidebar' }); -}); - + // this is a technical counter which allows for generation of unique room names + RocketChat.settings.add('Thread_Count', 1, { + group: 'Threading', + i18nLabel: 'Thread_count', + type: 'int', + public: true + }); +}); diff --git a/packages/assistify-threading/server/methods/createThread.js b/packages/assistify-threading/server/methods/createThread.js index 23e8425ea1d80..e2d422afcf350 100644 --- a/packages/assistify-threading/server/methods/createThread.js +++ b/packages/assistify-threading/server/methods/createThread.js @@ -109,7 +109,7 @@ export class ThreadBuilder { create() { const parentRoom = ThreadBuilder.getRoom(this._parentRoomId); // Generate RoomName for xthe new room to be created. - this.name = `${ parentRoom.name }-${ ThreadBuilder.getNextId() }`; + this.name = `${ parentRoom.name || parentRoom.usernames.join('-') }-${ ThreadBuilder.getNextId() }`; const threadRoomType = parentRoom.t === 'd' ? 'p' : parentRoom.t; const threadRoom = RocketChat.createRoom(threadRoomType, this.name, Meteor.user() && Meteor.user().username, this._getMembers(), false, { parentRoomId: this._parentRoomId }); From ad7f2cd4686708ff2e96588253100548a97f864b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Wed, 15 Aug 2018 15:54:38 +0200 Subject: [PATCH 034/124] Improve UX --- .../client/public/stylesheets/threading.css | 25 ++-- packages/assistify-threading/client/router.js | 12 -- .../views/creationDialog/CreateThread.html | 107 ++++++++---------- .../views/creationDialog/CreateThread.js | 19 ++++ .../client/views/threadList.html | 2 +- packages/assistify-threading/config.js | 9 +- packages/assistify-threading/package.js | 1 - packages/rocketchat-i18n/i18n/de.i18n.json | 1 + packages/rocketchat-i18n/i18n/en.i18n.json | 1 + .../rocketchat-ui/client/views/app/home.html | 14 +-- .../rocketchat-ui/client/views/app/home.js | 2 +- 11 files changed, 102 insertions(+), 91 deletions(-) delete mode 100644 packages/assistify-threading/client/router.js diff --git a/packages/assistify-threading/client/public/stylesheets/threading.css b/packages/assistify-threading/client/public/stylesheets/threading.css index 2bcfe0a87d31a..98e107633ed3b 100644 --- a/packages/assistify-threading/client/public/stylesheets/threading.css +++ b/packages/assistify-threading/client/public/stylesheets/threading.css @@ -1,11 +1,3 @@ -.create-thread .create-channel__title { - padding: 25% 0 1rem; -} - -.create-thread header.create-channel__header { - text-align: center; -} - .create-thread textarea { width: 100%; @@ -23,15 +15,30 @@ max-height: 250px; } +.content .threading-wrapper { + max-width: 650px; + margin-top: 50px; +} + +.create-thread .action-link { + cursor: pointer; +} + .create-thread-sidebar { margin-bottom: 22px; } .create-thread-sidebar button { font-size: 100%; - margin-top: 6px; + margin-top: 10px; + margin-right: auto; + min-height: 24px; } .create-thread-sidebar .rooms-list__list { margin-bottom: 0px; } + +.create-thread-sidebar .rooms-list__empty-room { + margin-bottom: 6px; +} diff --git a/packages/assistify-threading/client/router.js b/packages/assistify-threading/client/router.js deleted file mode 100644 index fd751e23aab4f..0000000000000 --- a/packages/assistify-threading/client/router.js +++ /dev/null @@ -1,12 +0,0 @@ -import { FlowRouter } from 'meteor/kadira:flow-router'; - -FlowRouter.route('/create-thread', { - name: 'create-thread', - - action() { - return BlazeLayout.render('main', {center: 'CreateThread'}); - }, - triggersExit: [function() { - $('.main-content').addClass('rc-old'); - }] -}); diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.html b/packages/assistify-threading/client/views/creationDialog/CreateThread.html index f47d4d7b2a4d7..56188b1beb65b 100644 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.html +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.html @@ -1,70 +1,59 @@ diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.js b/packages/assistify-threading/client/views/creationDialog/CreateThread.js index 1826081f19ccd..ab6d708a7ed18 100755 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.js +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.js @@ -3,6 +3,25 @@ import { FlowRouter } from 'meteor/kadira:flow-router'; import { ReactiveVar } from 'meteor/reactive-var'; +const parent = document.querySelector('.main-content'); + +FlowRouter.route('/create-thread', { + name: 'create-thread', + + action() { + if (parent) { + Blaze.renderWithData(Template.fullModal, {template: 'CreateThread'}, parent); + } else { + BlazeLayout.render('main', {center: 'fullModal', template: 'CreateThread'}); + } + }, + + triggersExit: [function() { + Blaze.remove(Blaze.getView(document.getElementsByClassName('full-modal')[0])); + $('.main-content').addClass('rc-old'); + }] +}); + const acEvents = { 'click .rc-popup-list__item'(e, t) { t.ac.onItemClick(this, e); diff --git a/packages/assistify-threading/client/views/threadList.html b/packages/assistify-threading/client/views/threadList.html index 97b93e5e2d21c..2820d098dbe04 100644 --- a/packages/assistify-threading/client/views/threadList.html +++ b/packages/assistify-threading/client/views/threadList.html @@ -11,7 +11,7 @@

{{/each}}

- +

diff --git a/packages/assistify-threading/config.js b/packages/assistify-threading/config.js index 41551a1f689e2..7e79340fb3b46 100644 --- a/packages/assistify-threading/config.js +++ b/packages/assistify-threading/config.js @@ -29,6 +29,13 @@ Meteor.startup(() => { RocketChat.models.Settings.updateValueById('Thread_default_parent_Channel', defaultChannel); } + RocketChat.settings.add('Thread_creation_on_home', false, { + group: 'Threading', + type: 'boolean', + 'public': true, + i18nLabel: 'Thread_creation_on_home' + }); + RocketChat.settings.add('Accounts_Default_User_Preferences_sidebarShowThreads', true, { group: 'Accounts', section: 'Accounts_Default_User_Preferences', @@ -42,6 +49,6 @@ Meteor.startup(() => { group: 'Threading', i18nLabel: 'Thread_count', type: 'int', - public: true + public: false }); }); diff --git a/packages/assistify-threading/package.js b/packages/assistify-threading/package.js index 0e6f018e1e801..9ed95ca5fb8ce 100644 --- a/packages/assistify-threading/package.js +++ b/packages/assistify-threading/package.js @@ -49,7 +49,6 @@ Package.onUse(function(api) { api.addFiles('client/views/createThreadMessageAction.js', 'client'); api.addFiles('client/views/threadList.html', 'client'); api.addFiles('client/views/threadList.js', 'client'); - api.addFiles('client/router.js', 'client'); //styling diff --git a/packages/rocketchat-i18n/i18n/de.i18n.json b/packages/rocketchat-i18n/i18n/de.i18n.json index 0a9aae2b5038c..8a2d51294a5af 100644 --- a/packages/rocketchat-i18n/i18n/de.i18n.json +++ b/packages/rocketchat-i18n/i18n/de.i18n.json @@ -2425,6 +2425,7 @@ "Thread_start": "Thread starten", "thread-created" : "__username__ hat einen neuen Thread angelegt: __message__.", "Threading_description": "Hilf dabei, die Übersicht zu behalten! Indem Du einen Thread anlegst, wird ein Unterkanal mit passenden Mitgliedern erstellt.", + "Thread_creation_on_home": "Threads von der Home-Seite aus anlegen", "Thread_default_parent_Channel": "Standard-Kanal für neue Threads", "Thread_target_channel": "Übergeordneter Kanal oder Gruppe", "Thread_target_channel_description": "Wähle einen Kanal oder eine Gruppe aus, die zu Deinem Anliegen passt", diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 61442b0eeff73..8eff65edafdcd 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -2445,6 +2445,7 @@ "Thread_start": "Start a thread", "thread-created" : "__username__ has started a new thread: __message__.", "Threading_description": "Help keeping an overview about what's going on! By creating a thread, a sub-channel of the one you selected is created and both are linked.", + "Thread_creation_on_home": "Create threads on home screen", "Thread_default_parent_Channel": "Default channel for new Threads", "Thread_target_channel": "Parent channel or group", "Thread_target_channel_description": "Select a channel which is related to what you want to ask", diff --git a/packages/rocketchat-ui/client/views/app/home.html b/packages/rocketchat-ui/client/views/app/home.html index 89ea6117a50ce..a352adab7347e 100644 --- a/packages/rocketchat-ui/client/views/app/home.html +++ b/packages/rocketchat-ui/client/views/app/home.html @@ -1,13 +1,13 @@ diff --git a/packages/rocketchat-ui/client/views/app/home.js b/packages/rocketchat-ui/client/views/app/home.js index ec8a9ba5fd531..d3dd38be9b52f 100644 --- a/packages/rocketchat-ui/client/views/app/home.js +++ b/packages/rocketchat-ui/client/views/app/home.js @@ -6,6 +6,6 @@ Template.home.helpers({ return RocketChat.settings.get('Layout_Home_Body'); }, threadingOnHome() { - return true; // TODO provide setting + return RocketChat.settings.get('Thread_creation_on_home'); } }); From 4f818bacac9a613adf753a8dff5810748e5dbed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Wed, 15 Aug 2018 16:30:53 +0200 Subject: [PATCH 035/124] Fix scrolling and make sidebar-button larger --- .../client/public/stylesheets/threading.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/assistify-threading/client/public/stylesheets/threading.css b/packages/assistify-threading/client/public/stylesheets/threading.css index 98e107633ed3b..95c0ce52b3efb 100644 --- a/packages/assistify-threading/client/public/stylesheets/threading.css +++ b/packages/assistify-threading/client/public/stylesheets/threading.css @@ -24,6 +24,10 @@ cursor: pointer; } +.create-thread .create-channel { + height: 100%; +} + .create-thread-sidebar { margin-bottom: 22px; } @@ -32,6 +36,8 @@ font-size: 100%; margin-top: 10px; margin-right: auto; + margin-left: auto; + width: 100%; min-height: 24px; } From 5e5edebba0137e06cec457e5efdd191ca6c1efbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Wed, 15 Aug 2018 17:40:42 +0200 Subject: [PATCH 036/124] Unimplement threading on home fix overlapping modals --- .../views/creationDialog/CreateThread.html | 104 ++++++++++-------- .../views/creationDialog/CreateThread.js | 7 +- packages/assistify-threading/config.js | 7 -- .../rocketchat-ui/client/views/app/home.html | 17 +-- .../rocketchat-ui/client/views/app/home.js | 3 - 5 files changed, 67 insertions(+), 71 deletions(-) diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.html b/packages/assistify-threading/client/views/creationDialog/CreateThread.html index 56188b1beb65b..569823375a04f 100644 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.html +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.html @@ -1,59 +1,67 @@ diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.js b/packages/assistify-threading/client/views/creationDialog/CreateThread.js index ab6d708a7ed18..8821279ebb6bd 100755 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.js +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.js @@ -10,9 +10,9 @@ FlowRouter.route('/create-thread', { action() { if (parent) { - Blaze.renderWithData(Template.fullModal, {template: 'CreateThread'}, parent); + Blaze.renderWithData('CreateThread', parent); } else { - BlazeLayout.render('main', {center: 'fullModal', template: 'CreateThread'}); + BlazeLayout.render('main', { center: 'CreateThread'}); } }, @@ -248,6 +248,9 @@ Template.CreateThread.events({ FlowRouter.goToRoomById(result.rid); }); } + }, + 'click .full-modal__back-button'() { + FlowRouter.go('home'); //back would be nicer but somewhat this seems difficult } }); diff --git a/packages/assistify-threading/config.js b/packages/assistify-threading/config.js index 7e79340fb3b46..a76a7319d1c41 100644 --- a/packages/assistify-threading/config.js +++ b/packages/assistify-threading/config.js @@ -29,13 +29,6 @@ Meteor.startup(() => { RocketChat.models.Settings.updateValueById('Thread_default_parent_Channel', defaultChannel); } - RocketChat.settings.add('Thread_creation_on_home', false, { - group: 'Threading', - type: 'boolean', - 'public': true, - i18nLabel: 'Thread_creation_on_home' - }); - RocketChat.settings.add('Accounts_Default_User_Preferences_sidebarShowThreads', true, { group: 'Accounts', section: 'Accounts_Default_User_Preferences', diff --git a/packages/rocketchat-ui/client/views/app/home.html b/packages/rocketchat-ui/client/views/app/home.html index a352adab7347e..7bc50d94a90ee 100644 --- a/packages/rocketchat-ui/client/views/app/home.html +++ b/packages/rocketchat-ui/client/views/app/home.html @@ -1,13 +1,8 @@ + + diff --git a/packages/rocketchat-ui/client/views/app/home.js b/packages/rocketchat-ui/client/views/app/home.js index d3dd38be9b52f..fd66695d37851 100644 --- a/packages/rocketchat-ui/client/views/app/home.js +++ b/packages/rocketchat-ui/client/views/app/home.js @@ -4,8 +4,5 @@ Template.home.helpers({ }, body() { return RocketChat.settings.get('Layout_Home_Body'); - }, - threadingOnHome() { - return RocketChat.settings.get('Thread_creation_on_home'); } }); From a495f840d4c74e6ca1c6bb688f892722fd15bed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Thu, 16 Aug 2018 08:25:34 +0200 Subject: [PATCH 037/124] Minor beautifications on code level --- .../client/public/stylesheets/threading.css | 4 ++++ .../views/creationDialog/CreateThread.html | 2 +- .../views/creationDialog/CreateThread.js | 18 +++++++++++++++--- .../rocketchat-ui/client/views/app/home.html | 14 +++++++------- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/packages/assistify-threading/client/public/stylesheets/threading.css b/packages/assistify-threading/client/public/stylesheets/threading.css index 95c0ce52b3efb..4857a950e8a9e 100644 --- a/packages/assistify-threading/client/public/stylesheets/threading.css +++ b/packages/assistify-threading/client/public/stylesheets/threading.css @@ -28,6 +28,10 @@ height: 100%; } +.create-thread .full-modal__back-text { + font-size: 11px; /*no clue, why we have to specify this explicitly. Dirty hack.*/ +} + .create-thread-sidebar { margin-bottom: 22px; } diff --git a/packages/assistify-threading/client/views/creationDialog/CreateThread.html b/packages/assistify-threading/client/views/creationDialog/CreateThread.html index 569823375a04f..e9348931a1d81 100644 --- a/packages/assistify-threading/client/views/creationDialog/CreateThread.html +++ b/packages/assistify-threading/client/views/creationDialog/CreateThread.html @@ -29,7 +29,7 @@

{{_ "Threading_title"}}

{{_ "Thread_target_channel_suffix"}}
{{/unless}} -
+
{{/if}} {{/if}} - \ No newline at end of file + diff --git a/packages/rocketchat-message-attachments/client/renderField.js b/packages/rocketchat-message-attachments/client/renderField.js index d8181679817e5..28bc9fd0adabf 100644 --- a/packages/rocketchat-message-attachments/client/renderField.js +++ b/packages/rocketchat-message-attachments/client/renderField.js @@ -1,3 +1,6 @@ +import { Template } from 'meteor/templating'; +import { Blaze } from 'meteor/blaze'; + const renderers = {}; /** @@ -34,6 +37,11 @@ export function registerFieldTemplate(fieldType, templateName, events) { } } +// onRendered is not being executed (no idea why). Consequently, we cannot use Blaze.renderWithData(), since we don't +// have access to the DOM outside onRendered. Therefore, we can only translate the content of the field to HTML and +// embed it non-reactively. +// This in turn means that onRendered of the field template will not be processed either. +// I guess it may have someting to do with rocketchat-nrr Template.renderField.helpers({ specializedRendering({ hash: { field, message } }) { let html = ''; From e7586b719bfb6a41184c1a0912f821070233ab62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Thu, 20 Dec 2018 13:54:40 +0100 Subject: [PATCH 078/124] add package.js --- packages/assistify-threading/package.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/assistify-threading/package.js b/packages/assistify-threading/package.js index edc0007a0ca46..412a876c95091 100644 --- a/packages/assistify-threading/package.js +++ b/packages/assistify-threading/package.js @@ -49,6 +49,10 @@ Package.onUse(function(api) { api.addFiles('client/views/creationDialog/ChannelSelection.js', 'client'); api.addFiles('client/views/ThreadList.html', 'client'); api.addFiles('client/views/ThreadList.js', 'client'); + api.addFiles('client/views/fieldTypeThreadReplyCounter.html', 'client'); + api.addFiles('client/views/fieldTypeThreadReplyCounter.js', 'client'); + api.addFiles('client/views/fieldTypeThreadLastMessageAge.html', 'client'); + api.addFiles('client/views/fieldTypeThreadLastMessageAge.js', 'client'); // Other UI extensions api.addFiles('client/createThreadMessageAction.js', 'client'); From 637accc3b2875d7bf22f0803df50862f4820aabe Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 3 Jan 2019 10:40:28 -0200 Subject: [PATCH 079/124] Fix file names --- packages/assistify-threading/package.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/assistify-threading/package.js b/packages/assistify-threading/package.js index 412a876c95091..2a2d9f23cdeb8 100644 --- a/packages/assistify-threading/package.js +++ b/packages/assistify-threading/package.js @@ -47,8 +47,8 @@ Package.onUse(function(api) { api.addFiles('client/views/creationDialog/ChannelNotFound.js', 'client'); api.addFiles('client/views/creationDialog/ChannelSelection.html', 'client'); api.addFiles('client/views/creationDialog/ChannelSelection.js', 'client'); - api.addFiles('client/views/ThreadList.html', 'client'); - api.addFiles('client/views/ThreadList.js', 'client'); + api.addFiles('client/views/threadList.html', 'client'); + api.addFiles('client/views/threadList.js', 'client'); api.addFiles('client/views/fieldTypeThreadReplyCounter.html', 'client'); api.addFiles('client/views/fieldTypeThreadReplyCounter.js', 'client'); api.addFiles('client/views/fieldTypeThreadLastMessageAge.html', 'client'); From b490778df7abe6653feb24ea7e48acd864ab6c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Sat, 5 Jan 2019 23:21:07 +0100 Subject: [PATCH 080/124] Don't suppress system messages in threads --- packages/assistify-threading/server/methods/createThread.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/assistify-threading/server/methods/createThread.js b/packages/assistify-threading/server/methods/createThread.js index b62c380d8b30a..0a7f256778eb4 100644 --- a/packages/assistify-threading/server/methods/createThread.js +++ b/packages/assistify-threading/server/methods/createThread.js @@ -200,8 +200,6 @@ export class ThreadBuilder { // Create messages linking the parent room and the thread this._linkMessages(threadRoom, this._parentRoom, repostedMessage); } - Meteor.call('saveRoomSettings', threadRoomCreationResult.rid, 'systemMessages', false); - return threadRoom; } } From cfcc1136cf6a1159c0324b5ee38ee9b7d10efb9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Sat, 5 Jan 2019 23:35:36 +0100 Subject: [PATCH 081/124] Slash command /thread --- .../client/client.js | 4 ++++ .../package.js | 19 +++++++++++++++++++ .../server/server.js | 14 ++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 packages/rocketchat-slashcommands-create-thread/client/client.js create mode 100644 packages/rocketchat-slashcommands-create-thread/package.js create mode 100644 packages/rocketchat-slashcommands-create-thread/server/server.js diff --git a/packages/rocketchat-slashcommands-create-thread/client/client.js b/packages/rocketchat-slashcommands-create-thread/client/client.js new file mode 100644 index 0000000000000..23d96dbbb0398 --- /dev/null +++ b/packages/rocketchat-slashcommands-create-thread/client/client.js @@ -0,0 +1,4 @@ +RocketChat.slashCommands.add('thread', null, { + description: 'Thread_slash_command_description', + params: 'Thread_slash_command_params', +}); diff --git a/packages/rocketchat-slashcommands-create-thread/package.js b/packages/rocketchat-slashcommands-create-thread/package.js new file mode 100644 index 0000000000000..cfbcd895b0e07 --- /dev/null +++ b/packages/rocketchat-slashcommands-create-thread/package.js @@ -0,0 +1,19 @@ +Package.describe({ + name: 'rocketchat:slashcommands-create-thread', + version: '0.0.1', + summary: 'Command handler for the /create-thread command', + git: '', +}); + +Package.onUse(function(api) { + api.use([ + 'ecmascript', + 'check', + 'rocketchat:lib', + ]); + + api.use('templating', 'client'); + + api.addFiles('client/client.js', 'client'); + api.addFiles('server/server.js', 'server'); +}); diff --git a/packages/rocketchat-slashcommands-create-thread/server/server.js b/packages/rocketchat-slashcommands-create-thread/server/server.js new file mode 100644 index 0000000000000..e0cb488c7a469 --- /dev/null +++ b/packages/rocketchat-slashcommands-create-thread/server/server.js @@ -0,0 +1,14 @@ +function CreateThread(command, params, item) { + if (command !== 'thread' || !Match.test(params, String)) { + return; + } + + const openingMessage = params.trim(); + + Meteor.call('createThread', item.rid, { msg: openingMessage }); +} + +RocketChat.slashCommands.add('thread', CreateThread, { + description: 'Thread_slash_command_description', + params: 'Thread_slash_command_params', +}); From fef61d666419c8be64bdc9deb750790ed4ee9c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Sun, 6 Jan 2019 01:10:05 +0100 Subject: [PATCH 082/124] Make thread metadata on message update on new thread message --- .meteor/versions | 3 +- .../views/fieldTypeThreadLastMessageAge.js | 14 +------ .../views/fieldTypeThreadReplyCounter.js | 25 ++---------- packages/assistify-threading/package.js | 6 ++- .../server/hooks/propagateThreadMetadata.js | 12 ++++++ .../server/methods/createThread.js | 13 +++++-- .../server/models/MessagesExtension.js | 38 +++++++++++++++++++ .../server/models/RoomsExtension.js | 12 ++++++ 8 files changed, 82 insertions(+), 41 deletions(-) create mode 100644 packages/assistify-threading/server/hooks/propagateThreadMetadata.js create mode 100644 packages/assistify-threading/server/models/MessagesExtension.js diff --git a/.meteor/versions b/.meteor/versions index 326bc1c52bd32..317f0230b5ece 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -115,8 +115,8 @@ oauth1@1.2.2 oauth2@1.2.1 observe-sequence@1.0.16 ordered-dict@1.1.0 -overture8:wordcloud2@1.0.0 ostrio:cookies@2.3.0 +overture8:wordcloud2@1.0.0 pauli:accounts-linkedin@2.1.5 pauli:linkedin-oauth@1.2.0 promise@0.11.1 @@ -219,6 +219,7 @@ rocketchat:slackbridge@0.0.1 rocketchat:slashcommands-archive@0.0.1 rocketchat:slashcommands-asciiarts@0.0.1 rocketchat:slashcommands-create@0.0.1 +rocketchat:slashcommands-create-thread@0.0.1 rocketchat:slashcommands-help@0.0.1 rocketchat:slashcommands-hide@0.0.1 rocketchat:slashcommands-invite@0.0.1 diff --git a/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js b/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js index e65b6194b985f..f973eb68e948d 100644 --- a/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js +++ b/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js @@ -6,21 +6,9 @@ import moment from 'moment'; Template.LastMessageAge.helpers({ lastMessageAge() { - const lastMessageTimestamp = Template.instance().lastMessageTimestamp.get(); + const lastMessageTimestamp = Template.instance().data.field.lm; return moment(lastMessageTimestamp).fromNow(); }, }); -Template.LastMessageAge.onCreated(function() { - this.lastMessageTimestamp = new ReactiveVar(new Date('2018-12-19 13:15:00')); - - Meteor.call('getRoomMessageMetadata', this.data.field.roomId, (err, metadata) => { - const { lastMessageTimestamp } = metadata; - - if (!err) { - this.lastMessageTimestamp.set(lastMessageTimestamp); - } - }); -}); - registerFieldTemplate('lastMessageAge', 'LastMessageAge', {}); diff --git a/packages/assistify-threading/client/views/fieldTypeThreadReplyCounter.js b/packages/assistify-threading/client/views/fieldTypeThreadReplyCounter.js index 3534889036474..645941108d9fd 100644 --- a/packages/assistify-threading/client/views/fieldTypeThreadReplyCounter.js +++ b/packages/assistify-threading/client/views/fieldTypeThreadReplyCounter.js @@ -6,40 +6,21 @@ import { FlowRouter } from 'meteor/kadira:flow-router'; Template.MessageCounter.helpers({ hasReplies() { - return Template.instance().threadReplies.get() > 0; + return Template.instance().data.field.count > 0; }, replyCount() { - return Template.instance().threadReplies.get(); + return Template.instance().data.field.count; }, i18nKeyReply() { - return Template.instance().threadReplies.get() > 1 + return Template.instance().data.field.count > 1 ? 'Replies' : 'Reply'; }, }); -Template.MessageCounter.onCreated(function() { - this.threadReplies = new ReactiveVar(2); // just some dummy value until it's reactive -}); - -Template.MessageCounter.onRendered(function() { - // this is - unfortunately - not invoked since no real rendering is performed. see renderField.js and the comments there - - Meteor.call('getRoomMessageMetadata', this.data.field.roomId, (err, metadata) => { - const { visibleMessagesCount } = metadata; - - if (!err) { - this.threadReplies.set(visibleMessagesCount - 1); - - // here, some magic needs to happen in order to trigger a re-rendering - or at least refresh the DOM - console.log(this.find('.no-replies')); - } - }); -}); - const events = { 'click .js-navigate-to-thread'(event) { event.preventDefault(); diff --git a/packages/assistify-threading/package.js b/packages/assistify-threading/package.js index 2a2d9f23cdeb8..90b95acd83709 100644 --- a/packages/assistify-threading/package.js +++ b/packages/assistify-threading/package.js @@ -25,6 +25,8 @@ Package.onUse(function(api) { // Extensions to the rest of RC api.addFiles('server/models/RoomsExtension.js', 'server'); + api.addFiles('server/models/MessagesExtension.js', 'server'); + api.addFiles('server/hooks/propagateThreadMetadata.js', 'server'); api.addFiles('server/publications/threadParentAutocomplete.js', 'server'); // Methods @@ -47,8 +49,8 @@ Package.onUse(function(api) { api.addFiles('client/views/creationDialog/ChannelNotFound.js', 'client'); api.addFiles('client/views/creationDialog/ChannelSelection.html', 'client'); api.addFiles('client/views/creationDialog/ChannelSelection.js', 'client'); - api.addFiles('client/views/threadList.html', 'client'); - api.addFiles('client/views/threadList.js', 'client'); + api.addFiles('client/views/ThreadList.html', 'client'); + api.addFiles('client/views/ThreadList.js', 'client'); api.addFiles('client/views/fieldTypeThreadReplyCounter.html', 'client'); api.addFiles('client/views/fieldTypeThreadReplyCounter.js', 'client'); api.addFiles('client/views/fieldTypeThreadLastMessageAge.html', 'client'); diff --git a/packages/assistify-threading/server/hooks/propagateThreadMetadata.js b/packages/assistify-threading/server/hooks/propagateThreadMetadata.js new file mode 100644 index 0000000000000..70240dd7d3add --- /dev/null +++ b/packages/assistify-threading/server/hooks/propagateThreadMetadata.js @@ -0,0 +1,12 @@ +import { RocketChat } from 'meteor/rocketchat:lib'; + +/** + * We need to propagate the writing of new message in a thread to the linking + * system message + */ +RocketChat.callbacks.add('afterSaveMessage', function(message, room) { + if (room.linkMessageId) { + RocketChat.models.Messages.refreshThreadMetadata(room.linkMessageId); + } + return message; +}, RocketChat.callbacks.priority.LOW, 'PropagateThreadMetadata'); diff --git a/packages/assistify-threading/server/methods/createThread.js b/packages/assistify-threading/server/methods/createThread.js index 0a7f256778eb4..144472da97955 100644 --- a/packages/assistify-threading/server/methods/createThread.js +++ b/packages/assistify-threading/server/methods/createThread.js @@ -91,11 +91,11 @@ export class ThreadBuilder { fields: [ { type: 'messageCounter', - roomId: roomCreated._id, + count: 1, }, { type: 'lastMessageAge', - roomId: roomCreated._id, + lm: this._openingMessage.ts, }], }; @@ -113,12 +113,18 @@ export class ThreadBuilder { if (!parentRoom.sysMes) { RocketChat.models.Rooms.setSystemMessagesById(parentRoom._id, true); } - RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser('create-thread', parentRoom._id, this._getMessageUrl(repostedMessage._id), this.rocketCatUser, linkMessage, { ts: this._openingMessage.ts }); + const createdLinkMessage = RocketChat.models.Messages.createWithTypeRoomIdMessageAndUser('create-thread', parentRoom._id, this._getMessageUrl(repostedMessage._id), this.rocketCatUser, linkMessage, { ts: this._openingMessage.ts }); // reset it if necessary if (!parentRoom.sysMes) { RocketChat.models.Rooms.setSystemMessagesById(parentRoom._id, false); } + + // finally, propagate the message ID of the system message in the parent to the thread + // so that this system message can be updated on changes of the thread. + // this redundancy is neccessary in order to re-render the actually non-reactive message list + // in order to update the visualized thread metadata (e. g. last message ts) on the link message + RocketChat.models.Rooms.setLinkMessageById(roomCreated._id, createdLinkMessage._id); return true; } } @@ -200,6 +206,7 @@ export class ThreadBuilder { // Create messages linking the parent room and the thread this._linkMessages(threadRoom, this._parentRoom, repostedMessage); } + return threadRoom; } } diff --git a/packages/assistify-threading/server/models/MessagesExtension.js b/packages/assistify-threading/server/models/MessagesExtension.js new file mode 100644 index 0000000000000..4684897827459 --- /dev/null +++ b/packages/assistify-threading/server/models/MessagesExtension.js @@ -0,0 +1,38 @@ +import { RocketChat } from 'meteor/rocketchat:lib'; + +/** + * Copy metadata from the thread to the system message in the parent channel + * which links to the thread. + * Since we don't pass this metadata into the model's function, it is not a subject + * to race conditions: If multiple updates occur, the current state will be updated + * only if the new state of the thread room is really newer. + */ +Object.assign(RocketChat.models.Messages, { + refreshThreadMetadata(linkMessageId) { + const linkMessage = this.findOneById(linkMessageId); + + if (linkMessage && linkMessage.channels[0] && linkMessage.channels[0]._id) { + const threadRoom = RocketChat.models.Rooms.findOneById(linkMessage.channels[0]._id); + const query = { + _id: linkMessageId, + _updatedAt: { + $lt: threadRoom._updatedAt, + }, + }; + + return this.update(query, { + $set: { + 'attachments.0.fields': [ + { + type: 'messageCounter', + count: threadRoom.msgs, + }, + { + type: 'lastMessageAge', + lm: threadRoom.lm, + }], + }, + }); + } else { return null; } + }, +}); diff --git a/packages/assistify-threading/server/models/RoomsExtension.js b/packages/assistify-threading/server/models/RoomsExtension.js index f1debbe42be54..d2c1a7fcdcb40 100644 --- a/packages/assistify-threading/server/models/RoomsExtension.js +++ b/packages/assistify-threading/server/models/RoomsExtension.js @@ -19,4 +19,16 @@ Object.assign(RocketChat.models.Rooms, { return this.find(query, options); }, + + setLinkMessageById(_id, linkMessageId) { + const query = { _id }; + + const update = { + $set: { + linkMessageId, + }, + }; + + return this.update(query, update); + }, }); From 0a6272a8260f4c40a48c7f74b5a2ba986765943a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Sun, 6 Jan 2019 01:14:30 +0100 Subject: [PATCH 083/124] Add slash command and fix linting --- .meteor/packages | 3 ++- .../client/views/fieldTypeThreadLastMessageAge.js | 2 -- .../client/views/fieldTypeThreadReplyCounter.js | 2 -- .../rocketchat-slashcommands-create-thread/server/server.js | 3 +++ 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.meteor/packages b/.meteor/packages index 0551cb6881d6e..e99a0a70e6e6c 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -117,6 +117,7 @@ rocketchat:slackbridge rocketchat:slashcommands-archive rocketchat:slashcommands-asciiarts rocketchat:slashcommands-create +rocketchat:slashcommands-create-thread rocketchat:slashcommands-help rocketchat:slashcommands-hide rocketchat:slashcommands-invite @@ -202,4 +203,4 @@ rocketchat:bigbluebutton rocketchat:mailmessages juliancwirko:postcss littledata:synced-cron -rocketchat:utils \ No newline at end of file +rocketchat:utils diff --git a/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js b/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js index f973eb68e948d..976978355403f 100644 --- a/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js +++ b/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js @@ -1,6 +1,4 @@ import { registerFieldTemplate } from 'meteor/rocketchat:message-attachments'; -import { Meteor } from 'meteor/meteor'; -import { ReactiveVar } from 'meteor/reactive-var'; import { Template } from 'meteor/templating'; import moment from 'moment'; diff --git a/packages/assistify-threading/client/views/fieldTypeThreadReplyCounter.js b/packages/assistify-threading/client/views/fieldTypeThreadReplyCounter.js index 645941108d9fd..6e7ff0c31a198 100644 --- a/packages/assistify-threading/client/views/fieldTypeThreadReplyCounter.js +++ b/packages/assistify-threading/client/views/fieldTypeThreadReplyCounter.js @@ -1,6 +1,4 @@ import { registerFieldTemplate } from 'meteor/rocketchat:message-attachments'; -import { Meteor } from 'meteor/meteor'; -import { ReactiveVar } from 'meteor/reactive-var'; import { Template } from 'meteor/templating'; import { FlowRouter } from 'meteor/kadira:flow-router'; diff --git a/packages/rocketchat-slashcommands-create-thread/server/server.js b/packages/rocketchat-slashcommands-create-thread/server/server.js index e0cb488c7a469..1ef89e9cd1f2f 100644 --- a/packages/rocketchat-slashcommands-create-thread/server/server.js +++ b/packages/rocketchat-slashcommands-create-thread/server/server.js @@ -1,3 +1,6 @@ +import { Meteor } from 'meteor/meteor'; +import { Match } from 'meteor/check'; + function CreateThread(command, params, item) { if (command !== 'thread' || !Match.test(params, String)) { return; From a00e8266153f609968e00e023a9e468a4107ca1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Sun, 6 Jan 2019 01:53:02 +0100 Subject: [PATCH 084/124] Add threads tabbar --- .../client/lib/threadsOfRoom.js | 3 ++ .../client/public/stylesheets/threading.css | 20 +++++++ packages/assistify-threading/client/tabBar.js | 13 +++++ .../client/views/ThreadsTabbar.html | 22 ++++++++ .../client/views/ThreadsTabbar.js | 54 +++++++++++++++++++ packages/assistify-threading/package.js | 4 ++ .../server/publications/threadsOfRoom.js | 32 +++++++++++ 7 files changed, 148 insertions(+) create mode 100644 packages/assistify-threading/client/lib/threadsOfRoom.js create mode 100644 packages/assistify-threading/client/tabBar.js create mode 100644 packages/assistify-threading/client/views/ThreadsTabbar.html create mode 100644 packages/assistify-threading/client/views/ThreadsTabbar.js create mode 100644 packages/assistify-threading/server/publications/threadsOfRoom.js diff --git a/packages/assistify-threading/client/lib/threadsOfRoom.js b/packages/assistify-threading/client/lib/threadsOfRoom.js new file mode 100644 index 0000000000000..76d63d68195ef --- /dev/null +++ b/packages/assistify-threading/client/lib/threadsOfRoom.js @@ -0,0 +1,3 @@ +import { Mongo } from 'meteor/mongo'; + +export const ThreadsOfRoom = new Mongo.Collection('rocketchat_threads_of_room'); diff --git a/packages/assistify-threading/client/public/stylesheets/threading.css b/packages/assistify-threading/client/public/stylesheets/threading.css index 0dbdda9bbbb3b..dac19aff504dc 100644 --- a/packages/assistify-threading/client/public/stylesheets/threading.css +++ b/packages/assistify-threading/client/public/stylesheets/threading.css @@ -53,3 +53,23 @@ .attachment-fields button.no-replies { opacity: 0.4; } + +.threads-list li.empty { + margin-top: 60px; + + text-align: center; + + color: #7f7f7f; +} + +.threads-list .load-more { + text-align: center; + text-transform: lowercase; + + font-style: italic; + line-height: 40px; +} + +.threads-list .load-more .load-more-loading { + color: #aaaaaa; +} diff --git a/packages/assistify-threading/client/tabBar.js b/packages/assistify-threading/client/tabBar.js new file mode 100644 index 0000000000000..934bd37074388 --- /dev/null +++ b/packages/assistify-threading/client/tabBar.js @@ -0,0 +1,13 @@ +import { Meteor } from 'meteor/meteor'; +import { RocketChat } from 'meteor/rocketchat:lib'; + +Meteor.startup(function() { + return RocketChat.TabBar.addButton({ + groups: ['channel', 'group', 'direct'], + id: 'threads', + i18nTitle: 'Threads', + icon: 'thread', + template: 'threadsTabbar', + order: 10, + }); +}); diff --git a/packages/assistify-threading/client/views/ThreadsTabbar.html b/packages/assistify-threading/client/views/ThreadsTabbar.html new file mode 100644 index 0000000000000..502f83585d43c --- /dev/null +++ b/packages/assistify-threading/client/views/ThreadsTabbar.html @@ -0,0 +1,22 @@ + diff --git a/packages/assistify-threading/client/views/ThreadsTabbar.js b/packages/assistify-threading/client/views/ThreadsTabbar.js new file mode 100644 index 0000000000000..a6c7ab209c0c3 --- /dev/null +++ b/packages/assistify-threading/client/views/ThreadsTabbar.js @@ -0,0 +1,54 @@ +import _ from 'underscore'; +import { ReactiveVar } from 'meteor/reactive-var'; +import { Template } from 'meteor/templating'; +import { ThreadsOfRoom } from '../lib/threadsOfRoom'; + +Template.threadsTabbar.helpers({ + hasMessages() { + return ThreadsOfRoom.find({ + rid: this.rid, + }, { + sort: { + ts: -1, + }, + }).count() > 0; + }, + messages() { + return ThreadsOfRoom.find({ + rid: this.rid, + }, { + sort: { + ts: -1, + }, + }); + }, + message() { + return _.extend(this, { customClass: 'pinned', actionContext: 'pinned' }); + }, + hasMore() { + return Template.instance().hasMore.get(); + }, +}); + +Template.threadsTabbar.onCreated(function() { + this.hasMore = new ReactiveVar(true); + this.limit = new ReactiveVar(50); + return this.autorun(() => { + const data = Template.currentData(); + return this.subscribe('threadsOfRoom', data.rid, this.limit.get(), () => { + if (ThreadsOfRoom.find({ + rid: data.rid, + }).count() < this.limit.get()) { + return this.hasMore.set(false); + } + }); + }); +}); + +Template.pinnedMessages.events({ + 'scroll .js-list': _.throttle(function(e, instance) { + if (e.target.scrollTop >= e.target.scrollHeight - e.target.clientHeight && instance.hasMore.get()) { + return instance.limit.set(instance.limit.get() + 50); + } + }, 200), +}); diff --git a/packages/assistify-threading/package.js b/packages/assistify-threading/package.js index 90b95acd83709..2f5198b48289a 100644 --- a/packages/assistify-threading/package.js +++ b/packages/assistify-threading/package.js @@ -28,6 +28,7 @@ Package.onUse(function(api) { api.addFiles('server/models/MessagesExtension.js', 'server'); api.addFiles('server/hooks/propagateThreadMetadata.js', 'server'); api.addFiles('server/publications/threadParentAutocomplete.js', 'server'); + api.addFiles('server/publications/threadsOfRoom.js', 'server'); // Methods api.addFiles('server/methods/createThread.js', 'server'); @@ -51,6 +52,8 @@ Package.onUse(function(api) { api.addFiles('client/views/creationDialog/ChannelSelection.js', 'client'); api.addFiles('client/views/ThreadList.html', 'client'); api.addFiles('client/views/ThreadList.js', 'client'); + api.addFiles('client/views/ThreadsTabbar.html', 'client'); + api.addFiles('client/views/ThreadsTabbar.js', 'client'); api.addFiles('client/views/fieldTypeThreadReplyCounter.html', 'client'); api.addFiles('client/views/fieldTypeThreadReplyCounter.js', 'client'); api.addFiles('client/views/fieldTypeThreadLastMessageAge.html', 'client'); @@ -59,6 +62,7 @@ Package.onUse(function(api) { // Other UI extensions api.addFiles('client/createThreadMessageAction.js', 'client'); api.addFiles('client/threadFromMessageBox.js', 'client'); + api.addFiles('client/tabBar.js', 'client'); // styling api.addFiles('client/public/stylesheets/threading.css', 'client'); diff --git a/packages/assistify-threading/server/publications/threadsOfRoom.js b/packages/assistify-threading/server/publications/threadsOfRoom.js new file mode 100644 index 0000000000000..5b9b81dfe4a27 --- /dev/null +++ b/packages/assistify-threading/server/publications/threadsOfRoom.js @@ -0,0 +1,32 @@ +import { Meteor } from 'meteor/meteor'; +import { RocketChat } from 'meteor/rocketchat:lib'; + +Meteor.publish('threadsOfRoom', function(rid, limit = 50) { + if (!this.userId) { + return this.ready(); + } + const publication = this; + + const user = RocketChat.models.Users.findOneById(this.userId); + if (!user) { + return this.ready(); + } + if (!Meteor.call('canAccessRoom', rid, this.userId)) { + return this.ready(); + } + const cursorHandle = RocketChat.models.Messages.findByRoomIdAndType(rid, 'create-thread', { sort: { ts: -1 }, limit }).observeChanges({ + added(_id, record) { + return publication.added('rocketchat_threads_of_room', _id, record); + }, + changed(_id, record) { + return publication.changed('rocketchat_threads_of_room', _id, record); + }, + removed(_id) { + return publication.removed('rocketchat_threads_of_room', _id); + }, + }); + this.ready(); + return this.onStop(function() { + return cursorHandle.stop(); + }); +}); From 701ad20dee1bad724c9d6636552915e1313ff447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Sun, 6 Jan 2019 01:59:13 +0100 Subject: [PATCH 085/124] Threads: Display last change on instead of age --- .../client/views/fieldTypeThreadLastMessageAge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js b/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js index 976978355403f..91afd7b56eae9 100644 --- a/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js +++ b/packages/assistify-threading/client/views/fieldTypeThreadLastMessageAge.js @@ -5,7 +5,7 @@ import moment from 'moment'; Template.LastMessageAge.helpers({ lastMessageAge() { const lastMessageTimestamp = Template.instance().data.field.lm; - return moment(lastMessageTimestamp).fromNow(); + return moment(lastMessageTimestamp).format('LLL'); }, }); From e9f1faed940b1865ef44e23db3960d01bab8632f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Sun, 6 Jan 2019 02:07:24 +0100 Subject: [PATCH 086/124] Fix filenames Git somewhat does not recognize case-changes of files --- .../client/views/{threadList.html => ThreadList.html} | 0 .../client/views/{threadList.js => ThreadList.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/assistify-threading/client/views/{threadList.html => ThreadList.html} (100%) rename packages/assistify-threading/client/views/{threadList.js => ThreadList.js} (100%) diff --git a/packages/assistify-threading/client/views/threadList.html b/packages/assistify-threading/client/views/ThreadList.html similarity index 100% rename from packages/assistify-threading/client/views/threadList.html rename to packages/assistify-threading/client/views/ThreadList.html diff --git a/packages/assistify-threading/client/views/threadList.js b/packages/assistify-threading/client/views/ThreadList.js similarity index 100% rename from packages/assistify-threading/client/views/threadList.js rename to packages/assistify-threading/client/views/ThreadList.js From 89a1db88cd20e53e645b5206bca20db6cc8fc892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20J=C3=A4gle?= Date: Fri, 1 Feb 2019 23:16:45 +0100 Subject: [PATCH 087/124] Add missing imports --- package-lock.json | 420 ++++++++---------- .../client/createThreadMessageAction.js | 1 + .../client/views/ThreadList.js | 1 + .../server/methods/createThread.js | 1 + packages/rocketchat-katex/package-lock.json | 2 +- .../client/components/header/header.js | 2 +- 6 files changed, 199 insertions(+), 228 deletions(-) diff --git a/package-lock.json b/package-lock.json index 174266c775e55..b9cb11dd2a192 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1345,7 +1345,7 @@ }, "axios": { "version": "0.18.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz", "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", "requires": { "follow-redirects": "^1.3.0", @@ -1396,7 +1396,7 @@ }, "babel-core": { "version": "6.9.1", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.9.1.tgz", + "resolved": "http://registry.npmjs.org/babel-core/-/babel-core-6.9.1.tgz", "integrity": "sha1-SNRx7r9N5GngqUL+RW3MlLGL6A0=", "dev": true, "requires": { @@ -1707,7 +1707,7 @@ }, "babel-plugin-add-module-exports": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz", "integrity": "sha1-mumh9KjcZ/DN7E9K7aHkOl/2XiU=", "dev": true }, @@ -1728,79 +1728,79 @@ }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", "dev": true }, "babel-plugin-syntax-async-generators": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", "dev": true }, "babel-plugin-syntax-class-constructor-call": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", "dev": true }, "babel-plugin-syntax-class-properties": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", "dev": true }, "babel-plugin-syntax-decorators": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", "dev": true }, "babel-plugin-syntax-do-expressions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", "dev": true }, "babel-plugin-syntax-dynamic-import": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", "dev": true }, "babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", "dev": true }, "babel-plugin-syntax-export-extensions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", "dev": true }, "babel-plugin-syntax-flow": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", "dev": true }, "babel-plugin-syntax-function-bind": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", "dev": true }, "babel-plugin-syntax-jsx": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", "dev": true }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", "dev": true }, @@ -2207,7 +2207,7 @@ }, "babel-preset-es2015": { "version": "6.3.13", - "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.3.13.tgz", + "resolved": "http://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.3.13.tgz", "integrity": "sha1-l9zn7ykuGMubK3VF2AxZPCjZUX8=", "dev": true, "requires": { @@ -2235,7 +2235,7 @@ }, "babel-preset-react": { "version": "6.3.13", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.3.13.tgz", + "resolved": "http://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.3.13.tgz", "integrity": "sha1-E9VeBqZfqqoHw5v2Op2DbgMhFvo=", "dev": true, "requires": { @@ -2249,7 +2249,7 @@ }, "babel-preset-stage-0": { "version": "6.3.13", - "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.3.13.tgz", + "resolved": "http://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.3.13.tgz", "integrity": "sha1-eKN8VvCzmI8qeZMtywzrj/N3sNE=", "dev": true, "requires": { @@ -3194,6 +3194,12 @@ } } }, + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "dev": true + }, "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", @@ -3580,7 +3586,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "requires": { "core-util-is": "~1.0.0", @@ -3856,7 +3862,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -4024,7 +4030,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4113,7 +4119,7 @@ "mocha": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", - "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "integrity": "sha1-fYbPvPNcuCnidUwy4XNV7AUzh5Q=", "dev": true, "requires": { "browser-stdout": "1.3.0", @@ -4131,13 +4137,13 @@ "commander": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=", "dev": true }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -4243,7 +4249,7 @@ "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "integrity": "sha1-iD992rwWUUKyphQn8zUt7RldGj4=", "dev": true, "requires": { "has-flag": "^2.0.0" @@ -4351,6 +4357,19 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" }, + "chromedriver": { + "version": "2.45.0", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-2.45.0.tgz", + "integrity": "sha512-Qwmcr+2mU3INeR6mVsQ8gO00vZpL8ZeTJLclX44C0dcs88jrSDgckPqbG+qkVX+m2L/aOPnF0lYgPdOiOiLt5w==", + "dev": true, + "requires": { + "del": "^3.0.0", + "extract-zip": "^1.6.7", + "mkdirp": "^0.5.1", + "request": "^2.88.0", + "tcp-port-used": "^1.0.1" + } + }, "ci-info": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", @@ -5016,7 +5035,7 @@ }, "d": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { @@ -5285,7 +5304,7 @@ }, "deprecate": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/deprecate/-/deprecate-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/deprecate/-/deprecate-1.0.0.tgz", "integrity": "sha1-ZhSQ7SQokWpsiIPYg05WRvTkpKg=" }, "des.js": { @@ -5332,7 +5351,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "requires": { "core-util-is": "~1.0.0", @@ -6532,7 +6551,7 @@ }, "external-editor": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, "requires": { @@ -6673,7 +6692,7 @@ "dependencies": { "lodash": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", "dev": true }, @@ -6998,23 +7017,21 @@ "dev": true, "optional": true, "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -7027,20 +7044,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -7096,14 +7110,14 @@ "dev": true, "optional": true, "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" } }, "glob": { @@ -7112,12 +7126,12 @@ "dev": true, "optional": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "has-unicode": { @@ -7132,7 +7146,7 @@ "dev": true, "optional": true, "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": "^2.1.0" } }, "ignore-walk": { @@ -7141,7 +7155,7 @@ "dev": true, "optional": true, "requires": { - "minimatch": "3.0.4" + "minimatch": "^3.0.4" } }, "inflight": { @@ -7150,15 +7164,14 @@ "dev": true, "optional": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -7170,9 +7183,8 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "isarray": { @@ -7185,9 +7197,8 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -7240,9 +7251,9 @@ "dev": true, "optional": true, "requires": { - "debug": "2.6.9", - "iconv-lite": "0.4.21", - "sax": "1.2.4" + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" } }, "node-pre-gyp": { @@ -7269,8 +7280,8 @@ "dev": true, "optional": true, "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" + "abbrev": "1", + "osenv": "^0.1.4" } }, "npm-bundled": { @@ -7285,8 +7296,8 @@ "dev": true, "optional": true, "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.3" + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" } }, "npmlog": { @@ -7295,17 +7306,16 @@ "dev": true, "optional": true, "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -7317,9 +7327,8 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "os-homedir": { @@ -7340,8 +7349,8 @@ "dev": true, "optional": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "path-is-absolute": { @@ -7362,10 +7371,10 @@ "dev": true, "optional": true, "requires": { - "deep-extend": "0.5.1", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { @@ -7382,13 +7391,13 @@ "dev": true, "optional": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "rimraf": { @@ -7439,11 +7448,10 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -7452,7 +7460,7 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -7460,7 +7468,7 @@ "bundled": true, "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -7496,7 +7504,7 @@ "dev": true, "optional": true, "requires": { - "string-width": "1.0.2" + "string-width": "^1.0.2" } }, "wrappy": { @@ -7595,7 +7603,7 @@ }, "get-stream": { "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "get-value": { @@ -7822,7 +7830,7 @@ "dependencies": { "minimist": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz", "integrity": "sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=", "dev": true } @@ -8541,7 +8549,7 @@ }, "catbox": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/catbox/-/catbox-4.3.0.tgz", + "resolved": "http://registry.npmjs.org/catbox/-/catbox-4.3.0.tgz", "integrity": "sha1-IiN3vWfxKRrA4l0AAC0GWp3385o=", "dev": true, "requires": { @@ -8638,7 +8646,7 @@ }, "joi": { "version": "6.4.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-6.4.1.tgz", + "resolved": "http://registry.npmjs.org/joi/-/joi-6.4.1.tgz", "integrity": "sha1-9Q9CRTVgBo5jg9oVrC0w3Xzra24=", "dev": true, "requires": { @@ -8656,7 +8664,7 @@ }, "moment": { "version": "2.10.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.10.3.tgz", + "resolved": "http://registry.npmjs.org/moment/-/moment-2.10.3.tgz", "integrity": "sha1-CruZ8wf2UhgwjGk17+KcV7Ggon8=", "dev": true } @@ -9286,7 +9294,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "requires": { "core-util-is": "~1.0.0", @@ -9594,6 +9602,12 @@ } } }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, "ipaddr.js": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", @@ -9668,7 +9682,7 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { @@ -9818,7 +9832,7 @@ }, "is-obj": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" }, "is-object": { @@ -9957,6 +9971,12 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, "is-whitespace-character": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz", @@ -9974,6 +9994,17 @@ "integrity": "sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA==", "dev": true }, + "is2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.1.tgz", + "integrity": "sha512-+WaJvnaA7aJySz2q/8sLjMb2Mw14KTplHmSwcSpZ/fWJPkUmqw3YTzSWbPJ7OAwRvdYTWF2Wg+yYJ1AdP5Z8CA==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "ip-regex": "^2.1.0", + "is-url": "^1.2.2" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -10160,7 +10191,7 @@ }, "jsonfile": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "requires": { @@ -11292,7 +11323,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -11314,7 +11345,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" @@ -11463,7 +11494,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "minimist-options": { @@ -11537,7 +11568,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -11720,7 +11751,7 @@ }, "ncp": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", "optional": true }, @@ -11730,11 +11761,6 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - }, "no-case": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", @@ -11867,7 +11893,7 @@ "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -12159,7 +12185,7 @@ }, "os-locale": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "requires": { "lcid": "^1.0.0" @@ -12198,7 +12224,7 @@ }, "p-is-promise": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" }, "p-limit": { @@ -12361,7 +12387,7 @@ "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", "requires": { "pify": "^3.0.0" } @@ -12470,7 +12496,7 @@ }, "es6-promise": { "version": "4.0.5", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz", + "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz", "integrity": "sha1-eILzCt3lskDM+n99eMVIMwlRrkI=", "dev": true }, @@ -13392,7 +13418,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "simple-get": { @@ -13686,7 +13712,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } @@ -13793,7 +13819,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -14305,7 +14331,7 @@ }, "rimraf": { "version": "2.4.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", "requires": { "glob": "^6.0.1" @@ -14413,7 +14439,7 @@ }, "sax": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "resolved": "http://registry.npmjs.org/sax/-/sax-1.2.1.tgz", "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" }, "schema-inspector": { @@ -14450,75 +14476,6 @@ "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" }, - "selenium-standalone": { - "version": "6.15.4", - "resolved": "https://registry.npmjs.org/selenium-standalone/-/selenium-standalone-6.15.4.tgz", - "integrity": "sha512-J4FZzbkgnQ0D148ZgR9a+SqdnXPyKEhWLHP4pg5dP8b3U0CZmfzXL2gp/R4c1FrmXujosueVE57XO9//l4sEaA==", - "dev": true, - "requires": { - "async": "^2.1.4", - "commander": "^2.9.0", - "cross-spawn": "^6.0.0", - "debug": "^4.0.0", - "lodash": "^4.17.4", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "progress": "2.0.1", - "request": "2.88.0", - "tar-stream": "1.6.2", - "urijs": "^1.18.4", - "which": "^1.2.12", - "yauzl": "^2.5.0" - }, - "dependencies": { - "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz", - "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==", - "dev": true - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - } - }, "semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", @@ -14954,22 +14911,6 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" }, - "sshpk": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", - "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "stack-chain": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", @@ -15598,6 +15539,33 @@ "xtend": "^4.0.0" } }, + "tcp-port-used": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.1.tgz", + "integrity": "sha512-rwi5xJeU6utXoEIiMvVBMc9eJ2/ofzB+7nLOdnZuFTmNCLqRiQh2sMG9MqCxHU/69VC/Fwp5dV9306Qd54ll1Q==", + "dev": true, + "requires": { + "debug": "4.1.0", + "is2": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, "tdigest": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", @@ -15630,7 +15598,7 @@ }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, @@ -16933,7 +16901,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", @@ -17032,7 +17000,7 @@ }, "xolvio-ddp": { "version": "0.12.3", - "resolved": "https://registry.npmjs.org/xolvio-ddp/-/xolvio-ddp-0.12.3.tgz", + "resolved": "http://registry.npmjs.org/xolvio-ddp/-/xolvio-ddp-0.12.3.tgz", "integrity": "sha1-NqarlhKyQLWg0cCoNJCK8XwLjwI=", "dev": true, "requires": { @@ -17078,7 +17046,7 @@ }, "bluebird": { "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", "dev": true }, @@ -17090,7 +17058,7 @@ }, "combined-stream": { "version": "0.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", "dev": true, "requires": { @@ -17190,7 +17158,7 @@ }, "readable-stream": { "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { @@ -17202,7 +17170,7 @@ }, "request": { "version": "2.53.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.53.0.tgz", + "resolved": "http://registry.npmjs.org/request/-/request-2.53.0.tgz", "integrity": "sha1-GAo66St7Y5gC5PlUXdj83rcddgw=", "dev": true, "requires": { @@ -17250,7 +17218,7 @@ }, "xolvio-fiber-utils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/xolvio-fiber-utils/-/xolvio-fiber-utils-2.0.3.tgz", + "resolved": "http://registry.npmjs.org/xolvio-fiber-utils/-/xolvio-fiber-utils-2.0.3.tgz", "integrity": "sha1-vsjXDHQGGjFjFbun0w0lyz6C3FA=", "dev": true, "requires": { @@ -17268,7 +17236,7 @@ }, "xolvio-jasmine-expect": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xolvio-jasmine-expect/-/xolvio-jasmine-expect-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/xolvio-jasmine-expect/-/xolvio-jasmine-expect-1.1.0.tgz", "integrity": "sha1-vCud1ghCMR8EV59agtzqaisxnH0=", "dev": true, "requires": { @@ -17324,7 +17292,7 @@ }, "yargs": { "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", "requires": { "camelcase": "^2.0.1", diff --git a/packages/assistify-threading/client/createThreadMessageAction.js b/packages/assistify-threading/client/createThreadMessageAction.js index 6513de87fa23d..646c326554ddf 100644 --- a/packages/assistify-threading/client/createThreadMessageAction.js +++ b/packages/assistify-threading/client/createThreadMessageAction.js @@ -3,6 +3,7 @@ import { RocketChat } from 'meteor/rocketchat:lib'; import { FlowRouter } from 'meteor/kadira:flow-router'; import { ReactiveVar } from 'meteor/reactive-var'; import { Tracker } from 'meteor/tracker'; +import { ChatMessage } from 'meteor/rocketchat:models'; Meteor.startup(function() { const instance = this; diff --git a/packages/assistify-threading/client/views/ThreadList.js b/packages/assistify-threading/client/views/ThreadList.js index c6b4763ff4755..91876eb027dd1 100644 --- a/packages/assistify-threading/client/views/ThreadList.js +++ b/packages/assistify-threading/client/views/ThreadList.js @@ -3,6 +3,7 @@ import { FlowRouter } from 'meteor/kadira:flow-router'; import { ReactiveVar } from 'meteor/reactive-var'; import { Template } from 'meteor/templating'; import { Tracker } from 'meteor/tracker'; +import { ChatSubscription } from 'meteor/rocketchat:models'; Template.ThreadList.events({ 'click .js-create-thread'() { diff --git a/packages/assistify-threading/server/methods/createThread.js b/packages/assistify-threading/server/methods/createThread.js index 144472da97955..a600eb11b3f9d 100644 --- a/packages/assistify-threading/server/methods/createThread.js +++ b/packages/assistify-threading/server/methods/createThread.js @@ -3,6 +3,7 @@ import { RocketChat } from 'meteor/rocketchat:lib'; import { FlowRouter } from 'meteor/kadira:flow-router'; import { Meteor } from 'meteor/meteor'; import { Random } from 'meteor/random'; +import { getAvatarUrlFromUsername } from 'meteor/rocketchat:utils'; /* * When a repostedMessage is eligible to be answered as a independent question then it can be threaded into a new channel. diff --git a/packages/rocketchat-katex/package-lock.json b/packages/rocketchat-katex/package-lock.json index ffa8c00dc2f83..72332574d8de7 100644 --- a/packages/rocketchat-katex/package-lock.json +++ b/packages/rocketchat-katex/package-lock.json @@ -9,7 +9,7 @@ "resolved": "https://registry.npmjs.org/katex/-/katex-0.9.0.tgz", "integrity": "sha512-lp3x90LT1tDZBW2tjLheJ98wmRMRjUHwk4QpaswT9bhqoQZ+XA4cPcjcQBxgOQNwaOSt6ZeL/a6GKQ1of3LFxQ==", "requires": { - "match-at": "0.1.1" + "match-at": "^0.1.1" } }, "match-at": { diff --git a/packages/rocketchat-ui/client/components/header/header.js b/packages/rocketchat-ui/client/components/header/header.js index f23792285c0b8..7f401b52fd7b3 100644 --- a/packages/rocketchat-ui/client/components/header/header.js +++ b/packages/rocketchat-ui/client/components/header/header.js @@ -4,7 +4,7 @@ import { Template } from 'meteor/templating'; import { FlowRouter } from 'meteor/kadira:flow-router'; import { t, roomTypes, handleError } from 'meteor/rocketchat:utils'; import { TabBar, fireGlobalEvent } from 'meteor/rocketchat:ui-utils'; -import { ChatSubscription, Rooms } from 'meteor/rocketchat:models'; +import { ChatSubscription, ChatRoom, Rooms } from 'meteor/rocketchat:models'; import { settings } from 'meteor/rocketchat:settings'; const isSubscribed = (_id) => ChatSubscription.find({ rid: _id }).count() > 0; From 46f65b44715d3436624583ee143f95627fe30a0f Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Wed, 13 Feb 2019 16:02:17 -0200 Subject: [PATCH 088/124] removed sidenav button --- packages/rocketchat-ui-sidenav/client/sideNav.html | 3 --- packages/rocketchat-ui-sidenav/client/sideNav.js | 8 -------- 2 files changed, 11 deletions(-) diff --git a/packages/rocketchat-ui-sidenav/client/sideNav.html b/packages/rocketchat-ui-sidenav/client/sideNav.html index 6426a606fe014..d5aa78944ffa5 100644 --- a/packages/rocketchat-ui-sidenav/client/sideNav.html +++ b/packages/rocketchat-ui-sidenav/client/sideNav.html @@ -2,9 +2,6 @@