Project initial

This commit is contained in:
chengpu
2022-12-03 00:54:53 +08:00
commit 5092a5e717
502 changed files with 50820 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
import PropTypes from 'prop-types'
import get from 'lodash.get'
import set from 'lodash.set'
import React, {useReducer} from 'react'
import useTheme from '../utils/Theme'
import {isValidDependency} from '../utils/ApiUtils'
import {rangeToText} from '../utils/Version'
export const defaultAppContext = {
more: false,
complete: false,
explore: false,
share: false,
fetch: false,
tab: 'quicksearch',
theme: 'light',
language: 'zh',
config: {},
groupsOpened: [],
dependencies: {
list: [],
groups: [],
},
}
export function reduceDependencies(boot, items) {
const groups = []
const list = []
const getParent = (m, name) => {
return m.find(item => item.group === name)
}
for (let i = 0; i < items.length; i += 1) {
let message = ''
const dep = items[i]
let parent = getParent(groups, dep.group)
if (!parent) {
parent = {
group: dep.group,
items: [],
}
groups.push(parent)
}
const valid = isValidDependency(boot, dep)
if (!valid) {
message = `Requires Spring Boot ${rangeToText(
get(dep, 'versionRequirement')
)}.`
}
parent.items.push({ ...dep, valid, message })
list.push({ ...dep, valid, message })
}
return {
list,
groups,
}
}
export function reducer(state, action) {
switch (action.type) {
case 'UPDATE': {
const newState = { ...state }
const keysContext = Object.keys(defaultAppContext)
const keys = Object.keys(get(action, 'payload', {}))
keys.map(key => {
if (keysContext.indexOf(key) === -1) {
throw Error('Error AppProvider, invalid paylaod field action')
}
const value = get(action, `payload.${key}`)
set(newState, key, value)
if (key === 'theme') {
localStorage.setItem('springtheme', value)
}
return key
})
return newState
}
case 'TOGGLE_GROUP': {
const id = get(action, 'payload.id')
let groupsOpened = [...state.groupsOpened]
if (groupsOpened.indexOf(id) > -1) {
groupsOpened = [...groupsOpened.filter(g => g !== id)]
} else {
groupsOpened = [...groupsOpened, id]
}
return { ...state, groupsOpened }
}
case 'UPDATE_DEPENDENCIES': {
const dependencies = reduceDependencies(
get(action, 'payload.boot'),
get(state, 'config.lists.dependencies')
)
return { ...state, dependencies }
}
case 'SHARE_UPDATE': {
const share = get(action, 'payload.open', false)
return { ...state, share }
}
case 'EXPLORE_UPDATE': {
const explore = get(action, 'payload.open', false)
return { ...state, explore }
}
case 'FETCH_UPDATE': {
const fetch = get(action, 'payload.open', false)
return { ...state, fetch }
}
case 'COMPLETE': {
const json = get(action, 'payload', {})
const dependencies = reduceDependencies(
get(json, 'defaultValues.boot'),
get(json, 'lists.dependencies')
)
return { ...state, complete: true, config: json, dependencies }
}
default:
return state
}
}
export const AppContext = React.createContext({ ...defaultAppContext })
export function AppProvider({ children }) {
const theme = useTheme()
const [state, dispatch] = useReducer(reducer, { ...defaultAppContext, theme })
return (
<AppContext.Provider value={{ ...state, dispatch }}>
{children}
</AppContext.Provider>
)
}
AppProvider.propTypes = {
children: PropTypes.node.isRequired,
}

View File

