Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ src/webview/welcome
src/webview/helm-chart
src/webview/feedback
src/webview/serverless-function
src/webview/manage-repository
Comment thread
msivasubramaniaan marked this conversation as resolved.
Outdated
# vendored from https://github.com/IonicaBizau/git-url-parse, see https://github.com/IonicaBizau/git-url-parse/pull/159
src/util/gitParse.ts
test/sandbox-registration
1 change: 1 addition & 0 deletions build/esbuild.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const webviews = [
'welcome',
'feedback',
'serverless-function',
'manage-repository',
'add-service-binding',
];

Expand Down
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,12 @@
"category": "OpenShift",
"icon": "$(plus)"
},
{
"command": "openshift.Serverless.manageRepository",
"title": "Manage Repositories",
Comment thread
msivasubramaniaan marked this conversation as resolved.
Outdated
"category": "OpenShift",
"icon": "$(gist)"
},
{
"command": "openshift.Serverless.refresh",
"title": "Refresh Serverless Function View",
Expand Down Expand Up @@ -1299,6 +1305,11 @@
"when": "view == openshiftServerlessFunctionsView",
"group": "navigation@1"
},
{
"command": "openshift.Serverless.manageRepository",
"when": "view == openshiftServerlessFunctionsView",
"group": "navigation@2"
},
{
"command": "openshift.component.openCreateComponent",
"when": "view == openshiftComponentsView",
Expand Down
40 changes: 31 additions & 9 deletions src/serverlessFunction/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,41 @@ export class ServerlessCommand {
}

static config(functionPath: string, mode: string, isAdd: boolean): CommandText {
const option = isAdd ? mode === 'git' ? 'set' : 'add' : 'remove';
const commandText = new CommandText('func', 'config', [
new CommandOption(mode),
new CommandOption(option),
new CommandOption('-p', functionPath)
]);
if (isAdd) {
if (mode === 'git') {
commandText.addOption(new CommandOption('set'));
} else {
commandText.addOption(new CommandOption('add'));
}
} else {
commandText.addOption(new CommandOption('remove'));
}
return commandText;
}

static addRepo(name: string, gitURL: string): CommandText {
const commandText = new CommandText('func', 'repository');
commandText.addOption(new CommandOption('add'));
commandText.addOption(new CommandOption(name));
commandText.addOption(new CommandOption(gitURL));
return commandText;
}

static deleteRepo(name: string): CommandText {
const commandText = new CommandText('func', 'repository');
commandText.addOption(new CommandOption('remove'));
commandText.addOption(new CommandOption(name));
return commandText;
}

static list(): CommandText {
const commandText = new CommandText('func', 'repository');
commandText.addOption(new CommandOption('list'));
return commandText;
}

static renameRepo(oldName: string, newName: string): CommandText {
const commandText = new CommandText('func', 'repository');
commandText.addOption(new CommandOption('rename'));
commandText.addOption(new CommandOption(oldName));
commandText.addOption(new CommandOption(newName));
return commandText;
}
}
97 changes: 97 additions & 0 deletions src/serverlessFunction/mangeRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*-----------------------------------------------------------------------------------------------
Comment thread
msivasubramaniaan marked this conversation as resolved.
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See LICENSE file in the project root for license information.
*-----------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { OdoImpl } from '../odo';
import sendTelemetry from '../telemetry';
import { Progress } from '../util/progress';
import { ServerlessCommand } from './commands';

export class ManageRepository {

private static instance: ManageRepository;

static getInstance(): ManageRepository {
if (!ManageRepository.instance) {
ManageRepository.instance = new ManageRepository();
}
return ManageRepository.instance;
}

public async deleteRepo(name: string): Promise<boolean> {
await sendTelemetry('openshift.managerepo.delete', {
name
});
const result = await OdoImpl.Instance.execute(ServerlessCommand.deleteRepo(name), '', false);
if (result.error) {
await sendTelemetry('openshift.managerepo.delete.error', {
error: result.error.message
});
void vscode.window.showErrorMessage(result.error.message);
return false;
}
return true;
}

public async renameRepo(oldName: string, newName: string): Promise<boolean> {
await sendTelemetry('openshift.managerepo.rename', {
oldName,
newName
});
const result = await OdoImpl.Instance.execute(ServerlessCommand.renameRepo(oldName, newName), '', false);
if (result.error) {
await sendTelemetry('openshift.managerepo.rename.error', {
error: result.error.message
});
void vscode.window.showErrorMessage(result.error.message);
return false;
}
await sendTelemetry('openshift.managerepo.rename.success', {
message: `Repo ${newName} renamed successfully`
});
return true;
}

public async addRepo(name: string, url: string): Promise<boolean> {
await sendTelemetry('openshift.managerepo.add', {
name, url
});
return new Promise<boolean>((resolve, _reject) => {
void Progress.execFunctionWithProgress(`Adding repository ${name}`, async () => {
Comment thread
msivasubramaniaan marked this conversation as resolved.
Outdated
const result = await OdoImpl.Instance.execute(ServerlessCommand.addRepo(name, url), '', false);
if (result.error) {
await sendTelemetry('openshift.managerepo.add.error', {
error: result.error.message
});
void vscode.window.showErrorMessage(result.error.message);
resolve(false);
} else if (result.stdout.length === 0) {
await sendTelemetry('openshift.managerepo.add.success', {
name,
message: 'Repo added successfully'
});
void vscode.window.showInformationMessage(`Repository ${name} added successfully`);
resolve(true);
}
});
});
}

public async list(): Promise<string[]> {
await sendTelemetry('openshift.managerepo.list');
const result = await OdoImpl.Instance.execute(ServerlessCommand.list(), '', false);
if (result.error) {
await sendTelemetry('openshift.managerepo.list.error', {
error: result.error.message
});
void vscode.window.showErrorMessage(result.error.message);
return [];
}
await sendTelemetry('openshift.managerepo.list.success', {
repos: result.stdout.split('\n')
});
return result.stdout.split('\n');
}
}
6 changes: 6 additions & 0 deletions src/serverlessFunction/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { FunctionContextType, FunctionObject, FunctionStatus } from './types';
import ServerlessFunctionViewLoader from '../webview/serverless-function/serverlessFunctionLoader';
import { Functions } from './functions';
import { vsCommand } from '../vscommand';
import ManageRepositoryViewLoader from '../webview/manage-repository/manageRepositoryLoader';

