diff --git a/packages/rocketchat-theme/client/imports/components/modal/create-channel.css b/packages/rocketchat-theme/client/imports/components/modal/create-channel.css index dd308b743e0..285f8c237b0 100644 --- a/packages/rocketchat-theme/client/imports/components/modal/create-channel.css +++ b/packages/rocketchat-theme/client/imports/components/modal/create-channel.css @@ -3,6 +3,9 @@ } .create-channel { + animation-name: fadeIn; + animation-duration: 1s; + &__header, &__switches, &__inputs, @@ -31,3 +34,4 @@ width: 50%; } } +@keyframes fadeIn{0%{opacity:0}100%{opacity:1}} diff --git a/packages/rocketchat-theme/client/imports/components/modal/full-modal.css b/packages/rocketchat-theme/client/imports/components/modal/full-modal.css index 97b0939bd81..51c5462da0e 100644 --- a/packages/rocketchat-theme/client/imports/components/modal/full-modal.css +++ b/packages/rocketchat-theme/client/imports/components/modal/full-modal.css @@ -12,6 +12,7 @@ display: flex; justify-content: center; + &__wrapper { position: relative; width: var(--modal-wrapper-width); @@ -36,3 +37,10 @@ height: 10px; } } + + +@media (width < 1024px) { + .full-modal { + padding: 50px; + } +} diff --git a/packages/rocketchat-theme/client/imports/components/sidebar.css b/packages/rocketchat-theme/client/imports/components/sidebar.css index 38268a35bae..f6af060bf15 100644 --- a/packages/rocketchat-theme/client/imports/components/sidebar.css +++ b/packages/rocketchat-theme/client/imports/components/sidebar.css @@ -17,6 +17,7 @@ flex-direction: column; z-index: 2; position: relative; + transition: transform .3s; &--flex { position: absolute; @@ -32,6 +33,7 @@ user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + transition: opacity .3s; } &__header { diff --git a/packages/rocketchat-ui-sidenav/client/toolbar.js b/packages/rocketchat-ui-sidenav/client/toolbar.js index a3741ddc33c..cd398a4de38 100644 --- a/packages/rocketchat-ui-sidenav/client/toolbar.js +++ b/packages/rocketchat-ui-sidenav/client/toolbar.js @@ -228,6 +228,8 @@ Template.toolbar.events({ 'click [role="search"] button, touchend [role="search"] button'(e) { if (RocketChat.authz.hasAtLeastOnePermission(['create-c', 'create-p'])) { + // TODO: resolve this name menu/sidebar/sidebav/flex... + menu.close(); FlowRouter.go('create-channel'); } else { e.preventDefault(); diff --git a/packages/rocketchat-ui/client/lib/menu.js b/packages/rocketchat-ui/client/lib/menu.js index b4453306db0..a187856579b 100644 --- a/packages/rocketchat-ui/client/lib/menu.js +++ b/packages/rocketchat-ui/client/lib/menu.js @@ -81,7 +81,8 @@ this.menu = new class extends EventEmitter { if (this.blockmove) { return; } - + this.sidebar.css('transition', 'none'); + this.sidebarWrap.css('transition', 'none'); if (this.movestarted === true || absX > 5) { this.movestarted = true; if (this.isRtl) { @@ -129,8 +130,6 @@ this.menu = new class extends EventEmitter { return; } this.movestarted = false; - this.mainContent[0].style.transition = null; - this.wrapper.css('overflow', ''); if (this.isRtl) { if (this.isOpen()) { return this.diff >= -max ? this.close() : this.open(); @@ -167,6 +166,9 @@ this.menu = new class extends EventEmitter { this.sidebarWrap.css('background-color', ''); this.sidebar.css('transform', ''); this.sidebar.css('box-shadow', ''); + this.sidebar.css('transition', ''); + this.sidebarWrap.css('transition', ''); + this.wrapper && this.wrapper.css('overflow', ''); }); this.on('open', () => { this.sidebar.css('box-shadow', '0 0 15px 1px rgba(0,0,0,.3)'); @@ -213,6 +215,8 @@ this.menu.on('clickOut', function() { }); this.menu.on('close', function() { + this.sidebar.css('transition', ''); + this.sidebarWrap.css('transition', ''); if (passClosePopover) { passClosePopover = false; return; diff --git a/packages/rocketchat-ui/client/views/app/createChannel.html b/packages/rocketchat-ui/client/views/app/createChannel.html index 4d38a752f73..a38a4cc6a83 100644 --- a/packages/rocketchat-ui/client/views/app/createChannel.html +++ b/packages/rocketchat-ui/client/views/app/createChannel.html @@ -4,10 +4,10 @@

New Channel

Channels are where your team communicates.

-
+
-
- +
Names must be all lower case and shorter than 22 characters
- {{#if invalidChannel}} + {{#if inUse}}
-
{{invalidChannel}}
+
canal já existe
{{/if}}
@@ -71,6 +71,6 @@ - + diff --git a/packages/rocketchat-ui/client/views/app/createChannel.js b/packages/rocketchat-ui/client/views/app/createChannel.js index b0b8e7c3af3..96b722e7c8f 100644 --- a/packages/rocketchat-ui/client/views/app/createChannel.js +++ b/packages/rocketchat-ui/client/views/app/createChannel.js @@ -2,10 +2,17 @@ const validateChannelName = (name) => { const reg = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`); return name.length === 0 || reg.test(name); }; + Template.createChannel.helpers({ + inUse() { + const instance = Template.instance(); + return instance.inUse.get(); + }, invalidChannel() { - const name = Template.instance().name.get(); - return !validateChannelName(name); + const instance = Template.instance(); + const invalid = instance.invalid.get(); + const inUse = instance.inUse.get(); + return invalid || inUse; }, readOnlyIsDisabled() { return 'disabled'; @@ -19,9 +26,12 @@ Template.createChannel.helpers({ return t(type === 'p' ? 'Just invited people can access this channel': 'Everyone can access this channel'); }, createIsDisabled() { + const instance = Template.instance(); + const invalid = instance.invalid.get(); + const inUse = instance.inUse.get(); const name = Template.instance().name.get(); - if (name.length === 0 || !validateChannelName(name)) { + if (name.length === 0 || invalid || inUse === true || inUse === undefined) { return 'disabled'; } return ''; @@ -46,11 +56,61 @@ Template.createChannel.events({ input.value = modified; document.activeElement === input && e && /input/i.test(e.type) && (input.selectionEnd = position + input.value.length - length); - t.name.set(modified); + t.invalid.set(!validateChannelName(input.value)); + if (input.value !== t.name.get()) { + t.inUse.set(undefined); + t.checkChannel(input.value); + t.name.set(modified); + } + }, + 'submit form'(e, instance) { + e.preventDefault(); + const name = e.target.name.value; + const type = instance.type.get(); + const isPrivate = type === 'p'; + const readOnly = false;//instance.find('#channel-ro').checked; + + if (instance.invalid.get() || instance.inUse.get()) { + return e.target.name.focus(); + } + Meteor.call(isPrivate ? 'createPrivateGroup' : 'createChannel', name, instance.selectedUsers.get(), readOnly, function(err, result) { + if (err) { + if (err.error === 'error-invalid-name') { + return instance.invalid.set(true); + } + if (err.error === 'error-duplicate-channel-name') { + return instance.inUse.set(true); + } + return; + } + if (!isPrivate) { + RocketChat.callbacks.run('aftercreateCombined', { _id: result.rid, name }); + } + return FlowRouter.go(isPrivate ? 'group' : 'channel', { name }, FlowRouter.current().queryParams); + }); + return false; } }); +Template.createChannel.onRendered(function functionName() { + this.firstNode.querySelector('[name=name]').focus(); +}); + Template.createChannel.onCreated(function() { this.name = new ReactiveVar(''); this.type = new ReactiveVar('d'); + this.inUse = new ReactiveVar(undefined); + this.invalid = new ReactiveVar(false); + this.selectedUsers = new ReactiveVar([]); + this.checkChannel = _.debounce((name) => { + if (validateChannelName(name)) { + return Meteor.call('roomNameExists', name, (error, result) => { + if (error) { + return; + } + this.inUse.set(result); + }); + } + this.inUse.set(undefined); + }, 1000); }); diff --git a/server/methods/roomNameExists.js b/server/methods/roomNameExists.js new file mode 100644 index 00000000000..7f35660dae8 --- /dev/null +++ b/server/methods/roomNameExists.js @@ -0,0 +1,13 @@ +Meteor.methods({ + roomNameExists(rid) { + check(rid, String); + + if (!Meteor.userId()) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { + method: 'roomExists' + }); + } + const room = RocketChat.models.Rooms.findOneByName(rid); + return !!room; + } +});