Initial AngularJS version of Webmail (desktop)
parent
1c9da902d3
commit
2f17e94fef
|
@ -786,7 +786,7 @@
|
|||
forKey: @"Sent"];
|
||||
[mailboxes setObject: [_defaults trashFolderName]
|
||||
forKey: @"Trash"];
|
||||
[mailAccount setObject: mailboxes forKey: @"mailboxes"];
|
||||
[mailAccount setObject: mailboxes forKey: @"specialMailboxes"];
|
||||
[mailboxes release];
|
||||
|
||||
[mailAccounts addObject: mailAccount];
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
<?xml version="1.0" standalone="yes"?>
|
||||
<!DOCTYPE var:component>
|
||||
<var:component xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:rsrc="OGo:url"
|
||||
xmlns:label="OGo:label"
|
||||
className="UIxPageFrame"
|
||||
title="title"
|
||||
const:userDefaultsKeys="SOGoMailMessageCheck,SOGoRefreshViewCheck,SOGoMailSortByThreads,SOGoMailListViewColumnsOrder,SOGoMailDisplayRemoteInlineImages"
|
||||
const:userSettingsKeys="Mail"
|
||||
const:jsFiles="dtree.js,MailerUIdTree.js,SOGoAutoCompletion.js,SOGoResizableTable.js,SOGoMailDataSource.js,SOGoDataTable.js,jquery-ui.js, UIxMailSearch.js"
|
||||
const:cssFiles="UIxMailSearch.css">
|
||||
<var:component
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:rsrc="OGo:url"
|
||||
xmlns:label="OGo:label"
|
||||
className="UIxPageFrame"
|
||||
title="title"
|
||||
const:userDefaultsKeys="SOGoMailMessageCheck,SOGoRefreshViewCheck,SOGoMailSortByThreads,SOGoMailListViewColumnsOrder,SOGoMailDisplayRemoteInlineImages"
|
||||
const:userSettingsKeys="Mail"
|
||||
const:jsFiles="Common/resource.js, Mailer/message-model.js, Mailer/mailbox-model.js, Mailer/account-model.js">
|
||||
<script type="text/javascript">
|
||||
var mailAccounts = <var:string value="mailAccounts" const:escapeHTML="NO"/>;
|
||||
var userNames = <var:string value="userNames" const:escapeHTML="NO" />;
|
||||
var inboxData = <var:string value="inboxData" const:escapeHTML="NO"/>;
|
||||
var unseenCountFolders = <var:string value="unseenCountFolders" const:escapeHTML="NO"/>;
|
||||
</script>
|
||||
<style type="text/css">
|
||||
|
@ -28,28 +27,12 @@
|
|||
{ color: #fff;
|
||||
background-color: <var:string value="currentLabel.color"/> !important; }
|
||||
</var:foreach>
|
||||
<var:if condition="horizontalDragHandleStyle">
|
||||
DIV#verticalDragHandle, DIV#rightPanel
|
||||
{ left: <var:string value="horizontalDragHandleStyle" />; }
|
||||
DIV#leftPanel
|
||||
{ width: <var:string value="horizontalDragHandleStyle" />; }
|
||||
</var:if><var:if condition="verticalDragHandleStyle">
|
||||
DIV#rightDragHandle, DIV#messageContent
|
||||
{ top: <var:string value="verticalDragHandleStyle" />; }
|
||||
</var:if><var:if condition="singleWindowModeEnabled" const:negate="YES"><var:if condition="mailboxContentStyle">
|
||||
DIV#mailboxContent
|
||||
{ height: <var:string value="mailboxContentStyle" />; }
|
||||
</var:if></var:if><var:if condition="singleWindowModeEnabled">
|
||||
DIV#mailboxContent
|
||||
{ height: auto;
|
||||
bottom: 0px; }
|
||||
</var:if>
|
||||
</style>
|
||||
|
||||
|
||||
<div id="signatureFlagMessage" style="display: none" class="dialog right">
|
||||
</div>
|
||||
|
||||
<div class="menu" id="accountIconMenu">
|
||||
|
||||
<div class="f-dropdown" id="accountIconMenu">
|
||||
<ul>
|
||||
<li><var:string label:value="Subscribe..." /></li>
|
||||
<li><var:string label:value="Get Messages for Account" /></li>
|
||||
|
@ -60,7 +43,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="inboxIconMenu">
|
||||
<div class="f-dropdown" id="inboxIconMenu">
|
||||
<ul>
|
||||
<li><var:string label:value="Open in New Mail Window" /></li>
|
||||
<li><var:string label:value="Copy Folder Location" /></li>
|
||||
|
@ -75,8 +58,8 @@
|
|||
<li><var:string label:value="Sharing..." /></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="trashIconMenu">
|
||||
|
||||
<div class="f-dropdown" id="trashIconMenu">
|
||||
<ul>
|
||||
<li><var:string label:value="Open in New Mail Window" /></li>
|
||||
<li><var:string label:value="Copy Folder Location" /></li>
|
||||
|
@ -93,7 +76,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="mailboxIconMenu">
|
||||
<div class="f-dropdown" id="mailboxIconMenu">
|
||||
<ul>
|
||||
<li><var:string label:value="Open in New Mail Window" /></li>
|
||||
<li><var:string label:value="Copy Folder Location" /></li>
|
||||
|
@ -112,15 +95,15 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="folderTypeMenu">
|
||||
<div class="f-dropdown" id="folderTypeMenu">
|
||||
<ul>
|
||||
<li><var:string label:value="Sent Messages" /></li>
|
||||
<li><var:string label:value="Drafts" /></li>
|
||||
<li><var:string label:value="Deleted Messages" /></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="moveMailboxMenu">
|
||||
|
||||
<div class="f-dropdown" id="moveMailboxMenu">
|
||||
<ul>
|
||||
<var:foreach list="clientObject.mailAccounts" item="currentLabel">
|
||||
<li><img rsrc:src="tbtv_account_17x17.png"/> <var:string value="currentLabel.name"/></li>
|
||||
|
@ -128,7 +111,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="copyMailboxMenu">
|
||||
<div class="f-dropdown" id="copyMailboxMenu">
|
||||
<ul>
|
||||
<var:foreach list="clientObject.mailAccounts" item="currentLabel">
|
||||
<li><img rsrc:src="tbtv_account_17x17.png"/> <var:string value="currentLabel.name"/></li>
|
||||
|
@ -136,7 +119,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="messageListMenu">
|
||||
<div class="f-dropdown" id="messageListMenu">
|
||||
<ul>
|
||||
<li><var:string label:value="Open Message In New Window"/></li>
|
||||
<li><!-- separator --></li>
|
||||
|
@ -158,7 +141,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="messagesListMenu">
|
||||
<div class="f-dropdown" id="messagesListMenu">
|
||||
<ul>
|
||||
<li><var:string label:value="Forward"/></li>
|
||||
<li><!-- separator --></li>
|
||||
|
@ -174,7 +157,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="messageContentMenu">
|
||||
<div class="f-dropdown" id="messageContentMenu">
|
||||
<ul>
|
||||
<li><var:string label:value="Reply to Sender Only"/></li>
|
||||
<li><var:string label:value="Reply to All"/></li>
|
||||
|
@ -194,7 +177,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="label-menu">
|
||||
<div class="f-dropdown" id="label-menu">
|
||||
<ul id="" class="choiceMenu">
|
||||
<li><var:string label:value="None" /></li>
|
||||
<li><!-- separator --></li>
|
||||
|
@ -204,7 +187,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="mark-menu">
|
||||
<div class="f-dropdown" id="mark-menu">
|
||||
<ul id="" class="choiceMenu">
|
||||
<li><var:string label:value="As Read" /></li>
|
||||
<li><var:string label:value="Thread As Read" /></li>
|
||||
|
@ -215,126 +198,101 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="addressMenu">
|
||||
<div class="f-dropdown" id="addressMenu">
|
||||
<ul>
|
||||
<li id="add_to_addressbook"><var:string label:value="Add to Address Book..."/></li>
|
||||
<li id="compose_mailto"><var:string label:value="Compose Mail To"/></li>
|
||||
<!--<li id="create_filter"><var:string label:value="Create Filter From Message..."/></li>-->
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="menu" id="imageMenu">
|
||||
<div class="f-dropdown" id="imageMenu">
|
||||
<ul>
|
||||
<li id="save_image"><var:string label:value="Save Image"/></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="leftPanel">
|
||||
<div class="titlediv"><var:string label:value="Folders" /></div>
|
||||
<div id="folderTreeContent"><!-- space --></div>
|
||||
</div>
|
||||
<div data-ui-view="mailboxes"><!-- mailboxes list --></div>
|
||||
|
||||
<div class="dragHandle" id="verticalDragHandle"><!-- space --></div>
|
||||
<script type="text/ng-template" id="mailboxes.html">
|
||||
|
||||
<div id="rightPanel">
|
||||
<var:component className="UIxMailFilterPanel" qualifier="qualifier" />
|
||||
|
||||
<div id="mailboxContent">
|
||||
|
||||
<table id="messageListHeader" class="messageList" cellspacing="0">
|
||||
<thead>
|
||||
<tr class="tableview"
|
||||
><var:foreach list="columnsDisplayOrder" item="currentColumn">
|
||||
<th var:class="currentColumn.headerClass" var:id="currentColumn.headerId">
|
||||
<var:if condition="currentColumn.value" const:value="Thread">
|
||||
<entity name="nbsp"/>
|
||||
</var:if>
|
||||
<var:if condition="currentColumn.value" const:value="Flagged">
|
||||
<entity name="nbsp"/>
|
||||
</var:if>
|
||||
<var:if condition="currentColumn.value" const:value="Attachment">
|
||||
<img rsrc:src="title_attachment_14x14.png" label:title="$currentColumn.value" width="14"
|
||||
height="14"/>
|
||||
</var:if>
|
||||
<var:if condition="currentColumn.value" const:value="Unread">
|
||||
<img rsrc:src="title_read_14x14.png" label:title="$currentColumn.value" />
|
||||
</var:if>
|
||||
<var:if condition="currentColumn.value" const:value="Thread" const:negate="YES">
|
||||
<var:if condition="currentColumn.value" const:value="Flagged" const:negate="YES">
|
||||
<var:if condition="currentColumn.value" const:value="Attachment" const:negate="YES">
|
||||
<var:if condition="currentColumn.value" const:value="Unread" const:negate="YES">
|
||||
<var:string var:value="columnTitle" />
|
||||
</var:if>
|
||||
</var:if>
|
||||
</var:if>
|
||||
</var:if>
|
||||
</th>
|
||||
</var:foreach>
|
||||
</tr>
|
||||
<tr id="messageCountHeader" class="tableview"
|
||||
><th var:colspan="columnsDisplayCount" class="tbtv_navcell"
|
||||
><entity name="nbsp"/></th
|
||||
></tr
|
||||
>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
<div id="mailboxList">
|
||||
<table id="messageListBody" class="messageList" cellspacing="0">
|
||||
<tbody>
|
||||
<tr const:style="display: none;"
|
||||
><var:foreach list="columnsDisplayOrder" item="currentColumn"
|
||||
><var:if condition="currentColumn.value" const:value="Thread"
|
||||
><td class="messageThreadColumn"
|
||||
><!-- thread --></td
|
||||
></var:if
|
||||
><var:if condition="currentColumn.value" const:value="Flagged"
|
||||
><td class="messageFlagColumn"
|
||||
><!-- flagged --></td
|
||||
></var:if>
|
||||
<var:if condition="currentColumn.value" const:value="Attachment"
|
||||
><td class="messageAttachmentColumn"
|
||||
><!-- attachment --></td
|
||||
></var:if
|
||||
><var:if condition="currentColumn.value" const:value="Subject"
|
||||
><td class="messageSubjectColumn"
|
||||
><!-- subject --></td
|
||||
></var:if
|
||||
><var:if condition="currentColumn.value" const:value="From"
|
||||
><td class="messageAddressColumn"
|
||||
><!-- from --></td
|
||||
></var:if
|
||||
><var:if condition="currentColumn.value" const:value="To"
|
||||
><td class="messageAddressColumn"
|
||||
><!-- to --></td
|
||||
></var:if
|
||||
><var:if condition="currentColumn.value" const:value="Unread"
|
||||
><td class="messageUnreadColumn"
|
||||
><!-- unread --></td
|
||||
></var:if
|
||||
><var:if condition="currentColumn.value" const:value="Date"
|
||||
><td class="messageDateColumn"
|
||||
><!-- date --></td
|
||||
></var:if
|
||||
><var:if condition="currentColumn.value" const:value="Priority"
|
||||
><td class="messagePriorityColumn"
|
||||
><!-- priority --></td
|
||||
></var:if
|
||||
><var:if condition="currentColumn.value" const:value="Size"
|
||||
><td class="messageSizeColumn"
|
||||
><!-- size --></td
|
||||
></var:if>
|
||||
</var:foreach>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- dropdown menu for addressbook options button -->
|
||||
<div id="folderProperties" class="f-dropdown icons-dropdown" data-dropdown-content="dropdown-content">
|
||||
<ul class="button-group">
|
||||
<li>
|
||||
<span class="button"><i class="icon-hyperlink"><!-- links --></i></span>
|
||||
</li>
|
||||
<li data-ng-show="currentFolder.type == 'folder'">
|
||||
<span class="button" data-ng-click="edit()"><i class="icon-pencil"><!-- rename --></i></span>
|
||||
</li>
|
||||
<li data-ng-show="currentFolder.type == 'folder'">
|
||||
<span class="button" data-ng-click="share()"><i class="icon-earth"><!-- share --></i></span>
|
||||
</li>
|
||||
<li data-ng-show="currentFolder.type == 'folder'">
|
||||
<span class="button" data-ng-click="confirmDelete()"><i class="icon-trash"><!-- delete --></i></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<var:if condition="singleWindowModeEnabled" const:negate="YES"
|
||||
><div class="dragHandle" id="rightDragHandle"><!-- space --></div>
|
||||
<div id="messageContent"><!-- space --></div
|
||||
></var:if>
|
||||
</div>
|
||||
|
||||
<var:string value="errorAlertJavaScript" const:escapeHTML="NO" />
|
||||
<div id="mailboxesList" class="folders-list">
|
||||
<ul data-ng-repeat="account in accounts">
|
||||
<li><label>{{account.name}}</label></li>
|
||||
<sg-folder-tree data-ng-repeat="folder in account.mailboxes track by folder.id"
|
||||
data-sg-root="account"
|
||||
data-sg-folder="folder"
|
||||
data-sg-set-folder="setCurrentFolder"><!-- tree --></sg-folder-tree>
|
||||
</ul>
|
||||
</div>
|
||||
<div data-ui-view="mailbox"><!-- messages list --></div>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="mailbox.html">
|
||||
<div id="messagesList">
|
||||
<ul data-vs-repeat="56"
|
||||
data-vs-scroll-parent="#messagesList">
|
||||
<li ng-repeat="currentMessage in mailbox.$messages"
|
||||
data-ng-class="{unread: !currentMessage.isread, _selected: message.id == currentMessage.id}">
|
||||
<a name="{{}}" data-ui-sref="mail.account.mailbox.message({accountId: account.id, mailboxId: mailbox.path, messageId: currentMessage.uid})">
|
||||
<div class="name">
|
||||
{{currentMessage.from}}
|
||||
<span class="right" data-ng-bind-html="currentMessage.date"><!-- date --></span>
|
||||
</div>
|
||||
<div class="subject">{{currentMessage.subject}}</div>
|
||||
<i class="icon-ion-refresh"
|
||||
data-ng-hide="mailbox.$loadMessage(currentMessage.uid)"><!-- loading --></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="messageView" data-ui-view="message"><!-- message view --></div>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="message.html">
|
||||
<div class="header">
|
||||
<h1 data-ng-bind-html="message.from"><!-- sender --></h1>
|
||||
<h6>
|
||||
{{message.subject}}
|
||||
<span class="label radius" data-ng-repeat="flag in message.flags">{{flag}}</span>
|
||||
</h6>
|
||||
<div class="attr">
|
||||
<div class="key">
|
||||
<label class="right"><var:string label:value="To"/></label>
|
||||
</div>
|
||||
<div class="value">
|
||||
<span class="label radius" data-ng-repeat="addr in message.toAddresses">{{addr}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttonsToolbar">
|
||||
<span>
|
||||
<a class="button tiny radius"
|
||||
data-ui-sref="mail.acount.mailbox.messageEditor({accountId: account.id, mailboxId: mailbox.path, messageId: message.uid})"
|
||||
data-ng-show="message.isDraft"><i class="icon-pencil"><!-- edit --></i></a>
|
||||
<span class="button tiny radius alert"
|
||||
data-ng-click="delete(message)"><i class="icon-trash"><!-- delete --></i></span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="mailer_mailcontent"
|
||||
data-ng-bind-html="message.$content()"><!-- msg --></div>
|
||||
</script>
|
||||
</var:component>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label"
|
||||
xmlns:uix="OGo:uix"><var:string var:value="doctype" const:escapeHTML="NO" />
|
||||
<div id="modalACL">
|
||||
<h2><var:string label:value="Access Rights"/> - <em>{{addressbook.name}}</em></h2>
|
||||
|
@ -54,9 +55,7 @@
|
|||
</li>
|
||||
<!-- right side -->
|
||||
<li id="AccessRightList" data-ng-show="selectedUser">
|
||||
<div class="title">
|
||||
{{selectedUser.$shortFormat()}}
|
||||
</div>
|
||||
<h1>{{selectedUser.$shortFormat({email: false})}}</h1>
|
||||
<div data-ng-include="'userRights.html'"><!-- load template from main wox --></div>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
</var:if>
|
||||
<var:if condition="userHasMailAccess">
|
||||
<var:if condition="isMail">
|
||||
<li class="active"><var:string label:value="Mail"/></li>
|
||||
<li class="active"><a href="#"><var:string label:value="Mail"/></a></li>
|
||||
</var:if>
|
||||
<var:if condition="isMail" const:negate="YES">
|
||||
<li><a var:href="relativeMailPath"><var:string label:value="Mail" /></a></li>
|
||||
|
|
|
@ -16,6 +16,7 @@ module.exports = function(grunt) {
|
|||
'css/app.css': 'scss/app.scss',
|
||||
'css/SOGoRootPage.css': 'scss/SOGoRootPage.scss',
|
||||
'css/ContactsUI.css': 'scss/ContactsUI.scss',
|
||||
'css/MailerUI.css': 'scss/MailerUI.scss',
|
||||
'css/mobile.css': 'scss/mobile.scss'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,6 +117,24 @@
|
|||
return deferred.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function post
|
||||
* @memberof Resource.prototype
|
||||
* @desc Post a resource attributes on the server.
|
||||
* @return a promise
|
||||
*/
|
||||
Resource.prototype.post = function(id, action, data) {
|
||||
var deferred = this._q.defer(),
|
||||
path = this._path + '/' + id + '/' + action;
|
||||
|
||||
this._http
|
||||
.post(path, data)
|
||||
.success(deferred.resolve)
|
||||
.error(deferred.reject);
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function save
|
||||
* @memberof Resource.prototype
|
||||
|
@ -125,15 +143,9 @@
|
|||
*/
|
||||
Resource.prototype.save = function(id, newValue, options) {
|
||||
var deferred = this._q.defer(),
|
||||
action = (options && options.action)? options.action : 'save',
|
||||
path = this._path + '/' + id + '/' + action;
|
||||
action = (options && options.action)? options.action : 'save';
|
||||
|
||||
this._http
|
||||
.post(path, newValue)
|
||||
.success(deferred.resolve)
|
||||
.error(deferred.reject);
|
||||
|
||||
return deferred.promise;
|
||||
return this.post(id, action, newValue);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* JavaScript for common UI services for mobile theme */
|
||||
/* JavaScript for common UI services */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
|
|
@ -199,7 +199,6 @@
|
|||
// link.on('dblclick', function() {
|
||||
// });
|
||||
scope.$on('sgSelectFolder', function(event, folderId) {
|
||||
console.debug('select folder ' + folderId + ' = ' + scope.folder.id);
|
||||
if (folderId == scope.folder.id) {
|
||||
var list = iElement.parent();
|
||||
while (list[0].tagName != 'UL') {
|
||||
|
@ -367,7 +366,6 @@
|
|||
});
|
||||
};
|
||||
$scope.selectFolder = function(folder) {
|
||||
console.debug("select folder " + folder.displayName);
|
||||
$scope.onFolderSelect(folder);
|
||||
};
|
||||
}],
|
||||
|
|
|
@ -55,9 +55,10 @@
|
|||
* @memberof User.prototype
|
||||
* @return the fullname along with the email address
|
||||
*/
|
||||
User.prototype.$shortFormat = function() {
|
||||
User.prototype.$shortFormat = function(options) {
|
||||
var fullname = this.cn || this.c_email;
|
||||
if (this.c_email && fullname != this.c_email) {
|
||||
var no_email = options && options.email === false;
|
||||
if (!no_email && this.c_email && fullname != this.c_email) {
|
||||
fullname += ' (' + this.c_email + ')';
|
||||
}
|
||||
return fullname;
|
||||
|
|
|
@ -71,6 +71,25 @@ String.prototype.base64decode = function() {
|
|||
return output;
|
||||
};
|
||||
|
||||
String.prototype.asCSSIdentifier = function() {
|
||||
var characters = [ '_' , '\\.', '#' , '@' , '\\*', ':' , ',' , ' '
|
||||
, "'", '&', '\\+' ];
|
||||
var escapeds = [ '_U_', '_D_', '_H_', '_A_', '_S_', '_C_', '_CO_',
|
||||
'_SP_', '_SQ_', '_AM_', '_P_' ];
|
||||
|
||||
var newString = this;
|
||||
for (var i = 0; i < characters.length; i++) {
|
||||
var re = new RegExp(characters[i], 'g');
|
||||
newString = newString.replace(re, escapeds[i]);
|
||||
}
|
||||
|
||||
if (/^\d+/.test(newString)) {
|
||||
newString = '_' + newString;
|
||||
}
|
||||
|
||||
return newString;
|
||||
};
|
||||
|
||||
function l() {
|
||||
var key = arguments[0];
|
||||
var value = key;
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @name Account
|
||||
* @constructor
|
||||
* @param {object} futureAccountData
|
||||
*/
|
||||
function Account(futureAccountData) {
|
||||
// Data is immediately available
|
||||
if (typeof futureAccountData.then !== 'function') {
|
||||
angular.extend(this, futureAccountData);
|
||||
Account.$log.debug('Account:' + JSON.stringify(futureAccountData, undefined, 2));
|
||||
}
|
||||
else {
|
||||
// The promise will be unwrapped first
|
||||
//this.$unwrap(futureAccountData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @memberof Account
|
||||
* @desc The factory we'll use to register with Angular
|
||||
* @returns the Account constructor
|
||||
*/
|
||||
Account.$factory = ['$q', '$timeout', '$log', 'sgSettings', 'sgResource', 'sgMailbox', function($q, $timeout, $log, Settings, Resource, Mailbox) {
|
||||
angular.extend(Account, {
|
||||
$q: $q,
|
||||
$timeout: $timeout,
|
||||
$log: $log,
|
||||
$$resource: new Resource(Settings.baseURL, Settings.activeUser),
|
||||
$Mailbox: Mailbox
|
||||
});
|
||||
|
||||
return Account; // return constructor
|
||||
}];
|
||||
|
||||
/* Factory registration in Angular module */
|
||||
angular.module('SOGo.MailerUI')
|
||||
.factory('sgAccount', Account.$factory);
|
||||
|
||||
/**
|
||||
* @memberof Account
|
||||
* @desc Set the list of accounts and instanciate a new Account object for each item.
|
||||
* @param {array} [data] - the metadata of the accounts
|
||||
* @returns the list of accounts
|
||||
*/
|
||||
Account.$findAll = function(data) {
|
||||
var collection = [];
|
||||
if (data) {
|
||||
// Each entry is spun up as an Account instance
|
||||
angular.forEach(data, function(o, i) {
|
||||
o.id = i;
|
||||
collection[i] = new Account(o);
|
||||
});
|
||||
}
|
||||
return collection;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $getMailboxes
|
||||
* @memberof Account.prototype
|
||||
* @desc Fetch the list of mailboxes for the current account.
|
||||
* @returns a promise of the HTTP operation
|
||||
*/
|
||||
Account.prototype.$getMailboxes = function() {
|
||||
var mailboxes = Account.$Mailbox.$find(this.id);
|
||||
|
||||
return mailboxes;
|
||||
};
|
||||
|
||||
})();
|
|
@ -0,0 +1,300 @@
|
|||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @name Mailbox
|
||||
* @constructor
|
||||
* @param {object} futureMailboxData - either an object literal or a promise
|
||||
*/
|
||||
function Mailbox(accountId, futureMailboxData) {
|
||||
this.accountId = accountId;
|
||||
// Data is immediately available
|
||||
if (typeof futureMailboxData.then !== 'function') {
|
||||
angular.extend(this, futureMailboxData);
|
||||
this.id = this.$id();
|
||||
}
|
||||
else {
|
||||
// The promise will be unwrapped first
|
||||
// NOTE: this condition never happen for the moment
|
||||
this.$unwrap(futureMailboxData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @memberof Mailbox
|
||||
* @desc The factory we'll use to register with Angular
|
||||
* @returns the Mailbox constructor
|
||||
*/
|
||||
Mailbox.$factory = ['$q', '$timeout', '$log', 'sgSettings', 'sgResource', 'sgMessage', 'sgMailbox_PRELOAD', function($q, $timeout, $log, Settings, Resource, Message, PRELOAD) {
|
||||
angular.extend(Mailbox, {
|
||||
$q: $q,
|
||||
$timeout: $timeout,
|
||||
$log: $log,
|
||||
$$resource: new Resource(Settings.baseURL, Settings.activeUser),
|
||||
$Message: Message,
|
||||
PRELOAD: PRELOAD
|
||||
});
|
||||
|
||||
return Mailbox; // return constructor
|
||||
}];
|
||||
|
||||
angular.module('SOGo.MailerUI')
|
||||
/* Factory constants */
|
||||
.constant('sgMailbox_PRELOAD', {
|
||||
LOOKAHEAD: 50,
|
||||
SIZE: 100
|
||||
})
|
||||
/* Factory registration in Angular module */
|
||||
.factory('sgMailbox', Mailbox.$factory);
|
||||
|
||||
/**
|
||||
* @memberof Mailbox
|
||||
* @desc Fetch list of mailboxes of a specific account
|
||||
* @param {string} accountId - the account ID
|
||||
* @see {@link Account.$getMailboxes}
|
||||
*/
|
||||
Mailbox.$find = function(accountId) {
|
||||
var path, futureMailboxData;
|
||||
|
||||
path = Mailbox.$absolutePath(accountId);
|
||||
futureMailboxData = this.$$resource.post(path, 'view', {sortingAttributes: {sort: 'date', asc: false}});
|
||||
|
||||
return Mailbox.$unwrapCollection(accountId, futureMailboxData); // a collection of mailboxes
|
||||
};
|
||||
|
||||
/**
|
||||
* @memberof Mailbox
|
||||
* @desc Unwrap to a collection of Mailbox instances.
|
||||
* @param {string} accountId - the account ID
|
||||
* @param {promise} futureMailboxData - a promise of the mailboxes metadata
|
||||
* @returns a promise of a collection of Mailbox objects
|
||||
*/
|
||||
Mailbox.$unwrapCollection = function(accountId, futureMailboxData) {
|
||||
var collection = [],
|
||||
// Local recursive function
|
||||
createMailboxes = function(mailbox) {
|
||||
for (var i = 0; i < mailbox.children.length; i++) {
|
||||
mailbox.children[i] = new Mailbox(accountId, mailbox.children[i]);
|
||||
createMailboxes(mailbox.children[i]);
|
||||
}
|
||||
};
|
||||
//collection.$futureMailboxData = futureMailboxData;
|
||||
|
||||
return futureMailboxData.then(function(data) {
|
||||
return Mailbox.$timeout(function() {
|
||||
// Each entry is spun up as a Mailbox instance
|
||||
angular.forEach(data.mailboxes, function(data, index) {
|
||||
var mailbox = new Mailbox(accountId, data);
|
||||
createMailboxes(mailbox); // recursively create all sub-mailboxes
|
||||
collection.push(mailbox);
|
||||
});
|
||||
return collection;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @memberof Mailbox
|
||||
* @desc Build the path of the mailbox (or account only).
|
||||
* @param {string} accountId - the account ID
|
||||
* @param {string} [mailboxPath] - an array of the mailbox path components
|
||||
* @returns a string representing the path relative to the mail module
|
||||
*/
|
||||
Mailbox.$absolutePath = function(accountId, mailboxPath) {
|
||||
var path = [];
|
||||
|
||||
if (mailboxPath) {
|
||||
path = _.map(mailboxPath.split('/'), function(component) {
|
||||
return 'folder' + component.asCSSIdentifier();
|
||||
});
|
||||
}
|
||||
|
||||
path.splice(0, 0, accountId); // insert account ID
|
||||
|
||||
return path.join('/');
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $id
|
||||
* @memberof Mailbox.prototype
|
||||
* @desc Build the unique ID to identified the mailbox.
|
||||
* @returns a string representing the path relative to the mail module
|
||||
*/
|
||||
Mailbox.prototype.$id = function() {
|
||||
return Mailbox.$absolutePath(this.accountId, this.path);
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $update
|
||||
* @memberof Mailbox.prototype
|
||||
* @desc Fetch the messages metadata of the mailbox.
|
||||
* @returns a promise of the HTTP operation
|
||||
*/
|
||||
Mailbox.prototype.$update = function() {
|
||||
var futureMailboxData;
|
||||
|
||||
futureMailboxData = Mailbox.$$resource.post(this.id, 'view', {sortingAttributes: {sort: 'date', asc: false}});
|
||||
|
||||
return this.$unwrap(futureMailboxData);
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $loadMessage
|
||||
* @memberof Mailbox.prototype
|
||||
* @desc Check if the message is loaded and in any case, fetch more messages headers from the server.
|
||||
* @returns true if the message metadata are already fetched
|
||||
*/
|
||||
Mailbox.prototype.$loadMessage = function(messageId) {
|
||||
var startIndex = this.uidsMap[messageId],
|
||||
endIndex,
|
||||
max = this.$messages.length,
|
||||
loaded = false,
|
||||
uids,
|
||||
futureHeadersData;
|
||||
if (angular.isDefined(this.uidsMap[messageId]) && startIndex < this.$messages.length) {
|
||||
// Index is valid
|
||||
if (angular.isDefined(this.$messages[startIndex].subject)) {// || this.$messages[startIndex].loading) {
|
||||
// Message headers are loaded or data is coming
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
// Preload more headers if possible
|
||||
endIndex = Math.min(startIndex + Mailbox.PRELOAD.LOOKAHEAD, max - 1);
|
||||
if (!angular.isDefined(this.$messages[endIndex].subject)
|
||||
&& !angular.isDefined(this.$messages[endIndex].loading)) {
|
||||
endIndex = Math.min(startIndex + Mailbox.PRELOAD.SIZE, max);
|
||||
for (uids = []; startIndex < endIndex && startIndex < max; startIndex++) {
|
||||
if (angular.isDefined(this.$messages[startIndex].subject) || this.$messages[startIndex].loading) {
|
||||
// Message at this index is already loaded; increase the end index
|
||||
endIndex++;
|
||||
}
|
||||
else {
|
||||
// Message at this index will be loaded
|
||||
uids.push(this.$messages[startIndex].uid);
|
||||
this.$messages[startIndex].loading = true;
|
||||
}
|
||||
}
|
||||
|
||||
Mailbox.$log.debug('Loading UIDs ' + uids.join(' '));
|
||||
futureHeadersData = Mailbox.$$resource.post(this.id, 'headers', {uids: uids});
|
||||
this.$unwrapHeaders(futureHeadersData);
|
||||
}
|
||||
}
|
||||
return loaded;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $omit
|
||||
* @memberof Mailbox.prototype
|
||||
* @desc Return a sanitized object used to send to the server.
|
||||
* @return an object literal copy of the Mailbox instance
|
||||
*/
|
||||
Mailbox.prototype.$omit = function() {
|
||||
var mailbox = {};
|
||||
angular.forEach(this, function(value, key) {
|
||||
if (key != 'constructor' &&
|
||||
key != 'children' &&
|
||||
key[0] != '$') {
|
||||
mailbox[key] = value;
|
||||
}
|
||||
});
|
||||
return mailbox;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $unwrap
|
||||
* @memberof Mailbox.prototype
|
||||
* @desc Unwrap a promise and instanciate new Message objects using received data.
|
||||
* @param {promise} futureMailboxData - a promise of the Mailbox's metadata
|
||||
* @returns a promise of the HTTP operation
|
||||
*/
|
||||
Mailbox.prototype.$unwrap = function(futureMailboxData) {
|
||||
var _this = this,
|
||||
deferred = Mailbox.$q.defer();
|
||||
|
||||
this.$futureMailboxData = futureMailboxData;
|
||||
this.$futureMailboxData.then(function(data) {
|
||||
Mailbox.$timeout(function() {
|
||||
var uids, headers;
|
||||
|
||||
angular.extend(_this, data);
|
||||
_this.$messages = [];
|
||||
_this.uidsMap = {};
|
||||
|
||||
if (_this.uids) {
|
||||
// First entry of 'headers' are keys
|
||||
headers = _.invoke(_this.headers[0], 'toLowerCase');
|
||||
_this.headers.splice(0, 1);
|
||||
|
||||
// First entry of 'uids' are keys when threaded view is enabled
|
||||
if (_this.threaded) {
|
||||
uids = _this.uids[0];
|
||||
_this.uids.splice(0, 1);
|
||||
}
|
||||
|
||||
// Instanciate Message objects
|
||||
_.reduce(_this.uids, function(msgs, msg, i) {
|
||||
var data;
|
||||
if (_this.threaded)
|
||||
data = _.object(uids, msg);
|
||||
else
|
||||
data = {uid: msg.toString()};
|
||||
|
||||
// Build map of UID <=> index
|
||||
_this.uidsMap[data.uid] = i;
|
||||
|
||||
msgs.push(new Mailbox.$Message(_this.accountId, _this.path, data));
|
||||
|
||||
return msgs;
|
||||
}, _this.$messages);
|
||||
|
||||
// Extend Message objects with received headers
|
||||
_.each(_this.headers, function(data) {
|
||||
var msg = _.object(headers, data),
|
||||
i = _this.uidsMap[msg.uid.toString()];
|
||||
_.extend(_this.$messages[i], msg);
|
||||
});
|
||||
}
|
||||
Mailbox.$log.debug('mailbox ' + _this.id + ' ready');
|
||||
deferred.resolve(_this.$messages);
|
||||
});
|
||||
}, function(data) {
|
||||
angular.extend(_this, data);
|
||||
_this.isError = true;
|
||||
deferred.reject();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $unwrapHeaders
|
||||
* @memberof Mailbox.prototype
|
||||
* @desc Unwrap a promise and extend matching Message objects using received data.
|
||||
* @param {promise} futureHeadersData - a promise of some messages metadata
|
||||
*/
|
||||
Mailbox.prototype.$unwrapHeaders = function(futureHeadersData) {
|
||||
var _this = this;
|
||||
|
||||
futureHeadersData.then(function(data) {
|
||||
Mailbox.$timeout(function() {
|
||||
var headers, j;
|
||||
if (data.length > 0) {
|
||||
// First entry of 'headers' are keys
|
||||
headers = _.invoke(data[0], 'toLowerCase');
|
||||
data.splice(0, 1);
|
||||
_.each(data, function(messageHeaders) {
|
||||
messageHeaders = _.object(headers, messageHeaders);
|
||||
j = _this.uidsMap[messageHeaders.uid.toString()];
|
||||
if (angular.isDefined(j)) {
|
||||
_.extend(_this.$messages[j], messageHeaders);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
})();
|
|
@ -0,0 +1,116 @@
|
|||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @name Message
|
||||
* @constructor
|
||||
* @param {string} accountId - the account ID
|
||||
* @param {string} mailboxPath - an array of the mailbox path components
|
||||
* @param {object} futureAddressBookData - either an object literal or a promise
|
||||
*/
|
||||
function Message(accountId, mailboxPath, futureMessageData) {
|
||||
this.accountId = accountId;
|
||||
this.mailboxPath = mailboxPath;
|
||||
// Data is immediately available
|
||||
if (typeof futureMessageData.then !== 'function') {
|
||||
//console.debug(JSON.stringify(futureMessageData, undefined, 2));
|
||||
angular.extend(this, futureMessageData);
|
||||
this.id = this.$absolutePath();
|
||||
}
|
||||
else {
|
||||
// The promise will be unwrapped first
|
||||
this.$unwrap(futureMessageData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @memberof Message
|
||||
* @desc The factory we'll use to register with Angular
|
||||
* @returns the Message constructor
|
||||
*/
|
||||
Message.$factory = ['$q', '$timeout', '$log', '$sce', 'sgSettings', 'sgResource', function($q, $timeout, $log, $sce, Settings, Resource) {
|
||||
angular.extend(Message, {
|
||||
$q: $q,
|
||||
$timeout: $timeout,
|
||||
$log: $log,
|
||||
$sce: $sce,
|
||||
$$resource: new Resource(Settings.baseURL, Settings.activeUser)
|
||||
});
|
||||
|
||||
return Message; // return constructor
|
||||
}];
|
||||
|
||||
/* Factory registration in Angular module */
|
||||
angular.module('SOGo.MailerUI')
|
||||
.factory('sgMessage', Message.$factory);
|
||||
|
||||
/**
|
||||
* @function $absolutePath
|
||||
* @memberof Message.prototype
|
||||
* @desc Build the path of the message
|
||||
* @returns a string representing the path relative to the mail module
|
||||
*/
|
||||
Message.prototype.$absolutePath = function() {
|
||||
var path;
|
||||
|
||||
path = _.map(this.mailboxPath.split('/'), function(component) {
|
||||
return 'folder' + component.asCSSIdentifier();
|
||||
});
|
||||
path.splice(0, 0, this.accountId); // insert account ID
|
||||
path.push(this.uid); // add message UID
|
||||
|
||||
return path.join('/');
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $content
|
||||
* @memberof Message.prototype
|
||||
* @desc Fetch the message body along with other metadata such as the list of attachments.
|
||||
* @returns the HTML representation of the body or a promise of the HTTP operation
|
||||
*/
|
||||
Message.prototype.$content = function() {
|
||||
var futureMessageData;
|
||||
|
||||
if (this.$futureMessageData) {
|
||||
return Message.$sce.trustAs('html', this.content);
|
||||
}
|
||||
|
||||
futureMessageData = Message.$$resource.fetch(this.id, 'view');
|
||||
|
||||
return this.$unwrap(futureMessageData);
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $unwrap
|
||||
* @memberof Message.prototype
|
||||
* @desc Unwrap a promise.
|
||||
* @param {promise} futureMessageData - a promise of some of the Message's data
|
||||
*/
|
||||
Message.prototype.$unwrap = function(futureMessageData) {
|
||||
var _this = this,
|
||||
deferred = Message.$q.defer();
|
||||
|
||||
// Expose the promise
|
||||
this.$futureMessageData = futureMessageData;
|
||||
|
||||
// Resolve the promise
|
||||
this.$futureMessageData.then(function(data) {
|
||||
// Calling $timeout will force Angular to refresh the view
|
||||
Message.$timeout(function() {
|
||||
angular.extend(_this, data);
|
||||
_this.id = _this.$absolutePath();
|
||||
deferred.resolve(_this.content);
|
||||
});
|
||||
}, function(data) {
|
||||
angular.extend(_this, data);
|
||||
_this.isError = true;
|
||||
Message.$log.error(_this.error);
|
||||
deferred.reject();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
})();
|
|
@ -0,0 +1,348 @@
|
|||
@import "settings";
|
||||
|
||||
$module-color: #D04747; // red
|
||||
$module-secondary-color: #501B1B; // darker red
|
||||
$topbar-bg-color: $module-color;
|
||||
$topbar-link-bg-active-hover: scale-color($module-secondary-color, $lightness: -14%);
|
||||
$topbar-link-bg-active: $module-secondary-color;
|
||||
$topbar-link-bg-hover: scale-color($module-color, $lightness: -14%);
|
||||
|
||||
@import "foundation";
|
||||
|
||||
@mixin off-canvas-list {
|
||||
list-style-type: none;
|
||||
padding:0;
|
||||
margin:0;
|
||||
/* display: table; */
|
||||
width: 100%;
|
||||
|
||||
li {
|
||||
/*
|
||||
+-----------------------------------------------+
|
||||
+ li |
|
||||
|+------+-----------------------------+--------+|
|
||||
|| i | form | span ||
|
||||
|+------+-----------------------------+--------+|
|
||||
+-----------------------------------------------+
|
||||
*/
|
||||
/* display: table-row; */
|
||||
transition: background 300ms ease;
|
||||
label {
|
||||
display: block;
|
||||
padding: $off-canvas-label-padding;
|
||||
color: $off-canvas-label-color;
|
||||
text-transform: $off-canvas-label-text-transform;
|
||||
font-size: $off-canvas-label-font-size;
|
||||
font-weight: $off-canvas-label-font-weight;
|
||||
background: $off-canvas-label-bg;
|
||||
border-top: $off-canvas-label-border-top;
|
||||
border-bottom: $off-canvas-label-border-bottom;
|
||||
margin: $off-canvas-label-margin;
|
||||
}
|
||||
.folder-container {
|
||||
display: table;
|
||||
width: 100%;
|
||||
.folder-content {
|
||||
display: table-row;
|
||||
>* {
|
||||
display: table-cell;
|
||||
padding: $off-canvas-link-padding;
|
||||
color: $off-canvas-link-color;
|
||||
/* border-bottom: $off-canvas-link-border-bottom; */
|
||||
//vertical-align: middle;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background: scale-color($tabbar-bg, $lightness: -30%);
|
||||
}
|
||||
}
|
||||
>span {
|
||||
//vertical-align: middle; // causes glitch when selecting row
|
||||
border-left: 3px solid transparent;
|
||||
//width: 2em;
|
||||
}
|
||||
.icon {
|
||||
color: $off-canvas-label-color;
|
||||
width: 1px;
|
||||
}
|
||||
form {
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
* {
|
||||
color: $off-canvas-link-color;
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
//padding-left: $off-canvas-link-padding;
|
||||
}
|
||||
input {
|
||||
border: 0;
|
||||
color: #333 !important;
|
||||
font-size: 1rem;
|
||||
height: $off-canvas-link-padding/2+1rem;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
&._selected {
|
||||
//background-color: #242424 !important;
|
||||
//border: 0 !important;
|
||||
>span {
|
||||
border-left-color: $primary-color;
|
||||
}
|
||||
//* {
|
||||
// color: #eee;
|
||||
//}
|
||||
}
|
||||
&._loading {
|
||||
>span {
|
||||
border-left-color: $off-canvas-label-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.folders-list {
|
||||
@include off-canvas-wrap();
|
||||
ul {
|
||||
@include off-canvas-list();
|
||||
>li >ul {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$i: 1;
|
||||
@while $i < 12 {
|
||||
.folders-list ul li .folder-container .folder-content > .childLevel#{$i} { padding-left: 15px * $i; }
|
||||
$i: $i + 1;
|
||||
}
|
||||
|
||||
$total-columns: 13;
|
||||
$column-gutter: 0;
|
||||
|
||||
#pageContent {
|
||||
@include grid-row($behavior: nest);
|
||||
|
||||
#mailboxesList {
|
||||
position: absolute;
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
top: $topbar-height;
|
||||
bottom: 0;
|
||||
background-color: #333;
|
||||
@include grid-column($columns:13); //, $collapse:true);
|
||||
@media #{$medium-up} {
|
||||
@include grid-column($columns:3);
|
||||
}
|
||||
}
|
||||
|
||||
#messagesList {
|
||||
position: absolute;
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
top: $topbar-height;
|
||||
bottom: 0;
|
||||
left: 23.07692%;
|
||||
background-color: $f-dropdown-list-hover-bg;
|
||||
@include grid-column($columns:13);
|
||||
@media #{$medium-up} {
|
||||
@include grid-column($columns:4);
|
||||
}
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 5px 0;
|
||||
li {
|
||||
list-style-type: none;
|
||||
//border-bottom: $topbar-divider-border-bottom;
|
||||
width: 100%;
|
||||
height: 56px;
|
||||
float: left;
|
||||
clear: left;
|
||||
//border: 2px solid #fff;
|
||||
//-webkit-border-radius: 4px;
|
||||
//-moz-border-radius: 4px;
|
||||
//border-radius: 4px;
|
||||
//transition: all 300ms ease;
|
||||
background-color: $f-dropdown-list-hover-bg;
|
||||
transition: background 300ms ease;
|
||||
a {
|
||||
display: block;
|
||||
color: #666;
|
||||
//border-bottom: 1px dotted #ddd;
|
||||
//width: 100%;
|
||||
//font-size: $table-row-font-size;
|
||||
//line-height: $table-line-height;
|
||||
line-height: rem-calc(24);
|
||||
padding: $table-head-padding;
|
||||
//padding: rem-calc(8 10 18);
|
||||
//margin: 0 rem-calc(12);
|
||||
.name {
|
||||
margin: 0;
|
||||
//font-size: $table-head-font-size;
|
||||
//color: $table-head-font-color;
|
||||
font-weight: $table-head-font-weight;
|
||||
}
|
||||
div {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
span {
|
||||
font-weight: normal;
|
||||
font-size: smaller;
|
||||
}
|
||||
}
|
||||
&.unread {
|
||||
a {
|
||||
.name,
|
||||
.subject {
|
||||
color: $table-head-font-color;
|
||||
/* font-weight: $table-head-font-weight; */
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover,
|
||||
&:active {
|
||||
background-color: $f-dropdown-list-hover-bg;
|
||||
//background-color: scale-color($f-dropdown-list-hover-bg, $lightness: 28%);
|
||||
background-color: #fff;
|
||||
}
|
||||
&._selected,
|
||||
&._selected span {
|
||||
//background-color: $module-light-color;
|
||||
//background-color: $sub-nav-active-bg-hover;
|
||||
//background-color: $f-dropdown-list-hover-bg;
|
||||
background-color: $module-color;
|
||||
background-color: #fff;
|
||||
//color: $module-color;
|
||||
//color: $module-secondary-color;
|
||||
.name {
|
||||
//color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#messageView {
|
||||
position: absolute;
|
||||
top: $topbar-height;
|
||||
bottom: 0;
|
||||
left: 53.8461507692%;
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
border-left: $topbar-divider-border-bottom;
|
||||
padding: $table-head-padding;
|
||||
padding-top: 0;
|
||||
@include grid-column($columns:13);
|
||||
@media #{$medium-up} {
|
||||
@include grid-column($columns:6);
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-left: rem-calc(12);
|
||||
margin-top: 0;
|
||||
}
|
||||
h1 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.header {
|
||||
background-color: $secondary-color;
|
||||
padding-bottom: 0.2em;
|
||||
h1, h6 {
|
||||
color: #fff;
|
||||
}
|
||||
.label {
|
||||
background-color: transparent;
|
||||
border: 1px solid $primary-color;
|
||||
border: 1px solid scale-color($primary-color, $lightness: 52%);
|
||||
color: $primary-color;
|
||||
color: scale-color($primary-color, $lightness: 52%);
|
||||
}
|
||||
label {
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
+-----------------------------------------------+
|
||||
+ .attr (13) |
|
||||
|+-------------+-------------------------------+|
|
||||
|| .key (4) | .value (9) ||
|
||||
|+-------------+-------------------------------+|
|
||||
+-----------------------------------------------+
|
||||
*/
|
||||
.attr {
|
||||
@include grid-row($behavior:collapse);
|
||||
.key {
|
||||
@include grid-column($columns:4);
|
||||
label {
|
||||
color: #999;
|
||||
margin-right: rem-calc(12);
|
||||
}
|
||||
}
|
||||
.value {
|
||||
@include grid-column($columns:9);
|
||||
&.single {
|
||||
@include grid-column($offset: 4, $columns:9);
|
||||
}
|
||||
div {
|
||||
a {
|
||||
color: #666;
|
||||
margin-left: 0.2em;
|
||||
&:hover {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.buttonsToolbar {
|
||||
margin-bottom: rem-calc(12);
|
||||
background-color: #eee;
|
||||
border-top: 2px solid #ddd;
|
||||
.button {
|
||||
margin: 0.4em;
|
||||
&.alert {
|
||||
//display: $button-display;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mailer_mailcontent {
|
||||
background-color: #fff;
|
||||
padding: .5em;
|
||||
overflow: auto;
|
||||
.mailer_mailcontent TABLE {
|
||||
table-layout: auto;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.buttonsToolbar {
|
||||
text-align: right;
|
||||
.button {
|
||||
margin-bottom: 0;
|
||||
font-size: 1.0em;
|
||||
}
|
||||
.folders-list & {
|
||||
background-color: $tabbar-bg;
|
||||
background-color: $off-canvas-bg;
|
||||
text-align: center;
|
||||
.button {
|
||||
background-color: $tabbar-bg;
|
||||
font-size: 1.5em;
|
||||
transition: color 300ms ease;
|
||||
color: scale-color($tabbar-bg, $lightness: 52%);
|
||||
&:focus, &:hover {
|
||||
color: $primary-color;
|
||||
color: #fff;
|
||||
//background-color: scale-color($tabbar-bg, $lightness: 13%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue