diff options
Diffstat (limited to 'client/components/settings')
-rw-r--r-- | client/components/settings/invitationCode.js | 2 | ||||
-rw-r--r-- | client/components/settings/peopleBody.jade | 90 | ||||
-rw-r--r-- | client/components/settings/peopleBody.js | 158 | ||||
-rw-r--r-- | client/components/settings/peopleBody.styl | 15 | ||||
-rw-r--r-- | client/components/settings/settingBody.jade | 33 | ||||
-rw-r--r-- | client/components/settings/settingBody.js | 122 | ||||
-rw-r--r-- | client/components/settings/settingBody.styl | 7 | ||||
-rw-r--r-- | client/components/settings/settingHeader.jade | 9 | ||||
-rw-r--r-- | client/components/settings/settingHeader.styl | 2 |
9 files changed, 404 insertions, 34 deletions
diff --git a/client/components/settings/invitationCode.js b/client/components/settings/invitationCode.js index a403d8ab..c02f860f 100644 --- a/client/components/settings/invitationCode.js +++ b/client/components/settings/invitationCode.js @@ -1,6 +1,6 @@ Template.invitationCode.onRendered(() => { const setting = Settings.findOne(); - if (!setting || !setting.disableRegistration) { + if (setting || setting.disableRegistration) { $('#invitationcode').hide(); } }); diff --git a/client/components/settings/peopleBody.jade b/client/components/settings/peopleBody.jade new file mode 100644 index 00000000..a3506a24 --- /dev/null +++ b/client/components/settings/peopleBody.jade @@ -0,0 +1,90 @@ +template(name="people") + .setting-content + unless currentUser.isAdmin + | {{_ 'error-notAuthorized'}} + else + .content-title + span {{_ 'people'}} + .content-body + .side-menu + ul + li.active + a.js-setting-menu(data-id="people-setting") {{_ 'people'}} + .main-body + if loading.get + +spinner + else if people.get + +peopleGeneral + +template(name="peopleGeneral") + table + tbody + tr + th {{_ 'username'}} + th {{_ 'fullname'}} + th {{_ 'admin'}} + th {{_ 'email'}} + th {{_ 'verified'}} + th {{_ 'createdAt'}} + th {{_ 'active'}} + th + each user in peopleList + +peopleRow(userId=user._id) + +template(name="peopleRow") + tr + td.username {{ userData.username }} + td {{ userData.profile.fullname }} + td + if userData.isAdmin + | {{_ 'yes'}} + else + | {{_ 'no'}} + td {{ userData.emails.[0].address }} + td + if userData.emails.[0].verified + | {{_ 'yes'}} + else + | {{_ 'no'}} + td {{ moment userData.createdAt 'LLL' }} + td + if userData.loginDisabled + | {{_ 'no'}} + else + | {{_ 'yes'}} + td + a.edit-user + | {{_ 'edit'}} + +template(name="editUserPopup") + form + label.hide.userId(type="text" value=user._id) + label + | {{_ 'fullname'}} + input.js-profile-fullname(type="text" value=user.profile.fullname autofocus) + label + | {{_ 'username'}} + span.error.hide.username-taken + | {{_ 'error-username-taken'}} + input.js-profile-username(type="text" value=user.username) + label + | {{_ 'email'}} + span.error.hide.email-taken + | {{_ 'error-email-taken'}} + input.js-profile-email(type="email" value="{{user.emails.[0].address}}") + label + | {{_ 'admin'}} + select.select-role.js-profile-isadmin + option(value="false") {{_ 'no'}} + option(value="true" selected="{{user.isAdmin}}") {{_ 'yes'}} + label + | {{_ 'active'}} + select.select-active.js-profile-isactive + option(value="false") {{_ 'yes'}} + option(value="true" selected="{{user.loginDisabled}}") {{_ 'no'}} + hr + label + | {{_ 'password'}} + input.js-profile-password(type="password") + + input.primary.wide(type="submit" value="{{_ 'save'}}") diff --git a/client/components/settings/peopleBody.js b/client/components/settings/peopleBody.js new file mode 100644 index 00000000..7cc992f2 --- /dev/null +++ b/client/components/settings/peopleBody.js @@ -0,0 +1,158 @@ +const usersPerPage = 25; + +BlazeComponent.extendComponent({ + mixins() { + return [Mixins.InfiniteScrolling]; + }, + onCreated() { + this.error = new ReactiveVar(''); + this.loading = new ReactiveVar(false); + this.people = new ReactiveVar(true); + + this.page = new ReactiveVar(1); + this.loadNextPageLocked = false; + this.callFirstWith(null, 'resetNextPeak'); + this.autorun(() => { + const limit = this.page.get() * usersPerPage; + + this.subscribe('people', limit, () => { + this.loadNextPageLocked = false; + const nextPeakBefore = this.callFirstWith(null, 'getNextPeak'); + this.calculateNextPeak(); + const nextPeakAfter = this.callFirstWith(null, 'getNextPeak'); + if (nextPeakBefore === nextPeakAfter) { + this.callFirstWith(null, 'resetNextPeak'); + } + }); + }); + }, + loadNextPage() { + if (this.loadNextPageLocked === false) { + this.page.set(this.page.get() + 1); + this.loadNextPageLocked = true; + } + }, + calculateNextPeak() { + const element = this.find('.main-body'); + if (element) { + const altitude = element.scrollHeight; + this.callFirstWith(this, 'setNextPeak', altitude); + } + }, + reachNextPeak() { + this.loadNextPage(); + }, + setError(error) { + this.error.set(error); + }, + setLoading(w) { + this.loading.set(w); + }, + peopleList() { + return Users.find({}, { + fields: {_id: true}, + }); + }, +}).register('people'); + +Template.peopleRow.helpers({ + userData() { + const userCollection = this.esSearch ? ESSearchResults : Users; + return userCollection.findOne(this.userId); + }, +}); + +Template.editUserPopup.helpers({ + user() { + return Users.findOne(this.userId); + }, +}); + +BlazeComponent.extendComponent({ + onCreated() { + }, + user() { + return Users.findOne(this.userId); + }, + events() { + return [{ + 'click a.edit-user': Popup.open('editUser'), + }]; + }, +}).register('peopleRow'); + +Template.editUserPopup.events({ + submit(evt, tpl) { + evt.preventDefault(); + const user = Users.findOne(this.userId); + const fullname = tpl.find('.js-profile-fullname').value.trim(); + const username = tpl.find('.js-profile-username').value.trim(); + const password = tpl.find('.js-profile-password').value; + const isAdmin = tpl.find('.js-profile-isadmin').value.trim(); + const isActive = tpl.find('.js-profile-isactive').value.trim(); + const email = tpl.find('.js-profile-email').value.trim(); + + const isChangePassword = password.length > 0; + const isChangeUserName = username !== user.username; + const isChangeEmail = email.toLowerCase() !== user.emails[0].address.toLowerCase(); + + Users.update(this.userId, { + $set: { + 'profile.fullname': fullname, + 'isAdmin': isAdmin === 'true', + 'loginDisabled': isActive === 'true', + }, + }); + + if(isChangePassword){ + Meteor.call('setPassword', password, this.userId); + } + + if (isChangeUserName && isChangeEmail) { + Meteor.call('setUsernameAndEmail', username, email.toLowerCase(), this.userId, function (error) { + const usernameMessageElement = tpl.$('.username-taken'); + const emailMessageElement = tpl.$('.email-taken'); + if (error) { + const errorElement = error.error; + if (errorElement === 'username-already-taken') { + usernameMessageElement.show(); + emailMessageElement.hide(); + } else if (errorElement === 'email-already-taken') { + usernameMessageElement.hide(); + emailMessageElement.show(); + } + } else { + usernameMessageElement.hide(); + emailMessageElement.hide(); + Popup.close(); + } + }); + } else if (isChangeUserName) { + Meteor.call('setUsername', username, this.userId, function (error) { + const usernameMessageElement = tpl.$('.username-taken'); + if (error) { + const errorElement = error.error; + if (errorElement === 'username-already-taken') { + usernameMessageElement.show(); + } + } else { + usernameMessageElement.hide(); + Popup.close(); + } + }); + } else if (isChangeEmail) { + Meteor.call('setEmail', email.toLowerCase(), this.userId, function (error) { + const emailMessageElement = tpl.$('.email-taken'); + if (error) { + const errorElement = error.error; + if (errorElement === 'email-already-taken') { + emailMessageElement.show(); + } + } else { + emailMessageElement.hide(); + Popup.close(); + } + }); + } else Popup.close(); + }, +}); diff --git a/client/components/settings/peopleBody.styl b/client/components/settings/peopleBody.styl new file mode 100644 index 00000000..84db44a7 --- /dev/null +++ b/client/components/settings/peopleBody.styl @@ -0,0 +1,15 @@ +.main-body + overflow: scroll; + +table + border-collapse: collapse; + width: 100%; + color: #000; + + td, th + border: 1px solid #d2d0d0; + text-align: left; + padding: 8px; + + tr:nth-child(even) + background-color: #dddddd; diff --git a/client/components/settings/settingBody.jade b/client/components/settings/settingBody.jade index 5864efd5..5bc7972d 100644 --- a/client/components/settings/settingBody.jade +++ b/client/components/settings/settingBody.jade @@ -14,6 +14,8 @@ template(name="setting") a.js-setting-menu(data-id="email-setting") {{_ 'email'}} li a.js-setting-menu(data-id="account-setting") {{_ 'accounts'}} + li + a.js-setting-menu(data-id="announcement-setting") {{_ 'admin-announcement'}} .main-body if loading.get +spinner @@ -23,6 +25,8 @@ template(name="setting") +email else if accountSetting.get +accountSettings + else if announcementSetting.get + +announcementSettings template(name="general") ul#registration-setting.setting-detail @@ -85,9 +89,12 @@ template(name='email') li button.js-save.primary {{_ 'save'}} + li + button.js-send-smtp-test-email.primary {{_ 'send-smtp-test'}} + template(name='accountSettings') ul#account-setting.setting-detail - li.smtp-form + li.accounts-form .title {{_ 'accounts-allowEmailChange'}} .form-group.flex input.form-control#accounts-allowEmailChange(type="radio" name="allowEmailChange" value="true" checked="{{#if allowEmailChange}}checked{{/if}}") @@ -95,4 +102,28 @@ template(name='accountSettings') input.form-control#accounts-allowEmailChange(type="radio" name="allowEmailChange" value="false" checked="{{#unless allowEmailChange}}checked{{/unless}}") span {{_ 'no'}} li + li.accounts-form + .title {{_ 'accounts-allowUserNameChange'}} + .form-group.flex + input.form-control#accounts-allowUserNameChange(type="radio" name="allowUserNameChange" value="true" checked="{{#if allowUserNameChange}}checked{{/if}}") + span {{_ 'yes'}} + input.form-control#accounts-allowUserNameChange(type="radio" name="allowUserNameChange" value="false" checked="{{#unless allowUserNameChange}}checked{{/unless}}") + span {{_ 'no'}} + li button.js-accounts-save.primary {{_ 'save'}} + +template(name='announcementSettings') + ul#announcement-setting.setting-detail + li + a.flex.js-toggle-activemessage + .materialCheckBox(class="{{#if currentSetting.enabled}}is-checked{{/if}}") + + span {{_ 'admin-announcement-active'}} + li + .admin-announcement(class="{{#if currentSetting.enabled}}{{else}}hide{{/if}}") + ul + li + .title {{_ 'admin-announcement-title'}} + textarea#admin-announcement.form-control= currentSetting.body + li + button.js-announcement-save.primary {{_ 'save'}} diff --git a/client/components/settings/settingBody.js b/client/components/settings/settingBody.js index a2993426..7230d893 100644 --- a/client/components/settings/settingBody.js +++ b/client/components/settings/settingBody.js @@ -1,7 +1,3 @@ -Meteor.subscribe('setting'); -Meteor.subscribe('mailServer'); -Meteor.subscribe('accountSettings'); - BlazeComponent.extendComponent({ onCreated() { this.error = new ReactiveVar(''); @@ -9,6 +5,12 @@ BlazeComponent.extendComponent({ this.generalSetting = new ReactiveVar(true); this.emailSetting = new ReactiveVar(false); this.accountSetting = new ReactiveVar(false); + this.announcementSetting = new ReactiveVar(false); + + Meteor.subscribe('setting'); + Meteor.subscribe('mailServer'); + Meteor.subscribe('accountSettings'); + Meteor.subscribe('announcements'); }, setError(error) { @@ -21,7 +23,7 @@ BlazeComponent.extendComponent({ checkField(selector) { const value = $(selector).val(); - if(!value || value.trim() === ''){ + if (!value || value.trim() === '') { $(selector).parents('li.smtp-form').addClass('has-error'); throw Error('blank field'); } else { @@ -29,7 +31,7 @@ BlazeComponent.extendComponent({ } }, - currentSetting(){ + currentSetting() { return Settings.findOne(); }, @@ -42,35 +44,36 @@ BlazeComponent.extendComponent({ sort: ['title'], }); }, - toggleRegistration(){ + toggleRegistration() { this.setLoading(true); const registrationClosed = this.currentSetting().disableRegistration; - Settings.update(Settings.findOne()._id, {$set:{disableRegistration: !registrationClosed}}); + Settings.update(Settings.findOne()._id, {$set: {disableRegistration: !registrationClosed}}); this.setLoading(false); - if(registrationClosed){ + if (registrationClosed) { $('.invite-people').slideUp(); - }else{ + } else { $('.invite-people').slideDown(); } }, - toggleTLS(){ + toggleTLS() { $('#mail-server-tls').toggleClass('is-checked'); }, - switchMenu(event){ + switchMenu(event) { const target = $(event.target); - if(!target.hasClass('active')){ + if (!target.hasClass('active')) { $('.side-menu li.active').removeClass('active'); target.parent().addClass('active'); const targetID = target.data('id'); this.generalSetting.set('registration-setting' === targetID); this.emailSetting.set('email-setting' === targetID); this.accountSetting.set('account-setting' === targetID); + this.announcementSetting.set('announcement-setting' === targetID); } }, - checkBoard(event){ + checkBoard(event) { let target = $(event.target); - if(!target.hasClass('js-toggle-board-choose')){ + if (!target.hasClass('js-toggle-board-choose')) { target = target.parent(); } const checkboxId = target.attr('id'); @@ -78,7 +81,7 @@ BlazeComponent.extendComponent({ $(`#${checkboxId}`).toggleClass('is-checked'); }, - inviteThroughEmail(){ + inviteThroughEmail() { const emails = $('#email-to-invite').val().trim().split('\n').join(',').split(','); const boardsToInvite = []; $('.js-toggle-board-choose .materialCheckBox.is-checked').each(function () { @@ -101,19 +104,23 @@ BlazeComponent.extendComponent({ } }, - saveMailServerInfo(){ + saveMailServerInfo() { this.setLoading(true); $('li').removeClass('has-error'); - try{ + try { const host = this.checkField('#mail-server-host'); const port = this.checkField('#mail-server-port'); const username = $('#mail-server-username').val().trim(); const password = $('#mail-server-password').val().trim(); const from = this.checkField('#mail-server-from'); const tls = $('#mail-server-tls.is-checked').length > 0; - Settings.update(Settings.findOne()._id, {$set:{'mailServer.host':host, 'mailServer.port': port, 'mailServer.username': username, - 'mailServer.password': password, 'mailServer.enableTLS': tls, 'mailServer.from': from}}); + Settings.update(Settings.findOne()._id, { + $set: { + 'mailServer.host': host, 'mailServer.port': port, 'mailServer.username': username, + 'mailServer.password': password, 'mailServer.enableTLS': tls, 'mailServer.from': from, + }, + }); } catch (e) { return; } finally { @@ -122,7 +129,23 @@ BlazeComponent.extendComponent({ }, - events(){ + sendSMTPTestEmail() { + Meteor.call('sendSMTPTestEmail', (err, ret) => { + if (!err && ret) { /* eslint-disable no-console */ + const message = `${TAPi18n.__(ret.message)}: ${ret.email}`; + console.log(message); + alert(message); + } else { + const reason = err.reason || ''; + const message = `${TAPi18n.__(err.error)}\n${reason}`; + console.log(message, err); + alert(message); + } + /* eslint-enable no-console */ + }); + }, + + events() { return [{ 'click a.js-toggle-registration': this.toggleRegistration, 'click a.js-toggle-tls': this.toggleTLS, @@ -130,25 +153,76 @@ BlazeComponent.extendComponent({ 'click a.js-toggle-board-choose': this.checkBoard, 'click button.js-email-invite': this.inviteThroughEmail, 'click button.js-save': this.saveMailServerInfo, + 'click button.js-send-smtp-test-email': this.sendSMTPTestEmail, }]; }, }).register('setting'); BlazeComponent.extendComponent({ - saveAllowEmailChange() { + + saveAccountsChange() { const allowEmailChange = ($('input[name=allowEmailChange]:checked').val() === 'true'); + const allowUserNameChange = ($('input[name=allowUserNameChange]:checked').val() === 'true'); AccountSettings.update('accounts-allowEmailChange', { - $set: { 'booleanValue': allowEmailChange }, + $set: {'booleanValue': allowEmailChange}, + }); + AccountSettings.update('accounts-allowUserNameChange', { + $set: {'booleanValue': allowUserNameChange}, }); }, allowEmailChange() { return AccountSettings.findOne('accounts-allowEmailChange').booleanValue; }, + allowUserNameChange() { + return AccountSettings.findOne('accounts-allowUserNameChange').booleanValue; + }, events() { return [{ - 'click button.js-accounts-save': this.saveAllowEmailChange, + 'click button.js-accounts-save': this.saveAccountsChange, }]; }, }).register('accountSettings'); + +BlazeComponent.extendComponent({ + onCreated() { + this.loading = new ReactiveVar(false); + }, + + setLoading(w) { + this.loading.set(w); + }, + + currentSetting() { + return Announcements.findOne(); + }, + + saveMessage() { + const message = $('#admin-announcement').val().trim(); + Announcements.update(Announcements.findOne()._id, { + $set: {'body': message}, + }); + }, + + toggleActive() { + this.setLoading(true); + const isActive = this.currentSetting().enabled; + Announcements.update(Announcements.findOne()._id, { + $set: {'enabled': !isActive}, + }); + this.setLoading(false); + if (isActive) { + $('.admin-announcement').slideUp(); + } else { + $('.admin-announcement').slideDown(); + } + }, + + events() { + return [{ + 'click a.js-toggle-activemessage': this.toggleActive, + 'click button.js-announcement-save': this.saveMessage, + }]; + }, +}).register('announcementSettings'); diff --git a/client/components/settings/settingBody.styl b/client/components/settings/settingBody.styl index 118d364c..fec64cee 100644 --- a/client/components/settings/settingBody.styl +++ b/client/components/settings/settingBody.styl @@ -61,10 +61,11 @@ .is-checked border-bottom: 2px solid #2980b9; border-right: 2px solid #2980b9; - - span + + span padding: 0 0.5rem - + + .admin-announcement, .invite-people padding-left 20px; li diff --git a/client/components/settings/settingHeader.jade b/client/components/settings/settingHeader.jade index c22cf5c6..c2d4db3a 100644 --- a/client/components/settings/settingHeader.jade +++ b/client/components/settings/settingHeader.jade @@ -9,13 +9,14 @@ template(name="settingHeaderBar") a.setting-header-btn.settings(href="{{pathFor 'setting'}}") i.fa(class="fa-cog") span {{_ 'settings'}} + + a.setting-header-btn.people(href="{{pathFor 'people'}}") + i.fa(class="fa-users") + span {{_ 'people'}} + a.setting-header-btn.informations(href="{{pathFor 'information'}}") i.fa(class="fa-info-circle") span {{_ 'info'}} -//TODO -// a.setting-header-btn.people -// i.fa(class="fa-users") -// span {{_ 'people'}} else a.setting-header-btn.js-log-in( diff --git a/client/components/settings/settingHeader.styl b/client/components/settings/settingHeader.styl index 995ed26d..3699f180 100644 --- a/client/components/settings/settingHeader.styl +++ b/client/components/settings/settingHeader.styl @@ -22,4 +22,4 @@ + span display: inline-block margin-top: 1px - margin-right: 10px
\ No newline at end of file + margin-right: 10px |