Skip to content

Commit c0ffee5

Browse files
committed
extend copy pull command with custom prefix
* This commit adds custom as dropdown option * add custom_runtime localstorage variable for the pull prefix * fix artifact list tab styles * align copy icon in artifact tag list tab Signed-off-by: bupd <[email protected]>
1 parent 4fa9a0e commit c0ffee5

File tree

11 files changed

+184
-52
lines changed

11 files changed

+184
-52
lines changed

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

+69-9
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[clrModalClosable]="false"
44
[clrModalStaticBackdrop]="false">
55
<h3 class="modal-title">{{ 'CHANGE_PREF.TITLE' | translate }}</h3>
6-
<div class="modal-body dialog-body">
6+
<div class="modal-body body-format dialog-body">
77
<div class="dropdowns content-container">
88
<div class="content-area centered-content-area">
99
<div class="clr-control-label">
@@ -66,14 +66,74 @@ <h3 class="modal-title">{{ 'CHANGE_PREF.TITLE' | translate }}</h3>
6666
<clr-icon size="10" shape="caret down"></clr-icon>
6767
</button>
6868
<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-
>
69+
<clr-dropdown>
70+
<button clrDropdownTrigger>custom</button>
71+
<clr-dropdown-menu *clrIfOpen>
72+
<form
73+
#customruntimeForm="ngForm"
74+
class="clr-form">
75+
<div class="clr-form-control">
76+
<label
77+
for="customPrefix"
78+
class="clr-control-label"
79+
>Custom</label
80+
>
81+
<div class="clr-control-container">
82+
<div class="clr-input-wrapper">
83+
<input
84+
type="text"
85+
id="customPrefix"
86+
name="customPrefix"
87+
placeholder="Enter custom prefix"
88+
[(ngModel)]="customRuntime"
89+
#customPrefix="ngModel"
90+
minlength="2"
91+
class="clr-input" />
92+
<cds-icon
93+
class="clr-validate-icon"
94+
shape="exclamation-circle"></cds-icon>
95+
</div>
96+
<div
97+
*ngIf="
98+
customPrefix.invalid &&
99+
customPrefix.touched
100+
">
101+
<div
102+
*ngIf="customPrefix.errors?.['required']">
103+
Prefix is required
104+
</div>
105+
<div
106+
*ngIf="customPrefix.errors?.['minlength']">
107+
Prefix must be at least 2
108+
characters
109+
</div>
110+
</div>
111+
<!-- <span class="clr-subtext">Helper Text</span> -->
112+
</div>
113+
<div class="modal-footer">
114+
<button
115+
clrDropdownItem
116+
type="button"
117+
class="btn btn-primary"
118+
id="ok-btn"
119+
[disabled]="!isValid"
120+
(click)="addCustomRuntime()">
121+
{{ 'BUTTON.OK' | translate }}
122+
</button>
123+
</div>
124+
</div>
125+
</form>
126+
</clr-dropdown-menu>
127+
</clr-dropdown>
128+
<ng-container *ngFor="let runtime of guiRuntimes">
129+
<a
130+
href="javascript:void(0)"
131+
clrDropdownItem
132+
(click)="switchRuntime(runtime[0])"
133+
[class.lang-selected]="matchRuntime(runtime[0])"
134+
>{{ runtime[1] }}</a
135+
>
136+
</ng-container>
77137
</clr-dropdown-menu>
78138
</clr-dropdown>
79139
</div>

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
}
1818

1919
.centered-content-area {
20-
display: flex;
21-
justify-content: space-between;
22-
align-items: center;
23-
width: 70%
20+
display: flex;
21+
justify-content: space-between;
22+
align-items: center;
23+
width: 70%;
2424
}
2525

