Skip to content
Snippets Groups Projects
Commit ca0710d3 authored by Rodrigo Nascimento's avatar Rodrigo Nascimento
Browse files

Initial implementation of search in channel

parent b1de4c88
No related branches found
No related tags found
No related merge requests found
......@@ -2455,149 +2455,150 @@ a.github-fork {
border-radius: 4px;
}
}
.message {
font-size: 14px;
padding-left: 50px;
position: relative;
line-height: 20px;
margin: 12px 20px 5px;
margin-top: 12px;
min-height: 40px;
&:nth-child(1) {
margin-top: 0;
}
&.new-day {
margin-top: 60px;
}
&.new-day {
&:before {
content: attr(data-date);
display: block;
position: absolute;
top: -30px;
left: 0;
font-size: 12px;
font-weight: 600;
text-align: center;
.calc(left,
~"50% - 70px");
color: @secondary-font-color;
z-index: 10;
padding: 0 10px;
background-color: #FFF;
min-width: 140px;
}
&:after {
content: " ";
display: block;
position: absolute;
top: -20px;
left: 0;
width: 100%;
border-top: 1px solid #ddd;
}
}
.edit-message {
display: none;
cursor: pointer;
}
&.own:hover:not(.system) .edit-message {
display: inline-block;
}
.message {
font-size: 14px;
padding-left: 50px;
position: relative;
line-height: 20px;
margin: 12px 20px 5px;
margin-top: 12px;
min-height: 40px;
&:nth-child(1) {
margin-top: 0;
}
&.new-day {
margin-top: 60px;
}
&.new-day {
&:before {
content: attr(data-date);
display: block;
position: absolute;
top: -30px;
left: 0;
font-size: 12px;
font-weight: 600;
text-align: center;
.calc(left,
~"50% - 70px");
color: @secondary-font-color;
z-index: 10;
padding: 0 10px;
background-color: #FFF;
min-width: 140px;
}
.delete-message {
display: none;
cursor: pointer;
&:after {
content: " ";
display: block;
position: absolute;
top: -20px;
left: 0;
width: 100%;
border-top: 1px solid #ddd;
}
&.own:hover:not(.system) .delete-message {
display: inline-block;
}
.edit-message {
display: none;
cursor: pointer;
}
&.own:hover:not(.system) .edit-message {
display: inline-block;
}
.delete-message {
display: none;
cursor: pointer;
}
&.own:hover:not(.system) .delete-message {
display: inline-block;
}
.user {
display: inline-block;
font-weight: 600;
color: #444444;
margin-right: 5px;
&:hover {
color: #333;
}
}
.thumb {
position: absolute;
left: 0;
top: 0;
display: block;
width: 40px;
height: 40px;
}
.info {
font-size: 12px;
color: @info-font-color;
}
&.sequential {
margin-top: 5px;
min-height: 20px;
.user {
display: inline-block;
font-weight: 600;
color: #444444;
margin-right: 5px;
&:hover {
color: #333;
}
display: none;
}
.thumb {
position: absolute;
left: 0;
top: 0;
display: block;
width: 40px;
height: 40px;
display: none;
}
.info {
font-size: 12px;
color: @info-font-color;
}
&.sequential {
margin-top: 5px;
min-height: 20px;
.user {
position: absolute;
text-align: right;
left: -20px;
width: 65px;
.time {
display: none;
}
.thumb {
display: none;
.edited {
display: inline-block;
}
.info {
position: absolute;
text-align: right;
left: -20px;
width: 65px;
.time {
display: none;
}
.edited {
display: inline-block;
}
.edit-message {
float: left;
margin-left: 1px;
}
.delete-message {
float: left;
}
.edit-message {
float: left;
margin-left: 1px;
}
&:hover {
.time {
display: inline-block;
}
.edited {
display: none;
}
.delete-message {
float: left;
}
}
&.system {
.body {
color: @info-font-color;
font-style: italic;
text-transform: lowercase;
em {
font-weight: 600;
}
&:hover {
.time {
display: inline-block;
}
}
.avatar-initials {
line-height: 40px;
}
a {
color: @link-font-color;
font-weight: 400;
&:hover {
color: darken(@link-font-color, 10%);
text-decoration: underline;
.edited {
display: none;
}
}
}
&.system {
.body {
opacity: 1;
.transition(opacity 1s linear);
color: @info-font-color;
font-style: italic;
text-transform: lowercase;
em {
font-weight: 600;
}
}
&.temp .body {
opacity: .5;
}
.avatar-initials {
line-height: 40px;
}
a {
color: @link-font-color;
font-weight: 400;
&:hover {
color: darken(@link-font-color, 10%);
text-decoration: underline;
}
}
.body {
opacity: 1;
.transition(opacity 1s linear);
}
&.temp .body {
opacity: .5;
}
}
// FLEX-TAB and FLEX-TAB views
......@@ -2700,7 +2701,7 @@ a.github-fork {
> div {
position: relative;
}
.icon-plus {
.icon-plus {
position: absolute;
top: 11px;
left: 8px;
......
......@@ -80,8 +80,8 @@ Template.message.onViewRendered = (context) ->
if not lastNode.nextElementSibling?
if lastNode.classList.contains('own') is true
view.parentView.parentView.parentView.parentView.parentView.templateInstance().atBottom = true
view.parentView.parentView.parentView.parentView.parentView.templateInstance?().atBottom = true
else
if view.parentView.parentView.parentView.parentView.parentView.templateInstance().atBottom isnt true
if view.parentView.parentView.parentView.parentView.parentView.templateInstance?().atBottom isnt true
newMessage = document.querySelector(".new-message")
newMessage.className = "new-message"
......@@ -6,6 +6,9 @@ Template.room.helpers
tQuickSearch: ->
return t('Quick_Search')
searchResult: ->
return Template.instance().searchResult.get()
favorite: ->
sub = ChatSubscription.findOne { rid: this._id }, { fields: { f: 1 } }
return 'icon-star favorite-room' if sub?.f? and sub.f
......@@ -275,6 +278,18 @@ Template.room.helpers
Template.room.events
"keyup #room-search": _.debounce (e, t) ->
t.searchResult.set undefined
value = e.target.value.trim()
if value is ''
return
Tracker.nonreactive ->
Meteor.call 'messageSearch', value, Session.get('openedRoom'), (error, result) ->
if result? and (result.messages?.length > 0 or result.users?.length > 0 or result.channels?.length > 0)
t.searchResult.set result
, 1000
"touchstart .message": (e, t) ->
message = this._arguments[1]
doLongTouch = ->
......@@ -294,10 +309,11 @@ Template.room.events
"click .upload-progress-item > a": ->
Session.set "uploading-cancel-#{this.id}", true
"click .flex-tab .more": (event) ->
"click .flex-tab .more": (event, t) ->
if (Session.get('flexOpened'))
Session.set('rtcLayoutmode', 0)
Session.set('flexOpened',false)
t.searchResult.set undefined
else
Session.set('flexOpened', true)
......@@ -630,6 +646,7 @@ Template.room.onCreated ->
# this.typing = new msgTyping this.data._id
this.showUsersOffline = new ReactiveVar false
this.atBottom = true
this.searchResult = new ReactiveVar
self = @
......
......@@ -129,55 +129,69 @@
<section class="flex-tab">
<div class="control">
<button class="more"><span class="arrow {{arrowPosition}}"></span></button>
{{#if canAddUser}}
<div class="search-form">
<div class="input-line search">
{{> inputAutocomplete settings=autocompleteSettingsAddUser id="user-add-search" class="search" placeholder=tAddUsers}}
<i class="icon-plus"></i>
</div>
<form class="search-form" role="form">
<div class="input-line search">
<!-- {{> inputAutocomplete settings=autocompleteSettingsRoomSearch id="room-search" class="search" placeholder=tQuickSearch autocomplete="off"}} -->
<input type="text" id="room-search" class="search" placeholder="{{tQuickSearch}}" autocomplete="off" />
<i class="icon-search"></i>
</div>
{{else}}
{{#if isChannel}}
<form class="search-form" role="form">
<div class="input-line search">
{{> inputAutocomplete settings=autocompleteSettingsRoomSearch id="room-search" class="search" placeholder=tQuickSearch autocomplete="off"}}
<i class="icon-search"></i>
</div>
</form>
{{/if}}
{{/if}}
</form>
</div>
{{#if flexOpened}}
<div class="content">
{{#if isGroupChat}}
<div class="list-view{{#if $.Session.get 'showUserInfo'}} -hidden{{/if}}">
{{#with roomUsers}}
<div class="status">
<h2>{{_ "Members_List"}}</h2>
<p>
{{{_ "Showing_online_users" total_online=totalOnline total=total}}}
{{!--<button class="see-all">{{seeAll}}</button>--}}
</p>
</div>
<ul class='list clearfix lines'>
{{#each users}}
<li class='user-image user-card-room status-{{status}}'>
<a data-username="{{username}}" tabindex="0" title="{{username}}">
{{> avatar username=username}}
<p>{{username}} {{utcOffset}}</p>
</a>
</li>
{{/each}}
</ul>
{{/with}}
</div>
<div class="user-view animated{{#unless $.Session.get 'showUserInfo'}} -hidden{{/unless}}">
{{> userInfo user=flexUserInfo showAll=true}}
</div>
{{#if searchResult.messages}}
<ul>
{{#each searchResult.messages}}
{{#nrr nrrargs 'message' .}}{{/nrr}}
{{/each}}
</ul>
<!-- {{#each searchResult.users}}
@{{username}}
{{/each}}
{{#each searchResult.rooms}}
#{{name}}
{{/each}} -->
{{else}}
<div class="user-view">
{{> userInfo user=flexUserInfo video=true}}
</div>
{{#if isGroupChat}}
<div class="list-view{{#if $.Session.get 'showUserInfo'}} -hidden{{/if}}">
{{#with roomUsers}}
<div class="status">
<h2>{{_ "Members_List"}}</h2>
<p>
{{{_ "Showing_online_users" total_online=totalOnline total=total}}}
{{!--<button class="see-all">{{seeAll}}</button>--}}
</p>
{{#if canAddUser}}
<div class="control">
<div class="search-form">
<div class="input-line search">
{{> inputAutocomplete settings=autocompleteSettingsAddUser id="user-add-search" class="search" placeholder=tAddUsers}}
<i class="icon-plus"></i>
</div>
</div>
</div>
{{/if}}
</div>
<ul class='list clearfix lines'>
{{#each users}}
<li class='user-image user-card-room status-{{status}}'>
<a data-username="{{username}}" tabindex="0" title="{{username}}">
{{> avatar username=username}}
<p>{{username}} {{utcOffset}}</p>
</a>
</li>
{{/each}}
</ul>
{{/with}}
</div>
<div class="user-view animated{{#unless $.Session.get 'showUserInfo'}} -hidden{{/unless}}">
{{> userInfo user=flexUserInfo showAll=true}}
</div>
{{else}}
<div class="user-view">
{{> userInfo user=flexUserInfo video=true}}
</div>
{{/if}}
{{/if}}
</div>
{{/if}}
......
Meteor.methods
messageSearch: (text, rid) ->
###
text = 'from:rodrigo mention:gabriel chat'
###
# console.log '[method] -> messageSearch', text
result =
messages: []
users: []
channels: []
query = {}
options =
sort:
ts: -1
limit: 20
# Query for senders
from = []
text = text.replace /from:([a-z0-9.-_]+)/ig, (match, username, index) ->
from.push username
return ''
if from.length > 0
query['u.username'] =
$regex: from.join('|')
$options: 'i'
# Query for mentions
mention = []
text = text.replace /mention:([a-z0-9.-_]+)/ig, (match, username, index) ->
mention.push username
return ''
if mention.length > 0
query['mentions.username'] =
$regex: mention.join('|')
$options: 'i'
# Query in message text
text = text.trim().replace(/\s\s/g, ' ')
if text isnt ''
query.$text =
$search: text
options.fields =
score:
$meta: "textScore"
options.sort =
score:
$meta: 'textScore'
if Object.keys(query).length > 0
# Filter by room
if rid?
query.rid = rid
try
if Meteor.call('canAccessRoom', rid, this.userId) isnt false
result.messages = ChatMessage.find(query, options).fetch()
# ###
# # USERS
# ###
# if from.length is 0 and mention.length is 0 and text isnt ''
# query =
# username:
# $regex: text
# $options: 'i'
# options =
# limit: 5
# sort:
# username: 1
# fields:
# username: 1
# name: 1
# status: 1
# utcOffset: 1
# result.users = Meteor.users.find(query, options).fetch()
# ###
# # CHANNELS
# ###
# if from.length is 0 and mention.length is 0 and text isnt ''
# query =
# t: 'c'
# name:
# $regex: text
# $options: 'i'
# options =
# limit: 5
# sort:
# name: 1
# fields:
# username: 1
# name: 1
# status: 1
# utcOffset: 1
# result.channels = ChatRoom.find(query, options).fetch()
return result
\ No newline at end of file
......@@ -14,3 +14,4 @@ Meteor.startup ->
try ChatMessage._ensureIndex { 'ets': 1 }, { sparse: 1 } catch e then console.log e
try ChatMessage._ensureIndex { 'rid': 1, 't': 1, 'u._id': 1 } catch e then console.log e
try ChatMessage._ensureIndex { 'expireAt': 1 }, { expireAfterSeconds: 0 } catch e then console.log e
try ChatMessage._ensureIndex { 'msg': 'text' } catch e then console.log e
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment