diff --git a/plugins/c9.ide.restore/restore.css b/plugins/c9.ide.restore/restore.css new file mode 100644 index 00000000..9570de16 --- /dev/null +++ b/plugins/c9.ide.restore/restore.css @@ -0,0 +1,259 @@ +#c9_ide_restore { + display: none; + z-index: 1000000; + position: absolute; + height: 100%; + left: 0; + right: 0; + top: 0; + bottom: 0; +} + +#c9_ide_restore .timeout a { + color: #FFDE75; + text-decoration: none; +} + +#c9_ide_restore .timeout { + position: relative; + background: #DA7A30; + z-index: 10000000; + color: white; + padding: 5px; + border-radius: 3px; + margin: 10px; + text-align: center; + display: none; +} + +/* progress 3C7B0D*/ +#restoring { + font-style: normal; + height: 100%; + width: 100%; + position: fixed; + text-align: center; + z-index: 100000; + left: 0; + top: 0; + .font-smoothing(~"antialiased !important"); + background: white url("@{image-path}/loadingbgrepeat.png"); + background-size: 1px 8px; +} +.dark #restoring{ + background: black url("@{image-path}/loadingbgrepeat_dark.png"); + background-size: 1px 8px; +} + +#restoring .loading-progress { + font-size: 31px; + color: #4A8532; + height: 37px; + position: relative; + margin: 252px 0 0 0; + top: 30%; +} +#restoring .loading-msg { + color: #717171; + .font-smoothing(true); + margin: 58px 0 10px; +} +#restoring .loading-details{ + margin: 3px 0 0 0; + font-size: 14px; + color: #858E91; + .font-smoothing(true); + font-weight: bold; +} + +.stickynote { + position: absolute; + top: 30%; + left: 50%; + margin: 0px -261px; + z-index : 10000000; + .transform(~"rotate(2deg)"); +} +.stickynote.casual{ + bottom: 50px; + right: 50px; + left: auto; + top: auto; + margin: 0; +} +.stickynote .paper { + color: black; + width: 284px; + /*color: #f1f1f1;*/ + background: #FFDE75; + padding: 25px 20px 10px 20px; + box-shadow: 1px 1px 15px rgba(0,0,0,0.12); + // font-family : Tahoma; + font-size : 15px; + text-align : left; + .font-smoothing(true); +} +.stickynote strong { + font-size: 17px; +} +.stickynote a.restore-upsell { + text-decoration: none; + display: inline-block; + padding: 5px 10px 8px 10px; + background: #39A6D7; + border-radius: 5px; + color: white; + margin-bottom: -10px; +} +.stickynote a.restore-upsell:hover { + background: #0FB6FF; +} +.stickynote .tape { + position: absolute; + top: -15px; + right: 80px; + width: 130px; + height: 35px; + background-color: rgba(255, 255, 255, 0.6); + border-left: 1px dashed rgba(0, 0, 0, 0.1); + border-right: 1px dashed rgba(0, 0, 0, 0.1); + + .box-shadow(~"0px 0px 1px 0px rgba(204, 204, 204, 0.28)"); + .transform(~"rotate(-2deg) skew(0,0) translate(0%,-5px)"); +} +.stickynote .left-shadow { + width: 140px; + height: 140px; + bottom: -5px; + left: -12px; + position: absolute; + z-index: -6; + display: inline-block; + .box-shadow(~"-10px -10px 10px rgba(0, 0, 0, 0.12)"); + .transform(~"scale(1) rotate(274deg) translate(20px, 25px) skew(9deg, 0deg)"); +} +.stickynote .right-shadow { + width: 140px; + height: 140px; + bottom: -13px; + right: -4px; + position: absolute; + z-index: -6; + display: inline-block; + .box-shadow(~"-10px -10px 10px rgba(0, 0, 0, 0.12)"); + .transform(~"scale(1) rotate(184deg) translate(20px, 25px) skew(9deg, 0deg)"); +} + +/* +Copyright (c) 2010-2012 Ivan Vanderbyl +Originally found at http://ivan.ly/ui + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +/* Webkit animation keyframes */ +@-webkit-keyframes animate-stripes { + to { + background-position: 0 0; + } + + from { + background-position: 44px 0; + } +} + +@-moz-keyframes animate-stripes { + to { + background-position: 0 0; + } + + from { + background-position: 36px 0; + } +} + +/* Bar which is placed behind the progress */ +.ui-progress-bar { + /* Usual setup stuff */ + position: relative; + width: 240px; + margin: 15px auto 10px; + height: 8px; + /* Pad right so we don't cover the borders when fully progressed */ + /* For browser that don't support gradients, we'll set a blanket background colour */ + background-color: rgba(157, 167, 171, 0.42); + .border-radius(~"10px"); +} +.ui-progress-bar.blue .ui-progress { + background-color: #339BB9!important; + border: 1px solid #287a91; +} +.ui-progress-bar.error .ui-progress { + background-color: #C43C35 !important; + border: 1px solid #9c302a; +} +.ui-progress-bar.warning .ui-progress { + background-color: #D9B31A!important; + border: 1px solid #ab8d15; +} +.ui-progress-bar.success .ui-progress { + background-color: #57A957!important; + border: 1px solid #458845; +} +.ui-progress-bar.transition .ui-progress { + .transition(~"background-color 0.5s ease-in, border-color 1.5s ease-out, box-shadow 1.5s ease-out") +} +.ui-progress-bar .ui-progress { + /* Usual setup stuff */ + position: relative; + display: block; + overflow: hidden; + /* Height should be 2px less than .ui-progress-bar so as to not cover borders and give it a look of being inset */ + height: 8px; + /* Rounds the ends, we specify an excessive amount to make sure they are completely rounded */ + /* Adjust to your liking, and don't forget to adjust to the same amount in .ui-progress-bar */ + .border-radius(~"10px"); + /* Webkit background stripes and gradient */ + background: -webkit-gradient(linear, 0 0, 44 44, color-stop(0, rgba(0, 0, 0, 0.17)), color-stop(0.25, rgba(0, 0, 0, 0.17)), color-stop(0.26, rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0)), color-stop(0.51, rgba(0, 0, 0, 0.17)), color-stop(0.75, rgba(0, 0, 0, 0.17)), color-stop(0.76, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0))), -webkit-gradient(linear, left bottom, left top, color-stop(0, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0.35))), #EAF9FF; + background: -moz-repeating-linear-gradient(top left -30deg, rgba(0, 0, 0, 0.17), rgba(0, 0, 0, 0.17) 15px, rgba(0, 0, 0, 0) 15px, rgba(0, 0, 0, 0) 30px), -moz-linear-gradient(rgba(0, 0, 0, 0.25) 0%, rgba(0, 0, 0, 0) 100%), #EAF9FF; + + /* Set the background size so the stripes work correctly */ + -webkit-background-size: 44px 44px; + -moz-background-size: 36px 36px; + + /* Animate */ + -moz-animation: animate-stripes 2s linear infinite; + -webkit-animation: animate-stripes 2s linear infinite; + -o-animation: animate-stripes 2s linear infinite; + -ms-animation: animate-stripes 2s linear infinite; + -khtml-animation: animate-stripes 2s linear infinite; + animation: animate-stripes 2s linear infinite; + + /* Style status label */ + top:0px; + left:0px; +} +.dark .ui-progress-bar .ui-progress { + background: -webkit-gradient(linear, 0 0, 44 44, color-stop(0, rgba(0, 0, 0, 0.17)), color-stop(0.25, rgba(0, 0, 0, 0.17)), color-stop(0.26, rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0)), color-stop(0.51, rgba(0, 0, 0, 0.17)), color-stop(0.75, rgba(0, 0, 0, 0.17)), color-stop(0.76, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0))), -webkit-gradient(linear, left bottom, left top, color-stop(0, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0.35))), #4ACBFD; + background: -moz-repeating-linear-gradient(top left -30deg, rgba(0, 0, 0, 0.17), rgba(0, 0, 0, 0.17) 15px, rgba(0, 0, 0, 0) 15px, rgba(0, 0, 0, 0) 30px), -moz-linear-gradient(rgba(0, 0, 0, 0.25) 0%, rgba(0, 0, 0, 0) 100%), #4ACBFD; + + /* Set the background size so the stripes work correctly */ + -webkit-background-size: 44px 44px; + -moz-background-size: 36px 36px; +} \ No newline at end of file diff --git a/plugins/c9.ide.restore/restore.html b/plugins/c9.ide.restore/restore.html new file mode 100644 index 00000000..a9f71162 --- /dev/null +++ b/plugins/c9.ide.restore/restore.html @@ -0,0 +1,37 @@ +
+ We create a separate virtual machine for each workspace.
+ In order to provide a free
+ service for everyone, we hibernate workspaces of
+
+ Please wait a moment while we wake up your workspace. It will + be just as you left it. +
+ Upgrade to premium to make sure your workspace never + goes into hibernate. +
\n" + + "In order to provide a free\n" + + "service for everyone, we stop workspaces after a while.\n" + + "
\n" + + "Premium plans offer active workspaces, which ensure that the " + MAX_HOT_WORKSPACES + "\n" + + "most recently used workspaces are never stopped.\n" + + "
\n" + + "Upgrade to premium now"; + + var premiumStoppedDescription = + "Swapping in Workspace\n" + + "
\n" + + "This workspace is not one of your active workspaces and has been stopped.\n" + + "
\n" + + "The " + MAX_HOT_WORKSPACES + " most recently used workspaces are never stopped.\n" + + "
\n" + + "As part of a team plan you have more active workspaces.\n" + + "
\n" + + "Upgrade to team plans now"; + + var migrateDescription = + "What's going on here?\n" + + "
\n" + + "We rolled out a completely new backend infrastructure with \n" + + "improved performance and lots of new features.\n" + + "
\n" + + "With the new backend you get:\n" + + "
\n" + + "Please wait a moment while we move your workspace. It will\n" + + "be just as you left it.\n"; + + var premiumDescription = + "What's going on here?\n" + + "
\n" + + "We're migrating your premium workspace to a new server \n" + + "to ensure optimal performance.\n" + + "
\n" + + "Please wait a moment while we move your workspace. It will\n" + + "be just as you left it.\n"; + + var resizeDescription = + "What's going on here?\n" + + "
\n" + + "We're resizing your workspace\n" + + "to be exactly as you specified.\n" + + "
\n" + + "Please wait a moment while we resize your workspace.\n" + + "It will be just as you left it.\n"; + + var stateDescriptions = { + free: { casual: [STATE_MIGRATING, STATE_RESIZING] }, + premium: { casual: [STATE_MIGRATING, STATE_MARKED_FOR_ARCHIVE, STATE_ARCHIVING, STATE_ARCHIVED, STATE_MARKED_FOR_RESTORE, STATE_RESTORING, STATE_RESIZING] }, + }; + + stateDescriptions.free[STATE_CREATED] = ""; + stateDescriptions.free[STATE_READY] = description; + stateDescriptions.free[STATE_MIGRATING] = migrateDescription; // different location + stateDescriptions.free[STATE_MARKED_FOR_ARCHIVE] = description; + stateDescriptions.free[STATE_ARCHIVING] = description; + stateDescriptions.free[STATE_ARCHIVED] = description; + stateDescriptions.free[STATE_MARKED_FOR_RESTORE] = description; + stateDescriptions.free[STATE_RESTORING] = description; + stateDescriptions.free[STATE_RESIZING] = resizeDescription; // different location + + stateDescriptions.premium[STATE_CREATED] = ""; + stateDescriptions.premium[STATE_READY] = premiumStoppedDescription; + stateDescriptions.premium[STATE_MIGRATING] = migrateDescription; // different location + stateDescriptions.premium[STATE_MARKED_FOR_ARCHIVE] = premiumDescription; // different location + stateDescriptions.premium[STATE_ARCHIVING] = premiumDescription; // different location + stateDescriptions.premium[STATE_ARCHIVED] = premiumDescription; // different location + stateDescriptions.premium[STATE_MARKED_FOR_RESTORE] = premiumDescription; // different location + stateDescriptions.premium[STATE_RESTORING] = premiumDescription; // different location + stateDescriptions.premium[STATE_RESIZING] = resizeDescription; // different location + + var loaded = false; + function load() { + if (loaded) return false; + loaded = true; + + endpoint.on("restore", showRestore); + vfs.on("connect", hideRestore); + } + + var drawn = false; + function draw() { + if (drawn) return false; + drawn = true; + + ui.insertCss(require("text!./restore.css"), plugin); + ui.insertHtml(null, require("text!./restore.html"), plugin); + + el = document.getElementById("c9_ide_restore"); + msgEl = document.querySelector("#c9_ide_restore .loading-msg"); + detailsEl = document.querySelector("#c9_ide_restore .loading-details"); + descriptionEl = document.querySelector("#c9_ide_restore .paper"); + stickynoteEl = document.querySelector("#c9_ide_restore .stickynote"); + uiProgress = document.querySelector("#progress_bar .ui-progress"); + timeoutEl = document.querySelector("#c9_ide_restore .timeout"); + } + + /***** Methods *****/ + + var progress, maxProgress, run = 0, timer; + + function animateProgress(progress, callback) { + anims.animate(uiProgress, { + width: progress + "%", + timingFunction: "cubic-bezier(.02, .01, .47, 1)", + duration: "1s" + }, callback); + } + + function walk(loopId) { + if (loopId != run) return; + + if (progress > 100) + return; + + if (progress > maxProgress) + return (timer = setTimeout(walk.bind(null, loopId), 500)); + + animateProgress(progress++, function(){ + timer = setTimeout(walk.bind(null, loopId), 10); + }); + } + + function showTimeout(){ + timeoutEl.style.display = "block"; + } + + function showRestore(state) { + draw(); + + c9.startLoadTime = -1; + + if (el.style.display != "block") { + uiProgress.style.width = 0; + progress = 6; + maxProgress = 10; + } + + var isDark = layout.theme.indexOf("dark") > -1; + if (isDark) + el.classList.add("dark"); + else + el.classList.remove("dark"); + + var descriptions = stateDescriptions[state.premium ? "premium" : "free"]; + var description = descriptions[state.projectState || STATE_ARCHIVED]; + msgEl.innerText = stateMessages[state.projectState || STATE_ARCHIVED] || defaultStateMessage; + + if (description) { + descriptionEl.innerHTML = description; + var link = descriptionEl.querySelector("a.restore-upsell"); + if (link) + link.addEventListener("click", trackLink, false); + + stickynoteEl.style.display = "block"; + + if (~descriptions.casual.indexOf(state.projectState || STATE_ARCHIVED)) + stickynoteEl.classList.add("casual"); + else + stickynoteEl.classList.remove("casual"); + } + else { + stickynoteEl.style.display = "none"; + } + + // we did not receive JSON + if (!state.progress || state.progress.nextProgress == 100) + return hideRestore(); + + // Display Message to the User + if (!/^Internal/.test(state.progress.message)) + detailsEl.innerText = state.progress.message || ""; + + // Update Progress Bar + maxProgress = Math.max(maxProgress || 0, state.progress.nextProgress); + progress = Math.max(progress || 0, state.progress.progress); + + walk(++run); + + // Show Restore Screen + el.style.display = "block"; + + clearTimeout(timeoutTimer); + timeoutTimer = setTimeout(function(){ + showTimeout(); + }, TIMEOUT_TIME) + } + + function trackLink(e) { + var el = e.target; + analytics.track("Clicked Internal Link", { + href: el.href, + linkId: el.dataset.linkId + }); + } + + function hideRestore() { + if (!el) return; + + clearTimeout(timer); + + progress = 101; + animateProgress(100, function(){ + setTimeout(function(){ + anims.animate(el, { + opacity: 0 + }, function(){ + el.style.display = "none"; + el.style.opacity = 1; + + timeoutEl.style.display = ""; + }); + }, 100); + }); + + } + + /***** Lifecycle *****/ + + plugin.on("load", function(){ + load(); + }); + + /***** Register and define API *****/ + + /** + * + **/ + plugin.freezePublicAPI({ + show: showRestore, + hide: hideRestore + }); + + register(null, { "restore" : plugin }); + } +});