Skip to content

Commit 1adff5d

Browse files
committed
add container runtime to preference settings
Signed-off-by: bupd <[email protected]>
1 parent 9e62348 commit 1adff5d

14 files changed

+202
-49
lines changed

Diff for: src/portal/src/app/base/preference-settings/preference-settings.component.html

+74-41
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,81 @@
22
[(clrModalOpen)]="opened"
33
[clrModalClosable]="false"
44
[clrModalStaticBackdrop]="false">
5-
<h3 class="modal-title">{{ 'CHANGE_PWD.TITLE' | translate }}</h3>
5+
<h3 class="modal-title">{{ 'CHANGE_PREF.TITLE' | translate }}</h3>
66
<div class="modal-body dialog-body">
7-
<div class="dropdowns">
8-
<clr-dropdown class="dropdown-lang dropdown bottom-left">
9-
<button class="nav-icon nav-icon-width" clrDropdownToggle>
10-
<clr-icon shape="world" class="icon-left"></clr-icon>
11-
<span class="currentLocale">{{ currentLang }}</span>
12-
<clr-icon size="10" shape="caret down"></clr-icon>
13-
</button>
14-
<clr-dropdown-menu *clrIfOpen>
15-
<a
16-
*ngFor="let lang of guiLanguages"
17-
href="javascript:void(0)"
18-
clrDropdownItem
19-
(click)="switchLanguage(lang[0])"
20-
[class.lang-selected]="matchLang(lang[0])"
21-
>{{ lang[1][0] }}</a
22-
>
23-
</clr-dropdown-menu>
24-
</clr-dropdown>
25-
<div class="nav-divider"></div>
26-
<clr-dropdown class="dropdown-locale dropdown bottom-left">
27-
<button class="nav-icon nav-icon-width" clrDropdownToggle>
28-
<clr-icon shape="date" class="icon-left"></clr-icon>
29-
<span class="currentLocale">{{
30-
currentDatetimeRendering | translate
31-
}}</span>
32-
<clr-icon size="10" shape="caret down"></clr-icon>
33-
</button>
34-
<clr-dropdown-menu *clrIfOpen>
35-
<a
36-
*ngFor="let rendering of guiDatetimeRenderings"
37-
href="javascript:void(0)"
38-
clrDropdownItem
39-
(click)="switchDatetimeRendering(rendering[0])"
40-
[class.locale-selected]="
41-
matchDatetimeRendering(rendering[0])
42-
"
43-
>{{ rendering[1] | translate }}</a
44-
>
45-
</clr-dropdown-menu>
46-
</clr-dropdown>
7+
<div class="dropdowns content-container">
8+
<div class="content-area centered-content-area">
9+
<div class="clr-control-label">
10+
{{ 'CHANGE_PREF.LANGUAGE' | translate }}
11+
</div>
12+
<clr-dropdown class="dropdown-lang dropdown bottom-left">
13+
<button class="nav-icon nav-icon-width" clrDropdownToggle>
14+
<clr-icon shape="world" class="icon-left"></clr-icon>
15+
<span class="currentLocale">{{ currentLang }}</span>
16+
<clr-icon size="10" shape="caret down"></clr-icon>
17+
</button>
18+
<clr-dropdown-menu *clrIfOpen>
19+
<a
20+
*ngFor="let lang of guiLanguages"
21+
href="javascript:void(0)"
22+
clrDropdownItem
23+
(click)="switchLanguage(lang[0])"
24+
[class.lang-selected]="matchLang(lang[0])"
25+
>{{ lang[1][0] }}</a
26+
>
27+
</clr-dropdown-menu>
28+
</clr-dropdown>
29+
</div>
30+
31+
<div class="content-area centered-content-area">
32+
<div class="clr-control-label">
33+
{{ 'CHANGE_PREF.DATE_TIME_FORMAT' | translate }}
34+
</div>
35+
<clr-dropdown class="dropdown bottom-left">
36+
<button class="nav-icon nav-icon-width" clrDropdownToggle>
37+
<clr-icon shape="date" class="icon-left"></clr-icon>
38+
<span class="currentLocale">{{
39+
currentDatetimeRendering | translate
40+
}}</span>
41+
<clr-icon size="10" shape="caret down"></clr-icon>
42+
</button>
43+
<clr-dropdown-menu *clrIfOpen>
44+
<a
45+
*ngFor="let rendering of guiDatetimeRenderings"
46+
href="javascript:void(0)"
47+
clrDropdownItem
48+
(click)="switchDatetimeRendering(rendering[0])"
49+
[class.locale-selected]="
50+
matchDatetimeRendering(rendering[0])
51+
"
52+
>{{ rendering[1] | translate }}</a
53+
>
54+
</clr-dropdown-menu>
55+
</clr-dropdown>
56+
</div>
57+
58+
<div class="content-area centered-content-area">
59+
<div class="clr-control-label">
60+
{{ 'CHANGE_PREF.CONTAINER_RUN' | translate }}
61+
</div>
62+
<clr-dropdown class="dropdown-lang dropdown bottom-left">
63+
<button class="nav-icon nav-icon-width" clrDropdownToggle>
64+
<clr-icon shape="bundle" class="icon-left"></clr-icon>
65+
<span class="currentLocale">{{ currentRuntime }}</span>
66+
<clr-icon size="10" shape="caret down"></clr-icon>
67+
</button>
68+
<clr-dropdown-menu *clrIfOpen>
69+
<a
70+
*ngFor="let runtime of guiRuntimes"
71+
href="javascript:void(0)"
72+
clrDropdownItem
73+
(click)="switchRuntime(runtime[0])"
74+
[class.lang-selected]="matchRuntime(runtime[0])"
75+
>{{ runtime[1] }}</a
76+
>
77+
</clr-dropdown-menu>
78+
</clr-dropdown>
79+
</div>
4780
</div>
4881
</div>
4982
<div class="modal-footer margin-left-override">

