web: migrate Stage List to web

This commit is contained in:
Jens Langhammer
2021-02-19 19:29:17 +01:00
parent a76cbf8b70
commit 93478a55d7
17 changed files with 172 additions and 216 deletions

View File

@ -1,4 +1,4 @@
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
import { DefaultClient, AKResponse, QueryArguments, BaseInheritanceModel } from "./Client";
import { TypeCreate } from "./Providers";
export enum FlowDesignation {
@ -49,16 +49,26 @@ export class Flow {
}
}
export class Stage {
export class Stage implements BaseInheritanceModel {
pk: string;
name: string;
__type__: string;
object_type: string;
verbose_name: string;
verbose_name_plural: string;
flow_set: Flow[];
constructor() {
throw Error();
}
static get(slug: string): Promise<Stage> {
return DefaultClient.fetch<Stage>(["stages", "all", slug]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Stage>> {
return DefaultClient.fetch<AKResponse<Stage>>(["stages", "all"], filter);
}
static getTypes(): Promise<TypeCreate[]> {
return DefaultClient.fetch<TypeCreate[]>(["stages", "all", "types"]);
}

View File

@ -20,37 +20,37 @@ export const SIDEBAR_ITEMS: SidebarItem[] = [
return User.me().then(u => u.is_superuser);
}),
new SidebarItem("Resources").children(
new SidebarItem("Applications", "/applications").activeWhen(
`^/applications/(?<slug>${SLUG_REGEX})$`
new SidebarItem("Applications", "/core/applications").activeWhen(
`^/core/applications/(?<slug>${SLUG_REGEX})$`
),
new SidebarItem("Sources", "/sources").activeWhen(
`^/sources/(?<slug>${SLUG_REGEX})$`,
new SidebarItem("Sources", "/core/sources").activeWhen(
`^/core/sources/(?<slug>${SLUG_REGEX})$`,
),
new SidebarItem("Providers", "/providers"),
new SidebarItem("Outposts", "/outposts"),
new SidebarItem("Outpost Service Connections", "/outpost-service-connections"),
new SidebarItem("Providers", "/core/providers"),
new SidebarItem("Outposts", "/outpost/outposts"),
new SidebarItem("Outpost Service Connections", "/outpost/service-connections"),
).when((): Promise<boolean> => {
return User.me().then(u => u.is_superuser);
}),
new SidebarItem("Customisation").children(
new SidebarItem("Policies", "/policies"),
new SidebarItem("Property Mappings", "/property-mappings"),
new SidebarItem("Policies", "/policy/policies"),
new SidebarItem("Property Mappings", "/core/property-mappings"),
).when((): Promise<boolean> => {
return User.me().then(u => u.is_superuser);
}),
new SidebarItem("Flows").children(
new SidebarItem("Flows", "/flows").activeWhen(`^/flows/(?<slug>${SLUG_REGEX})$`),
new SidebarItem("Stages", "/administration/stages/"),
new SidebarItem("Flows", "/flow/flows").activeWhen(`^/flow/flows/(?<slug>${SLUG_REGEX})$`),
new SidebarItem("Stages", "/flow/stages"),
new SidebarItem("Prompts", "/administration/stages_prompts/"),
new SidebarItem("Invitations", "/administration/stages/invitations/"),
).when((): Promise<boolean> => {
return User.me().then(u => u.is_superuser);
}),
new SidebarItem("Identity & Cryptography").children(
new SidebarItem("User", "/users"),
new SidebarItem("Groups", "/groups"),
new SidebarItem("User", "/identity/users"),
new SidebarItem("Groups", "/identity/groups"),
new SidebarItem("Certificates", "/crypto/certificates"),
new SidebarItem("Tokens", "/tokens"),
new SidebarItem("Tokens", "/core/tokens"),
).when((): Promise<boolean> => {
return User.me().then(u => u.is_superuser);
}),

View File

@ -36,7 +36,7 @@ export class AdminOverviewPage extends LitElement {
<ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header="Apps with most usage" style="grid-column-end: span 2;grid-row-end: span 3;">
<ak-top-applications-table></ak-top-applications-table>
</ak-aggregate-card>
<ak-admin-status-card-provider class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header="Providers" headerLink="#/providers/">
<ak-admin-status-card-provider class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header="Providers" headerLink="#/core/providers/">
</ak-admin-status-card-provider>
<ak-admin-status-card-policy-unbound class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-infrastructure" header="Policies" headerLink="#/administration/policies/">
</ak-admin-status-card-policy-unbound>

View File

@ -50,7 +50,7 @@ export class ApplicationListPage extends TablePage<Application> {
item.meta_icon ?
html`<img class="app-icon pf-c-avatar" src="${item.meta_icon}" alt="${gettext("Application Icon")}">` :
html`<i class="pf-icon pf-icon-arrow"></i>`,
html`<a href="#/applications/${item.slug}">
html`<a href="#/core/applications/${item.slug}">
<div>
${item.name}
</div>

View File

@ -80,7 +80,7 @@ export class ApplicationViewPage extends LitElement {
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<a href="#/providers/${this.application.provider.pk}">
<a href="#/core/providers/${this.application.provider.pk}">
${this.application.provider.name}
</a>
</div>

View File

@ -107,7 +107,7 @@ export class EventInfo extends LitElement {
<span>${until(Flow.list({
flow_uuid: this.event.context.flow as string,
}).then(resp => {
return html`<a href="#/flows/${resp.results[0].slug}">${resp.results[0].name}</a>`;
return html`<a href="#/flow/flows/${resp.results[0].slug}">${resp.results[0].name}</a>`;
}), html`<ak-spinner size=${SpinnerSize.Medium}></ak-spinner>`)}
</span>
</div>

View File

@ -47,7 +47,7 @@ export class FlowListPage extends TablePage<Flow> {
row(item: Flow): TemplateResult[] {
return [
html`<a href="#/flows/${item.slug}">
html`<a href="#/flow/flows/${item.slug}">
<code>${item.slug}</code>
</a>`,
html`${item.name}`,

View File

@ -48,7 +48,7 @@ export class OutpostListPage extends TablePage<Outpost> {
return [
html`${item.name}`,
html`<ul>${item.providers_obj.map((p) => {
return html`<li><a href="#/providers/${p.pk}">${p.name}</a></li>`;
return html`<li><a href="#/core/providers/${p.pk}">${p.name}</a></li>`;
})}</ul>`,
html`<ak-outpost-health outpostId=${item.pk}></ak-outpost-health>`,
html`

View File

@ -47,13 +47,13 @@ export class ProviderListPage extends TablePage<Provider> {
row(item: Provider): TemplateResult[] {
return [
html`<a href="#/providers/${item.pk}">
html`<a href="#/core/providers/${item.pk}">
${item.name}
</a>`,
item.assigned_application_name ?
html`<i class="pf-icon pf-icon-ok"></i>
${gettext("Assigned to application ")}
<a href="#/applications/${item.assigned_application_slug}">${item.assigned_application_name}</a>` :
<a href="#/core/applications/${item.assigned_application_slug}">${item.assigned_application_name}</a>` :
html`<i class="pf-icon pf-icon-warning-triangle"></i>
${gettext("Warning: Provider not assigned to any application.")}`,
html`${item.verbose_name}`,

View File

@ -14,7 +14,7 @@ export class RelatedApplicationButton extends LitElement {
render(): TemplateResult {
if (this.provider?.assigned_application_slug) {
return html`<a href="#/applications/${this.provider.assigned_application_slug}">
return html`<a href="#/core/applications/${this.provider.assigned_application_slug}">
${this.provider.assigned_application_name}
</a>`;
}

View File

@ -46,7 +46,7 @@ export class SourceListPage extends TablePage<Source> {
row(item: Source): TemplateResult[] {
return [
html`<a href="#/sources/${item.slug}">
html`<a href="#/core/sources/${item.slug}">
<div>${item.name}</div>
${item.enabled ? html`` : html`<small>${gettext("Disabled")}</small>`}
</a>`,

View File

@ -0,0 +1,100 @@
import { gettext } from "django";
import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client";
import { TableColumn } from "../../elements/table/Table";
import { TablePage } from "../../elements/table/TablePage";
import "../../elements/buttons/ModalButton";
import "../../elements/buttons/SpinnerButton";
import "../../elements/buttons/Dropdown";
import { until } from "lit-html/directives/until";
import { Stage } from "../../api/Flows";
@customElement("ak-stage-list")
export class StageListPage extends TablePage<Stage> {
pageTitle(): string {
return "Stages";
}
pageDescription(): string | undefined {
return "Stages are single steps of a Flow that a user is guided through.";
}
pageIcon(): string {
return "pf-icon pf-icon-plugged";
}
searchEnabled(): boolean {
return true;
}
@property()
order = "name";
apiEndpoint(page: number): Promise<AKResponse<Stage>> {
return Stage.list({
ordering: this.order,
page: page,
search: this.search || "",
});
}
columns(): TableColumn[] {
return [
new TableColumn("Name", "name"),
new TableColumn("Flows"),
new TableColumn(""),
];
}
row(item: Stage): TemplateResult[] {
return [
html`<div>
<div>${item.name}</div>
<small>${item.verbose_name}</small>
</div>`,
html`${item.flow_set.map((flow) => {
return html`<a href="#/flow/flows/${flow.slug}">
<code>${flow.slug}</code>
</a>`;
})}`,
html`
<ak-modal-button href="${Stage.adminUrl(`${item.pk}/update/`)}">
<ak-spinner-button slot="trigger" class="pf-m-secondary">
${gettext("Edit")}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
<ak-modal-button href="${Stage.adminUrl(`${item.pk}/delete/`)}">
<ak-spinner-button slot="trigger" class="pf-m-danger">
${gettext("Delete")}
</ak-spinner-button>
<div slot="modal"></div>
</ak-modal-button>
`,
];
}
renderToolbar(): TemplateResult {
return html`
<ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">${gettext("Create")}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
${until(Stage.getTypes().then((types) => {
return types.map((type) => {
return html`<li>
<ak-modal-button href="${type.link}">
<button slot="trigger" class="pf-c-dropdown__menu-item">${type.name}<br>
<small>${type.description}</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>`;
});
}), html`<ak-spinner></ak-spinner>`)}
</ul>
</ak-dropdown>
${super.renderToolbar()}`;
}
}

View File

@ -11,6 +11,7 @@ import "./pages/events/RuleListPage";
import "./pages/events/TransportListPage";
import "./pages/flows/FlowListPage";
import "./pages/flows/FlowViewPage";
import "./pages/groups/GroupListPage";
import "./pages/LibraryPage";
import "./pages/outposts/OutpostListPage";
import "./pages/outposts/OutpostServiceConnectionListPage";
@ -20,10 +21,10 @@ import "./pages/providers/ProviderListPage";
import "./pages/providers/ProviderViewPage";
import "./pages/sources/SourcesListPage";
import "./pages/sources/SourceViewPage";
import "./pages/groups/GroupListPage";
import "./pages/users/UserListPage";
import "./pages/tokens/TokenListPage";
import "./pages/stages/StageListPage";
import "./pages/system-tasks/SystemTaskListPage";
import "./pages/tokens/TokenListPage";
import "./pages/users/UserListPage";
export const ROUTES: Route[] = [
// Prevent infinite Shell loops
@ -32,24 +33,25 @@ export const ROUTES: Route[] = [
new Route(new RegExp("^/library$"), html`<ak-library></ak-library>`),
new Route(new RegExp("^/administration/overview$"), html`<ak-admin-overview></ak-admin-overview>`),
new Route(new RegExp("^/administration/system-tasks$"), html`<ak-system-task-list></ak-system-task-list>`),
new Route(new RegExp("^/providers$"), html`<ak-provider-list></ak-provider-list>`),
new Route(new RegExp(`^/providers/(?<id>${ID_REGEX})$`)).then((args) => {
new Route(new RegExp("^/core/providers$"), html`<ak-provider-list></ak-provider-list>`),
new Route(new RegExp(`^/core/providers/(?<id>${ID_REGEX})$`)).then((args) => {
return html`<ak-provider-view .providerID=${parseInt(args.id, 10)}></ak-provider-view>`;
}),
new Route(new RegExp("^/applications$"), html`<ak-application-list></ak-application-list>`),
new Route(new RegExp(`^/applications/(?<slug>${SLUG_REGEX})$`)).then((args) => {
new Route(new RegExp("^/core/applications$"), html`<ak-application-list></ak-application-list>`),
new Route(new RegExp(`^/core/applications/(?<slug>${SLUG_REGEX})$`)).then((args) => {
return html`<ak-application-view .args=${args}></ak-application-view>`;
}),
new Route(new RegExp("^/sources$"), html`<ak-source-list></ak-source-list>`),
new Route(new RegExp(`^/sources/(?<slug>${SLUG_REGEX})$`)).then((args) => {
new Route(new RegExp("^/core/sources$"), html`<ak-source-list></ak-source-list>`),
new Route(new RegExp(`^/core/sources/(?<slug>${SLUG_REGEX})$`)).then((args) => {
return html`<ak-source-view .args=${args}></ak-source-view>`;
}),
new Route(new RegExp("^/policies$"), html`<ak-policy-list></ak-policy-list>`),
new Route(new RegExp("^/groups$"), html`<ak-group-list></ak-group-list>`),
new Route(new RegExp("^/users$"), html`<ak-user-list></ak-user-list>`),
new Route(new RegExp("^/flows$"), html`<ak-flow-list></ak-flow-list>`),
new Route(new RegExp("^/tokens$"), html`<ak-token-list></ak-token-list>`),
new Route(new RegExp(`^/flows/(?<slug>${SLUG_REGEX})$`)).then((args) => {
new Route(new RegExp("^/policy/policies$"), html`<ak-policy-list></ak-policy-list>`),
new Route(new RegExp("^/identity/groups$"), html`<ak-group-list></ak-group-list>`),
new Route(new RegExp("^/identity/users$"), html`<ak-user-list></ak-user-list>`),
new Route(new RegExp("^/core/tokens$"), html`<ak-token-list></ak-token-list>`),
new Route(new RegExp("^/flow/stages$"), html`<ak-stage-list></ak-stage-list>`),
new Route(new RegExp("^/flow/flows$"), html`<ak-flow-list></ak-flow-list>`),
new Route(new RegExp(`^/flow/flows/(?<slug>${SLUG_REGEX})$`)).then((args) => {
return html`<ak-flow-view .flowSlug=${args.slug}></ak-flow-view>`;
}),
new Route(new RegExp("^/events/log$"), html`<ak-event-list></ak-event-list>`),
@ -58,8 +60,8 @@ export const ROUTES: Route[] = [
}),
new Route(new RegExp("^/events/transports$"), html`<ak-event-transport-list></ak-event-transport-list>`),
new Route(new RegExp("^/events/rules$"), html`<ak-event-rule-list></ak-event-rule-list>`),
new Route(new RegExp("^/property-mappings$"), html`<ak-property-mapping-list></ak-property-mapping-list>`),
new Route(new RegExp("^/outposts$"), html`<ak-outpost-list></ak-outpost-list>`),
new Route(new RegExp("^/outpost-service-connections$"), html`<ak-outpost-service-connection-list></ak-outpost-service-connection-list>`),
new Route(new RegExp("^/core/property-mappings$"), html`<ak-property-mapping-list></ak-property-mapping-list>`),
new Route(new RegExp("^/outpost/outposts$"), html`<ak-outpost-list></ak-outpost-list>`),
new Route(new RegExp("^/outpost/service-connections$"), html`<ak-outpost-service-connection-list></ak-outpost-service-connection-list>`),
new Route(new RegExp("^/crypto/certificates$"), html`<ak-crypto-certificatekeypair-list></ak-crypto-certificatekeypair-list>`),
];