const kubeConfigFolder: string = path.join(Platform.getUserHomePath(), '.kube');

Expand Down Expand Up @@ -203,6 +204,11 @@ export class ServerlessFunctionView implements TreeDataProvider<ExplorerItem>, D
await ServerlessFunctionViewLoader.loadView('Serverless Function - Create');
}

@vsCommand('openshift.Serverless.manageRepository')
static async openManageRepository(): Promise<void> {
await ManageRepositoryViewLoader.loadView('Manage Repository');
}

@vsCommand('openshift.Serverless.refresh')
static refresh(target?: ExplorerItem) {
ServerlessFunctionView.getInstance().refresh(target);
Expand Down
2 changes: 1 addition & 1 deletion src/webview/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function validateName(value: string): string | null {
let validationMessage = OpenShiftItem.emptyName('Required', value.trim());
if (!validationMessage)
validationMessage = OpenShiftItem.validateMatches(
`Please use lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character`,
`Only lower case alphabets and numeric characters or '-', start and ends with only alphabets`,
value,
);
if (!validationMessage)
Expand Down
162 changes: 162 additions & 0 deletions src/webview/manage-repository/app/addRepository.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*-----------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See LICENSE file in the project root for license information.
*-----------------------------------------------------------------------------------------------*/

import * as React from 'react';
import { Button, Stack, TextField } from '@mui/material';
import { DefaultProps } from '../../common/propertyTypes';
import './home.scss';
import { VSCodeMessage } from './vsCodeMessage';

export class AddRepository extends React.Component<DefaultProps, {
input: {
name: string,
error: boolean,
helpText: string
},
repo: {
url: string,
error: boolean,
helpText: string
}
}> {

constructor(props: DefaultProps | Readonly<DefaultProps>) {
super(props);
this.state = {
input: {
name: '',
error: false,
helpText: ''
},
repo: {
url: '',
error: false,
helpText: ''
}
}
}

componentDidMount(): void {
VSCodeMessage.onMessage((message) => {
if (message.data.action === 'validateGitURL') {
this.setState({
repo: {
url: message.data.url,
error: message.data.error,
helpText: message.data.helpText
}
})
} else if (message.data.action === 'validateName') {
this.setState({
input: {
name: message.data.name,
error: message.data.error,
helpText: message.data.helpText
}
})
}
});
}

handleButtonDisable(): boolean {
return this.state.input.name?.length === 0 || this.state.input.error
|| this.state.repo.url?.length === 0 || this.state.repo.error
}

validateGitURL = (value: string): void => {
VSCodeMessage.postMessage({
action: `validateGitURL`,
url: value
})
}

validateName = (value: string): void => {
VSCodeMessage.postMessage({
action: `validateName`,
name: value
})
}

addRepo = (): void => {
VSCodeMessage.postMessage({
action: `addRepo`,
name: this.state.input.name,
url: this.state.repo.url
})
}


render(): React.ReactNode {
const { input, repo } = this.state;
return (
<>
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={1}>
<Button variant='contained'
disabled={true}
sx={{ width: { xs: 'auto', sm: '200px' } }}
className='labelStyle'>
Name *
</Button>
<TextField
type='string'
variant='outlined'
required
autoFocus
fullWidth
defaultValue={input.name}
error={input.error}
onChange={(e) => this.validateName(e.target.value)}
id='git-name'
placeholder='Provide name for the repository'
Comment thread
msivasubramaniaan marked this conversation as resolved.
Outdated
sx={{
input: {
color: 'var(--vscode-settings-textInputForeground)',
height: '7px !important',
}
}}
helperText={input.helpText} />
</Stack>
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={1}>
<Button variant='contained'
disabled={true}
sx={{ width: { xs: 'auto', sm: '200px' } }}
className='labelStyle'>
Url *
</Button>
<TextField
type='string'
variant='outlined'
required
autoFocus
fullWidth
defaultValue={repo.url}
error={repo.error}
onChange={(e) => this.validateGitURL(e.target.value)}
id='git-url'
placeholder='Provide git URL'
sx={{
input: {
color: 'var(--vscode-settings-textInputForeground)',
height: '7px !important',
}
}}
helperText={repo.helpText} />
</Stack>
<Stack direction='column'>
<Button variant='contained'
disabled={this.handleButtonDisable()}
className='buttonStyle'
style={{
backgroundColor: this.handleButtonDisable() ?
'var(--vscode-button-secondaryBackground)' : '#EE0000', textTransform: 'none', color: 'white'
}}
onClick={() => this.addRepo()}>
Add
</Button>
</Stack>
</>
)
}
}
Loading