Merge pull request #8101 from RocketChat/dynamic-popover

[FIX] Dynamic popover
# Conflicts:
#	packages/rocketchat-ui-master/public/icons.svg
pull/8689/head
Rodrigo Nascimento 8 years ago
parent eab15e96c8
commit 8643d35542
No known key found for this signature in database
GPG Key ID: CFCE33B7B01AC335
  1. 18
      packages/rocketchat-lib/client/MessageAction.js
  2. 10
      packages/rocketchat-lib/lib/messageBox.js
  3. 2
      packages/rocketchat-reactions/client/init.js
  4. 43
      packages/rocketchat-theme/client/imports/components/message-box.css
  5. 15
      packages/rocketchat-theme/client/imports/components/messages.css
  6. 54
      packages/rocketchat-theme/client/imports/components/popover.css
  7. 2
      packages/rocketchat-theme/client/imports/components/sidebar/rooms-list.css
  8. 48
      packages/rocketchat-theme/client/imports/components/sidebar/sidebar-account.css
  9. 8
      packages/rocketchat-theme/client/imports/components/sidebar/sidebar-item.css
  10. 9
      packages/rocketchat-theme/client/imports/components/sidebar/sidebar.css
  11. 14
      packages/rocketchat-theme/client/imports/components/sidebar/toolbar.css
  12. 7
      packages/rocketchat-theme/client/imports/general/base.css
  13. 26
      packages/rocketchat-theme/client/imports/general/base_old.css
  14. 2
      packages/rocketchat-theme/client/imports/general/variables.css
  15. 6
      packages/rocketchat-ui-master/client/main.js
  16. 1
      packages/rocketchat-ui-master/public/icons.svg
  17. 26
      packages/rocketchat-ui-message/client/message.html
  18. 3
      packages/rocketchat-ui-message/client/message.js
  19. 34
      packages/rocketchat-ui-message/client/messageBox.html
  20. 62
      packages/rocketchat-ui-message/client/messageBox.js
  21. 4
      packages/rocketchat-ui-message/startup/messageBoxActions.js
  22. 63
      packages/rocketchat-ui-sidenav/client/accountBox.html
  23. 133
      packages/rocketchat-ui-sidenav/client/accountBox.js
  24. 71
      packages/rocketchat-ui/client/lib/popover.js
  25. 28
      packages/rocketchat-ui/client/views/app/popover.html
  26. 133
      packages/rocketchat-ui/client/views/app/popover.js
  27. 41
      packages/rocketchat-ui/client/views/app/room.js
  28. 3
      packages/rocketchat-ui/package.js
  29. 2
      tests/end-to-end/ui/04-main-elements-render.js
  30. 2
      tests/end-to-end/ui/06-messaging.js
  31. 36
      tests/pageobjects/main-content.page.js
  32. 16
      tests/pageobjects/side-nav.page.js

