Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement node config download btn #492

Merged
merged 3 commits into from
Oct 29, 2022
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
1 change: 1 addition & 0 deletions src/api-engine/api/routes/node/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ def block_file(self, request, pk=None):
for chunk in uploaded_block_file.chunks():
f.write(chunk)
join_peers(envs, block_path)
os.remove(block_path)
return Response(status=status.HTTP_202_ACCEPTED)
except Exception as e:
return Response(
Expand Down
1 change: 1 addition & 0 deletions src/dashboard/src/locales/en-US/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
export default {
'form.button.new': 'New',
'form.table.header.operation': 'Operation',
'form.menu.item.download': 'Download',
'form.menu.item.delete': 'Delete',
'form.input.placeholder': 'Please input',
'form.menu.item.update': 'Update',
Expand Down
1 change: 1 addition & 0 deletions src/dashboard/src/locales/en-US/operatorNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default {
'app.operator.node.delete.confirm':
'Deleting node {name} may cause abnormality in the blockchain network. Confirm delete?',
'app.operator.node.delete.success': 'Delete Node Successful.',
'app.operator.node.download.success': 'Download Node Config File Successful.',
'app.operator.node.operation.start.success': 'Start Node Successful.',
'app.operator.node.operation.stop.success': 'Stop Node Successful.',
'app.operator.node.operation.restart.success': 'Restart Node Successful.',
Expand Down
1 change: 1 addition & 0 deletions src/dashboard/src/locales/zh-CN/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
export default {
'form.button.new': '新建',
'form.table.header.operation': '操作',
'form.menu.item.download': '下载',
'form.menu.item.delete': '删除',
'form.input.placeholder': '请输入',
'form.menu.item.update': '更新',
Expand Down
1 change: 1 addition & 0 deletions src/dashboard/src/locales/zh-CN/operatorNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default {
'app.operator.node.delete.title': '删除节点',
'app.operator.node.delete.confirm': '删除节点 {name} 可能导致区块链网络异常,是否确认删除?',
'app.operator.node.delete.success': '删除节点成功。',
'app.operator.node.download.success': '下载节点配置文件成功。',
'app.operator.node.operation.start.success': '启动节点成功。',
'app.operator.node.operation.stop.success': '停止节点成功。',
'app.operator.node.operation.restart.success': '重启节点成功。',
Expand Down
7 changes: 7 additions & 0 deletions src/dashboard/src/models/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
deleteNode,
operateNode,
createNode,
downloadNodeConfig,
} from '@/services/node';

export default {
Expand Down Expand Up @@ -90,6 +91,12 @@ export default {
});
}
},
*downloadNodeConfig({ payload, callback }, { call }) {
const response = yield call(downloadNodeConfig, payload);
if (callback) {
callback(response);
}
},
},
reducers: {
save(state, { payload }) {
Expand Down
45 changes: 45 additions & 0 deletions src/dashboard/src/pages/Operator/Node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ import styles from '../styles.less';
const FormItem = Form.Item;
const { Option } = Select;

// function str2bytes (str) {
// var bytes = new Uint8Array(str.length);
// for (var i=0; i<str.length; i++) {
// bytes[i] = str.charCodeAt(i);
// }
// return bytes;
// }

const RegisterUserForm = props => {
const {
registerUserFormVisible,
Expand Down Expand Up @@ -502,6 +510,36 @@ class Index extends PureComponent {
});
};

handleDownloadConfig = row => {
const { dispatch } = this.props;
const params = {
id: row.id,
};
dispatch({
type: 'node/downloadNodeConfig',
payload: params,
callback: this.downloadCallBack,
});
};

downloadCallBack = response => {
const { intl } = this.props;
message.success(
intl.formatMessage({
id: 'app.operator.node.download.success',
defaultMessage: 'Download Node Config File Successful.',
})
);
const dispositionHeader = response.response.headers.get('Content-Disposition');
const blob = response.data;
const link = document.createElement('a');
link.href = URL.createObjectURL(new Blob([blob], { type: 'application/zip' }));
link.download = dispositionHeader.split('filename=')[1];
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
};

render() {
const { selectedRows, registerUserFormVisible, targetNodeId, createModalVisible } = this.state;

Expand Down Expand Up @@ -567,6 +605,13 @@ class Index extends PureComponent {
</a>
</Menu.Item>
)}
{(record.type === 'peer' || record.type === 'orderer') && (
<Menu.Item>
<a onClick={() => this.handleDownloadConfig(record)}>
{intl.formatMessage({ id: 'form.menu.item.download', defaultMessage: 'Download' })}
</a>
</Menu.Item>
)}
<Menu.Item>
<a onClick={() => this.handleDeleteNode(record)}>
{intl.formatMessage({ id: 'form.menu.item.delete', defaultMessage: 'Delete' })}
Expand Down
8 changes: 8 additions & 0 deletions src/dashboard/src/services/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,11 @@ export async function operateNode(params) {
data: { action: params.message },
});
}

export async function downloadNodeConfig(params) {
return request(`/api/v1/nodes/${params.id}/config`, {
method: 'GET',
responseType: 'blob',
getResponse: true,
});
}