mirror of https://github.com/openspug/spug
fix issue #270
parent
2cbd91b555
commit
c78c24b859
|
@ -10,6 +10,7 @@ class Environment(models.Model, ModelMixin):
|
||||||
name = models.CharField(max_length=50)
|
name = models.CharField(max_length=50)
|
||||||
key = models.CharField(max_length=50)
|
key = models.CharField(max_length=50)
|
||||||
desc = models.CharField(max_length=255, null=True)
|
desc = models.CharField(max_length=255, null=True)
|
||||||
|
sort_id = models.IntegerField(default=0, db_index=True)
|
||||||
created_at = models.CharField(max_length=20, default=human_datetime)
|
created_at = models.CharField(max_length=20, default=human_datetime)
|
||||||
created_by = models.ForeignKey(User, on_delete=models.PROTECT)
|
created_by = models.ForeignKey(User, on_delete=models.PROTECT)
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ class Environment(models.Model, ModelMixin):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'environments'
|
db_table = 'environments'
|
||||||
ordering = ('-id',)
|
ordering = ('-sort_id',)
|
||||||
|
|
||||||
|
|
||||||
class Service(models.Model, ModelMixin):
|
class Service(models.Model, ModelMixin):
|
||||||
|
|
|
@ -33,10 +33,32 @@ class EnvironmentView(View):
|
||||||
Environment.objects.filter(pk=form.id).update(**form)
|
Environment.objects.filter(pk=form.id).update(**form)
|
||||||
else:
|
else:
|
||||||
env = Environment.objects.create(created_by=request.user, **form)
|
env = Environment.objects.create(created_by=request.user, **form)
|
||||||
|
env.sort_id = env.id
|
||||||
|
env.save()
|
||||||
if request.user.role:
|
if request.user.role:
|
||||||
request.user.role.add_deploy_perm('envs', env.id)
|
request.user.role.add_deploy_perm('envs', env.id)
|
||||||
return json_response(error=error)
|
return json_response(error=error)
|
||||||
|
|
||||||
|
def patch(self, request):
|
||||||
|
form, error = JsonParser(
|
||||||
|
Argument('id', type=int, help='参数错误'),
|
||||||
|
Argument('sort', filter=lambda x: x in ('up', 'down'), required=False)
|
||||||
|
).parse(request.body)
|
||||||
|
if error is None:
|
||||||
|
env = Environment.objects.filter(pk=form.id).first()
|
||||||
|
if not env:
|
||||||
|
return json_response(error='未找到指定环境')
|
||||||
|
if form.sort:
|
||||||
|
if form.sort == 'up':
|
||||||
|
tmp = Environment.objects.filter(sort_id__gt=env.sort_id).last()
|
||||||
|
else:
|
||||||
|
tmp = Environment.objects.filter(sort_id__lt=env.sort_id).first()
|
||||||
|
if tmp:
|
||||||
|
tmp.sort_id, env.sort_id = env.sort_id, tmp.sort_id
|
||||||
|
tmp.save()
|
||||||
|
env.save()
|
||||||
|
return json_response(error=error)
|
||||||
|
|
||||||
def delete(self, request):
|
def delete(self, request):
|
||||||
form, error = JsonParser(
|
form, error = JsonParser(
|
||||||
Argument('id', type=int, help='请指定操作对象')
|
Argument('id', type=int, help='请指定操作对象')
|
||||||
|
|
|
@ -3,21 +3,20 @@
|
||||||
* Copyright (c) <spug.dev@gmail.com>
|
* Copyright (c) <spug.dev@gmail.com>
|
||||||
* Released under the AGPL-3.0 License.
|
* Released under the AGPL-3.0 License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import { Table, Modal, message } from 'antd';
|
import { Table, Modal, Divider, message } from 'antd';
|
||||||
import { PlusOutlined } from '@ant-design/icons';
|
import { PlusOutlined, UpSquareOutlined, DownSquareOutlined } from '@ant-design/icons';
|
||||||
import { Action, TableCard, AuthButton } from 'components';
|
import { Action, TableCard, AuthButton } from 'components';
|
||||||
import { http, hasPermission } from 'libs';
|
import { http, hasPermission } from 'libs';
|
||||||
import store from './store';
|
import store from './store';
|
||||||
|
|
||||||
@observer
|
function ComTable() {
|
||||||
class ComTable extends React.Component {
|
useEffect(() => {
|
||||||
componentDidMount() {
|
|
||||||
store.fetchRecords()
|
store.fetchRecords()
|
||||||
}
|
}, [])
|
||||||
|
|
||||||
handleDelete = (text) => {
|
function handleDelete(text) {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '删除确认',
|
title: '删除确认',
|
||||||
content: `确定要删除【${text['name']}】?`,
|
content: `确定要删除【${text['name']}】?`,
|
||||||
|
@ -29,49 +28,59 @@ class ComTable extends React.Component {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
let data = store.records;
|
|
||||||
if (store.f_name) {
|
|
||||||
data = data.filter(item => item['name'].toLowerCase().includes(store.f_name.toLowerCase()))
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<TableCard
|
|
||||||
rowKey="id"
|
|
||||||
title="环境列表"
|
|
||||||
loading={store.isFetching}
|
|
||||||
dataSource={data}
|
|
||||||
onReload={store.fetchRecords}
|
|
||||||
actions={[
|
|
||||||
<AuthButton
|
|
||||||
auth="config.env.add"
|
|
||||||
type="primary"
|
|
||||||
icon={<PlusOutlined/>}
|
|
||||||
onClick={() => store.showForm()}>新建</AuthButton>
|
|
||||||
]}
|
|
||||||
pagination={{
|
|
||||||
showSizeChanger: true,
|
|
||||||
showLessItems: true,
|
|
||||||
hideOnSinglePage: true,
|
|
||||||
showTotal: total => `共 ${total} 条`,
|
|
||||||
pageSizeOptions: ['10', '20', '50', '100']
|
|
||||||
}}>
|
|
||||||
<Table.Column title="序号" key="series" render={(_, __, index) => index + 1}/>
|
|
||||||
<Table.Column title="环境名称" dataIndex="name"/>
|
|
||||||
<Table.Column title="标识符" dataIndex="key"/>
|
|
||||||
<Table.Column ellipsis title="描述信息" dataIndex="desc"/>
|
|
||||||
{hasPermission('config.env.edit|config.env.del') && (
|
|
||||||
<Table.Column title="操作" render={info => (
|
|
||||||
<Action>
|
|
||||||
<Action.Button auth="config.env.edit" onClick={() => store.showForm(info)}>编辑</Action.Button>
|
|
||||||
<Action.Button auth="config.env.del" onClick={() => this.handleDelete(info)}>删除</Action.Button>
|
|
||||||
</Action>
|
|
||||||
)}/>
|
|
||||||
)}
|
|
||||||
</TableCard>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleSort(info, sort) {
|
||||||
|
store.fetching = true;
|
||||||
|
http.patch('/api/config/environment/', {id: info.id, sort})
|
||||||
|
.then(store.fetchRecords, () => store.fetching = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableCard
|
||||||
|
rowKey="id"
|
||||||
|
title="环境列表"
|
||||||
|
loading={store.isFetching}
|
||||||
|
dataSource={store.dataSource}
|
||||||
|
onReload={store.fetchRecords}
|
||||||
|
actions={[
|
||||||
|
<AuthButton
|
||||||
|
auth="config.env.add"
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined/>}
|
||||||
|
onClick={() => store.showForm()}>新建</AuthButton>
|
||||||
|
]}
|
||||||
|
pagination={{
|
||||||
|
showSizeChanger: true,
|
||||||
|
showLessItems: true,
|
||||||
|
hideOnSinglePage: true,
|
||||||
|
showTotal: total => `共 ${total} 条`,
|
||||||
|
pageSizeOptions: ['10', '20', '50', '100']
|
||||||
|
}}>
|
||||||
|
<Table.Column width={120} title="排序" key="series" render={(info) => (
|
||||||
|
<div>
|
||||||
|
<UpSquareOutlined
|
||||||
|
onClick={() => handleSort(info, 'up')}
|
||||||
|
style={{cursor: 'pointer', color: '#1890ff'}}/>
|
||||||
|
<Divider type="vertical"/>
|
||||||
|
<DownSquareOutlined
|
||||||
|
onClick={() => handleSort(info, 'down')}
|
||||||
|
style={{cursor: 'pointer', color: '#1890ff'}}/>
|
||||||
|
</div>
|
||||||
|
)}/>
|
||||||
|
<Table.Column title="环境名称" dataIndex="name"/>
|
||||||
|
<Table.Column title="标识符" dataIndex="key"/>
|
||||||
|
<Table.Column ellipsis title="描述信息" dataIndex="desc"/>
|
||||||
|
{hasPermission('config.env.edit|config.env.del') && (
|
||||||
|
<Table.Column title="操作" render={info => (
|
||||||
|
<Action>
|
||||||
|
<Action.Button auth="config.env.edit" onClick={() => store.showForm(info)}>编辑</Action.Button>
|
||||||
|
<Action.Button auth="config.env.del" onClick={() => handleDelete(info)}>删除</Action.Button>
|
||||||
|
</Action>
|
||||||
|
)}/>
|
||||||
|
)}
|
||||||
|
</TableCard>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ComTable
|
export default observer(ComTable)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* Copyright (c) <spug.dev@gmail.com>
|
* Copyright (c) <spug.dev@gmail.com>
|
||||||
* Released under the AGPL-3.0 License.
|
* Released under the AGPL-3.0 License.
|
||||||
*/
|
*/
|
||||||
import { observable } from "mobx";
|
import { observable, computed } from "mobx";
|
||||||
import http from 'libs/http';
|
import http from 'libs/http';
|
||||||
|
|
||||||
class Store {
|
class Store {
|
||||||
|
@ -15,6 +15,12 @@ class Store {
|
||||||
|
|
||||||
@observable f_name;
|
@observable f_name;
|
||||||
|
|
||||||
|
@computed get dataSource() {
|
||||||
|
let records = this.records;
|
||||||
|
if (this.f_name) records = records.filter(x => x.name.toLowerCase().includes(this.f_name.toLowerCase()));
|
||||||
|
return records
|
||||||
|
}
|
||||||
|
|
||||||
fetchRecords = () => {
|
fetchRecords = () => {
|
||||||
this.isFetching = true;
|
this.isFetching = true;
|
||||||
return http.get('/api/config/environment/')
|
return http.get('/api/config/environment/')
|
||||||
|
|
Loading…
Reference in New Issue