mirror of
https://github.com/redhat-developer/odo.git
synced 2025-10-19 03:06:19 +03:00
[ui] Edit volumes (#7061)
* Update volumes * Proxy use ipv4 * Static ui files * e2e tests
This commit is contained in:
@@ -939,6 +939,47 @@ paths:
|
|||||||
example:
|
example:
|
||||||
message: "Error deleting the volume"
|
message: "Error deleting the volume"
|
||||||
|
|
||||||
|
patch:
|
||||||
|
tags:
|
||||||
|
- devstate
|
||||||
|
description: "Update a volume"
|
||||||
|
parameters:
|
||||||
|
- name: volumeName
|
||||||
|
in: path
|
||||||
|
description: Volume name to update
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
size:
|
||||||
|
description: Minimal size of the volume
|
||||||
|
type: string
|
||||||
|
ephemeral:
|
||||||
|
description: True if the Volume is Ephemeral
|
||||||
|
type: boolean
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GeneralSuccess'
|
||||||
|
example:
|
||||||
|
message: "Volume has been updated"
|
||||||
|
description: "Volume has been updated"
|
||||||
|
'500':
|
||||||
|
description: Error updating the volume
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GeneralError'
|
||||||
|
example:
|
||||||
|
message: "Error updating the volume"
|
||||||
|
|
||||||
/devstate/applyCommand:
|
/devstate/applyCommand:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
|
|||||||
1
pkg/apiserver-gen/.openapi-generator/FILES
generated
1
pkg/apiserver-gen/.openapi-generator/FILES
generated
@@ -20,6 +20,7 @@ go/model__devstate_exec_command_post_request.go
|
|||||||
go/model__devstate_image_post_request.go
|
go/model__devstate_image_post_request.go
|
||||||
go/model__devstate_quantity_valid_post_request.go
|
go/model__devstate_quantity_valid_post_request.go
|
||||||
go/model__devstate_resource_post_request.go
|
go/model__devstate_resource_post_request.go
|
||||||
|
go/model__devstate_volume__volume_name__patch_request.go
|
||||||
go/model__devstate_volume_post_request.go
|
go/model__devstate_volume_post_request.go
|
||||||
go/model__instance_get_200_response.go
|
go/model__instance_get_200_response.go
|
||||||
go/model_annotation.go
|
go/model_annotation.go
|
||||||
|
|||||||
2
pkg/apiserver-gen/go/api.go
generated
2
pkg/apiserver-gen/go/api.go
generated
@@ -53,6 +53,7 @@ type DevstateApiRouter interface {
|
|||||||
DevstateResourceResourceNameDelete(http.ResponseWriter, *http.Request)
|
DevstateResourceResourceNameDelete(http.ResponseWriter, *http.Request)
|
||||||
DevstateVolumePost(http.ResponseWriter, *http.Request)
|
DevstateVolumePost(http.ResponseWriter, *http.Request)
|
||||||
DevstateVolumeVolumeNameDelete(http.ResponseWriter, *http.Request)
|
DevstateVolumeVolumeNameDelete(http.ResponseWriter, *http.Request)
|
||||||
|
DevstateVolumeVolumeNamePatch(http.ResponseWriter, *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultApiServicer defines the api actions for the DefaultApi service
|
// DefaultApiServicer defines the api actions for the DefaultApi service
|
||||||
@@ -96,4 +97,5 @@ type DevstateApiServicer interface {
|
|||||||
DevstateResourceResourceNameDelete(context.Context, string) (ImplResponse, error)
|
DevstateResourceResourceNameDelete(context.Context, string) (ImplResponse, error)
|
||||||
DevstateVolumePost(context.Context, DevstateVolumePostRequest) (ImplResponse, error)
|
DevstateVolumePost(context.Context, DevstateVolumePostRequest) (ImplResponse, error)
|
||||||
DevstateVolumeVolumeNameDelete(context.Context, string) (ImplResponse, error)
|
DevstateVolumeVolumeNameDelete(context.Context, string) (ImplResponse, error)
|
||||||
|
DevstateVolumeVolumeNamePatch(context.Context, string, DevstateVolumeVolumeNamePatchRequest) (ImplResponse, error)
|
||||||
}
|
}
|
||||||
|
|||||||
32
pkg/apiserver-gen/go/api_devstate.go
generated
32
pkg/apiserver-gen/go/api_devstate.go
generated
@@ -182,6 +182,12 @@ func (c *DevstateApiController) Routes() Routes {
|
|||||||
"/api/v1/devstate/volume/{volumeName}",
|
"/api/v1/devstate/volume/{volumeName}",
|
||||||
c.DevstateVolumeVolumeNameDelete,
|
c.DevstateVolumeVolumeNameDelete,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"DevstateVolumeVolumeNamePatch",
|
||||||
|
strings.ToUpper("Patch"),
|
||||||
|
"/api/v1/devstate/volume/{volumeName}",
|
||||||
|
c.DevstateVolumeVolumeNamePatch,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,3 +635,29 @@ func (c *DevstateApiController) DevstateVolumeVolumeNameDelete(w http.ResponseWr
|
|||||||
EncodeJSONResponse(result.Body, &result.Code, w)
|
EncodeJSONResponse(result.Body, &result.Code, w)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DevstateVolumeVolumeNamePatch -
|
||||||
|
func (c *DevstateApiController) DevstateVolumeVolumeNamePatch(w http.ResponseWriter, r *http.Request) {
|
||||||
|
params := mux.Vars(r)
|
||||||
|
volumeNameParam := params["volumeName"]
|
||||||
|
devstateVolumeVolumeNamePatchRequestParam := DevstateVolumeVolumeNamePatchRequest{}
|
||||||
|
d := json.NewDecoder(r.Body)
|
||||||
|
d.DisallowUnknownFields()
|
||||||
|
if err := d.Decode(&devstateVolumeVolumeNamePatchRequestParam); err != nil {
|
||||||
|
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := AssertDevstateVolumeVolumeNamePatchRequestRequired(devstateVolumeVolumeNamePatchRequestParam); err != nil {
|
||||||
|
c.errorHandler(w, r, err, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result, err := c.service.DevstateVolumeVolumeNamePatch(r.Context(), volumeNameParam, devstateVolumeVolumeNamePatchRequestParam)
|
||||||
|
// If an error occurred, encode the error with the status code
|
||||||
|
if err != nil {
|
||||||
|
c.errorHandler(w, r, err, &result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// If no error, encode the body and the result code
|
||||||
|
EncodeJSONResponse(result.Body, &result.Code, w)
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
36
pkg/apiserver-gen/go/model__devstate_volume__volume_name__patch_request.go
generated
Normal file
36
pkg/apiserver-gen/go/model__devstate_volume__volume_name__patch_request.go
generated
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* odo dev
|
||||||
|
*
|
||||||
|
* API interface for 'odo dev'
|
||||||
|
*
|
||||||
|
* API version: 0.1
|
||||||
|
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
|
||||||
|
*/
|
||||||
|
|
||||||
|
package openapi
|
||||||
|
|
||||||
|
type DevstateVolumeVolumeNamePatchRequest struct {
|
||||||
|
|
||||||
|
// Minimal size of the volume
|
||||||
|
Size string `json:"size,omitempty"`
|
||||||
|
|
||||||
|
// True if the Volume is Ephemeral
|
||||||
|
Ephemeral bool `json:"ephemeral,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssertDevstateVolumeVolumeNamePatchRequestRequired checks if the required fields are not zero-ed
|
||||||
|
func AssertDevstateVolumeVolumeNamePatchRequestRequired(obj DevstateVolumeVolumeNamePatchRequest) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssertRecurseDevstateVolumeVolumeNamePatchRequestRequired recursively checks if required fields are not zero-ed in a nested slice.
|
||||||
|
// Accepts only nested slice of DevstateVolumeVolumeNamePatchRequest (e.g. [][]DevstateVolumeVolumeNamePatchRequest), otherwise ErrTypeAssertionError is thrown.
|
||||||
|
func AssertRecurseDevstateVolumeVolumeNamePatchRequestRequired(objSlice interface{}) error {
|
||||||
|
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
|
||||||
|
aDevstateVolumeVolumeNamePatchRequest, ok := obj.(DevstateVolumeVolumeNamePatchRequest)
|
||||||
|
if !ok {
|
||||||
|
return ErrTypeAssertionError
|
||||||
|
}
|
||||||
|
return AssertDevstateVolumeVolumeNamePatchRequestRequired(aDevstateVolumeVolumeNamePatchRequest)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -297,3 +297,18 @@ func (s *DevstateApiService) DevstateDevfileDelete(context.Context) (openapi.Imp
|
|||||||
}
|
}
|
||||||
return openapi.Response(http.StatusOK, newContent), nil
|
return openapi.Response(http.StatusOK, newContent), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DevstateApiService) DevstateVolumeVolumeNamePatch(ctx context.Context, name string, patch openapi.DevstateVolumeVolumeNamePatchRequest) (openapi.ImplResponse, error) {
|
||||||
|
newContent, err := s.devfileState.PatchVolume(
|
||||||
|
name,
|
||||||
|
patch.Ephemeral,
|
||||||
|
patch.Size,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return openapi.Response(http.StatusInternalServerError, openapi.GeneralError{
|
||||||
|
Message: fmt.Sprintf("Error updating the volume: %s", err),
|
||||||
|
}), nil
|
||||||
|
}
|
||||||
|
return openapi.Response(http.StatusOK, newContent), nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -267,8 +267,32 @@ func (o *DevfileState) AddVolume(name string, ephemeral bool, size string) (Devf
|
|||||||
return o.GetContent()
|
return o.GetContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *DevfileState) DeleteVolume(name string) (DevfileContent, error) {
|
func (o *DevfileState) PatchVolume(name string, ephemeral bool, size string) (DevfileContent, error) {
|
||||||
|
found, err := o.Devfile.Data.GetComponents(common.DevfileOptions{
|
||||||
|
ComponentOptions: common.ComponentOptions{
|
||||||
|
ComponentType: v1alpha2.VolumeComponentType,
|
||||||
|
},
|
||||||
|
FilterByName: name,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return DevfileContent{}, err
|
||||||
|
}
|
||||||
|
if len(found) != 1 {
|
||||||
|
return DevfileContent{}, fmt.Errorf("%d Volume found with name %q", len(found), name)
|
||||||
|
}
|
||||||
|
|
||||||
|
volume := found[0]
|
||||||
|
volume.Volume.Ephemeral = &ephemeral
|
||||||
|
volume.Volume.Size = size
|
||||||
|
|
||||||
|
err = o.Devfile.Data.UpdateComponent(volume)
|
||||||
|
if err != nil {
|
||||||
|
return DevfileContent{}, err
|
||||||
|
}
|
||||||
|
return o.GetContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *DevfileState) DeleteVolume(name string) (DevfileContent, error) {
|
||||||
err := o.checkVolumeUsed(name)
|
err := o.checkVolumeUsed(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DevfileContent{}, fmt.Errorf("error deleting volume %q: %w", name, err)
|
return DevfileContent{}, fmt.Errorf("error deleting volume %q: %w", name, err)
|
||||||
|
|||||||
@@ -939,6 +939,47 @@ paths:
|
|||||||
example:
|
example:
|
||||||
message: "Error deleting the volume"
|
message: "Error deleting the volume"
|
||||||
|
|
||||||
|
patch:
|
||||||
|
tags:
|
||||||
|
- devstate
|
||||||
|
description: "Update a volume"
|
||||||
|
parameters:
|
||||||
|
- name: volumeName
|
||||||
|
in: path
|
||||||
|
description: Volume name to update
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
size:
|
||||||
|
description: Minimal size of the volume
|
||||||
|
type: string
|
||||||
|
ephemeral:
|
||||||
|
description: True if the Volume is Ephemeral
|
||||||
|
type: boolean
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GeneralSuccess'
|
||||||
|
example:
|
||||||
|
message: "Volume has been updated"
|
||||||
|
description: "Volume has been updated"
|
||||||
|
'500':
|
||||||
|
description: Error updating the volume
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/GeneralError'
|
||||||
|
example:
|
||||||
|
message: "Error updating the volume"
|
||||||
|
|
||||||
/devstate/applyCommand:
|
/devstate/applyCommand:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
|
|||||||
2
pkg/apiserver-impl/ui/index.html
generated
2
pkg/apiserver-impl/ui/index.html
generated
@@ -11,6 +11,6 @@
|
|||||||
<body class="mat-typography">
|
<body class="mat-typography">
|
||||||
<div id="loading">Loading, please wait...</div>
|
<div id="loading">Loading, please wait...</div>
|
||||||
<app-root></app-root>
|
<app-root></app-root>
|
||||||
<script src="runtime.1289ea0acffcdc5e.js" type="module"></script><script src="polyfills.8b3b37cedaf377c3.js" type="module"></script><script src="main.fcdb01b1f229861f.js" type="module"></script>
|
<script src="runtime.1289ea0acffcdc5e.js" type="module"></script><script src="polyfills.8b3b37cedaf377c3.js" type="module"></script><script src="main.74249c789bca5336.js" type="module"></script>
|
||||||
|
|
||||||
</body></html>
|
</body></html>
|
||||||
File diff suppressed because one or more lines are too long
@@ -220,6 +220,31 @@ describe('devfile editor spec', () => {
|
|||||||
.should('contain.text', 'Yes')
|
.should('contain.text', 'Yes')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('displays a modified volume', () => {
|
||||||
|
cy.init();
|
||||||
|
|
||||||
|
cy.selectTab(TAB_VOLUMES);
|
||||||
|
cy.getByDataCy('volume-name').type('created-volume');
|
||||||
|
cy.getByDataCy('volume-size').type('512Mi');
|
||||||
|
cy.getByDataCy('volume-ephemeral').click();
|
||||||
|
cy.getByDataCy('volume-create').click();
|
||||||
|
|
||||||
|
cy.getByDataCy('volume-info').first()
|
||||||
|
.should('contain.text', 'created-volume')
|
||||||
|
.should('contain.text', '512Mi')
|
||||||
|
.should('contain.text', 'Yes');
|
||||||
|
|
||||||
|
cy.getByDataCy('volume-edit').click();
|
||||||
|
cy.getByDataCy('volume-size').type('{selectAll}{del}1Gi');
|
||||||
|
cy.getByDataCy('volume-ephemeral').click();
|
||||||
|
cy.getByDataCy('volume-save').click();
|
||||||
|
|
||||||
|
cy.getByDataCy('volume-info').first()
|
||||||
|
.should('contain.text', 'created-volume')
|
||||||
|
.should('contain.text', '1Gi')
|
||||||
|
.should('contain.text', 'No');
|
||||||
|
});
|
||||||
|
|
||||||
it('creates an exec command with a new container', () => {
|
it('creates an exec command with a new container', () => {
|
||||||
cy.init();
|
cy.init();
|
||||||
|
|
||||||
|
|||||||
1
ui/src/app/api-gen/.openapi-generator/FILES
generated
1
ui/src/app/api-gen/.openapi-generator/FILES
generated
@@ -31,6 +31,7 @@ model/devstateImagePostRequest.ts
|
|||||||
model/devstateQuantityValidPostRequest.ts
|
model/devstateQuantityValidPostRequest.ts
|
||||||
model/devstateResourcePostRequest.ts
|
model/devstateResourcePostRequest.ts
|
||||||
model/devstateVolumePostRequest.ts
|
model/devstateVolumePostRequest.ts
|
||||||
|
model/devstateVolumeVolumeNamePatchRequest.ts
|
||||||
model/endpoint.ts
|
model/endpoint.ts
|
||||||
model/env.ts
|
model/env.ts
|
||||||
model/events.ts
|
model/events.ts
|
||||||
|
|||||||
71
ui/src/app/api-gen/api/devstate.service.ts
generated
71
ui/src/app/api-gen/api/devstate.service.ts
generated
@@ -47,6 +47,8 @@ import { DevstateResourcePostRequest } from '../model/devstateResourcePostReques
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { DevstateVolumePostRequest } from '../model/devstateVolumePostRequest';
|
import { DevstateVolumePostRequest } from '../model/devstateVolumePostRequest';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
import { DevstateVolumeVolumeNamePatchRequest } from '../model/devstateVolumeVolumeNamePatchRequest';
|
||||||
|
// @ts-ignore
|
||||||
import { GeneralError } from '../model/generalError';
|
import { GeneralError } from '../model/generalError';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { GeneralSuccess } from '../model/generalSuccess';
|
import { GeneralSuccess } from '../model/generalSuccess';
|
||||||
@@ -1486,4 +1488,73 @@ export class DevstateService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a volume
|
||||||
|
* @param volumeName Volume name to update
|
||||||
|
* @param devstateVolumeVolumeNamePatchRequest
|
||||||
|
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||||
|
* @param reportProgress flag to report request and response progress.
|
||||||
|
*/
|
||||||
|
public devstateVolumeVolumeNamePatch(volumeName: string, devstateVolumeVolumeNamePatchRequest?: DevstateVolumeVolumeNamePatchRequest, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<GeneralSuccess>;
|
||||||
|
public devstateVolumeVolumeNamePatch(volumeName: string, devstateVolumeVolumeNamePatchRequest?: DevstateVolumeVolumeNamePatchRequest, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<GeneralSuccess>>;
|
||||||
|
public devstateVolumeVolumeNamePatch(volumeName: string, devstateVolumeVolumeNamePatchRequest?: DevstateVolumeVolumeNamePatchRequest, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<GeneralSuccess>>;
|
||||||
|
public devstateVolumeVolumeNamePatch(volumeName: string, devstateVolumeVolumeNamePatchRequest?: DevstateVolumeVolumeNamePatchRequest, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||||
|
if (volumeName === null || volumeName === undefined) {
|
||||||
|
throw new Error('Required parameter volumeName was null or undefined when calling devstateVolumeVolumeNamePatch.');
|
||||||
|
}
|
||||||
|
|
||||||
|
let localVarHeaders = this.defaultHeaders;
|
||||||
|
|
||||||
|
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||||
|
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||||
|
// to determine the Accept header
|
||||||
|
const httpHeaderAccepts: string[] = [
|
||||||
|
'application/json'
|
||||||
|
];
|
||||||
|
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||||
|
}
|
||||||
|
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||||
|
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||||
|
if (localVarHttpContext === undefined) {
|
||||||
|
localVarHttpContext = new HttpContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// to determine the Content-Type header
|
||||||
|
const consumes: string[] = [
|
||||||
|
'application/json'
|
||||||
|
];
|
||||||
|
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
|
||||||
|
if (httpContentTypeSelected !== undefined) {
|
||||||
|
localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
let responseType_: 'text' | 'json' | 'blob' = 'json';
|
||||||
|
if (localVarHttpHeaderAcceptSelected) {
|
||||||
|
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||||
|
responseType_ = 'text';
|
||||||
|
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
|
||||||
|
responseType_ = 'json';
|
||||||
|
} else {
|
||||||
|
responseType_ = 'blob';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let localVarPath = `/devstate/volume/${this.configuration.encodeParam({name: "volumeName", value: volumeName, in: "path", style: "simple", explode: false, dataType: "string", dataFormat: undefined})}`;
|
||||||
|
return this.httpClient.request<GeneralSuccess>('patch', `${this.configuration.basePath}${localVarPath}`,
|
||||||
|
{
|
||||||
|
context: localVarHttpContext,
|
||||||
|
body: devstateVolumeVolumeNamePatchRequest,
|
||||||
|
responseType: <any>responseType_,
|
||||||
|
withCredentials: this.configuration.withCredentials,
|
||||||
|
headers: localVarHeaders,
|
||||||
|
observe: observe,
|
||||||
|
reportProgress: reportProgress
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
24
ui/src/app/api-gen/model/devstateVolumeVolumeNamePatchRequest.ts
generated
Normal file
24
ui/src/app/api-gen/model/devstateVolumeVolumeNamePatchRequest.ts
generated
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* odo dev
|
||||||
|
* API interface for \'odo dev\'
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 0.1
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
export interface DevstateVolumeVolumeNamePatchRequest {
|
||||||
|
/**
|
||||||
|
* Minimal size of the volume
|
||||||
|
*/
|
||||||
|
size?: string;
|
||||||
|
/**
|
||||||
|
* True if the Volume is Ephemeral
|
||||||
|
*/
|
||||||
|
ephemeral?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
1
ui/src/app/api-gen/model/models.ts
generated
1
ui/src/app/api-gen/model/models.ts
generated
@@ -21,6 +21,7 @@ export * from './devstateImagePostRequest';
|
|||||||
export * from './devstateQuantityValidPostRequest';
|
export * from './devstateQuantityValidPostRequest';
|
||||||
export * from './devstateResourcePostRequest';
|
export * from './devstateResourcePostRequest';
|
||||||
export * from './devstateVolumePostRequest';
|
export * from './devstateVolumePostRequest';
|
||||||
|
export * from './devstateVolumeVolumeNamePatchRequest';
|
||||||
export * from './endpoint';
|
export * from './endpoint';
|
||||||
export * from './env';
|
export * from './env';
|
||||||
export * from './events';
|
export * from './events';
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<div class="main">
|
<div class="main">
|
||||||
<h2>Add a new volume</h2>
|
<h2 *ngIf="!volume">Add a new volume</h2>
|
||||||
|
<h2 *ngIf="volume">Edit volume <i>{{volume.name}}</i></h2>
|
||||||
<div class="description">A volume can be mounted and shared by several containers.</div>
|
<div class="description">A volume can be mounted and shared by several containers.</div>
|
||||||
<form [formGroup]="form">
|
<form [formGroup]="form">
|
||||||
<mat-form-field appearance="outline" class="mid-width">
|
<mat-form-field appearance="outline" class="mid-width">
|
||||||
@@ -15,6 +16,7 @@
|
|||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<button data-cy="volume-create" [disabled]="form.invalid" mat-flat-button color="primary" matTooltip="create new volume" (click)="create()">Create</button>
|
<button *ngIf="!volume" data-cy="volume-create" [disabled]="form.invalid" mat-flat-button color="primary" matTooltip="create new volume" (click)="create()">Create</button>
|
||||||
|
<button *ngIf="volume" data-cy="volume-save" [disabled]="form.invalid" mat-flat-button color="primary" matTooltip="save volume" (click)="save()">Save</button>
|
||||||
<button *ngIf="cancelable" mat-flat-button (click)="cancel()">Cancel</button>
|
<button *ngIf="cancelable" mat-flat-button (click)="cancel()">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, Output, SimpleChanges } from '@angular/core';
|
||||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
import { Volume } from 'src/app/api-gen';
|
import { Volume } from 'src/app/api-gen';
|
||||||
import { TelemetryService } from 'src/app/services/telemetry.service';
|
import { TelemetryService } from 'src/app/services/telemetry.service';
|
||||||
@@ -12,8 +12,11 @@ import { DevstateService } from 'src/app/services/devstate.service';
|
|||||||
})
|
})
|
||||||
export class VolumeComponent {
|
export class VolumeComponent {
|
||||||
@Input() cancelable: boolean = false;
|
@Input() cancelable: boolean = false;
|
||||||
|
@Input() volume: Volume | undefined;
|
||||||
|
|
||||||
@Output() canceled = new EventEmitter<void>();
|
@Output() canceled = new EventEmitter<void>();
|
||||||
@Output() created = new EventEmitter<Volume>();
|
@Output() created = new EventEmitter<Volume>();
|
||||||
|
@Output() saved = new EventEmitter<Volume>();
|
||||||
|
|
||||||
form: FormGroup;
|
form: FormGroup;
|
||||||
|
|
||||||
@@ -33,7 +36,28 @@ export class VolumeComponent {
|
|||||||
this.created.emit(this.form.value);
|
this.created.emit(this.form.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
const newValue = this.form.value;
|
||||||
|
newValue.name = this.volume?.name;
|
||||||
|
this.telemetry.track("[ui] edit volume");
|
||||||
|
this.saved.emit(this.form.value);
|
||||||
|
}
|
||||||
|
|
||||||
cancel() {
|
cancel() {
|
||||||
this.canceled.emit();
|
this.canceled.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
if (!changes['volume']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const vol = changes['volume'].currentValue;
|
||||||
|
if (vol == undefined) {
|
||||||
|
this.form.get('name')?.enable();
|
||||||
|
} else {
|
||||||
|
this.form.reset();
|
||||||
|
this.form.patchValue(vol);
|
||||||
|
this.form.get('name')?.disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,13 @@ export class DevstateService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
saveVolume(volume: Volume): Observable<DevfileContent> {
|
||||||
|
return this.http.patch<DevfileContent>(this.base+"/volume/"+volume.name, {
|
||||||
|
ephemeral: volume.ephemeral,
|
||||||
|
size: volume.size,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
addExecCommand(name: string, cmd: ExecCommand): Observable<DevfileContent> {
|
addExecCommand(name: string, cmd: ExecCommand): Observable<DevfileContent> {
|
||||||
return this.http.post<DevfileContent>(this.base+"/execCommand", {
|
return this.http.post<DevfileContent>(this.base+"/execCommand", {
|
||||||
name: name,
|
name: name,
|
||||||
|
|||||||
@@ -19,19 +19,22 @@
|
|||||||
|
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<button mat-button color="warn" (click)="delete(volume.name)">Delete</button>
|
<button mat-button color="warn" (click)="delete(volume.name)">Delete</button>
|
||||||
|
<button data-cy="volume-edit" mat-button (click)="edit(volume)">Edit</button>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
|
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
<app-volume
|
<app-volume
|
||||||
*ngIf="forceDisplayAdd || volumes == undefined || volumes.length == 0"
|
*ngIf="forceDisplayForm || volumes == undefined || volumes.length == 0"
|
||||||
[cancelable]="forceDisplayAdd"
|
[cancelable]="forceDisplayForm"
|
||||||
(canceled)="undisplayAddForm()"
|
(canceled)="undisplayAddForm()"
|
||||||
(created)="onCreated($event)"
|
(created)="onCreated($event)"
|
||||||
|
[volume]="editingVolume"
|
||||||
|
(saved)="onSaved($event)"
|
||||||
></app-volume>
|
></app-volume>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container *ngIf="!forceDisplayAdd && volumes != undefined && volumes.length > 0">
|
<ng-container *ngIf="!forceDisplayForm && volumes != undefined && volumes.length > 0">
|
||||||
<button class="fab" mat-fab color="primary" (click)="displayAddForm()">
|
<button class="fab" mat-fab color="primary" (click)="displayAddForm()">
|
||||||
<mat-icon class="material-icons-outlined">add</mat-icon>
|
<mat-icon class="material-icons-outlined">add</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ import { StateService } from 'src/app/services/state.service';
|
|||||||
})
|
})
|
||||||
export class VolumesComponent {
|
export class VolumesComponent {
|
||||||
|
|
||||||
forceDisplayAdd: boolean = false;
|
forceDisplayForm: boolean = false;
|
||||||
volumes: Volume[] | undefined = [];
|
volumes: Volume[] | undefined = [];
|
||||||
|
editingVolume: Volume | undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private state: StateService,
|
private state: StateService,
|
||||||
@@ -25,19 +26,24 @@ export class VolumesComponent {
|
|||||||
if (this.volumes == null) {
|
if (this.volumes == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
that.forceDisplayAdd = false;
|
that.forceDisplayForm = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
displayAddForm() {
|
displayAddForm() {
|
||||||
this.forceDisplayAdd = true;
|
this.editingVolume = undefined;
|
||||||
|
this.displayForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
displayForm() {
|
||||||
|
this.forceDisplayForm = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.scrollToBottom();
|
this.scrollToBottom();
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
undisplayAddForm() {
|
undisplayAddForm() {
|
||||||
this.forceDisplayAdd = false;
|
this.forceDisplayForm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(name: string) {
|
delete(name: string) {
|
||||||
@@ -54,6 +60,11 @@ export class VolumesComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
edit(volume: Volume) {
|
||||||
|
this.editingVolume = volume;
|
||||||
|
this.displayForm();
|
||||||
|
}
|
||||||
|
|
||||||
onCreated(volume: Volume) {
|
onCreated(volume: Volume) {
|
||||||
const result = this.devstate.addVolume(volume);
|
const result = this.devstate.addVolume(volume);
|
||||||
result.subscribe({
|
result.subscribe({
|
||||||
@@ -66,6 +77,18 @@ export class VolumesComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSaved(volume: Volume) {
|
||||||
|
const result = this.devstate.saveVolume(volume);
|
||||||
|
result.subscribe({
|
||||||
|
next: value => {
|
||||||
|
this.state.changeDevfileYaml(value);
|
||||||
|
},
|
||||||
|
error: error => {
|
||||||
|
alert(error.error.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
scrollToBottom() {
|
scrollToBottom() {
|
||||||
window.scrollTo(0,document.body.scrollHeight);
|
window.scrollTo(0,document.body.scrollHeight);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"/api/v1": {
|
"/api/v1": {
|
||||||
"target": "http://localhost:20000",
|
"target": "http://127.0.0.1:20000",
|
||||||
"secure": false
|
"secure": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user