Permalink
51a5143 Mar 6, 2018
0 contributors

Users who have contributed to this file

435 lines (392 sloc) 15.3 KB
<!DOCTYPE html>
<!--
* Copyright 2017 Unify Software and Solutions GmbH & Co.KG.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
-->
<html lang="en">
<head>
<title>Circuit JS-SDK</title>
<style>
body {
font-family: sans-serif;
font-size: 14px;
}
section {
margin-bottom: 20px;
}
.pad-top {
margin-top: 5px;
}
.pad-bottom {
margin-bottom: 5px;
}
.error {
color: red;
}
button {
width: 70px;
}
.login input {
width: 150px;
}
select {
width: 310px;
}
.send input {
width: 310px;
margin-top: 5px;
}
.sending span {
color: grey;
}
.create input {
width: 306px;
}
.item {
color: CornflowerBlue;
}
.item.sent-by-me {
color: ForestGreen;
}
.light {
color: #888888;
}
.italic {
font-style: italic;
}
</style>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular-sanitize.min.js"></script>
<script src="//unpkg.com/circuit-sdk@beta"></script>
</head>
<body>
<h3>Messaging example</h3>
<p>In this example you can create conversations, send text messages and upload files.</p>
<div ng-app="circuit.sdk.examples" ng-controller="ctrl" class="ng-cloak">
<section class="error" ng-show="!!error">{{error}}</section>
<section class="login" ng-show="!error">
<div>
<button ng-click="login()" ng-show="!localUser">Logon</button>
<button ng-click="logout()" ng-show="!!localUser">Logout</button>
</div>
</section>
<section class="conv" ng-show="conversations.length && !createMode">
<div class="pad-bottom">Select or <a ng-click="createMode=true;query=null" href="">Create a Conversation</a></div>
<select class="select-wide" ng-model="selectedConv" ng-options="conv as (conv.title || conv.participantFirstNames) for conv in conversations" size="5"></select>
</section>
<section class="conv" ng-show="!!localUser && !conversations.length && !createMode">
<a ng-click="createMode=true;query=null" href="">Create a Conversation</a>
</section>
<section class="create" ng-show="createMode">
<div><input type="text" ng-model="query" ng-keyup="search(query, $event)" placeholder="Search for a user"/></div>
<div class="pad-bottom">
<select class="select-wide" multiple size="5">
<option ng-repeat="user in users" value="user" ng-click="selectUser(user)">{{user.displayName}}</option>
</select>
</div>
<div class="pad-bottom">
<select class="select-wide" multiple size="5">
<option ng-repeat="user in selectedUsers" value="user" ng-click="deselectUser(user)">{{user.displayName}}</option>
</select>
</div>
<div><input type="text" ng-show="selectedUsers.length>=2" class="pad-bottom" ng-model="title" placeholder="Enter title"/></div>
<button ng-click="createMode=false;selectedUsers=[]">Cancel</button>
<button ng-click="createConversation()" ng-disabled="!selectedUsers.length">Create</button>
</section>
<section class="send" ng-show="!!selectedConv && !createMode">
<div>Conversation: {{getConvName(selectedConv)}}</div>
<div class="send-container">
<input type="text" ng-model="message" placeholder="Enter message"/>
<button ng-click="send()" ng-disabled="!message">Send</button>
<input type="file" id="fileToUpload" multiple onchange="angular.element(this).scope().setFiles(this)" style="width:200px">
</div>
<div class="sending" ng-show="!!sending">me: {{sendingItem.text.content}}<span> sending...</span></div>
<div ng-repeat="item in items | limitTo:-10 | orderBy:'modificationTime':true" class="item" ng-class="{'sent-by-me': item.sentByMe}"><span class="light">{{item.modificationTime | date:'hh:mm a'}}:</span> {{item.sentByMe?'Me':item.creator.firstName}}: <span ng-class="{'italic':!!item.parent}" ng-bind-html="item.trustedText"></span></div>
</section>
</div>
<script>
var app = angular.module('circuit.sdk.examples', []);
app.controller('ctrl', ['$rootScope', '$scope','$sce', function($rootScope, $scope, $sce){
$scope.domain = 'circuitsandbox.net';
$scope.localUser = null;
$scope.registrationState = null;
$scope.conversations = [];
$scope.users = [];
$scope.items = [];
$scope.createMode = false;
$scope.selectedUsers = [];
var $fileToUpload = document.getElementById('fileToUpload');
var _isInitialized = false;
var _searchId;
var _selectedConvId;
// Create a new Circuit SDK client
var client = null;
$scope.login = function () {
if (client) {
return;
}
client = new Circuit.Client({
domain: $scope.domain,
client_id: '78cafde2f6854ad5ad80a67c532687bc',
scope: 'ALL' // Asking for ALL permissions because all these examples use the same domain
});
Circuit.logger.setLevel(Circuit.Enums.LogLevel.Debug);
client.logon().then(function (user) {
$scope.localUser = user;
setupEventListeners(user);
}).then(function () {
// Retrieve newest 20 conversations
return client.getConversations({numberOfConversations: 20});
}).then(function(conversations) {
_isInitialized = true;
if (!conversations.length) {
// The user has no conversations
$scope.selectedConv = null;
return;
}
// Save conversations in scope and pass first conversation to next promise chain element
$scope.conversations = conversations.reverse();
$scope.selectedConv = $scope.conversations[0];
_selectedConvId = $scope.selectedConv.convId;
return getItems();
}).then(function(items) {
if (items) {
console.log('Loaded item count: ', items.length);
}
$scope.$apply();
}).catch(function(err) {
if (!$scope.localUser) {
client = null;
}
if (err) { return alert('Error: ' + err.message); }
});
}
$scope.logout = function () {
if (!client) {
return;
}
client.logout();
client.removeAllListeners();
client = null;
$scope.localUser = null;
$scope.selectedConv = null;
$scope.conversations = [];
$scope.items = [];
}
$scope.setFiles = function(element) {
$scope.$apply(function(scope) {
console.log('files:', element.files);
$scope.files = []
for (var i = 0; i < element.files.length; i++) {
$scope.files.push(element.files[i])
}
});
};
$scope.send = function () {
$scope.sending = true;
client.addTextItem($scope.selectedConv.convId,
{content: $scope.message, attachments: $scope.files}).then(function (item) {
$scope.message = null;
$fileToUpload.value = '';
$scope.files = [];
});
}
$scope.createConversation = function () {
$scope.createMode = false;
var members = $scope.selectedUsers.map(function (m) { return m.userId; });
client.createGroupConversation(members, $scope.title).then(function (conv) {
$rootScope.$apply(function () {
$scope.conversations.unshift(conv);
$scope.selectedConv = conv;
});
}).catch(function (err) {
console.log(err);
});
$scope.selectedUsers = [];
}
$scope.getConvName = function (conv) {
if (!conv) { return ''; }
return conv.title || conv.participantFirstNames || conv.participants[0].displayName;
}
$scope.search = function (query) {
if (!query) {
$scope.users = [];
return;
}
client.startUserSearch({query: query}).then(function (searchId) {
_searchId = searchId;
});
}
$scope.selectUser = function (user) {
if ($scope.selectedUsers.indexOf(user) === -1) {
$scope.selectedUsers.unshift(user);
}
if ($scope.selectedUsers.length < 2) {
$scope.title = null;
}
}
$scope.deselectUser = function (user) {
$scope.selectedUsers.remove(user);
}
$scope.$watch('selectedConv', function (newValue, oldValue) {
if (newValue && oldValue && newValue.convId === oldValue.convId) {
return;
}
if (newValue && _isInitialized) {
_selectedConvId = newValue.convId
getItems();
}
});
function updateOrAddConversation(conv) {
var exists = $scope.conversations.some(function (c, idx) {
if (c.convId === conv.convId) {
$scope.conversations[idx] = conv;
if (c.convId === _selectedConvId) {
$scope.selectedConv = conv;
}
return true;
}
});
if (!exists) {
$scope.conversations.unshift(conv);
}
}
function setupEventListeners(user) {
client.addEventListener('registrationStateChange', function (evt) {
$scope.$apply(function () {
$scope.registrationState = evt.state;
if (evt.state === Circuit.Enums.RegistrationState.Disconnected) {
$scope.logout();
}
});
});
client.addEventListener('itemAdded', function (evt) {
if (evt.item.convId === _selectedConvId) {
getItems().then(function (items) {
$scope.$apply(function () {
$scope.sending = false;
});
});
}
});
client.addEventListener('itemUpdated', function (evt) {
if (evt.item.convId === _selectedConvId) {
getItems();
}
});
client.addEventListener('conversationCreated', function (evt) {
$scope.$apply(function () {
updateOrAddConversation(evt.conversation);
});
});
client.addEventListener('conversationUpdated', function (evt) {
$scope.$apply(function () {
updateOrAddConversation(evt.conversation);
});
});
client.addEventListener('basicSearchResults', function (evt) {
if (_searchId === evt.data.searchId) {
// For better performance more specific searches (i.e. another char is typed)
// instead of fetching the users again the prior list should be filtered.
client.getUsersById(evt.data.users).then(function (users) {
$rootScope.$apply(function () {
$scope.users = users;
});
});
}
});
}
function getItems() {
return new Promise(function (resolve, reject) {
if (!_selectedConvId) {
reject('No conversation selected');
return;
}
client.getConversationItems(_selectedConvId).then(function(items) {
$scope.$apply(function () {
$scope.items = items;
$scope.items.forEach(function (i) { trustItem(i); });
resolve(items);
});
}, function (reason) {
console.log('Error retrieving items. Reason: ', reasons);
reject(reason);
});
});
}
function trustItem(item) {
switch (item.type) {
case Circuit.Constants.ConversationItemType.SYSTEM:
item.trustedText = $sce.trustAsHtml(item.system.type);
break;
case Circuit.Constants.ConversationItemType.TEXT:
item.trustedText = $sce.trustAsHtml(item.text.content.replace(/<hr>/g, ' '));
break;
case Circuit.Constants.ConversationItemType.RTC:
item.trustedText = $sce.trustAsHtml(item.rtc.type);
break;
}
}
if (typeof Circuit === 'undefined') {
$scope.error = 'Could not load SDK (circuit.js). Make sure Circuit is running on https://localhost:8094.';
} else {
// The conversation injector example needs to be asynchroneous since the
// user lookup is an API call.
Circuit.Injectors.conversationInjector = function (conversation) {
return new Promise(function (resolve, reject) {
var userIds = conversation.participants.filter(function (p) {
return p !== client.loggedOnUser.userId;
});
client.getUsersById(userIds).then(function (users) {
// Set conversation.otherUsers
conversation.otherUsers = users;
// Set conversation.title and firstName
if (conversation.type === 'DIRECT') {
conversation.title = conversation.otherUsers[0].displayName;
} else {
var firstNames = conversation.otherUsers.map(function (u) {
return u.firstName;
});
firstNames.push(client.loggedOnUser.firstName);
conversation.participantFirstNames = firstNames.join(', ');
conversation.title = conversation.topic || conversation.otherUsers.map(function (u) {
return u.displayName;
}).join(', ');
}
resolve(conversation);
}, function (err) {
reject(err);
});
});
}
Circuit.Injectors.itemInjector = function (item) {
item.sentByMe = (item.creatorId === client.loggedOnUser.userId);
if (item.sentByMe) {
item.creator = client.loggedOnUser;
} else if ($scope.selectedConv && $scope.selectedConv.otherUsers) {
item.creator = $scope.selectedConv.otherUsers.find(function (u) {
return u.userId === item.creatorId;
});
}
if (item.type === 'TEXT') {
// Replacing br and hr tags with a space
item.text.content = item.text.content.replace(/<(\/li|hr[\/]?)>/gi, ' ');
}
};
}
}]);
</script>
</body>
</html>