js-base64#decode TypeScript Examples
The following examples show how to use
js-base64#decode.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: service-generator.ts From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
getSwaggerData = (url: string) => {
return http
.get(url)
.set('content-type', 'application-json')
.set('User-Agent', '')
.then((response) => {
logInfo('get swagger data successfully!');
const content = decode(response?.body?.content);
return content ? JSON.parse(content) : '';
})
.catch((err) => {
logError('fail to get swagger data: ', err);
return false;
});
}
Example #2
Source File: xterm-binary.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
function proxyOutput(term: ITerminal, socket: WebSocket) {
const { __getMessage } = term;
socket.removeEventListener('message', __getMessage);
const timeZoneReg = /^\d[\d-]+T[\d:.]+Z/;
term.__getMessage = (ev) => {
let { data } = ev;
data = data && decode(data);
const timeRegResult = timeZoneReg.exec(data);
if (timeRegResult) {
data = `${moment(timeRegResult[0]).format('YYYY-MM-DD HH:mm:ss')} ${data.split(timeRegResult[0])?.[1]}`;
}
__getMessage({ data: `\r${data}\n` });
};
socket.addEventListener('message', term.__getMessage);
}
Example #3
Source File: xterm-channel.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
function proxyOutput(term: ITerminal, socket: WebSocket) {
const { __getMessage } = term;
socket.removeEventListener('message', __getMessage);
term.__getMessage = (ev) => {
let { data } = ev;
const type = data.substr(0, 1);
data = data.substr(1);
data && (data = decode(data));
switch (type) {
case Ping:
sendData(term, Pong);
break;
case Pong:
break;
case Output:
case Error:
case ServiceError:
__getMessage({ data });
break;
default:
break;
}
};
socket.addEventListener('message', term.__getMessage);
}
Example #4
Source File: list.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
parseDetailSearch = (v: string) => {
if (v) {
try {
const res = JSON.parse(decode(v));
return res;
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
return null;
}
}
return null;
}
Example #5
Source File: judge0.ts From netless-app with MIT License | 6 votes |
public async runCode(source: string, lang: string): Promise<string> {
if (!this.hasLanguage(lang)) {
return "Language not supported!\n";
}
try {
const response = await fetch(
"https://judge0-ce.p.rapidapi.com/submissions?base64_encoded=true&wait=true&fields=*",
{
method: "POST",
headers: {
"content-type": "application/json",
"x-rapidapi-host": "judge0-ce.p.rapidapi.com",
"x-rapidapi-key": this.apiKey,
},
body: JSON.stringify({
language_id: Judge0.lanMap[lang],
source_code: encode(source),
}),
}
);
const data = await response.json();
if (data.stderr) {
return decode(data.stderr);
} else if (data.stdout) {
return decode(data.stdout);
}
return "Unknown error\n";
} catch (err) {
return `${err instanceof Error ? err.message : String(err)}\n`;
}
}
Example #6
Source File: register-command.tsx From logseq-plugin-todo-master with MIT License | 5 votes |
export function registerCommand() {
logseq.provideStyle(style);
logseq.App.onMacroRendererSlotted(async ({ payload, slot }) => {
const [type] = payload.arguments;
if (!type?.startsWith(macroPrefix)) {
return;
}
logseq.provideStyle({
key: slot,
style: `#${slot} {display: inline-flex;}`,
});
let maybeUUID = null;
// Implicitly use the current block
if (type === macroPrefix) {
maybeUUID = payload.uuid;
} else {
maybeUUID = decode(type.substring(macroPrefix.length + 1));
}
if (maybeUUID) {
startRendering(maybeUUID, slot);
}
});
async function insertMacro(mode: "page" | "block" = "block") {
const block = await logseq.Editor.getCurrentBlock();
if (block && block.uuid) {
let content = "";
let maybeUUID = "";
if (mode === "block") {
// We will from now on always use implicit block IDs to get rid of "Tracking target not found" issue
// maybeUUID = block.uuid;
} else {
const page = await logseq.Editor.getPage(block.page.id);
if (page?.originalName) {
maybeUUID = page.originalName;
}
}
if (maybeUUID) {
// Use base64 to avoid incorrectly rendering in properties
content = `{{renderer ${macroPrefix}-${encode(maybeUUID)}}}`;
} else {
content = `{{renderer ${macroPrefix}}}`;
}
await logseq.Editor.insertAtEditingCursor(content);
}
}
logseq.Editor.registerSlashCommand(
"[TODO Master] Add Progress Bar",
async () => {
return insertMacro();
}
);
}
Example #7
Source File: export-factory.ts From vscode-code-review with MIT License | 4 votes |
private exportHandlerMap = new Map<ExportFormat, ExportMap>([
[
'html',
{
fileExtension: 'html',
storeOutside: true,
writeFileHeader: (_outputFile: string) => {
return;
},
handleData: (_outputFile: string, row: CsvEntry): CsvEntry => {
row.code = this.includeCodeSelection ? this.getCodeForFile(row.filename, row.lines) : '';
return row;
},
handleEnd: (outputFile: string, rows: CsvEntry[], template: Uri) => {
// check template
let templateData;
try {
templateData = fs.readFileSync(template.fsPath, 'utf8');
} catch (error: any) {
window.showErrorMessage(`Error when reading the template file: '${template.fsPath}'`);
throw error;
}
// check if grouping should be applied
let reviewExportData: ReviewFileExportSection[] = [];
reviewExportData = this.groupResults(rows, this.groupBy);
if (this.groupBy === Group.filename) {
reviewExportData.forEach((group) => {
group.lines.sort(sortCsvEntryForLines);
});
}
// Helper that decodes the Base64 content to be displayed in the handlebar
handlebars.registerHelper('codeBlock', (code: string) => decode(code));
// compile template after helper is registered
const templateCompiled = handlebars.compile(templateData);
// inject date into the template
const htmlOut = templateCompiled(reviewExportData);
fs.writeFileSync(outputFile, htmlOut);
window.showInformationMessage(`Code review file: '${outputFile}' successfully created.`);
this.showPreview(outputFile);
},
},
],
[
'markdown',
{
fileExtension: 'md',
storeOutside: true,
writeFileHeader: (_outputFile: string) => {
return;
},
handleData: (_outputFile: string, row: CsvEntry): CsvEntry => {
row.code = this.includeCodeSelection ? this.getCodeForFile(row.filename, row.lines) : '';
return row;
},
handleEnd: (outputFile: string, rows: CsvEntry[], template: Uri) => {
// check template
let templateData;
try {
templateData = fs.readFileSync(template.fsPath, 'utf8');
} catch (error: any) {
window.showErrorMessage(`Error when reading the template file: '${template.fsPath}'`);
throw error;
}
// check if grouping should be applied
let reviewExportData: ReviewFileExportSection[] = [];
reviewExportData = this.groupResults(rows, this.groupBy);
if (this.groupBy === Group.filename) {
reviewExportData.forEach((group) => {
group.lines.sort(sortCsvEntryForLines);
});
}
// Helper that decodes the Base64 content to be displayed in the handlebar
handlebars.registerHelper('codeBlock', (code: string) => decode(code));
// compile template after helper is registered
const templateCompiled = handlebars.compile(templateData);
// inject data into the template
const markdownOut = templateCompiled(reviewExportData);
fs.writeFileSync(outputFile, markdownOut);
window.showInformationMessage(`Code review file: '${outputFile}' successfully created.`);
this.openFile(outputFile);
},
},
],
[
'gitlab',
{
fileExtension: 'gitlab.csv',
storeOutside: false,
writeFileHeader: (outputFile: string) => {
fs.writeFileSync(outputFile, `title,description${EOL}`);
},
handleData: (outputFile: string, row: CsvEntry): CsvEntry => {
row.comment = escapeEndOfLineForCsv(row.comment);
this.includeCodeSelection ? (row.code = this.getCodeForFile(row.filename, row.lines)) : delete row.code;
// cut the description (100 chars max) along with '...' at the end
const descShort = row.comment.length > 100 ? `${row.comment.substring(0, 100)}...` : row.comment;
// use the title when provided but max 255 characters (as GitLab supports this length for titles), otherwise use the shortened description
const title = row.title ? row.title.substring(0, 255) : descShort;
const fileRow = row.url ? `- file: [${row.filename}](${row.url})${EOL}` : `${row.filename}${EOL}`;
const linesRow = `- lines: ${row.lines}${EOL}`;
const shaRow = row.sha ? `- SHA: ${row.sha}${EOL}${EOL}` : '';
const commentSection = `## Comment${EOL}${row.comment}${EOL}`;
const additional = row.additional ? `## Additional information${EOL}${row.additional}${EOL}` : '';
const priority = row.priority ? `## Priority${EOL}${this.priorityName(row.priority)}${EOL}${EOL}` : '';
const category = row.category ? `## Category${EOL}${row.category}${EOL}${EOL}` : '';
const code = row.code ? `${EOL}## Source Code${EOL}${EOL}\`\`\`${EOL}${row.code}\`\`\`${EOL}` : '';
const description = `${priority}${category}## Affected${EOL}${fileRow}${linesRow}${shaRow}${commentSection}${EOL}${additional}${code}`;
fs.appendFileSync(outputFile, `"[code review] ${title}","${description}"${EOL}`);
return row;
},
handleEnd: (outputFile: string, _rows: CsvEntry[]) => {
window.showInformationMessage(`GitLab importable CSV file: '${outputFile}' successfully created.`);
},
},
],
[
'github',
{
fileExtension: 'github.csv',
storeOutside: false,
writeFileHeader: (outputFile: string) => {
fs.writeFileSync(outputFile, `title,description,labels,state,assignee${EOL}`);
},
handleData: (outputFile: string, row: CsvEntry): CsvEntry => {
row.comment = escapeEndOfLineForCsv(row.comment);
this.includeCodeSelection ? (row.code = this.getCodeForFile(row.filename, row.lines)) : delete row.code;
// cut the description (100 chars max) along with '...' at the end
const descShort = row.comment.length > 100 ? `${row.comment.substring(0, 100)}...` : row.comment;
// use the title when provided but max 255 characters (as GitLab supports this length for titles), otherwise use the shortened description
const title = row.title ? row.title.substring(0, 255) : descShort;
const fileRow = row.url ? `- file: [${row.filename}](${row.url})${EOL}` : `${row.filename}${EOL}`;
const linesRow = `- lines: ${row.lines}${EOL}`;
const shaRow = row.sha ? `- SHA: ${row.sha}${EOL}${EOL}` : '';
const commentSection = `## Comment${EOL}${row.comment}${EOL}`;
const additional = row.additional ? `## Additional information${EOL}${row.additional}${EOL}` : '';
const priority = row.priority ? `## Priority${EOL}${this.priorityName(row.priority)}${EOL}${EOL}` : '';
const category = row.category ? `## Category${EOL}${row.category}${EOL}${EOL}` : '';
const code = row.code ? `${EOL}## Source Code${EOL}${EOL}\`\`\`${EOL}${row.code}\`\`\`${EOL}` : '';
const description = `${priority}${category}## Affected${EOL}${fileRow}${linesRow}${shaRow}${commentSection}${EOL}${additional}${code}`;
fs.appendFileSync(outputFile, `"[code review] ${title}","${description}","code-review","open",""${EOL}`);
return row;
},
handleEnd: (outputFile: string, _rows: CsvEntry[]) => {
window.showInformationMessage(`GitHub importable CSV file: '${outputFile}' successfully created.`);
},
},
],
[
'jira',
{
fileExtension: 'jira.csv',
storeOutside: false,
writeFileHeader: (outputFile: string) => {
fs.writeFileSync(
outputFile,
`Summary,Description,Priority,sha,filename,url,lines,title,category,comment,additional${EOL}`,
);
},
handleData: (outputFile: string, row: CsvEntry): CsvEntry => {
row.comment = escapeEndOfLineForCsv(row.comment);
this.includeCodeSelection ? (row.code = this.getCodeForFile(row.filename, row.lines)) : delete row.code;
// cut the description (100 chars max) along with '...' at the end
const descShort = row.comment?.length > 100 ? `${row.comment.substring(0, 100)}...` : row.comment;
// use the title when provided but max 255 characters (as GitLab supports this length for titles), otherwise use the shortened description
const title = row.title ? row.title.substring(0, 255) : descShort;
const fileRow = row.url ? `* file: [${row.filename}|${row.url}]${EOL}` : `${row.filename}${EOL}`;
const linesRow = `* lines: ${row.lines}${EOL}`;
const shaRow = row.sha ? `* SHA: ${row.sha}${EOL}${EOL}` : '';
const categorySection = `h2. Category${EOL}${row.category}${EOL}${EOL}`;
const commentSection = `h2. Comment${EOL}${row.comment}${EOL}`;
const additional = row.additional ? `h2. Additional information${EOL}${row.additional}${EOL}` : '';
const code = row.code ? `${EOL}h2. Source Code${EOL}${EOL}{code}${EOL}${row.code}{code}${EOL}` : '';
const description = `h2. Affected${EOL}${fileRow}${linesRow}${shaRow}${categorySection}${commentSection}${EOL}${additional}${code}`;
fs.appendFileSync(
outputFile,
`"[code review] ${title}","${description}","${this.priorityName(row.priority)}","${row.sha}","${
row.filename
}","${row.url}","${row.lines}","${row.title}","${row.category}","${row.comment}","${row.additional}"${EOL}`,
);
return row;
},
handleEnd: (outputFile: string, _rows: CsvEntry[]) => {
window.showInformationMessage(`JIRA importable file: '${outputFile}' successfully created.`);
},
},
],
[
'json',
{
fileExtension: 'json',
storeOutside: true,
writeFileHeader: (_outputFile: string) => {
return;
},
handleData: (_outputFile: string, row: CsvEntry): CsvEntry => {
this.includeCodeSelection ? (row.code = this.getCodeForFile(row.filename, row.lines)) : delete row.code;
return row;
},
handleEnd: (outputFile: string, rows: CsvEntry[]) => {
fs.writeFileSync(outputFile, JSON.stringify(rows, null, 2));
window.showInformationMessage(`GitHub importable CSV file: '${outputFile}' successfully created.`);
},
},
],
]);
Example #8
Source File: form.tsx From erda-ui with GNU Affero General Public License v3.0 | 4 votes |
PipelineForm = ({ onCancel, pipelineCategory, onOk, data: editData, fixedApp }: IProps) => {
const { key: pipelineCategoryKey, rules: pipelineCategoryRules } = pipelineCategory || {};
const [{ projectId }] = routeInfoStore.useStore((s) => [s.params]);
const [form] = Form.useForm();
const [appList, setAppList] = React.useState<App[]>([]);
const [app, setApp] = React.useState<App>({} as App);
const [tree, setTree] = React.useState<TreeNode[]>([]);
const [treeVisible, setTreeVisible] = React.useState(false);
const [treeValue, setTreeValue] = React.useState('');
const [treeExpandedKeys, setTreeExpandedKeys] = React.useState<Array<string | number>>([]);
const canTreeSelectClose = React.useRef(true);
const [sourceErrorMessage, setSourceErrorMessage] = React.useState('');
const appDetail = appStore.useStore((s) => s.detail);
const type = editData ? 'edit' : 'add';
const convertTreeData = (data: Node[]) => {
return data.map((item) => ({
...item,
key: item.inode,
id: item.inode,
pId: item.pinode,
title: item.name,
isLeaf: item.type === 'f',
value: item.inode,
}));
};
const getTree = React.useCallback(
async (pinode: string) => {
const res = await getFileTree.fetch({
scopeID: projectId,
scope: 'project-app',
pinode,
pipelineCategoryKey: !pipelineCategoryKey || pipelineCategoryKey === 'all' ? '' : pipelineCategoryKey,
});
if (res.success) {
return convertTreeData(res.data || []);
} else {
return [];
}
},
[projectId, pipelineCategoryKey],
);
const loadTree = async (node: TreeNode) => {
const data = await getTree(node.id);
setTree((prev) => [...prev, ...data]);
return Promise.resolve();
};
const getApps = React.useCallback(async () => {
if (!fixedApp) {
const res = await getAppList.fetch({ projectID: projectId });
if (res.success) {
setAppList(
res.data?.map((item) => ({ value: item.ID, label: item.displayName, projectName: item.projectName })) || [],
);
}
}
}, [projectId, fixedApp]);
React.useEffect(() => {
getApps();
}, [getApps]);
React.useEffect(() => {
const initialTree = async () => {
const data = await getTree(btoa(encodeURI(`${projectId}/${app.value || fixedApp}`)));
setTree(data);
};
if (app.value || fixedApp) {
initialTree();
setSourceErrorMessage('');
if (tree.length !== 0) {
setTreeValue('');
form.resetFields(['tree']);
}
}
}, [app.value, projectId, getTree, form, fixedApp]);
React.useEffect(() => {
if (fixedApp) {
form.setFieldsValue?.({ app: fixedApp });
setApp({ value: fixedApp });
}
}, [form, fixedApp]);
useEffectOnce(() => {
if (editData) {
const { name, app, fileName, inode } = editData;
form.setFieldsValue({ name, app, tree: inode });
setApp({ value: app });
setTreeValue(fileName);
}
});
const submit = () => {
form.validateFields().then(async (value) => {
const path = decode(value.tree).split('/');
const fileName = path[path.length - 1];
path.length--;
const appId = path[1];
const branch = path.join('/').split('tree/')[1].split('/.dice')[0].split('/.erda')[0];
const ymlPath = (path.join('/').split(branch)[1] || '').substr(1);
const params = {
edit: {
projectID: +projectId,
name: value.name,
id: editData?.id,
projectPipelineSource: {
sourceType: 'erda',
appID: appId,
ref: branch,
path: ymlPath,
fileName,
},
},
add: {
projectID: +projectId,
name: value.name,
sourceType: 'erda',
appID: appId,
ref: branch,
path: ymlPath,
fileName,
},
};
const res = await interfaceMap[type].fetch({ ...params[type], $options: { successMsg: successMsgMap[type] } });
if (res.success) {
onOk();
}
});
};
const sourceCheck = async (value: string) => {
if (value === editData?.inode) {
return Promise.resolve();
}
const node = tree.find((item) => item.id === value);
if (node?.isLeaf) {
const path = decode(node.pId);
const _appID = path.split('/')[1];
const ref = path.split('tree/')[1].split('/.dice')[0].split('/.erda')[0];
const payload = {
appID: _appID,
ref,
fileName: node.name,
sourceType: 'erda',
};
const res = await checkSource.fetch(payload);
const { data } = res;
if (data?.pass) {
setSourceErrorMessage('');
} else {
data?.message && setSourceErrorMessage(data.message);
}
}
return Promise.resolve();
};
return (
<div className="project-pipeline-form flex flex-col h-full">
<div className="header py-2.5 pl-4 bg-default-02 flex-h-center">
<span className="text-base text-default">{titleMap[type]}</span>
<ErdaIcon type="zhedie" className="ml-1" />
<div className="flex-h-center cursor-pointer mx-2 px-2 py-1 flex-1 justify-end">
<ErdaIcon type="guanbi" size="20" onClick={() => onCancel()} />
</div>
</div>
<div className="flex-1 min-h-0 pl-4 pt-4 w-1/2">
<Form form={form}>
<RenderFormItem
name={'name'}
type={'input'}
rules={[
{
required: true,
message: i18n.t('Please enter the {name}', { name: i18n.t('Pipeline').toLowerCase() }),
},
{ max: 30, message: i18n.t('dop:no more than 30 characters') },
{
pattern: /^[\u4e00-\u9fa5A-Za-z0-9._-]+$/,
message: i18n.t('dop:Must be composed of Chinese, letters, numbers, underscores, hyphens and dots.'),
},
]}
itemProps={{
className: 'border-transparent shadow-none pl-0 text-xl bg-transparent',
placeholder: i18n.t('Please enter the {name}', { name: i18n.t('Pipeline').toLowerCase() }),
}}
/>
<div>
<div className="text-default">{i18n.t('dop:Code source')}</div>
<CodeResource />
</div>
<div>
<div className="text-default mb-3">{i18n.t('Configuration')}</div>
<div className="flex-h-center">
<div className="mb-3 w-32 text-default-6 flex-h-center">
<ErdaIcon type="yingyongmingcheng" size={20} className="text-default-4 mr-1" />
{i18n.t('App')}
</div>
<div className="flex-1 pr-6 mb-3">
{fixedApp ? (
appDetail?.displayName || appDetail?.name
) : (
<RenderFormItem
name="app"
type="select"
options={appList}
rules={[{ required: true, message: i18n.t('please choose the {name}', { name: i18n.t('App') }) }]}
itemProps={{
disabled: type === 'edit',
className: 'project-release-select',
onChange: (_: string, _app: App) => setApp(_app),
}}
/>
)}
</div>
</div>
<div className="flex">
<div className="w-32 text-default-6">
<div className="flex-h-center mt-1.5">
<ErdaIcon type="pipeline" size={20} className="text-default-4 mr-1" />
{i18n.t('dop:Pipeline file')}
</div>
</div>
<div className="flex-1">
<RenderFormItem
name="tree"
type="custom"
rules={[
{
validator: (_: string, value: string) => {
if (!value) {
return Promise.reject(
new Error(i18n.t('please choose the {name}', { name: i18n.t('Pipelines').toLowerCase() })),
);
}
return sourceCheck(value);
},
},
]}
getComp={() => (
<div className="flex">
<TreeSelect
className="project-release-select"
treeDataSimpleMode
treeData={tree}
open={treeVisible}
onDropdownVisibleChange={(_visible) => {
if (canTreeSelectClose.current) {
setTreeVisible(_visible);
} else {
canTreeSelectClose.current = true;
}
}}
value={treeValue}
onSelect={(value, node) => {
if (node.isLeaf === false) {
canTreeSelectClose.current = false;
if (treeExpandedKeys.includes(value)) {
setTreeExpandedKeys((pre) => pre.filter((item) => item !== value));
} else {
setTreeExpandedKeys((pre) => [...pre, value]);
}
} else {
setTreeValue(value);
form.setFieldsValue({ tree: value });
}
}}
treeExpandedKeys={treeExpandedKeys}
onTreeExpand={(expandedKeys: Array<string | number>) => {
setTreeExpandedKeys(expandedKeys);
}}
loadData={loadTree}
/>
{pipelineCategoryRules ? (
<Tooltip title={pipelineCategoryRules?.join(', ')}>
<ErdaIcon type="help" className="text-default-6 ml-2" size="16" />
</Tooltip>
) : (
<div className="w-6" />
)}
</div>
)}
/>
</div>
</div>
{sourceErrorMessage ? (
<ErdaAlert message={sourceErrorMessage} type="error" closeable={false} className="py-1.5" />
) : null}
</div>
</Form>
</div>
<div className="py-3 px-4">
<Button type="primary" className="mr-2" onClick={submit}>
{btnMap[type]}
</Button>
<Button className="bg-default-06 border-default-06 text-default-8" onClick={() => onCancel()}>
{i18n.t('Cancel')}
</Button>
</div>
</div>
);
}
Example #9
Source File: list.tsx From erda-ui with GNU Affero General Public License v3.0 | 4 votes |
PipelineProtocol = React.forwardRef(
(
{ pipelineCategory, updateCategory, onAddPipeline, projectId, appId }: IProps,
ref: React.Ref<{ reload: () => void }>,
) => {
const { name: projectName } = projectStore.useStore((s) => s.info);
const inParams = {
projectId,
appId,
pipelineCategoryKey: pipelineCategory === 'all' ? undefined : pipelineCategory,
};
const detailId = routeInfoStore.useStore((s) => s.query.detailId);
const initDetail = parseDetailSearch(detailId);
const [detailVisible, setDetailVisible] = React.useState(!!initDetail);
const [newPipelineUsed, setNewPipelineUsed] = React.useState(false);
const [detail, setDetail] = React.useState<Detail | null>(initDetail);
const [executeRecordId, setExecuteRecordId] = React.useState('');
const reloadRef = React.useRef<{ reload: () => void }>(null);
const executeRef = React.useRef<{
execute: (_ymlStr: string, extra: { pipelineID?: string; pipelineDetail?: BUILD.IPipelineDetail }) => void;
}>(null);
React.useEffect(() => {
reloadRef.current?.reload();
}, [pipelineCategory]);
React.useImperativeHandle(ref, () => ({
reload: () => {
reloadRef.current?.reload();
},
}));
const runBuild = (_v?: { runParams: Obj<string | number> }) => {
runPipeline({ pipelineDefinitionID: executeRecordId, projectID: +projectId, ..._v }).then(() => {
reloadRef.current?.reload();
});
};
const onDetailClose = React.useCallback(() => {
updateSearch({
detailId: undefined,
});
setDetailVisible(false);
setDetail(null);
if (newPipelineUsed) {
reloadRef.current?.reload();
setNewPipelineUsed(false);
}
}, [newPipelineUsed]);
const shareLink = `${location.href.split('?')[0]}?${mergeSearch({ detailId: getDetailId(detail) }, true)}`;
return (
<>
<DiceConfigPage
scenarioKey="project-pipeline"
scenarioType="project-pipeline"
showLoading
inParams={inParams}
ref={reloadRef}
operationCallBack={(reqConfig) => {
const { event } = reqConfig;
const { component, operationData } = event || {};
if (component === 'pipelineTable') {
const id = get(operationData, 'clientData.dataRef.id');
if (['run', 'cancelRun', 'batchRun'].includes(id)) {
updateCategory?.();
}
}
}}
customProps={{
myPage: {
props: {
fullHeight: true,
},
},
pageHeader: {
props: {
className: 'mx-2',
isTopHead: true,
},
},
pipelineTable: {
op: {
clickRow: async (record: {
id: string;
operations: { click: { serverData: { pipelineID: string; inode: string; appName: string } } };
}) => {
setDetailVisible(true);
const { operations, id } = record;
const serverData = get(operations, 'click.serverData');
const { pipelineID: pipelineId, inode, appName, pipelineName } = serverData;
if (inode) {
const path = decode(inode).split('/');
path.pop();
const _appId = path[1];
const branchName = path.join('/').split('tree/')[1].split('/.dice')[0].split('/.erda')[0]; // such as '1/12/tree/feature/0.17.x-treeOrder/.dice', take the 'feature/0.17.x-treeOrder' of it
const res = await getAllBranch.fetch({ appID: +_appId });
let branchExist = false;
if (res.data) {
const branch = res.data.find((item: { name: string }) => item.name === branchName);
branch && (branchExist = true);
}
// url search 'applicationId' use for action-config-form some action with member-selector
updateSearch({ applicationId: appId });
setDetail({
nodeId: inode,
appId: _appId,
pipelineId,
pipelineDefinitionID: id,
branchExist,
pipelineName,
projectId,
projectName,
appName,
});
}
},
operations: {
run: async (
op: {
operations: { click: { serverData: { inode: string; pipelineID: string } } };
},
record: { id: string },
) => {
setExecuteRecordId(record.id);
const { inode, pipelineID } = op.operations?.click?.serverData || {};
if (inode) {
const path = decode(inode).split('/');
path.pop();
const _appId = path[1];
const res = await getTreeNodeDetailNew({ id: inode, scopeID: _appId, scope: 'project-app' });
const ymlStr = res?.data?.meta?.pipelineYml;
executeRef?.current?.execute(ymlStr, { pipelineID });
}
},
update: (
op: Obj,
record: {
id: string;
pipeline: {
data: { pipelineName: { data: { text: string } }; sourceFile: { data: { text: string } } };
};
},
) => {
const { appID, inode } = op.operations.click.serverData;
const { id, pipeline } = record;
const { data } = pipeline;
const { pipelineName, sourceFile } = data;
onAddPipeline({
id,
name: pipelineName.data.text,
fileName: sourceFile.data.text,
app: appID,
inode,
});
},
},
},
props: {
tableProps: {
whiteHead: true,
whiteFooter: true,
styleNames: 'h-full',
wrapperClassName: 'flex-1',
tableKey: 'project-pipeline',
},
columnsRender: {
source: (_val: string, _record: string, map: { [key: string]: React.ReactNode }) => {
return (
<div>
<div className="leading-5 text-default-9">{map.applicationName}</div>
<div className="flex-h-center">
<div className="mr-1 flex-h-center text-default-4">{map.icon}</div>
<div className="text-default-6">{map.branch}</div>
</div>
</div>
);
},
pipeline: (_val: string, _record: string, map: { [key: string]: React.ReactNode }) => {
return (
<div>
<div className="leading-5 text-default-9">{map.pipelineName}</div>
<div className="text-default-6">{map.sourceFile}</div>
</div>
);
},
},
},
},
addPipelineBtn: {
op: {
click: () => {
onAddPipeline();
},
},
},
}}
/>
<Drawer
title={
<div className="flex justify-between items-center">
<span>
{i18n.t('Pipeline')} {detail?.pipelineName || ''}
</span>
<div>
<Copy selector=".copy-share-link" tipName={i18n.t('dop:link-share')} />
<ErdaIcon
type="lianjie"
className="cursor-copy hover-active copy-share-link ml-4 text-default-6"
size="20"
data-clipboard-text={shareLink}
/>
<ErdaIcon
type="guanbi"
className="ml-4 hover-active text-default-6"
size="20"
onClick={onDetailClose}
/>
</div>
</div>
}
onClose={onDetailClose}
visible={detailVisible}
closable={false}
width="80%"
destroyOnClose
>
{detail ? <PipelineDetail {...detail} setNewPipelineUsed={setNewPipelineUsed} /> : null}
</Drawer>
<InParamsForm ref={executeRef} onExecute={runBuild} />
</>
);
},
)