diff options
author | Hongyuan Ma | 2018-08-08 13:50:52 +0000 |
---|---|---|
committer | Hongyuan Ma | 2018-08-08 13:50:52 +0000 |
commit | 54af3cc5196a593d72688fd90d719c629ff0f05c (patch) | |
tree | 6ec217f8791717625af98bb7eea78491cd9b5dc6 | |
parent | 169fe430df64b8bd1ec0ca47294ebc34f6ed2adf (diff) |
add farmer apply page
-rw-r--r-- | front-end/src/app.jsx | 3 | ||||
-rw-r--r-- | front-end/src/component/layout/theme.css | 1 | ||||
-rw-r--r-- | front-end/src/page/detailInfo/index.css | 9 | ||||
-rw-r--r-- | front-end/src/page/detailInfo/index.jsx | 63 | ||||
-rw-r--r-- | front-end/src/page/farmerApply/index.jsx | 141 | ||||
-rw-r--r-- | front-end/src/page/machineInfo/index.jsx | 16 | ||||
-rw-r--r-- | front-end/src/page/portal/index.jsx | 8 | ||||
-rw-r--r-- | front-end/src/service/user-service.jsx | 9 | ||||
-rw-r--r-- | web/apps/test_records/serializer.py | 1 | ||||
-rw-r--r-- | web/apps/user_operation/serializer.py | 4 | ||||
-rw-r--r-- | web/apps/user_operation/views.py | 46 | ||||
-rw-r--r-- | web/apps/users/models.py | 2 | ||||
-rw-r--r-- | web/apps/users/serializer.py | 8 |
13 files changed, 235 insertions, 76 deletions
diff --git a/front-end/src/app.jsx b/front-end/src/app.jsx index cf10cfc..60f0002 100644 --- a/front-end/src/app.jsx +++ b/front-end/src/app.jsx @@ -17,6 +17,8 @@ import DetailInfo from './page/detailInfo/index.jsx' import MachinelInfo from './page/machineInfo/index.jsx' import Portal from './page/portal/index.jsx' +import FarmerApply from './page/farmerApply/index.jsx' + // we need to map the `scale` prop we define below // to the transform style property function mapStyles(styles) { @@ -71,6 +73,7 @@ class App extends React.Component { <Route exact path="/ppolicy/" component={PPolicy}/> <Route exact path="/portal/" component={Portal}/> + <Route exact path="/farmerApply/" component={FarmerApply}/> <Route path="/detailInfo/:uuid" component={DetailInfo}/> <Route path="/machineInfo/:machine_sn" component={MachinelInfo}/> {/*<Redirect exact from="/order" to="/order/index"/>*/} diff --git a/front-end/src/component/layout/theme.css b/front-end/src/component/layout/theme.css index edb28f9..942a4ad 100644 --- a/front-end/src/component/layout/theme.css +++ b/front-end/src/component/layout/theme.css @@ -1,5 +1,6 @@ /*---------------------------------------------- COMMON STYLES + https://www.webthemez.com/demo/insight-free-bootstrap-html5-admin-template/empty.html# ------------------------------------------------*/ body { font-family: 'Open Sans', sans-serif; diff --git a/front-end/src/page/detailInfo/index.css b/front-end/src/page/detailInfo/index.css index 758664a..e16cc40 100644 --- a/front-end/src/page/detailInfo/index.css +++ b/front-end/src/page/detailInfo/index.css @@ -66,4 +66,13 @@ .trend-span .regressive{ color: #cf1322!important; +} + + +/*catalog*/ +.catalog.ui.vertical.menu { + width: 100%; +} +.catalog.ui.menu .item{ + color: inherit; }
\ No newline at end of file diff --git a/front-end/src/page/detailInfo/index.jsx b/front-end/src/page/detailInfo/index.jsx index 2a7bf6f..1711ace 100644 --- a/front-end/src/page/detailInfo/index.jsx +++ b/front-end/src/page/detailInfo/index.jsx @@ -1,7 +1,7 @@ import React from 'react'; import {Link} from 'react-router-dom'; import './index.css'; -import {Table, Divider, Segment, Icon} from 'semantic-ui-react' +import {Table, Divider, Segment, Icon, Menu, Input, Dropdown, Sticky} from 'semantic-ui-react' import PGUtil from 'util/util.jsx' import FarmerCard from 'component/farmer-card/index.jsx' import InfoList from 'component/info-list/index.jsx' @@ -45,10 +45,11 @@ class DetailInfo extends React.Component { }); } + render() { let prev = this.state.recordInfo.prev || 'none'; - let branch = this.state.recordInfo.branch || ''; - let commit = this.state.recordInfo.commit || ''; + let branch = this.state.recordInfo.branch || ''; + let commit = this.state.recordInfo.commit || ''; let date = this.state.recordInfo.date || ''; let machine = this.state.recordInfo.test_machine || {}; let dataset = this.state.recordInfo.dataset_info || {}; @@ -92,12 +93,13 @@ class DetailInfo extends React.Component { if (status == -1) { trend_span = <span>{percentage}</span>; - } else if (status == 1){ + } else if (status == 1) { trend_span = <span className="trend-span improved"><Icon name="angle double up"/>+{percentage}</span>; - } else if (status == 2){ + } else if (status == 2) { trend_span = <span className="trend-span quo"><Icon name="bars"/>+{percentage}</span>; - } else if (status == 3){ - trend_span = <span className="trend-span regressive"><Icon name="angle double down"/>{percentage}</span>; + } else if (status == 3) { + trend_span = + <span className="trend-span regressive"><Icon name="angle double down"/>{percentage}</span>; } return ( @@ -106,11 +108,11 @@ class DetailInfo extends React.Component { <Table.Row> <Table.HeaderCell colSpan="4"> <div className="client-title-div"> - <div>Client(s) {key}: {metric} {trend_span}</div> + <div>Client(s) {key}: {metric} {trend_span}</div> {/*<div><a href=""> >>prev</a></div>*/} </div> {/*<div>*/} - {/*<span>Improved ()</span>*/} + {/*<span>Improved ()</span>*/} {/*</div>*/} </Table.HeaderCell> </Table.Row> @@ -165,12 +167,13 @@ class DetailInfo extends React.Component { if (status == -1) { trend_span = <span>{percentage}</span>; - } else if (status == 1){ + } else if (status == 1) { trend_span = <span className="trend-span improved"><Icon name="angle double up"/>+{percentage}</span>; - } else if (status == 2){ + } else if (status == 2) { trend_span = <span className="trend-span quo"><Icon name="bars"/>+{percentage}</span>; - } else if (status == 3){ - trend_span = <span className="trend-span regressive"><Icon name="angle double down"/>{percentage}</span>; + } else if (status == 3) { + trend_span = + <span className="trend-span regressive"><Icon name="angle double down"/>{percentage}</span>; } return ( @@ -179,7 +182,7 @@ class DetailInfo extends React.Component { <Table.Row> <Table.HeaderCell colSpan="4"> <div className="client-title-div"> - <div>Client(s) {key}: {metric} {trend_span}</div> + <div>Client(s) {key}: {metric} {trend_span}</div> {/*<div><a href=""> >>prev</a></div>*/} </div> {/*<div>*/} @@ -209,22 +212,24 @@ class DetailInfo extends React.Component { }); let prev_link - if(prev == 'none') { + if (prev == 'none') { prev_link = prev - }else{ + } else { prev_link = ( - <Link target = '_blank' color='linkedin' to={'/detailInfo/' + prev}> + <Link target='_blank' color='linkedin' to={'/detailInfo/' + prev}> {prev.substring(0, 7)} </Link> ) } + return ( <div className="container-fluid detail-container"> <div className="record-title "> <div className="record-title-right title-flex"> <div className="record-title-top"> <span>Branch: {branch}</span> - <span>Commit: <a target="_blank" href={ PGConstant.PG_GITHUB_MIRROR + commit}>{commit.substring(0, 7)}</a></span> + <span>Commit: <a target="_blank" + href={ PGConstant.PG_GITHUB_MIRROR + commit}>{commit.substring(0, 7)}</a></span> </div> <div className="record-title-bottom"> <h2 >NO: {this.state.recordNo}</h2> @@ -245,7 +250,7 @@ class DetailInfo extends React.Component { <Segment vertical>Farmer Info</Segment> <FarmerCard machine={machine}></FarmerCard> {/*//todo add a catalog*/} - {/*<div className="affix">aaaa</div>*/} + </div> <div className="col-md-9"> @@ -307,16 +312,16 @@ class DetailInfo extends React.Component { <div> {/*<h2><a href="#linuxInfo">Linux Info</a></h2>*/} {/*<div className="" data-example-id="">*/} - {/*<dl>*/} - {/*<dt><a href="#">Description lists</a></dt>*/} - {/*<dd>A description list is perfect for defining terms.</dd>*/} - {/*<dt>Euismod</dt>*/} - {/*<dd>*/} - {/*</dd>*/} - {/*<dd></dd>*/} - {/*<dt>Malesuada porta</dt>*/} - {/*<dd>Etiam porta sem malesuada magna mollis euismod.</dd>*/} - {/*</dl>*/} + {/*<dl>*/} + {/*<dt><a href="#">Description lists</a></dt>*/} + {/*<dd>A description list is perfect for defining terms.</dd>*/} + {/*<dt>Euismod</dt>*/} + {/*<dd>*/} + {/*</dd>*/} + {/*<dd></dd>*/} + {/*<dt>Malesuada porta</dt>*/} + {/*<dd>Etiam porta sem malesuada magna mollis euismod.</dd>*/} + {/*</dl>*/} {/*</div>*/} diff --git a/front-end/src/page/farmerApply/index.jsx b/front-end/src/page/farmerApply/index.jsx index df329d0..43068e3 100644 --- a/front-end/src/page/farmerApply/index.jsx +++ b/front-end/src/page/farmerApply/index.jsx @@ -1,12 +1,13 @@ import React from 'react'; +import {hashHistory} from 'React-router' import './index.css'; -import { hashHistory } from 'react-router' -import ResultFilter from 'component/result-filter/index.jsx'; -import MachineTable from 'util/machine-table/index.jsx'; +import {Link} from 'react-router-dom'; import UserInfoCard from 'component/userinfo-card/index.jsx' import Record from 'service/record-service.jsx' import PGUtil from 'util/util.jsx' import User from 'service/user-service.jsx' +import PGConstant from 'util/constant.jsx' + const _user = new User(); const _util = new PGUtil(); @@ -16,39 +17,45 @@ class FarmerApply extends React.Component { super(props); this.state = { username: '', - isLoading: false, machines:[], userinfo: {} } - + this.loadUserMachineManageList = this.loadUserMachineManageList.bind(this); } componentDidMount(){ let user = _util.getStorage('userInfo') + let _this = this this.setState({ username: user.username, + },()=>{ + _this.loadUserPortalInfo() + _this.loadUserMachineManageList(); }); console.log(user.token) - this.loadUserPortalInfo() - this.loadUserMachineManageList(); + } loadUserPortalInfo(){ - _user.getUserPortalInfo().then(res => { + let username = this.state.username + _user.getUserPortalInfo(username).then(res => { this.setState({ - userinfo: res.results, + userinfo: res, }); }, errMsg => { - _util.errorTips(errMsg); + _util.errorTips('Please make sure no fields are empty.'); }); } loadUserMachineManageList(page=1){ - _user.getUserMachineManageList().then(res => { + + let listParam = {}; + listParam.page = page; + listParam.machine_owner__username = this.state.username; + _user.getUserMachineManageList(listParam).then(res => { this.setState({ machines: res.results, total: res.count, - isLoading: false }); }, errMsg => { _util.errorTips(errMsg); @@ -59,12 +66,54 @@ class FarmerApply extends React.Component { // this.props.history.push('/login') // hashHistory.push('/login') window.location.href = '/'; - // _user.logout().then(res => { - // _util.removeStorage('userInfo'); - // window.location.href = '/login'; - // }, errMsg => { - // _util.errorTips(errMsg); - // }); + } + + onInputChange(e) { + let inputValue = e.target.value, + inputName = e.target.name; + this.setState({ + [inputName]: inputValue + }); + } + + onInputKeyUp(e) { + if (e.keyCode === 13) { + this.onSubmit(); + } + } + + onSubmit() { + // alert(1) + let machineInfo = { + os_name: this.state.os_name, + os_version: this.state.os_version, + comp_name: this.state.comp_name, + comp_version: this.state.comp_version, + machine_owner:this.state.username + } + let checkResult = true + // check success + if (checkResult) { + _user.farmerApply(machineInfo).then((res) => { + // console.dir(res) + alert('add machine success!') + hashHistory.push('/portal') + // window.location.href = this.state.redirect; + }, (err) => { + // console.log(err) + if (PGConstant.AuthorizedErrorCode === err) { + _util.errorTips('username or password is mistake!'); + }else{ + _util.errorTips('login fail'); + } + }); + } + // check failure + else { + + _util.errorTips(checkResult.msg); + } + } render() { @@ -79,7 +128,7 @@ class FarmerApply extends React.Component { <div className="col-md-3"> {/*<Segment vertical>Farmer Info</Segment>*/} - <UserInfoCard info={this.state.userinfo}></UserInfoCard> + <UserInfoCard userinfo={this.state.userinfo}></UserInfoCard> <div className="panel panel-default panel-blue"> <div className="panel-heading"> @@ -88,9 +137,9 @@ class FarmerApply extends React.Component { </h3> </div> <div className="list-group"> - <a href="\add-machine" className="list-group-item"> + <Link target='_blank' to="farmerApply/" className="list-group-item"> <i className="fa fa-globe fa-fw"></i> Add a New Mchine - </a> + </Link> <a onClick={() => {this.onLogout()}} className="list-group-item"> <i className="fa fa-arrow-left fa-fw"></i> Logout </a> @@ -103,7 +152,55 @@ class FarmerApply extends React.Component { <h2 >Welcome Back, {this.state.username}</h2> </div> - <MachineTable list={this.state.machines} total={this.state.total} current={this.state.currentPage} loadfunc={this.loadRecordList}/> + <div className="panel panel-default"> + <div className="panel-heading"> + Apply New Machines + </div> + <div className="panel-body"> + <div className="row"> + {/*<!-- /.col-lg-6 (nested) -->*/} + <div className="col-lg-12"> + {/*<h4>Login Form</h4>*/} + <form role="form"> + <div className="form-group input-group"> + {/*<label className="control-label" for="inputLogin"> login input</label>*/} + <span class="input-group-addon">system name</span> + <input type="text" className="form-control" id="inputOSName" + placeholder="etc.Debian,Ubuntu" + name="os_name" + onKeyUp={e => this.onInputKeyUp(e)} + onChange={e => this.onInputChange(e)}/> + </div> + <div className="form-group input-group"> + <span class="input-group-addon">system version</span> + <input type="text" className="form-control" id="inputOSVersion" + name="os_version" + placeholder="etc.9,14.4" onKeyUp={e => this.onInputKeyUp(e)} + onChange={e => this.onInputChange(e)}/> + </div> + <div className="form-group input-group"> + <span class="input-group-addon">arch name</span> + <input type="text" className="form-control" id="inputCampName" + name="comp_name" + placeholder="etc.x86" onKeyUp={e => this.onInputKeyUp(e)} + onChange={e => this.onInputChange(e)}/> + </div> + <div className="form-group input-group"> + <span class="input-group-addon">arch version</span> + <input type="text" className="form-control" id="inputCampVersion" + name="comp_version" + placeholder="etc.64" onKeyUp={e => this.onInputKeyUp(e)} + onChange={e => this.onInputChange(e)}/> + </div> + <button type="button" className="btn btn-primary" onClick={e => {this.onSubmit(e)}}>Submit</button> + </form> + </div> + {/*<!-- /.col-lg-6 (nested) -->*/} + </div> + {/*<!-- /.row (nested) -->*/} + </div> + {/*<!-- /.panel-body -->*/} + </div> </div> </div> diff --git a/front-end/src/page/machineInfo/index.jsx b/front-end/src/page/machineInfo/index.jsx index 3634145..80d4738 100644 --- a/front-end/src/page/machineInfo/index.jsx +++ b/front-end/src/page/machineInfo/index.jsx @@ -86,12 +86,18 @@ class MachineInfo extends React.Component { return ( <div className="container-fluid detail-container"> <div className="record-title"> - - <div className="record-title-top"> - <span>NO: {this.state.machineNo}</span> - {/*<span>Add Date: {this.state.machineInfo.addtime}</span>*/} + <div className="record-title-right title-flex"> + <div className="record-title-top"> + <span>NO: {this.state.machineNo}</span> + {/*<span>Commit: <a target="_blank" href={ PGConstant.PG_GITHUB_MIRROR + commit}>{commit.substring(0, 7)}</a></span>*/} + </div> + <div className="record-title-bottom"> + <h2 >Farmer: {this.state.machineInfo.alias}</h2> + </div> </div> - <h2 >Farmer: {this.state.machineInfo.alias}</h2> + {/*<div className="record-title-left title-flex">*/} + {/*<span>Date joined: {this.state.machineInfo.add_time}</span>*/} + {/*</div>*/} </div> <div className="machine-info-divier-div"> diff --git a/front-end/src/page/portal/index.jsx b/front-end/src/page/portal/index.jsx index e6ba7d7..e58188d 100644 --- a/front-end/src/page/portal/index.jsx +++ b/front-end/src/page/portal/index.jsx @@ -1,7 +1,6 @@ import React from 'react'; +import {Link} from 'react-router-dom'; import './index.css'; -import { hashHistory } from 'react-router' -import ResultFilter from 'component/result-filter/index.jsx'; import MachineTable from 'util/machine-table/index.jsx'; import UserInfoCard from 'component/userinfo-card/index.jsx' import Record from 'service/record-service.jsx' @@ -82,9 +81,10 @@ class Portal extends React.Component { </h3> </div> <div className="list-group"> - <a href="\add-machine" className="list-group-item"> + <Link target='_blank' to="farmerApply/" className="list-group-item"> <i className="fa fa-globe fa-fw"></i> Add a New Mchine - </a> + </Link> + <a onClick={() => {this.onLogout()}} className="list-group-item"> <i className="fa fa-arrow-left fa-fw"></i> Logout </a> diff --git a/front-end/src/service/user-service.jsx b/front-end/src/service/user-service.jsx index 4020bab..04f2b56 100644 --- a/front-end/src/service/user-service.jsx +++ b/front-end/src/service/user-service.jsx @@ -4,6 +4,15 @@ import PGConstant from 'util/constant.jsx' const _util = new PGUtil(); class User{ + farmerApply(farmerInfo){ + let url = PGConstant.base_url + '/my-machine/'; + return _util.request({ + type: 'post', + url: url, + data: farmerInfo + }); + } + login(loginInfo){ let url = PGConstant.base_url + '/login/'; return _util.request({ diff --git a/web/apps/test_records/serializer.py b/web/apps/test_records/serializer.py index a57b54c..5decb02 100644 --- a/web/apps/test_records/serializer.py +++ b/web/apps/test_records/serializer.py @@ -346,7 +346,6 @@ class TestRecordDetailSerializer(serializers.ModelSerializer): test_machine = UserMachineSerializer() hardware_info = serializers.SerializerMethodField() meta_info = MetaInfoDetailSerializer() - dataset_info = serializers.SerializerMethodField() prev = serializers.SerializerMethodField() diff --git a/web/apps/user_operation/serializer.py b/web/apps/user_operation/serializer.py index 069c175..1a18f32 100644 --- a/web/apps/user_operation/serializer.py +++ b/web/apps/user_operation/serializer.py @@ -64,6 +64,10 @@ class UserPortalInfoSerializer(serializers.ModelSerializer): reports = TestRecord.objects.filter(test_machine__machine_sn__in=machine_dict).values_list('branch__branch_name').annotate(Count('id')) return reports.count() +class CreateUserMachineSerializer(serializers.ModelSerializer): + class Meta: + model = UserMachine + fields = "__all__" class UserMachineManageSerializer(serializers.ModelSerializer): ''' diff --git a/web/apps/user_operation/views.py b/web/apps/user_operation/views.py index 0985349..e7641cf 100644 --- a/web/apps/user_operation/views.py +++ b/web/apps/user_operation/views.py @@ -11,9 +11,11 @@ from rest_framework_jwt.authentication import JSONWebTokenAuthentication from filters import MachineRecordListFilter, UserMachineListFilter from test_records.models import TestRecord from users.models import UserMachine, UserProfile +from users.serializer import CreateUserProfileSerializer from serializer import UserMachineManageSerializer, UserPortalInfoSerializer, TestRecordListSerializer, \ - UserMachineSerializer - + UserMachineSerializer, CreateUserMachineSerializer +from rest_framework.response import Response +from rest_framework import status class StandardResultsSetPagination(PageNumberPagination): page_size = 20 @@ -37,7 +39,7 @@ class UserMachineRecordByBranchListViewSet(mixins.ListModelMixin, viewsets.Gener filter_backends = (django_filters.rest_framework.DjangoFilterBackend,) filter_class = MachineRecordListFilter -class UserMachineListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): +class UserMachineListViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet): """ List test records """ @@ -49,17 +51,33 @@ class UserMachineListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): filter_backends = (django_filters.rest_framework.DjangoFilterBackend,) filter_class = UserMachineListFilter - # def perform_create(self, serializer): - # shop_cart = serializer.save() - # goods = shop_cart.goods - # goods.goods_num -= shop_cart.nums - # goods.save() - - # def get_serializer_class(self): - # if self.action == 'create': - # return UserMachineSerializer - # else: - # return UserMachineManageSerializer + def post(self, request, *args, **kwargs): + return self.create(request, *args, **kwargs) + + def create(self, request, *args, **kwargs): + data = {} + data['os_name'] = request.data['os_name'] + data['os_version'] = request.data['os_version'] + data['comp_name'] = request.data['comp_name'] + data['comp_version'] = request.data['comp_version'] + + username = request.data['machine_owner'] + user = UserProfile.objects.filter(username=username).filter().first() + user_serializer = CreateUserProfileSerializer(user) + + data['machine_owner'] = user_serializer.data['id'] + + serializer = CreateUserMachineSerializer(data=data) + serializer.is_valid(raise_exception=True) + machine = self.perform_create(serializer) + + headers = self.get_success_headers(serializer.data) + + return Response('success', status=status.HTTP_201_CREATED, headers=headers) + + def perform_create(self, serializer): + return serializer.save() + class PublicMachineListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ diff --git a/web/apps/users/models.py b/web/apps/users/models.py index 35ed109..6db5ace 100644 --- a/web/apps/users/models.py +++ b/web/apps/users/models.py @@ -20,7 +20,7 @@ class UserProfile(AbstractUser): # first_name = None # last_name = None - # user_name = models.CharField(max_length=64, verbose_name="name") + username = models.CharField(max_length=64, unique=True, verbose_name="username") # user_email = models.EmailField(max_length=256, verbose_name="email") # add_time = models.DateTimeField(default=datetime.now, verbose_name="user added time") diff --git a/web/apps/users/serializer.py b/web/apps/users/serializer.py index 1ef3ae2..e1ba40a 100644 --- a/web/apps/users/serializer.py +++ b/web/apps/users/serializer.py @@ -14,6 +14,14 @@ class AliasSerializer(serializers.ModelSerializer): model = Alias fields = ('name', ) +class CreateUserProfileSerializer(serializers.ModelSerializer): + ''' + use CreateUserProfileSerializer + ''' + class Meta: + model = UserProfile + fields = "__all__" + class UserMachineSerializer(serializers.ModelSerializer): ''' use UserMachineSerializer |