web: fix formatting mostly, add pipeline

This commit is contained in:
Jens Langhammer 2020-12-01 13:59:59 +01:00
parent 71fbb23a2f
commit bce75dc047
13 changed files with 159 additions and 90 deletions

View file

@ -1,19 +0,0 @@
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 12,
sourceType: "module",
},
plugins: ["@typescript-eslint"],
rules: {
indent: ["error", 4],
"linebreak-style": ["error", "unix"],
quotes: ["error", "double"],
semi: ["error", "always"],
},
};

25
web/.eslintrc.json Normal file
View file

@ -0,0 +1,25 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
"indent": ["error", 4],
"linebreak-style": ["error", "unix"],
"quotes": ["error", "double"],
"semi": ["error", "always"],
"@typescript-eslint/ban-ts-comment": "off"
}
}

42
web/azure-pipelines.yml Normal file
View file

@ -0,0 +1,42 @@
trigger:
- main
stages:
- stage: link
jobs:
- job: lint
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: '12.x'
displayName: 'Install Node.js'
- task: Npm@1
inputs:
command: 'install'
workingDir: 'web/'
- task: Npm@1
inputs:
command: 'custom'
workingDir: 'web/'
customCommand: 'run lint'
- stage: Build
jobs:
- job: build
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: '12.x'
displayName: 'Install Node.js'
- task: Npm@1
inputs:
command: 'install'
workingDir: 'web/'
- task: Npm@1
inputs:
command: 'custom'
workingDir: 'web/'
customCommand: 'run build'

6
web/package-lock.json generated
View file

