Archived
1 parent
c42a6b511c
commit
433a0cb9cc
5 files changed
+606
-352
No files matched your search
+3
-3
@@ -18,7 +18,7 @@ func init() {
|
||||
bs, _ = ioutil.ReadAll(gr)
|
||||
Assets["angular.min.js"] = bs
|
||||
|
||||
bs, _ = hex.DecodeString("1f8b080000096e8800ffd45bdd6fe336127fcf5fc16e7b90bcf1dadee2703824cd026df603b9fd48b1deeb4b9007daa26d6e64524752498cc0fffb0d294a26254a9693dbeed540b336399c8f1f8733c3913a7efe55a694293413fc4e12718294c8c910cd395394e5a4fc9da5b9d4ff15bfd1f3f1d1f8f932e5339ca29f4ed002a71288305be62916f6b7263a8a72f82295a073159d1e1ddd6281e486cdd58ab2253a2b578cd63cc9531247d55c344457d70358518d8cb44a82a7291171342d47cf9548817691c36fca198a7f92739e812e3fad94ca06e8e108c1478bcd04b97d8d1501a993a119d51f104cd277445dbe87716d1a88d4e3051b2d9311c359c2fcc3f6b436b9a0cbe6f87a73f11a46a3c81b65204933b9ba0e30b960daa24a05679e08c145609d2484bdd1735692991b8fd114b0664b896664c1054133ce538952ce6f604429227c1e4a1962e05e21f2409313147da0521106cc005cd07b0e9b6a4047bf0baef89ca7a8a040bf268920521209846a9381c3448adc2bf805c30a0b5578cc765813f0eedf1776a92301066b7c0fe4fa11df4f094bdecf3297ed65ae965c3bdc67bdff1fe89a2a14bfff2d93831d7b96af6744ec15f019586276c100c95b9c4e1d21c50c2aa750fc28eed6e1c202ece4d364fc8e058643947e26ffc981d0c509d0438015ac6689816b4772980c6074be82b34d6a1ba105bca52941c56cb11fbd77a201164e2e59baf120c209b263969b3e007bf57d0b6185df4d376b088537aec2c50472660e61fbce04c85f197bc3f02c2589ebe945ec84390ea18b1cc8f8039fb7f035338f653bd573bf1589c03df77a18edc65d9696c7b50d40551c2ee3ea349fcf0949481297b1587fe802c53fec42af3b65c2531cfdc888bae3e2c684b868a013044ee3684513120d4e3dea40082fa7b647c5dfb06e6f31b86253b147e8f530c3f39b44f00c600180159d034c376433e35824361d6ebbd43614fbf4d619e49caf332c488c876856571c8f3e0185ce3d67676e2eaa9b2188ca05432f5ed605968c6687316ae55329f40b2a591ea48b9dacd8bcaad89cba0099543f5a12154763ede0e35b22240006db23b5fb4919efea83042bec2a61cdb34b602b3481656f77acc15f6e2045ad0f615facf0b83bb3b660d073e6fbe92ed4356417f5422fd98e84aa54f1e5372846979929764655fe47679d14364d8fbe427e8dc1e9f5e1f4d8ebd2ab2c7d7c469f49c625555c5022af26d76667a5af9b5938925ca8d871fe41d0805208f3d9b8c7ae05ccb1ae311f876855b799bd73c79a1a6c077e6d29c8029458e9d35f09f45ce7096eb7dff53a7131b1e950416651d0c502c9c055a4a871e3300aeefa3260f7dfddb278ef6d4be1ae776086be2b8053ddc583a147a13f2a018258d3bda8ee150334462f279349939a26b533e15c458047d09b2983ca495f5582b33c57d5b4370f353f8a6982284321eb8c363af71a775d617979c7a0a0cf88501b583608d1eb4f791b3c6dcc6e9bd8884d0b172df48a26d795711fb15a8dd6f83e9e0cd13fd1f362470cc505fb6da388fcc21554332f02b7b10695865f2583a6869ee40ab876d15000f791ed91b50adfa23956f3158a491bb40d50267d4d08103677c373a7e3b39ab82607dfc1dc05c590bf62db12199d3bf3015187416c38e8a0d22162785df3cae208187c1085cac3b87a4ad852ad60e0f838b4119a0b2a6d854c043f47324ba956ad5e6eee36e37a345d416afa542cd63caef41f2b0c5ce7e575175c463193db7696d6cbbaf25354533b71baa0aa7eb5b956a0b60a6b1292f0ea0009bd0458da9ad7d6abe23299832b1ce63c459fe4d09c557557c292b67ec6d6a5055c86542ebda46d4a93c5d215a1bd539f03afe8a9e2875d606b59c749f42668c2bab6e5f8485740293162756d0ef926b43516eae882215d8a4435c811d1ddb9f6657a8dbefec7113a4675b1c728fadba0ced1a9ddebc57bf49a4a6b3b9cee56582fe6a6f8fe0b80ca6f0ec5d3167a8780b6866c2bdbd13a4fb1fc8bf8a03d8e87629609bac662730866942d783b64faa2f22723661533a0d97b52c72d378a737603e520dc770bda41c7fe3b5bf0dd4caa0585a8cbb67653fe207bb7452be36bdab331e1dfed43fa7d4b78524a98faa35d7663dfad9e1dfb6e4b8dfe680572b715eb927468e74300c9752695d045f33fc22952e25b32dd3d5668b9d906afd0b51e588faec39edec45489b28a1bea561dce9ca2e01e142a8dbc1f29083770af0c94181997f5decb10fd6b7af96924cd9316bad8c49e1283217a58119cc0669ea087e81cae4ee0072fbe6c32129da00867a0115c0a4089f157c959b4f564c6d18fe553992fbab70b7acf799ae24c12bffbb9ad37134c63774f33c135c6ae70cbdb7d8fa46a32494295f68b7d1e59b2cd850024ec0a4bd710ae9982f56fee610b8b67847e4bb7c96c543d822ada55a5cb56c35e73ca45ba34e0517ddc1a1810b41b58ec05e1a13856200de4b866c048b281cb0428b0ed0151fde8fc8f6d4b08c479d2699ee99b90bb4fd543ce21a26e1b33a451a39b6f5a136123c351ec34540fd42f806e7fb0eb22a8a5bbb4e62658a49b1f76e9c675bc704b5b7f4a2846592e5775ae831e454dbda969f9b585c7602fd55b7760f0fd93635f208bec77b7e29c0f51c219a9b95b2f1b7bf9a49582420ed0a0dac59c501c7a643eaa84683b9b667c0377d7d5959ff8433e5e5b1c8ae935cdfd485e7e6682e09b1e47a2685c02a796bb3cdb1db8320905e38347def16ca1df0973b9359edb7cb703c4d58a8852c5ee235485eb2162a74f8fa2ac860978c669c3ef5820b086ea78c3d0d9d68ec8597e73ea56198446ada8dc1b5bbe0b187b2e358e7557acb5b3b80d566abacda58be24ea31baf1a55a61b481ae617f45df61bae3b0c8a054110c8e80b355dc7faeb4d2114ac60e313f5a7811d3e512c0b3ac53c2558bc29edeface0dc17af7cbb42b0982eb0b12d287701e18425e9a679542140b8c23bb661af179a4bae9bc2c2be284df50c7fe13291a5784ee27915ff87f55ba89e1b0c3a2e8ec0a7e5a2629a61e5433cb8ec946f33c53ec5d03c4d9b009d498215320999d335a440402385539aafdd97fc12baa44aea5757e66534d6dea5df95d2a7cbeb54f90d699b200a06e503a245cab988cdd7942f8b2f7866440ff4339f6ae6e5a404434bae3d5f021dc10d0ace96caca2ed4dcba6f392e68aaf41b8e0c0305f6df6d2cb5b7ab77139465b91a0202294d02269ae991e26fe93d49e20a406fd52e8f6cfdd72e4b856694e9865c7f7dea4d093368b62167095950469296de443441c16ed28ecb2b708e9fff8e9ebbff340a1c43393e0b909e86a476a3f4336cf8318ad03b7a886a7d747a82321ffb29d3a9c513c4bf0f8bb73ccc11101c36bbf407bd26dae7676ba2df16fe3ff2b3c9c46c54f54f079a75d2a7f8d9219af551e9296ed64b974e259e20fde61b3899d44f361fe9639ef2c1Line truncated
|
||||
bs, _ = hex.DecodeString("1f8b080000096e8800ffd43b5b6fdb38d6eff9159c7cfd20b9716477b0582c92a68b994c6690ed154d3b2f811f688bb6d9c89497a4931881fffb1e52944c8a942c27edb463a08d4d1e9e1b0fcf4dd4e0f917915126d198e77782f01324f98af4d1246792b215297f2fb39550ff8adfe8f9e060f07c96e5639ca16727688a33014098cd5619e6e6b7023a8856f045484e27323a3d38b8c51c89359bc83965337456ae481679baca481c5573511f5d8f7ab0a21a49144b3ccf32c2e3e8aa1c3d973c03d8e90a7ed39ca1f89998e44be0e5d95cca650f3d1c20f828b24b4e6e7fc39200d5615f8fce887cff1a7e2a8980921a2a562b528c688402e61f36a7b5c9299df9e38bf5e56f301a45ce28cb53a2905c8f02482e9912a462c19a279ce73cb04e10c22ed49c4f097448329f2d4e967989488f0f06e80a3684cd041a9369ce091ae779265096e737302225e12e45293530a0d0e30f343d41d11b2a24618008b40f124e60d7f5aea00f3c97f924cf5001817e49534e84200200e57a09161549722fe1170c4bcc6561529bbe85fc2dbebf222c7d3d5e0a0bfdfb959ce5ca6e3eaa6d7c431754a2f8f5af4bd1dba266abc598f056e41f011d66970ce4bcc5d99545a09841e5148af7c66c0c278cdc4c3e1eff07cc31d87ff691fc770540b66e406308f4032b59aa55b405e98e1f909ccfe148929ae215f2df694650315be8bfb3e62d027f688ff10b63170c8f33925a348a290473399c65b2c5ab8cb395eb37f9a401a79e790cca2b35fe6be1116dfb56c3683b6ea333eb47ae2399ade855f8fc9863616be0f3e553cecc67975785ed97959c13f0e313ac7de36787eb9d083f6021ee729eb623b5a00ce2e5762484bcd450e5b2c10d5fad2613425292c6a5c7561f3a45f14fda49dba35abb71f47f8c48a072a39d61d453de0f677134a729897aa70eb4ebe7cbd1cd41f1bfc7ccef184cdde7643f461ec6787293f27c090a011d80ba401d37643dce314f4d80dc34f0a9277731aae2ca79be58624e62dc47e33abb387907102a229d9dd911aa2e012772c5193a7e512758221aef87a8114fc5d04b54a2dc8b173359a17955a139b5155445bd2918df5c69b34a0d6c723a3d4840e3713450563a106b38790bd83fa16c518878bb2ec512d759758dd6ddc732706a8cc0815a6f49d42b827b1c66cc202f8dd05eb7fd6e87f60442f8059ecc2d7c6adcb3d4bac03a5d1844e80829f00476a3a3e816031ac7b5593ff244adb3ed8850e7c7cab93aef82caeb587e0784556607b9d65ddceb3b103285c958c11c5719600f0dd08be170e842d2d438a6f263258cb03eb8c59441a054096570365fc96ada99871d43314d1165a849c1daf7a9c9648ec5fb3b0659d59270b98665bd10bcfa9439fba937bbf146245f37605144af693aaa847b8be53c59e0fb78d847ff42cf8b9dd01097ecd7b524e2532e21cc1e0792670f4aa95ea63d9f438772a5b866d290eb74a1ed803512df20086693398a49936a3da50cbb8a1000f477c331a7a3b31a391f836b60f68262a8760443c6e996387517d5724e8bcaa4f311add733614a1b376d5245df07c2279067e019719c78ddb7a983a2128f7cea3ba5918e59d18aa5644a19a4864d316b386c8a5a3ecea4287bb55969fcc36e58abafba188532e04c4180510748505d1716240621008b87d37a84d487664268160395b07e55f200c9ac5c0947b73aa798ce6c7914b3ca54d059e8889905260e8f4e1dd529c0ba6acaf144a52e19d164950e4113a1a367248a2e19520a896a768d886a33342f536b543114ab2857277b84a2ffefd53186f6abc4f61b154676b0a446b55e4e94487f07a5e637fbead32455fb286d010149346beb3c8362e1efa12ee3eef6d5d992d305e6eb7d7446d9346f5699aa0dff628d19c6b4d24c69da92a147ff6ed96f4be5df4d849a1388da646916e54fb2731b14332ea71d8b2803714bb800dc21febea57a320a71f7cf66da1df6f91d5e90bdb403f00d3cd9202ddcb8224372321692abbcf19fe11048522aadd64c439508e57dd9ffec5adaeb56472f54930a7c4b76930cf6876b2d01072879bfd4bb9e14cd2373401dc3f0a1ae244fc432a390d6f595647869e571f7c050a9d7fb448207834234901542f569976f400534f19fabf7ef12a11bcc74ba8e1d267a7df430273805db3a410fd139142c606ac79f207f8b409b78091c157da5c11791b368e3d00c6dc6a16af81c86b7d8749f76f4006c21cc8ac82fb51bfbf501b35226b8cbf84bb42bce410366c5b384dc8342d2f861d32f0dda674591001d5cdcc346164f51dcc6968f3aa9fa89b0edba9c2dce4a359c7cc929034b40514ddfa5388f327e5733384d3dc5ecd4c883cd39904cd70c2f80e6a68356ea67e6eb8a03b93891a45da21045af43a92bfdb010618f182c2a6a4f9bec9fc9946692d8fda626f7cfca28f5d3364ad96664b7db34fda673a221eb7c584d10dd0051218cea0a19febc747b5a196133398789a3a3868252c35dd3519d943bde41f627c85fd781bf1f3bdcf85fec45eb5536c4a356032eda6bda57f4519a33d247f4745f193b1d02430585d4ee416dfd56c8973d32b25544949cbe1845cbceb3d6e280b558abd543d0b0a5659a54d0cd5a5a3aade5e2adc47e57c870ee4683f233e604df7428428ac623606a387785c4cb9598c77e846a704889c8b98cad27168ff51bdff9c0e4724e78c962f8c8b8097ca3ffedec7e5591b0b35d26e754ec3cc814528aba0b7e8441b3daee804d9e7a16cf3a963b96f0d76cd46c9d0199754351e5b21db7a26840fa7bd1547690e413851ae69577f162e76e4c3282f945d9ef6c4d76ecdb1c0e9fd72ed7c57ea063f462a4d90ad29d72a8dbd26ced1b281c0b9b784bf4ddb9fdbaeeb41d75d80884ce33e17f158f333c21f1a4f272fd7aa1a8e67abd96da0ef03426db1f21deef976c9b15db645b402aa79a7a5a71e020366dd9b785a44c31bce76f5e8e1158eb10bd2e0fccc87f4cfd8802c0845c45e7eb24ee9e92776a37a0d4c7a7ec5f491095efb44aa28c5be58f5f23df7178f6f21d43c5cb77d42a0faa8a8ad7237fceb523cbd7faa6549d7b563867cac25842394c981c2b8df6aca015f6ef961045e2f05018fb8961a47e0fa2eef9d5a728b7c2fc3e3679db596a58c95b555698a05632d29ab4958b5005ff9d92b64252ad7bc34887aa2551c628a8cc21aed40bac1f27272b0ca3dd41753a925fb50e2f2f5dba1735eab9076fc83d7812ac413f16f72cdcd8f0b4bdfba1abd4fa9367d30eeff4e8d9eda03bcf9d2bad3de50e50fb1d1fcb0d9b392b916fa66ff4ba07fdea2e72907e53e777476fd894d24e53d0eb09f80d66e38b4bc0ae955f89ccabf582272960dea135fa3965797b6a97c207eabac1fe5aafce8bde5f7bac465690ea4270ec72d8d7f7908600a8812bc22999d0059c4288d619e4a2ab857d913da5332a85ba9439296557be4b5d28f6ae23188732741e471408caeb35Line truncated
|
||||
gr, _ = gzip.NewReader(bytes.NewBuffer(bs))
|
||||
bs, _ = ioutil.ReadAll(gr)
|
||||
Assets["app.js"] = bs
|
||||
@@ -28,7 +28,7 @@ func init() {
|
||||
bs, _ = ioutil.ReadAll(gr)
|
||||
Assets["bootstrap/css/bootstrap-theme.min.css"] = bs
|
||||
|
||||
bs, _ = hex.DecodeString("1f8b080000096e8800ffecbd5bb3e3369220fc3ebf825d0e47b95c928ad4fd123e5fcfd73331d311d3f3b2fd3011b6778322a923b629514d5275f159fdf7c59548241224a53af6ec46f4d46efb084824129909642209243e7cff877f0abe0ffeffb26ceaa68a2fc1c7d9249a84c177c7a6b96c3f7c78ce9abdae9b24e5e91d87fe5379f952e5cfc7269886513466ff330ffefa296f9aac1a057f3e27130ef41f79929deb2c0daee734ab82bffcf9af1269cdb1e6cdf1bae7f83e349ff6f587b68b0ffba2dc7f38c53543f5e13ffefca77ffdcffff1afbccb0ffff44f8cd2e05c56a7b8c87fcd26495d73524346eaff16b85577ec17433ec9cb0f2d2c6b7d6c4ec5cba13c37e3437cca8b2fdb3a3ed7e33aabf2c36e7caac74df6b919d70c761ca77fbbd6cd360ac36f77e34fd9fe97bca16b6ffb32fdf2728aabe7fcbc0d6f71d5e449918de23a4fb3519a35715ed4a343fe9cc497262fcffccf6b958d0e6ca48c4bc72c4ef97f9eabf27a199de2fc3c3ac71f47759608e0fa7a6298bfbca4797d29e22f5bc695e4975b7c4df37294c4e78f713dba54e57395d5f5e823ebb06c21f373919fb3b168b0fb9871aae262ccf8f07cdeeee33ae3b512d1f65c36dffd9830a6546551fffcae45712ecfd9ee9871f9b281fd78ccd3343bff3c6ab213ab6e320bee16bfece3e4173e8c73ba65123cd797b8cacecd2ddec66c2c1f1947b6c79211f2525e1bde39e7d57e5ffdd8e44d91fdfcb22f2bc688f1be6c9af2b48d2e9f8394fd99a5b7fd882944797e9662fb24c9d997457a4b0f675958375f8a6c9b376c74c9ed18a94226a7ed343bedb46826cb55760ac21bfbfd0b24f69bc321dc25655156db6fc230bcd54c5b0a8063cd645c5f1919d70b285d2dbedd090e6b06ed2e659d73a16dab8cb1878dd8cb768ea9292fdb71385964278efc458d9b954c79517e7a561c616caa3f3e0b196d2ba633ef5e38130f45f9692b0572930aa5353062639c8797cfb763f5323e95bf328e7ee614e7e7e72d973113092fda798a5b715f18cab6a7f8da94b7a4640afdcb3e651a978deaf874b126d2a93c974ce449360ada3f77865d8cacdbfecac6781ee5e7cbb519959746ea3ce30953f6119f5b4c61e2172989fc7c6493b21118da1fed2493980c7d1ff33adf1799ee41a27c11d355a8e2812d01524d15045f070241c88fcd974bf6c31b59fee6e7112c64d32a6b501913d62967852f7a51882f972c669d24d95622d925d7aa6643b89439e36ba5bafc91cd9698d198fe0c3b6f0b5f54a3343bc4d7a2518db65b21c243995ceb717e3eb39542b473cb5b6dd95de234e5520d6f02f4052aa95c0a6f703cc9314b7e6192c7438fd9caf0864fcb564dda19fa19f7a1da9cafa77d56bdf99951a77823481bd797fc3c86c2f7c2b3a5c1867f51840b05b4c4c0789e1c693170b91ff2ac48775d134037bc6b7e903418fa65c938e16414d490bd4dd22c29ab982f1fd48884ea8a213185d4a2e66b645d16791a7c9384fc5f3b3f82e905c868325bf0756fb29ccaffaef8025364cfd939a5b4a69d88f6ecd7f3d55d861baec17afd66b3b7882f75b6d57fec54055f105407e9a839be980eff78cad23c0e2e159b2e2fdfcb595b1fe394f5ccc71dfc213f5dcaaa89cf0d58a561296d782c082e4c12e52d6676892f1fccd4c8ae8d24b6c2619186f2c763951d7edec607a6a02f4a21b66f82efde0471d354dff1da77c19b776fa04df3428b6a052e10ffcf1fdefc2d66c63ca9f20b03542d476de5376f1c646ff80a3d12e6fdef57e64a105ab1d96c985c9f9913c0c4f90b9b8cdc25d9c61fcb9c098d3b1ead0517221c4b5f642cc47c6bd852c38c90af3daf3bc59fc79ff2b4390a3f0832f5323a4e47c7d94b595d8e4c20dbd98ec1959fd81f375901d08a7129ac6ae1b68df301629e30ef681f57b6ef3111f4074cb1f45f478063acb40663da37e7a749c274a5194dd2aabc5c2f4fa04c2b34b3d36352ed6e9322de6705c177ee444cba67858547725f823237b9398e9ca294e8264d5388e6f6fd0bb1a481451b2f86a08a2cbd7dbfdd67cc7266a3ef95f2bd327ee38c0b1761399d2c80af1d5fc647b6c8147ca15112a89ef7f177e148fc7b27fd6ee882bcf9f7acf898718f2bf8cfec9abd19b5bf47ff5ce5713102ce3ef04c166cb18446329acca7ebc52a9a4f377ac199cd663b52a1a43d18597e8771652071d0a1911deb12d8b72abb6937e81b46ca3e89777865922eb774a8d902261c01dd641a2fe79ba5d3042c660a5e3be2cd313f2b6f7ba7cb185302beee075a1ed2d7606bf4b31cbe861c978703334adb31b339c8150dc52a819ce013735a99a736615563e65f5d4ab6aa7cccec0dcece5e5976d009900db918323d29c6dc59b9d6db25a34054b33de5697f661bafd6cacc3b644c0a7647ceb79ddd21c7daea2bb73cd2ff67db876032ad838cf9fb6cd5e45ecdaea79adcb5f57121c9abc4ac318aa605dbad30d75f8a80af5edb291b83720df4f64a14b5b6dfac7470b859c6a45457e3f25c7c7969f736f19e55332f6da708bbb45b06d3cb761c41ff6387362cbba4c82f6c9394346c2e07eaffbd6bc9611b38693d46c7f9e8b8181d97a3092b9ab0b2092b9cb0d2092b9e1c97fef9a5dc93451822a9473b6b7bc1fa0ac4768ff5a8ff98e93fe6fa8f85fe63a9fe98b4cd266dbb49db70d2b69cb44d276d5bd674d2763969fb9cb49d4eda5e276db713d3efc4743c313d4f4cd713d3f7c4743e01bbda4f70336033482f78cc75b809a60b594ca43c58473d7a15b10d2ddf7a460ea3009f1c4e1bd6c1f1117c9a502c33c387b664c166c15c288bd015a5464b48bf24d63382b9234c204b4221960116e08492e58416ebd21dc18a8f40480014ce369c36211058ca975e251f10fa588a71703a406924300896bcd836f0a638044a67acf4d2aee6411828ee4c0aee3c124b0a68bbd23f95b64d9db938d79eff77278646ae27abe5faf2f9dd8bec008c652afabd297e39111ac6ab8479f0301aa4b6ba1361068beca0c201d208f1dfaa4a842f619d28509549c677f0b05696a86a1e03cc0f5f60bd2a5200a72bdf568039258bd9564744f52c1b7f8bad4a152cd30e48b88a62ddbcbe264956b7f67e96ac96b35437579576f3e97e319f26aa797e3e946ddb6815ae0fba2daf410de78be952f7fb29aece6c45d775eb7899cef6baadaab49b2f978ba8ed378dcfcfa62adecce7f3a96e2debecc6ebf96c319b333ffd19334cd867c76ab76c340d14421756f393816a6eba40e9e110a66b89d066ab0b9b44d9743f1308057f096c9b2c3dac2436c06817303e30d04ca0d21c275c94e4b0ce66129bcd7a02769525fb8540a86440c04c993f95497c96305cd06cbedfec19efc41e4eee19b59fa517830d5859b773b63cb1b503f81c30ca0bbc8d6b312a0bb84287f4e27c2d0201caff97fd5d8abf4d4b05ccf660455e37e3eb592c08694b239ffc5bbe18d566ade09b4851201db07bLine truncated
|
||||
bs, _ = hex.DecodeString("1f8b080000096e8800ffecbd6d8fe3389220fc7d7f85a71a8deaeab2d5925fd3363a77f69905761778e6ee809b0f0b74f71d645b4e6b5ab63c925c2fedf37f3fbe33180c4ab22bab770e98aa99ae4c32180c460419c11019fc637e3c975533b854c5776f7ef8615f9e9a3a7a29cb97224bcf791d6dcbe30fdbbafee77d7acc8bcf3ffef773767aff3fd353bd9ac671dea445be1d2ecc4fac8cfff6e6ddfa87effff04f83ef07ff5f5936f5c7b4d91e061f26511225ef135efcefe5313ba72fd96a70689af3ea871f36068e77c841fe549e3f57f9cba1198ce3643c62ff990efe72288f693df81f69f52b07f9fff36d76aab3dde072da65d5e0cffff117d165ca8bca93ecbba9d2f33f7dff032367702aab23a3f2b72c62e3e1e4c4513cf83fbc99c6c47e7bc99b282f7f30b083ef7f3834c7e2caf932923c58d56cf8a33aabf2fd7a74ac474df6a919d50c7694eefe7aa99b5512c7dfae471fb3cdaf7943d7de36e5eef3f598562ff96915dfd2aac9b745364ceb7c970d775993e6453ddce72fdbf4dce4e589ff78a9b2e19e8d28ab86872cddf17f5eaaf2721e1ed3fc343ca51f8675b615c0f5e5c8307fbeeef2fa5ca49f579ba2dcfe7a4b2fbbbc1c6ed3d387b41e9eabf2a5caea7af88175581ac8fc54e4a76c241aac3f649caab418313ebc9c561bc6565e2b11ad4e65f3dd4f5bc694aa2cea5fde1914a7f294ad0f19171c1bd84f877cb7cb4ebf0c9becc8aa9bcc81bba5d74dbafd950fe3b45b31499dea735a65a7e696ae5236960f8c23ab43c908b996978677ce79b5d9543f35795364bf5c3765c51831da944d531e57c9f9d360c77ecc76b7cd9009be3cbd48b17d94e46cca6277dbed4fb2b06e3e17d94aeaeded90a84226a7d5383baeb568a2f9223b0ee21bfbfd5748ec37fb7dbcde964559adbe89e3f856336d29008e2726e3fac2c8b89c41e962f6ed5a705833687d2eeb9c0b6d55658c3d6cc441b6734c4d795e8de268961d39f2ab1a372b19f3a2fcf8a238c2d8547f7811325a554c67de5d3913f745f971250572930aa5353061639cc6e74fb743751d1dcbdf18473f718af3d3cb8acb98898417ad03c546dc6786d2f4945e9af2b62d9942ffbad9318dcb86757a3c3b13e9589e4a26f26d361c981fd7965d8cacdbe6c2c6781ae6a7f3a51996e746ea3ce30953f6219f5b4c61d2ab94447e3ab049d9080ce61733c924264bdf87bcce3745a67b9028af62ba0a55dcb32540aaa982e0ebc04010f253f3f99cfdf84696bff965080bd9b4ca1a54c68475cc59e1552f0ae9f99ca5ac936db69248d6db4b55b3219ccb9cf1b5525dfec4664bca68dcfd023b378557d56897edd34bd1a846ab9510e1bedc5eea517e3ab19542b4f3cb8db6accfe96ec7a51adf04e8152aa95c0a6f703cdb43b6fd95491e0f3d652bc31b3e2d8d9a9819fa09f7a1da9c2ec74d56bdf98551a77823481bd5e7fc3482c20fc2b3a5c185bf2ac285023a62603cdf1e683170b9eff3acd8addb26806e78d7fc2069b0f4cb92d196935150430e36d965dbb24af9f2418d48a8ae181253482d6abe46d66591ef06df6c63fed7cc8fc1f80c64144d667cdd8be663f9ef822f3045f6929d7694d69889e8ce7e3d5ffd65b8e11aacd76f367b8bf45c672bfdc35a55f0054175b01b3687abedf08fc76c97a78373c5a6cbf57b396beb43ba633df3710ffe20bd9af4d480551a96d286c781e0c22451de526697f8f2c14c8decda4a62257c1169287f3a54d9fe9755ba670a7a550ab17a33f8eecd206d9aea3b5efb6ef0e6dd1b68d382d0a25a810bc4ffebc7377f4d9931df56f99901aa964353f9cd1b0fd91bbe420f8579ffdb85b91284562c97cb35f7cc461b26ce5fd964e42ec92afd50e64c68dcf130165c8870247d919110f3ad614b0d3342a1f6bcee987e1a7dcc77cd41f84190a9e7e1613c3c4cae65753e70ff72b26670e547f6c34d5600b4625c0aab5ab85de3bc879823e61d6dd2caf53d2241ff802996fee900708c94d6604c9be6f41c6d99ae34c3685795e7cbf91994698566767a44aadd2d2ad24d56107ce74e44d43e2b1c3c92fb1294b9bbcd61e815ed886e76bb1d4473fbfe4a2c6960d1c68b21a8224b6fdfaf3619b39cd9f07ba57caf8cdf3ae3c245988fa319f0b5d3f3e8c01699822f344a02d5cb26fd2e1e8abfefa4df0d5d90377c4333e01b9a37c33f31976b53e5ecdfd38e2da2c37fa9f2b418026f1fb82633b65a422b9944d3f1d36c914c277ac199883f6b52a7d81f6915868ef7611d1a4822746b64efba0412a0ca6eda19621ab560ddacf1fa241d6fe956b3654cb803b6c96cb999784dc092a6e0b53bde1cf293f2b9d7ba8c7166c057ff81968af438d84afd2239a02147e57ecf4cd36ac42c0f724863b1562057f8c85c57e6af45ac6ac4bcac73c9d616b645889a03f3094e6ccbf4cc6ac0af835416b0a9595e1883a567f11cb165fbd852235ab99ba7b5bb6aada18321c9e1f2cdf4841b7147e852b351884a4390b15fd3b0f284d4654dce65f6678dfab493819b35b9b9607b934134ae0719db4cb0b1729769dd514d6e09bbd8b0cdabad5dc0144533b61562fb0a2959be34aec66c10caefd07b3751641c0bbb8cc2f16673fef716d5d5a83c159faf66ef946e1804f302d78ab6b3d992d88e56a304fa376bb4215a6f8bfccc3661db86ad1503f5bf778622b64194d66978980e0fb3e1613e8c5851c4ca225618b1d288154787f9172e2eca479ac431529064edec71184103b1e76464e91f26fa87a9fe61a67f98ab1f22d32c32ed22d330322d23d334326d59d3c87419993e23d369647a8d4cb791ed37b21d47b6e7c8761dd9be23db7904b6d61fe18ec465905e7597e2cf4d0847c82c9272637d75a860c236d67c0b9c78bc02acf2986db9078748b02aa2b86639006dda8c4d98a9502aa1534adde6907e496c6004534f9e409c844ecc0758861125ce8896ecdc1fc1828f404800144e969c36211058ca177f251f1082998b71703a4069223008965c5d537c531c02a513567a36f664100f1477a2823bb1c4ea03da2ef4af4ae1c6de749cea1dc877478646ae3b8bf9d3f9d3bbabec008c652cfabd297e799122c6ab2d333c302aa5b6dc9130c445b65761096906f9efaa4ac447619d285095db8c471260ad2c51d53c1699ef3fc37a55a4008e17bebd71a795ac61bb2e1160741c8d5bea54aab89d0199cfb75bd5bcbe6cb7596d9c0ee50ea54ea5db5caffc02223fed4bba2daf6969f831ad4e6cf1a7dbaaca96e6bbf4f462abdcd6b28e6ebc79c10c13e6dcb3f3868db6814248c14a7e3250cd4d1f68b2dfcc932789d065ab0f3bde3f2d93b14028f8eb432c97b3e96623b10146fb808b6cb25fee042acd71caa959cc346d2eeb7dd86c3adbf2dd11035532a0f0c5f16429f139c2f041b70cd998b991623b29b7afda31d3ebc1122caeab295ba1d8f2013c141870767d934b312c0bb84ec7f4127d29060294ff97fd5c8a9f6d4bLine truncated
|
||||
gr, _ = gzip.NewReader(bytes.NewBuffer(bs))
|
||||
bs, _ = ioutil.ReadAll(gr)
|
||||
Assets["bootstrap/css/bootstrap.min.css"] = bs
|
||||
@@ -63,7 +63,7 @@ func init() {
|
||||
bs, _ = ioutil.ReadAll(gr)
|
||||
Assets["favicon.png"] = bs
|
||||
|
||||
bs, _ = hex.DecodeString("1f8b080000096e8800ffec3b7b73db36f2fffb5320fc4deae4d7907292be4e953493dae99cefda24132777d7b9e91f100991a841820540db3a55dffd760192222552afdab9ebcc6526164100bbd807f6012c478f2ede9e7ff8e9dd6b9298544c4e46f84304cde2b1c7328f64b14ff37cece979169a8467b18763188de02765869230a14a3333f60a33f3bff1aad78931b9cf7e2df8cdd8fb87fff1957f2ed39c1a3e15cc23a1cc0ccb60cee5eb318b6256cfca68cac6de0d67b7b954a631f09647261947ec8687ccb78d678467dc702a7c1d52c1c6cf83b3353011d3a1e2b9e1326b405a1b440b9348b5d62f78764d14134036749ab03084870825516c36f666f4069b416eb9713232dc0836a939341ab817251c37672aa5d146d17c106a3da85b41cab300de78253a33174c278c195c866d1133cf619d86dd199c8a08a7329a93c509817f398d2240e91b990fc9d767f9ddb7add753698c4cab9ee5c9498070fc546652e7346425941910efcf68cac57c48eace72020591f9406ec432cda289b1c2376a8222d8ecc5b5f5f7ce80eefede1a72b41572676f0d392a699a4a1531e51893c9cc51635110a38849ca61961f54f0381b921014802947b690b12c87a454c51cbacf5abcaddb1683ff65cd7aa939aadc10250a0a7fe3308f06569a20d581db3d27232b461012aa9e92423035f6ae2a253a374aa00e44fc8684826a3df6327a33a58ab81f7fc6ef5884e4552f2236a38540c5c16534272202ca33a6ca3edb4fdb60fda9a259e44d463c8dab1ee48147b40a51317d6cf9cf5f7c63d59eb80de9bd7c019b82f13831f67942ae56bb8036b0e16a80540e3be1112c67c6e3cb0c87365664c7cda44ad716665f95cf0a31adcdb1f3a605287a56ee15d7f02a38539311f8efe78a8328e7d6a6858287d7634f316da8324f9e7a93f7ee91bc91b7a38183b0b6b601ae64ed5dbeb65854a7b5c57e48187124178aa26690846a32652c43db99c52c22800e74d4101a82be50c3a260c5479216da9072a1a06cf520d061463276db061e8c067983ef03607ca910eeb1fc39d9a61fcd3e256fbd3539d6b3849f46a011eb326cc89a2925d50f5c038703c1b218b6dd849cd59201bb0d34d9bffe2d5599732f1bc2cd119c6239a3c68204cb4f1a904169754a85982c16f036f8c053467e2311b068e825c9304d875a071a4ce77239846d688792c562a638cb22317f23c1513cc199af11e6d3e5b2c5c2bdd52c2f8470322795c6553435342e148c2a8b48e3cadffeb547d99a8cc629b0dd81ce9538d724dc3b39a71913c4fef57936935dfc5d1feea385b2b218252fdb3dd6b3799373014ac914d8b2975d8bb250ad89ae66bbc69ad5ee588b9b694d7d77df23df27e95c333123bedf375fd568adb72b6047794d1dca40e4e7b318f508f698460d4061744273102362cd7719880c9fbf78bc65b89d022e34ab0d299d320caae0ef9a99de1b442ce679825107a99f7c798d2a81a326e403d04190aeedab72a3fb091d98e810369c1dc48676ece1c17ec505bf8138ec492911bbf9ee75892f70898bc50d531aac23823f6cfa9730fd89a998fbf4c0e97f7aecb588eff35fcd7f8b05cfa6b906130661aae2e17209ad43998c2a4fba74264cd88d82df48de66b5f6dc17b38f235716e6e1e92df27ba7f6eb23a8edf6202bf7c0226eac39aa36c4461453da0ffb7ca7d1f7edb01239cb422e5696e235a0e8763afbf1027ad416e30cde9548084d94dd307aab95ee36c976b6f3ca3b8cf29126d8d99d73ec68189efbb0c80ef2253cb60057ac77dd57869aa289f9614df67f9d812ec1fe8da916d4fd66bd8aa283a61dbe43e9740af921c639636fb10051662cc4c85affb3441ba06e5e5efc1c5c66dfcd0dd31fa4a102ccd79467905e2c97df21e3b6cdebb0ef902d01da8345f5c9ccfc0372f16d618e636397df78283ede8ffbf89fb76831648b9c70c3ef36097f9811f724f9edc26d28068da22aa9d92d71c8e556f206fbfa40e21ef4a475d0816961675adbd16c26bc071d547cd5754ef1a059f27b660f03a59a6f4d943700239ffa72e3bccabd49796aa321aa4841d62288859c52f13d170c8d2215b774aedf14e994a9e592ccf0f5b3b5b1d6ee364d6e37ce6e7b0979d1e76d70174c3034a41bc823db41140ba58af4d352d7ec314b1f953fc810bc81aa39680fcd2a74023bf723d40ebd373a2db463c8dcc0d57b92d3d73c42a14b8b605f2c4e9d6ee9220c99d6a778ce8f14658c458e3de3f1989c3d23e5b8f2b0b463dc231cd7152d1fb143f0943301ffcaff650f2fef6f9b34072b192b666f4eba86f60df7a7547944490c60aa77f615559cfa3754142c93b763efabb3e6ab946763affd86de8dbde76767de567bdf12546305fbc8ab391c8d57bfcc762da14c6f172ebf254f60d9e4ff4b60dc9ed73b7003b261459e92cfc9e9e3d35d59d4627100ccb51d06cdcc3e0ccf96cbc75b9c53a7feeceab287cc3a4191ae730f8fac276fa0595b15ecdbcffeaca034cccfef37097f202f38a2e515a88767f2d437328e51cb604182e69a55afa98af11af9fff41cdc5b8ab6017ff11a69a759e0115e50db69ed255438488d6c0f7bb1cbb8387581e4c4a10ce0a7295cf2fed58f780a02ae02bc046a4239cebe6b8de4192934ebbd6e584714e6c53ba6f096b263675053282a86cf616b90f3771f1b7863a92055e25997b6aefafa2f3d7a18ff293cd87f5e199901eec4fa0386a8a09365737fad6ccdff54ca69af4c9debc2c75db946033e0ef763d089bc75615292810a5b51b4cf7159e326b09c16604203ae8b9c6280754a7efb8d6cf438237fba07028bc49decc1c2f1a0a102c6233c775bb56d2d081e17d9d17b42e6598e951fd106e016b7caeb7bafccd55643b18d838103d617d88bd6198f83b7b93bd058c1fc1913308b6e0faef63bb10de657db2d61e1f554de79bdd2984a290ee3f87e63f1df8614b671d631b1b5e0fb649e5dffbe4ab007a7770ce9aa19d863eae68ec7f29656fdc6c6947d0e0c74da3c37681e18687ac32ae386a70657d0dee31cc05da6f7264ee7b6be411343af1961b3190b0db94d58569533a049a9cba6823a5f72501fcc196da9846897d854e72bad8a1b5752b56f954d577dc8da7d64b35ca3108df115dec663d7d1d148f0c946350f569e55e56a588a371c00b53a9485d22c58b13c636600c22e722cb78310fc7ba98a32e402a887a3d18027e62629a64128d30124cb6932a8d10d1424c85433f01d3f406ca40d79ef5e3c1cc65b7ecdbdc9850c8b14c2a632c97c28645ceb0289fbaea8228407c002e20229868c9c8359dcc4321a14a2d9cafb751ecd2f28c0ad54d7b620a5361760702978541ab10e35b79d7ec4a990714faae1869415955b423c370e633608619bb540119a8d2e6b374abe684f2ec3badde7395d279fec0e3a53ab14bee6f18e8b92f3fa2a8258767518a1e48bad36a89bfe9e606ed4118eaf8ac23463a9c66ab0292378Line truncated
|
||||
bs, _ = hex.DecodeString("1f8b080000096e8800ffec5c5f73db36127fcfa74038d3369e3325db497a1d47d64c62a757cfb549264eaf77d3e90344ae44d420c102a06d9dabfbecb70b90142951b6e43fa993f6c11649000b60f787dd1fc095068f8fde1e7ef8cfbbd72cb1a91c3e1ad007933c9b1c0490052c9b843ccf0f0233cd229b886c12501de0f1f0116383142c6751c2b5017b1014761c7e13cc0b126bf3107e2bc4d941f0eff0c797e1a14a736ec54842c0229559c8b0d5f1eb038827d06897f1140e823301e7b9d2b651f55cc4363988e14c4410ba9b6d2632610597a189b88483dddece92a0184ca4456e85ca1ab296aaf1c2264a2fd590223b651a24aa008b6d54582622929468181f04637e46b7bddc69861a5861250c6b7d0dfafe412dcbb71b29658dd53cef47c6f4ebbb5e2ab21e3e09ca2eed54824900ac1f8cbb67769ae3782d5c586aec4a181ba978ca2edd2563398f63ec3b1c296b55bacffebe935fbc28cbc638bf70cc5321a7fb2cf80ee419581171f6060a08b659fd609bbdd4a8d86d66786642035a8cbd88d923f791ec6eb3640fff9ee2df33fc7b8e7f5fd743b87537a588731093c4eeb3a73b3badee796f64b3ba3752461843a434273befb34c65d0aa5fc8bf25cfebfa29d713918556e5fb6cb7f71cd256dd9e1397aa4c999c47d03da7ba78a1294778870889183203f1d0bac562f590c0ba5c4a665b5d3a465cac2ead25c7574aee2cad25c7f5ec464ac7a0bd4e96d4e73a6356e3455be95c8a09ea3bc22503baad0aa9266a41e3fb6ce7451ba38d27aee7f0f91caab932c29b1357031af66c41d7b956130dc6d49d242558f676e7424a53574b41640962ccae10545f8523ae6bb1b86e21ec92ed0061c47f0151b4573dae84464a4a9ea3b6c33361c8e9d5f2626172c9a76d35b7dbacd55c6434b205a50b63c34c85a3424ab08d29e063e73e42721fbeeb8586880f59a4d9aa7ec29154d169ad56d4a973c1e85daae5532b5b7b55edce0b463c3a9d68556431f5a2349a74327ab2f7f4eb6db6f76c87feed6ebd680351f3581406577e03101566d006ecd9a28dd136f8b861878579e16acd7a31478fbfe006248c71b43b733fd09adeeecefc7113f26e922faed7158d63d077bac7d8d9f7c1f3d1c0396cf4d1146f34da1af4417052458d43ab65194f1e8721fba07246800c43ff2ce3672c92dc9883002fa9c47fd0e2ad2e6318f34262f844e1e0ea8989738e65c018c4a2164263e0386c5d9651a84165b5fb08479a6771301c88745295d0120f98d111c5aa90eec2ddbd6f5c34643e5a074ff782725dbaeb213b998746eaa4ee7154e00acdcae8e66f82aa1ff2f5f8574dca5d9b94e508720fb66ad658e0484b2445748a142616f604acc5decc932d1c7b735a1339cd138adeacbe426b601c2f07c6aa9683be1f4ea9b83e6ace85e33e76ea0db24297be3e59f05ba18d45539c6f3395c9294332719e3131661944e86eb89ebe60efc158ae2d3be73ac36e2b6b97e271520289c363943f1693e38cd458eb0705cf4dd71a8c0cd3186d5297b6cb719a2099fb1f96dd366a76d40d09beaed62079da2e713c271856b3780310438c787f3aac35b65a2cad8656cf58291f7e4880f9f9163eb0b3841b3602c0c5cccfd04ba25dd09359c6238c0edc42dc9bc38ba505a9bc1c8e5575250a66a8f7f3b6e8dea09fb7c678fda0298836d6cc063846ec36e13cc77113bce5d0d7c2ad1a8fe7b8ad4da0cedbd0ed9a4a2481ebb1b8083accd47ed0ba6ddc94974b60874921d135213617a0dc026d258f1abe0717f2959eba80c59e903f23efbc3597d009f0afd7c077e5106f8def728c02cc6dd05dc8da89526c2e3217216207000d39704b08c8154614469f664180db4f2c3e5a70dc6d1e1b0c2f2f4952ef48688848cbb359db07af1e5ecd289646b172248baaa80371a78815632f704db32ec05b3e77d4eb88a3b85f2be0f868f5cc5dcb45937e8c19252a858da7e4198929228a220e3b1459fc7efd1d68a2e57c024fca596fb18303e433b8473ece9ca3bc516fb916489ca6aeb744c4707d6fd41579e42797972baace665f6cddc822837e37f6fe00484ea41a6d6e410265aa62903f97baf8a54782b8fc56e0de9ffdceb83ce753f3a64847a0673336a6c7db6c45a35753eb1a8d44c6697dbffa3c60dea12424d81bebc8b5b91b153d20dc455215711823a1948ac777a1db0cb9db86aaa5260f1f7c4d7abfbe7e06bc3cb55bdc5a1017702e6c1d8a96033a41396769af51c0a0cfaf1cce86f01bf40bb9c412966a2ed6ba17a6dbd89a7593dea62e715bef54b9961a6561e64a7c19c70dd678df6cb7c955df20fe1b2cd54df501d1541adea6fcb4adb5e4f9f01d806695a4e73720b019b63d1c4f88c32adc7569278bcc7c07549664bfe1293c293bd9fa84d92cbd19b891e3a6b9e31ad06b28c1c9f8239c6ecc4d32525c6f1e9a3cdff4b33ca4c78d6956b33fb1dc16e6b6f3ffbcc2398ac970872754667e2e15d3a3a547815a64a39c82740a568b6836c3bb078718af8222bf1705a8c2de8d061e10666eba1b26ddfc0b1eb4f7b863ca4628a8a7fbe9b1b6a510fd2111c685e8db47688ba29c7aee3b3e7f09a9c95f7c7a51da26375a64666a2ca43dfc68ee8dd8fb973f3cb8c566b93935b799649417e5e9cec2d6116f330cd49acbfdddd9ec0b76f8eec74fdde9de41a0fe5304e3cf31e0fe1595ba6b3d88b3842a88dde02cc147d28f708ae0affd5142bffd8a8c1ebdd65a69d3fd0a18a8ec7b8c904fb67a12b2894dd890ed3cc477c16f941511dcea1d7093abe0c489a734e64f364eb994e865f069ef834801fd0c2e36d80f92643f4df78de9196382d96c1fcdecaab2cbcbb11690c572ea8f23a8a5d3b76328f7ff127823383ba87934d074dffef3e3bed16dc1b44e6da81351e8f12b9759b55e7e4af5c2bbbcc541425ca666b144c43164e185592f41255fc84e21874dd1e60cb4c17d5fcb940d6649432b5b342efdbbf78662d0cfa1b36ef7e00e694a074eb9adfb7d548e8954a10df4ea84cf5e06b61f0c4f8a9cb257599f7dab74917ae7dcf49e2bbba81461d26667067b9b089b14a35ea4d27ec4659af4eb4efb1ad0e8065077df23f88d65effd830dfadda0b773712a82e1918a8a94dee3d13efbbe27288c29687aaf0acac7b9d7bed07868d308d8a10b06edbee601af2b0fc81d0c833d57fad4bb2996aa98cb7a6110a4458c23f475dcbaaefd82af3ae63174ac005718c6824b35e974efbe4299bdbcc2c5fb3ae4b6710d7309884ff73f8c793659706283e459bb59e9d3db6ee7ba080b1758983a8484464cb26ed274581fd7f8c0d7f258c9b3150eab6b6e4b316490b7bb9aa70719c06d28e5058d801189df668ad25b4103c32d3567b9562309293b47a0b02922821d538e2b9a8ecd8f977a2de1ef91e04e51f6970948295a5bdc5660b9c6efb61c70fdae8178e24a4055247273307981a1bc1b54b5757f5514c46d85c1e11231c6919854d4a202Line truncated
|
||||
gr, _ = gzip.NewReader(bytes.NewBuffer(bs))
|
||||
bs, _ = ioutil.ReadAll(gr)
|
||||
Assets["index.html"] = bs
|
||||
|
||||
+162
-98
@@ -7,7 +7,7 @@ var syncthing = angular.module('syncthing', []);
|
||||
|
||||
syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
var prevDate = 0,
|
||||
modelGetOK = true;
|
||||
getOK = true;
|
||||
|
||||
$scope.connections = {};
|
||||
$scope.config = {};
|
||||
@@ -16,35 +16,40 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
$scope.configInSync = true;
|
||||
$scope.errors = [];
|
||||
$scope.seenError = '';
|
||||
$scope.model = {};
|
||||
$scope.repos = [];
|
||||
|
||||
// Strings before bools look better
|
||||
$scope.settings = [
|
||||
{id: 'ListenStr', descr: 'Sync Protocol Listen Addresses', type: 'text', restart: true},
|
||||
{id: 'GUIAddress', descr: 'GUI Listen Address', type: 'text', restart: true},
|
||||
{id: 'MaxSendKbps', descr: 'Outgoing Rate Limit (KBps)', type: 'number', restart: true},
|
||||
{id: 'RescanIntervalS', descr: 'Rescan Interval (s)', type: 'number', restart: true},
|
||||
{id: 'ReconnectIntervalS', descr: 'Reconnect Interval (s)', type: 'number', restart: true},
|
||||
{id: 'ParallelRequests', descr: 'Max Outstanding Requests', type: 'number', restart: true},
|
||||
{id: 'MaxChangeKbps', descr: 'Max File Change Rate (KBps)', type: 'number', restart: true},
|
||||
{id: 'ListenStr', descr: 'Sync Protocol Listen Addresses', type: 'text', restart: true},
|
||||
{id: 'MaxSendKbps', descr: 'Outgoing Rate Limit (KBps)', type: 'number', restart: true},
|
||||
{id: 'RescanIntervalS', descr: 'Rescan Interval (s)', type: 'number', restart: true},
|
||||
{id: 'ReconnectIntervalS', descr: 'Reconnect Interval (s)', type: 'number', restart: true},
|
||||
{id: 'ParallelRequests', descr: 'Max Outstanding Requests', type: 'number', restart: true},
|
||||
{id: 'MaxChangeKbps', descr: 'Max File Change Rate (KBps)', type: 'number', restart: true},
|
||||
|
||||
{id: 'ReadOnly', descr: 'Read Only', type: 'bool', restart: true},
|
||||
{id: 'FollowSymlinks', descr: 'Follow Symlinks', type: 'bool', restart: true},
|
||||
{id: 'GlobalAnnEnabled', descr: 'Global Announce', type: 'bool', restart: true},
|
||||
{id: 'LocalAnnEnabled', descr: 'Local Announce', type: 'bool', restart: true},
|
||||
{id: 'StartBrowser', descr: 'Start Browser', type: 'bool'},
|
||||
{id: 'GlobalAnnEnabled', descr: 'Global Announce', type: 'bool', restart: true},
|
||||
{id: 'LocalAnnEnabled', descr: 'Local Announce', type: 'bool', restart: true},
|
||||
{id: 'StartBrowser', descr: 'Start Browser', type: 'bool'},
|
||||
];
|
||||
|
||||
function modelGetSucceeded() {
|
||||
if (!modelGetOK) {
|
||||
$scope.guiSettings = [
|
||||
{id: 'Address', descr: 'GUI Listen Addresses', type: 'text', restart: true},
|
||||
{id: 'User', descr: 'GUI Authentication User', type: 'text', restart: true},
|
||||
{id: 'Password', descr: 'GUI Authentication Password', type: 'password', restart: true},
|
||||
];
|
||||
|
||||
function getSucceeded() {
|
||||
if (!getOK) {
|
||||
$('#networkError').modal('hide');
|
||||
modelGetOK = true;
|
||||
getOK = true;
|
||||
}
|
||||
}
|
||||
|
||||
function modelGetFailed() {
|
||||
if (modelGetOK) {
|
||||
function getFailed() {
|
||||
if (getOK) {
|
||||
$('#networkError').modal({backdrop: 'static', keyboard: false});
|
||||
modelGetOK = false;
|
||||
getOK = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,40 +66,22 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
return a.NodeID > b.NodeID;
|
||||
}
|
||||
|
||||
$http.get('/rest/version').success(function (data) {
|
||||
$scope.version = data;
|
||||
});
|
||||
$http.get('/rest/system').success(function (data) {
|
||||
$scope.system = data;
|
||||
$scope.myID = data.myID;
|
||||
|
||||
$http.get('/rest/config').success(function (data) {
|
||||
$scope.config = data;
|
||||
$scope.config.Options.ListenStr = $scope.config.Options.ListenAddress.join(', ');
|
||||
|
||||
var nodes = $scope.config.Repositories[0].Nodes;
|
||||
nodes.sort(nodeCompare);
|
||||
$scope.nodes = nodes;
|
||||
});
|
||||
$http.get('/rest/config/sync').success(function (data) {
|
||||
$scope.configInSync = data.configInSync;
|
||||
});
|
||||
});
|
||||
|
||||
$scope.refresh = function () {
|
||||
$http.get('/rest/system').success(function (data) {
|
||||
getSucceeded();
|
||||
$scope.system = data;
|
||||
});
|
||||
$http.get('/rest/model').success(function (data) {
|
||||
$scope.model = data;
|
||||
modelGetSucceeded();
|
||||
}).error(function () {
|
||||
modelGetFailed();
|
||||
getFailed();
|
||||
});
|
||||
$scope.repos.forEach(function (repo) {
|
||||
$http.get('/rest/model/' + repo.ID).success(function (data) {
|
||||
$scope.model[repo.ID] = data;
|
||||
});
|
||||
});
|
||||
$http.get('/rest/connections').success(function (data) {
|
||||
var now = Date.now(),
|
||||
td = (now - prevDate) / 1000,
|
||||
id;
|
||||
td = (now - prevDate) / 1000,
|
||||
id;
|
||||
|
||||
prevDate = now;
|
||||
$scope.inbps = 0;
|
||||
@@ -116,28 +103,23 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
}
|
||||
$scope.connections = data;
|
||||
});
|
||||
$http.get('/rest/need').success(function (data) {
|
||||
var i, name;
|
||||
for (i = 0; i < data.length; i++) {
|
||||
name = data[i].Name.split('/');
|
||||
data[i].ShortName = name[name.length - 1];
|
||||
}
|
||||
data.sort(function (a, b) {
|
||||
if (a.ShortName < b.ShortName) {
|
||||
return -1;
|
||||
}
|
||||
if (a.ShortName > b.ShortName) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
$scope.need = data;
|
||||
});
|
||||
$http.get('/rest/errors').success(function (data) {
|
||||
$scope.errors = data;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.syncPercentage = function (repo) {
|
||||
if (typeof $scope.model[repo] === 'undefined') {
|
||||
return 100;
|
||||
}
|
||||
if ($scope.model[repo].globalBytes === 0) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
var pct = 100 * $scope.model[repo].inSyncBytes / $scope.model[repo].globalBytes;
|
||||
return Math.ceil(pct);
|
||||
};
|
||||
|
||||
$scope.nodeStatus = function (nodeCfg) {
|
||||
var conn = $scope.connections[nodeCfg.NodeID];
|
||||
if (conn) {
|
||||
@@ -182,7 +164,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
if (conn) {
|
||||
return conn.Address;
|
||||
}
|
||||
return '(unknown address)';
|
||||
return '?';
|
||||
};
|
||||
|
||||
$scope.nodeCompletion = function (nodeCfg) {
|
||||
@@ -201,7 +183,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
if (conn) {
|
||||
return conn.ClientVersion;
|
||||
}
|
||||
return '(unknown version)';
|
||||
return '?';
|
||||
};
|
||||
|
||||
$scope.nodeName = function (nodeCfg) {
|
||||
@@ -211,11 +193,15 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
return nodeCfg.NodeID.substr(0, 6);
|
||||
};
|
||||
|
||||
$scope.editSettings = function () {
|
||||
$('#settings').modal({backdrop: 'static', keyboard: true});
|
||||
}
|
||||
|
||||
$scope.saveSettings = function () {
|
||||
$scope.configInSync = false;
|
||||
$scope.config.Options.ListenAddress = $scope.config.Options.ListenStr.split(',').map(function (x) { return x.trim(); });
|
||||
$http.post('/rest/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}});
|
||||
$('#settingsTable').collapse('hide');
|
||||
$('#settings').modal("hide");
|
||||
};
|
||||
|
||||
$scope.restart = function () {
|
||||
@@ -224,34 +210,34 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
};
|
||||
|
||||
$scope.editNode = function (nodeCfg) {
|
||||
$scope.currentNode = nodeCfg;
|
||||
$scope.currentNode = $.extend({}, nodeCfg);
|
||||
$scope.editingExisting = true;
|
||||
$scope.currentNode.AddressesStr = nodeCfg.Addresses.join(', ');
|
||||
$('#editNode').modal({backdrop: 'static', keyboard: false});
|
||||
$('#editNode').modal({backdrop: 'static', keyboard: true});
|
||||
};
|
||||
|
||||
$scope.addNode = function () {
|
||||
$scope.currentNode = {NodeID: '', AddressesStr: 'dynamic'};
|
||||
$scope.currentNode = {AddressesStr: 'dynamic'};
|
||||
$scope.editingExisting = false;
|
||||
$('#editNode').modal({backdrop: 'static', keyboard: false});
|
||||
$('#editNode').modal({backdrop: 'static', keyboard: true});
|
||||
};
|
||||
|
||||
$scope.deleteNode = function () {
|
||||
var newNodes = [], i;
|
||||
|
||||
$('#editNode').modal('hide');
|
||||
if (!$scope.editingExisting) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < $scope.nodes.length; i++) {
|
||||
if ($scope.nodes[i].NodeID !== $scope.currentNode.NodeID) {
|
||||
newNodes.push($scope.nodes[i]);
|
||||
}
|
||||
}
|
||||
$scope.nodes = $scope.nodes.filter(function (n) {
|
||||
return n.NodeID !== $scope.currentNode.NodeID;
|
||||
});
|
||||
$scope.config.Nodes = $scope.nodes;
|
||||
|
||||
$scope.nodes = newNodes;
|
||||
$scope.config.Repositories[0].Nodes = newNodes;
|
||||
for (var i = 0; i < $scope.repos.length; i++) {
|
||||
$scope.repos[i].Nodes = $scope.repos[i].Nodes.filter(function (n) {
|
||||
return n.NodeID !== $scope.currentNode.NodeID;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.configInSync = false;
|
||||
$http.post('/rest/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}});
|
||||
@@ -279,21 +265,15 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
}
|
||||
|
||||
$scope.nodes.sort(nodeCompare);
|
||||
$scope.config.Repositories[0].Nodes = $scope.nodes;
|
||||
$scope.config.Nodes = $scope.nodes;
|
||||
|
||||
$http.post('/rest/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}});
|
||||
};
|
||||
|
||||
$scope.otherNodes = function () {
|
||||
var nodes = [], i, n;
|
||||
|
||||
for (i = 0; i < $scope.nodes.length; i++) {
|
||||
n = $scope.nodes[i];
|
||||
if (n.NodeID !== $scope.myID) {
|
||||
nodes.push(n);
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
return $scope.nodes.filter(function (n){
|
||||
return n.NodeID !== $scope.myID;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.thisNode = function () {
|
||||
@@ -308,14 +288,9 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
};
|
||||
|
||||
$scope.errorList = function () {
|
||||
var errors = [];
|
||||
for (var i = 0; i < $scope.errors.length; i++) {
|
||||
var e = $scope.errors[i];
|
||||
if (e.Time > $scope.seenError) {
|
||||
errors.push(e);
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
return $scope.errors.filter(function (e) {
|
||||
return e.Time > $scope.seenError;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.clearErrors = function () {
|
||||
@@ -330,7 +305,96 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) {
|
||||
return str;
|
||||
};
|
||||
|
||||
$scope.refresh();
|
||||
$scope.editRepo = function (nodeCfg) {
|
||||
$scope.currentRepo = $.extend({selectedNodes: {}}, nodeCfg);
|
||||
$scope.currentRepo.Nodes.forEach(function (n) {
|
||||
$scope.currentRepo.selectedNodes[n.NodeID] = true;
|
||||
});
|
||||
$scope.editingExisting = true;
|
||||
$('#editRepo').modal({backdrop: 'static', keyboard: true});
|
||||
};
|
||||
|
||||
$scope.addRepo = function () {
|
||||
$scope.currentRepo = {selectedNodes: {}};
|
||||
$scope.editingExisting = false;
|
||||
$('#editRepo').modal({backdrop: 'static', keyboard: true});
|
||||
};
|
||||
|
||||
$scope.saveRepo = function () {
|
||||
var repoCfg, done, i;
|
||||
|
||||
$scope.configInSync = false;
|
||||
$('#editRepo').modal('hide');
|
||||
repoCfg = $scope.currentRepo;
|
||||
repoCfg.Nodes = [];
|
||||
repoCfg.selectedNodes[$scope.myID] = true;
|
||||
for (var nodeID in repoCfg.selectedNodes) {
|
||||
if (repoCfg.selectedNodes[nodeID] === true) {
|
||||
repoCfg.Nodes.push({NodeID: nodeID});
|
||||
}
|
||||
}
|
||||
delete repoCfg.selectedNodes;
|
||||
|
||||
done = false;
|
||||
for (i = 0; i < $scope.repos.length; i++) {
|
||||
if ($scope.repos[i].ID === repoCfg.ID) {
|
||||
$scope.repos[i] = repoCfg;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
$scope.repos.push(repoCfg);
|
||||
}
|
||||
|
||||
$scope.config.Repositories = $scope.repos;
|
||||
|
||||
$http.post('/rest/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}});
|
||||
};
|
||||
|
||||
$scope.deleteRepo = function () {
|
||||
$('#editRepo').modal('hide');
|
||||
if (!$scope.editingExisting) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.repos = $scope.repos.filter(function (r) {
|
||||
return r.ID !== $scope.currentRepo.ID;
|
||||
});
|
||||
|
||||
$scope.config.Repositories = $scope.repos;
|
||||
|
||||
$scope.configInSync = false;
|
||||
$http.post('/rest/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}});
|
||||
};
|
||||
|
||||
$http.get('/rest/version').success(function (data) {
|
||||
$scope.version = data;
|
||||
});
|
||||
|
||||
$http.get('/rest/system').success(function (data) {
|
||||
$scope.system = data;
|
||||
$scope.myID = data.myID;
|
||||
});
|
||||
|
||||
$http.get('/rest/config').success(function (data) {
|
||||
$scope.config = data;
|
||||
$scope.config.Options.ListenStr = $scope.config.Options.ListenAddress.join(', ');
|
||||
|
||||
var nodes = $scope.config.Nodes;
|
||||
nodes.sort(nodeCompare);
|
||||
$scope.nodes = nodes;
|
||||
|
||||
$scope.repos = $scope.config.Repositories;
|
||||
|
||||
$scope.refresh();
|
||||
});
|
||||
|
||||
$http.get('/rest/config/sync').success(function (data) {
|
||||
$scope.configInSync = data.configInSync;
|
||||
});
|
||||
|
||||
setInterval($scope.refresh, 10000);
|
||||
});
|
||||
|
||||
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
/*!
|
||||
* Bootstrap v3.1.0 (http://getbootstrap.com)
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
|
||||
/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff !important}.navbar{display:none}.table td,.table th{background-color:#fff !important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:15px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:21px;margin-bottom:21px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:21px;margin-bottom:10.5px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10.5px;margin-bottom:10.5px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:39px}h2,.h2{font-size:32px}h3,.h3{font-size:26px}h4,.h4{font-size:19px}h5,.h5{font-size:15px}h6,.h6{font-size:13px}p{margin:0 0 10.5px}.leadLine truncated
|
||||
@import url("//fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700");/*!
|
||||
* Bootswatch v3.1.1+1
|
||||
* Homepage: http://bootswatch.com
|
||||
* Copyright 2012-2014 Thomas Park
|
||||
* Licensed under MIT
|
||||
* Based on Bootstrap
|
||||
*//*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff !important}.navbar{display:none}.table td,.table th{background-color:#fff !important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Open Sans",Calibri,Candara,Arial,sans-serif;font-size:15px;line-height:1.42857143;color:#333333;background-color:#ffffff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#007fff;text-decoration:none}a:hover,a:focus{color:#0059b3;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:0}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#ffffff;border:1px solid #dddddd;border-radius:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:21px;margin-bottom:21px;border:0;border-top:1px solid #e6e6e6}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Open Sans",Calibri,Candara,Arial,sans-serif;font-weight:300;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999999}h1,.h1,h2,.h2,h3,.h3{margin-top:21px;margin-bottom:10.5px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10.5px;margin-bottom:10.5px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:39Line truncated
|
||||
+432
-243
@@ -1,281 +1,470 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" ng-app="syncthing">
|
||||
<head>
|
||||
<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="">
|
||||
<link rel="shortcut icon" href="favicon.png">
|
||||
<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="">
|
||||
<link rel="shortcut icon" href="favicon.png">
|
||||
|
||||
<title>syncthing</title>
|
||||
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style type="text/css">
|
||||
<title>syncthing</title>
|
||||
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding-bottom: 70px;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: 70px;
|
||||
padding-bottom: 70px;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.text-monospace {
|
||||
font-family: monospace;
|
||||
}
|
||||
a.btn {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.table-condensed>thead>tr>th, .table-condensed>tbody>tr>th, .table-condensed>tfoot>tr>th, .table-condensed>thead>tr>td, .table-condensed>tbody>tr>td, .table-condensed>tfoot>tr>td {
|
||||
border-top: none;
|
||||
}
|
||||
ul+h5 {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
thead tr th {
|
||||
text-align: center;
|
||||
}
|
||||
.text-monospace {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: -5px;
|
||||
position: relative;
|
||||
}
|
||||
.table-condensed>thead>tr>th, .table-condensed>tbody>tr>th, .table-condensed>tfoot>tr>th, .table-condensed>thead>tr>td, .table-condensed>tbody>tr>td, .table-condensed>tfoot>tr>td {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
thead tr th {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
top: -5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.progress {
|
||||
height: 21px;
|
||||
margin-bottom: inherit;
|
||||
}
|
||||
|
||||
.progress .progress-bar {
|
||||
line-height: 21px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.collapsed-visible {
|
||||
display: none;
|
||||
}
|
||||
.collapsed .collapsed-visible {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.list-no-bullet {
|
||||
list-style-type: none
|
||||
}
|
||||
|
||||
.li-column {
|
||||
display: inline-block;
|
||||
min-width: 7em;
|
||||
margin-right: 1em;
|
||||
background-color: rgb(236, 240, 241);
|
||||
border-radius: 3px;
|
||||
padding: 1px 4px;
|
||||
margin: 2px 2px;
|
||||
}
|
||||
.li-column span.data {
|
||||
margin-left: 0.5em;
|
||||
min-width: 10em;
|
||||
text-align: right;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body ng-controller="SyncthingCtrl">
|
||||
<div class="navbar navbar-fixed-top navbar-default">
|
||||
<div class="container">
|
||||
<a class="navbar-brand"><img class="logo" src="st-logo-128.png" width="32" height="32"> Syncthing</a>
|
||||
<div ng-if="!configInSync">
|
||||
<form class="navbar-form navbar-right">
|
||||
<button type="button" class="btn btn-primary" ng-click="restart()">Restart Now</button>
|
||||
</form>
|
||||
<p class="navbar-text navbar-right">The configuration has been changed but not activated. Syncthing must restart to activate the new configuration.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div ng-if="errorList().length > 0" class="alert alert-warning">
|
||||
<p ng-repeat="err in errorList()"><small>{{err.Time | date:"hh:mm:ss.sss"}}:</small> {{friendlyNodes(err.Error)}}</p>
|
||||
<button type="button" class="pull-right btn btn-warning" ng-click="clearErrors()">OK</button>
|
||||
<!-- Top bar -->
|
||||
|
||||
<nav class="navbar navbar-top navbar-default" role="navigation">
|
||||
<div class="container">
|
||||
<span class="navbar-brand"><img class="logo" src="st-logo-128.png" width="32" height="32"> Syncthing</span>
|
||||
<button type="button" class="btn btn-default btn-sm pull-right navbar-btn" ng-click="editSettings()"><span class="glyphicon glyphicon-cog"></span> Settings</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!-- First row, only shown if necessary; Restart warning -->
|
||||
|
||||
<div ng-if="!configInSync" class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading"><h3 class="panel-title">Restart Needed</h3></div>
|
||||
<div class="panel-body">
|
||||
<p>The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.</p>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="button" class="btn btn-sm btn-default pull-right" ng-click="restart()"><span class="glyphicon glyphicon-off"></span> Restart Now</button>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">Cluster</h3></div>
|
||||
<table class="table table-condensed">
|
||||
<tbody>
|
||||
<!-- myself -->
|
||||
<tr class="text-muted" ng-repeat="nodeCfg in thisNode()">
|
||||
<td style="width:12%">
|
||||
<span class="label label-default">
|
||||
<span class="glyphicon glyphicon-ok"></span> This node
|
||||
</span>
|
||||
</td>
|
||||
<td style="width:10%">
|
||||
<span class="text-monospace">{{nodeName(nodeCfg)}}</span>
|
||||
</td>
|
||||
<td style="width:20%">{{version}}</td>
|
||||
<td style="width:25%">(this node)</td>
|
||||
<td style="width:9%" class="text-right">
|
||||
{{inbps | metric}}bps
|
||||
<span class="text-muted glyphicon glyphicon-chevron-down"></span>
|
||||
</td>
|
||||
<td style="width:9%" class="text-right">
|
||||
{{outbps | metric}}bps
|
||||
<span class="text-muted glyphicon glyphicon-chevron-up"></span>
|
||||
</td>
|
||||
<td style="width:7%" class="text-right">
|
||||
<button type="button" ng-click="editNode(nodeCfg)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pencil"></span> Edit</button>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- all other nodes -->
|
||||
<tr ng-repeat="nodeCfg in otherNodes()">
|
||||
<td>
|
||||
<span class="label label-{{nodeClass(nodeCfg)}}">
|
||||
<span class="glyphicon glyphicon-{{nodeIcon(nodeCfg)}}"></span> {{nodeStatus(nodeCfg)}}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="text-monospace">{{nodeName(nodeCfg)}}</span>
|
||||
</td>
|
||||
<td>{{nodeVer(nodeCfg)}}</td>
|
||||
<td>{{nodeAddr(nodeCfg)}}</td>
|
||||
<td class="text-right">
|
||||
<abbr title="{{connections[nodeCfg.NodeID].InBytesTotal | binary}}B">{{connections[nodeCfg.NodeID].inbps | metric}}bps</abbr>
|
||||
<span class="text-muted glyphicon glyphicon-chevron-down"></span>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<abbr title="{{connections[nodeCfg.NodeID].OutBytesTotal | binary}}B">{{connections[nodeCfg.NodeID].outbps | metric}}bps</abbr>
|
||||
<span class="text-muted glyphicon glyphicon-chevron-up"></span>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<button type="button" ng-click="editNode(nodeCfg)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pencil"></span> Edit</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="text-right">
|
||||
<button type="button" class="btn btn-default btn-xs" ng-click="addNode()"><span class="glyphicon glyphicon-plus"></span> Add</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- First regular row -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">Repository</h3></div>
|
||||
<div class="panel-body">
|
||||
<p>Cluster contains {{model.globalFiles | alwaysNumber}} files, {{model.globalBytes | binary}}B
|
||||
<span class="text-muted">(+{{model.globalDeleted | alwaysNumber}} delete records)</span></p>
|
||||
|
||||
<p>Local repository has {{model.localFiles | alwaysNumber}} files, {{model.localBytes | binary}}B
|
||||
<span class="text-muted">(+{{model.localDeleted | alwaysNumber}} delete records)</span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="panel" ng-class="{'panel-success': model.needBytes === 0, 'panel-primary': model.needBytes !== 0}">
|
||||
<div class="panel-heading"><h3 class="panel-title">Synchronization</h3></div>
|
||||
<div class="panel-body">
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"
|
||||
ng-class="{'progress-bar-success': model.needBytes === 0, 'progress-bar-info': model.needBytes !== 0}"
|
||||
ng-style="{width: (100 * model.inSyncBytes / model.globalBytes) + '%'}">
|
||||
{{100 * model.inSyncBytes / model.globalBytes | alwaysNumber | number:0}}%
|
||||
</div>
|
||||
<!-- Repository list (top left) -->
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><h3 class="panel-title">Repositories</h3></div>
|
||||
<div class="panel-body">
|
||||
<ul class="list-unstyled" ng-repeat="repo in repos">
|
||||
<li>
|
||||
<span class="text-monospace">{{repo.Directory}}</span>
|
||||
<ul class="list-no-bullet">
|
||||
<li>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-tag"></span>
|
||||
<span class="data">{{repo.ID}}</span>
|
||||
</div>
|
||||
<p ng-show="model.needBytes > 0">Need {{model.needFiles | alwaysNumber}} files, {{model.needBytes | binary}}B</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-home"></span>
|
||||
<span class="data text-success" ng-show="syncPercentage(repo.ID) == 100">In Sync</span>
|
||||
<span class="data text-primary" ng-hide="syncPercentage(repo.ID) == 100">Syncing ({{syncPercentage(repo.ID)}}%)</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-globe"></span>
|
||||
<span class="data">{{model[repo.ID].globalFiles | alwaysNumber}} files, {{model[repo.ID].globalBytes | binary}}B</span>
|
||||
</div>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-home"></span>
|
||||
<span class="data">{{model[repo.ID].localFiles | alwaysNumber}} files, {{model[repo.ID].localBytes | binary}}B</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-cloud-download"></span>
|
||||
<span class="data">{{model[repo.ID].needFiles | alwaysNumber}} files, {{model[repo.ID].needBytes | binary}}B</span>
|
||||
</div>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-cog"></span>
|
||||
<span class="data"><a href="" ng-click="editRepo(repo)"><span class="glyphicon glyphicon-pencil"></span> Edit</a></span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="button" class="pull-right btn btn-sm btn-default" ng-click="addRepo()"><span class="glyphicon glyphicon-plus"></span> Add Repository</button>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Node list (top right) -->
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><h3 class="panel-title">Nodes</h3></div>
|
||||
<div class="panel-body">
|
||||
|
||||
<h5>Peer Nodes</h5>
|
||||
<ul class="list-unstyled" ng-repeat="nodeCfg in otherNodes()">
|
||||
<li>
|
||||
<span class="text-monospace">{{nodeName(nodeCfg)}}</span>
|
||||
<ul class="list-no-bullet">
|
||||
<li>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-link"></span>
|
||||
<span class="data">{{nodeAddr(nodeCfg)}}</span>
|
||||
</div>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-dashboard"></span>
|
||||
<span class="data text-{{nodeClass(nodeCfg)}}">{{nodeStatus(nodeCfg)}}</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-cloud-download"></span>
|
||||
<span class="data">{{connections[nodeCfg.NodeID].inbps | metric}}bps</span>
|
||||
</div>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-cloud-upload"></span>
|
||||
<span class="data">{{connections[nodeCfg.NodeID].outbps | metric}}bps</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-tag"></span>
|
||||
<span class="data">{{nodeVer(nodeCfg)}}</span>
|
||||
</div>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-cog"></span>
|
||||
<span class="data"><a href="" ng-click="editNode(nodeCfg)"><span class="glyphicon glyphicon-pencil"></span> Edit</a></span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h5>This Node</h5>
|
||||
<ul class="list-unstyled" ng-repeat="nodeCfg in thisNode()">
|
||||
<li>
|
||||
<span class="text-monospace">{{nodeName(nodeCfg)}}</span> 
|
||||
<ul class="list-no-bullet">
|
||||
<li>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-th"></span>
|
||||
<span class="data">{{system.sys | binary}}B RAM</span>
|
||||
</div>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-tasks"></span>
|
||||
<span class="data">{{system.cpuPercent | alwaysNumber | natural:1}}% CPU</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-cloud-download"></span>
|
||||
<span class="data">{{inbps | metric}}bps</span>
|
||||
</div>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-cloud-upload"></span>
|
||||
<span class="data">{{outbps | metric}}bps</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="li-column">
|
||||
<span class="text-muted glyphicon glyphicon-cog"></span>
|
||||
<span class="data"><a href="" ng-click="editNode(nodeCfg)"><span class="glyphicon glyphicon-pencil"></span> Edit</a></span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="button" class="pull-right btn btn-sm btn-default" ng-click="addNode()"><span class="glyphicon glyphicon-plus"></span> Add Node</button>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div> <!-- /row -->
|
||||
|
||||
<!-- Errors -->
|
||||
|
||||
<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">Notice</h3></div>
|
||||
<div class="panel-body">
|
||||
<p ng-repeat="err in errorList()"><small>{{err.Time | date:"hh:mm:ss.sss"}}:</small> {{friendlyNodes(err.Error)}}</p>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="button" class="pull-right btn btn-sm btn-default" ng-click="clearErrors()">OK</button>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title"><a href="" data-toggle="collapse" data-target="#system">System</a></h3></div>
|
||||
<div id="system" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<p>{{system.sys | binary}}B RAM allocated, {{system.alloc | binary}}B in use</p>
|
||||
<p>{{system.cpuPercent | alwaysNumber | natural:1}}% CPU, {{system.goroutines | alwaysNumber}} goroutines</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title"><a href="" data-toggle="collapse" data-target="#settingsTable">Settings</a></h3></div>
|
||||
<div id="settingsTable" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<form role="form">
|
||||
<div class="form-group" ng-repeat="setting in settings">
|
||||
<div ng-if="setting.type == 'text' || setting.type == 'number'">
|
||||
<label for="{{setting.id}}">{{setting.descr}}</label>
|
||||
<input id="{{setting.id}}" class="form-control" type="{{setting.type}}" ng-model="config.Options[setting.id]"></input>
|
||||
</div>
|
||||
<div class="checkbox" ng-if="setting.type == 'bool'">
|
||||
<label>
|
||||
{{setting.descr}} <input id="{{setting.id}}" type="checkbox" ng-model="config.Options[setting.id]"></input>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="saveSettings()">Save</button>
|
||||
<small><span class="text-muted">Changes take effect when restarting syncthing.</span></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /container -->
|
||||
|
||||
<div class="navbar navbar-default navbar-fixed-bottom">
|
||||
<!-- Bottom bar -->
|
||||
|
||||
<nav class="navbar navbar-default navbar-fixed-bottom hidden-xs">
|
||||
<div class="container">
|
||||
<p class="navbar-text">{{version}}</p>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a class="navbar-link" href="http://discourse.syncthing.net/">Support / Forum</a></li>
|
||||
<li><a class="navbar-link" href="https://github.com/calmh/syncthing/releases">Latest Release</a></li>
|
||||
<li><a class="navbar-link" href="https://github.com/calmh/syncthing/wiki">Documentation</a></li>
|
||||
<li><a class="navbar-link" href="https://github.com/calmh/syncthing/issues">Bugs</a></li>
|
||||
<li><a class="navbar-link" href="https://github.com/calmh/syncthing">Source Code</a></li>
|
||||
</ul>
|
||||
</p>
|
||||
<p class="navbar-text">{{version}}</p>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a class="navbar-link" href="http://discourse.syncthing.net/">Support / Forum</a></li>
|
||||
<li><a class="navbar-link hidden-sm" href="https://github.com/calmh/syncthing/releases">Latest Release</a></li>
|
||||
<li><a class="navbar-link" href="https://github.com/calmh/syncthing/wiki">Documentation</a></li>
|
||||
<li><a class="navbar-link hidden-sm" href="https://github.com/calmh/syncthing/issues">Bugs</a></li>
|
||||
<li><a class="navbar-link hidden-sm" href="https://github.com/calmh/syncthing">Source Code</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div id="networkError" class="modal fade">
|
||||
<!-- Network error modal -->
|
||||
|
||||
<div id="networkError" class="modal fade">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header alert alert-danger">
|
||||
<h4 class="modal-title">
|
||||
<span class="glyphicon glyphicon-exclamation-sign"></span>
|
||||
Connection Error
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
Syncthing seems to be down, or there is a problem with your Internet connection.
|
||||
Retrying…
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-content">
|
||||
<div class="modal-header alert alert-danger">
|
||||
<h4 class="modal-title">
|
||||
<span class="glyphicon glyphicon-exclamation-sign"></span>
|
||||
Connection Error
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
Syncthing seems to be down, or there is a problem with your Internet connection.
|
||||
Retrying…
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="editNode" class="modal fade">
|
||||
<!-- Node editor modal -->
|
||||
|
||||
<div id="editNode" class="modal fade">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Edit Node</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form">
|
||||
<div class="form-group">
|
||||
<label for="nodeID">Node ID</label>
|
||||
<input placeholder="YUFJOUDPORCMA..." ng-disabled="editingExisting" id="nodeID" class="form-control" type="text" ng-model="currentNode.NodeID"></input>
|
||||
<p class="help-block">The node ID can be found in the logs or in the "Add Node" dialog on the other node.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input placeholder="Home Server" id="name" class="form-control" type="text" ng-model="currentNode.Name"></input>
|
||||
<p class="help-block">Shown instead of Node ID in the cluster status.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="addresses">Addresses</label>
|
||||
<input placeholder="dynamic" ng-disabled="currentNode.NodeID == myID" id="addresses" class="form-control" type="text" ng-model="currentNode.AddressesStr"></input>
|
||||
<p class="help-block">Enter comma separated <span class="text-monospace">ip:port</span> addresses or <span class="text-monospace">dynamic</span> to perform automatic discovery of the address.</p>
|
||||
</div>
|
||||
</form>
|
||||
<div ng-show="!editingExisting">
|
||||
When adding a new node, keep in mind that <em>this node</em> must be added on the other side too. The Node ID of this node is:
|
||||
<pre>{{myID}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" ng-click="saveNode()">Save</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<button ng-if="editingExisting" type="button" class="btn btn-danger pull-left" ng-click="deleteNode()">Delete</button>
|
||||
</div>
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 ng-show="!editingExisting" class="modal-title">Add Node</h4>
|
||||
<h4 ng-show="editingExisting" class="modal-title">Edit Node</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form">
|
||||
<div class="form-group">
|
||||
<label for="nodeID">Node ID</label>
|
||||
<input ng-disabled="editingExisting" id="nodeID" class="form-control" type="text" ng-model="currentNode.NodeID"></input>
|
||||
<p class="help-block">The node ID can be found in the logs or in the "Add Node" dialog on the other node.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input placeholder="Home Server" id="name" class="form-control" type="text" ng-model="currentNode.Name"></input>
|
||||
<p class="help-block">Shown instead of Node ID in the cluster status.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="addresses">Addresses</label>
|
||||
<input placeholder="dynamic" ng-disabled="currentNode.NodeID == myID" id="addresses" class="form-control" type="text" ng-model="currentNode.AddressesStr"></input>
|
||||
<p class="help-block">Enter comma separated <span class="text-monospace">ip:port</span> addresses or <span class="text-monospace">dynamic</span> to perform automatic discovery of the address.</p>
|
||||
</div>
|
||||
</form>
|
||||
<div ng-show="!editingExisting">
|
||||
When adding a new node, keep in mind that <em>this node</em> must be added on the other side too. The Node ID of this node is:
|
||||
<pre>{{myID}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" ng-click="saveNode()">Save</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<button ng-if="editingExisting" type="button" class="btn btn-danger pull-left" ng-click="deleteNode()">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="angular.min.js"></script>
|
||||
<script src="jquery-2.0.3.min.js"></script>
|
||||
<script src="bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
<!-- Repo editor modal -->
|
||||
|
||||
<div id="editRepo" class="modal fade">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 ng-show="!editingExisting" class="modal-title">Add Repository</h4>
|
||||
<h4 ng-show="editingExisting" class="modal-title">Edit Repository</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form">
|
||||
<div class="form-group">
|
||||
<label for="repoID">Repository ID</label>
|
||||
<input placeholder="documents" ng-disabled="editingExisting" id="repoID" class="form-control" type="text" ng-model="currentRepo.ID"></input>
|
||||
<p class="help-block">Short, unique identifier for the repository. Must be the same on all cluster nodes.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="repoPath">Repository Path</label>
|
||||
<input placeholder="~/Documents" id="repoPath" class="form-control" type="text" ng-model="currentRepo.Directory"></input>
|
||||
<p class="help-block">Path to the repository on the local computer. Will be created if it does not exist.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentRepo.ReadOnly"> Read Only
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="nodes">Nodes</label>
|
||||
<div class="checkbox" ng-repeat="node in otherNodes()">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentRepo.selectedNodes[node.NodeID]"> {{nodeName(node)}}
|
||||
</label>
|
||||
</div>
|
||||
<p class="help-block">Select the nodes to share this repository with.</p>
|
||||
</div>
|
||||
</form>
|
||||
<div ng-show="!editingExisting">
|
||||
When adding a new repository, keep in mind that the Repository ID is used to tie repositories together between nodes. They are case sensitive and must match exactly between all nodes.
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" ng-click="saveRepo()">Save</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<button ng-if="editingExisting" type="button" class="btn btn-danger pull-left" ng-click="deleteRepo()">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Settings modal -->
|
||||
|
||||
<div id="settings" class="modal fade">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title"> Settings</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form role="form">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group" ng-repeat="setting in settings">
|
||||
<div ng-if="setting.type == 'text' || setting.type == 'number'">
|
||||
<label for="{{setting.id}}">{{setting.descr}}</label>
|
||||
<input id="{{setting.id}}" class="form-control" type="{{setting.type}}" ng-model="config.Options[setting.id]"></input>
|
||||
</div>
|
||||
<div class="checkbox" ng-if="setting.type == 'bool'">
|
||||
<label>
|
||||
{{setting.descr}} <input id="{{setting.id}}" type="checkbox" ng-model="config.Options[setting.id]"></input>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group" ng-repeat="setting in guiSettings">
|
||||
<div ng-if="setting.type == 'text' || setting.type == 'number' || setting.type == 'password'">
|
||||
<label for="{{setting.id}}">{{setting.descr}}</label>
|
||||
<input id="{{setting.id}}" class="form-control" type="{{setting.type}}" ng-model="config.GUI[setting.id]"></input>
|
||||
</div>
|
||||
<div class="checkbox" ng-if="setting.type == 'bool'">
|
||||
<label>
|
||||
{{setting.descr}} <input id="{{setting.id}}" type="checkbox" ng-model="config.GUI[setting.id]"></input>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" ng-click="saveSettings()">Save</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="angular.min.js"></script>
|
||||
<script src="jquery-2.0.3.min.js"></script>
|
||||
<script src="bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user