The list of addressbook books is now splitted by type: personal addressbooks, other's addressbooks (subscriptions) and global addressbooks (from sogo.conf, per domain). The main ui-view has been splitted and therefore an additional controller has been created. The constructor of the AddressBook model has been improved.
355 lines
16 KiB
XML
355 lines
16 KiB
XML
<?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:label="OGo:label"
|
|
const:userDefaultsKeys="SOGoContactsCategories"
|
|
const:jsFiles="Common/user-model.js, Common/acl-model.js, Common/resource.js, Contacts/card-model.js, Contacts/addressbook-model.js"
|
|
className="UIxPageFrame"
|
|
title="name"
|
|
var:popup="isPopup">
|
|
<script type="text/javascript">
|
|
var contactFolders = <var:string value="contactFolders" const:escapeHTML="NO" />;
|
|
</script>
|
|
|
|
<!--
|
|
<div id="uploadDialog" style="display: none" class="dialog left">
|
|
<div>
|
|
<h3><var:string label:value="Import Cards"/></h3>
|
|
<p class="prompt"><var:string label:value="Select a vCard or LDIF file."/></p>
|
|
<form const:href="" name="uploadForm" id="uploadForm" method="post"
|
|
enctype="multipart/form-data"
|
|
onsubmit="return AIM.submit(this, {'onStart' : validateUploadForm,
|
|
'onComplete' : uploadCompleted})">
|
|
<p class="prompt"><input type="file" name="contactsFile" id="contactsFile" class="textField" required="required" />
|
|
<a href="#" class="button actionButton" id="uploadSubmit"
|
|
onclick="if($('uploadForm').onsubmit()) $('uploadForm').submit()">
|
|
<span><var:string label:value="Upload" /></span></a>
|
|
<a href="#" class="button" const:id="uploadCancel">
|
|
<span><var:string label:value="Cancel" /></span></a></p>
|
|
</form>
|
|
<hr/>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="uploadResults" dropdown-content="dropdown-content" class="f-dropdown">
|
|
<div>
|
|
<h3><var:string label:value="Import Cards"/></h3>
|
|
<p id="uploadResultsContent">!- empty -</p>
|
|
<p><a href="#" class="button" const:id="uploadOK">
|
|
<span><var:string label:value="Done" /></span></a></p>
|
|
<hr/>
|
|
</div>
|
|
</div>
|
|
|
|
<ul class="f-dropdown" dropdown-content="dropdown-content" id="contactMenu">
|
|
<li><var:string label:value="Properties" /></li>
|
|
<li><var:string label:value="Categories" /></li>
|
|
<li>!- separator -</li>
|
|
<li><var:string label:value="Write" /></li>
|
|
<li><var:string label:value="Instant Message" /></li>
|
|
<li>!- separator -</li>
|
|
<li><var:string label:value="Delete" /></li>
|
|
<li>!- separator -</li>
|
|
<li><var:string label:value="Move To" /></li>
|
|
<li><var:string label:value="Copy To" /></li>
|
|
<li><var:string label:value="Export" /></li>
|
|
<li><var:string label:value="View Raw Source" /></li>
|
|
</ul>
|
|
-->
|
|
<!--
|
|
MAIN CONTENT ROW
|
|
Content of the application view injected injected in the element bellow
|
|
MUST be the first html element after body
|
|
SHOULD be a main tag (with role="main")
|
|
|
|
Templates script tag wrappers goes next
|
|
-->
|
|
<main class="view md-layout-fill" ui-view="addressbooks" layout="row" ng-controller="navController"><!-- addressbooks list --></main>
|
|
|
|
<!-- TEMPLATE SCRIPT WRAPPER -->
|
|
<script type="text/ng-template" id="UIxContactFoldersView">
|
|
|
|
<!-- dropdown menu for addressbook options button -->
|
|
<div id="addressbookProperties" class="f-dropdown icons-dropdown" ng-hide="true">
|
|
<ul class="button-group">
|
|
<li label:tooltip="Links to this Address Book"
|
|
tooltip-popup-delay="500">
|
|
<span class="button"
|
|
sg-dropdown-content-toggle="#addressbookLinks">
|
|
<i class="icon-hyperlink"><!-- links --></i>
|
|
</span>
|
|
</li>
|
|
<li label:tooltip="Rename"
|
|
tooltip-popup-delay="500">
|
|
<span class="button" ng-click="edit()">
|
|
<i class="icon-pencil"><!-- rename --></i>
|
|
</span>
|
|
</li>
|
|
<li ng-show="addressbook.isOwned"
|
|
label:tooltip="Sharing..."
|
|
tooltip-popup-delay="500">
|
|
<span class="button" ng-click="share()">
|
|
<i class="icon-share"><!-- share --></i>
|
|
</span>
|
|
</li>
|
|
<li label:tooltip="Import Cards"
|
|
tooltip-popup-delay="500">
|
|
<span class="button" ng-click="importCards()">
|
|
<i class="icon-file"><!-- import --></i>
|
|
</span>
|
|
</li>
|
|
<li label:tooltip="Export"
|
|
tooltip-popup-delay="500">
|
|
<span class="button" ng-click="exportCards()">
|
|
<i class="icon-ion-ios7-upload-outline"><!-- export --></i>
|
|
</span>
|
|
</li>
|
|
<li label:tooltip="Delete"
|
|
tooltip-popup-delay="500">
|
|
<span class="button" ng-click="confirmDelete(addressbook)">
|
|
<i class="icon-trash"><!-- delete --></i>
|
|
</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- dropdown menu for new card split button
|
|
<ul id="newListDrop" class="f-dropdown">
|
|
<li><a class="tiny" ui-sref="addressbook.new({addressbookId: addressbook.id, contactType: 'list'})"><var:string label:value="New List"/></a></li>
|
|
</ul>
|
|
-->
|
|
|
|
<!-- dropdown menu for addressbook links
|
|
<div id="addressbookLinks" class="sg-dropdown-content joyride-tip-guide">
|
|
<span class="joyride-nub left">!- dropdown nub -</span>
|
|
<div class="joyride-content-wrapper">
|
|
<ul>
|
|
<li class="title"><var:string label:value="Links to this Address Book"/></li>
|
|
<li class="subtitle"><var:string label:value="CardDAV URL for Authenticated User Access"/></li>
|
|
<li class="value">{{addressbook.cardDavURL}}</li>
|
|
<var:if condition="isPublicAccessEnabled">
|
|
<li class="subtitle"><var:string label:value="CardDAV URL for Public Access"/></li>
|
|
<li class="value">{{addressbook.publicCardDavURL}}</li>
|
|
</var:if>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
-->
|
|
|
|
<!-- dropdown menu for subscriptions
|
|
<div id="folderSubscribe" class="sg-dropdown-content"
|
|
sg-subscribe="contact"
|
|
sg-subscribe-on-select="subscribeToFolder">!- subscription dropdown -</div>
|
|
-->
|
|
<!-- Sidenav -->
|
|
<md-sidenav id="left-sidenav" class="md-sidenav-left md-whiteframe-z1" md-component-id="left" md-is-locked-open="isGtMedium" layout="column">
|
|
<var:component className="UIxSidenavToolbarTemplate" />
|
|
<md-content md-scroll-y="md-scroll-y" class="md-flex">
|
|
<!-- User's addressbooks -->
|
|
<section>
|
|
<md-subheader class="sg-md-subheader">
|
|
<div layout="row" layout-align="space-between center">
|
|
<span><var:string label:value="AddressBooks"/></span>
|
|
<md-button
|
|
class="iconButton"
|
|
label:aria-label="New Addressbook..."
|
|
ng-click="newAddressbook()">
|
|
<i class="md-icon-add-circle-outline"><!-- add --></i>
|
|
</md-button>
|
|
</div>
|
|
</md-subheader>
|
|
<md-list>
|
|
<md-list-item ng-repeat="folder in service.$addressbooks track by folder.id"
|
|
ui-sref-active="sg-active"
|
|
ng-dblclick="edit($index, folder)">
|
|
<i ng-class="{'md-icon-public': folder.isRemote, 'md-icon-contacts': folder.isEditable}"><!-- icon --></i>
|
|
<button class="md-button md-flex sg-item-name"
|
|
ng-show="editMode!=folder.id"
|
|
ng-click="select(folder)"
|
|
ng-cloak="ng-cloak"
|
|
ui-sref="app.addressbook({addressbookId: folder.id})">{{folder.name}}</button>
|
|
<md-input-container
|
|
class="md-flex md-tile-content"
|
|
ng-show="editMode==folder.id">
|
|
<input class="folder-name" type="text"
|
|
ng-model="folder.name"
|
|
ng-cloak="ng-cloak"
|
|
ng-blur="save($index, folder)"
|
|
sg-focus-on="addressBookName_{{folder.id}}"
|
|
sg-enter="save(folder)"
|
|
sg-escape="revertEditing(folder)"/>
|
|
</md-input-container>
|
|
<md-button class="iconButton" label:aria-label="Options"
|
|
ng-show="currentFolder.id==folder.id">
|
|
<i class="md-icon-more-vert"><!-- options --></i>
|
|
</md-button>
|
|
</md-list-item>
|
|
</md-list>
|
|
</section>
|
|
<!-- Subscriptions -->
|
|
<section>
|
|
<md-subheader class="sg-md-subheader">
|
|
<div layout="row" layout-align="space-between center">
|
|
<span><var:string label:value="Subscriptions"/></span>
|
|
<md-button
|
|
class="iconButton"
|
|
label:aria-label="Subscribe to an Addressbook..."
|
|
sg-subscribe="contact"
|
|
sg-subscribe-on-select="subscribeToFolder(folderData)">
|
|
<i class="md-icon-add-circle-outline"><!-- add --></i>
|
|
</md-button>
|
|
</div>
|
|
</md-subheader>
|
|
<md-list>
|
|
<md-list-item ng-repeat="folder in service.$subscriptions track by folder.id"
|
|
ui-sref-active="sg-active"
|
|
ng-dblclick="edit($index, folder)">
|
|
<i ng-class="{'md-icon-public': folder.isRemote, 'md-icon-contacts': folder.isEditable}"><!-- icon --></i>
|
|
<button class="md-button md-flex sg-item-name"
|
|
ng-show="editMode!=folder.id"
|
|
ng-click="select(folder)"
|
|
ng-cloak="ng-cloak"
|
|
ui-sref="app.addressbook({addressbookId: folder.id})">{{folder.name}}</button>
|
|
<md-input-container
|
|
class="md-flex md-tile-content"
|
|
ng-show="editMode==folder.id">
|
|
<input class="folder-name" type="text"
|
|
ng-model="folder.name"
|
|
ng-cloak="ng-cloak"
|
|
ng-blur="save($index, folder)"
|
|
sg-focus-on="addressBookName_{{folder.id}}"
|
|
sg-enter="save(folder)"
|
|
sg-escape="revertEditing(folder)"/>
|
|
</md-input-container>
|
|
<md-button class="iconButton" label:aria-label="Options"
|
|
ng-show="currentFolder.id==folder.id">
|
|
<i class="md-icon-more-vert"><!-- options --></i>
|
|
</md-button>
|
|
</md-list-item>
|
|
</md-list>
|
|
</section>
|
|
<!-- Remote/domain addressbooks -->
|
|
<section>
|
|
<md-subheader class="sg-md-subheader md-padding">
|
|
<var:string label:value="Global Addressbooks"/>
|
|
</md-subheader>
|
|
<md-list>
|
|
<md-list-item ng-repeat="folder in service.$remotes track by folder.id"
|
|
ui-sref-active="sg-active">
|
|
<i ng-class="{'md-icon-public': folder.isRemote, 'md-icon-contacts': folder.isEditable}"><!-- icon --></i>
|
|
<button class="md-button md-flex sg-item-name"
|
|
ng-click="select(folder)"
|
|
ng-cloak="ng-cloak"
|
|
ui-sref="app.addressbook({addressbookId: folder.id})">{{folder.name}}</button>
|
|
</md-list-item>
|
|
</md-list>
|
|
</section>
|
|
</md-content>
|
|
</md-sidenav>
|
|
|
|
<section layout="column" class="sg-app-content md-layout-fill" ui-view="addressbook"><!-- contacts list --></section>
|
|
</script>
|
|
|
|
<script type="text/ng-template" id="addressbook">
|
|
<md-toolbar layout="column" layout-align="space-between start" class="md-tall toolbar-main">
|
|
<div class="md-toolbar-tools md-toolbar-tools-top sg-padded" layout="row" layout-align="space-between start">
|
|
<var:component className="UIxTopnavToolbarTemplate" />
|
|
</div>
|
|
<div class="md-toolbar-tools md-toolbar-tools-bottom" layout="row" layout-align="space-between center">
|
|
<div class="view-list cols-6 sg-padded" layout="row" layout-align="space-between center"
|
|
sg-search="addressbook.$filter(searchText, { search: searchField })">
|
|
<md-input-container class="sg-search-field-container">
|
|
<label style="color: white"><i class="md-icon-search"><!--icon--></i><var:string label:value="Search"/></label>
|
|
<input name="folderSearch" type="search" style="color: white"/>
|
|
</md-input-container>
|
|
|
|
<div class="sg-toolbar-group">
|
|
<md-select class="sg-toolbar-sort md-contrast-light">
|
|
<md-option value="name_or_address"><var:string label:value="Name or Email"/></md-option>
|
|
<md-option value="category"><var:string label:value="Category"/></md-option>
|
|
<md-option value="organization"><var:string label:value="Organization"/></md-option>
|
|
</md-select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</md-toolbar>
|
|
<div layout="row" class="md-flex" layout-align="space-between">
|
|
<md-content class="view-list" id="contactsList">
|
|
<header class="sg-md-subheader sg-md-subheader--fixed">
|
|
<h2 class="sg-md-subhead-solo fg-sogoBlue-700">Contacts</h2>
|
|
</header>
|
|
<!-- Search field & special results
|
|
<input type="text" placeholder="Search" ng-model="search.filter" ng-keyup="doSearch($event)" />
|
|
<div ng-switch="search.status">
|
|
<div ng-switch-when="min-char" class="alert-bg">
|
|
<i class="icon-warning"></i><var:string label:value="Please enter at least three characters"/>
|
|
</div>
|
|
<div ng-switch-when="no-result" class="alert-bg">
|
|
<i class="icon-ion-search"></i><var:string label:value="No matching card"/>
|
|
</div>
|
|
<div ng-switch-when="remote-addressbook" ng-show="addressbook.cards.length == 0" class="alert-bg">
|
|
<i class="icon-ion-search"></i><var:string label:value="Initiate a search"/>
|
|
</div>
|
|
</div>
|
|
-->
|
|
<md-list vs-repeat="72" vs-scroll-parent="#contactsList">
|
|
<md-list-item ng-repeat="currentCard in addressbook.cards track by currentCard.id">
|
|
<div
|
|
ng-class="{_selected: card.id == currentCard.id}"
|
|
ng-click="select($index); toggleDetailView()"
|
|
layout="row"
|
|
flex="true">
|
|
<div class="sg-avatar" ng-show="currentCard.tag == 'vcard'">
|
|
<!--card avatar-->
|
|
</div>
|
|
<div class="sg-list-avatar" ng-show="currentCard.tag == 'vlist'">
|
|
<!--list avatar-->
|
|
</div>
|
|
<div class="sg-tile-content">
|
|
<a ui-sref="app.addressbook.card.view({addressbookId: addressbook.id, cardId: currentCard.id})">
|
|
<div class="sg-md-body-multi contact-name" ng-bind-html="currentCard.$fullname()"><!-- cn --></div>
|
|
<div class="sg-md-subhead-multi contact-email">{{currentCard.$preferredEmail()}}</div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</md-list-item>
|
|
</md-list>
|
|
</md-content>
|
|
|
|
<md-button class="iconButton md-fab md-fab--bottom md-accent hide-sm"
|
|
label:aria-label="New Contact"
|
|
ng-click="newComponent()">
|
|
<i class="md-icon-add"><!--icon--></i>
|
|
</md-button>
|
|
|
|
<!-- This extra container is used to animate views transitions
|
|
double quotes in ng-animate is not a typo -->
|
|
<div id="detailView" class="view-detail" layout="column">
|
|
<md-card class="viewer" ui-view="card"><!-- card view --></md-card>
|
|
</div>
|
|
|
|
<md-button class="iconButton md-fab md-accent show-sm"
|
|
label:aria-label="New Contact"
|
|
ng-click="newComponent()">
|
|
<i class="md-icon-add"><!--icon--></i>
|
|
</md-button>
|
|
</div>
|
|
</script>
|
|
|
|
<!-- modal for addressbook sharing options -->
|
|
<script type="text/ng-template" id="UIxUserRightsEditor">
|
|
<var:component className="UIxContactsUserRightsEditor" />
|
|
</script>
|
|
<script type="text/ng-template" id="UIxContactViewTemplate">
|
|
<var:component className="UIxContactViewTemplate" />
|
|
</script>
|
|
|
|
|
|
|
|
<var:string value="errorAlertJavaScript" const:escapeHTML="NO" />
|
|
|
|
</var:component>
|