diff --git a/src/Ui/media/Infopanel.coffee b/src/Ui/media/Infopanel.coffee new file mode 100644 index 00000000..b5e367a8 --- /dev/null +++ b/src/Ui/media/Infopanel.coffee @@ -0,0 +1,18 @@ +class Infopanel + constructor: (@elem) -> + @visible = false + + show: -> + @elem.addClass("visible") + + hide: -> + @elem.removeClass("visible") + + setTitle: (line1, line2) -> + @elem.find(".line-1").text(line1) + @elem.find(".line-2").text(line2) + + setAction: (title, func) -> + @elem.find(".button").text(title).off("click").on("click", func) + +window.Infopanel = Infopanel diff --git a/src/Ui/media/Wrapper.coffee b/src/Ui/media/Wrapper.coffee index ed4363a8..b2a75f19 100644 --- a/src/Ui/media/Wrapper.coffee +++ b/src/Ui/media/Wrapper.coffee @@ -4,6 +4,7 @@ class Wrapper @loading = new Loading(@) @notifications = new Notifications($(".notifications")) + @infopanel = new Infopanel($(".infopanel")) @fixbutton = new Fixbutton() window.addEventListener("message", @onMessageInner, false) @@ -186,6 +187,8 @@ class Wrapper @actionRequestFullscreen() else # Send to websocket if message.id < 1000000 + if message.cmd == "fileWrite" and not @modified_panel_updater_timer + @modified_panel_updater_timer = setTimeout ( => @updateModifiedPanel(); @modified_panel_updater_timer = null ), 1000 @ws.send(message) # Pass message to websocket else @log "Invalid inner message id" @@ -533,9 +536,58 @@ class Wrapper if @loading.screen_visible and @inner_loaded and site_info.settings.size < site_info.size_limit*1024*1024 and site_info.settings.size > 0 # Loading screen still visible, but inner loaded @loading.hideScreen() + if site_info?.settings?.own and site_info?.settings?.modified != @site_info?.settings?.modified + @updateModifiedPanel() + @site_info = site_info @event_site_info.resolve() + siteSign: (inner_path, cb) => + if @site_info.privatekey + # Privatekey stored in users.json + @infopanel.elem.find(".button").addClass("loading") + @ws.cmd "siteSign", {privatekey: "stored", inner_path: inner_path, update_changed_files: true}, (res) => + if res == "ok" + cb?(true) + else + cb?(false) + @infopanel.elem.find(".button").removeClass("loading") + else + # Ask the user for privatekey + @displayPrompt "Enter your private key:", "password", "Sign", "", (privatekey) => # Prompt the private key + @infopanel.elem.find(".button").addClass("loading") + @ws.cmd "siteSign", {privatekey: privatekey, inner_path: inner_path, update_changed_files: true}, (res) => + if res == "ok" + cb?(true) + else + cb?(false) + @infopanel.elem.find(".button").removeClass("loading") + + sitePublish: (inner_path) => + @ws.cmd "sitePublish", {"inner_path": inner_path, "sign": false} + + updateModifiedPanel: => + @ws.cmd "siteListModifiedFiles", [], (res) => + num = res.modified_files.length + if num > 0 + @infopanel.show() + else + @infopanel.hide() + + if num > 0 + @infopanel.setTitle( + "#{res.modified_files.length} modified file#{if num > 1 then 's' else ''}", + res.modified_files.join(", ") + ) + @infopanel.setAction "Sign & Publish", => + @siteSign "content.json", (res) => + if (res) + @notifications.add "sign", "done", "content.json Signed!", 5000 + @sitePublish("content.json") + return false + + @log "siteListModifiedFiles", res + setAnnouncerInfo: (announcer_info) -> status_db = {announcing: [], error: [], announced: []} for key, val of announcer_info.stats diff --git a/src/Ui/media/Wrapper.css b/src/Ui/media/Wrapper.css index e7c0f54a..cfc1a9b5 100644 --- a/src/Ui/media/Wrapper.css +++ b/src/Ui/media/Wrapper.css @@ -104,6 +104,18 @@ a { color: black } .icon-success { left:6px; width:5px; height:12px; border-width:0 5px 5px 0; border-style:solid; border-color:white; margin-left: 20px; margin-top: 15px; transform:rotate(45deg) } +/* Infopanel */ +.infopanel { + position: absolute; z-index: 999; padding: 15px 15px; bottom: 55px; right: 50px; border: 1px solid #eff3fe; display: none; + font-family: 'Lucida Grande', 'Segoe UI', Helvetica, Arial, sans-serif; box-shadow: 0px 10px 55px rgba(58, 39, 176, 0.17); background-color: white; + border-left: 4px solid #9a61f8; border-top-left-radius: 4px; border-bottom-left-radius: 4px; transition: all 0.7s ease-in-out; +} +.infopanel.visible { display: block; } +.infopanel .message { font-size: 13px; line-height: 15px; display: inline-block; vertical-align: -9px; } +.infopanel .message .line { max-width: 200px; display: inline-block; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } +.infopanel .message .line-1 { font-weight: bold; } +.body-sidebar .infopanel { right: 425px; } + /* Loading screen */ .loadingscreen { width: 100%; height: 100%; position: absolute; background-color: #EEE; z-index: 1; overflow: hidden; display: none } diff --git a/src/Ui/media/all.css b/src/Ui/media/all.css index e5201abf..342d1302 100644 --- a/src/Ui/media/all.css +++ b/src/Ui/media/all.css @@ -118,6 +118,18 @@ a { color: black } .icon-success { left:6px; width:5px; height:12px; border-width:0 5px 5px 0; border-style:solid; border-color:white; margin-left: 20px; margin-top: 15px; transform:rotate(45deg) } +/* Infopanel */ +.infopanel { + position: absolute; z-index: 999; padding: 15px 15px; bottom: 55px; right: 50px; border: 1px solid #eff3fe; display: none; + font-family: 'Lucida Grande', 'Segoe UI', Helvetica, Arial, sans-serif; -webkit-box-shadow: 0px 10px 55px rgba(58, 39, 176, 0.17); -moz-box-shadow: 0px 10px 55px rgba(58, 39, 176, 0.17); -o-box-shadow: 0px 10px 55px rgba(58, 39, 176, 0.17); -ms-box-shadow: 0px 10px 55px rgba(58, 39, 176, 0.17); box-shadow: 0px 10px 55px rgba(58, 39, 176, 0.17) ; background-color: white; + border-left: 4px solid #9a61f8; border-top-left-radius: 4px; border-bottom-left-radius: 4px; -webkit-transition: all 0.7s ease-in-out; -moz-transition: all 0.7s ease-in-out; -o-transition: all 0.7s ease-in-out; -ms-transition: all 0.7s ease-in-out; transition: all 0.7s ease-in-out ; +} +.infopanel.visible { display: block; } +.infopanel .message { font-size: 13px; line-height: 15px; display: inline-block; vertical-align: -9px; } +.infopanel .message .line { max-width: 200px; display: inline-block; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } +.infopanel .message .line-1 { font-weight: bold; } +.body-sidebar .infopanel { right: 425px; } + /* Loading screen */ .loadingscreen { width: 100%; height: 100%; position: absolute; background-color: #EEE; z-index: 1; overflow: hidden; display: none } diff --git a/src/Ui/media/all.js b/src/Ui/media/all.js index 026afb5a..6953a92f 100644 --- a/src/Ui/media/all.js +++ b/src/Ui/media/all.js @@ -540,6 +540,44 @@ $.extend( $.easing, }).call(this); +/* ---- src/Ui/media/Infopanel.coffee ---- */ + + +(function() { + var Infopanel; + + Infopanel = (function() { + function Infopanel(elem) { + this.elem = elem; + this.visible = false; + } + + Infopanel.prototype.show = function() { + return this.elem.addClass("visible"); + }; + + Infopanel.prototype.hide = function() { + return this.elem.removeClass("visible"); + }; + + Infopanel.prototype.setTitle = function(line1, line2) { + this.elem.find(".line-1").text(line1); + return this.elem.find(".line-2").text(line2); + }; + + Infopanel.prototype.setAction = function(title, func) { + return this.elem.find(".button").text(title).off("click").on("click", func); + }; + + return Infopanel; + + })(); + + window.Infopanel = Infopanel; + +}).call(this); + + /* ---- src/Ui/media/Loading.coffee ---- */ @@ -835,6 +873,9 @@ $.extend( $.easing, function Wrapper(ws_url) { this.reloadIframe = bind(this.reloadIframe, this); this.setSizeLimit = bind(this.setSizeLimit, this); + this.updateModifiedPanel = bind(this.updateModifiedPanel, this); + this.sitePublish = bind(this.sitePublish, this); + this.siteSign = bind(this.siteSign, this); this.onWrapperLoad = bind(this.onWrapperLoad, this); this.onPageLoad = bind(this.onPageLoad, this); this.onCloseWebsocket = bind(this.onCloseWebsocket, this); @@ -847,6 +888,7 @@ $.extend( $.easing, this.log("Created!"); this.loading = new Loading(this); this.notifications = new Notifications($(".notifications")); + this.infopanel = new Infopanel($(".infopanel")); this.fixbutton = new Fixbutton(); window.addEventListener("message", this.onMessageInner, false); this.inner = document.getElementById("inner-iframe").contentWindow; @@ -1071,6 +1113,14 @@ $.extend( $.easing, return this.actionRequestFullscreen(); } else { if (message.id < 1000000) { + if (message.cmd === "fileWrite" && !this.modified_panel_updater_timer) { + this.modified_panel_updater_timer = setTimeout(((function(_this) { + return function() { + _this.updateModifiedPanel(); + return _this.modified_panel_updater_timer = null; + }; + })(this)), 1000); + } return this.ws.send(message); } else { return this.log("Invalid inner message id"); @@ -1530,6 +1580,7 @@ $.extend( $.easing, }; Wrapper.prototype.setSiteInfo = function(site_info) { + var ref, ref1, ref2, ref3; if (site_info.event != null) { if (site_info.event[0] === "file_added" && site_info.bad_files) { this.loading.printLine(site_info.bad_files + " files needs to be downloaded"); @@ -1584,10 +1635,93 @@ $.extend( $.easing, if (this.loading.screen_visible && this.inner_loaded && site_info.settings.size < site_info.size_limit * 1024 * 1024 && site_info.settings.size > 0) { this.loading.hideScreen(); } + if ((site_info != null ? (ref = site_info.settings) != null ? ref.own : void 0 : void 0) && (site_info != null ? (ref1 = site_info.settings) != null ? ref1.modified : void 0 : void 0) !== ((ref2 = this.site_info) != null ? (ref3 = ref2.settings) != null ? ref3.modified : void 0 : void 0)) { + this.updateModifiedPanel(); + } this.site_info = site_info; return this.event_site_info.resolve(); }; + Wrapper.prototype.siteSign = function(inner_path, cb) { + if (this.site_info.privatekey) { + this.infopanel.elem.find(".button").addClass("loading"); + return this.ws.cmd("siteSign", { + privatekey: "stored", + inner_path: inner_path, + update_changed_files: true + }, (function(_this) { + return function(res) { + if (res === "ok") { + if (typeof cb === "function") { + cb(true); + } + } else { + if (typeof cb === "function") { + cb(false); + } + } + return _this.infopanel.elem.find(".button").removeClass("loading"); + }; + })(this)); + } else { + return this.displayPrompt("Enter your private key:", "password", "Sign", "", (function(_this) { + return function(privatekey) { + _this.infopanel.elem.find(".button").addClass("loading"); + return _this.ws.cmd("siteSign", { + privatekey: privatekey, + inner_path: inner_path, + update_changed_files: true + }, function(res) { + if (res === "ok") { + if (typeof cb === "function") { + cb(true); + } + } else { + if (typeof cb === "function") { + cb(false); + } + } + return _this.infopanel.elem.find(".button").removeClass("loading"); + }); + }; + })(this)); + } + }; + + Wrapper.prototype.sitePublish = function(inner_path) { + return this.ws.cmd("sitePublish", { + "inner_path": inner_path, + "sign": false + }); + }; + + Wrapper.prototype.updateModifiedPanel = function() { + return this.ws.cmd("siteListModifiedFiles", [], (function(_this) { + return function(res) { + var num; + num = res.modified_files.length; + if (num > 0) { + _this.infopanel.show(); + } else { + _this.infopanel.hide(); + } + if (num > 0) { + _this.infopanel.setTitle(res.modified_files.length + " modified file" + (num > 1 ? 's' : ''), res.modified_files.join(", ")); + _this.infopanel.setAction("Sign & Publish", function() { + _this.siteSign("content.json", function(res) { + if (res) { + _this.notifications.add("sign", "done", "content.json Signed!", 5000); + return _this.sitePublish("content.json"); + } + }); + return false; + }); + } + return _this.log("siteListModifiedFiles", res); + }; + })(this)); + }; + Wrapper.prototype.setAnnouncerInfo = function(announcer_info) { var key, ref, status_db, status_line, val; status_db = { diff --git a/src/Ui/template/wrapper.html b/src/Ui/template/wrapper.html index ec7fcf87..eefb8d44 100644 --- a/src/Ui/template/wrapper.html +++ b/src/Ui/template/wrapper.html @@ -50,6 +50,10 @@ else if (window.opener && window.opener.location.toString()) {
! Test notification×
+ +
+
8 modified files
content.json, data.json
Sign & Publish +