@ -816,6 +816,12 @@
} }
} }
}, },
"eslint-config-google": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz",
"integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==",
"dev": true
},
"eslint-scope": { "eslint-scope": {
"version": "5.1.1", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",

View file

@ -3,7 +3,7 @@
"scripts": { "scripts": {
"build": "rollup -c ./rollup.config.js", "build": "rollup -c ./rollup.config.js",
"watch": "rollup -c -w", "watch": "rollup -c -w",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --fix" "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^5.15.1", "@fortawesome/fontawesome-free": "^5.15.1",
@ -28,6 +28,7 @@
"@typescript-eslint/eslint-plugin": "^4.9.0", "@typescript-eslint/eslint-plugin": "^4.9.0",
"@typescript-eslint/parser": "^4.9.0", "@typescript-eslint/parser": "^4.9.0",
"eslint": "^7.14.0", "eslint": "^7.14.0",
"eslint-config-google": "^0.14.0",
"rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-minify-html-literals": "^1.2.5", "rollup-plugin-minify-html-literals": "^1.2.5",
"rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-node-resolve": "^5.2.0",

View file

@ -1,13 +1,17 @@
import { DefaultClient } from "./client"; import { DefaultClient } from "./client";
export class AdminOverview { export class AdminOverview {
version?: string; version: string;
version_latest?: string; version_latest: string;
worker_count?: number; worker_count: number;
providers_without_application?: number; providers_without_application: number;
policies_without_binding?: number; policies_without_binding: number;
cached_policies?: number; cached_policies: number;
cached_flows?: number; cached_flows: number;
constructor() {
throw Error();
}
static get(): Promise<AdminOverview> { static get(): Promise<AdminOverview> {
return DefaultClient.fetch<AdminOverview>(["admin", "overview"]); return DefaultClient.fetch<AdminOverview>(["admin", "overview"]);

View file

@ -1,17 +1,21 @@
import { DefaultClient, PBResponse } from "./client"; import { DefaultClient, PBResponse } from "./client";
export class Application { export class Application {
pk?: string; pk: string;
name?: string; name: string;
slug?: string; slug: string;
provider?: number; provider: number;
launch_url?: string; launch_url: string;
meta_launch_url?: string; meta_launch_url: string;
meta_icon?: string; meta_icon: string;
meta_description?: string; meta_description: string;
meta_publisher?: string; meta_publisher: string;
policies?: string[]; policies: string[];
constructor() {
throw Error();
}
static get(slug: string): Promise<Application> { static get(slug: string): Promise<Application> {
return DefaultClient.fetch<Application>(["core", "applications", slug]); return DefaultClient.fetch<Application>(["core", "applications", slug]);

View file

@ -4,12 +4,16 @@ import { Integrations } from "@sentry/tracing";
import { VERSION } from "../constants"; import { VERSION } from "../constants";
export class Config { export class Config {
branding_logo?: string; branding_logo: string;
branding_title?: string; branding_title: string;
error_reporting_enabled?: boolean; error_reporting_enabled: boolean;
error_reporting_environment?: string; error_reporting_environment: string;
error_reporting_send_pii?: boolean; error_reporting_send_pii: boolean;
constructor() {
throw Error();
}
static get(): Promise<Config> { static get(): Promise<Config> {
return DefaultClient.fetch<Config>(["root", "config"]).then((config) => { return DefaultClient.fetch<Config>(["root", "config"]).then((config) => {

View file

@ -1,12 +1,16 @@
import { DefaultClient, PBResponse } from "./client"; import { DefaultClient, PBResponse } from "./client";
export class User { export class User {
pk?: number; pk: number;
username?: string; username: string;
name?: string; name: string;
is_superuser?: boolean; is_superuser: boolean;
email?: boolean; email: boolean;
avatar?: string; avatar: string;
constructor() {
throw Error();
}
static me(): Promise<User> { static me(): Promise<User> {
return DefaultClient.fetch<User>(["core", "users", "me"]); return DefaultClient.fetch<User>(["core", "users", "me"]);

View file

@ -24,7 +24,7 @@ export const SIDEBAR_ITEMS: SidebarItem[] = [
name: "Monitor", name: "Monitor",
path: ["/audit/audit/"], path: ["/audit/audit/"],
condition: (sb: Sidebar) => { condition: (sb: Sidebar) => {
return sb.user?.is_superuser!; return sb.user?.is_superuser || false;
}, },
}, },
{ {
@ -124,7 +124,7 @@ export const SIDEBAR_ITEMS: SidebarItem[] = [
}, },
], ],
condition: (sb: Sidebar) => { condition: (sb: Sidebar) => {
return sb.user?.is_superuser!; return sb.user?.is_superuser || false;
}, },
}, },
]; ];
@ -181,29 +181,22 @@ export class Sidebar extends LitElement {
return html``; return html``;
} }
} }
return html` <li return html` <li class="pf-c-nav__item ${item.children ? "pf-m-expandable pf-m-expanded" : ""}">
class="pf-c-nav__item ${item.children ? "pf-m-expandable pf-m-expanded" : ""}" ${item.path ?
> html`<a href="#${item.path}" class="pf-c-nav__link ${item.path.some((v) => v === this.activePath) ? "pf-m-current": ""}">
${item.path ${item.name}
? html`<a </a>` :
href="#${item.path}" html`<a class="pf-c-nav__link" aria-expanded="true">
class="pf-c-nav__link ${item.path.some((v) => v === this.activePath) ${item.name}
? "pf-m-current" <span class="pf-c-nav__toggle">
: ""}" <i class="fas fa-angle-right" aria-hidden="true"></i>
> </span>
${item.name} </a>
</a>` <section class="pf-c-nav__subnav">
: html`<a class="pf-c-nav__link" aria-expanded="true" <ul class="pf-c-nav__simple-list">
>${item.name} ${item.children?.map((i) => this.renderItem(i))}
<span class="pf-c-nav__toggle"> </ul>
<i class="fas fa-angle-right" aria-hidden="true"></i> </section>`}
</span>
</a>
<section class="pf-c-nav__subnav">
<ul class="pf-c-nav__simple-list">
${item.children?.map((i) => this.renderItem(i))}
</ul>
</section>`}
</li>`; </li>`;
} }

View file

@ -53,8 +53,8 @@ export class SidebarBrand extends LitElement {
<div class="pf-c-brand pb-brand"> <div class="pf-c-brand pb-brand">
<img src="${this.config.branding_logo}" alt="passbook icon" loading="lazy" /> <img src="${this.config.branding_logo}" alt="passbook icon" loading="lazy" />
${this.config.branding_title ${this.config.branding_title
? html`<span>${this.config.branding_title}</span>` ? html`<span>${this.config.branding_title}</span>`
: ""} : ""}
</div> </div>
</a>`; </a>`;
} }

View file

@ -82,39 +82,39 @@ export class AdminOverviewPage extends LitElement {
</pb-aggregate-card> </pb-aggregate-card>
<pb-aggregate-card icon="pf-icon pf-icon-server" header="Workers"> <pb-aggregate-card icon="pf-icon pf-icon-server" header="Workers">
${this.data ? ${this.data ?
this.data?.worker_count! < 1 ? this.data?.worker_count < 1 ?
html`<p class="pb-aggregate-card"> html`<p class="pb-aggregate-card">
<i class="fa fa-exclamation-triangle"></i> ${this.data.worker_count} <i class="fa fa-exclamation-triangle"></i> ${this.data.worker_count}
</p> </p>
<p>${gettext("No workers connected.")}</p>` : <p>${gettext("No workers connected.")}</p>` :
html`<p class="pb-aggregate-card"> html`<p class="pb-aggregate-card">
<i class="fa fa-check-circle"></i> ${this.data.worker_count} <i class="fa fa-check-circle"></i> ${this.data.worker_count}
</p>` </p>`
: html`<pb-spinner></pb-spinner>`} : html`<pb-spinner></pb-spinner>`}
</pb-aggregate-card> </pb-aggregate-card>
<pb-aggregate-card icon="pf-icon pf-icon-plugged" header="Providers" headerLink="#/administration/providers/"> <pb-aggregate-card icon="pf-icon pf-icon-plugged" header="Providers" headerLink="#/administration/providers/">
${this.data ? ${this.data ?
this.data?.providers_without_application! < 1 ? this.data?.providers_without_application < 1 ?
html`<p class="pb-aggregate-card"> html`<p class="pb-aggregate-card">
<i class="fa fa-exclamation-triangle"></i> 0 <i class="fa fa-exclamation-triangle"></i> 0
</p> </p>
<p>${gettext("At least one Provider has no application assigned.")}</p>` : <p>${gettext("At least one Provider has no application assigned.")}</p>` :
html`<p class="pb-aggregate-card"> html`<p class="pb-aggregate-card">
<i class="fa fa-check-circle"></i> 0 <i class="fa fa-check-circle"></i> 0
</p>` </p>`
: html`<pb-spinner></pb-spinner>`} : html`<pb-spinner></pb-spinner>`}
</pb-aggregate-card> </pb-aggregate-card>
<pb-aggregate-card icon="pf-icon pf-icon-plugged" header="Policies" headerLink="#/administration/policies/"> <pb-aggregate-card icon="pf-icon pf-icon-plugged" header="Policies" headerLink="#/administration/policies/">
${this.data ? ${this.data ?
this.data?.policies_without_binding! < 1 ? this.data?.policies_without_binding < 1 ?
html`<p class="pb-aggregate-card"> html`<p class="pb-aggregate-card">
<i class="fa fa-exclamation-triangle"></i> 0 <i class="fa fa-exclamation-triangle"></i> 0
</p> </p>
<p>${gettext("Policies without binding exist.")}</p>` : <p>${gettext("Policies without binding exist.")}</p>` :
html`<p class="pb-aggregate-card"> html`<p class="pb-aggregate-card">
<i class="fa fa-check-circle"></i> 0 <i class="fa fa-check-circle"></i> 0
</p>` </p>`
: html`<pb-spinner></pb-spinner>`} : html`<pb-spinner></pb-spinner>`}
</pb-aggregate-card> </pb-aggregate-card>
<pb-aggregate-card-promise <pb-aggregate-card-promise
icon="pf-icon pf-icon-user" icon="pf-icon pf-icon-user"

View file

@ -1,3 +1,4 @@
import { gettext } from "django";
import { css, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { css, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import { Application } from "../../api/application"; import { Application } from "../../api/application";
import { DefaultClient, PBResponse } from "../../api/client"; import { DefaultClient, PBResponse } from "../../api/client";
@ -61,7 +62,7 @@ export class ApplicationViewPage extends LitElement {
@property() @property()
application?: Application; application?: Application;
static get styles() { static get styles(): any[] {
return COMMON_STYLES.concat( return COMMON_STYLES.concat(
css` css`
img.pf-icon { img.pf-icon {
@ -90,12 +91,16 @@ export class ApplicationViewPage extends LitElement {
<div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-4-col" style="grid-column-end: span 3;grid-row-end: span 2;"> <div class="pf-c-card pf-c-card-aggregate pf-l-gallery__item pf-m-4-col" style="grid-column-end: span 3;grid-row-end: span 2;">
<div class="pf-c-card__header"> <div class="pf-c-card__header">
<div class="pf-c-card__header-main"> <div class="pf-c-card__header-main">
<i class="pf-icon pf-icon-server"></i> Logins over the last 24 hours <i class="pf-icon pf-icon-server"></i> ${gettext("Logins over the last 24 hours")}
</div> </div>
</div> </div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
${this.application ? ${this.application ?
html`<pb-admin-logins-chart url="${DefaultClient.makeUrl(["core", "applications", this.application?.slug!, "metrics"])}"></pb-admin-logins-chart>` : ""} html`
<pb-admin-logins-chart
url="${DefaultClient.makeUrl(["core", "applications", this.application?.slug, "metrics"])}">
</pb-admin-logins-chart>`
: ""}
</div> </div>
</div> </div>
</div> </div>