diff --git a/auto/gui.files.go b/auto/gui.files.go index e47873c56..fc4256a50 100644 --- a/auto/gui.files.go +++ b/auto/gui.files.go @@ -18,7 +18,7 @@ func init() { bs, _ = ioutil.ReadAll(gr) Assets["angular.min.js"] = bs - bs, _ = hex.DecodeString("1f8b080000096e8800ffec3cfd73dbb692bffbaf4075e923d5c89493bed7bb89ebbc499df43dbf7c79e2a47373ae6f8612218b35052a246845e3e87fbf5d00a4f0458ab693b66fe63cd3c60616fb85c5627701703c26c7f9725da497734ec2e321797cf0e8afe45ff1553e213fe5c525895942723ea70599e68c17e9a4e2795146e459961131aa24052d69714d93680fb07d2829c96784cfd3929479554c290c4c28813f2ff36b5a309a90c91ad092d727eff74bbece28c9d22965308ecf634ea6d035a1886a9657403c65d04ec9ab93e3176fce5e90599ad1686f6ffcdd6f6596324e2645be02f24f082f2a3a124ca6aca2f5dfcbac2af13ff937f96e0c232fb37c1267e4c113328bb312806276596571a1fe46a0bda0825f4a9077ca83c3bdbdebb820e59a4d412c76498eea11d1224faa8c8641d3178cc8f9c5f0500ca88a6c12039a2312808a049e062e024667e96538aba021cd19091fcc395f9e16f9759ad062486ef608fc188d5142677195f132fa5416b37fd218dadec40b41e0bff78fcfdefdbcff3ebfa20c08ed187b9ce75729adc71a2337439b4d5ee459468b3038ab5b8f799181a01aefe5345f822205c99a7754c1b2a0d7cf638e640e0e9bd64bcadfbe84269c926d2bea282eb854b09809e0440822b0232b8c0a822500dc6c0ead4e50a7dbbe589f3c471903a39581452292f30b0f921386821aeca9fe6591f37c9a67c773987fb0e3864d0d861605ac0f177749297b817d2e3760443473592fe832af2515edb024cec022d965090b649617944cf23c2b4906b3092d9cd3c2a4c8b900065e44fb4d9a3c21c1abb4e49401229841d0c214cc5ecc2c3955d21109419e25094c49494b00e4eb252ca980d34f1cfe523325d7d466a4217f1d7f3aa32c793959961afab715bfcc715edfa129bc4a1729f89a97e94fe372b8c5cdaac584169dd8df01be989d3010f43acece340ab287d45d24bc3566655d7ee4aaf3eef84fe322864594bda31f2b00d295032a23a02018c912a1a32d487ffc80441aa5a57944fe33784c227be504f457bd46e11fc2693e63ec058b27194d3422b28b3c4fc1eec0c3afb788d13e3bf97e954f5b908a9e7be13ccd0bde8e90a8eefe3a3ec3f69fe476a3af1d6c26db769d4d63fc875376eaca295b0876fa075f985ef0b24acffc0b5bad577d623e9cdc67317f3005456ccf2ad88b61879dc6c2f17f3044de89f0342ecb555e24dd4835288578b96de9e4f6fd2b7dd96224f2cff7ef4fcf2090280810ba850d3d3b3d7949d71a326820b245a18897e915fc6d4d52b325c21677564da794263409eb1d117fd21909bf111ba0deaa4d70ca521e0e0fcdae30f80f4639e8e04aec21c110378d380b83396cee8105ed6eaff8b33158d86eb6b764633bb09b09842de7154ff215eb86f4edfb26d31b57b93fc7e0d55ccdb68b55505e15ac4d1dfe0969d3facd249e5e2545be043b007a60b96017600d933c2e1215456e5a26a54bc066e39f811c73046e222c9d371165458030ac23cc872418976b58e80be0b144bb2b4b2db44c621edbc299067ae833018911d8c0f11acb4319e4847eee14f27a82f471dbdfdf4e7e83fd34029d95a11eee0c2358ab2fe2e95c439e26cec4781520c2a8bf239aa3001a28c3bce3c3bb93e37cb1cc193818c4d4573d9a1a04def334b97034614ba5ffeee7518b617bcf14c6c62c5f01758ca421765d85c39101c131140d1166bf89b887644c1e1d1c1c989069a21c55fda305e830de140ddd26e80c33b03615096f869dd13c2edfae18c4904b5af0b550b5071e7fea14edd0e9dd382d1c366a3f16248a93028e0a421e60ff75cce7d122fe141e8cc87f91efa42e05c409fb69cd69f93ee71000ec7bd209070a95c793a1cba14139aff82ed210d8f5a16d80b512df406ecca77312d236d53a4a39e82b8207d09c8d8dcf43982999ed26762d06992af55e077682e527b739dcb3932888d078551aee149bedbd0337f67c66ae7a8483757f04395bc520854e19046ffead05020e76c570b7d3bdbb41c1450d1305e904acb16f90442be6339e2f9740d98b59d426b85cc3017a3e0f19d1bf1d5d838b7fcf0f2e229e7f0002c5314c0d38f387b203e66552f2227c343c34e550c38fc8001347d86c07e4f367b26d3d49323ab06591dd0fa19b84832d97586a38a5c514fc737c49d5c43c24836f8703afb44a259a409e193fce2062fcfa139eb259fe15663bc154adf862936dcc5890c2dcb452560b31680b93b6684a39f1ad989645ba88216df361f2a8cf9a43d328befa44c23ed926b147bdb27c28fcb5c07fd00fab3185cb2907a90002760baf9de0c29224c63e008d87435baf62379a6539446840c6ef16b100e6718bd87c3c336267e416dd3cc079362f35207a03ff9e3cbf308d0e016dddd4ed1146651915645189a00adfa6d6b8d625e1b9887f022bfc22144bb6ed23958722212e169b32ec42df0e6d8c1d5e2710e503217ee38d3d9a3d99a254ff0e7acdaf6eab4f959cdc46690b88f6ca766db9cefa4fab2ed73ff6d299eb0c77eaacdd37a2ac58cdf99d35a618134a53c5a42edffef78ef9d654fe8789603981ce7daa5d945fe8ce6940664c4e85a169c7132d6c2a886b5a9480dbc7dfd7544f96c2defb4b3bed1df30cdb6d82841ded98e2a2040bcc69c4698c7e380318324ef51a03f25b93655b551289f5d0c83750448537ca28bbe47308b9c8a316899bf8a04350850d62e5566350c7693bad41452baab767883218b44528cd3c03f996c13a48878ca6c5d4d13fe4b43ff883083ce37de313dc9e62262dc11a165a13a6e9a5af52c24aa65c62d0b05345bbf4d34739bd354393946b557abf66c66308d5ae2889095618314681b1eba6db38938c14c8db659d6cd727d03826346115909e7ffb7061e9bd130f00e838b0a0ab64ea5b09157575bf8acaf89af656515915f0bf7c41e5f9fb549ebf9a8eb03993fda691897eace2acf46b67d4a9e02124b4ce762e7f76a007a5b5a036d599ce42c5f2d0b44990b9a414edb63e6e26ab34cb08a3201d04c113dac80aea52056f2bb871798ae4f188c83cdbb85330c3d64aa87bfe6d1e31c885634bf36cb9ccd6c0fe8a3427d2199ec565eb3d0f0d7396ba0dd49a336f117bab825eb8e424b5236a2e075875fc5609227900a74226626bdf843ae345542eb39487c108d758bcd436c04fda06f829e21053820725f639832cb52df3d2293c0339589cff3a7bfb262ac53582746629613822377371ada47c426e82e39c014f7cff3d38e6401c79016bf2906efc5b99b3606314bff7ba5dc500cf7e066d553a61c5ad7ec03822326daee54ceab647342d6a539883365f6add15d11dd7d92ac562ed8a4e9658c36816332c6c264e5d7457e05f6043f720a04103fb23b21c58c6dab1f6dd756d2373121b13374ce9fb7441f38a3756197a9cc50a62bf7c15e11a479048a352ff6a911989938a9675d779e9467229fe6f6d2feae8f14e26e5b705ed34d32d58fbce0e9de3cfdb1ae5a6a7d979e4c708c41b805b01698db62a0a58ea6ac483887e82959f84373035f52087152401ea7bf1095c97578d06d819cd66f294caca858c54c89577cb58d4dc610037498e9a70b5698e7ecb53069e9378962b02bf004ef2227a00767c5a08a68d1814a7ac56db17087052370132140fd4d2e4a376945fcef355e0c715273b90f966f146d717b09fac59bc00fe373d66d25a62dea9f4c3fcfe8a4e2824f274a7b21d8ace65047198e957c9eedb043e3df44b6abd1949bd3ef4784d5b0ab2b787a71090361f9aa31567bcb8b1c8735ee32cde7ffe26fac4e1a185daeae821ec3d04b6857627a03b5efb43c2244f0ad469b675ee0c5e6e44929cd111490f6f2b682fd36f8a111edd3b508defb62b066001593ca5e1988c81e100c8352dfb758b71d25847b10e85c675f9fcfc1da3e486086ad25594bced208ec2494a7e3417ae2c2241c7c387be52b20e7b9e5ee8853e53451dd74ceac15b890f1d50c5b99b75e1cfa4a0f1558f12b3bcb301985a16b894785995f3d0ddfb5b1c5d54e6050febea6e5cd0bbfaa33fc3ba14cf1d6a3edba247bd46dbeadc7bfb760c7e5c6fde526febf41729446cb67fbf8355336b8ac0300f1db3673d2bdabaf0ed06ea9138ceb2ee79a83da46651dbd9b31d8b326aa70ca98169c5bed21f57e3ed134cd67b9a86bcade2da465b299246986291a7ceb3819dd631cd685cbca82fc774c689fa5b0483cf73936b553adf278f2e045b3bb74f316e2c3869896467450a8945b676a71516b5ceea3630b9bdf18a7aa0be9bf94db8146904fcbfd9a6a68da31ed9957dec1b0e3b0ac480a7a5b6b1ccfb184c0d67de876c4deede41f7ed923b35c2a881b52677da1830974c1c78d77376e366103ab88afe9c7b9c4ef8b78bd479ed5f2edccbcc56d8ee41a50eaf309ff9cb5f7cb4b600116e11c2890dca14cf059dcb4b3e5605243eaed028f9f6e6d6b12f295dc28887ddbce1d39145195d01b0cffa7661efeefffc99fcedae893d1a68cf4c0fc97e814c0fd260c7ec77dafb8d615310186cee9e00fffe22638ed029b37c39b7ccbf448e60f0ece4088a8ad7a61ca826ce3bbf70fbcc55ae050eee426fb60179cc8b39aa178b2f2af79363b54b3992b4fcc18a26848c1a6ea42b7aa218b1cbee7620833fb230e1e7d7ba51d9c0789c8a1b294858c3edb8320475dc2b7106231742ba168071478b7ef4398801af4e991ca2f370115a37864d0dd9daf048da63c04bd30dfa6ede58e37ce8dd2c46162fea31d212d55f6d990cda7d89be201586deb67fffa9529b720eb959693994dafa9cc01ac29eb625dcbac9e341bc9d4b201e23f66e822aebba48a89db20f872d9570894e249c9ec85d748a42f060445a8e9ba485746f25bd5ce297a9182a83352cd1b36d1b9778ee698aff362532cae5533c63a2a6a6ad62d4de4015314bf2857c271d7e7f3022df3f6ea9cfb3548fc97bbcb05257b16efb60410df3be58d841f1966fba6aa5f9df6d6910ea55bc78b8e3961e7630a50ce0964c350ff45b996a3b11df7166aeca82c6e14f6b59cbc1f5669be9fbe07d752d1f70fd561fff7d1d2fc3f6e5d98a405cabb5dfcbf59a8a315e97bfdb7c346b5f9882deb6b3dea03f1085655a3f8d0f4d81e4d12e9eed0a711ad6349586f1884c6a2eb58b60b1b89225df4a6caf826132a700265e00fbba9d42f3a3021ffaaa2efb8f9c8d440d7baa862915ec695865402af03ab55d0baf1cb7c52c873e6d86827634dd883db6453771f43c2d208ccc8bb520ddfcd59ffa16c1531d81cb031a72a67fcd63a125ff9967f3370a388bf3a28ea3141bca58ea1b952e41b1672d748a99167e5847550b9d5826c38b051e3f0d75a933b98235959a5c642617099da60bbcd405963c22ac329849d2cb9497f8267c5ac7ef3825f83d08e71d88427f50f322fe9108ea0783f28986f835cb2fe52ff144901ee21bc0a6e7d1411d0a2165ebbd21f048f615665334c9a6a1637d6fcc2803dbc2517b92ed89e44dfcf3f933f9fe87c346f2bce2d2110f20a862747556d7ba5673fcb84428fbeb7ae18f047e91eb6cab1039aa665e72820740b96247701295f829a0f0b1e60515e987470a830201c9a516c0e9ab0e497d4450325089c153134c1a6b41811847524263dbefdfa8c26dc06218119b5fbda9e75b61d35e2cb365c54744bcf5f21885e806aa3fa79f68123626678cdafa5ceb833c35439394c5e2b3187df9b1fda2681486dbf8ceb6c75c07a4f54598c4f214bcfce3bf92eff47f9c8c5c408e8f3ca0873eaadd5a7a3cc4578201f9477a1bd6faf0740f665ef763a6938b7b907fe927af3f0b2bf0935ab53de09860979d2d287e04eb4f6467e2cd9cf64f87366dd0fbd8d96d38ebc3d27dccac172f9d4cdc83fad55730b2722e3fc673171b3398f7decc6f211a67ab785dbea93ffcf3f5eddbfbc854677f17c7d379c5ae4e9e7f61667daceacf4dc4b5d3b810c181d4b2780c138ea39b47a31f36e34bbb20228077a2554d0258256ffbc1ce491396720a56f6872b41de40199fff3afef5d78bb15707184649f9eac8e8887cdf621c9a01780d641045d118dfcd4b84320ad291ef3f1eaabad778b0538d7844cbeeb7e07cdf5711a0db4b3fdfaa4b3f6ddc2422f748af6918e422a797672b5d7ce96cc8cf333e21c1b156dc56c4d5f71f9b660e116739cdaac4e911e9aa5d0257b7d701f791fa5523b1d1d0d20590e3f841a81fa559616e7a34c04f610d08bbdc178fb68f0666e5e25ce18c205b193cfd712c463e55143ad554b1f463252a979a92ba74f4b182c1f87db3cbd7c889264596b2ab275b1c420d2342b3c588c49c1790e74c7991d9d68a6dd103b0bb92166554b1729eceb4ebe0d7295dfd1267fe5315f105813eb5d2fa673c262b4a60c95759c2022e4363d0b6175872069afd05a152beb6b425ce7a0e9da1ea0861cb9bacbf36825c743087df25457042519092c45941e3647d27f644f1b59dbfdd3ca4259108bfa8769c1665638d7ecc311be78644a7398b09c512489afcbf3def9e31535ddd06ede740dc8c41df2f1e5234d27d819b9bb66214953a56f8dff367fbfff378ff3f2f6efef678f360dcfa71a8fb48be53fa5ec8db16a2c0fef516c8ff010000ffff010000ffffb944a65489590000") + bs, _ = hex.DecodeString("1f8b080000096e8800ffec3c6b73db3892dffd2b30bacc929ac89493d99dbb8ae36c659cccae372f579c4c5d9dc757458990c531452a246859e5e8bf5f3700527852749cccee55adab6662038d7ea1d1e86e001c8fc971b15c97e9e59c91f078481e1f3cfa33f9477c554cc8cf457949e23c21059bd3924c8b9c95e9a466455945e47996113eaa2225ad68794d93680fb07dac28296684cdd38a54455d4e290c4c28813f2f8b6b5ae634219335a0256f4e3eec576c9d5192a5539ac338368f199942d78422aa595103f13487764a5e9f1cbf7c7bf692ccd28c467b7be31f7eafb234676452162b20ff84b0b2a623ce649ad7b4f97b99d515fe27fe263f8c61e465564ce28c3c784266715601509c5fd6595ccabf11682fa8e1970ae49db2e0706fef3a2e49b5cea720567e498e9a11d1a248ea8c8641db178cc8f9c5f0900fa8cb6c12039a2312808a389e162e024667e96538aba1212d72123e9833b63c2d8beb34a1e590dcee11f8d11aa384cee23a6355745395b3bfd318dadec60b4ee0bff78fcfdeffb2ffa1b8a23910da31f6b828ae52da8cd5466e86269bac2cb28c966170d6b41eb332034115deab69b1044572920defa8826549af5fc40cc91c1cb6ad9794bd7b054d3825db56d4515c32a1603e13c009178463475672ca09560070bb39343a419d76fb627df202650cb4d61c2c12919c5f38909ce428a8c69eec5f96052ba645763c87f9073b6ed954606859c2fab0715794e62fb1cfe6068c886636eb255d168da4bc1d96c41958647e59c1029915252593a2c82a92c16c420b63b4d42932c6818117de7e9b264f48f03aad18cd0111cc2068610a66cf67969c4ae9888020cf9304a6a4a21500b2f5129654c0e80d83bfe44c8935b51929c8dfc43767344f5e4d969582fe5dcd2e0b9cd7f7680aafd3450abee655faf3b81a6e71e7f56242cb4eecef015f9c9fe420e8759c9d2914440f69ba487867ccd2badcc865e797e33f8dcb181651f69e7eaa0148550ea88c808260649e701d6d41fae30724c2280dcd23f25fc06312d12b26a0bfea150a7fe34ef3799ebfcce34946138588e8222f52b03bf0f0eb2d62b4cf4ebe5f17530f52de732f9ca745c9fc0889eceeafe3336cff596c37eadac166b26d57d9d4c67f3ccd4f6d39450bc14ef7e00bdd0b5ed6e9997b61cbf5aa4eccc793fb2ce68fbaa088ed790d7b31ecb0d3983bfe8f9ac83b119ec655b52acaa41ba90225112fb72d9ddc7e78ad2e5b8c44fefee1c3e919041225014277b0a1e7a727afe85a41060d44b44814f132bd82bf8d496ab744d8e2ceeae994d2842661b323e24f3a23e1777c03545b95094ef39485c343bd2b0cfe23a70c7470c5f79060889b469c85c11c36f7c080b6b757fcd9682c6c37db3bb2b11dd8cd04c256f39a25c52aef8674edfb3ad31b5bb9bfc4e0d56ccdfac52a29abcbdca70ef784f8b47e3b89a75749592cc10e801e582ed80558c3a488cb4446911bcfa47409d86efc3390638ec06d84a5f2c6a3ac0810864d84f99004e36a0d0b7d013c56687755a5849649cc625338dd400f5d262030021b385e617928829cd0cd9d44de4c903a6efbfbbbc9efb09f46a0b32a54c39d61046bf5653c9d2bc8d3c49a18a7027818f5574473144003cd31eff8f8fee4b8582c8b1c1c0c62eaab1e450d1cef799a5c589a30a5527f77f3a8c4b0bd670a63e3bc5801758ca421765d85c39106c130140d1166bf8db887644c1e1d1c1ce89069221d55f3a304e8305e170ddd26e80c33309f8ab837c3ce681e57ef5639c4904b5ab23557b5031e7f9a14edd0eadd582d0c366a3716248a93028e0a421e60ff4dcce6d122be090f46e4bfc80f42971ce224ff79cd68f5a1601000ec3bd2090b0a95c792a1cda146b9a8d92ed210d8f5a1ad8179896f203766d33909a94fb596520efa8ae000d46763e3f2107a4a66ba895d8b41a44abdd7819960b9c96d0ef7cc240a223456579a3bc56673efc08dbd98e9ab1ee160dd1f41ce56e79042a739046feead05028efc2ac7dd4ef5ee1a051b354c14a413b0c6be43125ecc67ac582e81b21333af4d30b18603f47c0e32bc7f3bba01e7ff9e1f5c44acf80804ca63981a70e60f4507cccba46265f86878a8cb21871f9101268eb0d90ec8e7cf64db7a92647460ca22ba1f423709075b2eb1d4704acb29f8e7f892ca89794806df0f074e69a54a14811c337e9c41c4f8ed273ccd67c53798ed0453b5f2ab4db63663410a73e3a52c1762e00b93b6682a31f15e4ccb325dc490b6b93039d467cca16e14df7c22619ff449ec50af281f727fcdf11ff4c3aa4de172ca402a8080ddc26927b8b00489b10b40e1e1d0d42bdf8d665901111a9071bb452c8039dc22361fcfb4d819b945370f708ecd4b0e88dec2bf272f2e74a3434053374d7b8451594639595422a8c2b5a9b5ae754958c1e39fc008bf08c592ad7fa4f45024c4c56252865de8fba189b1c3eb04bc7cc0c56fbdb143b3275394eaff835e8babbbea5326277751da02a2bdcaaf2ddb59ffcbaacbf68fbd74663bc39d3af3fb469415ab397fb0c624635c69b298d4e5dbffda31df8acaff6922184ea0739ff28bf22bdd390dc88cce293734e578c2c3a684b8a66505b85dfc7d4bf56429ecbdbffa69ef9867d86e13246c694717172558604ec34f63d4c319c09031aad61890df866cbe552511580fb57c03459478a38ce6976c0e211779e491b88d0f3a0495d82056f61a833c4edb690d325a91bd3d4394c1c017a1b4f30ce43d8355900e19758b69a27fc8697f72071178c6fbd625b839c5b9b0046358684c98a297be4a096b9172f141c34e15edd24f1fe5f4d60c4d52a654e9dd9a198f2154bba224265861c41805c6aedb6eed4c329220ef964db2dd9c40e398508795406afeedc285a5f74e3c00a0e2c082ae94a96f2594d7d5dd2aaae26bd809e4a16da320cb72a6b840c83fcedebd8d2a7ef499ce0c2e150e7140b164fccc74ce4fc7ab27e436002a0c9cd9fe07b0af8057ee97993c6b18ff5e1579b0d998958a655159753ba005b20143234ec455b5e857a714b8c698e3f4ae7d5893d81e52f3e29bdab6bb3ce99889dec65ad525fcaf58507113622a4ec2f5396b4fc7bf6bad8b7eaae3ac72dbe9a8d3d487e4f3674b15e267077a305f0f6addb0d35928591eea4a07992b4ad1833407ff64956619c9294807e9c884b6b282bae4d1831166da3c45e2a08ad7007cdc4998a1d708ec9b08fa610f9fe63d539ae760f96b607f45dabb01199e8a66eb3dafa145bd5c8e3167871df876ba1de72479f98ac401a70c4989a9531dea8c955105ab9f85c1087d58bc54d6dd8d1260dc44e06d16b043f145e3e262ebbfb4338ebd6e7f39c003b081af54c90dc8bb04b573327dba3d0773773da7f2383f8939f06d28c68519d5679cad52ac58afe86489859c761dc19acaf9d1d39ebd540cdb1edaa7212d1a081290e5c098a28e65672f29139995dde9b8614a3fa40b5ad42cdcee5af63a5d41005cac225c5e081229549a5f0d32237e5ce3b1b6ce9b47824bfe7fc3b3cbf3d72f3229b72d2847ba3df63fd719f05d8d72d3d3ec1cf26318e6cc428ca8bc415b9725040a72c48388de80cb48c25b989a6690c50a9200f5bdbc01ffe254a3067646b39938aa3312422d1fb4e5dd3216b51739c09791a336666f9ba3df8b3407f7461ccb15815f022745193d003b3e2d39d35a208e53d6a8ed2b4479a99d056a8a076a69f249b9cf50cd8b55e0c615273b90b966f156d517b09facf37801fc6f7acca4b1c49c53e986f9e3159dd08c32ba53d91645eb46063fd175ab64f7950a971efa65f6ceb4ac591f6aa8a42c05d1dbc3537048930fc5d1f2836edc58c461b77621c17d08c9fbf809aa81dae8e821ec3d043685b627c08e521cc17fa7d534f9fb31263e4991d311490ff7ee68546dadc3219505d57a45b32001bacde2290dc7640cbc0440ae6dd96f5ab483cc2688b328b44ec1e541ef1b24a2926ccf202e53f093769292a7fa9210352ae878f8d055a95661cfd30bb58ea8aba8236d6c066f253eb44025e7762a813f9392c6573d2ad8e24a0860f22c1d21f1b2aee6a1bdab7a5c485415250b9be2715cd22f5de97d97057ff1d0e0f2c54e6a99d6ebda7a7b36dcfa77e6ea4dedac73b9a610af98deed0b2c2f37d408c673689966deb3a8ad0aef372287c4909d76cf43e3a09459dfce9eb9f8a5e1599548054ca9f755eea8122fa0603ed9d334c48515db367cd5481a6182419e592f07765ac734a371f9b2b91fd31925a9cf11343ecf75ae65f57c9f3cbae06ced4c10f8b831e7c413c7cdca14c2ea6c6d4f6bc54a95d5edb67c77e3dd160f3b4db8e24134fcbfdd4aa6ad331d99c57dec1b0e3b6ac480c793d92f8b3e06d3c0e95722bda9cd7be8be5b6a234768c5176f6aa38c0173c9f899773367b776fcac82cbd8c7baca69053fbb489d37fee5c2becf6c04ad0e54f2fc0aa3f93ffdc9456b0b106175983bb14195e2d1a0757fc9c52a87c4f7150a25d7fee91dfb8ad2258c78d8cd1bbe1e5954d11500bbac6f17f6eefecf9fc95fbe34ad4503ed99e720d9af90e740126899fd4e7bbfd56cea0958ef97a77f7fbcc818ac74ca2c1ecf2d8b1d21bac68e15a24b044e73b1a0da30ebfcc2eed317b01213d86bb8f5f0e21017932f27165750ec269737dee248d072c7218a102220b8155ee68964c4bcbc6fc628f823326e37bfc67dc916c6e12fec2040c06a1ec59621684eb304ce60644308af0130f668de8fee0431e0c5289d43f40b3642e33eb0ae21531b0e497b0c78a57b38d7bd1a639c0bbd9d4488acbc19232c51fee54b24d0ee2b5ce6293774dfd67cf7847b0ee94b65ace7c642acb816a20edf32f3eeb178146e86f288470b7ddb98c6b8b0112ae7dcc3a1a70c2bd0f19ccc1138f34e5e851c8c88e7ac43cc62b727efe5b6be4eb94a1a95662d8e5d53bb46f307990b65e22d9aa6a7a96e2a18b3b650659c27c5423c140e7f3c18911f1f7b6ab379ca7c67efee936b7917e9ae37f6e530e795fd1d14eff8a8a9519afbe19202219f85f3c3733bf1dec194bc0c7047a6da17ea5ea67c47963b0e3565e14a2bfc7b0b2f16aeb7db3cd705efaabcb8809bc7eaf8ef9b7819fa57871701bf576a3e18eb351577bb4be13e44eab847e13bdb505e48c2326dde8687ba40e2580fcff5b8382d6b8a4ac37844260d97ca4da898df49128f05b677a13095910013278079df4ca2792ac187ae9ac3fe23cb8fcb61cfe430a9823d05ab88d9385eabfa68e015e3b698c5d067ed50d08ea21bbec5797413472fd21222ada25c73d2ed5ffda96f113c5311d83ca02167eae72c164aea9b39f65ead7cb1382f9b5043b2218da5b9526813e45bc642a59829bbbf714cb150896562775fe0d1c350953a132b5851a9ce45a67391d069bac0bb3460c92392d71a33497a99b20a1f454f9b1017a7043f88603d8490e80f1a5ef83f0241f3624ebc51e0bf66c5a5f8259e70d2437c04d7f63c3a682211a46c3cb8031ec9bec4ac8b26d8d474acee8d19cdc1b670d49e607b2278e3ff4056fce34f87ade445cd84231e404c93d3d55953e959cdf1eb0aa1e86faa654f09fc22d6d956216254c3bce0048f280ac90ee724aaf05b38e163c50b4ad20f8f24060902920b2d80d3971d82fa88a064a0128da73696d3d68204d10e4db8c6b61f809165cb208f6144ac7ff6a5996f894d79b29b2f6b3622fcb193c328783750fd25bda149d89a9c366aeb738d2fd2340c4dd23ce6df85e8cb8fe917792337dcd677fa5e331d10ef932881e51978f9c77f263fa8ff58492b871c1f39400f5d54bbb5f47888cfe402f2b7f42eacf5e1e91eccbce9c74c2717f720ffca4d5e7d1755e237a51a7bc031c12e3b5b50fc0ad4bf909df14763ca3f1dda3441ef636777e1ac0f4bf731b35ebc7432710fea57dfc0c8aab9f81acd97d898c6bcf36aba87689cade275f5b6f9f2cdb7b76fe72b4b95fd5d1c4fe7757e75f2e22b33eb62557d6fc1af1cc6250f0e8496f96b90701cdd3e1afdb4195f9af5080ebc13ad6ce2c03279db0f764e1ab79453b0b27fba12c41d89f1f96fe3df7ebb183b7580619490af898c8ec88f1ee3500cc0692083288ac6f8705c201451908a7cfff150969dc6839d6ac403cafc7e0bcef581110ebabd96f2bdbc96e2e326e1b9477a4dc3a0e039bd3859e8e24b65437c9ff009098e95faaf242e3f80d836338838ab695627560f4f57cd2ab1bcb90cb88fe4af0a898d82962e801cc32f223d156685b9e9d100bf053520f9e53e7fb57c34d02b17e7126704d9cae0d9d3311ff94c52e854539da79f6a5e385494d4a5a34f350cc60f7c5dbe414e1429b234bf7ab2c5c1d53022345b8c48cc580979ce94959969add8163d00bbab685945755ecdd3997215f83aa5ab5fe3cc7df0c09fd0f72955363fe3315951024bbece923c602234066d3b810567a0d95f112a656b435bfc38e4d01a2aabec5bde44f9b315e4a28339fc302782138a825424ce4a1a27eb2f628f1fb7f9f9dbcd435a1181f0ab6ac76a9136d6ea471fb3b1ee07749a339f502c81a4c9bfed79f78ce9eaea36683707fc5e08fa7e7e89be95ee2bdc2d341523a934b1c2ff9e3fdfff9fc7fbff7971fb97c79b0763efd791ee23f94ee97b21f72d448efddb2d90ff030000ffff010000ffffeb001f9c8a580000") gr, _ = gzip.NewReader(bytes.NewBuffer(bs)) bs, _ = ioutil.ReadAll(gr) Assets["app.js"] = bs diff --git a/cmd/syncthing/gui.go b/cmd/syncthing/gui.go index ef21e95c4..2915bd7d4 100644 --- a/cmd/syncthing/gui.go +++ b/cmd/syncthing/gui.go @@ -16,6 +16,7 @@ import ( "net" "net/http" "path/filepath" + "reflect" "runtime" "sync" "time" @@ -210,9 +211,43 @@ func restPostConfig(req *http.Request) { newCfg.GUI.Password = string(hash) } } + + // Figure out if any changes require a restart + + if len(cfg.Repositories) != len(newCfg.Repositories) { + configInSync = false + } else { + om := cfg.RepoMap() + nm := newCfg.RepoMap() + for id := range om { + if !reflect.DeepEqual(om[id], nm[id]) { + configInSync = false + break + } + } + } + + if len(cfg.Nodes) != len(newCfg.Nodes) { + configInSync = false + } else { + om := cfg.NodeMap() + nm := newCfg.NodeMap() + for k := range om { + if _, ok := nm[k]; !ok { + configInSync = false + break + } + } + } + + if !reflect.DeepEqual(cfg.Options, newCfg.Options) { + configInSync = false + } + + // Activate and save + cfg = newCfg saveConfig() - configInSync = false } } diff --git a/config/config.go b/config/config.go index 865bf5c54..2c8b75551 100644 --- a/config/config.go +++ b/config/config.go @@ -126,6 +126,22 @@ type GUIConfiguration struct { APIKey string `xml:"apikey,omitempty"` } +func (cfg *Configuration) NodeMap() map[string]NodeConfiguration { + m := make(map[string]NodeConfiguration, len(cfg.Nodes)) + for _, n := range cfg.Nodes { + m[n.NodeID] = n + } + return m +} + +func (cfg *Configuration) RepoMap() map[string]RepositoryConfiguration { + m := make(map[string]RepositoryConfiguration, len(cfg.Repositories)) + for _, r := range cfg.Repositories { + m[r.ID] = r + } + return m +} + func setDefaults(data interface{}) error { s := reflect.ValueOf(data).Elem() t := s.Type() diff --git a/gui/app.js b/gui/app.js index ac77fdb7a..29417876d 100644 --- a/gui/app.js +++ b/gui/app.js @@ -268,6 +268,16 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) { $('#settings').modal({backdrop: 'static', keyboard: true}); }; + $scope.saveConfig = function() { + var cfg = JSON.stringify($scope.config); + var opts = {headers: {'Content-Type': 'application/json'}}; + $http.post(urlbase + '/config', cfg, opts).success(function () { + $http.get(urlbase + '/config/sync').success(function (data) { + $scope.configInSync = data.configInSync; + }); + }); + }; + $scope.saveSettings = function () { // Make sure something changed var changed = ! angular.equals($scope.config.Options, $scope.config.workingOptions) || @@ -281,10 +291,9 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) { // Apply new settings locally $scope.config.Options = angular.copy($scope.config.workingOptions); $scope.config.GUI = angular.copy($scope.config.workingGUI); - - $scope.configInSync = false; $scope.config.Options.ListenAddress = $scope.config.Options.ListenStr.split(',').map(function (x) { return x.trim(); }); - $http.post(urlbase + '/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}}); + + $scope.saveConfig(); } $('#settings').modal("hide"); @@ -358,14 +367,12 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) { }); } - $scope.configInSync = false; - $http.post(urlbase + '/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}}); + $scope.saveConfig(); }; $scope.saveNode = function () { var nodeCfg, done, i; - $scope.configInSync = false; $('#editNode').modal('hide'); nodeCfg = $scope.currentNode; nodeCfg.NodeID = nodeCfg.NodeID.replace(/ /g, '').replace(/-/g, '').toUpperCase().trim(); @@ -387,7 +394,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) { $scope.nodes.sort(nodeCompare); $scope.config.Nodes = $scope.nodes; - $http.post(urlbase + '/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}}); + $scope.saveConfig(); }; $scope.otherNodes = function () { @@ -462,7 +469,6 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) { $scope.saveRepo = function () { var repoCfg, done, i; - $scope.configInSync = false; $('#editRepo').modal('hide'); repoCfg = $scope.currentRepo; repoCfg.Nodes = []; @@ -490,7 +496,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) { $scope.repos[repoCfg.ID] = repoCfg; $scope.config.Repositories = repoList($scope.repos); - $http.post(urlbase + '/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}}); + $scope.saveConfig(); }; $scope.sharesRepo = function(repoCfg) { @@ -511,8 +517,7 @@ syncthing.controller('SyncthingCtrl', function ($scope, $http) { delete $scope.repos[$scope.currentRepo.ID]; $scope.config.Repositories = repoList($scope.repos); - $scope.configInSync = false; - $http.post(urlbase + '/config', JSON.stringify($scope.config), {headers: {'Content-Type': 'application/json'}}); + $scope.saveConfig(); }; $scope.setAPIKey = function (cfg) {