= {
28 | viewState: ViewState.IDLE,
29 | }
30 |
31 | private setViewState = (viewState: T) => {
32 | this.setState({
33 | viewState,
34 | })
35 | }
36 |
37 | render() {
38 | const { viewState: vs } = this.state
39 | const { viewState, children } = this.props
40 |
41 | return (
42 | (children &&
43 | typeof children === 'function' &&
44 | children({ viewState: viewState || vs, setViewState: this.setViewState })) ||
45 | null
46 | )
47 | }
48 | }
49 |
50 | export default Stateful
51 |
--------------------------------------------------------------------------------
/moss-ui/src/components/notification/dialog.tsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GrailStack/Moss/9e54b0274ddb769c411343cb736467867bf28b82/moss-ui/src/components/notification/dialog.tsx
--------------------------------------------------------------------------------
/moss-ui/src/components/notification/loading.tsx:
--------------------------------------------------------------------------------
1 | import { Spin } from 'antd';
2 | import React from 'react';
3 |
4 | class Loading extends React.Component {
5 | public render() {
6 | return (
7 |
8 |
9 |
10 | );
11 | }
12 | }
13 | export default Loading;
14 |
--------------------------------------------------------------------------------
/moss-ui/src/components/withAuth/index.tsx:
--------------------------------------------------------------------------------
1 | import { connect, wholeModel } from '@/util/store'
2 | import React from 'react'
3 | import { Redirect } from 'react-router-dom'
4 |
5 | export const withAuth = (BaseComponent: React.ComponentType) => {
6 | class AuthRoute extends React.Component<{
7 | login: LoginData
8 | }> {
9 | public render() {
10 | const { login } = this.props
11 | return login.token ? (
12 |
13 | ) : (
14 |
19 | )
20 | }
21 | }
22 | return connect({ login: wholeModel.login })(AuthRoute)
23 | }
24 |
25 | export default withAuth
26 |
--------------------------------------------------------------------------------
/moss-ui/src/global.less:
--------------------------------------------------------------------------------
1 | @import './style/index';
2 | @import './style/constants.less';
3 |
--------------------------------------------------------------------------------
/moss-ui/src/global.ts:
--------------------------------------------------------------------------------
1 | import 'moment/locale/zh-cn'
2 | import moment from 'moment'
3 |
4 | moment.locale('zh-cn')
5 |
--------------------------------------------------------------------------------
/moss-ui/src/layouts/__tests__/index.test.tsx:
--------------------------------------------------------------------------------
1 | import 'jest';
2 | import BasicLayout from '..';
3 | import React from 'react';
4 | import renderer, { ReactTestInstance, ReactTestRenderer } from 'react-test-renderer';
5 |
6 | describe('Layout: BasicLayout', () => {
7 | it('Render correctly', () => {
8 | const wrapper: ReactTestRenderer = renderer.create();
9 | expect(wrapper.root.children.length).toBe(1);
10 | const outerLayer = wrapper.root.children[0] as ReactTestInstance;
11 | expect(outerLayer.type).toBe('div');
12 | const title = outerLayer.children[0] as ReactTestInstance;
13 | expect(title.type).toBe('h1');
14 | expect(title.children[0]).toBe('Yay! Welcome to umi!');
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/moss-ui/src/layouts/index.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GrailStack/Moss/9e54b0274ddb769c411343cb736467867bf28b82/moss-ui/src/layouts/index.less
--------------------------------------------------------------------------------
/moss-ui/src/layouts/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import styles from './index.less'
3 |
4 | export type BasicLayoutComponent = React.SFC
5 |
6 | export interface BasicLayoutProps extends React.Props {
7 | history?: History
8 | location?: Location
9 | }
10 |
11 | const BasicLayout: BasicLayoutComponent = props => {
12 | return {props.children}
13 | }
14 |
15 | export default BasicLayout
16 |
--------------------------------------------------------------------------------
/moss-ui/src/models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GrailStack/Moss/9e54b0274ddb769c411343cb736467867bf28b82/moss-ui/src/models/.gitkeep
--------------------------------------------------------------------------------
/moss-ui/src/models/dashboard/model.ts:
--------------------------------------------------------------------------------
1 | import { gluer } from 'glue-redux'
2 |
3 | const dashboard = gluer((data: DashboardBasicData): DashboardBasicData => {
4 | return data
5 | }, {})
6 |
7 | const report = gluer((data: ReportData): ReportData => {
8 | return data
9 | }, {})
10 |
11 | export default { dashboard, report }
12 |
--------------------------------------------------------------------------------
/moss-ui/src/models/dashboard/service.ts:
--------------------------------------------------------------------------------
1 | import { wholeModel } from '@/util/store'
2 | import fetch from '@/util/fetch'
3 |
4 | export default {
5 | fetchDashBoard: (): Promise => {
6 | return fetch({
7 | method: 'get',
8 | url: `admin/dashboard/basic`,
9 | }).then(data => {
10 | return wholeModel.dashboard.dashboard(data)
11 | })
12 | },
13 | fetchReports: (): Promise => {
14 | return fetch({
15 | method: 'get',
16 | url: `admin/dashboard/report`,
17 | }).then(data => {
18 | return wholeModel.dashboard.report(data)
19 | })
20 | },
21 | }
22 |
--------------------------------------------------------------------------------
/moss-ui/src/models/global/model.ts:
--------------------------------------------------------------------------------
1 | import { gluer } from 'glue-redux'
2 |
3 | const globalConf = gluer((data?: GlobalConf) => {
4 | if (data && data.registerCenter && Array.isArray(data.registerCenter)) {
5 | const localRegisterCenter = localStorage.getItem('registerCenter')
6 | const localRegisterCenterInList = data.registerCenter.find(c => {
7 | return c.value === localRegisterCenter
8 | })
9 | if (!localRegisterCenterInList) {
10 | localStorage.setItem('registerCenter', '')
11 | }
12 | }
13 | return { ...data }
14 | }, {})
15 |
16 | export default globalConf
17 |
--------------------------------------------------------------------------------
/moss-ui/src/models/global/service.ts:
--------------------------------------------------------------------------------
1 | import fetch from '@/util/fetch'
2 | import { wholeModel } from '@/util/store'
3 |
4 | export default {
5 | fetchGlobalConf: (): Promise => {
6 | return fetch(
7 | {
8 | url: `admin/metadata/list`,
9 | },
10 | { showLoading: false }
11 | ).then(data => {
12 | return wholeModel.globalConf(data)
13 | })
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/moss-ui/src/models/login/model.ts:
--------------------------------------------------------------------------------
1 | import { gluer } from 'glue-redux'
2 |
3 | const login = gluer(
4 | (data?: LoginData) => {
5 | localStorage.setItem('token', (data && data.token) || '')
6 | localStorage.setItem('userName', (data && data.userName) || '')
7 | return data
8 | },
9 | {
10 | userName: localStorage.getItem('userName') || 'anonymous',
11 | token: localStorage.getItem('token'),
12 | }
13 | )
14 |
15 | export default login
16 |
--------------------------------------------------------------------------------
/moss-ui/src/models/login/service.ts:
--------------------------------------------------------------------------------
1 | import { wholeModel } from '@/util/store'
2 | import fetch from '@/util/fetch'
3 |
4 | export default {
5 | login: (body: any): Promise => {
6 | return fetch({
7 | method: 'POST',
8 | url: `/admin/login`,
9 | data: body,
10 | }).then(data => {
11 | return wholeModel.login(data)
12 | })
13 | },
14 | }
15 |
--------------------------------------------------------------------------------
/moss-ui/src/models/menu/model.ts:
--------------------------------------------------------------------------------
1 | import { gluer } from 'glue-redux';
2 |
3 | const menu = gluer([]);
4 |
5 | export default menu;
6 |
--------------------------------------------------------------------------------
/moss-ui/src/models/notification/model.ts:
--------------------------------------------------------------------------------
1 | import { gluer } from 'glue-redux';
2 |
3 | const loading = gluer((data: number, state: number) => data + state, 0);
4 |
5 | const notices = gluer([]);
6 |
7 | export default {
8 | loading,
9 | notices,
10 | };
11 |
--------------------------------------------------------------------------------
/moss-ui/src/models/notification/service.ts:
--------------------------------------------------------------------------------
1 | import { referToState, wholeModel } from '@/util/store'
2 |
3 | let currentCount = 0
4 | const notification = {
5 | addNotice: (source: { message: string; type: string; count?: number }) => {
6 | const state = referToState(wholeModel.notification.notices)
7 | return wholeModel.notification.notices([...state, { ...source, count: ++currentCount }])
8 | },
9 | loading: (data: number) => wholeModel.notification.loading(data),
10 | removeNotice: (source: { count?: number }) => {
11 | const state = referToState(wholeModel.notification.notices)
12 | if (state.length) {
13 | const newNotices = [...state]
14 |
15 | state.forEach((notice: INotice, index: number) => {
16 | if (notice.count === source.count) {
17 | newNotices.splice(index, 1)
18 | }
19 | })
20 | return wholeModel.notification.notices(newNotices)
21 | }
22 | },
23 | }
24 | export default notification
25 |
--------------------------------------------------------------------------------
/moss-ui/src/models/selectNode/initialState.ts:
--------------------------------------------------------------------------------
1 | export const SELECTNODE = {
2 | SELECTNODE: [],
3 | };
4 |
--------------------------------------------------------------------------------
/moss-ui/src/models/selectNode/model.ts:
--------------------------------------------------------------------------------
1 | import { gluer } from 'glue-redux';
2 |
3 | import { SELECTNODE } from './initialState';
4 |
5 | // 选择节点
6 | const SelectNode = gluer((data: any) => {
7 | return {
8 | data,
9 | };
10 | }, SELECTNODE);
11 |
12 | const nodeList = {
13 | SelectNode,
14 | };
15 |
16 | export default nodeList;
17 |
--------------------------------------------------------------------------------
/moss-ui/src/models/selectNode/service.ts:
--------------------------------------------------------------------------------
1 | import fetch from '@/util/fetch';
2 |
3 | import model from './model';
4 |
5 | const selectNode = {
6 | /* 节点列表 */
7 | fetchApplicationNodelist: () => {
8 | return fetch({
9 | method: 'get',
10 | url: `api/applications/`,
11 | }).then((data: any) => {
12 | return Promise.resolve(model.SelectNode(data));
13 | });
14 | },
15 | };
16 |
17 | export default selectNode;
18 |
--------------------------------------------------------------------------------
/moss-ui/src/models/tab/model.ts:
--------------------------------------------------------------------------------
1 | import { gluer } from 'glue-redux';
2 |
3 | const tab = gluer(['dashboard']);
4 | export default tab;
5 |
--------------------------------------------------------------------------------
/moss-ui/src/models/tab/service.ts:
--------------------------------------------------------------------------------
1 | import { getMenuInfo } from '@/models/menu/service'
2 | import { referToState, wholeModel } from '@/util/store'
3 |
4 | const model = wholeModel.tab
5 |
6 | export default {
7 | addTab: (source: { title: string; force?: boolean }) => {
8 | const state = referToState(model)
9 | const { title, force } = source
10 | const info = getMenuInfo(title)
11 |
12 | if (info) {
13 | const isOpened = state.indexOf(title) > -1
14 | let final
15 |
16 | if (isOpened) {
17 | final = state
18 | } else if (info.isExternal || force || state.length < 2) {
19 | final = state.concat(title)
20 | } else {
21 | const internalInfo = getMenuInfo(state[1])
22 |
23 | state.splice(1, internalInfo.isExternal ? 0 : 1, title)
24 | final = [...state]
25 | }
26 | return model(final)
27 | }
28 | return model([...state])
29 | },
30 | removeTab: (source: { title: string; force?: boolean }) => {
31 | const state = referToState(model)
32 | const { title } = source
33 | return model(state.filter((tabTitle: string) => tabTitle !== title))
34 | },
35 | }
36 |
--------------------------------------------------------------------------------
/moss-ui/src/models/user/model.ts:
--------------------------------------------------------------------------------
1 | import { gluer } from 'glue-redux'
2 |
3 | const User = gluer((data: UserData): UserData => {
4 | return data
5 | }, [])
6 |
7 | const userMgmt = {
8 | User,
9 | }
10 |
11 | export default userMgmt
12 |
--------------------------------------------------------------------------------
/moss-ui/src/models/user/service.ts:
--------------------------------------------------------------------------------
1 | import fetch from '@/util/fetch'
2 |
3 | import model from './model'
4 |
5 | export default {
6 | fetchUserList: (
7 | username: string = '',
8 | pageNo: number = 1,
9 | name: string = '',
10 | pageSize: number = 10
11 | ) => {
12 | debugger
13 | return fetch({
14 | method: 'POST',
15 | url: `admin/user/pageList`,
16 | data: { username, name, pageNo, pageSize },
17 | }).then((data: any) => {
18 | data.list = data.list.map((d: any) => {
19 | d.isDeleted = d.isDeleted === 1 ? true : false
20 | return d
21 | })
22 | return model.User(data)
23 | })
24 | },
25 | deleteUser: (userId: number) => {
26 | return fetch({
27 | url: `admin/user/delete/${userId}`,
28 | })
29 | },
30 |
31 |
32 | createUser: (userData: any) => {
33 | return fetch({
34 | method: 'POST',
35 | url: `admin/user/add`,
36 | data: userData,
37 | })
38 | },
39 |
40 | updateUser: (userData: any) => {
41 | return fetch({
42 | method: 'POST',
43 | url: `admin/user/update`,
44 | data: userData,
45 | })
46 | },
47 | }
48 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/.umi/DvaContainer.js:
--------------------------------------------------------------------------------
1 | import { Component } from 'react';
2 |
3 | class DvaContainer extends Component {
4 | render() {
5 | window.g_app.router(() => this.props.children);
6 | return window.g_app.start()();
7 | }
8 | }
9 |
10 | export default DvaContainer;
11 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/.umi/TitleWrapper.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class UmiReactTitle extends React.Component {
4 | componentDidMount() {
5 | document.title = this.props.route._title;
6 | }
7 | getTitle() {
8 | const separator = '' || ' - ';
9 | const title = this.props.route._title.split(separator).map(item => {
10 | return formatMessage({
11 | id: item.trim(),
12 | defaultMessage: item.trim(),
13 | });
14 | })
15 | return title.join(separator);
16 | }
17 | componentWillUnmount() {
18 | if (document.title === this.props.route._title) {
19 | document.title = this.props.route._title;
20 | }
21 | }
22 | render() {
23 | return this.props.children;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/.umi/initDva.js:
--------------------------------------------------------------------------------
1 | import dva from 'dva';
2 | import createLoading from 'dva-loading';
3 |
4 | const runtimeDva = window.g_plugins.mergeConfig('dva');
5 | let app = dva({
6 | history: window.g_history,
7 |
8 | ...(runtimeDva.config || {}),
9 | });
10 |
11 | window.g_app = app;
12 | app.use(createLoading());
13 | (runtimeDva.plugins || []).forEach(plugin => {
14 | app.use(plugin);
15 | });
16 |
17 |
18 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/.umi/initHistory.js:
--------------------------------------------------------------------------------
1 | // create history
2 | window.g_history = require('history/createHashHistory').default({});
3 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/.umi/polyfills.js:
--------------------------------------------------------------------------------
1 | import '@babel/polyfill';
2 |
3 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/Admin/Pages/OSManage/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Route, Switch } from 'react-router'
3 | import menuEdit from './menuEdit'
4 | import menuManage from './menuManage'
5 | import menuNew from './menuNew'
6 | import modifyExample from './modifyExample'
7 | class OSManage extends React.Component {
8 | public render() {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | )
20 | }
21 | }
22 | export default OSManage
23 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/Admin/Pages/SwitchCenter/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Route, Switch } from 'react-router';
3 |
4 | import switchManage from './switchManage';
5 | import switchPushLog from './switchPushLog';
6 |
7 | class SwitchManage extends React.Component {
8 | public render() {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 | );
17 | }
18 | }
19 |
20 | export default SwitchManage;
21 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/Admin/Pages/SwitchCenter/switchPushLog.tsx:
--------------------------------------------------------------------------------
1 | import PageTitle from '@/components/PageTitle';
2 | import { Col, Layout, Row } from 'antd';
3 | import React from 'react';
4 |
5 | const SwitchPushLog = React.memo(() => {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | );
17 | });
18 |
19 | export default SwitchPushLog;
20 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/Admin/Pages/index.ts:
--------------------------------------------------------------------------------
1 | import './style.less';
2 |
3 | import Application from './Application';
4 | import CodeGenerate from './CodeGenerate';
5 | import Dashboard from './Dashboard';
6 | import OSManage from './OSManage';
7 | import SwitchCenter from './SwitchCenter';
8 |
9 | const pages: { [key: string]: any } = {
10 | Application,
11 | Dashboard,
12 | CodeGenerate,
13 | OSManage,
14 | SwitchCenter,
15 | };
16 |
17 | export default pages;
18 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/Admin/style.less:
--------------------------------------------------------------------------------
1 | #stage {
2 | display: flex;
3 |
4 | iframe {
5 | flex: auto;
6 | overflow: auto;
7 | border: 0;
8 | }
9 |
10 | & > div {
11 | display: none;
12 | flex: auto;
13 | flex-direction: column;
14 |
15 | &.active {
16 | display: flex;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/__tests__/__mocks__/umi-plugin-locale.ts:
--------------------------------------------------------------------------------
1 | export const formatMessage = (): string => 'Mock text';
2 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/__tests__/index.test.tsx:
--------------------------------------------------------------------------------
1 | import 'jest';
2 | import Index from '..';
3 | import React from 'react';
4 | import renderer, { ReactTestInstance, ReactTestRenderer } from 'react-test-renderer';
5 |
6 | jest.mock('umi-plugin-locale');
7 |
8 | describe('Page: index', () => {
9 | it('Render correctly', () => {
10 | const wrapper: ReactTestRenderer = renderer.create();
11 | expect(wrapper.root.children.length).toBe(1);
12 | const outerLayer = wrapper.root.children[0] as ReactTestInstance;
13 | expect(outerLayer.type).toBe('div');
14 | expect(outerLayer.children.length).toBe(2);
15 | const getStartLink = outerLayer.findAllByProps({
16 | href: 'https://umijs.org/guide/getting-started.html',
17 | }) as ReactTestInstance[];
18 | expect(getStartLink.length).toBe(1);
19 | expect(getStartLink[0].children).toMatchObject(['Mock text']);
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/document.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 莫斯-服务治理平台
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/moss-ui/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import App from '@/pages/App'
2 | import { polyfill } from 'es6-promise'
3 | import React from 'react'
4 |
5 | if (window.Promise && !window.Promise.prototype.finally) {
6 | window.Promise = null
7 | polyfill()
8 | }
9 |
10 | export default function() {
11 | return
12 | }
13 |
--------------------------------------------------------------------------------
/moss-ui/src/style/antDesignOverride.less:
--------------------------------------------------------------------------------
1 | // ant design override
2 |
3 | // ant design notification override
4 | .ant-notification-notice-closable {
5 | border-radius: 25px;
6 | }
7 |
8 | .ant-notification-notice-with-icon {
9 | display: flex;
10 | flex-direction: column;
11 | justify-content: center;
12 |
13 | .ant-notification-notice-message {
14 | font-weight: 500;
15 | color: black;
16 | }
17 |
18 | .ant-notification-notice-description {
19 | font-size: 12px;
20 | }
21 |
22 | .icon {
23 | width: 46px;
24 | margin-left: -12px;
25 | }
26 | }
27 |
28 | .ant-tooltip-inner {
29 | user-select: text;
30 | }
31 |
--------------------------------------------------------------------------------
/moss-ui/src/style/icon/icon.less:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'iconfont';
3 | src: url('./iconfont.eot?t=1529483438781');
4 | }
5 |
6 | .iconfont {
7 | font-family: 'iconfont', sans-serif !important;
8 | font-style: normal;
9 | -webkit-font-smoothing: antialiased;
10 | -moz-osx-font-smoothing: grayscale;
11 | }
12 |
13 | .icon-back::before {
14 | content: '\e610';
15 | }
16 |
17 | .icon-close::before {
18 | content: '\e611';
19 | }
20 |
21 | .icon-eye-close::before {
22 | content: '\e612';
23 | }
24 |
25 | .icon-eye-open::before {
26 | content: '\e613';
27 | }
28 |
29 | .icon-unselectednormal::before {
30 | content: '\e614';
31 | }
32 |
33 | .icon-success::before {
34 | content: '\e615';
35 | }
36 |
37 | .icon-info::before {
38 | content: '\e617';
39 | }
40 |
41 | .icon-error::before {
42 | content: '\e618';
43 | }
44 |
45 | .icon-selectednormal::before {
46 | content: '\e61a';
47 | }
48 |
--------------------------------------------------------------------------------
/moss-ui/src/style/icon/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GrailStack/Moss/9e54b0274ddb769c411343cb736467867bf28b82/moss-ui/src/style/icon/iconfont.eot
--------------------------------------------------------------------------------
/moss-ui/src/style/icon/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GrailStack/Moss/9e54b0274ddb769c411343cb736467867bf28b82/moss-ui/src/style/icon/iconfont.ttf
--------------------------------------------------------------------------------
/moss-ui/src/style/icon/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GrailStack/Moss/9e54b0274ddb769c411343cb736467867bf28b82/moss-ui/src/style/icon/iconfont.woff
--------------------------------------------------------------------------------
/moss-ui/src/style/index.less:
--------------------------------------------------------------------------------
1 | @import (reference) './constants.less';
2 |
3 | html {
4 | font-size: 100px;
5 | }
6 |
7 | body {
8 | font-family: @font-family-base;
9 | font-size: 0.14rem;
10 | -webkit-font-smoothing: antialiased;
11 | -moz-osx-font-smoothing: grayscale;
12 | -webkit-touch-callout: none;
13 | -webkit-touch-scrolling: touch;
14 | -webkit-overflow-scrolling: touch;
15 | -webkit-tap-highlight-color: rgba(200, 200, 200, 0);
16 | }
17 |
18 | .link,
19 | a,
20 | a:hover,
21 | a:active {
22 | text-decoration-line: none;
23 | }
24 |
25 | p {
26 | line-height: 1.5;
27 | }
28 |
29 | h1 {
30 | margin-bottom: 0.3rem;
31 | font-size: 0.24rem;
32 | line-height: 1.5;
33 | }
34 |
35 | * {
36 | box-sizing: border-box;
37 | }
38 |
39 | pre {
40 | user-select: text;
41 | }
42 |
43 | @import './icon/icon';
44 | @import './form.less';
45 | @import './antDesignOverride.less';
46 |
--------------------------------------------------------------------------------
/moss-ui/src/style/util.less:
--------------------------------------------------------------------------------
1 | /* --- CLEARFIX --- */
2 | .clearfix() {
3 | *zoom: 1;
4 |
5 | &::before,
6 | &::after {
7 | display: table;
8 | line-height: 0;
9 | content: '';
10 | }
11 |
12 | &::after {
13 | clear: both;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/moss-ui/src/util/commonTableRender.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment'
2 |
3 | export const renderBoolean = (booleanValue: boolean | number) => {
4 | return Boolean(Number(booleanValue)) ? '是' : '否'
5 | }
6 |
7 | export const renderDate = (format?: string) => (date: string | number) => {
8 | if (format) {
9 | return moment(String(date), format).fromNow()
10 | } else {
11 | return moment(String(date)).fromNow()
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/moss-ui/src/util/eventbus.ts:
--------------------------------------------------------------------------------
1 | import EventEmitter from 'events';
2 |
3 | export const EventBus = new EventEmitter();
4 | export const EVENTS = { COLLAPSE_CHANGE: 'COLLAPSE_CHANGE' };
5 |
--------------------------------------------------------------------------------
/moss-ui/src/util/timestamp.ts:
--------------------------------------------------------------------------------
1 | // 时间戳转本地时间
2 | export function getLocalTime(str: string) {
3 | return new Date(parseInt(str, 10)).toLocaleString().replace(/:\d{1,2}$/, ' ');
4 | }
5 |
6 | // 获取当前时分秒
7 | export function getTime(timeType: string) {
8 | const myDate = new Date();
9 | const hours = myDate.getHours(); // 获取当前小时数(0-23)
10 | const minutes = myDate.getMinutes(); // 获取当前分钟数(0-59)
11 | const seconds = myDate.getSeconds(); // 获取当前秒数(0-59)
12 | let returnDate = '';
13 | if (timeType === 'hms') {
14 | returnDate = `${hours}:${minutes}:${seconds}`;
15 | }
16 | return returnDate;
17 | }
18 |
19 | export function timestampToTime(timestamp: number) {
20 | const unixTimestamp = new Date(timestamp);
21 | const commonTime = unixTimestamp.toLocaleString();
22 | return commonTime;
23 | }
24 |
--------------------------------------------------------------------------------
/moss-ui/src/util/validator.ts:
--------------------------------------------------------------------------------
1 | const phoneRegexp = new RegExp(/^(\d{3})\d{4}(\d{4})$/);
2 | const passwordRegexp = new RegExp(/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,}$/);
3 |
4 | export function isPhone(str: string): boolean {
5 | return phoneRegexp.test(str);
6 | }
7 |
8 | export function isPassword(str: string): boolean {
9 | return passwordRegexp.test(str);
10 | }
11 |
--------------------------------------------------------------------------------
/moss-ui/stylelint.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = {
3 | extends: ['stylelint-config-standard', 'stylelint-config-recess-order'],
4 | rules: { 'no-descending-specificity': null },
5 | ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'],
6 | };
7 |
--------------------------------------------------------------------------------
/moss-ui/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "importHelpers": true,
7 | "jsx": "react",
8 | "esModuleInterop": true,
9 | "sourceMap": true,
10 | "strict": true,
11 | "noImplicitReturns": true,
12 | "allowSyntheticDefaultImports": true,
13 | "noUnusedLocals": true,
14 | "noUnusedParameters": true,
15 | "skipLibCheck": true,
16 | "pretty": true,
17 | "baseUrl": ".",
18 | "paths": {
19 | "@/*": ["src/*"]
20 | }
21 | },
22 | "include": ["src/*", "src/**/*", "./typings.d.ts"]
23 | }
24 |
--------------------------------------------------------------------------------
/moss-ui/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": ["tslint-react", "tslint-eslint-rules", "tslint-config-prettier"],
4 | "rules": {
5 | "eofline": true,
6 | "no-construct": true,
7 | "no-reference": true,
8 | "jsx-no-multiline-js": false,
9 | "no-object-literal-type-assertion": false,
10 | "no-implicit-dependencies": false,
11 | "no-submodule-imports": false,
12 | "no-console": false,
13 | "curly": true,
14 | "ordered-imports": true,
15 | "object-literal-sort-keys": false,
16 | "variable-name": [true, "ban-keywords", "allow-leading-underscore"],
17 | "no-unsafe-finally": true,
18 | "no-unused-expression": true,
19 | "no-use-before-declare": true,
20 | "no-var-keyword": true,
21 | "triple-equals": true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/moss-web/src/main/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM java:alpine
2 | VOLUME /tmp
3 | ADD moss-web.jar app.jar
4 | ENTRYPOINT ["java","-jar","/app.jar"]
5 |
--------------------------------------------------------------------------------
/moss-web/src/main/java/org/xujin/moss/config/Swagger2Config.java:
--------------------------------------------------------------------------------
1 | package org.xujin.moss.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import springfox.documentation.builders.ApiInfoBuilder;
6 | import springfox.documentation.builders.PathSelectors;
7 | import springfox.documentation.service.ApiInfo;
8 | import springfox.documentation.spi.DocumentationType;
9 | import springfox.documentation.spring.web.plugins.Docket;
10 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
11 |
12 | @Configuration
13 | @EnableSwagger2
14 | public class Swagger2Config {
15 |
16 | @Bean
17 | public Docket createRestApi() {
18 | return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
19 | .paths(PathSelectors.any()).build();
20 | }
21 | private ApiInfo apiInfo() {
22 | return new ApiInfoBuilder().title("服务治理平台").description("统一的服务服务治理平台测试")
23 | .contact("Software_King@qq.com").version("2.0").build();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/moss-web/src/main/resources/META-INF/spring-configuration-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "hints": [],
3 | "groups": [],
4 | "properties": [
5 | {
6 | "name": "logging.moss.path",
7 | "type": "java.lang.String",
8 | "defaultValue":"~/logs",
9 | "description":"logback files prefix."
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/moss-web/src/main/resources/config/application-consul.yml:
--------------------------------------------------------------------------------
1 | management:
2 | server:
3 | port: 8082
4 |
5 |
6 | spring:
7 | cloud:
8 | consul:
9 | discovery:
10 | tags: management.port=${management.port}
--------------------------------------------------------------------------------
/moss-web/src/main/resources/config/application-eureka.yml:
--------------------------------------------------------------------------------
1 | eureka:
2 | instance:
3 | leaseRenewalIntervalInSeconds: 10
4 | health-check-url-path: /actuator/health
5 | prefer-ip-address: true
6 | client:
7 | enabled: false
--------------------------------------------------------------------------------
/moss-web/src/main/resources/config/application-h2.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | datasource:
3 | url: jdbc:h2:mem:moss;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL
4 | username: root
5 | password:
6 | driver-class-name: org.h2.Driver
7 | type: com.alibaba.druid.pool.DruidDataSource
8 | filters: stat
9 | maxActive: 20
10 | initialSize: 1
11 | maxWait: 60000
12 | minIdle: 1
13 | timeBetweenEvictionRunsMillis: 60000
14 | minEvictableIdleTimeMillis: 300000
15 | validationQuery: select 'x'
16 | testWhileIdle: false
17 | testOnBorrow: false
18 | testOnReturn: false
19 | poolPreparedStatements: true
20 | maxOpenPreparedStatements: 20
21 | schema: classpath:db/h2/moss-init.sql
22 | h2:
23 | console:
24 | enabled: true
25 |
--------------------------------------------------------------------------------
/moss-web/src/main/resources/config/application-mysql.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | datasource:
3 | url: jdbc:mysql://${DATASOURCE_HOST:localhost}:${DATASOURCE_PORT:3306}/moss?useUnicode=true&characterEncoding=utf8&useSSL=false
4 | username: ${DATASOURCE_USERNAME:root}
5 | password: ${DATASOURCE_PASSWORD:root123}
6 | driver-class-name: com.mysql.cj.jdbc.Driver
7 | type: com.alibaba.druid.pool.DruidDataSource
8 | filters: stat
9 | maxActive: 20
10 | initialSize: 1
11 | maxWait: 60000
12 | minIdle: 1
13 | timeBetweenEvictionRunsMillis: 60000
14 | minEvictableIdleTimeMillis: 300000
15 | validationQuery: select 'x'
16 | testWhileIdle: true
17 | testOnBorrow: false
18 | testOnReturn: false
19 | poolPreparedStatements: true
20 | maxOpenPreparedStatements: 20
21 |
--------------------------------------------------------------------------------
/moss-web/src/main/resources/config/application-nacos.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | nacos:
4 | discovery:
5 | server-addr: 127.0.0.1:8848
6 | maxOpenPreparedStatements: 20
7 |
8 |
--------------------------------------------------------------------------------
/moss-web/src/main/resources/config/application-zookeeper.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | zookeeper:
4 | connect-string: localhost:2181
5 | discovery:
6 | root: /moss-client
7 | management:
8 | endpoints:
9 | web:
10 | exposure:
11 | include: '*'
12 | exclude: ['pause', 'refresh', 'restart', 'resume', 'shutdown', 'heapdump']
13 | jmx:
14 | exposure:
15 | include: '*'
16 | exclude: ['pause', 'refresh', 'restart', 'resume', 'shutdown', 'heapdump']
17 | endpoint:
18 | health:
19 | show-details: always
20 | heapdump:
21 | enabled: false
22 | pause:
23 | enabled: false
24 | refresh:
25 | enabled: false
26 | restart:
27 | enabled: false
28 | resume:
29 | enabled: false
30 | shutdown:
31 | enabled: false
32 | info:
33 | git:
34 | mode: full
35 |
--------------------------------------------------------------------------------
/moss-web/src/main/resources/config/application.properties:
--------------------------------------------------------------------------------
1 | info.groupId: @project.groupId@
2 | info.artifactId: @project.artifactId@
3 | info.version: @project.version@
4 |
--------------------------------------------------------------------------------
/moss-web/src/main/resources/config/readme.md:
--------------------------------------------------------------------------------
1 | # Application Properties
2 |
3 | you can easily change the registry and backend database type by `spring.profiles.active`
--------------------------------------------------------------------------------
/moss-web/src/main/resources/static/index.html:
--------------------------------------------------------------------------------
1 | 莫斯-服务治理平台
--------------------------------------------------------------------------------
/moss-web/src/main/resources/static/static/MYSQL.15a5498c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GrailStack/Moss/9e54b0274ddb769c411343cb736467867bf28b82/moss-web/src/main/resources/static/static/MYSQL.15a5498c.png
--------------------------------------------------------------------------------
/moss-web/src/main/resources/static/static/delIcon.8939d775.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GrailStack/Moss/9e54b0274ddb769c411343cb736467867bf28b82/moss-web/src/main/resources/static/static/delIcon.8939d775.jpg
--------------------------------------------------------------------------------
/moss-web/src/main/resources/static/static/kafka.bd032ad8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GrailStack/Moss/9e54b0274ddb769c411343cb736467867bf28b82/moss-web/src/main/resources/static/static/kafka.bd032ad8.png
--------------------------------------------------------------------------------
/moss-web/src/main/resources/static/static/warning.f07d2bc9.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GrailStack/Moss/9e54b0274ddb769c411343cb736467867bf28b82/moss-web/src/main/resources/static/static/warning.f07d2bc9.gif
--------------------------------------------------------------------------------