Diff for: src/portal/src/app/base/preference-settings/preference-settings.component.scss

+9-7
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,18 @@
5555
}
5656
}
5757

58+
.centered-content-area {
59+
display: flex;
60+
justify-content: space-between;
61+
align-items: center;
62+
width: 70%
63+
}
64+
5865
.dropdowns {
5966
display: flex;
60-
flex-direction: row;
61-
align-content: center;
67+
flex-direction: column;
6268
justify-content: flex-start;
63-
align-items: center;
69+
align-items: start;
6470
gap: 20px;
6571
}
6672

@@ -78,10 +84,6 @@
7884
outline: none;
7985
}
8086

81-
.dropdown-locale {
82-
padding-right: 0.5rem;
83-
}
84-
8587
.user-down {
8688
right: 1rem !important;
8789
}

Diff for: src/portal/src/app/base/preference-settings/preference-settings.component.ts

+29-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ import { Component, OnInit } from '@angular/core';
1515
import { AppConfigService } from '../../services/app-config.service';
1616
import { SkinableConfig } from '../../services/skinable-config.service';
1717
import { TranslateService } from '@ngx-translate/core';
18-
import { getDatetimeRendering } from 'src/app/shared/units/shared.utils';
18+
import {
19+
getContainerRuntime,
20+
getDatetimeRendering,
21+
} from 'src/app/shared/units/shared.utils';
1922
import { registerLocaleData } from '@angular/common';
2023
import { forkJoin, Observable } from 'rxjs';
2124
import { map } from 'rxjs/operators';
@@ -26,11 +29,15 @@ import {
2629
DatetimeRendering,
2730
DEFAULT_DATETIME_RENDERING_LOCALSTORAGE_KEY,
2831
DEFAULT_LANG_LOCALSTORAGE_KEY,
32+
DEFAULT_RUNTIME_LOCALSTORAGE_KEY,
2933
DefaultDatetimeRendering,
3034
DeFaultLang,
35+
DeFaultRuntime,
3136
LANGUAGES,
37+
RUNTIMES,
3238
stringsForClarity,
3339
SupportedLanguage,
40+
SupportedRuntime,
3441
} from '../../shared/entities/shared.const';
3542