@@ -0,0 +1,132 @@
import PropTypes from 'prop-types'
import get from 'lodash.get'
import set from 'lodash.set'
import React, {useReducer} from 'react'
import {getShareUrl, parseParams} from '../utils/ApiUtils'
export const defaultInitializrContext = {
values: {
project: '',
language: '',
architecture: '',
boot: '',
meta: {
name: '',
group: '',
artifact: '',
description: '',
packaging: '',
packageName: '',
java: '',
},
dependencies: [],
share: [],
},
share: '',
errors: {},
warnings: {},
}
export function reducer(state, action) {
switch (action.type) {
case 'COMPLETE': {
const json = get(action, 'payload')
const defaultValues = {
...get(json, 'defaultValues'),
meta: get(json, 'defaultValues.meta'),
}
return {
values: defaultValues,
share: getShareUrl(defaultValues),
errors: {},
warnings: {},
}
}
case 'UPDATE': {
const changes = get(action, 'payload')
let errors = { ...state.errors }
let meta = { ...get(state, 'values.meta') }
if (get(changes, 'meta')) {
meta = { ...meta, ...get(changes, 'meta') }
}
if (get(changes, 'boot')) {
const { boot, ...err } = errors
errors = err
}
if (get(changes, 'meta.group')) {
set(
meta,
'packageName',
`${get(meta, 'group')}.${get(meta, 'artifact')}`
)
}
if (get(changes, 'meta.artifact')) {
set(
meta,
'packageName',
`${get(meta, 'group')}.${get(meta, 'artifact')}`
)
set(meta, 'name', `${get(meta, 'artifact')}`)
}
const values = {
...get(state, 'values'),
...changes,
meta,
}
return { ...state, values, share: getShareUrl(values), errors }
}
case 'LOAD': {
const params = get(action, 'payload.params')
const lists = get(action, 'payload.lists')
const { values, errors, warnings } = parseParams(
state.values,
params,
lists
)
return { ...state, values, errors, warnings, share: getShareUrl(values) }
}
case 'ADD_DEPENDENCY': {
const dependency = get(action, 'payload.id')
const values = { ...get(state, 'values') }
if(get(values, 'dependencies', []).filter(item => item === dependency).length == 0){
values.dependencies = [...get(values, 'dependencies'), dependency]
}
return { ...state, values, share: getShareUrl(values) }
}
case 'REMOVE_DEPENDENCY': {
const dependency = get(action, 'payload.id')
const values = { ...get(state, 'values') }
values.dependencies = [
...get(values, 'dependencies').filter(dep => dep !== dependency),
]
return { ...state, values, share: getShareUrl(values) }
}
case 'CLEAR_WARNINGS': {
return { ...state, warnings: {} }
}
default:
return state
}
}
export const InitializrContext = React.createContext({
...defaultInitializrContext,
})
export function InitializrProvider({ children }) {
const [state, dispatch] = useReducer(reducer, { ...defaultInitializrContext })
return (
<InitializrContext.Provider value={{ ...state, dispatch }}>
{children}
</InitializrContext.Provider>
)
}
InitializrProvider.defaultProps = {
children: null,
}
InitializrProvider.propTypes = {
children: PropTypes.node,
}

View File

@@ -0,0 +1,137 @@
import get from 'lodash.get'
import {reducer} from '../App'
let state = {}
beforeEach(() => {
state = {
more: false,
complete: false,
explore: false,
share: false,
tab: 'quicksearch',
theme: 'light',
config: {},
groupsOpened: [],
dependencies: {
list: [],
groups: [],
},
}
})
describe('UPDATE action', () => {
it('should reduce the state', () => {
let result = reducer(state, { type: 'UPDATE', payload: { more: true } })
expect(get(result, 'more')).toBe(true)
result = reducer(state, { type: 'UPDATE', payload: { theme: 'dark' } })
expect(get(result, 'theme')).toBe('dark')
})
it('should throw an error', () => {
expect(() => {
reducer(state, { type: 'UPDATE', payload: { foo: 'bar' } })
}).toThrow(Error)
})
})
describe('TOGGLE_GROUP action', () => {
it('should add/remove a group', () => {
let result = reducer(state, {
type: 'TOGGLE_GROUP',
payload: { id: 'foo1' },
})
expect(get(result, 'groupsOpened').length).toBe(1)
expect(get(result, 'groupsOpened[0]')).toBe('foo1')
result = reducer(result, {
type: 'TOGGLE_GROUP',
payload: { id: 'foo2' },
})
expect(get(result, 'groupsOpened').length).toBe(2)
expect(get(result, 'groupsOpened[0]')).toBe('foo1')
expect(get(result, 'groupsOpened[1]')).toBe('foo2')
result = reducer(result, {
type: 'TOGGLE_GROUP',
payload: { id: 'foo1' },
})
expect(get(result, 'groupsOpened').length).toBe(1)
expect(get(result, 'groupsOpened[0]')).toBe('foo2')
})
})
describe('UPDATE_DEPENDENCIES action', () => {
it('should update dependencies', () => {
state.config = {
lists: {
dependencies: [
{
id: 'foo1',
group: 'bar2',
versionRange: '',
},
],
},
}
const result = reducer(state, {
type: 'UPDATE_DEPENDENCIES',
payload: {
boot: '1.0.0.RELEASE',
},
})
expect(get(result, 'dependencies.list').length).toBe(1)
expect(get(result, 'dependencies.list[0].id')).toBe('foo1')
expect(get(result, 'dependencies.list[0].valid')).toBe(true)
})
})
describe('SHARE_UPDATE/EXPLORE_UPDATE action', () => {
it('should add/remove a group', () => {
let result = reducer(state, {
type: 'SHARE_UPDATE',
payload: { open: true },
})
expect(get(result, 'share')).toBe(true)
result = reducer(result, {
type: 'SHARE_UPDATE',
payload: { open: false },
})
expect(get(result, 'share')).toBe(false)
result = reducer(result, {
type: 'EXPLORE_UPDATE',
payload: { open: true },
})
expect(get(result, 'explore')).toBe(true)
result = reducer(result, {
type: 'EXPLORE_UPDATE',
payload: { open: false },
})
expect(get(result, 'explore')).toBe(false)
})
})
describe('COMPLETE action', () => {
it('should add/remove a group', () => {
const result = reducer(state, {
type: 'COMPLETE',
payload: {
defaultValues: {
boot: '1.0.0',
},
lists: {
dependencies: [
{
id: 'foo1',
group: 'bar2',
versionRange: '',
},
],
},
},
})
expect(get(result, 'complete')).toBe(true)
expect(get(result, 'config.json')).not.toBe(null)
expect(get(result, 'dependencies')).not.toBe(null)
expect(get(result, 'dependencies.list').length).toBe(1)
})
})

