feat(opsserver,web): replace the Angular UI and REST management layer with a TypedRequest-based ops server and bundled web frontend
This commit is contained in:
100
ts_web/elements/sg-view-dashboard.ts
Normal file
100
ts_web/elements/sg-view-dashboard.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import * as appstate from '../appstate.js';
|
||||
import * as shared from './shared/index.js';
|
||||
import {
|
||||
css,
|
||||
cssManager,
|
||||
customElement,
|
||||
DeesElement,
|
||||
html,
|
||||
state,
|
||||
type TemplateResult,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
@customElement('sg-view-dashboard')
|
||||
export class SgViewDashboard extends DeesElement {
|
||||
@state()
|
||||
accessor organizationsState: appstate.IOrganizationsState = {
|
||||
organizations: [],
|
||||
currentOrg: null,
|
||||
repositories: [],
|
||||
members: [],
|
||||
};
|
||||
|
||||
@state()
|
||||
accessor packagesState: appstate.IPackagesState = {
|
||||
packages: [],
|
||||
currentPackage: null,
|
||||
versions: [],
|
||||
total: 0,
|
||||
query: '',
|
||||
protocolFilter: '',
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const orgSub = appstate.organizationsStatePart
|
||||
.select((s) => s)
|
||||
.subscribe((s) => {
|
||||
this.organizationsState = s;
|
||||
});
|
||||
this.rxSubscriptions.push(orgSub);
|
||||
|
||||
const pkgSub = appstate.packagesStatePart
|
||||
.select((s) => s)
|
||||
.subscribe((s) => {
|
||||
this.packagesState = s;
|
||||
});
|
||||
this.rxSubscriptions.push(pkgSub);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
shared.viewHostCss,
|
||||
];
|
||||
|
||||
async connectedCallback() {
|
||||
super.connectedCallback();
|
||||
await appstate.organizationsStatePart.dispatchAction(appstate.fetchOrganizationsAction, null);
|
||||
await appstate.packagesStatePart.dispatchAction(appstate.searchPackagesAction, { offset: 0 });
|
||||
}
|
||||
|
||||
public render(): TemplateResult {
|
||||
return html`
|
||||
<sg-dashboard-view
|
||||
.stats="${{
|
||||
organizationCount: this.organizationsState.organizations.length,
|
||||
packageCount: this.packagesState.total,
|
||||
totalDownloads: 0,
|
||||
tokenCount: 0,
|
||||
}}"
|
||||
.recentPackages="${this.packagesState.packages.slice(0, 5)}"
|
||||
.organizations="${this.organizationsState.organizations}"
|
||||
@navigate="${(e: CustomEvent) => this.handleNavigate(e)}"
|
||||
></sg-dashboard-view>
|
||||
`;
|
||||
}
|
||||
|
||||
private handleNavigate(e: CustomEvent) {
|
||||
const { type, id } = e.detail;
|
||||
if (type === 'org' && id) {
|
||||
const { appRouter } = await_import_router();
|
||||
appRouter.navigateToEntity('organizations', id);
|
||||
} else if (type === 'package' && id) {
|
||||
const { appRouter } = await_import_router();
|
||||
appRouter.navigateToEntity('packages', id);
|
||||
} else if (type === 'packages') {
|
||||
const { appRouter } = await_import_router();
|
||||
appRouter.navigateToView('packages');
|
||||
} else if (type === 'tokens') {
|
||||
const { appRouter } = await_import_router();
|
||||
appRouter.navigateToView('tokens');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lazy import to avoid circular dependency
|
||||
function await_import_router() {
|
||||
// Dynamic import not needed here since router is a separate module
|
||||
// We use a workaround by importing at the module level
|
||||
return { appRouter: (globalThis as any).__sgAppRouter };
|
||||
}
|
||||
Reference in New Issue
Block a user