mirror of
https://github.com/mickael-kerjean/filestash
synced 2025-12-15 21:04:46 +01:00
feature (admin): setup page
This commit is contained in:
parent
1c1f8b5052
commit
4217fb9ca3
4 changed files with 215 additions and 4 deletions
|
|
@ -20,6 +20,7 @@
|
|||
"/admin/settings": "/pages/adminpage/ctrl_settings.js",
|
||||
"/admin/logs": "/pages/adminpage/ctrl_logger.js",
|
||||
"/admin/about": "/pages/adminpage/ctrl_about.js",
|
||||
"/admin/setup": "/pages/adminpage/ctrl_setup.js",
|
||||
"/admin/": "/pages/adminpage/ctrl_home.js",
|
||||
|
||||
"/logout": "/pages/ctrl_logout.js",
|
||||
|
|
|
|||
79
public/pages/adminpage/ctrl_setup.css
Normal file
79
public/pages/adminpage/ctrl_setup.css
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
.component_setup {
|
||||
transform: none !important;
|
||||
}
|
||||
.component_setup h4 {
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
font-weight: 500;
|
||||
padding: 20px 0 0px 0;
|
||||
}
|
||||
.component_setup h4 .component_icon {
|
||||
vertical-align: text-top;
|
||||
width: 1.3em;
|
||||
cursor: pointer;
|
||||
}
|
||||
.component_setup h4 .component_icon[alt="loading"] {
|
||||
opacity: 0;
|
||||
}
|
||||
.component_setup #step1 p {
|
||||
font-size: 1.1em;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.component_setup #step1 form {
|
||||
max-width: 400px;
|
||||
}
|
||||
.component_setup #step1 form {
|
||||
display: flex;
|
||||
background: white;
|
||||
border-radius: 2px;
|
||||
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.component_setup #step1 form input {
|
||||
padding: 15px 20px;
|
||||
border-bottom: 0;
|
||||
margin: 0;
|
||||
height: inherit !important;
|
||||
}
|
||||
.component_setup #step1 form button {
|
||||
width: inherit;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.component_setup #step1 form button .component_icon {
|
||||
height: 25px;
|
||||
}
|
||||
.component_setup #step2 .component_dependency_installed {
|
||||
margin: 10px 0;
|
||||
padding: 10px 10px;
|
||||
border-radius: 3px;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
.component_setup #step2 .component_dependency_installed.yes {
|
||||
background: var(--success);
|
||||
}
|
||||
.component_setup #step2 .component_dependency_installed.no {
|
||||
background: var(--primary);
|
||||
}
|
||||
.component_setup #step2 .component_dependency_installed.no.severe {
|
||||
background: var(--error);
|
||||
}
|
||||
.component_setup #step2 .component_dependency_installed.no.severe span {
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
.component_setup .stepper-form-appear, .component_setup .stepper-form-enter {
|
||||
transition-delay: 0.3s;
|
||||
transform: scale(1.02);
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.component_setup .stepper-form-appear.stepper-form-appear-active,
|
||||
.component_setup .stepper-form-appear.stepper-form-enter-active,
|
||||
.component_setup .stepper-form-enter.stepper-form-appear-active,
|
||||
.component_setup .stepper-form-enter.stepper-form-enter-active {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
.component_setup .component_icon {
|
||||
width: 30px;
|
||||
}
|
||||
|
|
@ -1,6 +1,137 @@
|
|||
import { createElement } from "../../lib/skeleton/index.js";
|
||||
import { createElement, createRender } from "../../lib/skeleton/index.js";
|
||||
import rxjs, { effect, stateMutation, applyMutation, preventDefault } from "../../lib/rxjs/index.js";
|
||||
import { qs } from "../../lib/dom/index.js";
|
||||
import { ApplicationError } from "../../lib/error/index.js";
|
||||
import { transition, opacityOut } from "../../lib/animate/index.js";
|
||||
|
||||
export default function(render) {
|
||||
import CSSLoader from "../../helpers/css.js";
|
||||
import ctrlError from "../ctrl_error.js";
|
||||
import WithShell from "./decorator_sidemenu.js";
|
||||
import { zoomIn } from "./animate.js";
|
||||
|
||||
import "../../components/icon.js";
|
||||
|
||||
const stepper$ = new rxjs.BehaviorSubject(1);
|
||||
|
||||
export default function(render) {
|
||||
const $page = createElement(`
|
||||
<div class="component_setup">
|
||||
<div data-bind="multistep-form"></div>
|
||||
<style>${css}</style>
|
||||
</div>
|
||||
`);
|
||||
render($page);
|
||||
|
||||
effect(stepper$.pipe(
|
||||
dbg("CHANGE"),
|
||||
rxjs.map((step) => {
|
||||
switch(step) {
|
||||
case 1: return WithShell(componentStep1);
|
||||
case 2: return WithShell(componentStep2);
|
||||
default: throw new ApplicationError("INTERNAL_ERROR", "Assumption failed");
|
||||
}
|
||||
}),
|
||||
rxjs.tap((ctrl) => ctrl(createRender(qs($page, `[data-bind="multistep-form"]`)))),
|
||||
rxjs.catchError((err) => ctrlError(err)(render)),
|
||||
));
|
||||
};
|
||||
|
||||
const cssHideMenu = `.component_menu_sidebar{transform: translateX(-300px)}`;
|
||||
|
||||
function componentStep1(render) {
|
||||
const $page = createElement(`
|
||||
<div id="step1">
|
||||
<h4>Admin Password</h4>
|
||||
<div>
|
||||
<p>Create your instance admin password: </p>
|
||||
<form>
|
||||
<input class="component_input" type="password" placeholder="Password" />
|
||||
<button theme="transparent">
|
||||
<component-icon name="arrow_right"></component-icon>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<style>${cssHideMenu}</style>
|
||||
</div>
|
||||
`);
|
||||
render(transition($page, {
|
||||
timeoutEnter: 250, enter: zoomIn(1.2),
|
||||
timeoutLeave: 0,
|
||||
}));
|
||||
render($page);
|
||||
|
||||
// feature: form handling
|
||||
effect(rxjs.fromEvent(qs($page, "form"), "submit").pipe(
|
||||
preventDefault(),
|
||||
rxjs.mapTo(["name", "loading"]), applyMutation(qs($page, "component-icon"), "setAttribute"),
|
||||
rxjs.map(() => qs($page, "input").value),
|
||||
rxjs.delay(1000),
|
||||
dbg("SUBMIT"),
|
||||
animateOut($page),
|
||||
dbg("after merge"),
|
||||
rxjs.tap(() => stepper$.next(2)),
|
||||
));
|
||||
|
||||
// feature: autofocus
|
||||
effect(rxjs.of([]).pipe(
|
||||
applyMutation(qs($page, "input"), "focus"),
|
||||
));
|
||||
}
|
||||
|
||||
// const css = await CSSLoader(import.meta, "ctrl_setup.css");
|
||||
function componentStep2(render) {
|
||||
const deps = [];
|
||||
const $page = createElement(`
|
||||
<div id="step2">
|
||||
<h4>
|
||||
<component-icon name="arrow_left" data-bind="previous"></component-icon>
|
||||
Summary
|
||||
</h4>
|
||||
${deps.map((t) => t.label).join("")}
|
||||
<style>${cssHideMenu}</style>
|
||||
</div>`);
|
||||
render($page);
|
||||
|
||||
// feature: navigate previous step
|
||||
effect(rxjs.fromEvent(qs($page, `[data-bind="previous"]`), "click").pipe(
|
||||
dbg("click"),
|
||||
rxjs.tap(() => stepper$.next(1)),
|
||||
));
|
||||
|
||||
// feature: animate the screen
|
||||
effect(rxjs.of([]).pipe(
|
||||
rxjs.tap(() => qs($page, "h4").animate([
|
||||
{ transform: "translateX(30px)", opacity: "0"},
|
||||
{ transform: "translateX(0px)", opacity: "1"},
|
||||
], {
|
||||
duration: 200,
|
||||
fill: "forwards",
|
||||
})),
|
||||
rxjs.delay(200),
|
||||
applyMutation(qs($page, "style"), "remove"),
|
||||
dbg("")
|
||||
));
|
||||
|
||||
|
||||
// feature: opt in for telemetry
|
||||
// onDestroy()
|
||||
}
|
||||
|
||||
const animateOut = ($el) => {
|
||||
return rxjs.pipe(
|
||||
dbg("animate: "+ opacityOut()),
|
||||
// rxjs.tap(() => transition($el, {
|
||||
// timeoutEnter: 500, enter: opacityOut(),
|
||||
// timeoutLeave: 0,
|
||||
// })),
|
||||
rxjs.tap(() => $el.animate([
|
||||
{ transform: "translateX(0px)", opacity: "1"},
|
||||
{ transform: "translateX(-30px)", opacity: "0"},
|
||||
], {
|
||||
duration: 300,
|
||||
fill: "forwards",
|
||||
})),
|
||||
rxjs.delay(200),
|
||||
);
|
||||
}
|
||||
|
||||
const css = await CSSLoader(import.meta, "ctrl_setup.css");
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
border-right: 2px solid var(--color);
|
||||
padding: 50px 0px 0px 40px;
|
||||
transition: transform 0.3s ease;
|
||||
transition-delay: 0.7s;
|
||||
transition-delay: 0s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.component_menu_sidebar h2 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue