Merge branch 'develop' into feature/better.select
This commit is contained in:
commit
17adf5a6c5
16 changed files with 833 additions and 364 deletions
2
Gemfile
2
Gemfile
|
@ -27,6 +27,7 @@ gem 'rack-cors'
|
|||
gem 'redis'
|
||||
gem 'slack-notifier'
|
||||
gem 'snorlax'
|
||||
gem 'puma'
|
||||
|
||||
# asset stuff
|
||||
gem 'jquery-rails'
|
||||
|
@ -44,7 +45,6 @@ group :test do
|
|||
end
|
||||
|
||||
group :development, :test do
|
||||
gem 'puma'
|
||||
gem 'better_errors'
|
||||
gem 'binding_of_caller'
|
||||
gem 'pry-byebug'
|
||||
|
|
2
Procfile
2
Procfile
|
@ -1,3 +1,3 @@
|
|||
web: bundle exec rails server -p $PORT
|
||||
web: bundle exec puma -p $PORT
|
||||
worker: bundle exec rake jobs:work
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|||
|
||||
The license can be read [here][license].
|
||||
|
||||
Copyright (c) 2016 Connor Turland
|
||||
Copyright (c) 2017 Connor Turland
|
||||
|
||||
[site-beta]: http://metamaps.cc
|
||||
[license]: https://github.com/metamaps/metamaps/blob/develop/LICENSE
|
||||
|
|
263
app/assets/stylesheets/emoji-mart-0.3.5.css
Normal file
263
app/assets/stylesheets/emoji-mart-0.3.5.css
Normal file
|
@ -0,0 +1,263 @@
|
|||
.emoji-mart,
|
||||
.emoji-mart * {
|
||||
box-sizing: border-box;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.emoji-mart {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
|
||||
font-size: 16px;
|
||||
display: inline-block;
|
||||
color: #222427;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 5px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.emoji-mart .emoji-mart-emoji {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.emoji-mart-bar:first-child {
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
.emoji-mart-bar:last-child {
|
||||
border-bottom-left-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
|
||||
.emoji-mart-anchors {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 6px;
|
||||
color: #858585;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.emoji-mart-anchor {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 12px 4px;
|
||||
overflow: hidden;
|
||||
transition: color .1s ease-out;
|
||||
}
|
||||
.emoji-mart-anchor:hover,
|
||||
.emoji-mart-anchor-selected {
|
||||
color: #464646;
|
||||
}
|
||||
|
||||
.emoji-mart-anchor-selected .emoji-mart-anchor-bar {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.emoji-mart-anchor-bar {
|
||||
position: absolute;
|
||||
bottom: -3px; left: 0;
|
||||
width: 100%; height: 3px;
|
||||
background-color: #464646;
|
||||
}
|
||||
|
||||
.emoji-mart-anchors i {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
max-width: 22px;
|
||||
}
|
||||
|
||||
.emoji-mart-anchors svg {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.emoji-mart-scroll {
|
||||
overflow-y: scroll;
|
||||
height: 270px;
|
||||
padding: 0 6px 6px 6px;
|
||||
border: solid #d9d9d9;
|
||||
border-width: 1px 0;
|
||||
}
|
||||
|
||||
.emoji-mart-search {
|
||||
font-size: 16px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: .2em .6em;
|
||||
margin-top: 6px;
|
||||
border-radius: 25px;
|
||||
border: 1px solid #d9d9d9;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.emoji-mart-category .emoji-mart-emoji span {
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.emoji-mart-category .emoji-mart-emoji:hover:before {
|
||||
z-index: 0;
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
background-color: #f4f4f4;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.emoji-mart-category-label {
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
position: -webkit-sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.emoji-mart-category-label span {
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-weight: 500;
|
||||
padding: 5px 6px;
|
||||
background-color: #fff;
|
||||
background-color: rgba(255, 255, 255, .95);
|
||||
}
|
||||
|
||||
.emoji-mart-emoji {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.emoji-mart-no-results {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
padding-top: 70px;
|
||||
color: #858585;
|
||||
}
|
||||
.emoji-mart-no-results span {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.emoji-mart-preview {
|
||||
position: relative;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.emoji-mart-preview-emoji,
|
||||
.emoji-mart-preview-data,
|
||||
.emoji-mart-preview-skins {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.emoji-mart-preview-emoji {
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
.emoji-mart-preview-data {
|
||||
left: 68px; right: 12px;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.emoji-mart-preview-skins {
|
||||
right: 30px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.emoji-mart-preview-name {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.emoji-mart-preview-shortname {
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
.emoji-mart-preview-shortname + .emoji-mart-preview-shortname,
|
||||
.emoji-mart-preview-shortname + .emoji-mart-preview-emoticon,
|
||||
.emoji-mart-preview-emoticon + .emoji-mart-preview-emoticon {
|
||||
margin-left: .5em;
|
||||
}
|
||||
|
||||
.emoji-mart-preview-emoticon {
|
||||
font-size: 11px;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.emoji-mart-title span {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.emoji-mart-title .emoji-mart-emoji {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.emoji-mart-title-label {
|
||||
color: #999A9C;
|
||||
font-size: 26px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.emoji-mart-skin-swatches {
|
||||
font-size: 0;
|
||||
padding: 2px 0;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.emoji-mart-skin-swatches-opened .emoji-mart-skin-swatch {
|
||||
width: 16px;
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.emoji-mart-skin-swatches-opened .emoji-mart-skin-swatch-selected:after {
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
.emoji-mart-skin-swatch {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
vertical-align: middle;
|
||||
transition-property: width, padding;
|
||||
transition-duration: .125s;
|
||||
transition-timing-function: ease-out;
|
||||
}
|
||||
|
||||
.emoji-mart-skin-swatch:nth-child(1) { transition-delay: 0 }
|
||||
.emoji-mart-skin-swatch:nth-child(2) { transition-delay: .03s }
|
||||
.emoji-mart-skin-swatch:nth-child(3) { transition-delay: .06s }
|
||||
.emoji-mart-skin-swatch:nth-child(4) { transition-delay: .09s }
|
||||
.emoji-mart-skin-swatch:nth-child(5) { transition-delay: .12s }
|
||||
.emoji-mart-skin-swatch:nth-child(6) { transition-delay: .15s }
|
||||
|
||||
.emoji-mart-skin-swatch-selected {
|
||||
position: relative;
|
||||
width: 16px;
|
||||
padding: 0 2px;
|
||||
}
|
||||
.emoji-mart-skin-swatch-selected:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%; left: 50%;
|
||||
width: 4px; height: 4px;
|
||||
margin: -2px 0 0 -2px;
|
||||
background-color: #fff;
|
||||
border-radius: 100%;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity .2s ease-out;
|
||||
}
|
||||
|
||||
.emoji-mart-skin {
|
||||
display: inline-block;
|
||||
width: 100%; padding-top: 100%;
|
||||
max-width: 12px;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.emoji-mart-skin-tone-1 { background-color: #ffc93a }
|
||||
.emoji-mart-skin-tone-2 { background-color: #fadcbc }
|
||||
.emoji-mart-skin-tone-3 { background-color: #e0bb95 }
|
||||
.emoji-mart-skin-tone-4 { background-color: #bf8f68 }
|
||||
.emoji-mart-skin-tone-5 { background-color: #9b643d }
|
||||
.emoji-mart-skin-tone-6 { background-color: #594539 }
|
|
@ -1,323 +0,0 @@
|
|||
.collaborator-video {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
cursor: default;
|
||||
color: #FFF;
|
||||
}
|
||||
.collaborator-video .video-receive {
|
||||
position: absolute;
|
||||
width: 160px;
|
||||
padding: 20px 20px 20px 170px;
|
||||
background: #424242;
|
||||
height: 110px;
|
||||
border-top-left-radius: 75px;
|
||||
border-bottom-left-radius: 75px;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
.collaborator-video .video-receive .video-statement {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.collaborator-video .video-receive .btn-group .btn-yes {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.collaborator-video .video-receive .btn-group .btn-no {
|
||||
background-color: #c04f4f;
|
||||
}
|
||||
.collaborator-video .video-receive .btn-group .btn-no:hover {
|
||||
background-color: #A54242;
|
||||
}
|
||||
.collaborator-video .video-cutoff {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
overflow: hidden;
|
||||
border-radius: 75px;
|
||||
z-index: 0;
|
||||
position: relative;
|
||||
-webkit-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
|
||||
-moz-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
|
||||
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
|
||||
}
|
||||
.collaborator-video .video-cutoff video {
|
||||
height: 150px;
|
||||
margin-left: -25px;
|
||||
}
|
||||
.collaborator-video .video-cutoff .collaborator-video-avatar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
display: none;
|
||||
}
|
||||
.collaborator-video .video-audio {
|
||||
position: absolute;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
top: 85%;
|
||||
right: 0px;
|
||||
cursor: pointer;
|
||||
background: url(<%= asset_path 'audio_sprite.png' %>) no-repeat;
|
||||
}
|
||||
.collaborator-video .video-audio:hover {
|
||||
background-position-x: -24px;
|
||||
}
|
||||
.collaborator-video .video-audio.active {
|
||||
background-position-y: -24px;
|
||||
}
|
||||
.collaborator-video .video-video {
|
||||
position: absolute;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
top: 85%;
|
||||
left: 0px;
|
||||
cursor: pointer;
|
||||
background: url(<%= asset_path 'camera_sprite.png' %>) no-repeat;
|
||||
}
|
||||
.collaborator-video .video-video:hover {
|
||||
background-position-x: -24px;
|
||||
}
|
||||
.collaborator-video .video-video.active {
|
||||
background-position-y: -24px;
|
||||
}
|
||||
.collaborator-video.my-video {
|
||||
left: 30px;
|
||||
top: 72px;
|
||||
}
|
||||
#chat-box-wrapper {
|
||||
height: 100%;
|
||||
float: right;
|
||||
}
|
||||
.chat-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 1;
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
background: #424242;
|
||||
box-shadow: -8px 0px 16px 2px rgba(0, 0, 0, 0.23);
|
||||
}
|
||||
.chat-box .chat-button {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: -36px;
|
||||
width: 36px;
|
||||
height: 49px;
|
||||
background: url(<%= asset_path 'junto.png' %>) no-repeat 2px 9px, url(<%= asset_path 'tray_tab.png' %>) no-repeat;
|
||||
cursor: pointer;
|
||||
}
|
||||
.chat-box .chat-button.active {
|
||||
background: url(<%= asset_path 'junto_spinner_dark.gif' %>) no-repeat 2px 8px, url(<%= asset_path 'tray_tab.png' %>) no-repeat !important;
|
||||
}
|
||||
.chat-box .chat-button .chat-unread {
|
||||
background: #DAB539;
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
left: -11px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 11px;
|
||||
border: 2px solid #424242;
|
||||
color: #424242;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
}
|
||||
.chat-box .junto-header {
|
||||
width: 276px;
|
||||
padding: 16px 8px 16px 16px;
|
||||
font-size: 16px;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
background-color: #000000;
|
||||
color: #f5f5f5;
|
||||
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23);
|
||||
}
|
||||
.chat-box .junto-header .cursor-toggle {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 8px;
|
||||
margin-top: -8px;
|
||||
float: right;
|
||||
background: url(<%= asset_path 'cursor_sprite.png' %>) no-repeat;
|
||||
}
|
||||
.chat-box .junto-header .cursor-toggle:hover {
|
||||
background-position-x: -32px;
|
||||
}
|
||||
.chat-box .junto-header .cursor-toggle.active {
|
||||
background-position-y: -32px;
|
||||
}
|
||||
.chat-box .junto-header .video-toggle {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 10px;
|
||||
margin-top: -8px;
|
||||
float: right;
|
||||
background: url(<%= asset_path 'video_sprite.png' %>) no-repeat;
|
||||
}
|
||||
.chat-box .junto-header .video-toggle:hover {
|
||||
background-position-x: -32px;
|
||||
}
|
||||
.chat-box .junto-header .video-toggle.active {
|
||||
background-position-y: -32px;
|
||||
}
|
||||
.chat-box .participants {
|
||||
width: 100%;
|
||||
min-height: 150px;
|
||||
padding: 16px 0px 16px 0px;
|
||||
text-align: left;
|
||||
color: #f5f5f5;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.chat-box .participants .conversation-live {
|
||||
padding: 5px 10px 5px 10px;
|
||||
background: #c04f4f;
|
||||
margin: 5px 10px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.chat-box .participants .conversation-live .call-action {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
color: #EBFF00;
|
||||
}
|
||||
.chat-box .participants .participant {
|
||||
width: 89%;
|
||||
padding: 8px 8px 2px 8px;
|
||||
color: #f5f5f5;
|
||||
font-family: arial, sans-serif;
|
||||
font-size: 13px;
|
||||
line-height: 14px;
|
||||
}
|
||||
.chat-box .participants .participant .chat-participant-image {
|
||||
width: 15%;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
color: #BBB;
|
||||
padding-top: 2px;
|
||||
}
|
||||
.chat-box .participants .participant .chat-participant-image img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 18px;
|
||||
}
|
||||
.chat-box .participants .participant .chat-participant-name {
|
||||
width: 53%;
|
||||
float: left;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
margin-top: 12px;
|
||||
padding: 2px 8px 0;
|
||||
text-align: left;
|
||||
}
|
||||
.chat-box .participants .participant .chat-participant-invite-call,
|
||||
.chat-box .participants .participant .chat-participant-invite-join
|
||||
{
|
||||
float: right;
|
||||
background: #4FC059 url(<%= asset_path 'invitepeer16.png' %>) no-repeat center center;
|
||||
}
|
||||
.chat-box .participants .participant .chat-participant-invite-call.pending,
|
||||
.chat-box .participants .participant .chat-participant-invite-join.pending {
|
||||
background: #dab539 url(<%= asset_path 'ellipsis.gif' %>) no-repeat center center;
|
||||
}
|
||||
.chat-box .participants .participant .chat-participant-participating {
|
||||
float: right;
|
||||
margin-top: 14px;
|
||||
}
|
||||
.chat-box .participants .participant .chat-participant-participating .green-dot {
|
||||
background: #4fc059;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.chat-box .chat-header {
|
||||
width: 276px;
|
||||
padding: 16px 8px 16px 16px;
|
||||
font-size: 16px;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
background-color: #000000;
|
||||
color: #f5f5f5;
|
||||
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23);
|
||||
}
|
||||
.chat-box .chat-header .sound-toggle {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 10px;
|
||||
margin-top: -2px;
|
||||
float: right;
|
||||
background: url(<%= asset_path 'sound_sprite.png' %>) no-repeat;
|
||||
}
|
||||
.chat-box .chat-header .sound-toggle:hover {
|
||||
background-position-x: -24px;
|
||||
}
|
||||
.chat-box .chat-header .sound-toggle.active {
|
||||
background-position-y: -24px;
|
||||
}
|
||||
.chat-box .chat-input {
|
||||
min-height: 80px;
|
||||
width: 94%;
|
||||
padding: 8px 3% 8px 3%;
|
||||
font-size: 13px;
|
||||
outline: none;
|
||||
resize: none;
|
||||
}
|
||||
.chat-box .chat-messages {
|
||||
width: 100%;
|
||||
padding: 16px 0px 0px 0px;
|
||||
overflow-y: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.chat-box .chat-messages .chat-message {
|
||||
width: 89%;
|
||||
padding: 8px 8px 2px 8px;
|
||||
color: #f5f5f5;
|
||||
font-family: arial, sans-serif;
|
||||
font-size: 13px;
|
||||
line-height: 14px;
|
||||
}
|
||||
.chat-box .chat-messages .chat-message a:link {
|
||||
color: #4fb5c0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.chat-box .chat-messages .chat-message a:visited {
|
||||
color: #aea9fd;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.chat-box .chat-messages .chat-message a:hover {
|
||||
color: #dab539;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.chat-box .chat-messages .chat-message .chat-message-user {
|
||||
width: 15%;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
color: #BBB;
|
||||
padding-top: 2px;
|
||||
}
|
||||
.chat-box .chat-messages .chat-message .chat-message-user img {
|
||||
border: 2px solid #424242;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 18px;
|
||||
}
|
||||
.chat-box .chat-messages .chat-message .chat-message-text {
|
||||
width: 73%;
|
||||
float: left;
|
||||
margin-top: 12px;
|
||||
padding: 2px 8px 0;
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.chat-box .chat-messages .chat-message .chat-message-time {
|
||||
float: right;
|
||||
font-size: 10px;
|
||||
color: #757575;
|
||||
}
|
370
app/assets/stylesheets/junto.scss.erb
Normal file
370
app/assets/stylesheets/junto.scss.erb
Normal file
|
@ -0,0 +1,370 @@
|
|||
.collaborator-video {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
cursor: default;
|
||||
color: #FFF;
|
||||
|
||||
.video-receive {
|
||||
position: absolute;
|
||||
width: 160px;
|
||||
padding: 20px 20px 20px 170px;
|
||||
background: #424242;
|
||||
height: 110px;
|
||||
border-top-left-radius: 75px;
|
||||
border-bottom-left-radius: 75px;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
|
||||
.video-statement {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.btn-group {
|
||||
.btn-yes {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.btn-no {
|
||||
background-color: #c04f4f;
|
||||
&:hover {
|
||||
background-color: #A54242;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.video-cutoff {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
overflow: hidden;
|
||||
border-radius: 75px;
|
||||
z-index: 0;
|
||||
position: relative;
|
||||
-webkit-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
|
||||
-moz-box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
|
||||
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23), 10px 10px 10px rgba(0, 0, 0, 0.19);
|
||||
|
||||
video {
|
||||
height: 150px;
|
||||
margin-left: -25px;
|
||||
}
|
||||
.collaborator-video-avatar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.video-audio {
|
||||
position: absolute;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
top: 85%;
|
||||
right: 0px;
|
||||
cursor: pointer;
|
||||
background: url(<%= asset_path 'audio_sprite.png' %>) no-repeat;
|
||||
}
|
||||
.video-audio:hover {
|
||||
background-position-x: -24px;
|
||||
}
|
||||
.video-audio.active {
|
||||
background-position-y: -24px;
|
||||
}
|
||||
.video-video {
|
||||
position: absolute;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
top: 85%;
|
||||
left: 0px;
|
||||
cursor: pointer;
|
||||
background: url(<%= asset_path 'camera_sprite.png' %>) no-repeat;
|
||||
}
|
||||
.video-video:hover {
|
||||
background-position-x: -24px;
|
||||
}
|
||||
.video-video.active {
|
||||
background-position-y: -24px;
|
||||
}
|
||||
}
|
||||
|
||||
.collaborator-video.my-video {
|
||||
left: 30px;
|
||||
top: 72px;
|
||||
}
|
||||
|
||||
#chat-box-wrapper {
|
||||
height: 100%;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.chat-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 1;
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
background: #424242;
|
||||
box-shadow: -8px 0px 16px 2px rgba(0, 0, 0, 0.23);
|
||||
|
||||
.chat-button {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: -36px;
|
||||
width: 36px;
|
||||
height: 49px;
|
||||
background: url(<%= asset_path 'junto.png' %>) no-repeat 2px 9px, url(<%= asset_path 'tray_tab.png' %>) no-repeat;
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
background: url(<%= asset_path 'junto_spinner_dark.gif' %>) no-repeat 2px 8px, url(<%= asset_path 'tray_tab.png' %>) no-repeat !important;
|
||||
}
|
||||
.chat-unread {
|
||||
background: #DAB539;
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
left: -11px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 11px;
|
||||
border: 2px solid #424242;
|
||||
color: #424242;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.junto-header {
|
||||
width: 276px;
|
||||
padding: 16px 8px 16px 16px;
|
||||
font-size: 16px;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
background-color: #000000;
|
||||
color: #f5f5f5;
|
||||
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23);
|
||||
|
||||
.cursor-toggle {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 8px;
|
||||
margin-top: -8px;
|
||||
float: right;
|
||||
background: url(<%= asset_path 'cursor_sprite.png' %>) no-repeat;
|
||||
}
|
||||
.cursor-toggle:hover {
|
||||
background-position-x: -32px;
|
||||
}
|
||||
.cursor-toggle.active {
|
||||
background-position-y: -32px;
|
||||
}
|
||||
.video-toggle {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 10px;
|
||||
margin-top: -8px;
|
||||
float: right;
|
||||
background: url(<%= asset_path 'video_sprite.png' %>) no-repeat;
|
||||
}
|
||||
.video-toggle:hover {
|
||||
background-position-x: -32px;
|
||||
}
|
||||
.video-toggle.active {
|
||||
background-position-y: -32px;
|
||||
}
|
||||
}
|
||||
|
||||
.participants {
|
||||
width: 100%;
|
||||
min-height: 150px;
|
||||
padding: 16px 0px 16px 0px;
|
||||
text-align: left;
|
||||
color: #f5f5f5;
|
||||
overflow-y: auto;
|
||||
|
||||
.conversation-live {
|
||||
padding: 5px 10px 5px 10px;
|
||||
background: #c04f4f;
|
||||
margin: 5px 10px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.conversation-live .call-action {
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
color: #EBFF00;
|
||||
}
|
||||
.participant {
|
||||
width: 89%;
|
||||
padding: 8px 8px 2px 8px;
|
||||
color: #f5f5f5;
|
||||
font-family: arial, sans-serif;
|
||||
font-size: 13px;
|
||||
line-height: 14px;
|
||||
|
||||
.chat-participant-image {
|
||||
width: 15%;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
color: #BBB;
|
||||
padding-top: 2px;
|
||||
}
|
||||
.chat-participant-image img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 18px;
|
||||
}
|
||||
.chat-participant-name {
|
||||
width: 53%;
|
||||
float: left;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
margin-top: 12px;
|
||||
padding: 2px 8px 0;
|
||||
text-align: left;
|
||||
}
|
||||
.chat-participant-invite-call,
|
||||
.chat-participant-invite-join
|
||||
{
|
||||
float: right;
|
||||
background: #4FC059 url(<%= asset_path 'invitepeer16.png' %>) no-repeat center center;
|
||||
}
|
||||
.chat-participant-invite-call.pending,
|
||||
.chat-participant-invite-join.pending {
|
||||
background: #dab539 url(<%= asset_path 'ellipsis.gif' %>) no-repeat center center;
|
||||
}
|
||||
.chat-participant-participating {
|
||||
float: right;
|
||||
margin-top: 14px;
|
||||
}
|
||||
.chat-participant-participating .green-dot {
|
||||
background: #4fc059;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat-header {
|
||||
width: 276px;
|
||||
padding: 16px 8px 16px 16px;
|
||||
font-size: 16px;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
background-color: #000000;
|
||||
color: #f5f5f5;
|
||||
box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.23);
|
||||
|
||||
.sound-toggle {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 10px;
|
||||
margin-top: -2px;
|
||||
float: right;
|
||||
background: url(<%= asset_path 'sound_sprite.png' %>) no-repeat;
|
||||
}
|
||||
.sound-toggle:hover {
|
||||
background-position-x: -24px;
|
||||
}
|
||||
.sound-toggle.active {
|
||||
background-position-y: -24px;
|
||||
}
|
||||
}
|
||||
|
||||
$chat_font_size: 16px;
|
||||
|
||||
.chat-input {
|
||||
min-height: 80px;
|
||||
width: 88%;
|
||||
padding: 8px 9% 8px 3%;
|
||||
font-size: $chat_font_size;
|
||||
outline: none;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.chat-messages {
|
||||
width: 100%;
|
||||
padding: 16px 0px;
|
||||
overflow-y: auto;
|
||||
flex-grow: 1;
|
||||
|
||||
.chat-message {
|
||||
width: 89%;
|
||||
padding: 8px 8px 2px 8px;
|
||||
color: #f5f5f5;
|
||||
font-family: arial, sans-serif;
|
||||
font-size: $chat_font_size;
|
||||
line-height: $chat_font_size + 1px;
|
||||
|
||||
a:link {
|
||||
color: #4fb5c0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:visited {
|
||||
color: #aea9fd;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
color: #dab539;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.chat-message-user {
|
||||
width: 12%;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
color: #BBB;
|
||||
padding-top: 2px;
|
||||
}
|
||||
.chat-message-user img {
|
||||
border: 2px solid #424242;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
.chat-message-meta {
|
||||
padding: 0 8px;
|
||||
float: left;
|
||||
}
|
||||
.chat-message-username {
|
||||
color: #4fc059;
|
||||
}
|
||||
.chat-message-text {
|
||||
width: 80%;
|
||||
float: left;
|
||||
padding: 2px 8px 0;
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.chat-message-time {
|
||||
font-size: 12px;
|
||||
color: #757575;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.new-message-area {
|
||||
position: relative;
|
||||
|
||||
.extra-message-options {
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
bottom: 74px;
|
||||
|
||||
.emoji-picker-button {
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,6 @@
|
|||
|
||||
Metamaps.Loading.setup()
|
||||
</script>
|
||||
<%= render :partial => 'layouts/googleanalytics' if Rails.env.production? %>
|
||||
<%= render :partial => 'layouts/googleanalytics' if ENV["GA_TRACKING_CODE"].present? %>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -3,16 +3,13 @@
|
|||
# Google analytics, rendered on every page
|
||||
#%>
|
||||
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-35984510-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl.' : 'http://') + 'stats.g.doubleclick.net/dc.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
ga('create', '<%= ENV["GA_TRACKING_CODE"] %>', 'auto');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
|
|
|
@ -6,4 +6,4 @@ test:
|
|||
|
||||
production:
|
||||
adapter: redis
|
||||
url: redis://localhost:6379/1
|
||||
url: <%= ENV['REDISTOGO_URL'] %>
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb
|
||||
|
||||
config.action_cable.allowed_request_origins = ['https://metamaps.herokuapp.com', 'http://metamaps.herokuapp.com', 'https://metamaps.cc']
|
||||
|
||||
# log to stdout
|
||||
logger = Logger.new(STDOUT)
|
||||
logger.formatter = config.log_formatter
|
||||
|
|
|
@ -103,7 +103,7 @@ server to see what problems show up:
|
|||
|
||||
#### Upstart service for delayed_worker:
|
||||
|
||||
Put the following code into `/etc/init/metamaps_delayed_worker.conf`:
|
||||
If your system uses upstart for init scripts, put the following code into `/etc/init/metamaps_delayed_job.conf`:
|
||||
|
||||
description "Delayed Jobs Worker for Metamaps"
|
||||
|
||||
|
@ -128,3 +128,30 @@ Then start the service and check the last ten lines of the log file to make sure
|
|||
|
||||
sudo service metamaps_delayed_job start
|
||||
tail /var/log/upstart/metamaps_delayed_job.log
|
||||
|
||||
#### Systemd service for delayed_worker:
|
||||
|
||||
If your system uses systemd for init scripts, ptu the following code into `/etc/systemd/system/metamaps_delayed_job.service`:
|
||||
|
||||
[Unit]
|
||||
Description=metamaps delayed job service
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/rvm/gems/ruby-2.3.0@metamaps/bin/bundle exec rails jobs:work
|
||||
WorkingDirectory=/home/metamaps/metamaps
|
||||
Restart=always
|
||||
User=metamaps
|
||||
Group=metamaps
|
||||
Environment=HOME=/home/metamaps
|
||||
Environment=PATH="/usr/local/rvm/gems/ruby-2.3.0@metamaps/bin:/usr/local/rvm/gems/ruby-2.3.0@global/bin:/usr/local/rvm/rubies/ruby-2.3.0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin"
|
||||
Environment=GEM_PATH="/usr/local/rvm/gems/ruby-2.3.0@metamaps:/usr/local/rvm/gems/ruby-2.3.0@global"
|
||||
Environment=RAILS_ENV="production"
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
Then start the service and check the last ten lines of the log file to make sure it's running OK:
|
||||
|
||||
sudo systemctl start metamaps_delayed_job
|
||||
# ??? how the heck do you check systemd logs??
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
/* global $ */
|
||||
|
||||
import { Parser, HtmlRenderer } from 'commonmark'
|
||||
import { emojiIndex } from 'emoji-mart'
|
||||
import { escapeRegExp } from 'lodash'
|
||||
|
||||
const emojiToShortcodes = {}
|
||||
Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
const emoji = emojiIndex.emojis[key]
|
||||
emojiToShortcodes[emoji.native] = emoji.colons
|
||||
})
|
||||
|
||||
const Util = {
|
||||
// helper function to determine how many lines are needed
|
||||
|
@ -150,6 +158,29 @@ const Util = {
|
|||
canvas.scale(oldAttr.scaleX, oldAttr.scaleY)
|
||||
const newAttr = Util.logCanvasAttributes(canvas)
|
||||
canvas.translate(newAttr.centreCoords.x - oldAttr.centreCoords.x, newAttr.centreCoords.y - oldAttr.centreCoords.y)
|
||||
},
|
||||
removeEmoji: function(withEmoji) {
|
||||
let text = withEmoji
|
||||
Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
const emoji = emojiIndex.emojis[key]
|
||||
text = text.replace(new RegExp(escapeRegExp(emoji.native), 'g'), emoji.colons)
|
||||
})
|
||||
return text
|
||||
},
|
||||
addEmoji: function(withoutEmoji, opts = { emoticons: false }) {
|
||||
let text = withoutEmoji
|
||||
Object.keys(emojiIndex.emojis).forEach(key => {
|
||||
const emoji = emojiIndex.emojis[key]
|
||||
text = text.replace(new RegExp(escapeRegExp(emoji.colons), 'g'), emoji.native)
|
||||
})
|
||||
if (opts.emoticons) {
|
||||
Object.keys(emojiIndex.emoticons).forEach(emoticon => {
|
||||
const key = emojiIndex.emoticons[emoticon]
|
||||
const emoji = emojiIndex.emojis[key]
|
||||
text = text.replace(new RegExp(escapeRegExp(emoticon), 'g'), emoji.native)
|
||||
})
|
||||
}
|
||||
return text
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react'
|
||||
import Autolinker from 'autolinker'
|
||||
import Util from '../../Metamaps/Util'
|
||||
|
||||
const linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false })
|
||||
|
||||
|
@ -18,15 +19,19 @@ function formatDate(created_at) {
|
|||
}
|
||||
|
||||
const Message = props => {
|
||||
const { user_image, user_name, message, created_at } = props
|
||||
const messageHtml = {__html: linker.link(message)}
|
||||
const { user_image, user_name, message, created_at, heading } = props
|
||||
const messageHtml = {__html: linker.link(Util.addEmoji(message, { emoticons: false }))}
|
||||
|
||||
return (
|
||||
<div className="chat-message">
|
||||
<div className="chat-message-user">
|
||||
<img src={user_image} title={user_name} />
|
||||
{heading && <img src={user_image} />}
|
||||
</div>
|
||||
{heading && <div className="chat-message-meta">
|
||||
<span className='chat-message-username'>{user_name}</span>
|
||||
<span className='chat-message-time'>{formatDate(created_at)}</span>
|
||||
</div>}
|
||||
<div className="chat-message-text" dangerouslySetInnerHTML={messageHtml}></div>
|
||||
<div className="chat-message-time">{formatDate(created_at)}</div>
|
||||
<div className="clearfloat"></div>
|
||||
</div>
|
||||
)
|
||||
|
|
70
frontend/src/components/MapChat/NewMessage.js
Normal file
70
frontend/src/components/MapChat/NewMessage.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
import React, { PropTypes, Component } from 'react'
|
||||
import { Emoji, Picker } from 'emoji-mart'
|
||||
import Util from '../../Metamaps/Util'
|
||||
|
||||
class NewMessage extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
showEmojiPicker: false
|
||||
}
|
||||
}
|
||||
|
||||
toggleEmojiPicker = () => {
|
||||
this.setState({ showEmojiPicker: !this.state.showEmojiPicker })
|
||||
}
|
||||
|
||||
textAreaValue = () => {
|
||||
return Util.addEmoji(this.props.messageText)
|
||||
}
|
||||
|
||||
handleClick = (emoji, event) => {
|
||||
const { messageText } = this.props
|
||||
this.props.handleChange({ target: {
|
||||
value: messageText + emoji.colons
|
||||
}})
|
||||
|
||||
this.setState({ showEmojiPicker: false })
|
||||
this.props.focusMessageInput()
|
||||
}
|
||||
|
||||
render = () => {
|
||||
return (
|
||||
<div className="new-message-area">
|
||||
<Picker set="emojione"
|
||||
onClick={this.handleClick}
|
||||
style={{
|
||||
display: this.state.showEmojiPicker ? 'block' : 'none',
|
||||
maxWidth: '100%'
|
||||
}}
|
||||
emoji="upside_down_face"
|
||||
title="Emoji"
|
||||
/>
|
||||
<div className="extra-message-options">
|
||||
<span className="emoji-picker-button" onClick={this.toggleEmojiPicker}><Emoji size={24} emoji="upside_down_face" /></span>
|
||||
</div>
|
||||
<textarea value={this.textAreaValue()}
|
||||
onChange={this.props.handleChange}
|
||||
{...this.props.textAreaProps}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
NewMessage.propTypes = {
|
||||
messageText: PropTypes.string,
|
||||
handleChange: PropTypes.func,
|
||||
focusMessageInput: PropTypes.func,
|
||||
textAreaProps: PropTypes.shape({
|
||||
className: PropTypes.string,
|
||||
ref: PropTypes.func,
|
||||
placeholder: PropTypes.string,
|
||||
onKeyUp: PropTypes.func,
|
||||
onFocus: PropTypes.func,
|
||||
onBlur: PropTypes.func
|
||||
})
|
||||
}
|
||||
|
||||
export default NewMessage
|
|
@ -2,6 +2,24 @@ import React, { PropTypes, Component } from 'react'
|
|||
import Unread from './Unread'
|
||||
import Participant from './Participant'
|
||||
import Message from './Message'
|
||||
import NewMessage from './NewMessage'
|
||||
import Util from '../../Metamaps/Util'
|
||||
|
||||
function makeList(messages) {
|
||||
let currentHeader
|
||||
return messages ? messages.map(m => {
|
||||
let heading = false
|
||||
if (!currentHeader) {
|
||||
heading = true
|
||||
currentHeader = m
|
||||
} else {
|
||||
// not same user or time diff of greater than 3 minutes
|
||||
heading = m.user_id !== currentHeader.user_id || Math.floor(Math.abs(new Date(currentHeader.created_at) - new Date(m.created_at)) / 60000) > 3
|
||||
currentHeader = heading ? m : currentHeader
|
||||
}
|
||||
return <Message {...m} key={m.id} heading={heading}/>
|
||||
}) : null
|
||||
}
|
||||
|
||||
class MapChat extends Component {
|
||||
constructor(props) {
|
||||
|
@ -13,7 +31,7 @@ class MapChat extends Component {
|
|||
messageText: '',
|
||||
alertSound: true, // whether to play sounds on arrival of new messages or not
|
||||
cursorsShowing: true,
|
||||
videosShowing: true
|
||||
videosShowing: true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +42,7 @@ class MapChat extends Component {
|
|||
messageText: '',
|
||||
alertSound: true, // whether to play sounds on arrival of new messages or not
|
||||
cursorsShowing: true,
|
||||
videosShowing: true
|
||||
videosShowing: true
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -78,12 +96,17 @@ class MapChat extends Component {
|
|||
handleTextareaKeyUp = e => {
|
||||
if (e.which === 13) {
|
||||
e.preventDefault()
|
||||
const text = this.state.messageText
|
||||
const text = Util.removeEmoji(this.state.messageText)
|
||||
this.props.handleInputMessage(text)
|
||||
this.setState({ messageText: '' })
|
||||
}
|
||||
}
|
||||
|
||||
focusMessageInput = () => {
|
||||
if (!this.messageInput) return
|
||||
this.messageInput.focus()
|
||||
}
|
||||
|
||||
render = () => {
|
||||
const rightOffset = this.state.open ? '0' : '-300px'
|
||||
const { conversationLive, isParticipating, participants, messages, inviteACall, inviteToJoin } = this.props
|
||||
|
@ -100,12 +123,12 @@ class MapChat extends Component {
|
|||
<div className="participants">
|
||||
{conversationLive && <div className="conversation-live">
|
||||
LIVE
|
||||
{isParticipating && <span className="call-action leave" onClick={this.props.leaveCall}>
|
||||
LEAVE
|
||||
</span>}
|
||||
{!isParticipating && <span className="call-action join" onClick={this.props.joinCall}>
|
||||
JOIN
|
||||
</span>}
|
||||
{isParticipating && <span className="call-action leave" onClick={this.props.leaveCall}>
|
||||
LEAVE
|
||||
</span>}
|
||||
{!isParticipating && <span className="call-action join" onClick={this.props.joinCall}>
|
||||
JOIN
|
||||
</span>}
|
||||
</div>}
|
||||
{participants.map(participant => <Participant
|
||||
key={participant.id}
|
||||
|
@ -124,17 +147,20 @@ class MapChat extends Component {
|
|||
<div className="tooltips">Chat</div>
|
||||
<Unread count={unreadMessages} />
|
||||
</div>
|
||||
<div className="chat-messages" ref={div => this.messagesDiv = div}>
|
||||
{messages.map(message => <Message key={message.id} {...message} />)}
|
||||
<div className="chat-messages" ref={div => { this.messagesDiv = div }}>
|
||||
{makeList(messages)}
|
||||
</div>
|
||||
<textarea className="chat-input"
|
||||
ref={textarea => this.messageInput = textarea}
|
||||
placeholder="Send a message..."
|
||||
value={this.state.messageText}
|
||||
onChange={this.handleChange('messageText')}
|
||||
onKeyUp={this.handleTextareaKeyUp}
|
||||
onFocus={this.props.inputFocus}
|
||||
onBlur={this.props.inputBlur}
|
||||
<NewMessage messageText={this.state.messageText}
|
||||
focusMessageInput={this.focusMessageInput}
|
||||
handleChange={this.handleChange('messageText')}
|
||||
textAreaProps={{
|
||||
className: 'chat-input',
|
||||
ref: textarea => { this.messageInput = textarea },
|
||||
placeholder: 'Send a message...',
|
||||
onKeyUp: this.handleTextareaKeyUp,
|
||||
onFocus: this.props.inputFocus,
|
||||
onBlur: this.props.inputBlur
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
@ -152,7 +178,7 @@ MapChat.propTypes = {
|
|||
inviteToJoin: PropTypes.func,
|
||||
videoToggleClick: PropTypes.func,
|
||||
cursorToggleClick: PropTypes.func,
|
||||
soundToggleClick: PropTypes.func,
|
||||
soundToggleClick: PropTypes.func,
|
||||
participants: PropTypes.arrayOf(PropTypes.shape({
|
||||
color: PropTypes.string, // css color
|
||||
id: PropTypes.number,
|
||||
|
|
|
@ -27,9 +27,10 @@
|
|||
"babel-preset-es2015": "6.18.0",
|
||||
"babel-preset-react": "6.16.0",
|
||||
"backbone": "1.0.0",
|
||||
"clipboard-js": "git://github.com/devvmh/clipboard.js#patch-1",
|
||||
"clipboard-js": "0.3.2",
|
||||
"commonmark": "0.27.0",
|
||||
"csv-parse": "1.1.7",
|
||||
"emoji-mart": "^0.3.5",
|
||||
"getScreenMedia": "git://github.com/devvmh/getScreenMedia#patch-1",
|
||||
"hark": "git://github.com/devvmh/hark#patch-1",
|
||||
"howler": "2.0.2",
|
||||
|
|
Loading…
Reference in a new issue