Commit 4bf4dc0b authored by wanli's avatar wanli

feat(): 新增统计功能,完成前后端开发

parent 497be17d
''' '''
Author: your name Author: your name
Date: 2021-06-30 18:03:41 Date: 2021-06-30 18:03:41
LastEditTime: 2021-07-20 17:12:57 LastEditTime: 2021-07-23 00:26:38
LastEditors: Please set LastEditors LastEditors: Please set LastEditors
Description: In User Settings Edit Description: In User Settings Edit
FilePath: \evm-store\tools\build_out\application\signal_manager.py FilePath: \evm-store\tools\build_out\application\signal_manager.py
...@@ -73,6 +73,8 @@ class SignalManager(object): ...@@ -73,6 +73,8 @@ class SignalManager(object):
actionGetEpk = PySignal() actionGetEpk = PySignal()
actionApplicationBuild = PySignal() actionApplicationBuild = PySignal()
actionCheckVersion = PySignal() actionCheckVersion = PySignal()
# workbench
actionWorkbench = PySignal()
def __init__(self): def __init__(self):
super().__init__() super().__init__()
......
''' '''
Author: your name Author: your name
Date: 2021-06-30 17:43:46 Date: 2021-06-30 17:43:46
LastEditTime: 2021-07-20 17:13:15 LastEditTime: 2021-07-23 00:27:31
LastEditors: Please set LastEditors LastEditors: Please set LastEditors
Description: In User Settings Edit Description: In User Settings Edit
FilePath: \evm-store\tools\build_out\controllers\__init__.py FilePath: \evm-store\tools\build_out\controllers\__init__.py
...@@ -25,6 +25,7 @@ from .monitorLvgl import monitorLvglManager ...@@ -25,6 +25,7 @@ from .monitorLvgl import monitorLvglManager
from .monitorImage import monitorImageManager from .monitorImage import monitorImageManager
from .monitorEvm import monitorEvmManager from .monitorEvm import monitorEvmManager
from .file import fileManager from .file import fileManager
from .workbench import workbenchResource
def initConnect(): def initConnect():
signalManager.actionPostArea.connect(areaManager.post) signalManager.actionPostArea.connect(areaManager.post)
...@@ -87,3 +88,4 @@ def initConnect(): ...@@ -87,3 +88,4 @@ def initConnect():
signalManager.actionGetApplication.connect(appReview.getApp) signalManager.actionGetApplication.connect(appReview.getApp)
signalManager.actionGetEpk.connect(appReview.getDownloadFile) signalManager.actionGetEpk.connect(appReview.getDownloadFile)
signalManager.actionCheckVersion.connect(appReview.checkAppVersion) signalManager.actionCheckVersion.connect(appReview.checkAppVersion)
signalManager.actionWorkbench.connect(workbenchResource.get)
''' '''
Author: your name Author: your name
Date: 2021-07-22 04:03:24 Date: 2021-07-22 04:03:24
LastEditTime: 2021-07-22 18:58:34 LastEditTime: 2021-07-23 00:51:58
LastEditors: Please set LastEditors LastEditors: Please set LastEditors
Description: In User Settings Edit Description: In User Settings Edit
FilePath: \evm-store\tools\build_out\controllers\workbench.py FilePath: \evm-store\tools\build_out\controllers\workbench.py
''' '''
import datetime
from models.user import UserModel from models.user import UserModel
from datetime import datetime, timedelta from models.device import DeviceModel
from models.app import AppModel
from models.package import PackageModel
from webcreator.log import logger
from webcreator.response import ResponseCode
# 今日上传应用数 、历史应用总数
# 今日打包次数、历史打包总数
# 今日新增设备数,绑定设备数
# 今日新增开发者,开发者总数
'''
time_now = datetime.now() time_now = datetime.now()
#最近30天数据 #最近30天数据
result = UserModel.query.filter(UserModel.create_time >= time_now - timedelta(days=30)).all() result = UserModel.query.filter(UserModel.create_time >= time_now - timedelta(days=30)).all()
...@@ -21,3 +31,65 @@ result = UserModel.query.filter(UserModel.create_time >= time_now - timedelta(da ...@@ -21,3 +31,65 @@ result = UserModel.query.filter(UserModel.create_time >= time_now - timedelta(da
result = UserModel.query.filter(UserModel.create_time >= time_now - timedelta(hours=12)).all() result = UserModel.query.filter(UserModel.create_time >= time_now - timedelta(hours=12)).all()
#最近半小时 #最近半小时
result = UserModel.query.filter(UserModel.create_time >= time_now - timedelta(seconds=30)).all() result = UserModel.query.filter(UserModel.create_time >= time_now - timedelta(seconds=30)).all()
'''
class WorkbenchResource(object):
def __init__(self):
super().__init__()
def get(self, jwt={}):
if not jwt:
return None, ResponseCode.HTTP_INVAILD_REQUEST
user = UserModel.query.filter(UserModel.uuid==jwt.get("uuid")).one_or_none()
if not user:
return None, ResponseCode.USER_NOT_EXISTS
today = datetime.date.today()
tomorrow = today + datetime.timedelta(days=1)
logger.info(user.role)
if user.role == 1:
total_user = UserModel.query.filter().count()
today_user = UserModel.query.filter(UserModel.create_at >= today.strftime("%Y-%m-%d 00:00:00"), UserModel.create_at <= tomorrow.strftime("%Y-%m-%d 00:00:00")).count()
total_device = DeviceModel.query.filter().count()
today_device = DeviceModel.query.filter(DeviceModel.create_at >= today.strftime("%Y-%m-%d 00:00:00"), DeviceModel.create_at <= tomorrow.strftime("%Y-%m-%d 00:00:00")).count()
total_app = AppModel.query.filter().count()
today_app = AppModel.query.filter(AppModel.create_at >= today.strftime("%Y-%m-%d 00:00:00"), AppModel.create_at <= tomorrow.strftime("%Y-%m-%d 00:00:00")).count()
total_package = PackageModel.query.filter().count()
today_package = PackageModel.query.filter(PackageModel.create_at >= today.strftime("%Y-%m-%d 00:00:00"), PackageModel.create_at <= tomorrow.strftime("%Y-%m-%d 00:00:00")).count()
else:
total_user = UserModel.query.filter(UserModel.create_by==user.id).count()
today_user = UserModel.query.filter(UserModel.create_by==user.id, UserModel.create_at >= today.strftime("%Y-%m-%d 00:00:00"), UserModel.create_at <= tomorrow.strftime("%Y-%m-%d 00:00:00")).count()
total_device = DeviceModel.query.filter(DeviceModel.create_by==user.id).count()
today_device = DeviceModel.query.filter(DeviceModel.create_by==user.id, DeviceModel.create_at >= today.strftime("%Y-%m-%d 00:00:00"), DeviceModel.create_at <= tomorrow.strftime("%Y-%m-%d 00:00:00")).count()
total_app = AppModel.query.filter(AppModel.create_by==user.id).count()
today_app = AppModel.query.filter(AppModel.create_by==user.id, AppModel.create_at >= today.strftime("%Y-%m-%d 00:00:00"), AppModel.create_at <= tomorrow.strftime("%Y-%m-%d 00:00:00")).count()
total_package = PackageModel.query.filter(PackageModel.create_by==user.id).count()
today_package = PackageModel.query.filter(PackageModel.create_by==user.id, PackageModel.create_at >= today.strftime("%Y-%m-%d 00:00:00"), PackageModel.create_at <= tomorrow.strftime("%Y-%m-%d 00:00:00")).count()
result = {
'total_user': total_user,
'today_user': today_user,
'total_device': total_device,
'today_device': today_device,
'total_app': total_app,
'today_app': today_app,
'total_package': total_package,
'today_package': today_package
}
logger.info(result)
return result, ResponseCode.HTTP_SUCCESS
workbenchResource = WorkbenchResource()
\ No newline at end of file
''' '''
Author: your name Author: your name
Date: 2021-07-15 03:22:19 Date: 2021-07-15 03:22:19
LastEditTime: 2021-07-22 18:51:05 LastEditTime: 2021-07-23 00:32:33
LastEditors: Please set LastEditors LastEditors: Please set LastEditors
Description: In User Settings Edit Description: In User Settings Edit
FilePath: \evm-store\tools\build_out\views\__init__.py FilePath: \evm-store\tools\build_out\views\__init__.py
...@@ -41,6 +41,7 @@ api.add_resource(app.AppResourceList, '/app') ...@@ -41,6 +41,7 @@ api.add_resource(app.AppResourceList, '/app')
api.add_resource(openapi.AppReviewResource, '/api/app-review') api.add_resource(openapi.AppReviewResource, '/api/app-review')
api.add_resource(openapi.CStringToolResource, '/api/convert-to-c-string') api.add_resource(openapi.CStringToolResource, '/api/convert-to-c-string')
api.add_resource(openapi.BuildAppResource, '/evm_store/application/build') api.add_resource(openapi.BuildAppResource, '/evm_store/application/build')
api.add_resource(openapi.Workbench, '/api/workbench')
api.add_resource(openapi.App, '/api/app') api.add_resource(openapi.App, '/api/app')
api.add_resource(openapi.AppInfo, '/api/app-info') api.add_resource(openapi.AppInfo, '/api/app-info')
api.add_resource(openapi.LauncherResource, '/api/app-launcher') api.add_resource(openapi.LauncherResource, '/api/app-launcher')
......
''' '''
Author: your name Author: your name
Date: 2021-07-19 14:29:33 Date: 2021-07-19 14:29:33
LastEditTime: 2021-07-22 18:47:43 LastEditTime: 2021-07-23 00:37:20
LastEditors: Please set LastEditors LastEditors: Please set LastEditors
Description: In User Settings Edit Description: In User Settings Edit
FilePath: \evm-store\tools\build_out\views\api.py FilePath: \evm-store\tools\build_out\views\api.py
...@@ -107,6 +107,8 @@ class BuildAppResource(Resource): ...@@ -107,6 +107,8 @@ class BuildAppResource(Resource):
def get(self): def get(self):
try: try:
return ResponseCode.HTTP_SUCCESS
result = db.session.query(AnnexModel).all() result = db.session.query(AnnexModel).all()
for item in result: for item in result:
item.uuid = uuid.uuid1().hex item.uuid = uuid.uuid1().hex
...@@ -419,8 +421,6 @@ class ObfuscatedCode(Resource): ...@@ -419,8 +421,6 @@ class ObfuscatedCode(Resource):
return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data) return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)
# 获取启动器接口 # 获取启动器接口
class LauncherResource(Resource): class LauncherResource(Resource):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() super().__init__()
...@@ -455,8 +455,6 @@ class LauncherResource(Resource): ...@@ -455,8 +455,6 @@ class LauncherResource(Resource):
return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data) return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)
# 获取App列表接口 # 获取App列表接口
class AppListResource(Resource): class AppListResource(Resource):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() super().__init__()
...@@ -537,8 +535,6 @@ class AppListResource(Resource): ...@@ -537,8 +535,6 @@ class AppListResource(Resource):
return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data) return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)
# 获取应用接口 # 获取应用接口
class App(Resource): class App(Resource):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() super().__init__()
...@@ -575,8 +571,6 @@ class App(Resource): ...@@ -575,8 +571,6 @@ class App(Resource):
return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data) return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)
# 获取应用信息接口 # 获取应用信息接口
class AppInfo(Resource): class AppInfo(Resource):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() super().__init__()
...@@ -611,8 +605,6 @@ class AppInfo(Resource): ...@@ -611,8 +605,6 @@ class AppInfo(Resource):
return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data) return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)
# 下载EPK文件接口 # 下载EPK文件接口
class DownloadEpk(Resource): class DownloadEpk(Resource):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() super().__init__()
...@@ -678,3 +670,24 @@ class DownloadApp(Resource): ...@@ -678,3 +670,24 @@ class DownloadApp(Resource):
data = e.args data = e.args
current_app.logger.error(e) current_app.logger.error(e)
return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data) return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)
class Workbench(Resource):
def __init__(self) -> None:
super().__init__()
self.parser = RequestParser()
@jwt_required(locations=["headers"])
def get(self):
# 特殊参数,即不是从json获取参数的接口,可以将这个注释打开
# self.parser.add_argument("page", type=int, location="args", default=1)
self.parser.add_argument("string", type=str, location="json", required=False)
args = self.parser.parse_args()
try:
jwt = get_jwt_identity()
result, message = signalManager.actionWorkbench.emit(jwt)
return response_result(message, data=result)
except Exception as e:
traceback.print_exc()
current_app.logger.error(e)
return response_result(ResponseCode.HTTP_SERVER_ERROR)
\ No newline at end of file
/* /*
* @Author: your name * @Author: your name
* @Date: 2021-07-15 09:33:39 * @Date: 2021-07-15 09:33:39
* @LastEditTime: 2021-07-22 18:53:32 * @LastEditTime: 2021-07-23 00:35:38
* @LastEditors: Please set LastEditors * @LastEditors: Please set LastEditors
* @Description: In User Settings Edit * @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\src\api\openapi.js * @FilePath: \evm-store\tools\frontend\src\api\openapi.js
...@@ -15,6 +15,13 @@ export function menuNav() { ...@@ -15,6 +15,13 @@ export function menuNav() {
}) })
} }
export function workbench() {
return request({
url: "/api/v1/api/workbench",
method: 'get'
})
}
export function getWatchList() { export function getWatchList() {
return request({ return request({
url: "/api/v1/monitor/watch", url: "/api/v1/monitor/watch",
......
...@@ -13,14 +13,14 @@ ...@@ -13,14 +13,14 @@
<a-menu slot="overlay" @click="handleMenuClick"> <a-menu slot="overlay" @click="handleMenuClick">
<a-menu-item key="gitee"> <a-menu-item key="gitee">
<a target="_blank" href="https://gitee.com/scriptiot/evm"> <a target="_blank" href="https://gitee.com/scriptiot/evm">
<a-icon type="slack-square" theme="outlined" /> <a-icon type="slack-square" theme="outlined" />
Gitee Gitee
</a> </a>
</a-menu-item> </a-menu-item>
<a-menu-item key="github"> <a-menu-item key="github">
<a target="_blank" href="https://github.com/scriptiot/evm"> <a target="_blank" href="https://github.com/scriptiot/evm">
<a-icon type="github" /> <a-icon type="github" />
Github Github
</a> </a>
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>
...@@ -28,27 +28,11 @@ ...@@ -28,27 +28,11 @@
<a-notice-icon <a-notice-icon
class="ai-notice" class="ai-notice"
className="action" className="action"
:count="8" :count="msgCount"
:loading="false" :loading="false"
> >
<a-notice-icon-tab <a-notice-icon-tab
:list="[ :list="msgList"
{
id: '000000001',
avatar:
'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
title: '你收到了 14 份新周报',
datetime: '2017-08-09',
},
{
id: '000000002',
avatar:
'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png',
title: '你推荐的 曲妮妮 已通过第三轮面试',
datetime: '2017-08-08',
read: true,
},
]"
title="通知" title="通知"
emptyText="你已查看所有通知" emptyText="你已查看所有通知"
emptyImage="https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg" emptyImage="https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg"
...@@ -60,39 +44,7 @@ ...@@ -60,39 +44,7 @@
emptyImage="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg" emptyImage="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg"
/> />
<a-notice-icon-tab <a-notice-icon-tab
:list="[ :list="todoList"
{
id: '000000009',
title: '任务名称',
description: '任务需要在 2017-01-12 20:00 前启动',
extra: '未开始',
status: 'todo',
},
{
id: '000000010',
title: '第三方紧急代码变更',
description:
'冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务',
extra: '马上到期',
read: true,
status: 'urgent',
},
{
id: '000000011',
title: '信息安全考试',
description: '指派竹尔于 2017-01-09 前完成更新并发布',
extra: '已耗时 8 天',
status: 'doing',
},
{
id: '000000012',
title: 'ABCD 版本发布',
description:
'冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务',
extra: '进行中',
status: 'processing',
},
]"
title="待办" title="待办"
emptyText="你已完成所有待办" emptyText="你已完成所有待办"
emptyImage="https://gw.alipayobjects.com/zos/rmsportal/HsIsxMZiWKrNUavQUXqx.svg" emptyImage="https://gw.alipayobjects.com/zos/rmsportal/HsIsxMZiWKrNUavQUXqx.svg"
...@@ -169,6 +121,57 @@ import SettingDrawer from "@/components/SettingDrawer"; ...@@ -169,6 +121,57 @@ import SettingDrawer from "@/components/SettingDrawer";
export default { export default {
data: () => ({ data: () => ({
collapse: false, collapse: false,
msgCount: null,
msgList: [
// {
// id: "000000001",
// avatar:
// "https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png",
// title: "你收到了 14 份新周报",
// datetime: "2017-08-09",
// },
// {
// id: "000000002",
// avatar:
// "https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png",
// title: "你推荐的 曲妮妮 已通过第三轮面试",
// datetime: "2017-08-08",
// read: true,
// },
],
todoList: [
// {
// id: "000000009",
// title: "任务名称",
// description: "任务需要在 2017-01-12 20:00 前启动",
// extra: "未开始",
// status: "todo",
// },
// {
// id: "000000010",
// title: "第三方紧急代码变更",
// description:
// "冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务",
// extra: "马上到期",
// read: true,
// status: "urgent",
// },
// {
// id: "000000011",
// title: "信息安全考试",
// description: "指派竹尔于 2017-01-09 前完成更新并发布",
// extra: "已耗时 8 天",
// status: "doing",
// },
// {
// id: "000000012",
// title: "ABCD 版本发布",
// description:
// "冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务",
// extra: "进行中",
// status: "processing",
// },
],
}), }),
components: { components: {
ATooltip: Tooltip, ATooltip: Tooltip,
...@@ -190,15 +193,9 @@ export default { ...@@ -190,15 +193,9 @@ export default {
}, },
handleMenuClick(e) { handleMenuClick(e) {
if (e.key === "gitee") { if (e.key === "gitee") {
window.open( window.open("https://gitee.com/scriptiot/evm", "_blank");
"https://gitee.com/scriptiot/evm",
"_blank"
);
} else { } else {
window.open( window.open("https://gitee.com/scriptiot/evm", "_blank");
"https://gitee.com/scriptiot/evm",
"_blank"
);
} }
}, },
logout() { logout() {
...@@ -227,8 +224,8 @@ export default { ...@@ -227,8 +224,8 @@ export default {
return className; return className;
}, },
userinfo() { userinfo() {
return this.$store.state.frontend.login.userinfo return this.$store.state.frontend.login.userinfo;
} },
}, },
}; };
</script> </script>
/* /*
* @Author: your name * @Author: your name
* @Date: 2021-07-15 09:33:39 * @Date: 2021-07-15 09:33:39
* @LastEditTime: 2021-07-22 19:26:59 * @LastEditTime: 2021-07-22 23:16:09
* @LastEditors: Please set LastEditors * @LastEditors: Please set LastEditors
* @Description: In User Settings Edit * @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\src\defaultSettings.js * @FilePath: \evm-store\tools\frontend\src\defaultSettings.js
...@@ -10,10 +10,10 @@ export default { ...@@ -10,10 +10,10 @@ export default {
navTheme: 'dark', // theme for nav menu navTheme: 'dark', // theme for nav menu
primaryColor: '#1890FF', // primary color of ant design primaryColor: '#1890FF', // primary color of ant design
layout: 'sidemenu', // nav menu position: sidemenu or topmenu layout: 'sidemenu', // nav menu position: sidemenu or topmenu
contentWidth: 'Fixed', // layout of content: Fluid or Fixed, only works when layout is topmenu contentWidth: 'Fluid', // layout of content: Fluid or Fixed, only works when layout is topmenu
fixedHeader: true, // sticky header fixedHeader: false, // sticky header
autoHideHeader: true, // auto hide header autoHideHeader: false, // auto hide header
fixSiderbar: true, // sticky siderbar fixSiderbar: false, // sticky siderbar
leftMenuTitle: "EVM 应用商店", // 左侧边栏顶部名称 leftMenuTitle: "EVM 应用商店", // 左侧边栏顶部名称
leftMenuIcon: "", // 左侧边栏顶部Logo leftMenuIcon: "", // 左侧边栏顶部Logo
appSlogan: "EVM,致力于为互联网行业提供物联网解决方案", // 应用宣传文案 appSlogan: "EVM,致力于为互联网行业提供物联网解决方案", // 应用宣传文案
......
...@@ -62,17 +62,17 @@ export default { ...@@ -62,17 +62,17 @@ export default {
'app.home.introduce': '介绍', 'app.home.introduce': '介绍',
'app.analysis.test': '工专路 {no} 号店', 'app.analysis.test': '工专路 {no} 号店',
'app.analysis.introduce': '指标说明', 'app.analysis.introduce': '指标说明',
'app.analysis.total-sales': '总销售额', 'app.analysis.total-sales': '应用总数',
'app.analysis.day-sales': '日销售额', 'app.analysis.day-sales': '今日新增',
'app.analysis.visits': '访问量', 'app.analysis.visits': '打包总数',
'app.analysis.visits-trend': '访问量趋势', 'app.analysis.visits-trend': '访问量趋势',
'app.analysis.visits-ranking': '门店访问量排名', 'app.analysis.visits-ranking': '门店访问量排名',
'app.analysis.day-visits': '日访问量', 'app.analysis.day-visits': '今日新增',
'app.analysis.week': '周同比', 'app.analysis.week': '周同比',
'app.analysis.day': '日同比', 'app.analysis.day': '今日新增',
'app.analysis.payments': '支付笔', 'app.analysis.payments': '开发者',
'app.analysis.conversion-rate': '转化率', 'app.analysis.conversion-rate': '今日新增',
'app.analysis.operational-effect': '运营活动效果', 'app.analysis.operational-effect': '设备总数',
'app.analysis.sales-trend': '销售趋势', 'app.analysis.sales-trend': '销售趋势',
'app.analysis.sales-ranking': '门店销售额排名', 'app.analysis.sales-ranking': '门店销售额排名',
'app.analysis.all-year': '全年', 'app.analysis.all-year': '全年',
......
...@@ -59,14 +59,6 @@ const mock = [ ...@@ -59,14 +59,6 @@ const mock = [
leaf: true, leaf: true,
children: [], children: [],
}, },
{
id: "1044886630122659841",
parentId: "1044886629921333248",
name: "file-manager",
path: "/system/setting/file-manager",
leaf: true,
children: [],
},
], ],
}, },
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment