组织-基本管理

This commit is contained in:
caishi 2021-01-28 11:48:21 +08:00
parent 6deb8db08f
commit f68842beff
21 changed files with 510 additions and 221 deletions

View File

@ -236,7 +236,6 @@ class App extends Component {
path="/register"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
@ -248,7 +247,7 @@ class App extends Component {
<Route path={"/organize"}
render={
(props) => {
return (<OrganizeIndex {...this.props} {...props} {...this.state} />)
return (<OrganizeIndex {...props} {...this.props} {...this.state} />)
}
}>
</Route>

View File

@ -1,10 +1,11 @@
import React from 'react';
import { getImageUrl } from 'educoder';
import './Component.scss';
export default (({img , title, desc , rightBtn})=>{
function Cards({img , title, desc , rightBtn}){
return(
<div className="cards">
<div className="img"><img src={img} alt=""/></div>
<div className="img"><img src={getImageUrl(`images/${img}`)} alt=""/></div>
<div className="content">
<p className="titles">
<span>{title}</span>
@ -16,4 +17,5 @@ export default (({img , title, desc , rightBtn})=>{
</div>
</div>
)
})
}
export default Cards;

View File

@ -27,6 +27,7 @@ li.ant-menu-item{
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
img{
max-width: 100%;
}
@ -39,6 +40,8 @@ li.ant-menu-item{
justify-content: space-between;
margin-bottom: 10px!important;
align-items: center;
height: 22px;
line-height: 22px;;
&>span{
font-size:18px ;
color: #333;
@ -50,6 +53,7 @@ li.ant-menu-item{
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
line-height: 20px;
}
}
}

View File

@ -5,6 +5,7 @@ const { Search } = Input;
export default ({ placeholder , onSearch }) => {
return (
<Search
allowClear
placeholder={placeholder}
enterButton={'搜索'}
onSearch={onSearch}

View File

@ -31,14 +31,18 @@ const Infos = Loadable({
loader: () => import("./users/Infos"),
loading: Loading,
});
class Index extends Component {
render() {
return (
<div className="newMain clearfix">
<Handbook />
<Switch {...this.props}>
<Route
path="/projects/:projectsType/new/:OIdentifier"
render={(props) => (
<ProjectNew {...this.props} {...props} />
)}
></Route>
<Route
path="/projects/:projectsType/new"
render={(props) => (

View File

@ -153,7 +153,7 @@ class MergeFooter extends Component {
}
{
filesData && filesData.files && filesData.files.length>0 &&
<TabPane tab={
<TabPane tab={
<span><span className="font-16">文件</span>
{filesCount > 0 && <span className="tabNum">{filesCount}</span>}
</span>

View File

@ -23,18 +23,22 @@ class Index extends Component {
LanguageList: undefined,
GitignoreList: undefined,
LicensesList: undefined,
OwnerList: undefined,
isSpin: false,
project_language_id: undefined,
project_category_id: undefined,
license_id: undefined,
ignore_id: undefined,
owners_id:undefined,
project_language_list: undefined,
project_category_list: undefined,
license_list: undefined,
ignore_list: undefined,
owners_list:undefined,
project_language_name: undefined,
project_category_name: undefined,
license_name: undefined,
@ -42,6 +46,8 @@ class Index extends Component {
}
}
componentDidMount = () => {
// 获取拥有者列表
this.getOwner();
// 获取项目类别
this.getCategory();
// 获取项目语言
@ -50,7 +56,6 @@ class Index extends Component {
this.getGitignore();
// 获取开源许可证
this.getLicenses();
}
componentDidUpdate=(prevPros)=>{
if(prevPros && this.props && !this.props.checkIfLogin()){
@ -58,6 +63,30 @@ class Index extends Component {
return
}
}
getOwner=()=>{
const { OIdentifier } = this.props.match.params;
const url = `/owners.json`;
axios.get(url).then(result=>{
if(result && result.data){
let owner = result.data.owners;
if(OIdentifier){
owner = owner.filter(item=>item.name === OIdentifier);
this.props.form.setFieldsValue({
user_id:OIdentifier
})
this.setState({
owners_id:owner && owner[0].id
})
}
this.setOptionsList(owner, 'owners');
this.setState({
OwnerList: owner,
})
}
}).catch(error=>{})
}
getCategory = () => {
const url = `/project_categories.json`
axios.get(url).then((result) => {
@ -131,8 +160,8 @@ class Index extends Component {
isSpin: true
})
const { current_user } = this.props;
const { projectsType } = this.props.match.params;
const { project_language_id, project_category_id, license_id, ignore_id } = this.state;
const { projectsType , OIdentifier } = this.props.match.params;
const { project_language_id, project_category_id, license_id, ignore_id , owners_id } = this.state;
const decoderPass = Base64.encode(values.password);
const url = projectsType === "deposit" ? "/projects.json" : "/projects/migrate.json";
axios.post(url, {
@ -142,7 +171,7 @@ class Index extends Component {
project_category_id,
license_id,
ignore_id,
user_id: current_user.user_id
user_id:owners_id
}).then((result) => {
if (result) {
if (result.data.id) {
@ -150,7 +179,7 @@ class Index extends Component {
isSpin: false
})
this.props.showNotification(`${projectsType === "deposit" ? "托管" : "镜像"}项目创建成功!`);
this.props.history.push(`/projects/${current_user && current_user.login}/${result.data.identifier}`);
this.props.history.push(`/projects/${OIdentifier ? OIdentifier :(current_user && current_user.login)}/${result.data.identifier}`);
}
}
}).catch((error) => {
@ -230,20 +259,13 @@ class Index extends Component {
const { projectsType } = this.props.match.params;
const {
preType,
languageValue,
gitignoreType,
LicensesType,
CategoryList,
LanguageList,
GitignoreList,
LicensesList,
isSpin,
project_language_name,
project_category_name,
license_name,
ignore_name,
owners_list,
OwnerList,
project_language_list,
project_category_list,
@ -259,6 +281,24 @@ class Index extends Component {
<Spin spinning={isSpin}>
<Form>
<div className="newPanel_content">
<Form.Item
label="拥有者"
>
{getFieldDecorator('user_id', {
rules: [{
required: true, message: '请选择拥有者'
}],
})(
<AutoComplete
placeholder="请选择拥有者"
onChange={(value, e) => this.ChangePlatform(value, e, 'owners', OwnerList)}
className="plateAutoComplete"
onBlur={(value) => this.blurCategory(value, OwnerList, "owners")}
>
{owners_list}
</AutoComplete>
)}
</Form.Item>
{
projectsType !== "deposit" &&
<React.Fragment>

View File

@ -4,7 +4,6 @@ import { getUploadActionUrl } from 'educoder';
function UploadImage({ getImage , url }){
const [ imageUrl , setImageUrl ] = useState(undefined);
useEffect(()=>{
if(url){
setImageUrl(url);

View File

@ -11,25 +11,33 @@ const Common = Loadable({
loader: () => import("./SettingCommon"),
loading: Loading,
});
const Member = Loadable({
loader: () => import("./Setting/GroupMemberSetting"),
loading: Loading,
});
const Project = Loadable({
loader: () => import("./Setting/GroupProjectSetting"),
loading: Loading,
});
export default (props)=>{
const pathname = props.location.pathname;
const organizeId = props.match.params.organizeId;
const memberId = props.match.params.memberId;
const OIdentifier = props.match.params.OIdentifier;
const groupId = props.match.params.groupId;
function returnActive (pathname){
let a = 0;
if(pathname === `/organize/${organizeId}/member/${memberId}/setting/member`){
if(pathname === `/organize/${OIdentifier}/group/${groupId}/setting/member`){
a = 1;
}else if(pathname === `/organize/${organizeId}/member/${memberId}/setting/project`){
}else if(pathname === `/organize/${OIdentifier}/group/${groupId}/setting/project`){
a = 2;
}
return a;
}
const active = returnActive(pathname);
const array = {list:[
{name:'基本设置',icon:"icon-base",href:`/organize/${organizeId}/member/${memberId}/setting`},
{name:'团队成员管理',icon:"icon-zuzhichengyuan",href:`/organize/${organizeId}/member/${memberId}/setting/member`},
{name:'团队项目管理',icon:"icon-zuzhixiangmu",href:`/organize/${organizeId}/member/${memberId}/setting/project`},
{name:'基本设置',icon:"icon-base",href:`/organize/${OIdentifier}/group/${groupId}/setting`},
{name:'团队成员管理',icon:"icon-zuzhichengyuan",href:`/organize/${OIdentifier}/group/${groupId}/setting/member`},
{name:'团队项目管理',icon:"icon-zuzhixiangmu",href:`/organize/${OIdentifier}/group/${groupId}/setting/project`},
],
active
}
@ -43,7 +51,19 @@ export default (props)=>{
<WhiteBack>
<Switch>
<Route
path="/organize/:organizeId/member/:memberId/setting"
path="/organize/:OIdentifier/group/:groupId/setting/project"
render={() => (
<Project {...props} />
)}
></Route>
<Route
path="/organize/:OIdentifier/group/:groupId/setting/member"
render={() => (
<Member {...props} />
)}
></Route>
<Route
path="/organize/:OIdentifier/group/:groupId/setting"
render={() => (
<Common {...props} />
)}

View File

@ -0,0 +1,9 @@
import React , { useState } from 'react';
function GroupMemberSetting() {
return(
<div>团队成员管理</div>
)
}
export default GroupMemberSetting;

View File

@ -0,0 +1,9 @@
import React , { useState } from 'react';
function GroupProjectSetting() {
return(
<div>团队项目管理</div>
)
}
export default GroupProjectSetting;

View File

@ -3,7 +3,7 @@ import React from 'react';
import { Route, Switch } from "react-router-dom";
import Loadable from "react-loadable";
import Loading from "../../Loading";
import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
@ -23,43 +23,41 @@ const SubDetail = Loadable({
loader: () => import("./Sub/SubDetail"),
loading: Loading,
});
export default CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
export default withRouter(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
((props)=>{
return (
<div className="newMain">
<Switch {...props}>
<Switch>
{/* 组织团队 */}
<Route
path="/organize/:organizeId/group"
render={(props) => {
return <SubDetail {...props} />
path="/organize/:OIdentifier/group"
render={(p) => {
return <SubDetail {...props} {...p}/>
}}
></Route>
{/* 组织成员 */}
<Route
path="/organize/:organizeId/member/:memberId/setting"
render={(props) => {
return <DetailIndex {...props} />
}}
></Route>
<Route
path="/organize/:organizeId/member"
render={(props) => {
return <SubDetail {...props} />
path="/organize/:OIdentifier/member"
render={(p) => {
return <SubDetail {...props} {...p}/>
}}
></Route>
{/* 新建组织 */}
<Route
path="/organize/new"
render={(props) => {
return <New {...props} />
render={(p) => {
return <New {...props} {...p}/>
}}
></Route>
{/* 组织详情(包含组织设置) */}
<Route
path="/organize/:organizeId"
render={(props) => {
return <DetailIndex {...props} />
}}
path="/organize/:OIdentifier"
render={(p) => (
<DetailIndex {...props} {...p}/>
)}
></Route>
</Switch>
</div>
)
})
)))
))))

View File

@ -47,6 +47,7 @@
background-color: #fff;
max-width: 860px;
width: 72%;
margin-bottom: 30px;
.head{
padding:16px 32px;
border-bottom: 1px solid #eee;
@ -102,6 +103,7 @@
max-width: 340px;
padding-left: 20px;
box-sizing: border-box;
margin-bottom: 30px;
}
.box{
background:rgba(255,255,255,1);

View File

@ -1,124 +1,110 @@
import React from 'react';
import { Button } from 'antd';
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import Search from '../Component/Search';
import Sort from '../Component/Sort';
import ListCount from '../Component/ListCount';
import Box from './Box';
import './Index.scss';
import styled from 'styled-components';
import Item from './ListItem';
import Right from './RightBox';
import NoData from '../Nodata';
import { Menu } from 'antd';
import { Menu , Pagination , Dropdown , Spin } from 'antd';
import axios from 'axios';
const Span = styled.span`{
color:#888;
font-size:12px;
margin-right:10px;
}`
const Align = styled.div`{
display:flex;
aligin:center;
}`
const ListName = styled.div`{
font-size:14px;
color:#333;
margin-bottom:8px;
height:18px;
line-height:18px;
}`;
const ColorListName = styled.div`{
color:#5091FF;
font-size:14px;
margin-bottom:8px;
height:18px;
line-height:18px;
}`
const Img = styled.img`{
border-radius:50%;
width:45px;
height:45px;
margin-right:12px;
}`
export default (()=>{
function onSearch(value){
const limit = 15;
function List(props){
const [ list , setList ] = useState(undefined);
const [ isSpin , setIsSpin ] = useState(false);
const [ totalCount , setTotalCount ] = useState(undefined);
const [ search , setSearch ] = useState(undefined);
const [ page , setPage ] = useState(1);
const [ sortBy , setSortBy ] = useState("updated_on");
const [ sortDirection , setSortDirection ] = useState("asc");
const OIdentifier = props.match.params.OIdentifier;
useEffect(()=>{
if(OIdentifier){
setIsSpin(true);
getProject();
}
},[OIdentifier,sortBy,page,search])
function getProject(){
const url = `/organizations/${OIdentifier}/projects.json`;
axios.get(url,{
params:{
search,page,limit,
sort_by:sortBy,
sort_direction:sortDirection
}
}).then(result=>{
if(result && result.data){
setList(result.data.projects);
setTotalCount(result.data.total_count);
}
setIsSpin(false);
}).catch(error=>{setIsSpin(false);})
}
function onSearch(value){
setSearch(value);
}
const menu=(
<Menu>
<Menu onClick={(e)=>setSortBy(e.key)}>
<Menu.Item key="updated_on">更新时间排序</Menu.Item>
<Menu.Item key="created_on">项目数排序</Menu.Item>
<Menu.Item key="created_on">创建时间排序</Menu.Item>
<Menu.Item key="praises_count">点赞数排序</Menu.Item>
<Menu.Item key="forked_count">fork数排序</Menu.Item>
</Menu>
)
const menu_new=(
<Menu>
<Menu.Item key="updated_on">新建托管项目</Menu.Item>
<Menu.Item key="created_on">新建镜像项目</Menu.Item>
<Menu.Item key="updated_on"><Link to={`/projects/deposit/new/${OIdentifier}`}>新建托管项目</Link></Menu.Item>
<Menu.Item key="created_on"><Link to={`/projects/mirror/new/${OIdentifier}`}>新建镜像项目</Link></Menu.Item>
</Menu>
)
const leftList = (
<div className="team_project">
<p className="t_p_title">
<span className="flex1">
<span className="name">react项目react项目react项目react项目</span>
<i className="iconfont icon-banbenku font-20 color-green" />
<i className="iconfont icon-jingxiang font-18 color-green" />
<i className="iconfont icon-fork font-18 color-orange" />
</span>
<ListCount fork={1} parise={0}/>
</p>
<div className="desc">
用于构建用户界面的 JavaScript
</div>
<div className="infos">
<span className="font-12 color-grey-8">更新于1天前</span>
</div>
</div>
)
return(
<div className="list">
<div className="list-l">
<div className="head">
<div style={{width:"370px"}}>
<Search placeholder="输入仓库名称进行搜索" onSearch={onSearch}/>
</div>
<p>
<Sort menu={menu_new}>
<a className="addBtn mr30">+&nbsp;新建项目</a>
</Sort>
<Sort menu={menu}>
<a className="color-blue">排序<i className="iconfont icon-sanjiaoxing-down ml3 font-14"></i></a>
</Sort>
</p>
</div>
<div className="team">
{leftList}
</div>
</div>
<div className="list-r">
<Box name="组织成员" count={8}>
<div className="teammembers">
<Img src="https://dss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1990625098,3468619056&fm=111&gp=0.jpg" alt="" className="m-img"/>
<div>
<ListName>陈Professer</ListName>
<Align><i className="iconfont icon-shijian color-green mr3 font-13"></i><Span>加入时间2020-04-28</Span></Align>
<div className="list-l">
<div>
<div className="head">
<div style={{width:"370px"}}>
<Search placeholder="输入仓库名称进行搜索" onSearch={onSearch}/>
</div>
<p>
<Sort menu={menu_new}>
<a className="addBtn mr30">+&nbsp;新建项目</a>
</Sort>
<Dropdown overlay={menu}>
<a className="color-blue">排序<i className="iconfont icon-sanjiaoxing-down ml3 font-14"></i></a>
</Dropdown>
</p>
</div>
<Spin spinning={isSpin}>
<div className="team">
{
list && list.length>0 ? list.map((item,key)=>{
return(
<Item item={item} keu={key} OIdentifier={OIdentifier}/>
)
})
:
<NoData _html="暂无数据"/>
}
</div>
</Spin>
</div>
</Box>
<Box
name="组织团队"
count={3}
bottom={<Button type={'primary'} to={``}>新建团队</Button>}
>
<div className="teammembers">
<div>
<ColorListName>陈Professer</ColorListName>
<Align>
<Span>2名成员</Span>
<Span>1个仓库</Span>
</Align>
{
totalCount > limit &&
<div className="mb20 mt20" style={{textAlign:"center"}}>
<Pagination simple current={page} total={totalCount} onChange={(page)=>setPage(page)}/>
</div>
</div>
</Box>
</div>
}
</div>
<Right OIdentifier={OIdentifier}/>
</div>
)
})
}
export default List;

View File

@ -0,0 +1,25 @@
import React from 'react';
import ListCount from '../Component/ListCount';
import { Link } from 'react-router-dom';
function ListItem({item,key,OIdentifier}) {
return(
<div className="team_project" key={key}>
<p className="t_p_title">
<span className="flex1">
<Link to={`/projects/${OIdentifier}/${item.identifier}`} className="name">{item.identifier}</Link>
<i className="iconfont icon-banbenku font-20 color-green ml8" />
<i className="iconfont icon-jingxiang font-18 color-green ml8" />
<i className="iconfont icon-fork font-18 color-orange ml8" />
</span>
<ListCount fork={item.forked_count} parise={item.praises_count}/>
</p>
<div className="desc">
{item.description}
</div>
<div className="infos">
<span className="font-12 color-grey-8">更新于{item.time_ago}</span>
</div>
</div>
)
}
export default ListItem;

View File

@ -1,14 +1,13 @@
import React,{ forwardRef , useCallback, useEffect, useState } from 'react';
import React,{ forwardRef , useCallback , useState } from 'react';
import './Index.scss';
import { Form , Input , Radio , Checkbox , Button, InputNumber } from "antd";
import UploadImage from './Component/UploadImage';
import axios from 'axios';
export default Form.create()(
forwardRef(({form , showNotification ,history})=>{
forwardRef(({ form , showNotification , history })=>{
const [ image , setImage ] = useState(undefined);
const { getFieldDecorator, validateFields , setFieldsValue } = form;
const { getFieldDecorator, validateFields } = form;
const radioStyle = {
display: 'block',
@ -42,6 +41,7 @@ export default Form.create()(
}).then(result=>{
if(result && result.data){
showNotification("组织创建成功!");
history.push(`/organize/${result.data.name}`);
}
}).catch(error=>{})
}

113
src/forge/Team/RightBox.jsx Normal file
View File

@ -0,0 +1,113 @@
import React , { useEffect , useState } from 'react';
import { Button } from 'antd';
import styled from 'styled-components';
import Box from './Box';
import axios from 'axios';
import { getImageUrl } from 'educoder';
const Span = styled.span`{
color:#888;
font-size:12px;
margin-right:10px;
}`
const Align = styled.div`{
display:flex;
aligin:center;
}`
const ListName = styled.div`{
font-size:14px;
color:#333;
margin-bottom:8px;
height:18px;
line-height:18px;
}`;
const ColorListName = styled.div`{
color:#5091FF;
font-size:14px;
margin-bottom:8px;
height:18px;
line-height:18px;
}`
const Img = styled.img`{
border-radius:50%;
width:45px;
height:45px;
margin-right:12px;
}`
function RightBox({ OIdentifier }) {
const [ memberData, setMemberData ] = useState(undefined);
const [ groupData, setGroupData ] = useState(undefined);
useEffect(()=>{
if(OIdentifier){
getMember(OIdentifier);
getGroup(OIdentifier);
}
},[OIdentifier])
function getMember(iden){
const url = `/organizations/${iden}/organization_users.json`;
axios.get(url).then(result=>{
if(result && result.data){
setMemberData(result.data);
}
}).catch(error=>{})
}
function getGroup(iden){
const url = `/organizations/${iden}/teams.json`;
axios.get(url).then(result=>{
if(result && result.data){
setGroupData(result.data);
}
}).catch(error=>{})
}
return(
<div className="list-r">
{
memberData && memberData.organization_users && memberData.organization_users.length>0 ?
<Box name="组织成员" count={memberData && memberData.total_count}>
{
memberData.organization_users.map((item,key)=>{
return(
<div className="teammembers" key={key}>
<Img src={getImageUrl(`images/${item.user && item.user.image_url}`)} alt="" className="m-img"/>
<div>
<ListName>{item.user && item.user.name}</ListName>
<Align><i className="iconfont icon-shijian color-green mr3 font-13"></i><Span>加入时间{item.created_at}</Span></Align>
</div>
</div>
)
})
}
</Box>
:""
}
{
groupData && groupData.teams && groupData.teams.length>0?
<Box
name="组织团队"
count={groupData && groupData.total_count}
bottom={<Button type={'primary'} to={``}>新建团队</Button>}
>
{
groupData.teams.map((item,key)=>{
return(
<div className="teammembers" key={key}>
<div>
<ColorListName>{item.name}</ColorListName>
<Align>
<Span>{item.num_users}名成员</Span>
<Span>{item.num_projects}个仓库</Span>
</Align>
</div>
</div>
)
})
}
</Box>
:""
}
</div>
)
}
export default RightBox;

View File

@ -1,9 +1,11 @@
import React, { forwardRef , useCallback } from 'react';
import { Form , Input , Cascader , Radio ,Checkbox , Divider , Button } from 'antd';
import React, { forwardRef , useCallback , useEffect, useState } from 'react';
import { Form , Input , Radio ,Checkbox , Divider , Button } from 'antd';
import { WhiteBack , FlexAJ } from '../../Component/layout';
import Title from '../../Component/Title';
import styled from 'styled-components';
import { locData } from "../../Utils/locData";
import UploadImage from '../Component/UploadImage';
import axios from 'axios';
import { getImageUrl } from 'educoder';
const TextArea = Input.TextArea;
const Div = styled.div`{
@ -15,19 +17,58 @@ const radioStyle = {
lineHeight: '30px',
};
export default Form.create()(
forwardRef(({ form })=>{
const { getFieldDecorator } = form;
forwardRef(({ form , organizeDetail , showNotification , history })=>{
const [ image , setImage ] = useState(undefined);
const [ imageFlag , setImageFlag ] = useState(false);
const [ password , setPassword ] = useState(undefined);
const { getFieldDecorator , validateFields, setFieldsValue} = form;
useEffect(()=>{
if(organizeDetail){
setFieldsValue({
...organizeDetail
})
setImage(organizeDetail.avatar_url);
}
},[organizeDetail])
const helper = useCallback(
(label, name, rules, widget , isRequired ) => (
(label, name, rules, widget , isRequired , flag ) => (
<div>
<span className={isRequired?"required":""}>{label}</span>
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
{getFieldDecorator(name, { rules, validateFirst: true , valuePropName:flag ? "checked":"value" })(widget)}
</Form.Item>
</div>
),
[]
);
//
function updateDetail(){
validateFields((error,values)=>{
if(!error){
const url = `/organizations/${organizeDetail.id}.json`;
axios.patch(url,{
...values,image:imageFlag ? image : undefined
}).then(result=>{
if(result && result.data){
showNotification("组织信息更新成功!");
history.push(`/organize/${values.name}/setting`);
}
}).catch(error=>{})
}
})
}
function getImage(image){
setImageFlag(true);
setImage(image);
}
//
function deleteOrganize(){
}
return(
<div>
<WhiteBack>
@ -42,46 +83,48 @@ export default Form.create()(
)}
{helper(
"组织描述:",
"desc",
"description",
[],
<TextArea placeholder="请输入组织名称" />
)}
{helper(
"官方网站:",
"web",
"website",
[],
<Input placeholder="请输入官方网站" />
)}
{helper(
'所在地区:',
"area",
"location",
[],
<Cascader placeholder="请选择城市" options={locData}/>
<Input placeholder="请输入城市"/>
)}
{helper(
'可见性:',
"opacity",
"visibility",
[],
<Radio.Group>
<Radio value="0" style={radioStyle}>公开</Radio>
<Radio value="0" style={radioStyle}>受限<span>仅对登录用户可见</span></Radio>
<Radio value="0" style={radioStyle}>私有<span>仅对组织成员可见</span></Radio>
<Radio value="common" style={radioStyle}>公开</Radio>
<Radio value="limited" style={radioStyle}>受限<span>仅对登录用户可见</span></Radio>
<Radio value="privacy" style={radioStyle}>公开<span>仅对组织成员可见</span></Radio>
</Radio.Group>
)}
{helper(
'权限:',
"operation",
"repo_admin_change_team_access",
[],
<Checkbox value="0" style={radioStyle}>仓库管理员可以添加或移除团队的访问权限</Checkbox>
<Checkbox style={radioStyle}>仓库管理员可以添加或移除团队的访问权限</Checkbox>,false,true
)}
<Divider/>
{helper(
'最大仓库数:',
"number",
"max_repo_creation",
[],
<Input value="-1" style={{width:"350px"}}/>
)}
<Button type={"primary"}>更新仓库设置</Button>
<p>选择头像:</p>
<UploadImage url={getImageUrl(`images/${image}`)} getImage={getImage}/>
<Button type={"primary"} onClick={updateDetail}>更新仓库设置</Button>
</Form>
</Div>
</WhiteBack>
@ -93,9 +136,9 @@ export default Form.create()(
<FlexAJ>
<div>
<span className="required">密码</span>
<Input type="password" style={{width:"350px"}} />
<Input type="password" style={{width:"350px"}} value={password} onChange={(e)=>setPassword(e.target.value)}/>
</div>
<a className="warningDelete">删除组织</a>
<a className="warningDelete" onClick={deleteOrganize}>删除组织</a>
</FlexAJ>
</div>
</div>

View File

@ -26,25 +26,25 @@ const Hooks = Loadable({
});
export default (( props )=>{
const pathname = props.location.pathname;
const organizeId = props.match.params.organizeId;
const OIdentifier = props.match.params.OIdentifier;
function returnActive (pathname){
let a = 0;
if(pathname === `/organize/${organizeId}/setting/member`){
if(pathname === `/organize/${OIdentifier}/setting/member`){
a = 1;
}else if(pathname === `/organize/${organizeId}/setting/group`){
}else if(pathname === `/organize/${OIdentifier}/setting/group`){
a = 2;
}else if(pathname === `/organize/${organizeId}/setting/hooks`){
}else if(pathname === `/organize/${OIdentifier}/setting/hooks`){
a = 3;
}
return a;
}
const active = returnActive(pathname);
const array = {list:[
{name:'基本设置',icon:"icon-base",href:`/organize/${organizeId}/setting`},
{name:'组织成员管理',icon:"icon-zuzhichengyuan",href:`/organize/${organizeId}/setting/member`},
{name:'组织团队管理',icon:"icon-zuzhixiangmu",href:`/organize/${organizeId}/setting/group`},
{name:'管理web钩子',icon:"icon-zhongqingdianxinicon10",href:`/organize/${organizeId}/setting/hooks`}
{name:'基本设置',icon:"icon-base",href:`/organize/${OIdentifier}/setting`},
{name:'组织成员管理',icon:"icon-zuzhichengyuan",href:`/organize/${OIdentifier}/setting/member`},
{name:'组织团队管理',icon:"icon-zuzhixiangmu",href:`/organize/${OIdentifier}/setting/group`},
{name:'管理web钩子',icon:"icon-zhongqingdianxinicon10",href:`/organize/${OIdentifier}/setting/hooks`}
],
active
}
@ -57,25 +57,25 @@ export default (( props )=>{
<Gap>
<Switch>
<Route
path="/organize/:organizeId/setting/hooks"
path="/organize/:OIdentifier/setting/hooks"
render={() => (
<Hooks {...props} />
)}
></Route>
<Route
path="/organize/:organizeId/setting/group"
path="/organize/:OIdentifier/setting/group"
render={() => (
<Group {...props} />
)}
></Route>
<Route
path="/organize/:organizeId/setting/member"
path="/organize/:OIdentifier/setting/member"
render={() => (
<Member {...props} />
)}
></Route>
<Route
path="/organize/:organizeId/setting"
path="/organize/:OIdentifier/setting"
render={() => (
<Common {...props} />
)}

View File

@ -1,10 +1,10 @@
import React , { useEffect , useState } from 'react';
import { Route, Switch } from "react-router-dom";
import { Route, Switch , Link } from "react-router-dom";
import Loadable from "react-loadable";
import Loading from "../../../Loading";
import {AlignCenter} from '../../Component/layout';
import Cards from '../../Component/Cards';
import axios from 'axios';
import '../Index.scss';
const DetailIndex = Loadable({
@ -15,39 +15,59 @@ const Setting = Loadable({
loader: () => import("../Setting/TeamSettingIndex"),
loading: Loading,
});
const GroupSetting = Loadable({
loader: () => import("../Group/GroupDetailSetting"),
loading: Loading,
});
export default ((props)=>{
function Detail(props){
const OIdentifier = props.match.params.OIdentifier;
const pathname = props.location.pathname;
const [ detail , setDetail ] = useState(undefined);
const [ flag , setFlag ] = useState(true);
//
useEffect(()=>{
if(pathname){
if(pathname.indexOf("/setting") && pathname.indexOf("/organize")){
setFlag(false);
}
}
},[pathname])
useEffect(()=>{
if(OIdentifier){
getDetail(OIdentifier);
}
},[OIdentifier]);
function getDetail(id) {
const url = `/organizations/${id}.json`;
axios.get(url).then(result=>{
if(result && result.data){
setDetail(result.data);
}
}).catch(error=>{})
}
return(
<div className="teamDetail">
<Cards
title="组织名称"
desc="组织名称组织名称组织名称组织名称组织名称"
rightBtn={<a className="color-blue">设置<i className="iconfont icon-shezhi2 ml3"></i></a>}
img={`https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=4193840146,2109186388&fm=26&gp=0.jpg`}
title={detail && detail.name}
desc={detail && detail.description}
img={detail && detail.avatar_url}
rightBtn={flag && <AlignCenter className="color-blue"><Link to={`/organize/${OIdentifier}/setting`} className="color-blue">设置</Link><i className="iconfont icon-shezhi2 ml3"></i></AlignCenter>}
/>
<Switch {...props}>
<Route
path="/organize/:organizeId/member/:memberId/setting"
render={() => {
return <GroupSetting {...props} />
path="/organize/:OIdentifier/setting"
render={(p) => {
return <Setting {...props} {...p} organizeDetail={detail} />
}}
></Route>
<Route
path="/organize/:organizeId/setting"
render={() => {
return <Setting {...props} />
}}
></Route>
<Route
path="/organize/:organizeId"
render={() => {
return <DetailIndex {...props} />
path="/organize/:OIdentifier"
render={(p) => {
return <DetailIndex {...props} {...p}/>
}}
></Route>
</Switch>
</div>
)
})
}
export default Detail;

View File

@ -22,6 +22,10 @@ const GroupDetails = Loadable({
loader: () => import("../Group/GroupDetails"),
loading: Loading,
});
const GroupSetting = Loadable({
loader: () => import("../Group/GroupDetailSetting"),
loading: Loading,
});
export default ((props)=>{
return(
@ -37,26 +41,37 @@ export default ((props)=>{
img={`https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=4193840146,2109186388&fm=26&gp=0.jpg`}
/>
<Switch {...props}>
{/* 组织团队-设置 */}
<Route
path="/organize/:organizeId/member/:memberId"
path="/organize/:OIdentifier/group/:groupId/setting"
render={(props) => {
return <GroupSetting {...props} />
}}
></Route>
{/* 组织团队-成员 */}
<Route
path="/organize/:OIdentifier/group/:groupId/member"
render={(props) => {
return <GroupDetails {...props} />
}}
></Route>
{/* 组织成员 */}
<Route
path="/organize/:organizeId/member"
path="/organize/:OIdentifier/member"
render={(props) => {
return <Member {...props} />
}}
></Route>
{/* 组织-新建团队 */}
<Route
path="/organize/:organizeId/group/new"
path="/organize/:OIdentifier/group/new"
render={(props) => {
return <GroupNew {...props} />
}}
></Route>
{/* 组织团队 */}
<Route
path="/organize/:organizeId/group"
path="/organize/:OIdentifier/group"
render={(props) => {
return <Group {...props} />
}}