2626
.dropdowns {

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

+40-2
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14-
import { Component, OnInit } from '@angular/core';
14+
import { Component, OnInit, ViewChild } from '@angular/core';
1515
import { TranslateService } from '@ngx-translate/core';
1616
import {
1717
getContainerRuntime,
18+
getCustomContainerRuntime,
1819
getDatetimeRendering,
1920
} from 'src/app/shared/units/shared.utils';
2021
import { registerLocaleData } from '@angular/common';
@@ -23,6 +24,7 @@ import { map } from 'rxjs/operators';
2324
import { ClrCommonStrings } from '@clr/angular/utils/i18n/common-strings.interface';
2425
import { ClrCommonStringsService } from '@clr/angular';
2526
import {
27+
CUSTOM_RUNTIME_LOCALSTORAGE_KEY,
2628
DATETIME_RENDERINGS,
2729
DatetimeRendering,
2830
DEFAULT_DATETIME_RENDERING_LOCALSTORAGE_KEY,
@@ -37,6 +39,8 @@ import {
3739
SupportedLanguage,
3840
SupportedRuntime,
3941
} from '../../shared/entities/shared.const';
42+
import { NgForm } from '@angular/forms';
43+
import { InlineAlertComponent } from 'src/app/shared/components/inline-alert/inline-alert.component';
4044

4145
@Component({
4246
selector: 'preference-settings',
@@ -45,12 +49,21 @@ import {
4549
})
4650
export class PreferenceSettingsComponent implements OnInit {
4751
readonly guiLanguages = Object.entries(LANGUAGES);
48-
readonly guiRuntimes = Object.entries(RUNTIMES);
52+
readonly guiRuntimes = Object.entries(RUNTIMES).filter(
53+
([_, value]) => value !== RUNTIMES.custom
54+
);
4955
readonly guiDatetimeRenderings = Object.entries(DATETIME_RENDERINGS);
5056
selectedLang: SupportedLanguage = DeFaultLang;
5157
selectedRuntime: SupportedRuntime = DeFaultRuntime;
5258
selectedDatetimeRendering: DatetimeRendering = DefaultDatetimeRendering;
5359
opened: boolean = false;
60+
error: any = null;
61+
customRuntime: string = '';
62+
63+
@ViewChild('customruntimeForm', { static: false })
64+
customRuntimeForm: NgForm;
65+
@ViewChild(InlineAlertComponent, { static: true })
66+
inlineAlert: InlineAlertComponent;
5467

5568
constructor(
5669
private translate: TranslateService,
@@ -68,6 +81,27 @@ export class PreferenceSettingsComponent implements OnInit {
6881
}
6982
this.selectedDatetimeRendering = getDatetimeRendering();
7083
this.selectedRuntime = getContainerRuntime();
84+
this.customRuntime = getCustomContainerRuntime();
85+
}
86+
87+
// Check If form is valid
88+
public get isValid(): boolean {
89+
const customPrefixControl =
90+
this.customRuntimeForm?.form.get('customPrefix');
91+
92+
return (
93+
customPrefixControl?.valid &&
94+
customPrefixControl?.value?.trim() !== '' &&
95+
this.error === null
96+
);
97+
}
98+
99+
addCustomRuntime() {
100+
if (this.customRuntime.trim()) {
101+
const customRuntimeValue = this.customRuntime.trim();
102+
this.switchRuntime('custom');
103+
this.switchCustomRuntime(customRuntimeValue);
104+
}
71105
}
72106

73107
//Internationalization for Clarity components, refer to https://clarity.design/documentation/internationalization
@@ -137,6 +171,10 @@ export class PreferenceSettingsComponent implements OnInit {
137171
localStorage.setItem(DEFAULT_RUNTIME_LOCALSTORAGE_KEY, runtime);
138172
}
139173

174+
switchCustomRuntime(runtime: SupportedRuntime): void {
175+
localStorage.setItem(CUSTOM_RUNTIME_LOCALSTORAGE_KEY, runtime);
176+
}
177+
140178
switchDatetimeRendering(datetime: DatetimeRendering): void {
141179
this.selectedDatetimeRendering = datetime;
142180
localStorage.setItem(

Diff for: src/portal/src/app/base/project/repository/artifact/artifact-list-page/artifact-list/artifact-list-tab/artifact-list-tab.component.scss

+2
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@
203203
display: flex;
204204
align-items: center;
205205
justify-content: space-between;
206+
flex-wrap: wrap;
207+
gap: 8px;
206208
}
207209

208210
.signpost-item {

Diff for: src/portal/src/app/base/project/repository/artifact/artifact-list-page/artifact-list/artifact-list-tab/pull-command/pull-command.component.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<hbr-copy-input
33
#copyInputComponent
44
(onCopySuccess)="onCpSuccess(getPullCommandForTopModel())"
5-
inputSize="30"
5+
inputSize="55"
66
headerTitle=""
77
defaultValue="{{ getPullCommandForTopModel() }}"></hbr-copy-input>
88
</div>

Diff for: src/portal/src/app/base/project/repository/artifact/artifact-tag/artifact-tag.component.html

+1-3
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,7 @@ <h4>{{ 'REPOSITORY.TAGS' | translate }}</h4>
120120
</clr-dg-placeholder>
121121
<clr-dg-row *ngFor="let tag of currentTags" [clrDgItem]="tag">
122122
<clr-dg-cell>
123-
<div
124-
class="pull cell white-normal"
125-
[class.immutable]="tag.immutable">
123+
<div class="pull" [class.immutable]="tag.immutable">
126124
<span
127125
href="javascript:void(0)"
128126
class="max-width-150"
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,73 @@
1-
21
.label-form {
3-
max-width: 100% !important;
2+
max-width: 100% !important;
43
}
54

65
.clr-control-container {
7-
margin-bottom: 1rem;
8-
position: relative;
6+
margin-bottom: 1rem;
7+
position: relative;
98
}
109

1110
.btn.remove-btn {
12-
border: none;
13-
height: 0.6rem;
14-
line-height: 1;
11+
border: none;
12+
height: 0.6rem;
13+
line-height: 1;
1514
}
1615

1716
.immutable {
18-
display: flex;
19-
align-items: center;
20-
position: relative;
17+
display: flex;
18+
align-items: center;
19+
position: relative;
2120

22-
.label {
23-
position: absolute;
24-
right: 0;
25-
margin-right: 0;
26-
}
21+
.label {
22+
position: absolute;
23+
right: 0;
24+
margin-right: 0;
25+
}
2726
}
2827

2928
.datagrid-action-bar {
30-
margin-top: 0.5rem;
29+
margin-top: 0.5rem;
3130
}
3231

3332
.position-ab {
34-
position: absolute;
33+
position: absolute;
3534
}
3635

3736
.white-space-nowrap {
38-
white-space: nowrap;
37+
white-space: nowrap;
38+
}
39+
40+
.pull {
41+
display: flex;
42+
flex-flow: row wrap;
43+
align-content: center;
44+
justify-content: space-between;
45+
align-items: center;
3946
}
4047

4148
.refresh-btn {
42-
cursor: pointer;
49+
cursor: pointer;
4350
}
4451

4552
.spinner-tag {
46-
position: absolute;
47-
right: -.7rem;
48-
top: 1.2rem;
53+
position: absolute;
54+
right: -0.7rem;
55+
top: 1.2rem;
4956
}
5057

5158
.action-bar {
52-
display: flex;
53-
align-items: center;
54-
justify-content: space-between;
59+
display: flex;
60+
align-items: center;
61+
justify-content: space-between;
5562
}
5663

5764
.right-pos {
58-
margin-right: 35px;
59-
display: flex;
60-
align-items: center;
65+
margin-right: 35px;
66+
display: flex;
67+
align-items: center;
6168
}
6269

6370
.pull-btn {
64-
margin-left: 10px
71+
float: right;
72+
margin-right: -20px;
6573
}

Diff for: src/portal/src/app/base/project/repository/artifact/artifact.ts

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Accessory } from 'ng-swagger-gen/models/accessory';
22
import { Artifact } from '../../../../../../ng-swagger-gen/models/artifact';
33
import { Platform } from '../../../../../../ng-swagger-gen/models/platform';
44
import { Label } from '../../../../../../ng-swagger-gen/models/label';
5+
import { getCustomContainerRuntime } from 'src/app/shared/units/shared.utils';
56

67
export interface ArtifactFront extends Artifact {
78
platform?: Platform;
@@ -104,6 +105,9 @@ export function hasPullCommand(artifact: Artifact): boolean {
104105
export function getPullCommandForTop(url: string, client: Clients): string {
105106
if (url) {
106107
if (Object.values(Clients).includes(client)) {
108+
if (client == 'custom') {
109+
return `${getCustomContainerRuntime()} pull ${url}`;
110+
}
107111
return `${client} pull ${url}`;
108112
}
109113
}
@@ -119,6 +123,9 @@ export function getPullCommandByDigest(
119123
if (artifactType && url && digest) {
120124
if (artifactType === ArtifactType.IMAGE) {
121125
if (Object.values(Clients).includes(client)) {
126+
if (client == 'custom') {
127+
return `${getCustomContainerRuntime()} pull ${url}@${digest}`;
128+
}
122129
return `${client} pull ${url}@${digest}`;
123130
}
124131
}
@@ -139,6 +146,10 @@ export function getPullCommandByTag(
139146
if (artifactType && url && tag) {
140147
if (artifactType === ArtifactType.IMAGE) {
141148
if (Object.values(Clients).includes(client)) {
149+
if (client == 'custom') {
150+
return `${getCustomContainerRuntime()} pull ${url}:${tag}`;
151+
}
152+
142153
return `${client} pull ${url}:${tag}`;
143154
}
144155
}
@@ -166,6 +177,7 @@ export enum Clients {
166177
NERDCTL = 'nerdctl',
167178
CONTAINERD = 'ctr',
168179
CRI_O = 'crictl',
180+
CUSTOM = 'custom',
169181
CHART = 'helm',
170182
CNAB = 'cnab-to-oci',
171183
}

Diff for: src/portal/src/app/shared/components/push-image/copy-input.coponent.html

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
<div>
2-
<div class="command-title" *ngIf="!iconMode">
3-
{{ headerTitle }}
4-
</div>
2+
<div class="command-title" *ngIf="!iconMode">{{ headerTitle }}</div>
53
<div>
64
<span [class.hide]="iconMode">
75
<input

0 commit comments

Comments
 (0)