Skip to content

Commit b62f088

Browse files
committed
feat: add first state for resources count
Signed-off-by: Philippe Martin <[email protected]>
1 parent 0cc1c5e commit b62f088

File tree

11 files changed

+342
-2
lines changed

11 files changed

+342
-2
lines changed

packages/common/src/types/disposable.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*
1616
* SPDX-License-Identifier: Apache-2.0
1717
***********************************************************************/
18+
export const IDisposable = Symbol.for('IDisposable');
1819

1920
export interface IDisposable {
2021
dispose(): void;

packages/extension/src/manager/contexts-states-dispatcher.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import type { RpcExtension } from '/@common/rpc/rpc.js';
3131
import { CONTEXTS_HEALTHS, CONTEXTS_PERMISSIONS, RESOURCES_COUNT, UPDATE_RESOURCE } from '/@common/channels.js';
3232
import type { ExtensionContext, TelemetryLogger } from '@podman-desktop/api';
3333
import type { Container } from 'inversify';
34-
import { InversifyBinding } from '../inject/inversify-binding.js';
34+
import { InversifyBinding } from '/@/inject/inversify-binding.js';
3535

3636
let container: Container;
3737
const contextsManagerMock: ContextsManager = {

packages/webview/src/Main.svelte

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
11
<script lang="ts">
22
// App.css includes tailwind css dependencies that we use
33
import './app.css';
4+
import '@fortawesome/fontawesome-free/css/all.min.css';
5+
6+
import { onDestroy, onMount } from 'svelte';
7+
8+
import { Main, type MainContext } from './main';
9+
import MainContextAware from './MainContextAware.svelte';
10+
11+
let main: Main | undefined;
12+
let mainContext: MainContext | undefined = $state();
13+
14+
onMount(async () => {
15+
// Perform initalization
16+
main = new Main();
17+
const now = performance.now();
18+
mainContext = await main.init();
19+
console.log(`Initialization took ${performance.now() - now}ms`);
20+
});
21+
22+
onDestroy(() => {
23+
// Dispose
24+
main?.dispose();
25+
});
426
</script>
527

6-
Kubernetes Dashboard
28+
{#if mainContext}
29+
<MainContextAware context={mainContext} />
30+
{/if}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<script lang="ts">
2+
import { setContext } from 'svelte';
3+
4+
import type { MainContext } from './main';
5+
import { States } from './state/states';
6+
import ResourcesCount from './component/ResourcesCount.svelte';
7+
8+
interface Props {
9+
context: MainContext;
10+
}
11+
12+
const { context }: Props = $props();
13+
14+
let initialized = $state(false);
15+
16+
// Sets the value in the global svelte context
17+
setContext(States, context.states);
18+
19+
initialized = true;
20+
</script>
21+
22+
{#if initialized}
23+
Kubernetes Dashboard
24+
25+
<div>
26+
<ResourcesCount />
27+
</div>
28+
{/if}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script lang="ts">
2+
import { getContext } from 'svelte';
3+
import { States } from '/@/state/states';
4+
5+
const resourcesCount = getContext<States>(States).stateResourcesCountInfoUI;
6+
</script>
7+
8+
{#if resourcesCount.data?.counts}
9+
<ul>
10+
{#each resourcesCount.data.counts as count, index (index)}
11+
<li>{count.contextName}/{count.resourceName}: {count.count}</li>
12+
{/each}
13+
</ul>
14+
{/if}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**********************************************************************
2+
* Copyright (C) 2025 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
import 'reflect-metadata';
20+
21+
import type { WebviewApi } from '@podman-desktop/webview-api';
22+
import { Container } from 'inversify';
23+
24+
import { RpcBrowser } from '/@common/rpc/rpc';
25+
26+
import { statesModule } from '/@/state/state-module';
27+
28+
export class InversifyBinding {
29+
#container: Container | undefined;
30+
31+
#rpcBrowser: RpcBrowser;
32+
#webviewApi: WebviewApi;
33+
34+
constructor(rpcBrowser: RpcBrowser, webviewApi: WebviewApi) {
35+
this.#rpcBrowser = rpcBrowser;
36+
this.#webviewApi = webviewApi;
37+
}
38+
39+
public async initBindings(): Promise<Container> {
40+
this.#container = new Container();
41+
this.#container.bind(RpcBrowser).toConstantValue(this.#rpcBrowser);
42+
this.#container.bind('WebviewApi').toConstantValue(this.#webviewApi);
43+
44+
await this.#container.load(statesModule);
45+
46+
return this.#container;
47+
}
48+
}

packages/webview/src/main.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**********************************************************************
2+
* Copyright (C) 2025 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
import { RpcBrowser } from '/@common/rpc/rpc';
20+
21+
import { InversifyBinding } from './inject/inversify-binding';
22+
import { IDisposable } from '/@common/types/disposable';
23+
import { States } from './state/states';
24+
import { StateObject } from './state/util/state-object.svelte';
25+
26+
export interface MainContext {
27+
states: States;
28+
}
29+
30+
export class Main implements IDisposable {
31+
private disposables: IDisposable[] = [];
32+
33+
async init(): Promise<MainContext> {
34+
const webViewApi = acquirePodmanDesktopApi();
35+
36+
const rpcBrowser: RpcBrowser = new RpcBrowser(window, webViewApi);
37+
38+
const inversifyBinding = new InversifyBinding(rpcBrowser, webViewApi);
39+
const container = await inversifyBinding.initBindings();
40+
41+
// Grab all state object instances
42+
const stateObjectInstances = container.getAll<StateObject<unknown>>(StateObject);
43+
44+
// Init all state object instances
45+
for (const stateObjectInstance of stateObjectInstances) {
46+
await stateObjectInstance.init();
47+
}
48+
49+
// Register all disposables
50+
const disposables = await container.getAllAsync<IDisposable>(IDisposable);
51+
this.disposables.push(...disposables);
52+
53+
const mainContext: MainContext = {
54+
states: await container.getAsync<States>(States),
55+
};
56+
57+
return mainContext;
58+
}
59+
60+
dispose(): void {
61+
for (const disposable of this.disposables) {
62+
disposable.dispose();
63+
}
64+
}
65+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**********************************************************************
2+
* Copyright (C) 2025 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
import { inject, injectable } from 'inversify';
20+
21+
import { RESOURCES_COUNT } from '/@common/channels';
22+
import { RpcBrowser } from '/@common/rpc/rpc';
23+
24+
import { AbsStateObjectImpl, type StateObject } from './util/state-object.svelte';
25+
import type { ResourcesCountInfo } from '/@common/model/resources-count-info';
26+
27+
// Define a state for the ResourcesCountInfo
28+
@injectable()
29+
export class StateResourcesCountInfo
30+
extends AbsStateObjectImpl<ResourcesCountInfo>
31+
implements StateObject<ResourcesCountInfo>
32+
{
33+
constructor(@inject(RpcBrowser) rpcBrowser: RpcBrowser) {
34+
super(rpcBrowser);
35+
}
36+
37+
async init(): Promise<void> {
38+
await this.initChannel(RESOURCES_COUNT);
39+
}
40+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**********************************************************************
2+
* Copyright (C) 2025 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
import { ContainerModule } from 'inversify';
20+
21+
import { States } from './states';
22+
import { StateObject } from './util/state-object.svelte';
23+
import { IDisposable } from '/@common/types/disposable';
24+
import { StateResourcesCountInfo } from './resources-count.svelte';
25+
26+
const statesModule = new ContainerModule(options => {
27+
options.bind(States).toSelf().inSingletonScope();
28+
29+
options.bind(StateResourcesCountInfo).toSelf().inSingletonScope();
30+
options.bind(StateObject).toService(StateResourcesCountInfo);
31+
options.bind(IDisposable).toService(StateResourcesCountInfo);
32+
});
33+
34+
export { statesModule };
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**********************************************************************
2+
* Copyright (C) 2025 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
import { inject, injectable } from 'inversify';
20+
import { StateResourcesCountInfo } from './resources-count.svelte';
21+
22+
@injectable()
23+
export class States {
24+
@inject(StateResourcesCountInfo)
25+
private _stateResourcesCountInfoUI: StateResourcesCountInfo;
26+
27+
get stateResourcesCountInfoUI(): StateResourcesCountInfo {
28+
return this._stateResourcesCountInfoUI;
29+
}
30+
}

0 commit comments

Comments
 (0)