Skip to content

Commit 2289f99

Browse files
committed
feat: update tray menu to watch for new, deleted, and renamed profiles
1 parent 77164cb commit 2289f99

File tree

7 files changed

+234
-135
lines changed

7 files changed

+234
-135
lines changed

package-lock.json

Lines changed: 103 additions & 115 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@
8686
"printWidth": 120
8787
},
8888
"devDependencies": {
89-
"@kui-shell/builder": "11.5.0-dev-20220722-172700",
90-
"@kui-shell/proxy": "11.5.0-dev-20220722-172700",
91-
"@kui-shell/react": "11.5.0-dev-20220722-172700",
92-
"@kui-shell/webpack": "11.5.0-dev-20220722-172700",
89+
"@kui-shell/builder": "11.5.0-dev-20220725-153832",
90+
"@kui-shell/proxy": "11.5.0-dev-20220725-153832",
91+
"@kui-shell/react": "11.5.0-dev-20220725-153832",
92+
"@kui-shell/webpack": "11.5.0-dev-20220725-153832",
9393
"@playwright/test": "^1.23.2",
9494
"@types/debug": "^4.1.7",
9595
"@types/node": "14.11.8",
@@ -113,16 +113,16 @@
113113
},
114114
"dependencies": {
115115
"@kui-shell/client": "file:./plugins/plugin-client-default",
116-
"@kui-shell/core": "11.5.0-dev-20220722-172700",
117-
"@kui-shell/plugin-bash-like": "11.5.0-dev-20220722-172700",
118-
"@kui-shell/plugin-client-common": "11.5.0-dev-20220722-172700",
116+
"@kui-shell/core": "11.5.0-dev-20220725-153832",
117+
"@kui-shell/plugin-bash-like": "11.5.0-dev-20220725-153832",
118+
"@kui-shell/plugin-client-common": "11.5.0-dev-20220725-153832",
119119
"@kui-shell/plugin-codeflare": "file:./plugins/plugin-codeflare",
120-
"@kui-shell/plugin-core-support": "11.5.0-dev-20220722-172700",
121-
"@kui-shell/plugin-electron-components": "11.5.0-dev-20220722-172700",
122-
"@kui-shell/plugin-kubectl": "11.5.0-dev-20220722-172700",
120+
"@kui-shell/plugin-core-support": "11.5.0-dev-20220725-153832",
121+
"@kui-shell/plugin-electron-components": "11.5.0-dev-20220725-153832",
122+
"@kui-shell/plugin-kubectl": "11.5.0-dev-20220725-153832",
123123
"@kui-shell/plugin-madwizard": "file:./plugins/plugin-madwizard",
124-
"@kui-shell/plugin-patternfly4-themes": "11.5.0-dev-20220722-172700",
125-
"@kui-shell/plugin-proxy-support": "11.5.0-dev-20220722-172700",
126-
"@kui-shell/plugin-s3": "11.5.0-dev-20220722-172700"
124+
"@kui-shell/plugin-patternfly4-themes": "11.5.0-dev-20220725-153832",
125+
"@kui-shell/plugin-proxy-support": "11.5.0-dev-20220725-153832",
126+
"@kui-shell/plugin-s3": "11.5.0-dev-20220725-153832"
127127
}
128128
}

plugins/plugin-codeflare/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"@logdna/tail-file": "^3.0.0",
2727
"@patternfly/react-charts": "^6.77.1",
2828
"@patternfly/react-core": "^4.224.1",
29+
"chokidar": "^3.5.3",
2930
"open": "^8.4.0",
3031
"pretty-bytes": "^6.0.0",
3132
"pretty-ms": "8.0.0",

plugins/plugin-codeflare/src/tray/menus/profiles/index.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@ import dashboards from "./dashboards"
2525
import section from "../section"
2626
import UpdateFunction from "../../update"
2727
import { profileIcon } from "../../icons"
28+
import ProfileWatcher from "../../watchers/profile/list"
2829

2930
/** @return a menu for the given `profile` */
3031
async function profileMenu(
31-
profileObj: Profiles.Profile,
3232
createWindow: CreateWindowFunction,
33-
updateFunction: UpdateFunction
33+
updateFunction: UpdateFunction,
34+
profileObj: Profiles.Profile
3435
): Promise<MenuItemConstructorOptions> {
3536
const profile = profileObj.name
3637

@@ -45,17 +46,26 @@ async function profileMenu(
4546
}
4647
}
4748

