Merge branch 'rapper'

pull/103/head
bigfengyu 5 years ago
commit b7fd129521

@ -62,7 +62,8 @@ export interface IConfig {
key: string
}
}
export interface Repository {
export interface RepositoryFormData {
id: number
name: string
@ -95,6 +96,41 @@ export interface Repository {
collaboratorIdstring?: string
}
export interface Repository {
id: number
name: string
description: string
logo: string
/** true: 公开, false: 私有 */
visibility: boolean
creatorId: number
ownerId: number
organizationId: number
organization: Organization
memberIds: number[]
members: User[]
token: string
owner: User
collaborators: Repository[]
modules: Module[]
collaboratorIds: string[]
}
export interface Module {
id: number
@ -108,6 +144,8 @@ export interface Module {
priority: number
interfaces?: Interface[]
repository?: Repository
repositoryId?: number
@ -136,5 +174,28 @@ export interface Interface {
repository?: Repository
properties?: Property[]
status?: number
}
export type Property = {
name: string;
type: any;
rule: string;
value: any;
descripton: string;
creator: any;
repositoryId: number;
moduleId: number;
interfaceId: number;
scope: string;
parentId: number;
memory: boolean;
id: number;
}
export type Async<T> = {
data: T
fetching: boolean
}

@ -0,0 +1,197 @@
import React, { useState } from 'react'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import Dialog from '@material-ui/core/Dialog'
import TextField from '@material-ui/core/TextField'
import config from '../../config'
import AppBar from '@material-ui/core/AppBar'
import Toolbar from '@material-ui/core/Toolbar'
import IconButton from '@material-ui/core/IconButton'
import Typography from '@material-ui/core/Typography'
import CloseIcon from '@material-ui/icons/Close'
import Slide from '@material-ui/core/Slide'
import { TransitionProps } from '@material-ui/core/transitions'
import { DialogContent } from '@material-ui/core'
import Radio from '@material-ui/core/Radio'
import RadioGroup from '@material-ui/core/RadioGroup'
import FormControlLabel from '@material-ui/core/FormControlLabel'
import FormLabel from '@material-ui/core/FormLabel'
import { Repository } from 'actions/types'
type RapperType = 'normal' | 'redux'
const Transition = React.forwardRef<unknown, TransitionProps>((props, ref) => {
return <Slide direction="up" ref={ref} {...props} />
})
const codeTmpl = ({ projectId, token, rapperType, rapperPath }: {
projectId: number
token: string
rapperType: RapperType
rapperPath: string
}) => {
const apiUrl = `${config.serve}/repository/get?id=${projectId}&token=${token}`
const rapUrl = window.location.origin
return String.raw`"rapper": "rapper --type ${rapperType} --rapperPath \"${rapperPath}\" --apiUrl \"${apiUrl}\" --rapUrl \"${rapUrl}\""`
}
const useReadmeStyles = makeStyles({
root: {
'&': {
fontSize: 16,
},
},
})
function Readme() {
const classes = useReadmeStyles()
return (
<div className={classes.root}>
<p style={{ textAlign: 'center' }}>
<a href="https://github.com/thx/rapper" target="_blank" rel="noopener noreferrer">
<img src="https://img.alicdn.com/tfs/TB1SlW9lQT2gK0jSZPcXXcKkpXa-1138-220.png" alt="Logo" width="250" />
</a>
<h3></h3>
<p>
<a href="https://www.yuque.com/rap/rapper/readme" target="_blank" rel="noopener noreferrer"></a>
</p>
</p>
<h2>Rapper </h2>
<p>Rapper TypeScript </p>
<ul>
<li> HTTP </li>
<li>/</li>
<li> React/Redux hooks 使</li>
</ul>
<p><a href="https://www.yuque.com/rap/rapper/readme" target="_blank" rel="noopener noreferrer"></a></p>
<p>使21912534</p>
{/* <div style={{ textAlign: 'center' }}> */}
<img src="https://img.alicdn.com/tfs/TB1mLzfnF67gK0jSZPfXXahhFXa-828-1068.png" alt="dingtalk" width="200" />
{/* </div> */}
<h2></h2>
</div>
)
}
const useStyles = makeStyles(({ spacing }: Theme) =>
createStyles({
appBar: {
position: 'relative',
},
title: {
marginLeft: spacing(2),
flex: 1,
},
btn: {
marginBottom: spacing(2),
marginTop: spacing(2),
},
content: {
padding: '30px 15vw 40vh 15vw',
},
formControl: {
margin: 0,
},
formItem: {
marginBottom: 16,
},
formLabel: {
fontSize: 16,
marginBottom: 5,
},
step: {
fontSize: 16,
marginBottom: 10,
},
mode: {
fontSize: 12,
marginLeft: 10,
},
})
)
function RapperInstallerModal({
open,
handleClose,
repository,
}: {
open: boolean;
handleClose: () => void;
repository: Repository;
}) {
const classes = useStyles()
/** rapper 类型 normal redux */
const [rapperType, setRapperType] = useState<RapperType>('normal')
/** rapper 生成目录地址 */
const [rapperPath, setRapperPath] = useState<string>('src/rapper')
function handleRapperTypeChange(_event: React.ChangeEvent<HTMLInputElement>, value: RapperType) {
setRapperType(value)
}
return (
<Dialog
fullScreen={true}
open={open}
onClose={handleClose}
TransitionComponent={Transition}
>
<AppBar className={classes.appBar}>
<Toolbar>
<IconButton
edge="start"
color="inherit"
onClick={handleClose}
aria-label="close"
>
<CloseIcon />
</IconButton>
<Typography variant="h6" className={classes.title}>
Rapper
</Typography>
</Toolbar>
</AppBar>
<DialogContent className={classes.content}>
<Readme />
<div className={classes.formItem}>
<FormLabel component="legend" className={classes.formLabel}>
<a href="https://www.yuque.com/rap/rapper/which-model" className={classes.mode} target="_blank" rel="noopener noreferrer"></a>
</FormLabel>
<RadioGroup aria-label="rapperType" row={true} name="rapperType" value={rapperType} onChange={handleRapperTypeChange}>
<FormControlLabel value="normal" control={<Radio />} label="基础模式" />
<FormControlLabel value="redux" control={<Radio />} label="React + Redux 进阶模式" />
</RadioGroup>
</div>
<div className={classes.formItem}>
<FormLabel component="legend" className={classes.formLabel}>Rapper </FormLabel>
<TextField
placeholder="src/rapper"
fullWidth={true}
margin="normal"
variant="outlined"
value={rapperPath}
onChange={(event) => setRapperPath(event.target.value)}
/>
</div>
<p className={classes.step}>1. rapper </p>
<pre>npm install rap --save-dev</pre>
<p className={classes.step}>2. package.json scripts </p>
<pre>
{codeTmpl({ projectId: repository.id, token: repository.token, rapperType, rapperPath })}
</pre>
<p className={classes.step}>3. rapper </p>
<pre>
npm run rapper
</pre>
<p className={classes.step}>4. <a href="https://www.yuque.com/rap/rapper/use" target="_blank" rel="noopener noreferrer">使</a></p>
</DialogContent>
</Dialog>
)
}
export default RapperInstallerModal

@ -8,6 +8,8 @@ import ModuleList from './ModuleList'
import InterfaceList from './InterfaceList'
import InterfaceEditor from './InterfaceEditor'
import DuplicatedInterfacesWarning from './DuplicatedInterfacesWarning'
import RapperInstallerModal from './RapperInstallerModal'
import {
addRepository,
updateRepository,
@ -41,12 +43,13 @@ import {
GoJersey,
GoLinkExternal,
GoPencil,
GoCode,
GoEllipsis
} from 'react-icons/go'
import './RepositoryEditor.css'
import ExportPostmanForm from '../repository/ExportPostmanForm'
import { RootState } from 'actions/types'
import { RootState, Repository, Module, Interface } from 'actions/types'
import DefaultValueModal from './DefaultValueModal'
// DONE 2.1 import Spin from '../utils/Spin'
@ -65,6 +68,7 @@ interface Props {
}
interface States {
rapperInstallerModalOpen: boolean
defaultValuesModalOpen: boolean
update: boolean
exportPostman: boolean
@ -102,6 +106,7 @@ class RepositoryEditor extends Component<Props, States> {
this.state = {
update: false,
exportPostman: false,
rapperInstallerModalOpen: false,
defaultValuesModalOpen: false,
}
}
@ -120,29 +125,30 @@ class RepositoryEditor extends Component<Props, States> {
location: { params },
auth,
} = this.props
let { repository } = this.props
if (!repository.fetching && !repository.data) {
const { repository: repositoryAsync } = this.props
const idStr = auth.id.toString()
if (!repositoryAsync.fetching && !repositoryAsync.data) {
return <div className="p100 fontsize-30 text-center"></div>
}
if (repository.fetching || !repository.data || !repository.data.id) {
if (repositoryAsync.fetching || !repositoryAsync.data || !repositoryAsync.data.id) {
return <Spin />
}
repository = repository.data
const repository: Repository = repositoryAsync.data
if (repository.name) {
document.title = `RAP2 ${repository.name}`
}
const mod =
const mod: Module =
repository && repository.modules && repository.modules.length
? repository.modules.find((item: any) => item.id === +params.mod) ||
repository.modules[0]
: {}
const itf =
? repository.modules.find(item => item.id === +params.mod) ||
repository.modules[0]
: {} as Module
const itf: Interface =
mod.interfaces && mod.interfaces.length
? mod.interfaces.find((item: any) => item.id === +params.itf) ||
mod.interfaces[0]
: {}
mod.interfaces[0]
: {} as Interface
const properties = itf.properties || []
const ownerlink = repository.organization
@ -150,7 +156,7 @@ class RepositoryEditor extends Component<Props, States> {
: `/repository/joined?user=${repository.owner.id}`
const isOwned = repository.owner.id === auth.id
const isJoined = repository.members.find(
const isJoined = repository.members && repository.members.find(
(item: any) => item.id === auth.id
)
@ -196,7 +202,7 @@ class RepositoryEditor extends Component<Props, States> {
<GoPlug />
</a>
<a
href={`${serve}/repository/get?id=${repository.id}`}
href={`${serve}/repository/get?id=${repository.id}&token=${repository.token}`}
target="_blank"
rel="noopener noreferrer"
className="api"
@ -235,6 +241,18 @@ class RepositoryEditor extends Component<Props, States> {
handleClose={() => this.setState({ defaultValuesModalOpen: false })}
repositoryId={repository.id}
/>
<span
className="fake-link edit"
style={{color: '#f95e49'}}
onClick={() => this.setState({ rapperInstallerModalOpen: true })}
>
<GoCode /> TS
</span>
<RapperInstallerModal
open={this.state.rapperInstallerModalOpen}
handleClose={() => this.setState({ rapperInstallerModalOpen: false })}
repository={repository}
/>
</div>
<RepositorySearcher repository={repository} />
<div className="desc">{repository.description}</div>
@ -261,7 +279,7 @@ class RepositoryEditor extends Component<Props, States> {
/>
</div>
</div>
</article>
</article >
)
}
handleUpdate = () => {

@ -7,7 +7,7 @@ import * as Yup from 'yup'
import { Button, Theme, Dialog, Slide, DialogContent, DialogTitle } from '@material-ui/core'
import { makeStyles } from '@material-ui/styles'
import { TransitionProps } from '@material-ui/core/transitions/transition'
import { Repository, RootState } from '../../actions/types'
import { RepositoryFormData, RootState, Repository } from '../../actions/types'
import UserList from '../common/UserList'
import AccountService from '../../relatives/services/Account'
import * as _ from 'lodash'
@ -43,12 +43,12 @@ const useStyles = makeStyles(({ spacing }: Theme) => ({
},
}))
const schema = Yup.object().shape<Partial<Repository>>({
const schema = Yup.object().shape<Partial<RepositoryFormData>>({
name: Yup.string().required(YUP_MSG.REQUIRED).max(20, YUP_MSG.MAX_LENGTH(20)),
description: Yup.string().max(1000, YUP_MSG.MAX_LENGTH(1000)),
})
const FORM_STATE_INIT: Repository = {
const FORM_STATE_INIT: RepositoryFormData = {
id: 0,
name: '',
description: '',
@ -70,7 +70,8 @@ interface Props {
}
function RepositoryForm(props: Props) {
const { open, onClose, repository, title, organizationId } = props
const { open, onClose, title, organizationId } = props
const repository = props.repository as RepositoryFormData
if (repository) {
repository.collaboratorIdstring = repository.collaborators!.map(x => { return x.id }).join(',')
}
@ -96,7 +97,7 @@ function RepositoryForm(props: Props) {
validationSchema={schema}
onSubmit={(values) => {
const addOrUpdateRepository = values.id ? updateRepository : addRepository
const repository: Repository = {
const repository: RepositoryFormData = {
...values,
memberIds: (values.members || []).map(
(user: any) => user.id

@ -2,6 +2,7 @@ import { call, put, select } from 'redux-saga/effects'
import * as RepositoryAction from '../../actions/repository'
import RepositoryService from '../services/Repository'
import { RootState } from 'actions/types'
import { StoreStateRouterLocationURI } from 'family/index'
import { IFetchDefaultValsAction, fetchDefaultValsFailed, IUpdateDefaultValsAction } from '../../actions/repository'
//
@ -72,7 +73,10 @@ export function* importRepository(action: any) {
export function* fetchRepository(action: any) {
try {
const count = yield call(RepositoryService.fetchRepository, action.repository || action.id)
const router = yield select((state: RootState) => state.router)
const uri = StoreStateRouterLocationURI(router)
const params = uri.search(true)
const count = yield call(RepositoryService.fetchRepository, action.repository || action.id, params.token)
yield put(RepositoryAction.fetchRepositorySucceeded(count))
} catch (e) {
yield put(RepositoryAction.fetchRepositoryFailed(e.message))

@ -23,8 +23,13 @@ export default {
.then(res => res.json())
// .then(json => json.data)
},
fetchRepository(id: any) {
return fetch(`${serve}/repository/get?id=${id}`, { ...CREDENTIALS })
fetchRepository(id: any, token?: string) {
return fetch(
`${serve}/repository/get?id=${id}${
token !== undefined ? `&token=${token}` : ''
}`,
{ ...CREDENTIALS }
)
.then(res => res.json())
.then(json => json.data)
},

Loading…
Cancel
Save