@ -1,4 +1,4 @@
/* globals popover chatMessages cordova */
/* globals chatMessages cordova */
import moment from 'moment';
import toastr from 'toastr';
@ -91,10 +91,6 @@ RocketChat.MessageAction = new class {
}
return `${ Meteor.absoluteUrl().replace(/\/$/, '') + routePath }?msg=${ msgId }`;
}
closePopover() {
popover.close();
}
};
Meteor.startup(function() {
@ -120,7 +116,6 @@ Meteor.startup(function() {
input.value += text;
input.focus();
$(input).trigger('change').trigger('input');
RocketChat.MessageAction.closePopover();
},
condition(message) {
if (RocketChat.models.Subscriptions.findOne({rid: message.rid}) == null) {
@ -138,10 +133,9 @@ Meteor.startup(function() {
icon: 'edit',
label: 'Edit',
context: ['message', 'message-mobile'],
action(e) {
const message = $(e.currentTarget).closest('.message')[0];
chatMessages[Session.get('openedRoom')].edit(message);
RocketChat.MessageAction.closePopover();
action() {
const messageId = this._arguments[1]._id;
chatMessages[Session.get('openedRoom')].edit(document.getElementById(messageId));
},
condition(message) {
if (RocketChat.models.Subscriptions.findOne({
@ -181,7 +175,6 @@ Meteor.startup(function() {
context: ['message', 'message-mobile'],
action() {
const message = this._arguments[1];
RocketChat.MessageAction.closePopover();
chatMessages[Session.get('openedRoom')].confirmDeleteMsg(message);
},
condition(message) {
@ -226,7 +219,6 @@ Meteor.startup(function() {
action(event) {
const message = this._arguments[1];
const permalink = RocketChat.MessageAction.getPermaLink(message._id);
RocketChat.MessageAction.closePopover();
if (Meteor.isCordova) {
cordova.plugins.clipboard.copy(permalink);
} else {
@ -253,7 +245,6 @@ Meteor.startup(function() {
context: ['message', 'message-mobile'],
action(event) {
const message = this._arguments[1].msg;
RocketChat.MessageAction.closePopover();
if (Meteor.isCordova) {
cordova.plugins.clipboard.copy(message);
} else {
@ -288,7 +279,6 @@ Meteor.startup(function() {
input.value += text;
input.focus();
$(input).trigger('change').trigger('input');
RocketChat.MessageAction.closePopoverreaction-message();
},
condition(message) {
if (RocketChat.models.Subscriptions.findOne({rid: message.rid}) == null) {

@ -47,4 +47,14 @@ RocketChat.messageBox.actions = new class {
return this.actions[group].filter(action => !action.condition || action.condition());
}
getById(id) {
const messageActions = this.actions;
let actions = [];
Object.keys(messageActions).forEach(function(action) {
actions = actions.concat(messageActions[action]);
});
return actions.filter(action => action.id === id);
}
};

@ -1,5 +1,5 @@
Template.room.events({
'click .add-reaction'(event) {
'click .add-reaction, click [data-message-action="reaction-message"]'(event) {
event.preventDefault();
event.stopPropagation();
const data = Blaze.getData(event.currentTarget);

@ -85,13 +85,13 @@
cursor: text;
line-height: 20px;
transition: background-color 0.3s;
border-width: var(--message-box-container-border-width);
border-color: var(--message-box-container-border-color);
border-radius: var(--message-box-container-border-radius);
line-height: 20px;
align-items: center;
&.editing {
@ -138,29 +138,12 @@
}
}
&__action-label {
&__action-menu {
position: relative;
& #rc-message-box__action-input:checked ~ .rc-message-box__icon .rc-input__icon-svg {
&.active .rc-input__icon-svg--plus {
transform: rotate(135deg);
}
& .rc-popover {
right: 18px;
bottom: 30px;
&__column {
justify-content: space-between;
}
&__title {
text-transform: none;
color: var(--message-box-popover-title-text-color);
font-size: var(--message-box-popover-title-text-size);
}
}
}
& [data-small] {
@ -242,3 +225,21 @@
}
}
}
.rc-popover--message-box {
& .rc-popover__divider {
display: none;
}
& .rc-popover__title {
text-transform: none;
color: var(--message-box-popover-title-text-color);
font-size: var(--message-box-popover-title-text-size);
&:not(:first-child) {
margin-top: var(--popover-column-padding);
}
}
}

@ -21,18 +21,18 @@
}
}
&__label {
&__menu {
padding: 2px 0;
cursor: pointer;
&:hover {
color: var(--color-button-primary);
&:hover &-icon {
fill: var(--color-button-primary);
}
}
&__menu {
fill: currentColor;
&-icon {
fill: currentColor;
}
}
}
@ -56,10 +56,11 @@
display: block;
visibility: hidden;
opacity: 0;
width: 0;
height: 0;
opacity: 0;
}
& .rc-popover {

@ -20,29 +20,30 @@
}
}
.rc-popover-anchor {
display: none;
&:checked + .rc-popover {
@apply --rc-popover-open;
}
}
.rc-popover {
position: absolute;
position: fixed;
z-index: 9999;
top: 0;
left: 0;
display: none;
will-change: transform;
width: 100vw;
height: 100vh;
&__content {
position: absolute;
display: flex;
padding: var(--popover-padding);
animation: dropdown-show 0.1s cubic-bezier(0.45, 0.05, 0.55, 0.95);
white-space: nowrap;
cursor: default;
opacity: 0;
border-radius: var(--popover-radius);
background-color: var(--popover-background);
@ -119,6 +120,10 @@
margin: 1rem 0;
background: var(--popover-divider-color);
&:last-child {
display: none;
}
}
}
@ -126,6 +131,21 @@
fill: currentColor;
}
@media (width <= 400px) {
.rc-popover {
& .rc-popover__content {
top: initial !important;
bottom: 0;
left: 0 !important;
width: calc(100vw - 16px) !important;
margin: 8px !important;
animation: dropup-show 0.3s cubic-bezier(0.45, 0.05, 0.55, 0.95);
}
}
}
@keyframes dropdown-show {
0% {
transform: translate(0, -2%);
@ -153,15 +173,3 @@
opacity: 1;
}
}
@media (width <= 400px) {
.rc-popover {
&-anchor:checked + .rc-popover {
@apply --rc-popover-open-mobile;
}
&--show {
@apply --rc-popover-open-mobile;
}
}
}

@ -55,6 +55,8 @@
&__toolbar-search {
bottom: 0;
padding: 0 var(--sidebar-small-default-padding) var(--sidebar-small-default-padding) var(--sidebar-small-default-padding);
}
}
}

@ -1,9 +1,18 @@
.sidebar__account {
display: flex;
margin-bottom: 12px;
margin: calc(var(--sidebar-default-padding) / 2) 0;
padding: calc(var(--sidebar-default-padding) / 2) var(--sidebar-default-padding);
align-items: center;
&.active:hover {
cursor: pointer;
background-color: var(--sidebar-background-hover);
}
&--lighten {
& .sidebar__account-username {
color: var(--sidebar-account-username-color-darker);
@ -34,7 +43,6 @@
}
&-username {
overflow: hidden;
flex: 1;
@ -53,7 +61,6 @@
&-visual-status {
max-width: 124px;
margin-right: 8px;
user-select: none;
@ -129,6 +136,7 @@
@media (width <= 400px) {
.sidebar__account {
margin: 0 0 5px;
padding: 5px var(--sidebar-small-default-padding);
&-thumb {
@ -163,3 +171,37 @@
}
}
}
.rc-popover--account {
& [data-type="set-state"] {
& .rc-icon {
font-size: var(--sidebar-account-status-bullet-size);
}
&.rc-popover__item {
&--online {
& .rc-icon {
color: var(--status-online);
}
}
&--away {
& .rc-icon {
color: var(--status-away);
}
}
&--busy {
& .rc-icon {
color: var(--status-busy);
}
}
&--offline {
& .rc-icon {
color: var(--status-invisible);
}
}
}
}
}

@ -68,11 +68,15 @@
&__user-status {
position: absolute;
top: 50%;
left: 4px;
width: var(--sidebar-item-user-status-size);
height: var(--sidebar-item-user-status-size);
transform: translateY(-50%);
border-radius: var(--sidebar-item-user-status-radius);
&--online {
@ -114,6 +118,10 @@
.sidebar-item {
padding-left: 0;
& .badge {
margin: 0 0 0 3px;
}
&__user-status {
right: calc(100% + var(--sidebar-small-item-user-status-size));
left: auto;

@ -57,10 +57,6 @@
}
}
&__header {
padding: var(--sidebar-default-padding);
}
& .unread-rooms {
display: none;
}
@ -87,11 +83,6 @@
width: var(--sidebar-small-width);
&__header {
height: auto;
padding: var(--sidebar-small-default-padding);
}
& .unread-rooms,
& .rooms-list {
padding: 0 var(--sidebar-small-default-padding) var(--sidebar-small-default-padding) var(--sidebar-small-default-padding);

@ -1,4 +1,6 @@
.toolbar {
padding: 0 var(--sidebar-default-padding) var(--sidebar-default-padding);
&__wrapper {
display: flex;
@ -29,6 +31,12 @@
&__icon {
&--plus {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 1.25rem;
}
}
@ -88,3 +96,9 @@
font-size: 1rem;
}
}
@media (width <= 400px) {
.toolbar {
padding: 0 var(--sidebar-small-default-padding) var(--sidebar-small-default-padding);
}
}

@ -101,10 +101,11 @@ button {
}
.rc-icon {
overflow: hidden;
width: 1em;
height: 1em;
height: 1em;
vertical-align: -0.15em;
overflow: hidden;
}

@ -3236,8 +3236,8 @@
overflow: auto;
& tr {
background-color: #ffffff;
border-top: 1px solid #cccccc;
background-color: #ffffff;
&:nth-child(2n) {
background-color: #f6f8fa;
@ -3250,6 +3250,7 @@
& th,
& td {
padding: 6px 13px;
border: 1px solid #dddddd;
}
}
@ -3257,10 +3258,11 @@
& > hr {
height: 3px;
padding: 0;
margin: 12px 0;
background-color: #e7e7e7;
padding: 0;
border: 0;
background-color: #e7e7e7;
}
}
@ -3276,17 +3278,20 @@
}
.rc-old .image-labels {
margin: 5px 0 25px;
display: flex;
margin: 5px 0 25px;
flex-wrap: wrap;
}
.rc-old .image-label {
margin-top: 5px;
margin-right: 5px;
padding: 9px 4px;
border-radius: 2px;
font-size: 12px;
margin-right: 5px;
margin-top: 5px;
&:last-child {
margin-right: 0;
@ -3537,11 +3542,12 @@ body:not(.is-cordova) {
}
& .section {
margin: 20px;
padding: 20px;
border: 1px solid #dddddd;
border-radius: 4px;
background-color: #ffffff;
padding: 20px;
margin: 20px;
}
& > .animated {
@ -5188,18 +5194,20 @@ body:not(.is-cordova) {
&__content {
display: flex;
flex-direction: column;
height: 100%;
padding: 20px;
}
&__header {
flex: 0 0 auto;
padding-bottom: 10px;
}
&__result {
overflow-y: auto;
flex: 1 1 auto;
overflow-y: auto;
}
& .message-cog-container {

@ -129,7 +129,9 @@
--sidebar-width: 280px;
--sidebar-small-width: 90%;
--sidebar-background: var(--color-primary);
--sidebar-background-hover: var(--color-dark-medium);
--sidebar-background-light: var(--color-gray-lightest);
--sidebar-background-light-hover: var(--color-gray-light);
--sidebar-default-padding: 24px;
--sidebar-small-default-padding: 16px;
--sidebar-header-padding: var(--sidebar-default-padding);

@ -68,8 +68,6 @@ Template.body.onRendered(function() {
});
$(document.body).on('click', function(e) {
const target = $(e.target);
if (e.target.tagName === 'A') {
const link = e.currentTarget;
if (link.origin === s.rtrim(Meteor.absoluteUrl(), '/') && /msg=([a-zA-Z0-9]+)/.test(link.search)) {
@ -83,10 +81,6 @@ Template.body.onRendered(function() {
return FlowRouter.go(link.pathname + link.search, null, FlowRouter.current().queryParams);
}
}
if ([...target[0].classList].includes('rc-popover') || target.closest('[data-popover="label"], [data-popover="popover"]').length === 0 && target.data('popover') !== 'anchor') {
$('[data-popover="anchor"]:checked').prop('checked', false);
}
});
Tracker.autorun(function(c) {

@ -60,4 +60,5 @@
<symbol viewBox="0 0 20 20" id="icon-cross-circled"><path d="M733.808 723.266l-208.874-185.666 208.874-185.667c10.566-9.394 11.518-25.574 2.126-36.141-9.394-10.566-25.574-11.522-36.142-2.126l-213.392 189.682-213.392-189.68c-10.568-9.392-26.749-8.44-36.141 2.126-9.394 10.566-8.442 26.749 2.126 36.141l208.874 185.666-208.875 185.666c-10.566 9.394-11.518 25.574-2.126 36.142 5.059 5.691 12.085 8.592 19.142 8.592 6.048 0 12.122-2.131 16.998-6.466l213.394-189.683 213.392 189.683c4.878 4.334 10.949 6.466 16.998 6.466 7.058 0 14.086-2.902 19.144-8.592 9.392-10.568 8.44-26.749-2.126-36.142z"></path><path d="M486.4 1024c-129.922 0-252.067-50.594-343.936-142.464s-142.464-214.014-142.464-343.936c0-129.923 50.595-252.067 142.464-343.936s214.013-142.464 343.936-142.464c129.922 0 252.067 50.595 343.936 142.464s142.464 214.014 142.464 343.936-50.594 252.067-142.464 343.936c-91.869 91.87-214.014 142.464-343.936 142.464zM486.4 102.4c-239.97 0-435.2 195.23-435.2 435.2s195.23 435.2 435.2 435.2 435.2-195.23 435.2-435.2-195.23-435.2-435.2-435.2z"></path></symbol>
<symbol viewBox="0 0 20 20" id="icon-jump"><path d="M11.6 7.257V4L18 9.7l-6.4 5.7v-3.257S2 11.385 2 16c0-9.23 9.6-8.743 9.6-8.743z" stroke="currentColor" stroke-width="1.5" fill="none" fill-rule="evenodd"/></symbol>
<symbol viewBox="0 0 20 20" id="icon-flag"><path d="M12.928 6.063l3.263-3.77a.74.74 0 0 0 .112-.759.71.71 0 0 0-.647-.422H3.141v17.72h1.406v-7.876h11.11a.71.71 0 0 0 .646-.422.691.691 0 0 0-.112-.759l-3.263-3.713zM4.547 9.578V2.547h9.562l-2.643 3.065c-.225.254-.225.647 0 .929l2.643 3.065H4.547v-.028z" fill-rule="nonzero" fill="currentColor"/></symbol>
<symbol viewBox="0 0 20 20" id="icon-circle"><circle cx="10" cy="10" r="9" fill="currentColor" fill-rule="evenodd"/></symbol>
</svg>

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

@ -1,5 +1,5 @@
<template name="message">
<li id="{{actionContext}}{{_id}}" class="message background-transparent-dark-hover {{isSequential}} {{system}} {{t}} {{own}} {{isTemp}} {{chatops}} {{customClass}}" data-username="{{u.username}}" data-groupable="{{isGroupable}}" data-date="{{date}}" data-timestamp="{{timestamp}}">
<li id="{{_id}}" data-context={{actionContext}} class="message background-transparent-dark-hover {{isSequential}} {{system}} {{t}} {{own}} {{isTemp}} {{chatops}} {{customClass}}" data-username="{{u.username}}" data-groupable="{{isGroupable}}" data-date="{{date}}" data-timestamp="{{timestamp}}">
{{#if avatar}}
{{#if avatarFromUsername}}
<button class="thumb user-card-message" data-username="{{u.username}}" tabindex="1">{{> avatar username=avatarFromUsername}}</button>
@ -73,28 +73,8 @@
</div>
{{/if}}
{{#if messageActions 'menu'}}
<label class="message-actions__label" for="message-actions__menu--{{_id}}{{actionContext}}" data-popover="label">
{{> icon block="message-actions__menu" icon="menu"}}
</label>
<input id="message-actions__menu--{{_id}}{{actionContext}}" type="checkbox" class="rc-popover-anchor" data-popover="anchor">
<div class="rc-popover" data-popover="popover">
<div class="rc-popover__wrapper"></div>
<div class="rc-popover__content">
<div class="rc-popover__column">
<ul class="rc-popover__list">
{{#each action in messageActions 'menu'}}
<li class="rc-popover__item {{action.classes}}" data-message-action="{{action.id}}">
{{#if action.icon}}
<span class="rc-popover__icon">
{{> icon block="rc-popover__icon-element" icon=action.icon}}
</span>
{{/if}}
<span class="rc-popover__item-text">{{_ action.label}}</span>
</li>
{{/each}}
</ul>
</div>
</div>
<div class="message-actions__menu">
{{> icon block="message-actions__menu-icon" icon="menu"}}
</div>
{{/if}}
</div>

@ -265,6 +265,9 @@ Template.message.helpers({
return 'hidden';
}
},
actionContext() {
return this.actionContext;
},
messageActions(group) {
let messageGroup = group;
let context = this.actionContext;

@ -92,7 +92,7 @@
</template>
<template name="messageBox__actionsSmall">
<div class="js-message-actions rc-message-box__action-label" data-small>
{{# each actions }}
{{#each actions }}
<span class="js-message-action">
{{> icon block="rc-message-box__action" icon=icon }}
</span>
@ -101,37 +101,11 @@
{{> Template.contentBlock}}
</template>
<template name="messageBox__actions">
<label class="rc-message-box__action-label" for="rc-message-box__action-input" data-popover="label" data-desktop>
<input id="rc-message-box__action-input" type="checkbox" class="rc-popover-anchor" data-popover="anchor">
<div class="rc-popover js-message-actions" data-popover="popover">
<div class="rc-popover__content">
{{# each column in columns }}
<div class="rc-popover__column">
{{#each group in column }}
<div class="rc-popover__column-wrapper">
<h3 class="rc-popover__title">{{_ group.name}}</h3>
<ul class="rc-popover__list">
{{#each group.actions }}
<li class="rc-popover__item" data-action="open" data-open="account">
{{#if icon}}
<span class="rc-popover__icon">
{{> icon block="rc-popover__icon-element" icon=icon }}
</span>
{{/if}}
<span class="rc-popover__item-text">{{_ label}}</span>
</li>
{{/each}}
</ul>
</div>
{{/each}}
</div>
{{/each}}
</div>
</div>
{{#if columns}}
<div class="rc-message-box__action-menu" data-desktop>
{{#if actions}}
<div class="rc-message-box__icon">
{{> icon block="rc-input__icon-svg" icon="plus"}}
</div>
{{/if}}
</label>
</div>
</template>

@ -1,4 +1,4 @@
/* globals fileUpload KonchatNotification chatMessages */
/* globals fileUpload KonchatNotification chatMessages popover */
import toastr from 'toastr';
import moment from 'moment';
@ -134,29 +134,6 @@ const methods = {
actions() {
const groups = RocketChat.messageBox.actions.get();
return Object.keys(groups).reduce((ret, el) => ret.concat(groups[el]), []);
},
columns() {
const groups = RocketChat.messageBox.actions.get();
const sorted = Object.keys(groups).sort((a, b) => groups[b].length - groups[a].length);
const totalColumn = sorted.reduce((total, key) => total + groups[key].length, 0);
const totalPerColumn = Math.ceil(totalColumn / 2);
const columns = [];
let counter = 0;
let index = 0;
sorted.forEach(key => {
const actions = groups[key];
columns[index] = columns[index] || [];
counter += actions.length;
columns[index].push({name: key, actions});
if (counter > totalPerColumn) {
counter = 0;
index++;
}
});
return columns;
}
};
@ -445,8 +422,43 @@ Template.messageBox.events({
},
'click .js-md'(e, t) {
applyMd.apply(this, [e, t]);
}
},
'click .rc-message-box__action-menu'(e) {
const groups = RocketChat.messageBox.actions.get();
const config = {
popoverClass: 'message-box',
columns: [
{
groups: Object.keys(groups).map(group => {
const items = [];
groups[group].forEach(item => {
items.push({
icon: item.icon,
name: t(item.label),
type: 'messagebox-action',
id: item.id
});
});
return {
title: t(group),
items
};
})
}
],
mousePosition: {
x: document.querySelector('.rc-message-box__textarea').getBoundingClientRect().right + 10,
y: document.querySelector('.rc-message-box__textarea').getBoundingClientRect().top
},
data: {
rid: this._id
},
activeElement: e.currentTarget
};
popover.open(config);
}
});
Template.messageBox.onRendered(function() {

@ -4,6 +4,7 @@ import mime from 'mime-type/with-db';
import {VRecDialog} from 'meteor/rocketchat:ui-vrecord';
RocketChat.messageBox.actions.add('Create_new', 'Video_message', {
id: 'video-message',
icon: 'video',
condition: () => (navigator.getUserMedia || navigator.webkitGetUserMedia) && RocketChat.settings.get('FileUpload_Enabled') && RocketChat.settings.get('Message_VideoRecorderEnabled') && (!RocketChat.settings.get('FileUpload_MediaTypeWhiteList') || RocketChat.settings.get('FileUpload_MediaTypeWhiteList').match(/video\/webm|video\/\*/i)),
action({messageBox}) {
@ -12,6 +13,7 @@ RocketChat.messageBox.actions.add('Create_new', 'Video_message', {
});
RocketChat.messageBox.actions.add('Create_new', 'Audio_message', {
id: 'audio-message',
icon: 'mic',
condition: () => (navigator.getUserMedia || navigator.webkitGetUserMedia) && RocketChat.settings.get('FileUpload_Enabled') && RocketChat.settings.get('Message_AudioRecorderEnabled') && (!RocketChat.settings.get('FileUpload_MediaTypeWhiteList') || RocketChat.settings.get('FileUpload_MediaTypeWhiteList').match(/audio\/wav|audio\/\*/i)),
action({event, element}) {
@ -41,6 +43,7 @@ RocketChat.messageBox.actions.add('Create_new', 'Audio_message', {
RocketChat.messageBox.actions.add('Add_files_from', 'Computer', {
id: 'file-upload',
icon: 'computer',
condition: () => RocketChat.settings.get('FileUpload_Enabled'),
action() {
@ -73,6 +76,7 @@ RocketChat.messageBox.actions.add('Add_files_from', 'Computer', {
});
RocketChat.messageBox.actions.add('Share', 'My_location', {
id: 'share-location',
icon: 'map-pin',
condition: () => RocketChat.Geolocation.get() !== false,
action({rid}) {

@ -1,5 +1,5 @@
<template name="accountBox">
<div class="sidebar__account {{#if lighten}}sidebar__account--lighten{{/if}}" aria-label="{{_ "Account"}}" role="region">
<div class="sidebar__account {{#if lighten}}sidebar__account--lighten{{/if}} {{#unless isAnonymous}}active{{/unless}}" aria-label="{{_ "Account"}}" role="region">
{{#with myUserInfo}}
{{#if username}}
<div class="sidebar__account-thumb" data-status='{{visualStatus}}'>
@ -13,67 +13,8 @@
</div>
</div>
{{#unless isAnonymous}}
<label class="sidebar__account-label" for="sidebar__account-menu{{../modifier}}" data-popover="label">
<label class="sidebar__account-label">
{{> icon block="sidebar__account-menu" icon="menu"}}
<input id="sidebar__account-menu{{../modifier}}" type="checkbox" class="rc-popover-anchor" data-popover="anchor" {{isAnonymous}}>
<div class="rc-popover" data-popover="popover">
<div class="rc-popover__content">
<div class="rc-popover__column">
<h3 class="rc-popover__title">{{_ "User"}}</h3>
<ul class="rc-popover__list">
<li class="rc-popover__item" data-status="online" data-action="set-state">
<div class="sidebar__account-status-bullet sidebar__account-status-bullet--online rc-popover__item-icon"></div>
<span class="rc-popover__item-text">{{_ "Online"}}</span>
</li>
<li class="rc-popover__item" data-status="away" data-action="set-state">
<div class="sidebar__account-status-bullet sidebar__account-status-bullet--away rc-popover__item-icon"></div>
<span class="rc-popover__item-text">{{_ "Away" context="male"}}</span>
</li>
<li class="rc-popover__item" data-status="busy" data-action="set-state">
<div class="sidebar__account-status-bullet sidebar__account-status-bullet--busy rc-popover__item-icon"></div>
<span class="rc-popover__item-text">{{_ "Busy" context="male"}}</span>
</li>
<li class="rc-popover__item" data-status="offline" data-action="set-state">
<div class="sidebar__account-status-bullet sidebar__account-status-bullet--invisible rc-popover__item-icon"></div>
<span class="rc-popover__item-text">{{_ "Invisible"}}</span>
</li>
</ul>
<span class="rc-popover__divider"></span>
<ul class="rc-popover__list">
{{#each registeredMenus}}
<li class="rc-popover__item" data-action="open">
{{#if icon}}
<span class="rc-popover__icon">
{{> icon block="rc-popover__icon-element" icon=icon }}
</span>
{{/if}}
<span class="rc-popover__item-text">{{name}}</span>
</li>
{{/each}}
{{#if showAdminOption}}
<li class="rc-popover__item" data-action="open" data-open="administration">
<span class="rc-popover__icon">
{{> icon block="rc-popover__icon-element" icon="customize"}}
</span>
<span class="rc-popover__item-text">{{_ "Administration"}}</span>
</li>
{{/if}}
<li class="rc-popover__item" data-action="open" data-open="account">
<span class="rc-popover__icon">
{{> icon block="rc-popover__icon-element" icon="user"}}
</span>
<span class="rc-popover__item-text">{{_ "My_Account"}}</span>
</li>
<li class="rc-popover__item" data-action="open" data-open="logout">
<span class="rc-popover__icon">
{{> icon block="rc-popover__icon-element" icon="sign-out"}}
</span>
<span class="rc-popover__item-text">{{_ "Logout"}}</span>
</li>
</ul>
</div>
</div>
</div>
</label>
{{/unless}}
{{/if}}

@ -1,3 +1,5 @@
/* globals popover */
Template.accountBox.helpers({
myUserInfo() {
if (Meteor.user() == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')) {
@ -26,14 +28,6 @@ Template.accountBox.helpers({
};
},
showAdminOption() {
return RocketChat.authz.hasAtLeastOnePermission(['view-statistics', 'view-room-administration', 'view-user-administration', 'view-privileged-setting' ]) || (RocketChat.AdminBox.getOptions().length > 0);
},
registeredMenus() {
return AccountBox.getItems();
},
isAnonymous() {
if (Meteor.user() == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')) {
return 'disabled';
@ -42,48 +36,95 @@ Template.accountBox.helpers({
});
Template.accountBox.events({
'click [data-action="set-state"]'(e) {
e.preventDefault();
AccountBox.setStatus(e.currentTarget.dataset.status);
$('[data-popover="anchor"]:checked').prop('checked', false);
RocketChat.callbacks.run('userStatusManuallySet', e.currentTarget.dataset.status);
},
'click [data-action="open"]'(e) {
e.preventDefault();
$('[data-popover="anchor"]:checked').prop('checked', false);
'click .sidebar__account.active'() {
let adminOption;
if (RocketChat.authz.hasAtLeastOnePermission(['view-statistics', 'view-room-administration', 'view-user-administration', 'view-privileged-setting' ]) || (RocketChat.AdminBox.getOptions().length > 0)) {
adminOption = {
icon: 'customize',
name: t('Administration'),
type: 'open',
id: 'administration'
};
}
const open = e.currentTarget.dataset.open;
const accountBox = document.querySelector('.sidebar__account');
switch (open) {
case 'account':
SideNav.setFlex('accountFlex');
SideNav.openFlex();
FlowRouter.go('account');
break;
case 'logout':
const user = Meteor.user();
Meteor.logout(() => {
RocketChat.callbacks.run('afterLogoutCleanUp', user);
Meteor.call('logoutCleanUp', user);
FlowRouter.go('home');
});
break;
case 'administration':
SideNav.setFlex('adminFlex');
SideNav.openFlex();
FlowRouter.go('admin-info');
break;
}
const config = {
popoverClass: 'account',
columns: [
{
groups: [
{
title: t('User'),
items: [
{
icon: 'circle',
name: t('Online'),
type: 'set-state',
id: 'online',
class: 'online'
},
{
icon: 'circle',
name: t('Away'),
type: 'set-state',
id: 'away',
class: 'away'
},
{
icon: 'circle',
name: t('Busy'),
type: 'set-state',
id: 'busy',
class: 'busy'
},
{
icon: 'circle',
name: t('Invisible'),
type: 'set-state',
id: 'offline',
class: 'offline'
}
]
},
{
items: AccountBox.getItems().map(item => {
return {
icon: item.icon,
name: t(item.name),
type: 'open',
id: item.name
};
}).concat([
adminOption,
{
icon: 'user',
name: t('My_Account'),
type: 'open',
id: 'account'
},
{
icon: 'sign-out',
name: t('Logout'),
type: 'open',
id: 'logout'
}
])
}
if (this.href) {
FlowRouter.go(this.href);
}
]
}
],
position: {
top: accountBox.offsetHeight + parseInt(getComputedStyle(accountBox)['padding-bottom'].replace('px', '')),
left: parseInt(getComputedStyle(accountBox)['padding-left'].replace('px', ''))
},
customCSSProperties: {
width: `${ accountBox.offsetWidth - parseInt(getComputedStyle(accountBox)['padding-left'].replace('px', '')) * 2 }px`
}
};
if (this.sideNav != null) {
SideNav.setFlex(this.sideNav);
SideNav.openFlex();
}
popover.open(config);
}
});

@ -1,71 +0,0 @@
/* globals popover */
this.popover = {
close() {
document.querySelectorAll('[data-popover="anchor"]:checked').forEach((checkbox) => {
checkbox.checked = false;
});
}
};
function preventDefault(e) {
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
}
e.returnValue = false;
}
function enableWindowScroll() {
if (window.removeEventListener) {
window.removeEventListener('DOMMouseScroll', preventDefault, false);
}
window.onmousewheel = document.onmousewheel = null;
window.onwheel = null;
}
function disableWindowScroll() {
if (window.addEventListener) {
window.addEventListener('DOMMouseScroll', preventDefault, false);
}
window.onwheel = preventDefault;
}
$(document).on('click', function(e) {
const element = $(e.target);
if ($(element).parents('.message').length) {
if ($(element).data('popover') === 'label' || $(element).data('popover') === 'anchor') {
disableWindowScroll();
$(element).parents('.message').addClass('active');
const popover = $(element).siblings('.rc-popover');
const popoverContent = popover.children('.rc-popover__content');
setTimeout(function() {
const popoverWidth = popoverContent.outerWidth();
const popoverHeight = popoverContent.outerHeight();
const popoverHeightHalf = popoverContent.outerHeight() / 2;
const pointer = $(e.target).offset().top - $('.messages-container header').outerHeight();
const roomHeight = $('.messages-box').outerHeight();
let top;
if (pointer + popoverHeightHalf > roomHeight) {
top = popoverHeight - (roomHeight - pointer);
} else if (popoverHeightHalf < pointer) {
top = popoverHeightHalf;
} else {
top = pointer - 10;
}
popover.css({
top: -top,
right: popoverWidth + 30
});
}, 100);
} else if ($(element).hasClass('rc-popover__wrapper') || $(element).hasClass('rc-popover__item-text') || $(element).hasClass('rc-popover__icon-element')) {
enableWindowScroll();
$(element).parents('.message').removeClass('active');
popover.close();
}
}
});

@ -0,0 +1,28 @@
<template name="popover">
<div class="rc-popover rc-popover--{{popoverClass}}" data-popover="popover" style="display:block;">
<div class="rc-popover__content">
{{#each column in columns}}
<div class="rc-popover__column">
{{#each group in column.groups}}
{{#if group.title}}
<h3 class="rc-popover__title">{{group.title}}</h3>
{{/if}}
<ul class="rc-popover__list">
{{#each item in group.items}}
<li class="rc-popover__item rc-popover__item--{{item.class}}" data-type={{item.type}} data-id={{item.id}} >
{{#if item.icon}}
<span class="rc-popover__icon">
{{> icon block="rc-popover__icon-element" icon=item.icon }}
</span>
{{/if}}
<span class="rc-popover__item-text">{{item.name}}</span>
</li>
{{/each}}
</ul>
<span class="rc-popover__divider"></span>
{{/each}}
</div>
{{/each}}
</div>
</div>
</template>

@ -0,0 +1,133 @@
/* globals popover */
this.popover = {
renderedPopover: null,
open(config) {
this.renderedPopover = Blaze.renderWithData(Template.popover, config, document.body);
},
close() {
Blaze.remove(this.renderedPopover);
const activeElement = this.renderedPopover.dataVar.curValue.activeElement;
if (activeElement) {
$(activeElement).removeClass('active');
}
}
};
Template.popover.onRendered(function() {
$('.rc-popover').click(function(e) {
if (e.currentTarget === e.target) {
popover.close();
}
});
const activeElement = this.data.activeElement;
const popoverContent = this.firstNode.children[0];
const position = this.data.position;
const customCSSProperties = this.data.customCSSProperties;
if (position) {
popoverContent.style.top = `${ position.top }px`;
popoverContent.style.left = `${ position.left }px`;
} else {
const popoverWidth = popoverContent.offsetWidth;
const popoverHeight = popoverContent.offsetHeight;
const popoverHeightHalf = popoverHeight / 2;
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
const mousePosition = this.data.mousePosition;
let top;
if (mousePosition.y <= popoverHeight) {
top = 10;
} else if (mousePosition.y + popoverHeightHalf > windowHeight) {
top = windowHeight - popoverHeight - 10;
} else {
top = mousePosition.y - popoverHeightHalf;
}
let right;
if (mousePosition.x + popoverWidth >= windowWidth) {
right = mousePosition.x - popoverWidth;
} else if (mousePosition.x <= popoverWidth) {
right = 10;
} else if (mousePosition.x <= windowWidth / 2) {
right = mousePosition.x;
} else {
right = mousePosition.x - popoverWidth;
}
popoverContent.style.top = `${ top }px`;
popoverContent.style.left = `${ right }px`;
}
if (customCSSProperties) {
Object.keys(customCSSProperties).forEach(function(property) {
popoverContent.style[property] = customCSSProperties[property];
});
}
if (activeElement) {
$(activeElement).addClass('active');
}
popoverContent.style.opacity = 1;
});
Template.popover.events({
'click [data-type="messagebox-action"]'(event, t) {
const action = RocketChat.messageBox.actions.getById(event.currentTarget.dataset.id);
if ((action[0] != null ? action[0].action : undefined) != null) {
action[0].action({rid: t.data.data.rid, messageBox: document.querySelector('.rc-message-box'), element: event.currentTarget, event});
popover.close();
}
},
'click [data-type="message-action"]'(e, t) {
const button = RocketChat.MessageAction.getButtonById(e.currentTarget.dataset.id);
if ((button != null ? button.action : undefined) != null) {
button.action.call(t.data.data, e, t.data.instance);
popover.close();
}
},
'click [data-type="set-state"]'(e) {
AccountBox.setStatus(e.currentTarget.dataset.id);
RocketChat.callbacks.run('userStatusManuallySet', e.currentTarget.dataset.status);
popover.close();
},
'click [data-type="open"]'(e) {
const open = e.currentTarget.dataset.id;
switch (open) {
case 'account':
SideNav.setFlex('accountFlex');
SideNav.openFlex();
FlowRouter.go('account');
break;
case 'logout':
const user = Meteor.user();
Meteor.logout(() => {
RocketChat.callbacks.run('afterLogoutCleanUp', user);
Meteor.call('logoutCleanUp', user);
FlowRouter.go('home');
});
break;
case 'administration':
SideNav.setFlex('adminFlex');
SideNav.openFlex();
FlowRouter.go('admin-info');
break;
}
if (this.href) {
FlowRouter.go(this.href);
}
if (this.sideNav != null) {
SideNav.setFlex(this.sideNav);
SideNav.openFlex();
}
popover.close();
}
});

@ -539,13 +539,42 @@ Template.room.events({
Template.instance().atBottom = true;
return chatMessages[RocketChat.openedRoom].input.focus();
},
'click .message [data-message-action]'(e, t) {
const button = RocketChat.MessageAction.getButtonById(e.currentTarget.dataset.messageAction);
if ((button != null ? button.action : undefined) != null) {
popover.close();
button.action.call(this, e, t);
'click .message-actions__menu'(e, i) {
let context = $(e.target).parents('.message').data('context');
if (!context) {
context = 'message';
}
const [, message] = this._arguments;
const items = RocketChat.MessageAction.getButtons(message, context, 'menu').map(item => {
return {
icon: item.icon,
name: t(item.label),
type: 'message-action',
id: item.id
};
});
const config = {
columns: [
{
groups: [
{
items
}
]
}
],
instance: i,
data: this,
mousePosition: {
x: e.clientX,
y: e.clientY
},
activeElement: $(e.currentTarget).parents('.message')[0]
};
popover.open(config);
},
'click .mention-link'(e, instance) {

@ -47,7 +47,6 @@ Package.onUse(function(api) {
api.addFiles('client/lib/msgTyping.js', 'client');
api.addFiles('client/lib/notification.js', 'client');
api.addFiles('client/lib/parentTemplate.js', 'client');
api.addFiles('client/lib/popover.js', 'client');
api.addFiles('client/lib/readMessages.js', 'client');
api.addFiles('client/lib/rocket.js', 'client');
api.addFiles('client/lib/RoomHistoryManager.js', 'client');
@ -95,6 +94,7 @@ Package.onUse(function(api) {
api.addFiles('client/views/app/userSearch.html', 'client');
api.addFiles('client/views/app/videoCall/videoButtons.html', 'client');
api.addFiles('client/views/app/videoCall/videoCall.html', 'client');
api.addFiles('client/views/app/popover.html', 'client');
api.addFiles('client/views/app/photoswipe.html', 'client');
api.addFiles('client/views/cmsPage.js', 'client');
@ -112,6 +112,7 @@ Package.onUse(function(api) {
api.addFiles('client/views/app/secretURL.js', 'client');
api.addFiles('client/views/app/videoCall/videoButtons.js', 'client');
api.addFiles('client/views/app/videoCall/videoCall.js', 'client');
api.addFiles('client/views/app/popover.js', 'client');
api.addFiles('client/views/app/photoswipe.js', 'client');
api.addFiles('client/components/icon.html', 'client');

@ -91,7 +91,7 @@ describe('[Main Elements Render]', function() {
});
after(() => {
sideNav.accountMenu.click();
mainContent.popoverWrapper.click();
});
it('it should show online button', () => {

@ -105,7 +105,7 @@ function messageActionsTest() {
});
after(() => {
mainContent.closeMessageActionMenu();
mainContent.popoverWrapper.click();
});
it('it should show the message action menu', () => {

@ -32,20 +32,19 @@ class MainContent extends Page {
get lastMessageUserTag() { return browser.element('.message:last-child .role-tag'); }
get lastMessageImg() { return browser.element('.message:last-child .attachment-image img'); }
get lastMessageTextAttachment() { return browser.element('.message:last-child .attachment-text'); }
get messageOptionsBtn() { return browser.element('.message:last-child .message-actions__label'); }
get messageReply() { return browser.element('.message:last-child .rc-popover [data-message-action=reply-message]'); }
get messageActionMenu() { return browser.element('.message:last-child .rc-popover'); }
get messageActionMenuWrapper() { return browser.element('.message:last-child .rc-popover__wrapper'); }
get messageEdit() { return browser.element('.message:last-child .rc-popover [data-message-action=edit-message]'); }
get messageDelete() { return browser.element('.message:last-child .rc-popover [data-message-action=delete-message]'); }
get messagePermalink() { return browser.element('.message:last-child .rc-popover [data-message-action=permalink]'); }
get messageCopy() { return browser.element('.message:last-child .rc-popover [data-message-action=copy]'); }
get messageQuote() { return browser.element('.message:last-child .rc-popover [data-message-action=quote-message]'); }
get messageStar() { return browser.element('.message:last-child .rc-popover [data-message-action=star-message]'); }
get messageUnread() { return browser.element('.message:last-child .rc-popover [data-message-action=mark-message-as-unread]'); }
// get messageReaction() { return browser.element('.message:last-child .rc-popover [data-message-action=reaction-message]'); }
get messagePin() { return browser.element('.message:last-child .rc-popover [data-message-action=pin-message]'); }
// get messageClose() { return browser.element('.message:last-child .rc-popover [data-message-action=rc-popover-close]'); }
get messageOptionsBtn() { return browser.element('.message:last-child .message-actions__menu'); }
get messageActionMenu() { return browser.element('.rc-popover__content'); }
get messageReply() { return browser.element('[data-id="reply-message"][data-type="message-action"]'); }
get messageEdit() { return browser.element('[data-id="edit-message"][data-type="message-action"]'); }
get messageDelete() { return browser.element('[data-id="delete-message"][data-type="message-action"]'); }
get messagePermalink() { return browser.element('[data-id="permalink"][data-type="message-action"]'); }
get messageCopy() { return browser.element('[data-id="copy"][data-type="message-action"]'); }
get messageQuote() { return browser.element('[data-id="quote-message"][data-type="message-action"]'); }
get messageStar() { return browser.element('[data-id="star-message"][data-type="message-action"]'); }
get messageUnread() { return browser.element('[data-id="mark-message-as-unread"][data-type="message-action"]'); }
// get messageReaction() { return browser.element('.message-actions__button[data-message-action="reaction-message"]'); }
get messagePin() { return browser.element('[data-id="pin-message"][data-type="message-action"]'); }
// get messageClose() { return browser.element('[data-id="rc-popover-close"][data-type="message-action"]'); }
// Emojis
get emojiPickerMainScreen() { return browser.element('.emoji-picker'); }
@ -66,6 +65,9 @@ class MainContent extends Page {
get emojiGrinning() { return browser.element('.emoji-picker .emoji-grinning'); }
get emojiSmile() { return browser.element('.emoji-picker .emoji-smile'); }
// Popover
get popoverWrapper() { return browser.element('.rc-popover'); }
// Sends a message and wait for the message to equal the text sent
sendMessage(text) {
this.setTextToInput(text);
@ -124,12 +126,6 @@ class MainContent extends Page {
browser.pause(100);
}
closeMessageActionMenu() {
browser.moveToObject(this.messageActionMenu.selector, -30, -30);
browser.buttonPress(0);
this.messageActionMenu.waitForVisible(5000, true);
}
setLanguageToEnglish() {
this.settingLanguageSelect.click();
this.settingLanguageEnglish.click();

@ -10,15 +10,15 @@ class SideNav extends Page {
// Account box
get accountBoxUserName() { return browser.element('.sidebar__account-username'); }
get accountBoxUserAvatar() { return browser.element('.sidebar__account .avatar-image'); }
get accountMenu() { return browser.element('.sidebar__account-menu'); }
get accountMenu() { return browser.element('.sidebar__account'); }
get popOverContent() { return browser.element('.rc-popover__content'); }
get statusOnline() { return browser.element('[data-status="online"]'); }
get statusAway() { return browser.element('[data-status="away"]'); }
get statusBusy() { return browser.element('[data-status="busy"]'); }
get statusOffline() { return browser.element('[data-status="offline"]'); }
get account() { return browser.element('[data-open="account"]'); }
get admin() { return browser.element('[data-open="administration"]'); }
get logout() { return browser.element('[data-open="logout"]'); }
get statusOnline() { return browser.element('[data-id="online"]'); }
get statusAway() { return browser.element('[data-id="away"]'); }
get statusBusy() { return browser.element('[data-id="busy"]'); }
get statusOffline() { return browser.element('[data-id="offline"]'); }
get account() { return browser.element('[data-id="account"][data-type="open"]'); }
get admin() { return browser.element('[data-id="administration"][data-type="open"]'); }
get logout() { return browser.element('[data-id="logout"][data-type="open"]'); }
get sideNavBar() { return browser.element('.sidebar'); }
// Toolbar

Loading…
Cancel
Save