View File

@@ -0,0 +1,289 @@
import get from 'lodash.get'
import MockClient from '../../../../dev/api.json'
import {getDefaultValues, getLists} from '../../utils/ApiUtils'
import {reducer} from '../Initializr'
const defaultValues = getDefaultValues({ ...MockClient })
let state = {}
beforeEach(() => {
state = {
values: { ...defaultValues, meta: { ...defaultValues.meta } },
share: '',
errors: {},
warnings: {},
}
})
describe('COMPLETE action', () => {
beforeEach(() => {
state = {
values: {
project: '',
language: '',
architecture: '',
boot: '',
meta: {
name: '',
group: '',
artifact: '',
description: '',
packaging: '',
packageName: '',
java: '',
},
dependencies: [],
},
share: '',
errors: {},
warnings: {},
}
})
it('should reduce the state', () => {
const result = reducer(state, {
type: 'COMPLETE',
payload: {
defaultValues,
},
})
expect(get(result, 'share')).toBe(
'type=maven-project&language=java&architecture=none&platformVersion=2.2.0.RELEASE&packaging=jar&jvmVersion=1.8&groupId=com.example&artifactId=demo&name=demo&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.demo'
)
expect(get(result, 'values.project')).toBe('maven-project')
expect(get(result, 'values.language')).toBe('java')
expect(get(result, 'values.architecture')).toBe('none')
expect(get(result, 'values.boot')).toBe('2.2.0.RELEASE')
expect(get(result, 'values.meta.name')).toBe('demo')
expect(get(result, 'values.meta.group')).toBe('com.example')
expect(get(result, 'values.meta.artifact')).toBe('demo')
expect(get(result, 'values.meta.description')).toBe(
'Demo project for Spring Boot'
)
expect(get(result, 'values.meta.packaging')).toBe('jar')
expect(get(result, 'values.meta.packageName')).toBe('com.example.demo')
expect(get(result, 'values.meta.java')).toBe('1.8')
expect(get(result, 'values.dependencies').length).toBe(0)
expect(Object.keys(get(result, 'errors')).length).toBe(0)
expect(Object.keys(get(result, 'warnings')).length).toBe(0)
})
})
describe('UPDATE action', () => {
it('should reduce the state (type)', () => {
const result = reducer(state, {
type: 'UPDATE',
payload: {
project: 'maven-project',
},
})
expect(get(result, 'values.project')).toBe('maven-project')
})
it('should reduce the state (language)', () => {
const result = reducer(state, {
type: 'UPDATE',
payload: {
language: 'kotlin',
},
})
expect(get(result, 'values.language')).toBe('kotlin')
})
it('should reduce the state (boot)', () => {
const result = reducer(state, {
type: 'UPDATE',
payload: {
boot: '2.1.10.BUILD-SNAPSHOT',
},
})
expect(get(result, 'values.boot')).toBe('2.1.10.BUILD-SNAPSHOT')
})
it('should reduce the state (meta name)', () => {
const result = reducer(state, {
type: 'UPDATE',
payload: {
meta: {
name: 'demo1',
},
},
})
expect(get(result, 'values.meta.name')).toBe('demo1')
})
it('should reduce the state (meta group)', () => {
state.values.meta.artifact = 'demo3'
const result = reducer(state, {
type: 'UPDATE',
payload: {
meta: {
group: 'com.example1',
},
},
})
expect(get(result, 'values.meta.group')).toBe('com.example1')
expect(get(result, 'values.meta.packageName')).toBe('com.example1.demo3')
})
it('should reduce the state (meta artifact)', () => {
state.values.meta.group = 'com.example3'
const result = reducer(state, {
type: 'UPDATE',
payload: {
meta: {
artifact: 'demo2',
},
},
})
expect(get(result, 'values.meta.artifact')).toBe('demo2')
expect(get(result, 'values.meta.packageName')).toBe('com.example3.demo2')
})
it('should reduce the state (meta description)', () => {
const result = reducer(state, {
type: 'UPDATE',
payload: {
meta: {
description: 'desc',
},
},
})
expect(get(result, 'values.meta.description')).toBe('desc')
})
it('should reduce the state (meta packaging)', () => {
const result = reducer(state, {
type: 'UPDATE',
payload: {
meta: {
packaging: 'war',
},
},
})
expect(get(result, 'values.meta.packaging')).toBe('war')
})
it('should reduce the state (meta packageName)', () => {
const result = reducer(state, {
type: 'UPDATE',
payload: {
meta: {
packageName: 'com1.example2.demo3',
},
},
})
expect(get(result, 'values.meta.packageName')).toBe('com1.example2.demo3')
})
it('should reduce the state (meta java)', () => {
const result = reducer(state, {
type: 'UPDATE',
payload: {
meta: {
java: '1.9',
},
},
})
expect(get(result, 'values.meta.java')).toBe('1.9')
})
})
describe('LOAD action', () => {
it('should reduce the state', () => {
const json = { ...MockClient }
const listsValues = getLists(json)
const result = reducer(state, {
type: 'LOAD',
payload: {
params: {
artifactId: 'demo1',
description: 'Demo1 project for Spring Boot',
groupId: 'com.example1',
jvmVersion: '1.8',
language: 'java',
architecture: 'none',
name: 'demo1',
packageName: 'com.example1.demo1',
packaging: 'war',
platformVersion: '2.2.0.RELEASE',
type: 'gradle-project',
},
lists: listsValues,
},
})
expect(get(result, 'values.project')).toBe('gradle-project')
expect(get(result, 'values.language')).toBe('java')
expect(get(result, 'values.boot')).toBe('2.2.0.RELEASE')
expect(get(result, 'values.meta.name')).toBe('demo1')
expect(get(result, 'values.meta.group')).toBe('com.example1')
expect(get(result, 'values.meta.artifact')).toBe('demo1')
expect(get(result, 'values.meta.description')).toBe(
'Demo1 project for Spring Boot'
)
expect(get(result, 'values.meta.packaging')).toBe('war')
expect(get(result, 'values.meta.packageName')).toBe('com.example1.demo1')
expect(get(result, 'values.meta.java')).toBe('1.8')
expect(get(result, 'values.dependencies').length).toBe(0)
expect(Object.keys(get(result, 'errors')).length).toBe(0)
expect(Object.keys(get(result, 'warnings')).length).toBe(0)
})
})
describe('ADD_DEPENDENCY action', () => {
it('should reduce the state', () => {
let result = reducer(state, {
type: 'ADD_DEPENDENCY',
payload: {
id: 'foo1',
},
})
expect(get(result, 'values.dependencies').length).toBe(1)
expect(get(result, 'values.dependencies[0]')).toBe('foo1')
result = reducer(result, {
type: 'ADD_DEPENDENCY',
payload: {
id: 'foo2',
},
})
expect(get(result, 'values.dependencies').length).toBe(2)
expect(get(result, 'values.dependencies[0]')).toBe('foo1')
expect(get(result, 'values.dependencies[1]')).toBe('foo2')
})
})
describe('REMOVE_DEPENDENCY action', () => {
it('should reduce the state', () => {
let result = reducer(state, {
type: 'ADD_DEPENDENCY',
payload: {
id: 'foo1',
},
})
result = reducer(result, {
type: 'ADD_DEPENDENCY',
payload: {
id: 'foo2',
},
})
expect(get(result, 'values.dependencies').length).toBe(2)
expect(get(result, 'values.dependencies[0]')).toBe('foo1')
expect(get(result, 'values.dependencies[1]')).toBe('foo2')
result = reducer(result, {
type: 'REMOVE_DEPENDENCY',
payload: {
id: 'foo1',
},
})
expect(get(result, 'values.dependencies').length).toBe(1)
expect(get(result, 'values.dependencies[0]')).toBe('foo2')
result = reducer(result, {
type: 'REMOVE_DEPENDENCY',
payload: {
id: 'foo2',
},
})
expect(get(result, 'values.dependencies').length).toBe(0)
})
})
describe('CLEAR_WARNINGS action', () => {
it('should reduce the state', () => {
state.warnings = { foo: 'bar' }
const result = reducer(state, {
type: 'CLEAR_WARNINGS',
})
expect(Object.keys(get(result, 'warnings')).length).toBe(0)
})
})