49+
/** Memo of `ProfileWatcher`, which will watch for new/removed/renamed profiles */
50+
let watcher: null | ProfileWatcher = null
51+
4852
/** @return a menu for all profiles */
4953
export default async function profilesMenu(
5054
createWindow: CreateWindowFunction,
5155
updateFn: UpdateFunction
5256
): Promise<MenuItemConstructorOptions[]> {
57+
if (!watcher) {
58+
watcher = new ProfileWatcher(updateFn, await Profiles.profilesPath({}, true))
59+
}
60+
61+
await watcher.init()
62+
5363
// this will be a list of menu items, one per profile, and sorted by
5464
// profile name
5565
const profiles = await Promise.all(
56-
(await Profiles.list({}))
57-
.sort((a, b) => a.profile.name.localeCompare(b.profile.name))
58-
.map((_) => profileMenu(_.profile, createWindow, updateFn))
66+
watcher.profiles // current list of profiles
67+
.sort((a, b) => a.name.localeCompare(b.name))
68+
.map(profileMenu.bind(undefined, createWindow, updateFn))
5969
)
6070

6171
return section("Profiles", profiles, false)
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright 2022 The Kubernetes Authors
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+
17+
import chokidar from "chokidar"
18+
import { basename } from "path"
19+
import { Profiles } from "madwizard"
20+
21+
import UpdateFunction from "../../update"
22+
23+
/** Watch for new, removed, and renamed profiles */
24+
export default class ProfileWatcher {
25+
private _profiles: Profiles.Profile[] = []
26+
27+
private _initDone = false
28+
29+
public constructor(
30+
private readonly updateFn: UpdateFunction,
31+
private readonly profilesPath: string,
32+
private readonly watcher = chokidar.watch(profilesPath)
33+
) {}
34+
35+
/** Initialize `this._profiles` model */
36+
public async init(): Promise<ProfileWatcher> {
37+
if (!this._initDone) {
38+
await this.readOnce()
39+
this.initWatcher()
40+
this._initDone = true
41+
}
42+
43+
return this
44+
}
45+
46+
/** Options we will pass to the madwizard API */
47+
private get madwizardOptions() {
48+
return { profilesPath: this.profilesPath }
49+
}
50+
51+
/** Initialize the filesystem watcher to notify us of new or removed profiles */
52+
private initWatcher() {
53+
this.watcher.on("add", async (path) => {
54+
try {
55+
const profile = basename(path)
56+
if (Profiles.isTemporary(profile)) {
57+
// skip any write-file-atomic temps
58+
return
59+
}
60+
61+
const idx = this.profiles.findIndex((_) => _.name === profile)
62+
if (idx < 0) {
63+
this._profiles.push(await Profiles.restore(this.madwizardOptions, basename(path)).then((_) => _.profile))
64+
this.updateFn()
65+
}
66+
} catch (err) {
67+
console.error("Error loading new profile", path, err)
68+
}
69+
})
70+
71+
this.watcher.on("unlink", (path) => {
72+
const profile = basename(path)
73+
if (Profiles.isTemporary(profile)) {
74+
// skip any write-file-atomic temps
75+
return
76+
}
77+
78+
const idx = this.profiles.findIndex((_) => _.name === profile)
79+
if (idx >= 0) {
80+
this._profiles.splice(idx, 1)
81+
this.updateFn()
82+
}
83+
})
84+
}
85+
86+
/** @return the current profiles model */
87+
public get profiles() {
88+
return this._profiles
89+
}
90+
91+
/** Update the profiles model */
92+
private set profiles(profiles: Profiles.Profile[]) {
93+
this._profiles = profiles
94+
}
95+
96+
/** Read the full list of profiles */
97+
private async readOnce() {
98+
this.profiles = (await Profiles.list(this.madwizardOptions)).map((_) => _.profile)
99+
}
100+
}

plugins/plugin-codeflare/src/tray/watchers/profile/run.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default class ProfileRunWatcher {
3030
public constructor(private readonly profile: string) {}
3131

3232
/** Initialize `this._runs` model */
33-
public async init() {
33+
public async init(): Promise<ProfileRunWatcher> {
3434
await this.readRunsDir()
3535
return this
3636
}

plugins/plugin-madwizard/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@
2323
"access": "public"
2424
},
2525
"dependencies": {
26-
"madwizard": "^0.15.10"
26+
"madwizard": "^0.15.11"
2727
}
2828
}

0 commit comments

Comments
 (0)