diff --git a/public/assets/pages/adminpage/ctrl_setup.css b/public/assets/pages/adminpage/ctrl_setup.css index 34d31019..d626983a 100644 --- a/public/assets/pages/adminpage/ctrl_setup.css +++ b/public/assets/pages/adminpage/ctrl_setup.css @@ -42,6 +42,52 @@ font-weight: bold; font-style: italic; } +.component_setup #step2 #onboarding { + position: fixed; + right: 32px; + bottom: 32px; + border-radius: 16px; + padding: 12px 18px; + color: var(--light); +} +.component_setup #step2 #onboarding .dash-border { + position: absolute; + inset: 0; + width: 100%; + height: 100%; +} +.component_setup #step2 #onboarding .dash-border rect { + width: calc(100% - 4px); + height: calc(100% - 4px); + fill: none; + stroke: #57595A; + stroke-width: 3; + stroke-linecap: round; + stroke-linejoin: round; + stroke-dasharray: 8 6; + animation: dash-move 1.2s linear infinite; +} +@keyframes dash-move { + to { stroke-dashoffset: -14; } +} +.component_setup #step2 #onboarding svg { + position: fixed; + inset: 0; + width: 100%; + height: 100%; + pointer-events: none; +} +.component_setup #step2 #onboarding svg path { + stroke-width: 3; + fill: none; + stroke-linecap: round; + stroke-linejoin: round; + stroke: #57595A; +} +.component_setup #step2 #onboarding svg g { + fill: #57595A; +} + .component_setup .stepper-form-appear, .component_setup .stepper-form-enter { transition-delay: 0.3s; transform: scale(1.02); @@ -58,3 +104,12 @@ .component_setup .component_icon { width: 30px; } + +.pulse { + animation: zoomPulse 1.2s ease-in-out infinite; + transform-origin: center left; +} +@keyframes zoomPulse { + 0%, 100% { transform: scale(1.03); } + 50% { transform: scale(1.07); } +} diff --git a/public/assets/pages/adminpage/ctrl_setup.js b/public/assets/pages/adminpage/ctrl_setup.js index d1357208..6c2b9770 100644 --- a/public/assets/pages/adminpage/ctrl_setup.js +++ b/public/assets/pages/adminpage/ctrl_setup.js @@ -117,6 +117,7 @@ function componentStep2(render) { You're at the Helm now
+
`); @@ -187,6 +188,8 @@ function componentStep2(render) { }; return ret.toPromise(); }; + + // feature: modal effect(getAdminConfig().pipe( reshapeConfigBeforeSave, rxjs.delay(300), @@ -197,7 +200,57 @@ function componentStep2(render) { config["log"]["telemetry"] = enabled; return config; }), - rxjs.filter((config) => !!config), - saveConfig(), + rxjs.mergeMap((config) => { + if (config) return rxjs.of(config).pipe(saveConfig()); + return rxjs.of(null); + }), + // feature: onboarding + rxjs.mapTo(createElement(` +
+ Next step: Link your storage + + + + + + + + + + + + + + +
+ `)), + applyMutation(qs($page, "[data-bind=\"onboarding\"]"), "appendChild"), + rxjs.delay(500), + rxjs.map(($origin) => { + const $target = document.querySelector("a[href=\"/admin/storage\"]"); + const $path = $origin.querySelector("svg path"); + const $anims = [ + $origin.querySelector("svg animate"), + $origin.querySelector("svg animateMotion"), + ]; + + const arc = (start, end) => { + const r = Math.min(Math.abs(end.x - start.x), Math.abs(end.y - start.y)) * 0.9; + return `M ${start.x},${start.y} ` + + `L ${start.x},${end.y + r} ` + + `Q ${start.x},${end.y} ${start.x - r},${end.y} ` + + `L ${end.x+20},${end.y+2}`; + }; + const o = $origin.getBoundingClientRect(); + const t = $target.getBoundingClientRect(); + $path.setAttribute("d", arc( + { x: o.left + o.width/2, y: o.top }, + { x: t.right, y: t.top + t.height/2 } + )); + $anims.forEach(($el) => $el.beginElement()); + $target.classList.add("pulse"); + return $origin; + }), + rxjs.switchMap(($node) => rxjs.fromEvent(window, "resize").pipe(rxjs.tap(() => $node.remove()))), )); } diff --git a/public/assets/pages/adminpage/decorator_sidemenu.css b/public/assets/pages/adminpage/decorator_sidemenu.css index 54076997..5fea57b5 100644 --- a/public/assets/pages/adminpage/decorator_sidemenu.css +++ b/public/assets/pages/adminpage/decorator_sidemenu.css @@ -32,6 +32,9 @@ bottom: 0; opacity: 0.25; } +.component_menu_sidebar ul li a { + display: inline-block; +} .component_menu_sidebar .header { display: block; height: 40px;