Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (*modifyFileMetaTable) Up(basicRes context.BasicRes) errors.Error {
return errors.Default.Wrap(err, "failed to load column metadata for _tool_q_dev_s3_file_meta.processed_time")
}
if len(cols) == 0 {
// If column is not visible in metadata, treat as no processing needed
// If column is not visible in metadata, treat as no processing needed
return nil
}
if nullable, ok := cols[0].Nullable(); ok {
Expand Down
2 changes: 2 additions & 0 deletions config-ui/src/plugins/register/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { TAPDConfig } from './tapd';
import { WebhookConfig } from './webhook';
import { ZenTaoConfig } from './zentao';
import { OpsgenieConfig } from './opsgenie';
import { QDevConfig } from './q-dev';
import { TeambitionConfig } from './teambition';
import { TestmoConfig } from './testmo';
import { SlackConfig } from './slack/config';
Expand All @@ -50,6 +51,7 @@ export const pluginConfigs: IPluginConfig[] = [
JiraConfig,
PagerDutyConfig,
SlackConfig,
QDevConfig,
SonarQubeConfig,
TAPDConfig,
TestmoConfig,
Expand Down
62 changes: 62 additions & 0 deletions config-ui/src/plugins/register/q-dev/assets/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 82 additions & 0 deletions config-ui/src/plugins/register/q-dev/config.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import { IPluginConfig } from '@/types';

import Icon from './assets/icon.svg?react';

export const QDevConfig: IPluginConfig = {
plugin: 'q_dev',
name: 'Q Developer',
icon: ({ color }) => <Icon fill={color} />,
sort: 20,
connection: {
docLink: '', // TODO: 添加文档链接
initialValues: {
accessKeyId: '',
secretAccessKey: '',
region: 'us-east-1',
bucket: '',
identityStoreId: '',
identityStoreRegion: 'us-east-1',
rateLimitPerHour: 20000,
},
fields: [
'name',
{
key: 'accessKeyId',
label: 'AWS Access Key ID',
subLabel: '请输入您的AWS Access Key ID',
},
{
key: 'secretAccessKey',
label: 'AWS Secret Access Key',
subLabel: '请输入您的AWS Secret Access Key',
},
{
key: 'region',
label: 'AWS区域',
subLabel: '请输入AWS区域,例如:us-east-1',
},
{
key: 'bucket',
label: 'S3存储桶名称',
subLabel: '请输入存储Q Developer数据的S3存储桶名称',
},
{
key: 'identityStoreId',
label: 'IAM Identity Store ID',
subLabel: '请输入Identity Store ID,格式:d-xxxxxxxxxx',
},
{
key: 'identityStoreRegion',
label: 'IAM Identity Center区域',
subLabel: '请输入IAM Identity Center所在的AWS区域',
},
'proxy',
{
key: 'rateLimitPerHour',
subLabel: '设置每小时的API请求限制,用于控制数据收集速度',
defaultValue: 20000,
},
],
},
dataScope: {
title: 'Data Sources',
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import { ChangeEvent, useEffect } from 'react';

Check warning on line 19 in config-ui/src/plugins/register/q-dev/connection-fields/aws-credentials.tsx

View workflow job for this annotation

GitHub Actions / lint

'useEffect' is defined but never used
import { Input } from 'antd';

import { Block } from '@/components';

interface Props {
accessKeyId: string;
secretAccessKey: string;
region: string;
errors: {
accessKeyId?: string;
secretAccessKey?: string;
region?: string;
};
setValues: (values: any) => void;
setErrors: (errors: any) => void;
}

export const AwsCredentials = ({
accessKeyId,
secretAccessKey,
region,
errors,
setValues,
setErrors
}: Props) => {

const validateAccessKeyId = (value: string) => {
if (!value) {
return 'AWS Access Key ID是必填项';
}
if (!/^[A-Z0-9]{20}$/.test(value)) {
return 'AWS Access Key ID格式不正确';
}
return '';
};

const validateSecretAccessKey = (value: string) => {
if (!value) {
return 'AWS Secret Access Key是必填项';
}
if (value.length < 40) {
return 'AWS Secret Access Key长度不足';
}
return '';
};

const validateRegion = (value: string) => {
if (!value) {
return 'AWS区域是必填项';
}
if (!/^[a-z0-9-]+$/.test(value)) {
return 'AWS区域格式不正确';
}
return '';
};

const handleAccessKeyIdChange = (e: ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setValues({ accessKeyId: value });
setErrors({ accessKeyId: validateAccessKeyId(value) });
};

const handleSecretAccessKeyChange = (e: ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setValues({ secretAccessKey: value });
setErrors({ secretAccessKey: validateSecretAccessKey(value) });
};

const handleRegionChange = (e: ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setValues({ region: value });
setErrors({ region: validateRegion(value) });
};

return (
<>
<Block title="AWS Access Key ID" description="请输入您的AWS Access Key ID" required>
<Input
style={{ width: 386 }}
placeholder="AKIAIOSFODNN7EXAMPLE"
value={accessKeyId}
onChange={handleAccessKeyIdChange}
status={errors.accessKeyId ? 'error' : ''}
/>
{errors.accessKeyId && <div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>{errors.accessKeyId}</div>}
</Block>

<Block title="AWS Secret Access Key" description="请输入您的AWS Secret Access Key" required>
<Input.Password
style={{ width: 386 }}
placeholder="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
value={secretAccessKey}
onChange={handleSecretAccessKeyChange}
status={errors.secretAccessKey ? 'error' : ''}
/>
{errors.secretAccessKey && <div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>{errors.secretAccessKey}</div>}
</Block>

<Block title="AWS区域" description="请输入AWS区域,例如:us-east-1" required>
<Input
style={{ width: 386 }}
placeholder="us-east-1"
value={region}
onChange={handleRegionChange}
status={errors.region ? 'error' : ''}
/>
{errors.region && <div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>{errors.region}</div>}
</Block>
</>
);
};
Loading
Loading