diff --git a/.meteor/packages b/.meteor/packages index 7e790f6a67b7..16683a222d90 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -81,3 +81,4 @@ yasaricli:slugify yasinuslu:blaze-meta rocketchat:colors raix:push@2.6.13-rc.1 +monbro:mongodb-mapreduce-aggregation diff --git a/.meteor/versions b/.meteor/versions index a922af0abb46..173c8fc3150e 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -85,6 +85,7 @@ mizzao:autocomplete@0.5.1 mizzao:timesync@0.3.3 mobile-status-bar@1.0.3 momentjs:moment@2.10.6 +monbro:mongodb-mapreduce-aggregation@1.0.1 mongo@1.1.0 mongo-livedata@1.0.8 mrt:reactive-store@0.0.1 diff --git a/client/stylesheets/base.less b/client/stylesheets/base.less index acc9d46f3502..a78549742b83 100644 --- a/client/stylesheets/base.less +++ b/client/stylesheets/base.less @@ -658,6 +658,10 @@ label.required:after { &.meteor-developer { background-color: #de4f4f; } + &.button-block { + display: block; + width: 100%; + } } .sec-header { @@ -2766,6 +2770,23 @@ a.github-fork { } } } + .edit-form { + white-space: normal; + h3 { + font-size: 24px; + margin-bottom: 8px; + line-height: 22px; + } + p { + line-height: 18px; + font-size: 12px; + font-weight: 300; + color: @secondary-font-color; + } + > .input-line { + margin-top: 20px; + } + } } .user-image-status(@color) { @@ -3451,6 +3472,15 @@ a.github-fork { } } +.statistics-table { + border: 1px solid black; + th, td { + border: 1px solid black; + text-align: left; + padding: 3px 10px; + } +} + .rocket-team { display: block; li { diff --git a/client/views/admin/adminStatistics.coffee b/client/views/admin/adminStatistics.coffee index 76fabb590b5f..f0b2a93e3420 100644 --- a/client/views/admin/adminStatistics.coffee +++ b/client/views/admin/adminStatistics.coffee @@ -1,9 +1,45 @@ Template.adminStatistics.helpers isAdmin: -> return Meteor.user().admin is true + isReady: -> + return Template.instance().ready.get() + statistics: -> + return Template.instance().statistics.get() + inGB: (size) -> + if size > 1073741824 + return _.numberFormat(size / 1024 / 1024 / 1024, 2) + ' GB' + return _.numberFormat(size / 1024 / 1024, 2) + ' MB' + humanReadable: (time) -> + days = Math.floor time / 86400 + hours = Math.floor (time % 86400) / 3600 + minutes = Math.floor ((time % 86400) % 3600) / 60 + seconds = ((time % 86400) % 3600) % 60 + out = "" + if days > 0 + out += "#{days} #{TAPi18next.t 'project:days'}, " + if hours > 0 + out += "#{hours} #{TAPi18next.t 'project:hours'}, " + if minutes > 0 + out += "#{minutes} #{TAPi18next.t 'project:minutes'}, " + if seconds > 0 + out += "#{seconds} #{TAPi18next.t 'project:seconds'}" + return out + numFormat: (number) -> + return _.numberFormat(number, 2) -Template.adminUsers.onRendered -> +Template.adminStatistics.onRendered -> Tracker.afterFlush -> SideNav.setFlex "adminFlex" SideNav.openFlex() +Template.adminStatistics.onCreated -> + instance = @ + @statistics = new ReactiveVar {} + @ready = new ReactiveVar false + + Meteor.call 'generateStatistics', (error, statistics) -> + instance.ready.set true + if error + toastr.error error.reason + else + instance.statistics.set statistics diff --git a/client/views/admin/adminStatistics.html b/client/views/admin/adminStatistics.html index 305758f8b03e..0ad5174396b4 100644 --- a/client/views/admin/adminStatistics.html +++ b/client/views/admin/adminStatistics.html @@ -10,7 +10,96 @@

{{#unless isAdmin}}

You are not authorized to view this page.

{{else}} - + {{#if isReady}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{_ "Stats_Total_Users"}}{{statistics.totalUsers}}
{{_ "Stats_Active_Users"}}{{statistics.activeUsers}}
{{_ "Stats_Non_Active_Users"}}{{statistics.nonActiveUsers}}
{{_ "Stats_Online_Users"}}{{statistics.onlineUsers}}
{{_ "Stats_Offline_Users"}}{{statistics.offlineUsers}}
{{_ "Stats_Total_Rooms"}}{{statistics.totalRooms}}
{{_ "Stats_Total_Channels"}}{{statistics.totalChannels}}
{{_ "Stats_Total_Private_Groups"}}{{statistics.totalPrivateGroups}}
{{_ "Stats_Total_Direct_Messages"}}{{statistics.totalDirect}}
{{_ "Stats_Max_Room_Users"}}{{statistics.maxRoomUsers}}
{{_ "Stats_Avg_Channel_Users"}}{{numFormat statistics.avgChannelUsers}}
{{_ "Stats_Avg_Private_Group_Users"}}{{numFormat statistics.avgPrivateGroupUsers}}
{{_ "Stats_OS_Type"}}{{statistics.os.type}}
{{_ "Stats_OS_Platform"}}{{statistics.os.platform}}
{{_ "Stats_OS_Arch"}}{{statistics.os.arch}}
{{_ "Stats_OS_Release"}}{{statistics.os.release}}
{{_ "Stats_OS_Uptime"}}{{humanReadable statistics.os.uptime}}
{{_ "Stats_OS_Loadavg"}}{{numFormat statistics.os.loadavg.[0]}}, {{numFormat statistics.os.loadavg.[1]}}, {{numFormat statistics.os.loadavg.[2]}}
{{_ "Stats_OS_Totalmem"}}{{inGB statistics.os.totalmem}}
{{_ "Stats_OS_Freemem"}}{{inGB statistics.os.freemem}}
{{_ "Stats_OS_Cpus"}}{{statistics.os.cpus.length}}
+ {{else}} + {{_ "Please_wait_statistics"}} + {{/if}} {{/unless}} diff --git a/client/views/admin/users/adminUserChannels.coffee b/client/views/admin/users/adminUserChannels.coffee index 55c4b5d448c8..f7f5520e9215 100644 --- a/client/views/admin/users/adminUserChannels.coffee +++ b/client/views/admin/users/adminUserChannels.coffee @@ -1,3 +1,11 @@ Template.adminUserChannels.helpers type: -> - return if @t is 'd' then 'at' else if @t is 'p' then 'lock' else 'hash' \ No newline at end of file + return if @t is 'd' then 'at' else if @t is 'p' then 'lock' else 'hash' + route: -> + return switch @t + when 'd' + FlowRouter.path('direct', {username: @name}) + when 'p' + FlowRouter.path('group', {name: @name}) + when 'c' + FlowRouter.path('channel', {name: @name}) diff --git a/client/views/admin/users/adminUserChannels.html b/client/views/admin/users/adminUserChannels.html index 468a4951e92c..a2f020d077f5 100644 --- a/client/views/admin/users/adminUserChannels.html +++ b/client/views/admin/users/adminUserChannels.html @@ -1,5 +1,5 @@ \ No newline at end of file diff --git a/client/views/admin/users/adminUserEdit.coffee b/client/views/admin/users/adminUserEdit.coffee new file mode 100644 index 000000000000..569d7a668307 --- /dev/null +++ b/client/views/admin/users/adminUserEdit.coffee @@ -0,0 +1,35 @@ +Template.adminUserEdit.helpers + email: -> + return @emails?[0]?.address + +Template.adminUserEdit.events + 'click .cancel': (e, t) -> + e.stopPropagation() + e.preventDefault() + t.cancel() + + 'click .save': (e, t) -> + e.stopPropagation() + e.preventDefault() + t.save() + +Template.adminUserEdit.onCreated -> + instance = @ + + @cancel = -> + $('.user-info-content').hide() + $('#adminUserInfo').show() + + @save = -> + userData = { _id: Template.currentData()._id } + userData.name = $("#name", ".edit-form").val() + + unless userData._id and userData.name + toastr.error TAPi18next.t 'project:The_field_is_required', TAPi18next.t 'project:Name' + else + Meteor.call 'updateUser', userData, (error, result) -> + if result + toastr.success t('User_updated_successfully') + instance.cancel() + if error + toastr.error error.reason \ No newline at end of file diff --git a/client/views/admin/users/adminUserEdit.html b/client/views/admin/users/adminUserEdit.html new file mode 100644 index 000000000000..f74026430b50 --- /dev/null +++ b/client/views/admin/users/adminUserEdit.html @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/client/views/admin/users/adminUserInfo.coffee b/client/views/admin/users/adminUserInfo.coffee index 75caa12027ed..19873b20ad13 100644 --- a/client/views/admin/users/adminUserInfo.coffee +++ b/client/views/admin/users/adminUserInfo.coffee @@ -20,21 +20,45 @@ Template.adminUserInfo.helpers return "UTC #{@utcOffset}" Template.adminUserInfo.events - 'click .deactivate': -> + 'click .deactivate': (e) -> + e.stopPropagation() + e.preventDefault() Meteor.call 'setUserActiveStatus', Template.currentData()._id, false, (error, result) -> if result toastr.success t('User_has_been_deactivated') if error toastr.error error.reason - 'click .activate': -> + 'click .activate': (e) -> + e.stopPropagation() + e.preventDefault() Meteor.call 'setUserActiveStatus', Template.currentData()._id, true, (error, result) -> if result toastr.success t('User_has_been_activated') if error toastr.error error.reason + + 'click .make-admin': (e) -> + e.stopPropagation() + e.preventDefault() + Meteor.call 'setAdminStatus', Template.currentData()._id, true, (error, result) -> + if result + toastr.success t('User_is_now_an_admin') + if error + toastr.error error.reason + + 'click .remove-admin': (e) -> + e.stopPropagation() + e.preventDefault() + Meteor.call 'setAdminStatus', Template.currentData()._id, false, (error, result) -> + if result + toastr.success t('User_is_no_longer_an_admin') + if error + toastr.error error.reason - 'click .delete': -> + 'click .delete': (e) -> + e.stopPropagation() + e.preventDefault() _id = Template.currentData()._id swal { title: t('Are_you_sure') @@ -58,3 +82,9 @@ Template.adminUserInfo.events if error toastr.error error.reason + 'click .edit-user': (e) -> + e.stopPropagation() + e.preventDefault() + + $('.user-info-content').hide() + $('#user-edit-form').show() diff --git a/client/views/admin/users/adminUserInfo.html b/client/views/admin/users/adminUserInfo.html index 693a24683eb8..0567daf89ba8 100644 --- a/client/views/admin/users/adminUserInfo.html +++ b/client/views/admin/users/adminUserInfo.html @@ -13,11 +13,17 @@

{{name}}

\ No newline at end of file diff --git a/client/views/admin/users/adminUsers.coffee b/client/views/admin/users/adminUsers.coffee index cf7eb79298df..bb9828828e3f 100644 --- a/client/views/admin/users/adminUsers.coffee +++ b/client/views/admin/users/adminUsers.coffee @@ -12,7 +12,7 @@ Template.adminUsers.helpers userData: -> return Meteor.users.findOne Session.get 'adminUsersSelected' userChannels: -> - return ChatSubscription.find({ "u._id": Session.get 'settingsUsersSelected' }, { fields: { rid: 1, name: 1, t: 1 }, sort: { t: 1, name: 1 } }).fetch() + return ChatSubscription.find({ "u._id": Session.get 'adminUsersSelected' }, { fields: { rid: 1, name: 1, t: 1 }, sort: { t: 1, name: 1 } }).fetch() isLoading: -> return 'btn-loading' unless Template.instance().ready?.get() hasMore: -> @@ -47,7 +47,7 @@ Template.adminUsers.onCreated -> @autorun -> if Session.get 'adminUsersSelected' - channelSubscription = instance.subscribe 'userChannels', Session.get 'settingsUsersSelected' + channelSubscription = instance.subscribe 'userChannels', Session.get 'adminUsersSelected' @users = -> filter = _.trim instance.filter?.get() @@ -57,7 +57,7 @@ Template.adminUsers.onCreated -> else query = {} - return Meteor.users.find(query, { limit: instance.limit?.get(), sort: { username: 1 } }).fetch() + return Meteor.users.find(query, { limit: instance.limit?.get(), sort: { username: 1, name: 1 } }).fetch() Template.adminUsers.onRendered -> Tracker.afterFlush -> @@ -86,25 +86,11 @@ Template.adminUsers.events Session.set 'adminUsersSelected', $(e.currentTarget).data('id') Session.set 'flexOpened', true - 'click .user-info-tabs a': (e) -> + 'click .info-tabs a': (e) -> e.preventDefault() - $('.user-info-tabs a').removeClass 'active' + $('.info-tabs a').removeClass 'active' $(e.currentTarget).addClass 'active' - 'click .deactivate': -> - Meteor.call 'setUserActiveStatus', Session.get('adminUsersSelected'), false, (error, result) -> - if result - toastr.success t('User_has_been_deactivated') - if error - toastr.error error.reason - - 'click .activate': -> - Meteor.call 'setUserActiveStatus', Session.get('adminUsersSelected'), true, (error, result) -> - if result - toastr.success t('User_has_been_activated') - if error - toastr.error error.reason - $('.user-info-content').hide() $($(e.currentTarget).attr('href')).show() diff --git a/client/views/admin/users/adminUsers.html b/client/views/admin/users/adminUsers.html index 629e15dafcef..7a7e66433705 100644 --- a/client/views/admin/users/adminUsers.html +++ b/client/views/admin/users/adminUsers.html @@ -63,6 +63,9 @@

{{name}}

{{> adminUserChannels}} {{/each}} + {{/if}} diff --git a/client/views/app/sideNav/directMessagesFlex.html b/client/views/app/sideNav/directMessagesFlex.html index beb03ad88f7a..ebaca7cf4eb2 100644 --- a/client/views/app/sideNav/directMessagesFlex.html +++ b/client/views/app/sideNav/directMessagesFlex.html @@ -13,7 +13,7 @@

{{_ "Create_new_direct_message_room"}}

{{#if error}}
- Ops! + {{_ "Oops!"}} {{#each error}}

{{_ "The_field_is_required" error}}

{{/each}} diff --git a/client/views/login/form.coffee b/client/views/login/form.coffee index 0a2972fd5dad..eafffecefc32 100644 --- a/client/views/login/form.coffee +++ b/client/views/login/form.coffee @@ -24,7 +24,7 @@ Template.loginForm.helpers return 'hidden' unless Template.instance().state.get() is 'login' showBackToLoginLink: -> - return 'hidden' unless Template.instance().state.get() in ['register', 'forgot-password', 'email-verification'] + return 'hidden' unless Template.instance().state.get() in ['register', 'forgot-password', 'email-verification', 'wait-activation'] btnLoginSave: -> switch Template.instance().state.get() @@ -37,6 +37,9 @@ Template.loginForm.helpers when 'forgot-password' return t('Reset_password') + waitActivation: -> + return Template.instance().state.get() is 'wait-activation' + Template.loginForm.events 'submit #login-card': (event, instance) -> event.preventDefault() @@ -75,6 +78,8 @@ Template.loginForm.events if error?.error is 'no-valid-email' toastr.success t('We_have_sent_registration_email') instance.state.set 'login' + else if error?.error is 'inactive-user' + instance.state.set 'wait-activation' # else # FlowRouter.go 'index' else diff --git a/client/views/login/form.html b/client/views/login/form.html index d140ced1918a..9f36885c0675 100644 --- a/client/views/login/form.html +++ b/client/views/login/form.html @@ -1,37 +1,45 @@