3643
@Component({
@@ -40,8 +47,10 @@ import {
4047
})
4148
export class PreferenceSettingsComponent implements OnInit {
4249
readonly guiLanguages = Object.entries(LANGUAGES);
50+
readonly guiRuntimes = Object.entries(RUNTIMES);
4351
readonly guiDatetimeRenderings = Object.entries(DATETIME_RENDERINGS);
4452
selectedLang: SupportedLanguage = DeFaultLang;
53+
selectedRuntime: SupportedRuntime = DeFaultRuntime;
4554
selectedDatetimeRendering: DatetimeRendering = DefaultDatetimeRendering;
4655
opened: boolean = false;
4756
build: string = '4276418';
@@ -75,6 +84,7 @@ export class PreferenceSettingsComponent implements OnInit {
7584
this.translateClarityComponents();
7685
}
7786
this.selectedDatetimeRendering = getDatetimeRendering();
87+
this.selectedRuntime = getContainerRuntime();
7888
}
7989

8090
//Internationalization for Clarity components, refer to https://clarity.design/documentation/internationalization
@@ -105,6 +115,13 @@ export class PreferenceSettingsComponent implements OnInit {
105115
return appConfig.harbor_version;
106116
}
107117

118+
public get currentRuntime(): string {
119+
if (this.selectedRuntime) {
120+
return RUNTIMES[this.selectedRuntime] as string;
121+
}
122+
return null;
123+
}
124+
108125
public get currentLang(): string {
109126
if (this.selectedLang) {
110127
return LANGUAGES[this.selectedLang][0] as string;
@@ -120,6 +137,10 @@ export class PreferenceSettingsComponent implements OnInit {
120137
return lang === this.selectedLang;
121138
}
122139

140+
matchRuntime(runtime: SupportedRuntime): boolean {
141+
return runtime === this.selectedRuntime;
142+
}
143+
123144
matchDatetimeRendering(datetime: DatetimeRendering): boolean {
124145
return datetime === this.selectedDatetimeRendering;
125146
}
@@ -133,6 +154,13 @@ export class PreferenceSettingsComponent implements OnInit {
133154
this.translate.use(lang).subscribe(() => window.location.reload());
134155
}
135156

157+
switchRuntime(runtime: SupportedRuntime): void {
158+
this.selectedRuntime = runtime;
159+
localStorage.setItem(DEFAULT_RUNTIME_LOCALSTORAGE_KEY, runtime);
160+
// have to reload,as HarborDatetimePipe is pure pipe
161+
// window.location.reload();
162+
}
163+
136164
switchDatetimeRendering(datetime: DatetimeRendering): void {
137165
this.selectedDatetimeRendering = datetime;
138166
localStorage.setItem(

Diff for: src/portal/src/app/shared/entities/shared.const.ts

+15
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,21 @@ export enum GroupType {
231231
export const REFRESH_TIME_DIFFERENCE = 10000;
232232

233233
//
234+
//
235+
export const DeFaultRuntime = 'default';
236+
export type SupportedRuntime = string;
237+
export const RUNTIMES = {
238+
'default': 'docker',
239+
'podman': 'podman',
240+
'nerdctl': 'nerdctl',
241+
'ctr': 'containerd',
242+
'crictl': 'cri-o',
243+
} as const;
244+
export const supportedRuntimes = Object.keys(RUNTIMES) as SupportedRuntime[];
245+
/**
246+
* The default cookie key used to store current used language preference.
247+
*/
248+
export const DEFAULT_RUNTIME_LOCALSTORAGE_KEY = 'harbor-runtime';
234249

235250
export const DeFaultLang = 'en-us';
236251
export type SupportedLanguage = string;

Diff for: src/portal/src/app/shared/units/shared.utils.ts

+20
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ import {
2222
httpStatusCode,
2323
SupportedLanguage,
2424
LANGUAGES,
25+
SupportedRuntime,
26+
DEFAULT_RUNTIME_LOCALSTORAGE_KEY,
27+
RUNTIMES,
28+
DeFaultRuntime,
2529
} from '../entities/shared.const';
2630

2731
/**
@@ -208,6 +212,22 @@ export const errorHandler = function (error: any): string {
208212
}
209213
};
210214

215+
/**
216+
* Gets the datetime rendering setting saved by the user, or the default setting if no valid saved value is found.
217+
*/
218+
export function getContainerRuntime(): SupportedRuntime {
219+
const savedContainerRuntime = localStorage.getItem(
220+
DEFAULT_RUNTIME_LOCALSTORAGE_KEY
221+
);
222+
if (savedContainerRuntime && isSupportedRuntime(savedContainerRuntime)) {
223+
return savedContainerRuntime;
224+
}
225+
return DeFaultRuntime;
226+
}
227+
function isSupportedRuntime(x: unknown): x is DatetimeRendering {
228+
return Object.keys(RUNTIMES).some(k => k === x);
229+
}
230+
211231
/**
212232
* Gets the datetime rendering setting saved by the user, or the default setting if no valid saved value is found.
213233
*/

Diff for: src/portal/src/i18n/lang/de-de-lang.json

+6
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@
151151
"SAVE_SUCCESS": "Nutzerpasswort erfolgreich geändert.",
152152
"PASS_TIPS": "8-128 Zeichen mit einem Groß-, einem Kleinbuchstaben und einer Ziffer"
153153
},
154+
"CHANGE_PREF": {
155+
"TITLE": "Change Preference",
156+
"LANGUAGE": "Language",
157+
"DATE_TIME_FORMAT": "Date/Time Format",
158+
"CONTAINER_RUN": "Container Runtime"
159+
},
154160
"ACCOUNT_SETTINGS": {
155161
"PROFILE": "Nutzerprofil",
156162
"PREFERENCES": "Preferences",

Diff for: src/portal/src/i18n/lang/en-us-lang.json

+6
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@
151151
"SAVE_SUCCESS": "User password changed successfully.",
152152
"PASS_TIPS": "8-128 characters long with at least 1 uppercase, 1 lowercase and 1 number"
153153
},
154+
"CHANGE_PREF": {
155+
"TITLE": "Change Preference",
156+
"LANGUAGE": "Language",
157+
"DATE_TIME_FORMAT": "Date/Time Format",
158+
"CONTAINER_RUN": "Container Runtime"
159+
},
154160
"ACCOUNT_SETTINGS": {
155161
"PROFILE": "User Profile",
156162
"PREFERENCES": "Preferences",

Diff for: src/portal/src/i18n/lang/es-es-lang.json

+6
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@
151151
"SAVE_SUCCESS": "Contraseña de usuario guardada satisfactoriamente.",
152152
"PASS_TIPS": "8-128 caracteres con 1 letra mayúscula, 1 minúscula y 1 número"
153153
},
154+
"CHANGE_PREF": {
155+
"TITLE": "Change Preference",
156+
"LANGUAGE": "Language",
157+
"DATE_TIME_FORMAT": "Date/Time Format",
158+
"CONTAINER_RUN": "Container Runtime"
159+
},
154160
"ACCOUNT_SETTINGS": {
155161
"PROFILE": "Perfil de usuario",
156162
"PREFERENCES": "Preferences",

Diff for: src/portal/src/i18n/lang/fr-fr-lang.json

+6
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@
151151
"SAVE_SUCCESS": "Mot de passe utilisateur modifié avec succès.",
152152
"PASS_TIPS": "8-128 caractères avec au moins 1 majuscule, 1 minuscule et 1 chiffre"
153153
},
154+
"CHANGE_PREF": {
155+
"TITLE": "Change Preference",
156+
"LANGUAGE": "Language",
157+
"DATE_TIME_FORMAT": "Date/Time Format",
158+
"CONTAINER_RUN": "Container Runtime"
159+
},
154160
"ACCOUNT_SETTINGS": {
155161
"PROFILE": "Profil Utilisateur",
156162
"PREFERENCES": "Preferences",

Diff for: src/portal/src/i18n/lang/ko-kr-lang.json

+6
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@
143143
"CONFIRM_TITLE_CLI_GENERATE": "시크릿을 다시 생성할 수 있습니까?",
144144
"CONFIRM_BODY_CLI_GENERATE": "Cli 시크릿을 재생성하면 이전 Cli 시크릿이 삭제됩니다"
145145
},
146+
"CHANGE_PREF": {
147+
"TITLE": "Change Preference",
148+
"LANGUAGE": "Language",
149+
"DATE_TIME_FORMAT": "Date/Time Format",
150+
"CONTAINER_RUN": "Container Runtime"
151+
},
146152
"CHANGE_PWD": {
147153
"TITLE": "비밀번호 변경",
148154
"CURRENT_PWD": "현재 비밀번호",

Diff for: src/portal/src/i18n/lang/pt-br-lang.json

+6
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@
142142
"CONFIRM_TITLE_CLI_GENERATE": "Gostaria de redefinir o segredo?",
143143
"CONFIRM_BODY_CLI_GENERATE": "Ao fazer isso, o segredo atual não poderá ser recuperado"
144144
},
145+
"CHANGE_PREF": {
146+
"TITLE": "Change Preference",
147+
"LANGUAGE": "Language",
148+
"DATE_TIME_FORMAT": "Date/Time Format",
149+
"CONTAINER_RUN": "Container Runtime"
150+
},
145151
"CHANGE_PWD": {
146152
"TITLE": "Alterar Senha",
147153
"CURRENT_PWD": "Senha atual",

Diff for: src/portal/src/i18n/lang/tr-tr-lang.json

+7
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@
143143
"CONFIRM_TITLE_CLI_GENERATE": "Şifreyi yeniden oluşturabileceğine emin misin?",
144144
"CONFIRM_BODY_CLI_GENERATE": "Eğer cli şifresini yeniden oluşturursanız, eski cli şifresi atılır"
145145
},
146+
"CHANGE_PREF": {
147+
"TITLE": "Change Preference",
148+
"LANGUAGE": "Language",
149+
"DATE_TIME_FORMAT": "Date/Time Format",
150+
"CONTAINER_RUN": "Container Runtime"
151+
},
146152
"CHANGE_PWD": {
147153
"TITLE": "Şifreyi değiştir",
148154
"CURRENT_PWD": "Mevcut Şifre",
@@ -151,6 +157,7 @@
151157
"SAVE_SUCCESS": "Kullanıcı şifresi başarıyla değiştirildi.",
152158
"PASS_TIPS": "1 büyük harf, 1 küçük harf ve 1 sayı ile 8-128 karakter"
153159
},
160+
154161
"ACCOUNT_SETTINGS": {
155162
"PROFILE": "Kullanıcı Profili",
156163
"PREFERENCES": "Preferences",

0 commit comments

Comments
 (0)