2014-01-05 22:54:57 +00:00
<!DOCTYPE html>
2014-06-01 20:50:14 +00:00
<!--
2014-11-16 20:13:20 +00:00
// Copyright (C) 2014 The Syncthing Authors.
2014-09-29 19:43:32 +00:00
//
2015-03-07 20:36:35 +00:00
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
2014-06-01 20:50:14 +00:00
-->
2014-11-26 12:39:59 +00:00
< html lang = "en" ng-app = "syncthing" ng-controller = "SyncthingController" class = "ng-cloak" >
2014-01-05 22:54:57 +00:00
< head >
2014-04-09 21:00:23 +00:00
< meta charset = "utf-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< meta name = "description" content = "" >
< meta name = "author" content = "" >
2014-11-26 12:39:59 +00:00
< link rel = "shortcut icon" href = "assets/img/favicon.png" >
2014-04-09 21:00:23 +00:00
2015-07-20 09:18:48 +00:00
< title ng-bind = "thisDeviceName() + ' | Syncthing'" > < / title >
2014-11-26 12:39:59 +00:00
< link href = "vendor/bootstrap/css/bootstrap.min.css" rel = "stylesheet" >
< link href = "assets/font/raleway.css" rel = "stylesheet" >
< link href = "assets/css/overrides.css" rel = "stylesheet" >
2014-01-05 22:54:57 +00:00
< / head >
2014-05-16 16:42:22 +00:00
< body >
2014-04-09 21:00:23 +00:00
<!-- Top bar -->
< nav class = "navbar navbar-top navbar-default" role = "navigation" >
2014-01-08 12:52:17 +00:00
< div class = "container" >
2015-03-18 11:51:23 +00:00
< span class = "navbar-brand" > < img class = "logo" src = "assets/img/logo-horizontal.svg" height = "32" width = "117" / > < / span >
2015-04-02 12:48:59 +00:00
< p class = "navbar-text hidden-xs" ng-class = "{'hidden-sm':upgradeInfo && upgradeInfo.newer}" > {{thisDeviceName()}}< / p >
2014-05-20 17:36:37 +00:00
< ul class = "nav navbar-nav navbar-right" >
2014-09-30 22:01:32 +00:00
< li ng-if = "upgradeInfo && upgradeInfo.newer" >
2014-09-10 09:27:21 +00:00
< button type = "button" class = "btn navbar-btn btn-primary btn-sm" href = "" ng-click = "upgrade()" >
2015-05-27 19:54:00 +00:00
< span class = "glyphicon glyphicon-chevron-up" > < / span >
2014-09-10 09:27:21 +00:00
< span translate translate-value-version = "{{upgradeInfo.latest}}" > Upgrade To {%version%}< / span >
2014-07-20 11:49:26 +00:00
< / button >
2014-07-14 08:45:29 +00:00
< / li >
2015-04-22 12:41:08 +00:00
< li ng-if = "upgradeInfo && upgradeInfo.majorNewer" >
< button type = "button" class = "btn navbar-btn btn-danger btn-sm" href = "" ng-click = "upgradeMajor()" >
2015-05-27 19:54:00 +00:00
< span class = "glyphicon glyphicon-chevron-up" > < / span >
2015-04-22 12:41:08 +00:00
< span translate translate-value-version = "{{upgradeInfo.latest}}" > Upgrade To {%version%}< / span >
< / button >
< / li >
2015-04-02 12:48:59 +00:00
< li class = "dropdown" language-select > < / li >
2015-06-02 14:48:31 +00:00
< li class = "hidden-xs" >
2015-05-27 19:54:00 +00:00
< a href = "http://docs.syncthing.net/intro/gui.html" target = "_blank" >
2015-06-02 14:48:31 +00:00
< span class = "glyphicon glyphicon-book" > < / span > < span translate > Help< / span >
2015-05-27 19:54:00 +00:00
< / a >
< / li >
2014-05-24 19:56:09 +00:00
< li class = "dropdown" >
2015-05-27 19:54:00 +00:00
< a href = "#" class = "dropdown-toggle" data-toggle = "dropdown" > < span class = "glyphicon glyphicon-cog" aria-label = "Edit" > < / span > < span translate > Actions< / span > < span class = "caret" > < / span > < / a >
2014-05-20 17:36:37 +00:00
< ul class = "dropdown-menu" >
2015-05-27 19:54:00 +00:00
< li > < a href = "" ng-click = "editSettings()" > < span class = "glyphicon glyphicon-cog" > < / span > < span translate > Settings< / span > < / a > < / li >
< li > < a href = "" ng-click = "idDevice()" > < span class = "glyphicon glyphicon-qrcode" > < / span > < span translate > Show ID< / span > < / a > < / li >
2014-05-20 17:36:37 +00:00
< li class = "divider" > < / li >
2015-05-27 19:54:00 +00:00
< li > < a href = "" ng-click = "shutdown()" > < span class = "glyphicon glyphicon-off" > < / span > < span translate > Shutdown< / span > < / a > < / li >
< li > < a href = "" ng-click = "restart()" > < span class = "glyphicon glyphicon-refresh" > < / span > < span translate > Restart< / span > < / a > < / li >
2014-07-07 10:58:56 +00:00
< li class = "divider" > < / li >
2015-06-02 14:48:31 +00:00
< li class = "visible-xs" >
< a href = "http://docs.syncthing.net/intro/gui.html" target = "_blank" >
< span class = "glyphicon glyphicon-book" > < / span > < span translate > Help< / span >
< / a >
< / li >
2015-05-27 19:54:00 +00:00
< li > < a href = "" ng-click = "about()" > < span class = "glyphicon glyphicon-heart-empty" > < / span > < span translate > About< / span > < / a > < / li >
2015-07-03 12:07:38 +00:00
< li class = "divider" > < / li >
< li > < a href = "" ng-click = "advanced()" > < span class = "glyphicon glyphicon-cog" > < / span > < span translate > Advanced< / span > < / a > < / li >
2014-05-20 17:36:37 +00:00
< / ul >
< / li >
2014-05-24 19:56:09 +00:00
< / ul >
2014-02-12 11:10:44 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< / nav >
2014-01-05 22:54:57 +00:00
2014-04-09 21:00:23 +00:00
< div class = "container" >
2014-02-12 22:18:41 +00:00
2015-01-23 15:28:30 +00:00
<!-- Panel: Restart Needed -->
2014-04-09 21:00:23 +00:00
< div ng-if = "!configInSync" class = "row" >
< div class = "col-md-12" >
< div class = "panel panel-warning" >
2015-01-23 15:28:30 +00:00
< div class = "panel-heading" > < h3 class = "panel-title" > < span class = "glyphicon glyphicon-exclamation-sign" > < / span > < span translate > Restart Needed< / span > < / h3 > < / div >
2014-04-09 21:00:23 +00:00
< div class = "panel-body" >
2014-07-20 11:49:26 +00:00
< p translate > The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.< / p >
2014-04-09 21:00:23 +00:00
< / div >
< div class = "panel-footer" >
2015-05-27 19:54:00 +00:00
< button type = "button" class = "btn btn-sm btn-default pull-right" ng-click = "restart()" > < span class = "glyphicon glyphicon-refresh" > < / span > < span translate > Restart< / span > < / button >
2014-04-09 21:00:23 +00:00
< div class = "clearfix" > < / div >
< / div >
2014-01-05 22:54:57 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< / div >
2014-02-12 11:10:44 +00:00
< / div >
2015-01-23 15:28:30 +00:00
<!-- Panel: New Device -->
< div ng-repeat = "(device, event) in deviceRejections" class = "row" >
< div class = "col-md-12" >
< div class = "panel panel-warning" >
< div class = "panel-heading" >
< h3 class = "panel-title" >
2015-05-27 19:54:00 +00:00
< identicon data-value = "device" > < / identicon > < span translate > New Device< / span >
2015-01-23 15:28:30 +00:00
< / h3 >
< / div >
< div class = "panel-body" >
< p >
2015-05-21 08:40:46 +00:00
< small > {{ event.time | date:"yyyy-MM-dd HH:mm:ss" }}:< / small >
2015-01-23 15:28:30 +00:00
< span translate translate-value-device = "{{ device }}" translate-value-address = "{{ event.data.address }}" >
Device {%device%} ({%address%}) wants to connect. Add new device?
< span >
< / p >
< / div >
< div class = "panel-footer clearfix" >
< div class = "pull-right" >
2015-05-27 19:54:00 +00:00
< button class = "btn btn-sm btn-success" ng-click = "addNewDeviceID(device)" > < span class = "glyphicon glyphicon-ok" > < / span > < span translate > Add< / span > < / button >
< button class = "btn btn-sm btn-danger" ng-click = "ignoreRejectedDevice(device)" > < span class = "glyphicon glyphicon-remove" > < / span > < span translate > Ignore< / span > < / button >
< button class = "btn btn-sm btn-default" ng-click = "dismissDeviceRejection(device)" > < span class = "glyphicon glyphicon-time" > < / span > < span translate > Later< / span > < / button >
2015-01-23 15:28:30 +00:00
< / div >
< / div >
< / div >
< / div >
< / div >
<!-- Panel: New Folder -->
< div ng-repeat = "(key, event) in folderRejections" class = "row reject" >
< div class = "col-md-12" >
< div class = "panel panel-warning" >
< div class = "panel-heading" >
< h3 class = "panel-title" > < span class = "glyphicon glyphicon-hdd" > < / span >
< span translate ng-if = "!folders[event.data.folder]" > New Folder< / span >
< span translate ng-if = "folders[event.data.folder]" > Share Folder< / span >
< / h3 >
< / div >
< div class = "panel-body" >
< p >
2015-05-21 08:40:46 +00:00
< small > {{ event.time | date:"yyyy-MM-dd HH:mm:ss" }}:< / small >
2015-01-23 15:28:30 +00:00
< span translate translate-value-device = "{{ deviceName(findDevice(event.data.device)) }}" translate-value-folder = "{{ event.data.folder }}" >
{%device%} wants to share folder "{%folder%}".
< / span >
< span translate ng-if = "folders[event.data.folder]" > Share this folder?< / span >
< span translate ng-if = "!folders[event.data.folder]" > Add new folder?< / span >
< / p >
< / div >
< div class = "panel-footer clearfix" >
< div class = "pull-right" >
< button class = "btn btn-sm btn-success" ng-click = "addFolderAndShare(event.data.folder, event.data.device)" ng-if = "!folders[event.data.folder]" >
2015-05-27 19:54:00 +00:00
< span class = "glyphicon glyphicon-ok" > < / span > < span translate > Add< / span >
2015-01-23 15:28:30 +00:00
< / button >
< button class = "btn btn-sm btn-success" ng-click = "shareFolderWithDevice(event.data.folder, event.data.device)" ng-if = "folders[event.data.folder]" >
2015-05-27 19:54:00 +00:00
< span class = "glyphicon glyphicon-ok" > < / span > < span translate > Share< / span >
2015-01-23 15:28:30 +00:00
< / button >
< button class = "btn btn-sm btn-default" ng-click = "dismissFolderRejection(event.data.folder, event.data.device)" >
2015-05-27 19:54:00 +00:00
< span class = "glyphicon glyphicon-time" > < / span > < span translate > Later< / span >
2015-01-23 15:28:30 +00:00
< / button >
< / div >
< / div >
< / div >
< / div >
< / div >
<!-- Panel: Notice -->
< div ng-if = "errorList().length > 0" class = "row" >
< div class = "col-md-12" >
< div class = "panel panel-warning" >
< div class = "panel-heading" > < h3 class = "panel-title" > < span class = "glyphicon glyphicon-exclamation-sign" > < / span > < span translate > Notice< / span > < / h3 > < / div >
< div class = "panel-body" >
2015-05-21 08:40:46 +00:00
< p ng-repeat = "err in errorList()" > < small > {{err.time | date:"yyyy-MM-dd HH:mm:ss"}}:< / small > {{friendlyDevices(err.error)}}< / p >
2015-01-23 15:28:30 +00:00
< / div >
< div class = "panel-footer" >
2015-05-27 19:54:00 +00:00
< button type = "button" class = "pull-right btn btn-sm btn-default" ng-click = "clearErrors()" > < span class = "glyphicon glyphicon-ok" > < / span > < span translate > OK< / span > < / button >
2015-01-23 15:28:30 +00:00
< div class = "clearfix" > < / div >
< / div >
< / div >
< / div >
< / div >
2014-04-09 21:00:23 +00:00
<!-- First regular row -->
2014-02-12 11:10:44 +00:00
< div class = "row" >
2014-04-09 21:00:23 +00:00
2014-09-28 11:00:38 +00:00
<!-- Folder list (top left) -->
2014-04-09 21:00:23 +00:00
< div class = "col-md-6" >
2014-09-28 11:00:38 +00:00
< div class = "panel-group" id = "folders" >
2015-01-08 10:04:27 +00:00
< div class = "visible-xs" > < h3 > < span translate > Folders< / span > < / h3 > < hr > < / div >
2014-11-29 12:08:00 +00:00
< div class = "panel panel-default" ng-repeat = "folder in folderList()" >
2014-09-28 11:00:38 +00:00
< div class = "panel-heading" data-toggle = "collapse" data-parent = "#folders" href = "#folder-{{$index}}" style = "cursor: pointer" >
2015-03-10 22:45:43 +00:00
< div class = "panel-progress" ng-show = "folderStatus(folder) == 'syncing'" ng-attr-style = "width: {{syncPercentage(folder.id)}}%" > < / div >
2014-05-24 19:56:09 +00:00
< h3 class = "panel-title" >
2015-03-10 22:45:43 +00:00
< span class = "glyphicon glyphicon-hdd hidden-xs" > < / span > {{folder.id}}
2015-01-08 10:04:27 +00:00
< span class = "pull-right text-{{folderClass(folder)}}" ng-switch = "folderStatus(folder)" >
< span ng-switch-when = "unknown" > < span class = "hidden-xs" translate > Unknown< / span > < span class = "visible-xs" > ◼ < / span > < / span >
< span ng-switch-when = "unshared" > < span class = "hidden-xs" translate > Unshared< / span > < span class = "visible-xs" > ◼ < / span > < / span >
< span ng-switch-when = "stopped" > < span class = "hidden-xs" translate > Stopped< / span > < span class = "visible-xs" > ◼ < / span > < / span >
< span ng-switch-when = "scanning" > < span class = "hidden-xs" translate > Scanning< / span > < span class = "visible-xs" > ◼ < / span > < / span >
< span ng-switch-when = "idle" > < span class = "hidden-xs" translate > Up to Date< / span > < span class = "visible-xs" > ◼ < / span > < / span >
2014-09-08 17:46:33 +00:00
< span ng-switch-when = "syncing" >
2015-01-08 10:04:27 +00:00
< span class = "hidden-xs" translate > Syncing< / span >
2015-03-10 22:45:43 +00:00
({{syncPercentage(folder.id)}}%)
2014-09-08 17:46:33 +00:00
< / span >
2015-06-26 12:22:52 +00:00
< span ng-switch-when = "outofsync" > < span class = "hidden-xs" translate > Out of Sync< / span > < span class = "visible-xs" > ◼ < / span > < / span >
2014-09-08 17:46:33 +00:00
< / span >
2014-05-24 19:56:09 +00:00
< / h3 >
< / div >
2015-02-19 14:48:43 +00:00
< div id = "folder-{{$index}}" class = "panel-collapse collapse" >
2014-05-24 19:56:09 +00:00
< div class = "panel-body" >
2014-09-10 09:27:21 +00:00
< table class = "table table-condensed table-striped" >
< tbody >
< tr >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-folder-open" > < / span > < span translate > Folder Path< / span > < / th >
2015-03-10 22:45:43 +00:00
< td class = "text-right" > {{folder.path}}< / td >
2014-09-10 09:27:21 +00:00
< / tr >
2015-04-12 20:12:01 +00:00
< tr ng-if = "model[folder.id].invalid || model[folder.id].error" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-warning-sign" > < / span > < span translate > Error< / span > < / th >
2015-04-12 20:12:01 +00:00
< td class = "text-right" > {{model[folder.id].invalid || model[folder.id].error}}< / td >
2014-09-10 09:27:21 +00:00
< / tr >
< tr >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-globe" > < / span > < span translate > Global State< / span > < / th >
2015-03-10 22:45:43 +00:00
< td class = "text-right" > {{model[folder.id].globalFiles | alwaysNumber}} < span translate > items< / span > , ~{{model[folder.id].globalBytes | binary}}B< / td >
2014-09-10 09:27:21 +00:00
< / tr >
< tr >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-home" > < / span > < span translate > Local State< / span > < / th >
2015-03-10 22:45:43 +00:00
< td class = "text-right" > {{model[folder.id].localFiles | alwaysNumber}} < span translate > items< / span > , ~{{model[folder.id].localBytes | binary}}B< / td >
2014-09-10 09:27:21 +00:00
< / tr >
2015-03-10 22:45:43 +00:00
< tr ng-if = "model[folder.id].needFiles > 0" >
2015-07-03 12:07:38 +00:00
< th > < span class = "glyphicon glyphicon-cloud-download" > < / span > < span translate > Out of Sync< / span > < / th >
2014-09-10 09:27:21 +00:00
< td class = "text-right" >
2015-03-10 22:45:43 +00:00
< a ng-click = "showNeed(folder.id)" href = "" > {{model[folder.id].needFiles | alwaysNumber}} < span translate > items< / span > , ~{{model[folder.id].needBytes | binary}}B< / a >
2014-09-10 09:27:21 +00:00
< / td >
< / tr >
2015-07-05 09:21:15 +00:00
< tr ng-if = "!folder.readOnly && (folderStatus(folder) === 'outofsync' || hasFailedFiles(folder.id))" >
2015-06-26 12:22:52 +00:00
< th > < span class = "glyphicon glyphicon-exclamation-sign" > < / span > < span translate > Failed Items< / span > < / th >
<!-- Show the number of failed items as a link to bring up the list. -->
< td ng-if = "hasFailedFiles(folder.id)" class = "text-right" >
< a ng-click = "showFailed(folder.id)" href = "" > {{failed[folder.id].length | alwaysNumber}} < span translate > items< / span > < / a >
< / td >
<!-- The list of failed items hasn't loaded yet; show an ellipsis for the time being. -->
< td ng-if = "!hasFailedFiles(folder.id)" class = "text-right" >
...
< / td >
< / tr >
2015-03-10 22:45:43 +00:00
< tr ng-if = "folder.readOnly" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-lock" > < / span > < span translate > Folder Master< / span > < / th >
2014-09-10 09:27:21 +00:00
< td class = "text-right" >
2014-11-27 19:43:00 +00:00
< span translate > Yes< / span >
2014-09-10 09:27:21 +00:00
< / td >
< / tr >
2015-03-10 22:45:43 +00:00
< tr ng-if = "model[folder.id].ignorePatterns" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-eye-close" > < / span > < span translate > Ignore Patterns< / span > < / th >
2015-01-27 14:27:44 +00:00
< td class = "text-right" >
< span translate > Yes< / span >
< / td >
< / tr >
2015-03-10 22:45:43 +00:00
< tr ng-if = "folder.ignorePerms" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-unchecked" > < / span > < span translate > Ignore Permissions< / span > < / th >
2014-09-10 09:27:21 +00:00
< td class = "text-right" >
2014-11-27 19:43:00 +00:00
< span translate > Yes< / span >
2014-09-10 09:27:21 +00:00
< / td >
< / tr >
2015-03-10 22:45:43 +00:00
< tr ng-if = "folder.rescanIntervalS != 60" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-refresh" > < / span > < span translate > Rescan Interval< / span > < / th >
2015-03-10 22:45:43 +00:00
< td class = "text-right" > {{folder.rescanIntervalS}} s< / td >
2014-09-10 09:27:21 +00:00
< / tr >
2015-04-25 05:13:53 +00:00
< tr ng-if = "folder.order != 'random'" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-sort" > < / span > < span translate > File Pull Order< / span > < / th >
2015-04-25 05:13:53 +00:00
< td class = "text-right" ng-switch = "folder.order" >
< span ng-switch-when = "random" translate > Random< / span >
< span ng-switch-when = "alphabetic" translate > Alphabetic< / span >
< span ng-switch-when = "smallestFirst" translate > Smallest First< / span >
< span ng-switch-when = "largestFirst" translate > Largest First< / span >
< span ng-switch-when = "oldestFirst" translate > Oldest First< / span >
< span ng-switch-when = "newestFirst" translate > Newest First< / span >
< / td >
< / tr >
2015-03-10 22:45:43 +00:00
< tr ng-if = "folder.versioning.type" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-tags" > < / span > < span translate > File Versioning< / span > < / th >
2015-03-19 17:16:48 +00:00
< td class = "text-right" ng-switch = "folder.versioning.type" >
2015-06-12 11:04:00 +00:00
< span ng-switch-when = "trashcan" translate > Trash Can File Versioning< / span >
2015-01-15 14:47:47 +00:00
< span ng-switch-when = "staggered" translate > Staggered File Versioning< / span >
< span ng-switch-when = "simple" translate > Simple File Versioning< / span >
2015-03-19 10:31:21 +00:00
< span ng-switch-when = "external" translate > External File Versioning< / span >
2015-01-15 14:47:47 +00:00
< / td >
< / tr >
2014-12-01 19:50:27 +00:00
< tr >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-share-alt" > < / span > < span translate > Shared With< / span > < / th >
2014-12-01 19:50:27 +00:00
< td class = "text-right" > {{sharesFolder(folder)}}< / td >
< / tr >
2015-06-16 11:12:34 +00:00
< tr ng-if = "!folder.readOnly && folderStats[folder.id].lastFile && folderStats[folder.id].lastFile.filename" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-transfer" > < / span > < span translate > Last File Received< / span > < / th >
2014-12-07 20:21:12 +00:00
< td class = "text-right" >
2015-05-21 08:40:46 +00:00
< span title = "{{folderStats[folder.id].lastFile.filename}} @ {{folderStats[folder.id].lastFile.at | date:'yyyy-MM-dd HH:mm:ss'}}" >
2015-06-16 11:12:34 +00:00
< span translate ng-if = "!folderStats[folder.id].lastFile.deleted" > Updated< / span >
< span translate ng-if = "folderStats[folder.id].lastFile.deleted" > Deleted< / span >
2015-03-10 22:45:43 +00:00
{{folderStats[folder.id].lastFile.filename | basename}}
2014-12-07 20:21:12 +00:00
< / span >
< / td >
< / tr >
2014-09-10 09:27:21 +00:00
< / tbody >
< / table >
< / div >
< div class = "panel-footer" >
2015-07-05 09:20:59 +00:00
< button class = "btn btn-sm btn-danger pull-left" ng-if = "folderStatus(folder) == 'outofsync' && folder.readOnly" ng-click = "override(folder.id)" href = "" > < span class = "glyphicon glyphicon-upload" > < / span > < span translate > Override Changes< / span > < / button >
2014-06-16 08:47:02 +00:00
< span class = "pull-right" >
2015-06-13 18:10:11 +00:00
< button class = "btn btn-sm btn-default" href = "" ng-show = "['idle', 'stopped'].indexOf(folderStatus(folder)) > -1" ng-click = "rescanFolder(folder.id)" > < span class = "glyphicon glyphicon-refresh" > < / span > < span translate > Rescan< / span > < / button >
2015-05-27 19:54:00 +00:00
< button class = "btn btn-sm btn-default" href = "" ng-click = "editFolder(folder)" > < span class = "glyphicon glyphicon-pencil" > < / span > < span translate > Edit< / span > < / button >
2014-06-16 08:47:02 +00:00
< / span >
2014-09-10 09:27:21 +00:00
< div class = "clearfix" > < / div >
2014-05-24 19:56:09 +00:00
< / div >
2014-05-20 17:36:37 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< / div >
2014-02-12 11:10:44 +00:00
< / div >
2015-02-11 18:52:59 +00:00
< span class = "pull-right" >
2015-05-27 19:54:00 +00:00
< button class = "btn btn-sm btn-default" ng-click = "rescanAllFolders()" > < span class = "glyphicon glyphicon-repeat" > < / span > < span translate > Rescan All< / span > < / button >
< button class = "btn btn-sm btn-default" ng-click = "addFolder()" > < span class = "glyphicon glyphicon-plus" > < / span > < span translate > Add Folder< / span > < / button >
2015-02-11 18:52:59 +00:00
< / span >
< div class = "clearfix" > < / div >
2014-09-10 14:56:23 +00:00
< hr class = "visible-sm" / >
2014-04-09 21:00:23 +00:00
< / div >
2014-01-05 22:54:57 +00:00
2014-09-28 11:00:38 +00:00
<!-- Device list (top right) -->
2014-04-09 21:00:23 +00:00
2014-09-28 11:00:38 +00:00
<!-- This device -->
2014-09-10 09:27:21 +00:00
2014-04-09 21:00:23 +00:00
< div class = "col-md-6" >
2015-01-08 10:04:27 +00:00
< div class = "visible-xs" > < h3 > < span translate > Devices< / span > < / h3 > < hr > < / div >
2014-09-28 11:00:38 +00:00
< div class = "panel panel-default" ng-repeat = "deviceCfg in [thisDevice()]" >
< div class = "panel-heading" data-toggle = "collapse" href = "#device-this" style = "cursor: pointer" >
2014-09-10 09:27:21 +00:00
< h3 class = "panel-title" >
2015-03-10 22:45:43 +00:00
< identicon data-value = "deviceCfg.deviceID" > < / identicon >   {{deviceName(deviceCfg)}}
2014-09-10 09:27:21 +00:00
< / h3 >
< / div >
2014-09-28 11:00:38 +00:00
< div id = "device-this" class = "panel-collapse collapse in" >
2014-09-10 09:27:21 +00:00
< div class = "panel-body" >
< table class = "table table-condensed table-striped" >
< tbody >
< tr >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-cloud-download" > < / span > < span translate > Download Rate< / span > < / th >
2015-04-09 10:14:15 +00:00
< td class = "text-right" > {{connectionsTotal.inbps | binary}}B/s ({{connectionsTotal.inBytesTotal | binary}}B)< / td >
2014-09-10 09:27:21 +00:00
< / tr >
< tr >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-cloud-upload" > < / span > < span translate > Upload Rate< / span > < / th >
2015-04-09 10:14:15 +00:00
< td class = "text-right" > {{connectionsTotal.outbps | binary}}B/s ({{connectionsTotal.outBytesTotal | binary}}B)< / td >
2014-09-10 09:27:21 +00:00
< / tr >
2015-06-19 19:52:19 +00:00
< tr >
< th > < span class = "glyphicon glyphicon-home" > < / span > < span translate > Local State (Total)< / span > < / th >
< td class = "text-right" > {{foldersTotalLocalFiles | alwaysNumber}} < span translate > items< / span > , ~{{ foldersTotalLocalBytes | binary}}B< / td >
< / tr >
2014-09-10 09:27:21 +00:00
< tr >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-th" > < / span > < span translate > RAM Utilization< / span > < / th >
2014-09-10 09:27:21 +00:00
< td class = "text-right" > {{system.sys | binary}}B< / td >
< / tr >
< tr >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-dashboard" > < / span > < span translate > CPU Utilization< / span > < / th >
2014-09-10 09:27:21 +00:00
< td class = "text-right" > {{system.cpuPercent | alwaysNumber | natural:1}}%< / td >
< / tr >
2014-11-18 22:57:21 +00:00
< tr ng-if = "system.extAnnounceOK != undefined && announceServersTotal > 0" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-bullhorn" > < / span > < span translate > Global Discovery< / span > < / th >
2014-09-10 09:27:21 +00:00
< td class = "text-right" >
2014-11-18 22:57:21 +00:00
< span ng-if = "announceServersFailed.length == 0" class = "data text-success" >
< span > OK< / span >
< / span >
2015-03-09 21:08:32 +00:00
< span ng-if = "announceServersFailed.length != 0" class = "data" ng-class = "{'text-danger': announceServersFailed.length == announceServersTotal}" >
2014-11-18 22:57:21 +00:00
< span popover data-trigger = "hover" data-placement = "bottom" data-content = "{{announceServersFailed.join('\n')}}" >
{{announceServersTotal-announceServersFailed.length}}/{{announceServersTotal}}
< / span >
< / span >
2014-09-10 09:27:21 +00:00
< / td >
< / tr >
2015-04-03 18:00:13 +00:00
< tr >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-time" > < / span > < span translate > Uptime< / span > < / th >
2015-04-03 18:00:13 +00:00
< td class = "text-right" > {{system.uptime | duration:"m"}}< / td >
< / tr >
2014-09-10 09:27:21 +00:00
< tr >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-tag" > < / span > < span translate > Version< / span > < / th >
2015-04-09 09:32:54 +00:00
< td class = "text-right" > {{versionString()}}< / td >
2014-09-10 09:27:21 +00:00
< / tr >
< / tbody >
< / table >
2014-05-20 17:36:37 +00:00
< / div >
< / div >
2014-09-10 09:27:21 +00:00
< / div >
2014-09-28 11:00:38 +00:00
<!-- Remote devices -->
2014-04-09 21:00:23 +00:00
2014-09-28 11:00:38 +00:00
< div class = "panel-group" id = "devices" >
2014-11-29 12:08:00 +00:00
< div class = "panel panel-default" ng-repeat = "deviceCfg in otherDevices()" >
2014-09-28 11:00:38 +00:00
< div class = "panel-heading" data-toggle = "collapse" data-parent = "#devices" href = "#device-{{$index}}" style = "cursor: pointer" >
2015-03-10 22:45:43 +00:00
< div class = "panel-progress" ng-show = "deviceStatus(deviceCfg) == 'syncing'" ng-attr-style = "width: {{completion[deviceCfg.deviceID]._total | number:0}}%" > < / div >
2014-09-10 12:43:23 +00:00
< h3 class = "panel-title" >
2015-03-10 22:45:43 +00:00
< identicon data-value = "deviceCfg.deviceID" > < / identicon >   {{deviceName(deviceCfg)}}
2015-01-08 10:04:27 +00:00
< span ng-switch = "deviceStatus(deviceCfg)" class = "pull-right text-{{deviceClass(deviceCfg)}}" >
< span ng-switch-when = "insync" > < span class = "hidden-xs" translate > Up to Date< / span > < span class = "visible-xs" > ◼ < / span > < / span >
2014-11-29 08:42:16 +00:00
< span ng-switch-when = "syncing" >
2015-03-10 22:45:43 +00:00
< span class = "hidden-xs" translate > Syncing< / span > ({{completion[deviceCfg.deviceID]._total | number:0}}%)
2014-07-26 20:30:29 +00:00
< / span >
2015-01-08 10:04:27 +00:00
< span ng-switch-when = "disconnected" > < span class = "hidden-xs" translate > Disconnected< / span > < span class = "visible-xs" > ◼ < / span > < / span >
< span ng-switch-when = "unused" > < span class = "hidden-xs" translate > Unused< / span > < span class = "visible-xs" > ◼ < / span > < / span >
2014-09-08 17:46:33 +00:00
< / span >
2014-05-24 19:56:09 +00:00
< / h3 >
< / div >
2014-09-28 11:00:38 +00:00
< div id = "device-{{$index}}" class = "panel-collapse collapse" >
2014-05-24 19:56:09 +00:00
< div class = "panel-body" >
2014-09-10 09:27:21 +00:00
< table class = "table table-condensed table-striped" >
< tbody >
2015-03-10 22:45:43 +00:00
< tr ng-if = "connections[deviceCfg.deviceID]" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-cloud-download" > < / span > < span translate > Download Rate< / span > < / th >
2015-03-10 22:45:43 +00:00
< td class = "text-right" > {{connections[deviceCfg.deviceID].inbps | binary}}B/s ({{connections[deviceCfg.deviceID].inBytesTotal | binary}}B)< / td >
2014-09-10 09:27:21 +00:00
< / tr >
2015-03-10 22:45:43 +00:00
< tr ng-if = "connections[deviceCfg.deviceID]" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-cloud-upload" > < / span > < span translate > Upload Rate< / span > < / th >
2015-03-10 22:45:43 +00:00
< td class = "text-right" > {{connections[deviceCfg.deviceID].outbps | binary}}B/s ({{connections[deviceCfg.deviceID].outBytesTotal | binary}}B)< / td >
2014-09-10 09:27:21 +00:00
< / tr >
< tr >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-link" > < / span > < span translate > Address< / span > < / th >
2014-09-28 11:00:38 +00:00
< td class = "text-right" > {{deviceAddr(deviceCfg)}}< / td >
2014-09-10 09:27:21 +00:00
< / tr >
2015-03-10 22:45:43 +00:00
< tr ng-if = "deviceCfg.compression != 'metadata'" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-compressed" > < / span > < span translate > Compression< / span > < / th >
2015-02-23 08:44:10 +00:00
< td class = "text-right" >
2015-03-10 22:45:43 +00:00
< span ng-if = "deviceCfg.compression == 'always'" translate > All Data< / span >
< span ng-if = "deviceCfg.compression == 'never'" translate > Off< / span >
2015-02-23 08:44:10 +00:00
< / td >
2014-09-10 09:27:21 +00:00
< / tr >
2015-03-10 22:45:43 +00:00
< tr ng-if = "deviceCfg.introducer" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-thumbs-up" > < / span > < span translate > Introducer< / span > < / th >
2014-11-27 19:46:36 +00:00
< td translate class = "text-right" > Yes< / td >
2014-09-23 14:04:20 +00:00
< / tr >
2015-03-10 22:45:43 +00:00
< tr ng-if = "connections[deviceCfg.deviceID]" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-tag" > < / span > < span translate > Version< / span > < / th >
2015-03-10 22:45:43 +00:00
< td class = "text-right" > {{connections[deviceCfg.deviceID].clientVersion}}< / td >
2014-09-10 09:27:21 +00:00
< / tr >
2015-03-10 22:45:43 +00:00
< tr ng-if = "!connections[deviceCfg.deviceID]" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-eye-open" > < / span > < span translate > Last seen< / span > < / th >
2015-03-10 22:45:43 +00:00
< td translate ng-if = "!deviceStats[deviceCfg.deviceID].lastSeenDays || deviceStats[deviceCfg.deviceID].lastSeenDays >= 365" class = "text-right" > Never< / td >
2015-05-21 08:40:46 +00:00
< td ng-if = "deviceStats[deviceCfg.deviceID].lastSeenDays < 365" class = "text-right" > {{deviceStats[deviceCfg.deviceID].lastSeen | date:"yyyy-MM-dd HH:mm:ss"}}< / td >
2014-09-10 09:27:21 +00:00
< / tr >
2014-11-29 08:42:16 +00:00
< tr ng-if = "deviceFolders(deviceCfg).length > 0" >
2015-05-27 19:54:00 +00:00
< th > < span class = "glyphicon glyphicon-hdd" > < / span > < span translate > Folders< / span > < / th >
2014-11-29 08:42:16 +00:00
< td class = "text-right" > {{deviceFolders(deviceCfg).join(", ")}}< / td >
< / tr >
2014-09-10 09:27:21 +00:00
< / tbody >
< / table >
< / div >
< div class = "panel-footer" >
2015-05-27 19:54:00 +00:00
< span class = "pull-right" > < a class = "btn btn-sm btn-default" href = "" ng-click = "editDevice(deviceCfg)" > < span class = "glyphicon glyphicon-pencil" > < / span > < span translate > Edit< / span > < / a > < / span >
2014-09-10 09:27:21 +00:00
< div class = "clearfix" > < / div >
2014-05-24 19:56:09 +00:00
< / div >
2014-05-20 17:36:37 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< / div >
2014-01-05 22:54:57 +00:00
< / div >
2014-09-27 12:43:11 +00:00
< div class = "form-group" >
2015-05-27 19:54:00 +00:00
< button class = "btn btn-sm btn-default pull-right" ng-click = "addDevice()" > < span class = "glyphicon glyphicon-plus" > < / span > < span translate > Add Device< / span > < / button >
2014-09-27 12:43:11 +00:00
< div class = "clearfix" > < / div >
< / div >
2014-04-09 21:00:23 +00:00
< / div >
< / div > <!-- /row -->
< / div > <!-- /container -->
<!-- Bottom bar -->
2015-01-10 17:02:27 +00:00
< nav class = "navbar navbar-default navbar-fixed-bottom" >
2014-02-12 11:10:44 +00:00
< div class = "container" >
2014-05-20 17:36:37 +00:00
< ul class = "nav navbar-nav" >
2015-07-05 09:06:29 +00:00
< li > < a class = "navbar-link" href = "http://syncthing.net/" target = "_blank" > < span class = "glyphicon glyphicon-home" > < / span > < span translate > Home page< / span > < / a > < / li >
2015-05-27 19:54:00 +00:00
< li > < a class = "navbar-link" href = "http://docs.syncthing.net/" target = "_blank" > < span class = "glyphicon glyphicon-book" > < / span > < span translate > Documentation< / span > < / a > < / li >
< li > < a class = "navbar-link" href = "https://forum.syncthing.net" target = "_blank" > < span class = "glyphicon glyphicon-question-sign" > < / span > < span translate > Support< / span > < / a > < / li >
< li > < a class = "navbar-link" href = "https://github.com/syncthing/syncthing/releases" target = "_blank" > < span class = "glyphicon glyphicon-info-sign" > < / span > < span translate > Changelog< / span > < / a > < / li >
< li > < a class = "navbar-link" href = "https://github.com/syncthing/syncthing/issues" target = "_blank" > < span class = "glyphicon glyphicon-warning-sign" > < / span > < span translate > Bugs< / span > < / a > < / li >
< li > < a class = "navbar-link" href = "https://github.com/syncthing/syncthing" target = "_blank" > < span class = "glyphicon glyphicon-wrench" > < / span > < span translate > Source Code< / span > < / a > < / li >
< li > < a class = "navbar-link" href = "https://twitter.com/syncthing" target = "_blank" > < span class = "glyphicon glyphicon-send" > < / span > Twitter< / a > < / li >
2014-04-09 21:00:23 +00:00
< / ul >
2014-02-12 11:10:44 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< / nav >
<!-- Network error modal -->
2014-01-05 22:54:57 +00:00
2014-07-20 11:49:26 +00:00
< modal id = "networkError" status = "danger" icon = "exclamation-sign" title = "{{'Connection Error' | translate}}" >
< p translate >
Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…
2014-07-14 12:14:26 +00:00
< / p >
< / modal >
2014-04-09 21:00:23 +00:00
2015-01-05 14:42:27 +00:00
<!-- HTTP error modal -->
< modal id = "httpError" status = "danger" icon = "exclamation-sign" title = "{{'Connection Error' | translate}}" >
< p translate >
Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.
< / p >
< / modal >
2014-04-16 13:16:44 +00:00
<!-- Restarting modal -->
2014-08-06 12:41:46 +00:00
< modal id = "restarting" icon = "refresh" title = "{{'Restarting' | translate}}" status = "info" >
< p > < span translate > Syncthing is restarting.< / span > < span translate > Please wait< / span > ...< / p >
< / modal >
2014-08-10 22:28:04 +00:00
<!-- Upgrading modal -->
2014-08-06 12:41:46 +00:00
< modal id = "upgrading" icon = "refresh" title = "{{'Upgrading' | translate}}" status = "info" >
< p > < span translate > Syncthing is upgrading.< / span > < span translate > Please wait< / span > ...< / p >
2014-07-14 12:14:26 +00:00
< / modal >
2014-04-16 13:16:44 +00:00
2014-05-21 17:35:56 +00:00
<!-- Shutdown modal -->
2015-01-11 13:48:40 +00:00
< modal id = "shutdown" icon = "off" status = "success" title = "{{'Shutdown Complete' | translate}}" >
2014-07-20 11:49:26 +00:00
< p translate > Syncthing has been shut down.< / p >
2014-07-14 12:14:26 +00:00
< / modal >
2014-05-21 17:35:56 +00:00
2014-05-21 18:06:14 +00:00
<!-- ID modal -->
2014-09-28 11:00:38 +00:00
< modal id = "idqr" large = "yes" status = "info" close = "yes" icon = "qrcode" title = "{{'Device Identification' | translate}} — {{deviceName(thisDevice())}}" >
2015-07-01 14:44:23 +00:00
< div select-on-click class = "well well-sm text-monospace text-center" > {{myID}}< / div >
2015-04-22 00:37:12 +00:00
< img ng-if = "myID" class = "center-block img-thumbnail" ng-src = "qr/?text={{myID}}" / >
2014-07-14 12:14:26 +00:00
< / modal >
2014-05-21 18:06:14 +00:00
2015-04-22 12:41:08 +00:00
<!-- Major upgrade modal -->
< div id = "majorUpgrade" class = "modal fade" tabindex = "-1" data-backdrop = "true" data-keyboard = "true" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header alert alert-danger" >
< h4 class = "modal-title" >
< span ng-if = "icon" class = "glyphicon glyphicon-chevron-up" > < / span >
< span translate > Major Upgrade< / span >
< / h4 >
< / div >
< div class = "modal-body" >
< p >
< span translate > This is a major version upgrade.< / span >
< span translate > A new major version may not be compatible with previous versions.< / span >
< span translate > Please consult the release notes before performing a major upgrade.< / span >
< / p >
< p >
2015-05-04 02:39:04 +00:00
< a href = "https://github.com/syncthing/syncthing/releases/tag/{{upgradeInfo.latest}}" target = "_blank" translate > Release Notes< / a >
2015-04-22 12:41:08 +00:00
< / p >
< / div >
< div class = "modal-footer" >
2015-05-27 19:54:00 +00:00
< button type = "button" class = "btn btn-primary btn-sm" ng-click = "upgrade()" > < span class = "glyphicon glyphicon-ok" > < / span > < span translate > Upgrade< / span > < / button >
< button type = "button" class = "btn btn-default btn-sm" data-dismiss = "modal" > < span class = "glyphicon glyphicon-remove" > < / span > < span translate > Close< / span > < / button >
2015-04-22 12:41:08 +00:00
< / div >
< / div >
< / div >
< / div >
2014-09-28 11:00:38 +00:00
<!-- Device editor modal -->
2014-04-09 21:00:23 +00:00
2014-09-28 11:00:38 +00:00
< div id = "editDevice" class = "modal fade" tabindex = "-1" >
2014-04-09 21:00:23 +00:00
< div class = "modal-dialog modal-lg" >
< div class = "modal-content" >
< div class = "modal-header" >
2014-09-28 11:00:38 +00:00
< h4 translate ng-show = "!editingExisting" class = "modal-title" > Add Device< / h4 >
< h4 translate ng-show = "editingExisting" class = "modal-title" > Edit Device< / h4 >
2014-04-09 21:00:23 +00:00
< / div >
< div class = "modal-body" >
2014-09-28 11:00:38 +00:00
< form role = "form" name = "deviceEditor" >
< div class = "form-group" ng-class = "{'has-error': deviceEditor.deviceID.$invalid && deviceEditor.deviceID.$dirty}" >
< label translate for = "deviceID" > Device ID< / label >
2015-03-10 22:45:43 +00:00
< input ng-if = "!editingExisting" name = "deviceID" id = "deviceID" class = "form-control text-monospace" type = "text" ng-model = "currentDevice.deviceID" required valid-deviceid list = "discovery-list" / >
2014-10-15 20:02:57 +00:00
< datalist id = "discovery-list" ng-if = "!editingExisting" >
< option ng-repeat = "(id,address) in discovery" value = "{{ id }}" / >
< / datalist >
2015-07-13 16:01:13 +00:00
< div select-on-click ng-if = "editingExisting" class = "well well-sm text-monospace" > {{currentDevice.deviceID}}< / div >
2014-05-14 10:55:00 +00:00
< p class = "help-block" >
2014-09-28 11:00:38 +00:00
< span translate ng-if = "deviceEditor.deviceID.$valid || deviceEditor.deviceID.$pristine" > The device ID to enter here can be found in the "Edit > Show ID" dialog on the other device. Spaces and dashes are optional (ignored).< / span >
< span translate ng-show = "!editingExisting && (deviceEditor.deviceID.$valid || deviceEditor.deviceID.$pristine)" > When adding a new device, keep in mind that this device must be added on the other side too.< / span >
< span translate ng-if = "deviceEditor.deviceID.$error.required && deviceEditor.deviceID.$dirty" > The device ID cannot be blank.< / span >
< span translate ng-if = "deviceEditor.deviceID.$error.validDeviceid && deviceEditor.deviceID.$dirty" > The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.< / span >
2014-05-14 10:55:00 +00:00
< / p >
2014-04-09 21:00:23 +00:00
< / div >
< div class = "form-group" >
2014-09-28 11:00:38 +00:00
< label translate for = "name" > Device Name< / label >
2015-03-10 22:45:43 +00:00
< input id = "name" class = "form-control" type = "text" ng-model = "currentDevice.name" > < / input >
< p translate ng-if = "currentDevice.deviceID == myID" class = "help-block" > Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.< / p >
< p translate ng-if = "currentDevice.deviceID != myID" class = "help-block" > Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.< / p >
2014-01-09 09:31:27 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< div class = "form-group" >
2014-07-20 11:49:26 +00:00
< label translate for = "addresses" > Addresses< / label >
2015-07-03 12:07:38 +00:00
< input ng-disabled = "currentDevice.deviceID == myID" id = "addresses" class = "form-control" type = "text" ng-model = "currentDevice._addressesStr" > < / input >
2015-07-16 08:11:10 +00:00
< p translate class = "help-block" > Enter comma separated addresses ("ip:port", "host:port") or "dynamic" to perform automatic discovery of the address.< / p >
2014-01-09 09:31:27 +00:00
< / div >
2014-07-31 09:01:39 +00:00
< div ng-if = "!editingSelf" class = "form-group" >
2015-02-23 08:44:10 +00:00
< label translate > Compression< / label >
2015-03-10 22:45:43 +00:00
< select class = "form-control" ng-model = "currentDevice.compression" >
2015-02-23 08:44:10 +00:00
< option value = "always" translate > All Data< / option >
< option value = "metadata" translate > Metadata Only< / option >
< option value = "never" translate > Off< / option >
< / select >
2014-09-23 14:04:20 +00:00
< / div >
< div ng-if = "!editingSelf" class = "form-group" >
< div class = "checkbox" >
< label >
2015-03-10 22:45:43 +00:00
< input type = "checkbox" ng-model = "currentDevice.introducer" > < span translate > Introducer< / span >
2014-09-23 14:04:20 +00:00
< / label >
2014-09-28 11:00:38 +00:00
< p translate class = "help-block" > Any devices configured on an introducer device will be added to this device as well.< / p >
2014-07-28 10:44:46 +00:00
< / div >
< / div >
2014-12-05 00:22:16 +00:00
< div class = "row" ng-if = "!editingSelf" >
< div class = "col-md-12" >
< div class = "form-group" >
< label translate for = "folders" > Share Folders With Device< / label >
< p translate class = "help-block" > Select the folders to share with this device.< / p >
Use bootstrap grid instead of column-count:3 for aligning checkboxes (fixes #2029)
Upgrading to bootstrap 3.3.5 meant that checkboxes inside a div with
column-count:3 set would be unclickable in Chrome: in fact, the entire
div appears to sit on top of its contents, making interaction impossible.
This affected both the 'show folder with these devices' and 'these devices
can access this folder' sections of the UI.
I'm not sure what the the underlying cause is, but moving to Bootstrap's
grid system appears work around the issue. Devices/folders have to be
explicitly split out into rows, otherwise the final element appears offset.
To do this grouping by row, a new filter (groupFilter) has been added, which
turns an input of e.g. [1, 2, 3, 4, 5] with a groupSize of 3 into
[[1, 2, 3], [4, 5]]. However altering the collection in this way throws
Angular into an infinite watch loop, terminating in infdig. m59peacemaker's
pmkr.filterStabilize (MIT) was added to work around this issue.
This also has the nice side-effect of wrapping the list of devices/folders
when the screen width decreases.
See also:
- #2027 (bootstrap update which triggered this issue)
- #1121 (last time it happened)
2015-07-05 16:08:16 +00:00
< div class = "container-fluid" >
< div class = "row" ng-repeat = "folderGroup in folderList() | group:3" >
< div class = "checkbox col-md-4" ng-repeat = "folder in folderGroup" >
< label >
< input type = "checkbox" ng-model = "currentDevice.selectedFolders[folder.id]" > {{folder.id}}
< / label >
< / div >
2014-12-05 00:22:16 +00:00
< / div >
< / div >
< / div >
< / div >
< / div >
2014-04-09 21:00:23 +00:00
< / form >
< / div >
< div class = "modal-footer" >
2015-05-27 19:54:00 +00:00
< button type = "button" class = "btn btn-primary btn-sm" ng-click = "saveDevice()" ng-disabled = "deviceEditor.$invalid" > < span class = "glyphicon glyphicon-ok" > < / span > < span translate > Save< / span > < / button >
< button type = "button" class = "btn btn-default btn-sm" data-dismiss = "modal" > < span class = "glyphicon glyphicon-remove" > < / span > < span translate > Close< / span > < / button >
< button ng-if = "editingExisting && !editingSelf" type = "button" class = "btn btn-danger pull-left btn-sm" ng-click = "deleteDevice()" > < span class = "glyphicon glyphicon-minus" > < / span > < span translate > Delete< / span > < / button >
2014-01-09 09:31:27 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< / div >
2014-01-09 09:31:27 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< / div >
2014-01-09 09:31:27 +00:00
2014-09-28 11:00:38 +00:00
<!-- Folder editor modal -->
2014-04-09 21:00:23 +00:00
2014-09-28 11:00:38 +00:00
< div id = "editFolder" class = "modal fade" tabindex = "-1" >
2014-02-01 19:23:19 +00:00
< div class = "modal-dialog modal-lg" >
2014-04-09 21:00:23 +00:00
< div class = "modal-content" >
< div class = "modal-header" >
2014-09-28 11:00:38 +00:00
< h4 ng-show = "!editingExisting" class = "modal-title" > < span translate > Add Folder< / span > < / h4 >
< h4 ng-show = "editingExisting" class = "modal-title" > < span translate > Edit Folder< / span > < / h4 >
2014-04-09 21:00:23 +00:00
< / div >
< div class = "modal-body" >
2014-09-28 11:00:38 +00:00
< form role = "form" name = "folderEditor" >
2014-05-25 18:49:08 +00:00
< div class = "row" >
< div class = "col-md-12" >
2014-09-28 11:00:38 +00:00
< div class = "form-group" ng-class = "{'has-error': folderEditor.folderID.$invalid && folderEditor.folderID.$dirty}" >
< label for = "folderID" > < span translate > Folder ID< / span > < / label >
2015-03-10 22:45:43 +00:00
< input name = "folderID" ng-readonly = "editingExisting" id = "folderID" class = "form-control" type = "text" ng-model = "currentFolder.id" required unique-folder ng-pattern = "/^[a-zA-Z0-9-_.]{1,64}$/" > < / input >
2014-05-25 18:49:08 +00:00
< p class = "help-block" >
2014-09-28 11:00:38 +00:00
< span translate ng-if = "folderEditor.folderID.$valid || folderEditor.folderID.$pristine" > Short identifier for the folder. Must be the same on all cluster devices.< / span >
< span translate ng-if = "folderEditor.folderID.$error.uniqueFolder" > The folder ID must be unique.< / span >
< span translate ng-if = "folderEditor.folderID.$error.required && folderEditor.folderID.$dirty" > The folder ID cannot be blank.< / span >
2015-07-20 12:22:36 +00:00
< span translate ng-if = "folderEditor.folderID.$error.pattern && folderEditor.folderID.$dirty" > The folder ID must be a short identifier (64 characters or less) consisting of letters, numbers and the dot (.), dash (-) and underscore (_) characters only.< / span >
2014-05-25 18:49:08 +00:00
< / p >
< / div >
2014-09-28 11:00:38 +00:00
< div class = "form-group" ng-class = "{'has-error': folderEditor.folderPath.$invalid && folderEditor.folderPath.$dirty}" >
< label translate for = "folderPath" > Folder Path< / label >
2015-03-10 22:45:43 +00:00
< input name = "folderPath" ng-readonly = "editingExisting" id = "folderPath" class = "form-control" type = "text" ng-model = "currentFolder.path" list = "directory-list" required / >
2014-11-16 19:30:49 +00:00
< datalist id = "directory-list" >
< option ng-repeat = "directory in directoryList" value = "{{ directory }}" / >
< / datalist >
2014-05-25 18:49:08 +00:00
< p class = "help-block" >
2014-09-28 11:00:38 +00:00
< span translate ng-if = "folderEditor.folderPath.$valid || folderEditor.folderPath.$pristine" > Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for< / span > < code > {{system.tilde}}< / code > .
< span translate ng-if = "folderEditor.folderPath.$error.required && folderEditor.folderPath.$dirty" > The folder path cannot be blank.< / span >
2014-05-25 18:49:08 +00:00
< / p >
< / div >
2014-09-28 11:00:38 +00:00
< div class = "form-group" ng-class = "{'has-error': folderEditor.rescanIntervalS.$invalid && folderEditor.rescanIntervalS.$dirty}" >
2014-08-19 23:44:05 +00:00
< label for = "rescanIntervalS" > < span translate > Rescan Interval< / span > (s)< / label >
2015-03-10 22:45:43 +00:00
< input name = "rescanIntervalS" id = "rescanIntervalS" class = "form-control" type = "number" ng-model = "currentFolder.rescanIntervalS" required min = "0" > < / input >
2014-08-18 21:05:47 +00:00
< p class = "help-block" >
2014-10-30 23:25:38 +00:00
< span translate ng-if = "!folderEditor.rescanIntervalS.$valid && folderEditor.rescanIntervalS.$dirty" > The rescan interval must be a non-negative number of seconds.< / span >
2014-08-18 21:05:47 +00:00
< / p >
< / div >
2014-04-09 21:00:23 +00:00
< / div >
< / div >
2014-05-25 18:49:08 +00:00
< div class = "row" >
2015-04-25 05:13:53 +00:00
<!-- Left column -->
2014-05-25 18:49:08 +00:00
< div class = "col-md-6" >
< div class = "form-group" >
< div class = "checkbox" >
< label >
2015-03-10 22:45:43 +00:00
< input type = "checkbox" ng-model = "currentFolder.readOnly" > < span translate > Folder Master< / span >
2014-05-25 18:49:08 +00:00
< / label >
2015-06-15 20:34:39 +00:00
< a href = "http://docs.syncthing.net/users/foldermaster.html" target = "_blank" > < span class = "glyphicon glyphicon-book" > < / span > < span translate > Help< / span > < / a >
2014-05-25 18:49:08 +00:00
< / div >
2014-09-28 11:00:38 +00:00
< p translate class = "help-block" > Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.< / p >
2014-05-25 18:49:08 +00:00
< / div >
< div class = "form-group" >
< div class = "checkbox" >
< label >
2015-03-10 22:45:43 +00:00
< input type = "checkbox" ng-model = "currentFolder.ignorePerms" > < span translate > Ignore Permissions< / span >
2014-05-25 18:49:08 +00:00
< / label >
< / div >
2015-01-14 02:51:52 +00:00
< p translate class = "help-block" > File permission bits are ignored when looking for changes. Use on FAT file systems.< / p >
2014-05-25 18:49:08 +00:00
< / div >
2014-05-23 12:31:16 +00:00
< / div >
2015-04-25 05:13:53 +00:00
<!-- Right column -->
2014-05-25 18:49:08 +00:00
< div class = "col-md-6" >
2015-04-25 05:13:53 +00:00
< div class = "form-group" >
< label translate > File Pull Order< / label >
< select class = "form-control" ng-model = "currentFolder.order" >
< option value = "random" translate > Random< / option >
< option value = "alphabetic" translate > Alphabetic< / option >
< option value = "smallestFirst" translate > Smallest First< / option >
< option value = "largestFirst" translate > Largest First< / option >
< option value = "oldestFirst" translate > Oldest First< / option >
< option value = "newestFirst" translate > Newest First< / option >
< / select >
< / div >
2014-05-25 18:49:08 +00:00
< div class = "form-group" >
2015-06-12 11:04:00 +00:00
< label translate > File Versioning< / label >   < a href = "http://docs.syncthing.net/users/versioning.html" target = "_blank" > < span class = "glyphicon glyphicon-book" > < / span > < span translate > Help< / span > < / a >
< select class = "form-control" ng-model = "currentFolder.fileVersioningSelector" >
< option value = "none" translate > No File Versioning< / option >
< option value = "trashcan" translate > Trash Can File Versioning< / option >
< option value = "simple" translate > Simple File Versioning< / option >
< option value = "staggered" translate > Staggered File Versioning< / option >
< option value = "external" translate > External File Versioning< / option >
< / select >
< / div >
< div class = "form-group" ng-if = "currentFolder.fileVersioningSelector=='trashcan'" ng-class = "{'has-error': folderEditor.trashcanClean.$invalid && folderEditor.trashcanClean.$dirty}" >
< p translate class = "help-block" > Files are moved to .stversions folder when replaced or deleted by Syncthing.< / p >
< label translate for = "trashcanClean" > Clean out after< / label >
< div class = "input-group" >
< input name = "trashcanClean" id = "trashcanClean" class = "form-control text-right" type = "number" ng-model = "currentFolder.trashcanClean" required min = "0" > < / input >
< div class = "input-group-addon" > days< / div >
2015-03-19 10:31:21 +00:00
< / div >
2015-06-12 11:04:00 +00:00
< p class = "help-block" >
< span translate ng-if = "folderEditor.trashcanClean.$valid || folderEditor.trashcanClean.$pristine" > The number of days to keep files in the trash can. Zero means forever.< / span >
< span translate ng-if = "folderEditor.trashcanClean.$error.required && folderEditor.trashcanClean.$dirty" > The number of days must be a number and cannot be blank.< / span >
< span translate ng-if = "folderEditor.trashcanClean.$error.min && folderEditor.trashcanClean.$dirty" > A negative number of days doesn't make sense.< / span >
< / p >
2014-05-25 18:49:08 +00:00
< / div >
2015-03-10 22:45:43 +00:00
< div class = "form-group" ng-if = "currentFolder.fileVersioningSelector=='simple'" ng-class = "{'has-error': folderEditor.simpleKeep.$invalid && folderEditor.simpleKeep.$dirty}" >
2015-01-14 02:51:52 +00:00
< p translate class = "help-block" > Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.< / p >
2014-07-20 11:49:26 +00:00
< label translate for = "simpleKeep" > Keep Versions< / label >
2014-09-28 11:00:38 +00:00
< input name = "simpleKeep" id = "simpleKeep" class = "form-control" type = "number" ng-model = "currentFolder.simpleKeep" required min = "1" > < / input >
2014-05-25 18:49:08 +00:00
< p class = "help-block" >
2014-09-28 11:00:38 +00:00
< span translate ng-if = "folderEditor.simpleKeep.$valid || folderEditor.simpleKeep.$pristine" > The number of old versions to keep, per file.< / span >
< span translate ng-if = "folderEditor.simpleKeep.$error.required && folderEditor.simpleKeep.$dirty" > The number of versions must be a number and cannot be blank.< / span >
< span translate ng-if = "folderEditor.simpleKeep.$error.min && folderEditor.simpleKeep.$dirty" > You must keep at least one version.< / span >
2014-05-25 18:49:08 +00:00
< / p >
< / div >
2015-03-10 22:45:43 +00:00
< div class = "form-group" ng-if = "currentFolder.fileVersioningSelector=='staggered'" ng-class = "{'has-error': folderEditor.staggeredMaxAge.$invalid && folderEditor.staggeredMaxAge.$dirty}" >
2015-01-14 02:51:52 +00:00
< p class = "help-block" > < span translate > Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.< / span > < span translate > Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.< / span > < / p >
2014-08-21 22:41:17 +00:00
< p translate class = "help-block" > The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.< / p >
< label translate for = "staggeredMaxAge" > Maximum Age< / label >
2014-09-28 11:00:38 +00:00
< input name = "staggeredMaxAge" id = "staggeredMaxAge" class = "form-control" type = "number" ng-model = "currentFolder.staggeredMaxAge" required > < / input >
2014-08-21 22:41:17 +00:00
< p class = "help-block" >
2014-09-28 11:00:38 +00:00
< span translate ng-if = "folderEditor.staggeredMaxAge.$valid || folderEditor.staggeredMaxAge.$pristine" > The maximum time to keep a version (in days, set to 0 to keep versions forever).< / span >
< span translate ng-if = "folderEditor.staggeredMaxAge.$error.required && folderEditor.staggeredMaxAge.$dirty" > The maximum age must be a number and cannot be blank.< / span >
2014-08-21 22:41:17 +00:00
< / p >
< / div >
2015-03-10 22:45:43 +00:00
< div class = "form-group" ng-if = "currentFolder.fileVersioningSelector == 'staggered'" >
2014-08-21 22:41:17 +00:00
< label translate for = "staggeredVersionsPath" > Versions Path< / label >
2014-09-28 11:00:38 +00:00
< input name = "staggeredVersionsPath" id = "staggeredVersionsPath" class = "form-control" type = "text" ng-model = "currentFolder.staggeredVersionsPath" > < / input >
< p translate class = "help-block" > Path where versions should be stored (leave empty for the default .stversions folder in the folder).< / p >
2014-08-21 22:41:17 +00:00
< / div >
2015-03-19 10:31:21 +00:00
< div class = "form-group" ng-if = "currentFolder.fileVersioningSelector=='external'" ng-class = "{'has-error': folderEditor.externalCommand.$invalid && folderEditor.externalCommand.$dirty}" >
2015-03-31 17:27:25 +00:00
< p translate class = "help-block" > An external command handles the versioning. It has to remove the file from the synced folder.< / p >
2015-03-19 10:31:21 +00:00
< label translate for = "externalCommand" > Command< / label >
< input name = "externalCommand" id = "externalCommand" class = "form-control" type = "text" ng-model = "currentFolder.externalCommand" required > < / input >
< p class = "help-block" >
< span translate ng-if = "folderEditor.externalCommand.$valid || folderEditor.externalCommand.$pristine" > The first command line parameter is the folder path and the second parameter is the relative path in the folder.< / span >
< span translate ng-if = "folderEditor.externalCommand.$error.required && folderEditor.externalCommand.$dirty" > The path cannot be blank.< / span >
< / p >
< / div >
2014-04-09 21:00:23 +00:00
< / div >
2014-02-01 19:23:19 +00:00
< / div >
2014-11-27 20:34:14 +00:00
< div class = "row" >
< div class = "col-md-12" >
< div class = "form-group" >
< label translate for = "devices" > Share With Devices< / label >
< p translate class = "help-block" > Select the devices to share this folder with.< / p >
Use bootstrap grid instead of column-count:3 for aligning checkboxes (fixes #2029)
Upgrading to bootstrap 3.3.5 meant that checkboxes inside a div with
column-count:3 set would be unclickable in Chrome: in fact, the entire
div appears to sit on top of its contents, making interaction impossible.
This affected both the 'show folder with these devices' and 'these devices
can access this folder' sections of the UI.
I'm not sure what the the underlying cause is, but moving to Bootstrap's
grid system appears work around the issue. Devices/folders have to be
explicitly split out into rows, otherwise the final element appears offset.
To do this grouping by row, a new filter (groupFilter) has been added, which
turns an input of e.g. [1, 2, 3, 4, 5] with a groupSize of 3 into
[[1, 2, 3], [4, 5]]. However altering the collection in this way throws
Angular into an infinite watch loop, terminating in infdig. m59peacemaker's
pmkr.filterStabilize (MIT) was added to work around this issue.
This also has the nice side-effect of wrapping the list of devices/folders
when the screen width decreases.
See also:
- #2027 (bootstrap update which triggered this issue)
- #1121 (last time it happened)
2015-07-05 16:08:16 +00:00
< div class = "container-fluid" >
< div class = "row" ng-repeat = "deviceGroup in otherDevices() | group:3" >
< div class = "checkbox col-md-4" ng-repeat = "device in deviceGroup" >
< label >
< input type = "checkbox" ng-model = "currentFolder.selectedDevices[device.deviceID]" > {{deviceName(device)}}
< / label >
< / div >
2014-11-27 20:34:14 +00:00
< / div >
< / div >
< / div >
< / div >
< / div >
2014-04-09 21:00:23 +00:00
< / form >
2014-09-28 11:00:38 +00:00
< div translate ng-show = "!editingExisting" > When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.< / div >
2014-04-09 21:00:23 +00:00
< / div >
< div class = "modal-footer" >
2015-05-27 19:54:00 +00:00
< button type = "button" class = "btn btn-primary btn-sm" ng-click = "saveFolder()" ng-disabled = "folderEditor.$invalid" > < span class = "glyphicon glyphicon-ok" > < / span > < span translate > Save< / span > < / button >
< button type = "button" class = "btn btn-default btn-sm" data-dismiss = "modal" > < span class = "glyphicon glyphicon-remove" > < / span > < span translate > Close< / span > < / button >
< button ng-if = "editingExisting" type = "button" class = "btn btn-danger pull-left btn-sm" ng-click = "deleteFolder()" > < span class = "glyphicon glyphicon-minus" > < / span > < span translate > Delete< / span > < / button >
< button id = "editIgnoresButton" ng-if = "editingExisting" type = "button" class = "btn btn-default pull-left btn-sm" ng-click = "editIgnores()" > < span class = "glyphicon glyphicon-eye-close" > < / span > < span translate > Ignore Patterns< / span > < / button >
2014-09-19 20:02:53 +00:00
< / div >
< / div >
< / div >
< / div >
<!-- Ignores editor modal -->
< div id = "editIgnores" class = "modal fade" tabindex = "-1" >
< div class = "modal-dialog modal-lg" >
< div class = "modal-content" >
< div class = "modal-header" >
2014-09-22 12:04:20 +00:00
< h4 class = "modal-title" translate > Ignore Patterns< / h4 >
2014-09-19 20:02:53 +00:00
< / div >
< div class = "modal-body" >
2014-09-22 12:04:20 +00:00
< p translate > Enter ignore patterns, one per line.< / p >
2014-09-19 20:02:53 +00:00
< textarea class = "form-control" rows = "15" > < / textarea >
2014-09-22 12:04:20 +00:00
< hr / >
2015-06-03 17:08:58 +00:00
< p class = "small" > < span translate > Quick guide to supported patterns< / span > (< a href = "http://docs.syncthing.net/users/ignoring.html" target = "_blank" translate > full documentation< / a > ):< / p >
2014-09-22 12:04:20 +00:00
< dl class = "dl-horizontal dl-narrow small" >
< dt > < code > !< / code > < / dt > < dd > < span translate > Inversion of the given condition (i.e. do not exclude)< / span > < / dd >
< dt > < code > *< / code > < / dt > < dd > < span translate > Single level wildcard (matches within a directory only)< / span > < / dd >
< dt > < code > **< / code > < / dt > < dd > < span translate > Multi level wildcard (matches multiple directory levels)< / span > < / dd >
< dt > < code > //< / code > < / dt > < dd > < span translate > Comment, when used at the start of a line< / span > < / dd >
< / dl >
2014-09-19 20:02:53 +00:00
< / div >
< div class = "modal-footer" >
2015-03-10 22:45:43 +00:00
< div class = "pull-left" > < span translate > Editing< / span > < code > {{currentFolder.path}}{{system.pathSeparator}}.stignore< / code > < / div >
2015-05-27 19:54:00 +00:00
< button type = "button" class = "btn btn-primary btn-sm" data-dismiss = "modal" ng-click = "saveIgnores()" > < span class = "glyphicon glyphicon-ok" > < / span > < span translate > Save< / span > < / button >
< button type = "button" class = "btn btn-default btn-sm" data-dismiss = "modal" > < span class = "glyphicon glyphicon-remove" > < / span > < span translate > Close< / span > < / button >
2014-04-09 21:00:23 +00:00
< / div >
< / div >
< / div >
< / div >
<!-- Settings modal -->
2014-08-10 22:28:04 +00:00
< div id = "settings" class = "modal fade" tabindex = "-1" >
2014-04-09 21:00:23 +00:00
< div class = "modal-dialog modal-lg" >
< div class = "modal-content" >
< div class = "modal-header" >
2014-07-20 11:49:26 +00:00
< h4 translate class = "modal-title" > Settings< / h4 >
2014-04-09 21:00:23 +00:00
< / div >
< div class = "modal-body" >
< form role = "form" >
< div class = "row" >
2014-07-20 11:49:26 +00:00
2014-04-09 21:00:23 +00:00
< div class = "col-md-6" >
2014-09-10 09:27:21 +00:00
< div class = "form-group" >
2014-09-28 11:00:38 +00:00
< label translate for = "DeviceName" > Device Name< / label >
2015-03-10 22:45:43 +00:00
< input id = "DeviceName" class = "form-control" type = "text" ng-model = "tmpOptions.deviceName" >
2014-09-10 09:27:21 +00:00
< / div >
2014-07-20 11:49:26 +00:00
< div class = "form-group" >
2014-11-18 22:57:21 +00:00
< label translate for = "ListenAddressStr" > Sync Protocol Listen Addresses< / label >
2015-07-03 12:07:38 +00:00
< input id = "ListenAddressStr" class = "form-control" type = "text" ng-model = "tmpOptions._listenAddressStr" >
2014-07-20 11:49:26 +00:00
< / div >
2014-09-08 15:25:55 +00:00
< div class = "form-group" >
< label translate for = "MaxRecvKbps" > Incoming Rate Limit (KiB/s)< / label >
2015-03-10 22:45:43 +00:00
< input id = "MaxRecvKbps" class = "form-control" type = "number" ng-model = "tmpOptions.maxRecvKbps" >
2014-09-08 15:25:55 +00:00
< / div >
2014-07-20 11:49:26 +00:00
< div class = "form-group" >
< label translate for = "MaxSendKbps" > Outgoing Rate Limit (KiB/s)< / label >
2015-03-10 22:45:43 +00:00
< input id = "MaxSendKbps" class = "form-control" type = "number" ng-model = "tmpOptions.maxSendKbps" >
2014-07-20 11:49:26 +00:00
< / div >
2014-09-27 15:00:20 +00:00
< div class = "col-md-6" >
< div class = "form-group" >
< div class = "checkbox" >
< label >
2015-03-10 22:45:43 +00:00
< input id = "UPnPEnabled" type = "checkbox" ng-model = "tmpOptions.upnpEnabled" > < span translate > Enable UPnP< / span >
2014-09-27 15:00:20 +00:00
< / label >
< / div >
2014-07-31 07:02:56 +00:00
< / div >
2014-09-27 15:00:20 +00:00
< div class = "form-group" >
< div class = "checkbox" >
< label >
2015-03-10 22:45:43 +00:00
< input id = "GlobalAnnEnabled" type = "checkbox" ng-model = "tmpOptions.globalAnnounceEnabled" > < span translate > Global Discovery< / span >
2014-09-27 15:00:20 +00:00
< / label >
< / div >
2014-04-09 21:00:23 +00:00
< / div >
2014-07-20 11:49:26 +00:00
< / div >
2014-09-27 15:00:20 +00:00
< div class = "col-md-6" >
< div class = "form-group" >
< div class = "checkbox" >
2014-09-30 22:01:32 +00:00
< label ng-if = "upgradeInfo" >
2015-03-10 22:45:43 +00:00
< input id = "AutoUpgradeEnabled" type = "checkbox" ng-model = "tmpOptions.autoUpgradeEnabled" > < span translate > Automatic upgrades< / span >
2014-09-27 15:00:20 +00:00
< / label >
< / div >
< / div >
< div class = "form-group" >
< div class = "checkbox" >
< label >
2015-03-10 22:45:43 +00:00
< input id = "LocalAnnEnabled" type = "checkbox" ng-model = "tmpOptions.localAnnounceEnabled" > < span translate > Local Discovery< / span >
2014-09-27 15:00:20 +00:00
< / label >
< / div >
2014-07-20 11:49:26 +00:00
< / div >
< / div >
< div class = "form-group" >
2014-11-18 22:57:21 +00:00
< label translate for = "GlobalAnnServersStr" > Global Discovery Server< / label >
2015-07-03 12:07:38 +00:00
< input ng-disabled = "!tmpOptions.globalAnnounceEnabled" id = "GlobalAnnServersStr" class = "form-control" type = "text" ng-model = "tmpOptions._globalAnnounceServersStr" >
2014-04-09 21:00:23 +00:00
< / div >
< / div >
2014-07-20 11:49:26 +00:00
2014-04-09 21:00:23 +00:00
< div class = "col-md-6" >
2014-07-20 11:49:26 +00:00
< div class = "form-group" >
< label translate for = "Address" > GUI Listen Addresses< / label >
2015-03-10 22:45:43 +00:00
< input id = "Address" class = "form-control" type = "text" ng-model = "tmpGUI.address" >
2014-07-20 11:49:26 +00:00
< / div >
< div class = "form-group" >
< label translate for = "User" > GUI Authentication User< / label >
2015-03-10 22:45:43 +00:00
< input id = "User" class = "form-control" type = "text" ng-model = "tmpGUI.user" >
2014-07-20 11:49:26 +00:00
< / div >
< div class = "form-group" >
< label translate for = "Password" > GUI Authentication Password< / label >
2015-03-10 22:45:43 +00:00
< input id = "Password" class = "form-control" type = "password" ng-model = "tmpGUI.password" >
2014-07-20 11:49:26 +00:00
< / div >
< div class = "form-group" >
< div class = "checkbox" >
< label >
2015-03-10 22:45:43 +00:00
< input id = "UseTLS" type = "checkbox" ng-model = "tmpGUI.useTLS" > < span translate > Use HTTPS for GUI< / span >
2014-07-20 11:49:26 +00:00
< / label >
2014-04-09 21:00:23 +00:00
< / div >
2014-07-20 11:49:26 +00:00
< / div >
< div class = "form-group" >
< div class = "checkbox" >
2014-04-09 21:00:23 +00:00
< label >
2015-03-10 22:45:43 +00:00
< input id = "StartBrowser" type = "checkbox" ng-model = "tmpOptions.startBrowser" > < span translate > Start Browser< / span >
2014-04-09 21:00:23 +00:00
< / label >
< / div >
2014-07-20 11:49:26 +00:00
< / div >
< div class = "form-group" >
< div class = "checkbox" >
< label >
2015-03-10 22:45:43 +00:00
< input id = "UREnabled" type = "checkbox" ng-model = "tmpOptions.urEnabled" > < span translate > Anonymous Usage Reporting< / span > (< a translate ng-click = "showURPreview()" href = "#" > Preview< / a > )
2014-07-20 11:49:26 +00:00
< / label >
2014-06-04 20:00:55 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< / div >
2014-07-31 07:02:56 +00:00
< hr / >
< div class = "form-group" >
< label > < span translate > API Key< / span > < / label >
2015-07-13 16:01:13 +00:00
< div select-on-click class = "well well-sm text-monospace" > {{tmpGUI.apiKey || "-"}}< / div >
2014-07-31 07:02:56 +00:00
< button translate type = "button" class = "btn btn-sm btn-default" ng-click = "setAPIKey(tmpGUI)" > Generate< / button >
< / div >
2014-04-09 21:00:23 +00:00
< / div >
2014-07-20 11:49:26 +00:00
2014-02-01 19:23:19 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< / form >
2014-02-01 19:23:19 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< div class = "modal-footer" >
2015-05-27 19:54:00 +00:00
< button type = "button" class = "btn btn-primary btn-sm" ng-click = "saveSettings()" > < span class = "glyphicon glyphicon-ok" > < / span > < span translate > Save< / span > < / button >
< button type = "button" class = "btn btn-default btn-sm" data-dismiss = "modal" > < span class = "glyphicon glyphicon-remove" > < / span > < span translate > Close< / span > < / button >
2014-04-09 21:00:23 +00:00
< / div >
< / div >
2014-02-01 19:23:19 +00:00
< / div >
2014-04-09 21:00:23 +00:00
< / div >
2014-06-11 18:04:23 +00:00
<!-- Usage report modal -->
2014-08-10 22:28:04 +00:00
< div id = "ur" class = "modal fade" data-backdrop = "static" data-keyboard = "false" tabindex = "-1" >
2014-06-11 18:04:23 +00:00
< div class = "modal-dialog modal-lg" >
< div class = "modal-content" >
< div class = "modal-header alert alert-success" >
2014-07-20 11:49:26 +00:00
< h4 translate class = "modal-title" > Allow Anonymous Usage Reporting?< / h4 >
2014-06-11 18:04:23 +00:00
< / div >
< div class = "modal-body" >
2014-09-28 11:00:38 +00:00
< p translate > The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.< / p >
2015-01-26 13:42:50 +00:00
< p translate translate-value-url = "<a href="https://data.syncthing.net" target="_blank">https://data.syncthing.net</a>" > The aggregated statistics are publicly available at {%url%}.< / p >
2014-09-10 09:27:21 +00:00
< button translate type = "button" class = "btn btn-default btn-sm" ng-show = "!reportPreview" ng-click = "showReportPreview()" > Preview Usage Report< / button >
< pre ng-if = "reportPreview" > < small > {{reportData | json}}< / small > < / pre >
2014-06-11 18:04:23 +00:00
< / div >
< div class = "modal-footer" >
2015-05-27 19:54:00 +00:00
< button type = "button" class = "btn btn-success btn-sm" ng-click = "acceptUR()" > < span class = "glyphicon glyphicon-ok" > < / span > < span translate > Yes< / span > < / button >
< button type = "button" class = "btn btn-danger btn-sm" ng-click = "declineUR()" > < span class = "glyphicon glyphicon-remove" > < / span > < span translate > No< / span > < / button >
2014-06-11 18:04:23 +00:00
< / div >
< / div >
< / div >
< / div >
2014-09-08 22:52:31 +00:00
<!-- Usage report preview modal -->
< div id = "urPreview" class = "modal fade" tabindex = "-1" >
< div class = "modal-dialog modal-lg" >
< div class = "modal-content" >
< div class = "modal-header alert alert-success" >
< h4 translate class = "modal-title" > Anonymous Usage Reporting< / h4 >
< / div >
< div class = "modal-body" >
2014-09-28 11:00:38 +00:00
< p translate > The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.< / p >
2015-01-26 13:42:50 +00:00
< p translate translate-value-url = "<a href="https://data.syncthing.net" target="_blank">https://data.syncthing.net</a>" > The aggregated statistics are publicly available at {%url%}.< / p >
2014-09-08 22:52:31 +00:00
< pre > < small > {{reportData | json}}< / small > < / pre >
< / div >
< div class = "modal-footer" >
2015-05-27 19:54:00 +00:00
< button type = "button" class = "btn btn-success btn-sm" data-dismiss = "modal" > < span class = "glyphicon glyphicon-ok" > < / span > < span translate > OK< / span > < / button >
2014-09-08 22:52:31 +00:00
< / div >
< / div >
< / div >
< / div >
2014-06-14 08:58:36 +00:00
<!-- Needed files modal -->
2015-01-11 13:48:40 +00:00
< modal id = "needed" large = "yes" status = "info" icon = "cloud-download" close = "yes" title = "{{'Out of Sync Items' | translate}}" >
2014-12-14 23:34:03 +00:00
< div class = "progress" >
2014-12-13 17:33:20 +00:00
< div class = "progress-bar progress-bar-success" style = "width: 20%" > < span translate class = "show" > Reused< / span > < / div >
< div class = "progress-bar" style = "width: 20%" > < span translate class = "show" > Copied from original< / span > < / div >
< div class = "progress-bar progress-bar-info" style = "width: 20%" > < span translate class = "show" > Copied from elsewhere< / span > < / div >
< div class = "progress-bar progress-bar-warning" style = "width: 20%" > < span translate class = "show" > Downloaded< / span > < / div >
2014-12-14 23:34:03 +00:00
< div class = "progress-bar progress-bar-danger progress-bar-striped active" style = "width: 20%" > < span translate class = "show" > Downloading< / span > < / div >
2014-12-13 17:33:20 +00:00
< / div >
2014-12-14 23:34:03 +00:00
< hr / >
2014-07-14 12:14:26 +00:00
< table class = "table table-striped table-condensed" >
2015-04-25 21:53:44 +00:00
2015-06-26 12:22:52 +00:00
< tr dir-paginate = "f in needed | itemsPerPage: neededPageSize" current-page = "neededCurrentPage" total-items = "neededTotal" pagination-id = "needed" >
2015-04-25 21:53:44 +00:00
<!-- Icon -->
< td class = "small-data" > < span class = "glyphicon glyphicon-{{needIcons[f.action]}}" > < / span > {{needActions[f.action]}}< / td >
<!-- Name -->
< td ng-if = "f.type != 'queued'" title = "{{f.name}}" > {{f.name | basename}}< / td >
< td ng-if = "f.type == 'queued'" >
< a href = "" ng-click = "bumpFile(neededFolder, f.name)" title = "{{'Move to top of queue' | translate}}" >
< span class = "glyphicon glyphicon-eject" > < / span >
< / a >
2015-05-27 19:54:00 +00:00
< span title = "{{f.name}}" > {{f.name | basename}}< / span >
2015-04-25 21:53:44 +00:00
< / td >
<!-- Size/Progress -->
< td ng-if = "f.type == 'progress' && f.action == 'sync' && progress[neededFolder] && progress[neededFolder][f.name]" >
Add job queue (fixes #629)
Request to terminate currently ongoing downloads and jump to the bumped file
incoming in 3, 2, 1.
Also, has a slightly strange effect where we pop a job off the queue, but
the copyChannel is still busy and blocks, though it gets moved to the
progress slice in the jobqueue, and looks like it's in progress which it isn't
as it's waiting to be picked up from the copyChan.
As a result, the progress emitter doesn't register on the task, and hence the file
doesn't have a progress bar, but cannot be replaced by a bump.
I guess I can fix progress bar issue by moving the progressEmiter.Register just
before passing the file to the copyChan, but then we are back to the initial
problem of a file with a progress bar, but no progress happening as it's stuck
on write to copyChan
I checked if there is a way to check for channel writeability (before popping)
but got struck by lightning just for bringing the idea up in #go-nuts.
My ideal scenario would be to check if copyChan is writeable, pop job from the
queue and shove it down handleFile. This way jobs would stay in the queue while
they cannot be handled, meaning that the `Bump` could bring your file up higher.
2014-12-01 19:23:06 +00:00
< div class = "progress" >
2015-03-10 22:45:43 +00:00
< div class = "progress-bar progress-bar-success" style = "width: {{progress[neededFolder][f.name].reused}}%" > < / div >
< div class = "progress-bar" style = "width: {{progress[neededFolder][f.name].copiedFromOrigin}}%" > < / div >
< div class = "progress-bar progress-bar-info" style = "width: {{progress[neededFolder][f.name].copiedFromElsewhere}}%" > < / div >
< div class = "progress-bar progress-bar-warning" style = "width: {{progress[neededFolder][f.name].pulled}}%" > < / div >
< div class = "progress-bar progress-bar-danger progress-bar-striped active" style = "width: {{progress[neededFolder][f.name].pulling}}%" > < / div >
Add job queue (fixes #629)
Request to terminate currently ongoing downloads and jump to the bumped file
incoming in 3, 2, 1.
Also, has a slightly strange effect where we pop a job off the queue, but
the copyChannel is still busy and blocks, though it gets moved to the
progress slice in the jobqueue, and looks like it's in progress which it isn't
as it's waiting to be picked up from the copyChan.
As a result, the progress emitter doesn't register on the task, and hence the file
doesn't have a progress bar, but cannot be replaced by a bump.
I guess I can fix progress bar issue by moving the progressEmiter.Register just
before passing the file to the copyChan, but then we are back to the initial
problem of a file with a progress bar, but no progress happening as it's stuck
on write to copyChan
I checked if there is a way to check for channel writeability (before popping)
but got struck by lightning just for bringing the idea up in #go-nuts.
My ideal scenario would be to check if copyChan is writeable, pop job from the
queue and shove it down handleFile. This way jobs would stay in the queue while
they cannot be handled, meaning that the `Bump` could bring your file up higher.
2014-12-01 19:23:06 +00:00
< span class = "show frontal" >
2015-03-10 22:45:43 +00:00
{{progress[neededFolder][f.name].bytesDone | binary}}B / {{progress[neededFolder][f.name].bytesTotal | binary}}B
Add job queue (fixes #629)
Request to terminate currently ongoing downloads and jump to the bumped file
incoming in 3, 2, 1.
Also, has a slightly strange effect where we pop a job off the queue, but
the copyChannel is still busy and blocks, though it gets moved to the
progress slice in the jobqueue, and looks like it's in progress which it isn't
as it's waiting to be picked up from the copyChan.
As a result, the progress emitter doesn't register on the task, and hence the file
doesn't have a progress bar, but cannot be replaced by a bump.
I guess I can fix progress bar issue by moving the progressEmiter.Register just
before passing the file to the copyChan, but then we are back to the initial
problem of a file with a progress bar, but no progress happening as it's stuck
on write to copyChan
I checked if there is a way to check for channel writeability (before popping)
but got struck by lightning just for bringing the idea up in #go-nuts.
My ideal scenario would be to check if copyChan is writeable, pop job from the
queue and shove it down handleFile. This way jobs would stay in the queue while
they cannot be handled, meaning that the `Bump` could bring your file up higher.
2014-12-01 19:23:06 +00:00
< / span >
< / div >
< / td >
2015-04-25 21:53:44 +00:00
< td class = "text-right small-data" ng-if = "f.type != 'progress' || f.action != 'sync' || !progress[neededFolder] || !progress[neededFolder][f.name]" >
2015-03-10 22:45:43 +00:00
< span ng-if = "f.size > 0" > {{f.size | binary}}B< / span >
2014-11-16 23:18:59 +00:00
< / td >
2015-04-25 21:53:44 +00:00
Add job queue (fixes #629)
Request to terminate currently ongoing downloads and jump to the bumped file
incoming in 3, 2, 1.
Also, has a slightly strange effect where we pop a job off the queue, but
the copyChannel is still busy and blocks, though it gets moved to the
progress slice in the jobqueue, and looks like it's in progress which it isn't
as it's waiting to be picked up from the copyChan.
As a result, the progress emitter doesn't register on the task, and hence the file
doesn't have a progress bar, but cannot be replaced by a bump.
I guess I can fix progress bar issue by moving the progressEmiter.Register just
before passing the file to the copyChan, but then we are back to the initial
problem of a file with a progress bar, but no progress happening as it's stuck
on write to copyChan
I checked if there is a way to check for channel writeability (before popping)
but got struck by lightning just for bringing the idea up in #go-nuts.
My ideal scenario would be to check if copyChan is writeable, pop job from the
queue and shove it down handleFile. This way jobs would stay in the queue while
they cannot be handled, meaning that the `Bump` could bring your file up higher.
2014-12-01 19:23:06 +00:00
< / tr >
2014-07-14 12:14:26 +00:00
< / table >
2014-11-16 23:18:59 +00:00
2015-06-26 12:22:52 +00:00
< dir-pagination-controls on-page-change = "neededPageChanged(newPageNumber)" pagination-id = "needed" > < / dir-pagination-controls >
2015-04-25 21:53:44 +00:00
< ul class = "pagination pull-right" >
2015-06-26 12:22:52 +00:00
< li ng-repeat = "option in [10, 25, 50]" ng-class = "{ active: neededPageSize == option }" >
2015-04-25 21:53:44 +00:00
< a href = "#" ng-click = "neededChangePageSize(option)" > {{option}}< / a >
< li >
< / ul >
2015-04-26 19:14:15 +00:00
< div class = "clearfix" > < / div >
2014-07-14 12:14:26 +00:00
< / modal >
2014-06-14 08:58:36 +00:00
2015-06-26 12:22:52 +00:00
<!-- Failed Items modal -->
< modal id = "failed" large = "yes" status = "warning" icon = "exclamation-sign" close = "yes" title = "{{'Failed Items' | translate}}" >
< p >
< span translate > The following items could not be synchronized.< / span >
< span translate > They are retried automatically and will be synced when the error is resolved.< / span >
< / p >
< table class = "table table-striped table-condensed" >
< tr dir-paginate = "e in failedCurrent | itemsPerPage: failedPageSize" current-page = "failedCurrentPage" pagination-id = "failed" >
< td > < abbr title = "{{e.path}}" > {{e.path | basename}}< / abbr > < / td >
< td > < abbr title = "{{e.error}}" > {{e.error | lastErrorComponent}}< / abbr > < / td >
< / tr >
< / table >
< dir-pagination-controls on-page-change = "failedPageChanged(newPageNumber)" pagination-id = "failed" > < / dir-pagination-controls >
< ul class = "pagination pull-right" >
< li ng-repeat = "option in [10, 25, 50]" ng-class = "{ active: failedPageSize == option }" >
< a href = "#" ng-click = "failedChangePageSize(option)" > {{option}}< / a >
< li >
< / ul >
< div class = "clearfix" > < / div >
< / modal >
2014-07-07 10:58:56 +00:00
<!-- About modal -->
2015-01-11 13:48:40 +00:00
< modal id = "about" large = "yes" close = "yes" status = "info" title = "{{'About' | translate}}" >
2015-04-19 23:23:59 +00:00
< h1 class = "text-center" > < img alt = "Syncthing" title = "Syncthing" src = "assets/img/logo-horizontal.svg" style = "vertical-align: -16px" height = "100" width = "366" / > < br / > < small > {{versionString()}}< / small > < / h1 >
2014-07-14 12:14:26 +00:00
< hr / >
2014-07-07 10:58:56 +00:00
2015-04-04 08:09:06 +00:00
< p translate > Copyright © 2015 the following Contributors:< / p >
2014-07-14 12:14:26 +00:00
< div class = "row" >
2014-11-30 19:49:49 +00:00
< div class = "col-md-12" >
2015-04-04 08:09:06 +00:00
< ul class = "list-unstyled three-columns" id = "contributor-list" >
< li class = "auto-generated" > Aaron Bieber< / li >
< li class = "auto-generated" > Alexander Graf< / li >
< li class = "auto-generated" > Andrew Dunham< / li >
2015-07-05 17:44:19 +00:00
< li class = "auto-generated" > Antony Male< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Arthur Axel fREW Schmidt< / li >
< li class = "auto-generated" > Audrius Butkevicius< / li >
2015-05-25 06:07:59 +00:00
< li class = "auto-generated" > Bart De Vries< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Ben Curthoys< / li >
< li class = "auto-generated" > Ben Schulz< / li >
< li class = "auto-generated" > Ben Sidhom< / li >
< li class = "auto-generated" > Brandon Philips< / li >
< li class = "auto-generated" > Brendan Long< / li >
2015-07-20 12:22:36 +00:00
< li class = "auto-generated" > Brian R. Becker< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Caleb Callaway< / li >
2015-04-16 14:23:34 +00:00
< li class = "auto-generated" > Carsten Hagemann< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Cathryne Linenweaver< / li >
2015-05-14 06:11:02 +00:00
< li class = "auto-generated" > Chris Howie< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Chris Joel< / li >
< li class = "auto-generated" > Colin Kennedy< / li >
2015-07-02 08:44:33 +00:00
< li class = "auto-generated" > Daniel Bergmann< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Daniel Martí< / li >
2015-07-20 12:25:07 +00:00
< li class = "auto-generated" > Denis A.< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Dennis Wilson< / li >
< li class = "auto-generated" > Dominik Heidler< / li >
2015-04-26 10:40:02 +00:00
< li class = "auto-generated" > Elias Jarlebring< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Emil Hessman< / li >
2015-06-19 06:50:36 +00:00
< li class = "auto-generated" > Erik Meitner< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Federico Castagnini< / li >
< li class = "auto-generated" > Felix Ableitner< / li >
< li class = "auto-generated" > Felix Unterpaintner< / li >
2015-04-10 10:57:43 +00:00
< li class = "auto-generated" > Francois-Xavier Gsell< / li >
2015-06-20 09:32:55 +00:00
< li class = "auto-generated" > Frank Isemann< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Gilli Sigurdsson< / li >
2015-07-20 12:18:07 +00:00
< li class = "auto-generated" > Jacek Szafarkiewicz< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Jakob Borg< / li >
< li class = "auto-generated" > James Patterson< / li >
2015-04-04 21:21:45 +00:00
< li class = "auto-generated" > Jaroslav Malec< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Jens Diemer< / li >
< li class = "auto-generated" > Jochen Voss< / li >
< li class = "auto-generated" > Johan Vromans< / li >
< li class = "auto-generated" > Karol Różycki< / li >
< li class = "auto-generated" > Ken'ichi Kamada< / li >
< li class = "auto-generated" > Lode Hoste< / li >
2015-05-04 08:36:40 +00:00
< li class = "auto-generated" > Lord Landon Agahnim< / li >
2015-04-04 08:09:06 +00:00
< li class = "auto-generated" > Marc Laporte< / li >
< li class = "auto-generated" > Marc Pujol< / li >
< li class = "auto-generated" > Marcin Dziadus< / li >
< li class = "auto-generated" > Michael Jephcote< / li >
< li class = "auto-generated" > Michael Tilli< / li >
< li class = "auto-generated" > Pascal Jungblut< / li >
< li class = "auto-generated" > Peter Hoeg< / li >
< li class = "auto-generated" > Philippe Schommers< / li >
< li class = "auto-generated" > Phill Luby< / li >
< li class = "auto-generated" > Piotr Bejda< / li >
< li class = "auto-generated" > Ryan Sullivan< / li >
< li class = "auto-generated" > Sergey Mishin< / li >
< li class = "auto-generated" > Stefan Tatschner< / li >
< li class = "auto-generated" > Tim Abell< / li >
< li class = "auto-generated" > Tobias Nygren< / li >
< li class = "auto-generated" > Tomas Cerveny< / li >
< li class = "auto-generated" > Tully Robinson< / li >
< li class = "auto-generated" > Veeti Paananen< / li >
< li class = "auto-generated" > Vil Brekin< / li >
2014-07-07 10:58:56 +00:00
< / ul >
2014-09-10 09:27:21 +00:00
< / div >
2014-07-07 10:58:56 +00:00
< / div >
2014-07-14 12:14:26 +00:00
< hr / >
2014-07-20 11:49:26 +00:00
< p translate > Syncthing includes the following software or portions thereof:< / p >
2014-11-30 19:49:49 +00:00
< ul class = "list-unstyled two-columns" >
2014-08-14 23:58:25 +00:00
< li > < a href = "http://golang.org/" > The Go Programming Language< / a > , Copyright © 2012 The Go Authors.< / li >
2014-07-14 12:14:26 +00:00
< li > < a href = "https://bitbucket.org/kardianos/osext" > kardianos/osext< / a > , Copyright © 2012 Daniel Theophanes.< / li >
< li > < a href = "https://code.google.com/p/snappy-go/" > snappy-go< / a > , Copyright © 2011 The Snappy-Go Authors.< / li >
< li > < a href = "https://github.com/golang/groupcache" > groupcache/lru< / a > , Copyright © 2013 Google Inc.< / li >
< li > < a href = "https://github.com/juju/ratelimit" > juju/ratelimit< / a > , Copyright © 2014 Canonical Ltd.< / li >
< li > < a href = "https://github.com/syndtr/goleveldb" > syndtr/goleveldb< / a > , Copyright © 2012, Suryandaru Triandana< / li >
< li > < a href = "https://github.com/vitrun/qart" > vitrun/qart< / a > , Copyright © The Go Authors.< / li >
< li > < a href = "https://angularjs.org/" > AngularJS< / a > , Copyright © 2010-2014 Google, Inc.< / li >
< li > < a href = "http://getbootstrap.com/" > Bootstrap< / a > , Copyright © 2011-2014 Twitter, Inc.< / li >
< / ul >
< / modal >
2014-07-07 10:58:56 +00:00
2015-07-03 12:07:38 +00:00
<!-- Advanced modal -->
< div id = "advanced" class = "modal fade" tabindex = "-1" >
< div class = "modal-dialog modal-lg" >
< div class = "modal-content" >
< div class = "modal-header alert alert-danger" >
< h4 translate class = "modal-title" > Advanced Configuration< / h4 >
< / div >
< div class = "modal-body" >
< p class = "text-danger" >
< b translate > Be careful!< / b >
< span translate > Incorrect configuration may damage your folder contents and render Syncthing inoperable.< / span >
< / p >
< div class = "panel-group" id = "advancedAccordion" role = "tablist" aria-multiselectable = "true" >
< div class = "panel panel-default" >
< div class = "panel-heading" role = "tab" id = "guiHeading" data-toggle = "collapse" data-parent = "#advancedAccordion" href = "#guiConfig" aria-expanded = "true" aria-controls = "guiConfig" style = "cursor: pointer" >
< h4 class = "panel-title" translate > GUI< / h4 >
< / div >
< div id = "guiConfig" class = "panel-collapse collapse in" role = "tabpanel" aria-labelledby = "guiHeading" >
< div class = "panel-body" >
< form class = "form-horizontal" role = "form" >
2015-07-09 20:58:58 +00:00
< div ng-repeat = "(key, value) in advancedConfig.gui" ng-init = "type = inputTypeFor(key, value)" ng-if = "type != 'skip'" class = "form-group" >
2015-07-03 12:07:38 +00:00
< label for = "guiInput{{$index}}" class = "col-sm-4 control-label" > {{key}}< / label >
< div class = "col-sm-8" >
2015-07-09 20:58:58 +00:00
< input id = "guiInput{{$index}}" class = "form-control" type = "{{type}}" ng-model = "advancedConfig.gui[key]" / >
2015-07-03 12:07:38 +00:00
< / div >
< / div >
< / form >
< / div >
< / div >
< / div >
< div class = "panel panel-default" >
< div class = "panel-heading" role = "tab" id = "optionsHeading" data-toggle = "collapse" data-parent = "#advancedAccordion" href = "#optionsConfig" aria-expanded = "true" aria-controls = "optionsConfig" style = "cursor: pointer" >
< h4 class = "panel-title" translate > Options< / h4 >
< / div >
< div id = "optionsConfig" class = "panel-collapse collapse" role = "tabpanel" aria-labelledby = "optionsHeading" >
< div class = "panel-body" >
< form class = "form-horizontal" role = "form" >
2015-07-09 20:58:58 +00:00
< div ng-repeat = "(key, value) in advancedConfig.options" ng-if = "inputTypeFor(key, value) != 'skip'" class = "form-group" >
2015-07-03 12:07:38 +00:00
< label for = "optionsInput{{$index}}" class = "col-sm-4 control-label" > {{key}}< / label >
< div class = "col-sm-8" >
2015-07-09 20:58:58 +00:00
< input id = "optionsInput{{$index}}" class = "form-control" type = "{{inputTypeFor(key, value)}}" ng-model = "advancedConfig.options[key]" / >
2015-07-03 12:07:38 +00:00
< / div >
< / div >
< / form >
< / div >
< / div >
< / div >
2015-07-09 20:58:58 +00:00
< div class = "panel panel-default" ng-repeat = "folder in advancedConfig.folders" >
2015-07-16 06:13:02 +00:00
< div class = "panel-heading" role = "tab" id = "folder{{$index}}Heading" data-toggle = "collapse" data-parent = "#advancedAccordion" href = "#folder{{$index}}Config" aria-expanded = "true" aria-controls = "folder{{$index}}Config" style = "cursor: pointer" >
2015-07-03 12:07:38 +00:00
< h4 class = "panel-title" >
2015-07-09 20:58:58 +00:00
< span translate > Folder< / span > "{{folder.id}}"
2015-07-03 12:07:38 +00:00
< / h4 >
< / div >
2015-07-16 06:13:02 +00:00
< div id = "folder{{$index}}Config" class = "panel-collapse collapse" role = "tabpanel" aria-labelledby = "folder{{$index}}Heading" >
2015-07-03 12:07:38 +00:00
< div class = "panel-body" >
< form class = "form-horizontal" role = "form" >
2015-07-09 20:58:58 +00:00
< div ng-repeat = "(key, value) in folder" ng-if = "inputTypeFor(key, value) != 'skip'" class = "form-group" >
2015-07-16 06:13:02 +00:00
< label for = "folder{{$index}}Input{{$index}}" class = "col-sm-4 control-label" > {{key}}< / label >
2015-07-03 12:07:38 +00:00
< div class = "col-sm-8" >
2015-07-16 06:13:02 +00:00
< input id = "folder{{$index}}Input{{$index}}" class = "form-control" type = "{{inputTypeFor(key, value)}}" ng-model = "folder[key]" / >
2015-07-03 12:07:38 +00:00
< / div >
< / div >
< / form >
< / div >
< / div >
< / div >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-primary btn-sm" ng-click = "saveAdvanced()" > < span class = "glyphicon glyphicon-ok" > < / span > < span translate > Save< / span > < / button >
< button type = "button" class = "btn btn-default btn-sm" data-dismiss = "modal" > < span class = "glyphicon glyphicon-remove" > < / span > < span translate > Close< / span > < / button >
< / div >
< / div >
< / div >
< / div >
< / div >
2014-11-26 12:39:59 +00:00
<!-- vendor scripts -->
2015-07-03 12:07:38 +00:00
< script src = "vendor/jquery/jquery-2.0.3.min.js" > < / script >
2014-11-26 12:39:59 +00:00
< script src = "vendor/angular/angular.min.js" > < / script >
< script src = "vendor/angular/angular-translate.min.js" > < / script >
< script src = "vendor/angular/angular-translate-loader.min.js" > < / script >
2015-04-25 21:53:44 +00:00
< script src = "vendor/angular/angular-dirPagination.js" > < / script >
2014-11-26 12:39:59 +00:00
< script src = "vendor/bootstrap/js/bootstrap.min.js" > < / script >
<!-- / vendor scripts -->
<!-- gui application code -->
< script src = "scripts/syncthing/core/module.js" > < / script >
2015-06-14 14:17:48 +00:00
< script src = "scripts/syncthing/core/services/events.js" > < / script >
2014-11-26 12:39:59 +00:00
< script src = "scripts/syncthing/core/controllers/syncthingController.js" > < / script >
< script src = "scripts/syncthing/core/directives/identiconDirective.js" > < / script >
2015-04-02 12:48:59 +00:00
< script src = "scripts/syncthing/core/directives/languageSelectDirective.js" > < / script >
2014-11-26 12:39:59 +00:00
< script src = "scripts/syncthing/core/directives/modalDirective.js" > < / script >
< script src = "scripts/syncthing/core/directives/uniqueFolderDirective.js" > < / script >
< script src = "scripts/syncthing/core/directives/validDeviceidDirective.js" > < / script >
2014-11-18 22:57:21 +00:00
< script src = "scripts/syncthing/core/directives/popoverDirective.js" > < / script >
2015-07-01 14:44:23 +00:00
< script src = "scripts/syncthing/core/directives/selectOnClickDirective.js" > < / script >
2014-11-26 12:39:59 +00:00
< script src = "scripts/syncthing/core/filters/alwaysNumberFilter.js" > < / script >
< script src = "scripts/syncthing/core/filters/basenameFilter.js" > < / script >
< script src = "scripts/syncthing/core/filters/binaryFilter.js" > < / script >
2015-04-03 18:00:13 +00:00
< script src = "scripts/syncthing/core/filters/durationFilter.js" > < / script >
Use bootstrap grid instead of column-count:3 for aligning checkboxes (fixes #2029)
Upgrading to bootstrap 3.3.5 meant that checkboxes inside a div with
column-count:3 set would be unclickable in Chrome: in fact, the entire
div appears to sit on top of its contents, making interaction impossible.
This affected both the 'show folder with these devices' and 'these devices
can access this folder' sections of the UI.
I'm not sure what the the underlying cause is, but moving to Bootstrap's
grid system appears work around the issue. Devices/folders have to be
explicitly split out into rows, otherwise the final element appears offset.
To do this grouping by row, a new filter (groupFilter) has been added, which
turns an input of e.g. [1, 2, 3, 4, 5] with a groupSize of 3 into
[[1, 2, 3], [4, 5]]. However altering the collection in this way throws
Angular into an infinite watch loop, terminating in infdig. m59peacemaker's
pmkr.filterStabilize (MIT) was added to work around this issue.
This also has the nice side-effect of wrapping the list of devices/folders
when the screen width decreases.
See also:
- #2027 (bootstrap update which triggered this issue)
- #1121 (last time it happened)
2015-07-05 16:08:16 +00:00
< script src = "scripts/syncthing/core/filters/groupFilter.js" > < / script >
2014-11-26 12:39:59 +00:00
< script src = "scripts/syncthing/core/filters/naturalFilter.js" > < / script >
2015-06-26 12:22:52 +00:00
< script src = "scripts/syncthing/core/filters/lastErrorComponentFilter.js" > < / script >
Use bootstrap grid instead of column-count:3 for aligning checkboxes (fixes #2029)
Upgrading to bootstrap 3.3.5 meant that checkboxes inside a div with
column-count:3 set would be unclickable in Chrome: in fact, the entire
div appears to sit on top of its contents, making interaction impossible.
This affected both the 'show folder with these devices' and 'these devices
can access this folder' sections of the UI.
I'm not sure what the the underlying cause is, but moving to Bootstrap's
grid system appears work around the issue. Devices/folders have to be
explicitly split out into rows, otherwise the final element appears offset.
To do this grouping by row, a new filter (groupFilter) has been added, which
turns an input of e.g. [1, 2, 3, 4, 5] with a groupSize of 3 into
[[1, 2, 3], [4, 5]]. However altering the collection in this way throws
Angular into an infinite watch loop, terminating in infdig. m59peacemaker's
pmkr.filterStabilize (MIT) was added to work around this issue.
This also has the nice side-effect of wrapping the list of devices/folders
when the screen width decreases.
See also:
- #2027 (bootstrap update which triggered this issue)
- #1121 (last time it happened)
2015-07-05 16:08:16 +00:00
< script src = "scripts/syncthing/core/services/filterStabilize.js" > < / script >
2014-11-28 18:39:33 +00:00
< script src = "scripts/syncthing/core/services/localeService.js" > < / script >
Use bootstrap grid instead of column-count:3 for aligning checkboxes (fixes #2029)
Upgrading to bootstrap 3.3.5 meant that checkboxes inside a div with
column-count:3 set would be unclickable in Chrome: in fact, the entire
div appears to sit on top of its contents, making interaction impossible.
This affected both the 'show folder with these devices' and 'these devices
can access this folder' sections of the UI.
I'm not sure what the the underlying cause is, but moving to Bootstrap's
grid system appears work around the issue. Devices/folders have to be
explicitly split out into rows, otherwise the final element appears offset.
To do this grouping by row, a new filter (groupFilter) has been added, which
turns an input of e.g. [1, 2, 3, 4, 5] with a groupSize of 3 into
[[1, 2, 3], [4, 5]]. However altering the collection in this way throws
Angular into an infinite watch loop, terminating in infdig. m59peacemaker's
pmkr.filterStabilize (MIT) was added to work around this issue.
This also has the nice side-effect of wrapping the list of devices/folders
when the screen width decreases.
See also:
- #2027 (bootstrap update which triggered this issue)
- #1121 (last time it happened)
2015-07-05 16:08:16 +00:00
< script src = "scripts/syncthing/core/services/memoize.js" > < / script >
2014-11-26 12:39:59 +00:00
< script src = "assets/lang/valid-langs.js" > < / script >
2015-06-02 06:47:26 +00:00
< script src = "assets/lang/prettyprint.js" > < / script >
2014-11-26 12:39:59 +00:00
< script src = "scripts/syncthing/app.js" > < / script >
<!-- / gui application code -->
2014-01-05 22:54:57 +00:00
< / body >
< / html >