Merge pull request 'Lots of changes:' (#1) from new_build into master
Reviewed-on: https://git.stamm.me/OpenServer/OpenAuth_views/pulls/1
265
build.ts
@ -1,265 +0,0 @@
|
||||
import * as rollup from "rollup";
|
||||
import * as svelte from "rollup-plugin-svelte";
|
||||
import * as resolve from "rollup-plugin-node-resolve";
|
||||
import * as commonjs from "rollup-plugin-commonjs";
|
||||
import * as typescript from "rollup-plugin-typescript2";
|
||||
import * as fs from "fs";
|
||||
import * as copy from "rollup-plugin-copy-assets";
|
||||
|
||||
import { sass } from "svelte-preprocess-sass";
|
||||
import { terser } from "rollup-plugin-terser";
|
||||
|
||||
const production = process.argv.indexOf("-d") < 0;
|
||||
console.log(`Runnung in ${production ? "production" : "development"} mode!`);
|
||||
|
||||
let plg = [];
|
||||
|
||||
if (production) {
|
||||
plg.push(terser());
|
||||
}
|
||||
|
||||
if (!fs.existsSync("build")) fs.mkdirSync("build");
|
||||
|
||||
const pages = ["Login", "Home", "User"];
|
||||
|
||||
let configs = pages.map((page) => {
|
||||
if (!fs.existsSync("build/" + page.toLowerCase()))
|
||||
fs.mkdirSync("build/" + page.toLowerCase());
|
||||
|
||||
const pageHtml = generateHtml(page);
|
||||
|
||||
fs.writeFileSync(`build/${page.toLowerCase()}/index.html`, pageHtml);
|
||||
|
||||
return <rollup.RollupOptions>{
|
||||
input: `./src/${page}/main.js`,
|
||||
output: {
|
||||
sourcemap: !production,
|
||||
format: "iife",
|
||||
name: "app",
|
||||
file: `build/${page.toLowerCase()}/bundle.js`,
|
||||
},
|
||||
|
||||
watch: {
|
||||
clearScreen: false,
|
||||
},
|
||||
treeshake: production,
|
||||
plugins: [
|
||||
(typescript as any)({
|
||||
tsconfig: "./src/tsconfig.json",
|
||||
}),
|
||||
svelte({
|
||||
// enable run-time checks when not in production
|
||||
dev: !production,
|
||||
css: (css) => {
|
||||
css.write(`build/${page.toLowerCase()}/bundle.css`);
|
||||
},
|
||||
preprocess: {
|
||||
style: sass({
|
||||
includePaths: ["src", "node_modules"],
|
||||
}),
|
||||
},
|
||||
}),
|
||||
(resolve as any)(),
|
||||
(commonjs as any)(),
|
||||
...plg,
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
import * as path from "path";
|
||||
|
||||
function generateHtml(pagename: string) {
|
||||
const globalJS = fs.readFileSync("./src/global.js").toString("utf8");
|
||||
const globalCSS = fs.readFileSync("./src/global.css").toString("utf8");
|
||||
return `<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf8'>
|
||||
<meta name='viewport' content='width=device-width'>
|
||||
|
||||
<title>OpenAuth - ${pagename}</title>
|
||||
<style>
|
||||
${globalCSS}
|
||||
</style>
|
||||
<script>
|
||||
${globalJS}
|
||||
</script>
|
||||
<link rel='stylesheet' href='bundle.css'>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
<script src='bundle.js'></script>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto" lazyload>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
let start: [number, number];
|
||||
if (process.argv.indexOf("-w") >= 0) {
|
||||
rollup.watch(configs).on("event", (event) => {
|
||||
if (event.code === "BUNDLE_START") {
|
||||
start = process.hrtime();
|
||||
} else if (event.code === "BUNDLE_END") {
|
||||
let diff = process.hrtime(start);
|
||||
console.log(`--- Took ${diff[0] * 1000 + diff[1] / 1000000}ms`);
|
||||
} else if (event.code === "ERROR") {
|
||||
// console.error(event.error);
|
||||
handleError(event.error, true);
|
||||
// } else if (event.code === "FATAL") {
|
||||
// handleError(event.error, true);
|
||||
} else {
|
||||
console.log(event);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
start = process.hrtime();
|
||||
Promise.all(
|
||||
configs.map((config) => {
|
||||
return rollup
|
||||
.rollup(config)
|
||||
.then((value) => {
|
||||
return value.write(
|
||||
Array.isArray(config.output)
|
||||
? config.output[0]
|
||||
: config.output
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
handleError(err, true);
|
||||
// console.error(err);
|
||||
});
|
||||
})
|
||||
).then((vals) => {
|
||||
let diff = process.hrtime(start);
|
||||
console.log(`--- Took ${diff[0] * 1000 + diff[1] / 1000000}ms`);
|
||||
});
|
||||
}
|
||||
|
||||
var absolutePath = /^(?:\/|(?:[A-Za-z]:)?[\\|/])/;
|
||||
function isAbsolute(path) {
|
||||
return absolutePath.test(path);
|
||||
}
|
||||
|
||||
// function getAliasName(resolved, unresolved) {
|
||||
// var alias = path.basename(unresolved || resolved);
|
||||
// var ext = path.extname(resolved);
|
||||
// if (alias.endsWith(ext))
|
||||
// alias = alias.substr(0, alias.length - ext.length);
|
||||
// return alias;
|
||||
// }
|
||||
|
||||
function relativeId(id) {
|
||||
if (typeof process === "undefined" || !isAbsolute(id)) return id;
|
||||
return path.relative(process.cwd(), id);
|
||||
}
|
||||
|
||||
const tc: any = {
|
||||
enabled:
|
||||
process.env.FORCE_COLOR ||
|
||||
process.platform === "win32" ||
|
||||
(process.stdout.isTTY && process.env.TERM && process.env.TERM !== "dumb"),
|
||||
};
|
||||
const Styles = (tc.Styles = {});
|
||||
const defineProp = Object.defineProperty;
|
||||
|
||||
const init = (style, open, close, re) => {
|
||||
let i,
|
||||
len = 1,
|
||||
seq = [(Styles[style] = { open, close, re })];
|
||||
|
||||
const fn = (s) => {
|
||||
if (tc.enabled) {
|
||||
for (i = 0, s += ""; i < len; i++) {
|
||||
style = seq[i];
|
||||
s =
|
||||
(open = style.open) +
|
||||
(~s.indexOf((close = style.close), 4) // skip first \x1b[
|
||||
? s.replace(style.re, open)
|
||||
: s) +
|
||||
close;
|
||||
}
|
||||
len = 1;
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
defineProp(tc, style, {
|
||||
get: () => {
|
||||
for (let k in Styles)
|
||||
defineProp(fn, k, {
|
||||
get: () => ((seq[len++] = Styles[k]), fn),
|
||||
});
|
||||
delete tc[style];
|
||||
return (tc[style] = fn);
|
||||
},
|
||||
configurable: true,
|
||||
});
|
||||
};
|
||||
|
||||
init("reset", "\x1b[0m", "\x1b[0m", /\x1b\[0m/g);
|
||||
init("bold", "\x1b[1m", "\x1b[22m", /\x1b\[22m/g);
|
||||
init("dim", "\x1b[2m", "\x1b[22m", /\x1b\[22m/g);
|
||||
init("italic", "\x1b[3m", "\x1b[23m", /\x1b\[23m/g);
|
||||
init("underline", "\x1b[4m", "\x1b[24m", /\x1b\[24m/g);
|
||||
init("inverse", "\x1b[7m", "\x1b[27m", /\x1b\[27m/g);
|
||||
init("hidden", "\x1b[8m", "\x1b[28m", /\x1b\[28m/g);
|
||||
init("strikethrough", "\x1b[9m", "\x1b[29m", /\x1b\[29m/g);
|
||||
init("black", "\x1b[30m", "\x1b[39m", /\x1b\[39m/g);
|
||||
init("red", "\x1b[31m", "\x1b[39m", /\x1b\[39m/g);
|
||||
init("green", "\x1b[32m", "\x1b[39m", /\x1b\[39m/g);
|
||||
init("yellow", "\x1b[33m", "\x1b[39m", /\x1b\[39m/g);
|
||||
init("blue", "\x1b[34m", "\x1b[39m", /\x1b\[39m/g);
|
||||
init("magenta", "\x1b[35m", "\x1b[39m", /\x1b\[39m/g);
|
||||
init("cyan", "\x1b[36m", "\x1b[39m", /\x1b\[39m/g);
|
||||
init("white", "\x1b[37m", "\x1b[39m", /\x1b\[39m/g);
|
||||
init("gray", "\x1b[90m", "\x1b[39m", /\x1b\[39m/g);
|
||||
init("bgBlack", "\x1b[40m", "\x1b[49m", /\x1b\[49m/g);
|
||||
init("bgRed", "\x1b[41m", "\x1b[49m", /\x1b\[49m/g);
|
||||
init("bgGreen", "\x1b[42m", "\x1b[49m", /\x1b\[49m/g);
|
||||
init("bgYellow", "\x1b[43m", "\x1b[49m", /\x1b\[49m/g);
|
||||
init("bgBlue", "\x1b[44m", "\x1b[49m", /\x1b\[49m/g);
|
||||
init("bgMagenta", "\x1b[45m", "\x1b[49m", /\x1b\[49m/g);
|
||||
init("bgCyan", "\x1b[46m", "\x1b[49m", /\x1b\[49m/g);
|
||||
init("bgWhite", "\x1b[47m", "\x1b[49m", /\x1b\[49m/g);
|
||||
|
||||
const turbocolor: any = tc;
|
||||
|
||||
function handleError(err, recover) {
|
||||
if (recover === void 0) {
|
||||
recover = false;
|
||||
}
|
||||
var description = err.message || err;
|
||||
if (err.name) description = err.name + ": " + description;
|
||||
var message =
|
||||
(err.plugin
|
||||
? "(" + err.plugin + " plugin) " + description
|
||||
: description) || err;
|
||||
console.error(
|
||||
turbocolor.bold.red("[!] " + turbocolor.bold(message.toString()))
|
||||
);
|
||||
if (err.url) {
|
||||
console.error(turbocolor.cyan(err.url));
|
||||
}
|
||||
if (err.loc) {
|
||||
console.error(
|
||||
relativeId(err.loc.file || err.id) +
|
||||
" (" +
|
||||
err.loc.line +
|
||||
":" +
|
||||
err.loc.column +
|
||||
")"
|
||||
);
|
||||
} else if (err.id) {
|
||||
console.error(relativeId(err.id));
|
||||
}
|
||||
if (err.frame) {
|
||||
console.error(turbocolor.dim(err.frame));
|
||||
}
|
||||
if (err.stack) {
|
||||
//console.error(turbocolor.dim(err.stack));
|
||||
}
|
||||
console.error("");
|
||||
if (!recover) process.exit(1);
|
||||
}
|
4719
package-lock.json
generated
45
package.json
@ -2,31 +2,40 @@
|
||||
"name": "@hibas123/openauth-views",
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"node-sass": "^4.13.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^2.0.2",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-copy-assets": "^2.0.1",
|
||||
"@rollup/plugin-commonjs": "^16.0.0",
|
||||
"@rollup/plugin-html": "^0.2.0",
|
||||
"@rollup/plugin-image": "^2.0.5",
|
||||
"@rollup/plugin-typescript": "^6.1.0",
|
||||
"@tsconfig/svelte": "^1.0.10",
|
||||
"@types/cleave.js": "^1.4.3",
|
||||
"cssnano": "^4.1.10",
|
||||
"node-sass": "^5.0.0",
|
||||
"postcss": "^8.1.4",
|
||||
"postcss-import": "^13.0.0",
|
||||
"postcss-url": "^10.0.0",
|
||||
"rollup": "^2.33.1",
|
||||
"rollup-plugin-livereload": "^2.0.0",
|
||||
"rollup-plugin-node-resolve": "^5.2.0",
|
||||
"rollup-plugin-svelte": "^5.1.1",
|
||||
"rollup-plugin-terser": "^5.2.0",
|
||||
"sirv-cli": "^0.4.5",
|
||||
"svelte": "^3.19.2",
|
||||
"rollup-plugin-postcss": "^3.1.8",
|
||||
"rollup-plugin-sizes": "^1.0.3",
|
||||
"rollup-plugin-svelte": "^6.1.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"rollup-plugin-visualizer": "^4.1.2",
|
||||
"svelte": "^3.29.4",
|
||||
"svelte-preprocess": "^4.5.2",
|
||||
"svelte-preprocess-postcss": "^1.1.1",
|
||||
"svelte-preprocess-sass": "^0.2.0",
|
||||
"ts-node": "^8.6.2",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^4.0.5"
|
||||
},
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run build",
|
||||
"build": "ts-node build.ts",
|
||||
"autobuild": "ts-node build.ts -w -d",
|
||||
"dev": "run-p start:dev autobuild",
|
||||
"start": "sirv build",
|
||||
"start:dev": "sirv build --dev"
|
||||
"build": "rollup -c rollup.config.js ",
|
||||
"dev": "rollup -c rollup.config.js -w"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hibas123/utils": "^2.2.3",
|
||||
"rollup-plugin-typescript2": "^0.26.0",
|
||||
"@hibas123/theme": "^2.0.6",
|
||||
"@hibas123/utils": "^2.2.16",
|
||||
"cleave.js": "^1.6.0",
|
||||
"what-the-pack": "^2.0.3"
|
||||
}
|
||||
}
|
||||
|
7
postcss.config.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require("cssnano")({
|
||||
preset: "default",
|
||||
}),
|
||||
],
|
||||
};
|
118
rollup.config.js
Normal file
@ -0,0 +1,118 @@
|
||||
const svelte = require("rollup-plugin-svelte");
|
||||
const typescript = require("@rollup/plugin-typescript");
|
||||
const { terser } = require("rollup-plugin-terser");
|
||||
const html = require("@rollup/plugin-html");
|
||||
const resolve = require("rollup-plugin-node-resolve");
|
||||
const image = require("@rollup/plugin-image");
|
||||
const sizes = require("rollup-plugin-sizes");
|
||||
const visualise = require("rollup-plugin-visualizer");
|
||||
const postcss = require("rollup-plugin-postcss");
|
||||
const commonjs = require("@rollup/plugin-commonjs");
|
||||
const livereload = require("rollup-plugin-livereload");
|
||||
|
||||
const { preprocess } = require("./svelte.config");
|
||||
|
||||
const VIEWS = ["Home", "Login", "Popup", "User"];
|
||||
|
||||
const dev = process.env.NODE_ENV !== "production";
|
||||
|
||||
const htmlTemplate = ({ attributes, meta, files, publicPath, title }) => {
|
||||
const makeHtmlAttributes = (attributes) => {
|
||||
if (!attributes) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const keys = Object.keys(attributes);
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
return keys.reduce(
|
||||
(result, key) => (result += ` ${key}="${attributes[key]}"`),
|
||||
""
|
||||
);
|
||||
};
|
||||
const scripts = (files.js || [])
|
||||
.map(({ fileName }) => {
|
||||
const attrs = makeHtmlAttributes(attributes.script);
|
||||
return `<script src="${publicPath}${fileName}"${attrs}></script>`;
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
const links = (files.css || [])
|
||||
.map(({ fileName }) => {
|
||||
const attrs = makeHtmlAttributes(attributes.link);
|
||||
return `<link href="${publicPath}${fileName}" rel="stylesheet"${attrs}>`;
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
const metas = meta
|
||||
.map((input) => {
|
||||
const attrs = makeHtmlAttributes(input);
|
||||
return `<meta${attrs}>`;
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
return `
|
||||
<!doctype html>
|
||||
<html${makeHtmlAttributes(attributes.html)}>
|
||||
<head>
|
||||
${metas}
|
||||
<title>${title}</title>
|
||||
<link rel="stylesheet" href="bundle.css"/>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto"/>
|
||||
${links}
|
||||
</head>
|
||||
<body>
|
||||
${scripts}
|
||||
</body>
|
||||
</html>`;
|
||||
};
|
||||
|
||||
export default VIEWS.map((view) => ({
|
||||
input: `src/pages/${view}/main.ts`,
|
||||
output: [
|
||||
dev
|
||||
? {
|
||||
file: `build/${view}/bundle.js`,
|
||||
format: "iife",
|
||||
sourcemap: true,
|
||||
name: view,
|
||||
}
|
||||
: {
|
||||
file: `build/${view}/bundle.min.js`,
|
||||
format: "iife",
|
||||
name: view,
|
||||
plugins: [terser()],
|
||||
},
|
||||
],
|
||||
plugins: [
|
||||
commonjs(),
|
||||
svelte({
|
||||
emitCss: true,
|
||||
preprocess,
|
||||
}),
|
||||
typescript({ sourceMap: dev, inlineSources: dev }),
|
||||
html({
|
||||
attributes: {
|
||||
html: { lang: "en" },
|
||||
},
|
||||
meta: [
|
||||
{
|
||||
name: "viewport",
|
||||
content: "width=device-width",
|
||||
},
|
||||
],
|
||||
template: htmlTemplate,
|
||||
}),
|
||||
resolve({ browser: true, dedupe: ["svelte"] }),
|
||||
image(),
|
||||
sizes(),
|
||||
visualise({
|
||||
filename: `build/stats/${view}.html`,
|
||||
title: `Rullup bundle for ${view}`,
|
||||
}),
|
||||
postcss({
|
||||
extract: `bundle.css`, //TODO: Check if it should be enabled
|
||||
// inject: true,
|
||||
}),
|
||||
// dev && livereload(),
|
||||
],
|
||||
}));
|
@ -1,7 +0,0 @@
|
||||
import App from "./App.svelte";
|
||||
|
||||
var app = new App({
|
||||
target: document.getElementById("content"),
|
||||
});
|
||||
|
||||
export default app;
|
@ -1,7 +0,0 @@
|
||||
import App from "./App.svelte";
|
||||
|
||||
var app = new App({
|
||||
target: document.getElementById("content"),
|
||||
});
|
||||
|
||||
export default app;
|
@ -1,7 +0,0 @@
|
||||
import App from "./App.svelte";
|
||||
|
||||
var app = new App({
|
||||
target: document.getElementById("content"),
|
||||
});
|
||||
|
||||
export default app;
|
1918
src/cleave.js
90
src/components/HoveringContentBox.svelte
Normal file
@ -0,0 +1,90 @@
|
||||
<script lang="ts">
|
||||
// import { Tile } from "carbon-components-svelte";
|
||||
|
||||
export let title: string;
|
||||
export let loading = false;
|
||||
export let hide = false;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.wrapper {
|
||||
min-height: 100vh;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.container {
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
padding-top: 2.5rem;
|
||||
|
||||
min-height: calc(100px + 2.5rem);
|
||||
min-width: 100px;
|
||||
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.title-container {
|
||||
margin: -4.8rem auto 0 auto;
|
||||
max-width: 250px;
|
||||
background-color: var(--primary);
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
/* padding: 5px 20px; */
|
||||
}
|
||||
|
||||
.title-container > h1 {
|
||||
font-size: 2rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.content-container {
|
||||
padding: 2em;
|
||||
margin: 0 auto;
|
||||
max-width: 380px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.loading_container {
|
||||
filter: blur(1px) opacity(50%);
|
||||
}
|
||||
|
||||
.loader_container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="card-elevated container">
|
||||
<!-- <div class="container card"> -->
|
||||
<div class="card elv-8 title-container">
|
||||
<h1 style="margin:0">{title}</h1>
|
||||
</div>
|
||||
{#if loading}
|
||||
<div class="loader_container">
|
||||
<div class="loader_box">
|
||||
<div class="loader" />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="content-container" class:loading_container={loading}>
|
||||
{#if !(loading && hide)}
|
||||
<slot />
|
||||
{/if}
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
</div>
|
15
src/components/theme/Theme.svelte
Normal file
@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
// import { onMount, afterUpdate, setContext } from "svelte";
|
||||
// import { writable, derived } from "svelte/store";
|
||||
|
||||
// type Theme = "white" | "g10" | "g90" | "g100";
|
||||
|
||||
// export let persist: boolean = false;
|
||||
// export let persistKey: string = "theme";
|
||||
export let dark = false;
|
||||
</script>
|
||||
|
||||
|
||||
<div class={dark ? 'dark-theme' : 'light-theme'}>
|
||||
<slot />
|
||||
</div>
|
42
src/components/theme/index.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import "@hibas123/theme/out/base.css";
|
||||
import "./theme.css";
|
||||
import { default as Theme } from "./Theme.svelte";
|
||||
|
||||
(() => {
|
||||
const elements = new WeakSet();
|
||||
|
||||
function check() {
|
||||
document
|
||||
.querySelectorAll(".floating>input")
|
||||
.forEach((e: HTMLInputElement) => {
|
||||
if (elements.has(e)) return;
|
||||
elements.add(e);
|
||||
|
||||
function checkState() {
|
||||
console.log("Check State");
|
||||
if (e.value !== "") {
|
||||
if (e.classList.contains("used")) return;
|
||||
e.classList.add("used");
|
||||
} else {
|
||||
if (e.classList.contains("used")) e.classList.remove("used");
|
||||
}
|
||||
}
|
||||
|
||||
e.addEventListener("change", () => checkState());
|
||||
checkState();
|
||||
});
|
||||
}
|
||||
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
check();
|
||||
});
|
||||
|
||||
// Start observing the target node for configured mutations
|
||||
observer.observe(window.document, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
check();
|
||||
})();
|
||||
|
||||
export default Theme;
|
@ -21,6 +21,9 @@ body {
|
||||
background: #eee;
|
||||
height: 100%;
|
||||
font-size: var(--default-font-size);
|
||||
min-width: 100vw;
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.group {
|
@ -1,34 +0,0 @@
|
||||
(() => {
|
||||
const elements = new WeakSet();
|
||||
|
||||
function check() {
|
||||
document.querySelectorAll(".floating>input").forEach((e) => {
|
||||
if (elements.has(e)) return;
|
||||
elements.add(e);
|
||||
|
||||
function checkState() {
|
||||
console.log("Check State");
|
||||
if (e.value !== "") {
|
||||
if (e.classList.contains("used")) return;
|
||||
e.classList.add("used");
|
||||
} else {
|
||||
if (e.classList.contains("used")) e.classList.remove("used");
|
||||
}
|
||||
}
|
||||
|
||||
e.addEventListener("change", () => checkState());
|
||||
checkState();
|
||||
});
|
||||
}
|
||||
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
check();
|
||||
});
|
||||
|
||||
// Start observing the target node for configured mutations
|
||||
observer.observe(window.document, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
check();
|
||||
})();
|
@ -1,7 +1,5 @@
|
||||
import { getCookie } from "./cookie";
|
||||
|
||||
// const baseURL = "https://auth.stamm.me";
|
||||
// const baseURL = "http://localhost:3000";
|
||||
const baseURL = "";
|
||||
|
||||
export default async function request(
|
8
src/pages/Home/main.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import "../../components/theme";
|
||||
import App from "./App.svelte";
|
||||
|
||||
new App({
|
||||
target: document.body,
|
||||
});
|
||||
|
||||
export default app;
|
@ -1,4 +1,6 @@
|
||||
<script>
|
||||
import Theme from "../../components/theme";
|
||||
import HoveringContentBox from "../../components/HoveringContentBox.svelte";
|
||||
import Api from "./api.ts";
|
||||
import Credentials from "./Credentials.svelte";
|
||||
import Redirect from "./Redirect.svelte";
|
||||
@ -9,7 +11,7 @@
|
||||
const states = {
|
||||
credentials: 1,
|
||||
twofactor: 3,
|
||||
redirect: 4
|
||||
redirect: 4,
|
||||
};
|
||||
|
||||
let username = Api.getUsername();
|
||||
@ -95,41 +97,6 @@
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.card {
|
||||
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
|
||||
background: #fafafa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
max-width: 380px;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22);
|
||||
position: relative;
|
||||
padding: 1px;
|
||||
background-color: white !important;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.container {
|
||||
overflow: hidden;
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
@ -137,63 +104,21 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.floating {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
.title-container {
|
||||
margin: -30px auto 0 auto;
|
||||
max-width: 250px;
|
||||
background-color: var(--primary);
|
||||
color: white;
|
||||
padding: 5px 20px;
|
||||
}
|
||||
|
||||
.loading_container {
|
||||
filter: blur(1px) opacity(50%);
|
||||
}
|
||||
|
||||
.loader_container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="form-container">
|
||||
<form action="JavaScript:void(0)" class="card">
|
||||
<div class="card title-container">
|
||||
<h1>Login</h1>
|
||||
</div>
|
||||
{#if loading}
|
||||
<div class="loader_container">
|
||||
<div class="loader_box">
|
||||
<div class="loader" />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="container" class:loading_container={loading}>
|
||||
<Theme>
|
||||
<HoveringContentBox title="Login" {loading}>
|
||||
<form action="JavaScript:void(0)">
|
||||
{#if state === states.redirect}
|
||||
<Redirect />
|
||||
{:else if state === states.credentials}
|
||||
<Credentials next={afterCredentials} setLoading={s => (loading = s)} />
|
||||
<Credentials next={afterCredentials} setLoading={(s) => (loading = s)} />
|
||||
{:else if state === states.twofactor}
|
||||
<Twofactor finish={afterTwoFactor} setLoading={s => (loading = s)} />
|
||||
<Twofactor finish={afterTwoFactor} setLoading={(s) => (loading = s)} />
|
||||
{/if}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</HoveringContentBox>
|
||||
<footer>
|
||||
<p>Powered by {appname}</p>
|
||||
</footer>
|
||||
</Theme>
|
@ -47,8 +47,7 @@
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: var(--primary);
|
||||
.wide-button {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
@ -82,4 +81,4 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<button class="btn" on:click={buttonClick}>Next</button>
|
||||
<button class="btn btn-primary wide-button" on:click={buttonClick}>Next</button>
|
@ -1,6 +1,6 @@
|
||||
import request from "../request";
|
||||
import sha from "../sha512";
|
||||
import { setCookie, getCookie } from "../cookie";
|
||||
import request from "../../helper/request";
|
||||
import sha from "../../helper/sha512";
|
||||
import { setCookie, getCookie } from "../../helper/cookie";
|
||||
|
||||
export interface TwoFactor {
|
||||
id: string;
|
Before Width: | Height: | Size: 992 B After Width: | Height: | Size: 992 B |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 927 B After Width: | Height: | Size: 927 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
5
src/pages/Login/main.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import App from "./App.svelte";
|
||||
|
||||
new App({
|
||||
target: document.body,
|
||||
});
|
@ -1,9 +1,9 @@
|
||||
<script>
|
||||
import Cleave from "../../cleave";
|
||||
import Cleave from "cleave.js";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
export let error;
|
||||
export let label;
|
||||
// export let label;
|
||||
export let value;
|
||||
export let length = 6;
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
const cleaveCustom = new Cleave(input, {
|
||||
blocks: [length / 2, length / 2],
|
||||
delimiter: " ",
|
||||
numericOnly: true
|
||||
numericOnly: true,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@ -25,9 +25,9 @@
|
||||
</style>
|
||||
|
||||
<div class="floating group">
|
||||
<input bind:this={input} autofocus bind:value />
|
||||
<input id="noasidhglk" bind:this={input} autofocus bind:value />
|
||||
<span class="highlight" />
|
||||
<span class="bar" />
|
||||
<label>Code</label>
|
||||
<label for="noasidhglk">Code</label>
|
||||
<div class="error" style={!error ? 'display: none;' : ''}>{error}</div>
|
||||
</div>
|
@ -33,8 +33,7 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: var(--primary);
|
||||
.btn-next {
|
||||
margin: 0;
|
||||
margin-left: auto;
|
||||
min-width: 80px;
|
||||
@ -47,7 +46,5 @@
|
||||
|
||||
<div class="actions">
|
||||
<ToList {finish} />
|
||||
<button class="btn" style="margin-left: auto" on:click={sendCode}>
|
||||
Send
|
||||
</button>
|
||||
<button class="btn btn-primary btn-next" on:click={sendCode}> Send </button>
|
||||
</div>
|
@ -4,7 +4,7 @@
|
||||
let error = "";
|
||||
let code = "";
|
||||
export let device = "Handy01";
|
||||
export let deviceId = "";
|
||||
// export let deviceId = "";
|
||||
|
||||
export let finish;
|
||||
|
||||
@ -365,10 +365,7 @@
|
||||
|
||||
<h3>SMS</h3>
|
||||
|
||||
<p>
|
||||
A code was sent to your Device
|
||||
<b>{device}</b>
|
||||
</p>
|
||||
<p>A code was sent to your Device <b>{device}</b></p>
|
||||
|
||||
<div class="windows8">
|
||||
<div class="wBall" id="wBall_1">
|
@ -3,7 +3,7 @@
|
||||
|
||||
const states = {
|
||||
approve: 1,
|
||||
enter: 2
|
||||
enter: 2,
|
||||
};
|
||||
let state = states.approve;
|
||||
|
||||
@ -34,11 +34,11 @@
|
||||
<h3>SMS</h3>
|
||||
{#if state === states.approve}
|
||||
<p>Send SMS to {number}</p>
|
||||
<button class="btn" on:click={sendCode}>Send</button>
|
||||
<button class="btn btn-primary" on:click={sendCode}>Send</button>
|
||||
{:else}
|
||||
<p>A code was sent to you. Please enter</p>
|
||||
<input type="number" placeholder="Code" bind:value={code} />
|
||||
<button on:click={validateCode}>Send</button>
|
||||
<button class="btn btn-primary" on:click={validateCode}>Send</button>
|
||||
<br />
|
||||
<a href="# " on:click|preventDefault={() => (state = states.approve)}>
|
||||
Not received?
|
@ -6,6 +6,7 @@
|
||||
a {
|
||||
color: var(--primary);
|
||||
text-decoration: none;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
59
src/pages/Popup/App.svelte
Normal file
@ -0,0 +1,59 @@
|
||||
<script lang="ts">
|
||||
import HoveringContentBox from "../../components/HoveringContentBox.svelte";
|
||||
import Theme from "../../components/theme/Theme.svelte";
|
||||
|
||||
export let loading = true;
|
||||
export let appName = "";
|
||||
export let permissions: any[] = [];
|
||||
export let accept: () => void;
|
||||
|
||||
const base_perm = {
|
||||
name: "Access Profile",
|
||||
description:
|
||||
"Access your identity and some basic informations like your username",
|
||||
};
|
||||
|
||||
$: view_perms = [base_perm, ...permissions];
|
||||
|
||||
$: console.log({ loading, appName, permissions, accept });
|
||||
|
||||
function deny() {
|
||||
window.close();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.permission > h3 {
|
||||
}
|
||||
|
||||
.permission > p {
|
||||
}
|
||||
</style>
|
||||
|
||||
<Theme dark={false}>
|
||||
<HoveringContentBox title="Authorize" {loading} hide>
|
||||
<div class="title margin">
|
||||
<h2 style="font-weight: normal">
|
||||
Grant
|
||||
<span id="hostname" style="font-weight: bold;">{appName}</span>
|
||||
the following permissions?
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<ul class="list list-divider">
|
||||
{#each view_perms as permission (permission._íd)}
|
||||
<li class="permission">
|
||||
<h3>{permission.name}</h3>
|
||||
<p>{permission.description}</p>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
<div>
|
||||
<div style="text-align: right;">
|
||||
<button class="btn btn-primary" on:click={accept}>Allow</button>
|
||||
<button class="btn btn-primary" on:click={deny}>Deny</button>
|
||||
</div>
|
||||
</div>
|
||||
</HoveringContentBox>
|
||||
</Theme>
|
0
src/pages/Popup/api.ts
Normal file
146
src/pages/Popup/main.ts
Normal file
@ -0,0 +1,146 @@
|
||||
import "../../components/theme";
|
||||
import App from "./App.svelte";
|
||||
import request from "../../helper/request";
|
||||
|
||||
interface IPermission {
|
||||
_id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
let loading = true;
|
||||
let appName: string;
|
||||
let permissions: IPermission[] = [];
|
||||
let accept: () => void;
|
||||
|
||||
const app = new App({
|
||||
target: document.body,
|
||||
props: { loading },
|
||||
});
|
||||
|
||||
const setLoading = (_loading: boolean) => {
|
||||
loading = _loading;
|
||||
app.$set({ loading });
|
||||
};
|
||||
|
||||
const setAppName = (_appName: string) => {
|
||||
appName = _appName;
|
||||
app.$set({ appName });
|
||||
};
|
||||
|
||||
const setPermissions = (_permissions: IPermission[]) => {
|
||||
permissions = _permissions;
|
||||
app.$set({ permissions });
|
||||
};
|
||||
|
||||
const setAccept = (_accept: () => void) => {
|
||||
accept = _accept;
|
||||
app.$set({ accept });
|
||||
};
|
||||
|
||||
async function getJWT(client_id: string, origin: string) {
|
||||
origin = encodeURIComponent(origin);
|
||||
client_id = encodeURIComponent(client_id);
|
||||
|
||||
const res = await request(`/api/user/oauth/jwt`, {
|
||||
client_id,
|
||||
origin,
|
||||
}).then((res) => res.json());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
async function getRefreshToken(
|
||||
client_id: string,
|
||||
origin: string,
|
||||
permissions: string[]
|
||||
) {
|
||||
origin = encodeURIComponent(origin);
|
||||
client_id = encodeURIComponent(client_id);
|
||||
const perm = permissions.map((e) => encodeURIComponent(e)).join(",");
|
||||
|
||||
const res = await request(`/api/user/oauth/refresh_token`, {
|
||||
client_id,
|
||||
origin,
|
||||
permissions: perm,
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
let started = false;
|
||||
async function onMessage(msg: MessageEvent<any>) {
|
||||
const sendResponse = (data: any) => {
|
||||
try {
|
||||
console.log("Sending response:", data);
|
||||
(msg.source.postMessage as any)(data, msg.origin);
|
||||
} catch (err) {
|
||||
alert("Something went wrong, please try again later!");
|
||||
}
|
||||
};
|
||||
console.log("Received message", msg, started);
|
||||
if (!started) {
|
||||
started = true;
|
||||
const url = new URL(msg.origin);
|
||||
setAppName(url.hostname);
|
||||
|
||||
try {
|
||||
if (!msg.data.type || msg.data.type === "jwt") {
|
||||
console.log("JWT Request");
|
||||
await new Promise((yes) => {
|
||||
console.log("Await user acceptance");
|
||||
setLoading(false);
|
||||
setAccept(yes);
|
||||
});
|
||||
console.log("User has accepted");
|
||||
const res = await getJWT(msg.data.client_id, url.hostname);
|
||||
sendResponse(res);
|
||||
} else if (msg.data.type === "refresh") {
|
||||
console.log("RefreshToken Request");
|
||||
let permissions = msg.data.permissions || [];
|
||||
let permissions_resolved = [];
|
||||
|
||||
if (permissions.length > 0) {
|
||||
permissions_resolved = await request(
|
||||
"/api/user/oauth/permissions",
|
||||
{
|
||||
client_id: msg.data.client_id,
|
||||
origin: url.hostname,
|
||||
permissions: permissions.join(","),
|
||||
}
|
||||
).then(({ permissions }) => permissions);
|
||||
}
|
||||
|
||||
await new Promise((yes) => {
|
||||
console.log("Await user acceptance");
|
||||
setLoading(false);
|
||||
setPermissions(permissions_resolved);
|
||||
setAccept(yes);
|
||||
});
|
||||
|
||||
console.log("User has accepted");
|
||||
|
||||
const res = await getRefreshToken(
|
||||
msg.data.client_id,
|
||||
url.hostname,
|
||||
permissions
|
||||
);
|
||||
sendResponse(res);
|
||||
}
|
||||
} catch (err) {
|
||||
sendResponse({ error: true, message: err.message });
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if (!started) {
|
||||
console.log("No authentication request received!");
|
||||
alert(
|
||||
"The site requesting the login does not respond. Please try again later"
|
||||
);
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
window.addEventListener("message", onMessage);
|
@ -3,7 +3,7 @@
|
||||
import BoxItem from "./BoxItem.svelte";
|
||||
import NextIcon from "./NextIcon.svelte";
|
||||
|
||||
import request from "../../request.ts";
|
||||
import request from "../../../helper/request.ts";
|
||||
|
||||
export let loading = false;
|
||||
let account_error = undefined;
|
||||
@ -67,8 +67,8 @@
|
||||
true
|
||||
);
|
||||
|
||||
email = contact.mails.map(e => e.mail);
|
||||
phone = contact.phones.map(e => e.phone);
|
||||
email = contact.mails.map((e) => e.mail);
|
||||
phone = contact.phones.map((e) => e.phone);
|
||||
contact_error = undefined;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
@ -154,10 +154,14 @@
|
||||
<BoxItem name="Name" value={name}>
|
||||
<div class="input-container">
|
||||
<div class="floating group">
|
||||
<input type="text" autocomplete="username" bind:value={name} />
|
||||
<input
|
||||
id="name-inp"
|
||||
type="text"
|
||||
autocomplete="username"
|
||||
bind:value={name} />
|
||||
<span class="highlight" />
|
||||
<span class="bar" />
|
||||
<label>Name</label>
|
||||
<label for="name-inp">Name</label>
|
||||
</div>
|
||||
<button class="btn" on:click={saveName}>Save</button>
|
||||
</div>
|
@ -10,7 +10,7 @@
|
||||
import Box from "./Box.svelte";
|
||||
import BoxItem from "./BoxItem.svelte";
|
||||
import NextIcon from "./NextIcon.svelte";
|
||||
import request from "../../request.ts";
|
||||
import request from "../../../helper/request.ts";
|
||||
|
||||
export let loading = false;
|
||||
|
||||
@ -181,9 +181,7 @@
|
||||
Revoke
|
||||
</button>
|
||||
</BoxItem>
|
||||
{:else}
|
||||
<span>No Tokens</span>
|
||||
{/each}
|
||||
{:else}<span>No Tokens</span>{/each}
|
||||
|
||||
<!-- <BoxItem name="E-Mail" value={email} />
|
||||
<BoxItem name="Phone" value={phone} /> -->
|
6
src/pages/User/main.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import "../../components/theme";
|
||||
import App from "./App.svelte";
|
||||
|
||||
new App({
|
||||
target: document.body,
|
||||
});
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
10
svelte.config.js
Normal file
@ -0,0 +1,10 @@
|
||||
const sveltePreprocess = require("svelte-preprocess");
|
||||
|
||||
module.exports = {
|
||||
emitCss: true,
|
||||
preprocess: sveltePreprocess({
|
||||
scss: {
|
||||
includePaths: ["theme"],
|
||||
},
|
||||
}),
|
||||
};
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["build.ts"]
|
||||
"moduleResolution": "Node"
|
||||
}
|
||||
}
|
||||
|