Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save rfprod/7804498d14f5e7edb962f8c4a9e46bc3 to your computer and use it in GitHub Desktop.
Save rfprod/7804498d14f5e7edb962f8c4a9e46bc3 to your computer and use it in GitHub Desktop.
Messaging App Template [AngularJS Material]
<html >
<body ng-app="msgApp">
<div ng-controller="appCtrl" id="root" layout="column">
<md-toolbar class="nav" flex>
<div class="md-toolbar-tools">
<img hide-xs class="logo" alt="logo" ng-src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/423527/profile/profile-80.jpg"/>
<h1 md-truncate flex>{{title}}</h1>
<md-button title="Gist">
<a href="https://gist.github.com/rfprod/7804498d14f5e7edb962f8c4a9e46bc3" title="Gist" target=_blank>
<i class="fa fa-github-alt"></i><span hide-xs> GIST</span>
</a>
</md-button>
<md-button md-no-focus ng-disabled="true" title="{{currentYear()}} &copy; All trademarks and copyrights are property of their respective owners">
&copy;<span hide-xs > {{currentYear()}}</span>
</md-button>
</div>
</md-toolbar>
<md-tabs md-swipe-content flex="90">
<md-tab label="index" layout="column" layout-fill>
<div layout="row" layout-xs="column" layout-padding flex>
<div id="messages-list" flex="30" flex-xs="100">
<div id="msg-list-item" ng-repeat="item in data track by $index" ng-click="selectConversation($index)" ng-class="{ 'selected': item.id == selectedConversation.id }">
{{ item.subject }}<br/>
{{ item.created }}
</div>
</div>
<div id="messages-details" layout="column" flex>
<div id="msg-details" ng-repeat="item in dialogues track by $index" flex>
<span ng-bind-html="item.author"></span><br/>
<span ng-bind-html="item.text"></span>
<hr/>
</div>
</div>
</div>
<span us-spinner spinner-key="spinner-1"></span>
<hr/>
<div layout="column" layout-padding flex>
<div id="preview" ng-bind-html="markedPreview"></div>
<input id="username" placeholder="{{placeholders.name}}" aria-label="user name" type="text" ng-readonly="loading" ng-model="name"/>
<textarea id="messagetext" placeholder="{{placeholders.message}}" aria-label="message text" type="text" ng-readonly="loading" ng-model="message"></textarea>
<md-button ng-disabled="loading" aria-label="send message" ng-click="sendMessage()">
{{buttonText}}
</md-button>
</div>
</md-tab>
<md-tab label="info">
<div class="pad-1" aria-label="app description" ng-bind-html="infoText"></div>
</md-tab>
</md-tabs>
</div>
</body>
</html>

Messaging App Template [AngularJS Material]

User stories: User can select a Conversation, and see messages inside the Conversation in a separate section to the right of Conversations list. User can post a message to the selected Conversation (this information is stored locally and is discarded on the page reload). User can use markdown for message text formatting.

A Pen by V on CodePen.

License.

const app = angular.module('msgApp',['angularSpinner','ngSanitize', 'ngMaterial']);
app.controller('appCtrl', ($scope, $window, $timeout, usSpinnerService) => {
$scope.title = 'App template';
$scope.placeholders = {
name: 'your name, you can use markdown',
message: 'your message text, you can use markdown'
};
$scope.name = 'Your **name**';
$scope.message = '*Your* **message**\n####You can use [markdown](https://guides.github.com/features/mastering-markdown/)\nto create rich messages\n\n![image](https://s3-us-west-2.amazonaws.com/s.cdpn.io/423527/profile/profile-80.jpg)';
$scope.infoText = marked('This application uses libraries: **Markdown**, **AngularJS** and extensions.\n\n#### User stories:\n* User can select a *Conversation*, and see messages inside the *Conversation* in a separate section to the right of *Conversations* list.\n* User can post a message to the selected *Conversation* (this information is stored locally and is discarded on the page reload).\n* User can use [markdown](https://guides.github.com/features/mastering-markdown/) for message text formatting.');
$scope.$watch('name', () => {
$scope.markedPreview = marked($scope.name+'<br/>'+$scope.message);
});
$scope.$watch('message', () => {
$scope.markedPreview = marked($scope.name+'<br/>'+$scope.message);
});
$scope.markedPreview = marked($scope.name+'<br/>'+$scope.message);
$scope.buttonText = 'Send Message';
$scope.currentYear = () => {
return new Date().getFullYear();
};
$scope.data = [
{id: 0, subject: 'Conversation 1', created: new Date(new Date().getTime() - 100000000).toUTCString(),
parts: [
{id: 1, author: '*usr2*', text: 'usr2 **message1**'},
{id: 0, author: '**usr1**', text: 'usr1 *message1*'}
]
},
{id: 1, subject: 'Conversation 2', created: new Date().toUTCString(),
parts: [
{id: 1, author: '**usr4**', text: 'usr4 *message1*'},
{id: 0, author: '*usr3*', text: 'usr3 **message1**'}
]
}
];
$scope.selectedConversation = undefined;
$scope.dialogues = [];
$scope.$watch('selectedConversation', (newValue) => {
console.log('selectedConversation changed, nexValue', newValue);
$scope.dialogues = (newValue) ? newValue.parts.slice(0) : [];
if ($scope.dialogues.length) {
$scope.dialogues = $scope.dialogues.map(item => {
item.author = marked(item.author);
item.text = marked(item.text);
return item;
});
}
});
$scope.loading = false;
$scope.spinCounter = 0;
$scope.$watch('loading', (newValue) => {
if (newValue) {
usSpinnerService.spin('spinner-1');
$scope.spinCounter++;
} else {
$scope.spinCounter = ($scope.spinCounter > 0) ? $scope.spinCounter - 1 : 0;
if (!$scope.spinCounter) {
usSpinnerService.stop('spinner-1');
}
}
});
$scope.selectConversation = (index) => {
$scope.loading = true;
console.log('selected index', index);
$scope.selectedConversation = null;
$timeout(() => {
$scope.loading = false;
$scope.selectedConversation = $scope.data[index];
$window.scrollTo(0, 0);
},1500);
};
$scope.sendMessage = () => {
console.log('send message, selected conversation', $scope.selectedConversation);
if (typeof $scope.selectedConversation !== 'object') { alert('You must select a conversation first'); }
else {
const id = $scope.selectedConversation.id;
const nextIndex = $scope.data[id].length + 1;
$scope.data[id].parts.unshift({
id: nextIndex, author: $scope.name, text: $scope.message
});
$scope.selectConversation(id);
}
};
});
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-spinner/0.8.1/angular-spinner.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular-animate.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2/spin.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular-sanitize.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular-aria.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular-messages.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.js"></script>
$white: #ffffff
// bootstrap colors
$primary: #337ab7
$success: #dff0d8
$info: #d9edf7
$warning: #fcf8e3
$danger: #f2dede
.md-button
min-width: 40px
textarea
resize: vertical
min-height: 150px
a
text-decoration: none
&:hover
text-decoration: none
p
margin: 0
.pad-1
padding-left: 1em
padding-right: 1em
body
width: 100%
#root
height: 100%
.nav
background: $primary
.logo
height: 2em
margin-right: 0.8em
&:hover
border-radius: 50%
border: 1px $white dashed
#messages-list
max-height: 50vh
overflow-y: hidden
#msg-list-item
font-size: 0.85em
&:hover
background-color: #5bffff
cursor: pointer
.selected
background-color: #5beffe
#messages-details
max-height: 50vh
overflow-y: scroll
.msg-details
height: auto!important
#preview
background: $info
<link href="//ajax.googleapis.com/ajax/libs/angular_material/1.0.0/angular-material.min.css" rel="stylesheet" />
<link href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic" rel="stylesheet" />
<link href="//opensource.keycdn.com/fontawesome/4.7.0/font-awesome.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment