From 9ad7cff6cbbe45fdd60be92efadc3c8e49413e37 Mon Sep 17 00:00:00 2001 From: "huoyong.msb" Date: Mon, 20 Jul 2020 16:25:21 +0800 Subject: [PATCH] feat: sync from RAP2@alibaba-internal to RAP2@CE --- package.json | 59 ++-- public/index.html | 2 +- src/actions/account.ts | 92 +++++ src/actions/rootAction.ts | 19 + src/actions/types.ts | 10 + src/assets/components.sass | 20 +- src/assets/index.css.map | 2 +- src/assets/index.sass | 19 +- src/components/account/LoginForm.sass | 8 +- src/components/account/MySettings.tsx | 57 +++ src/components/account/MySettingsView.tsx | 49 +++ src/components/account/RegisterForm.sass | 8 +- src/components/account/ThemeChangeOverlay.tsx | 247 +++++++++++++ src/components/account/UserList.sass | 8 +- src/components/api/API.sass | 16 +- src/components/checker/Checker.sass | 14 +- src/components/common/Footer.sass | 4 +- src/components/common/Footer.tsx | 1 + src/components/common/GlobalStyles.tsx | 15 + src/components/common/LoadingButton.tsx | 10 +- src/components/common/Message.tsx | 1 - src/components/common/MuiTheme.tsx | 31 +- src/components/common/NoData.tsx | 11 + src/components/editor/DefaultValueModal.tsx | 2 +- src/components/editor/HistoryLogDrawer.tsx | 137 ++++++++ src/components/editor/Importer.tsx | 6 +- src/components/editor/InterfaceEditor.tsx | 18 +- .../editor/InterfaceEditorToolbar.tsx | 56 ++- src/components/editor/InterfaceForm.tsx | 2 +- src/components/editor/InterfaceList.tsx | 30 +- src/components/editor/InterfacePreviewer.tsx | 8 +- .../editor/InterfaceSummary.css.map | 2 +- src/components/editor/InterfaceSummary.sass | 37 +- src/components/editor/InterfaceSummary.tsx | 328 +++++++++--------- src/components/editor/ModuleList.tsx | 17 +- src/components/editor/MoveInterfaceForm.tsx | 2 +- src/components/editor/MoveModuleForm.tsx | 2 +- .../editor/RapperInstallerModal.tsx | 20 +- .../editor/RepositoryEditor.css.map | 2 +- src/components/editor/RepositoryEditor.sass | 86 +++-- src/components/editor/RepositoryEditor.tsx | 180 ++++++---- src/components/editor/RepositorySearcher.tsx | 17 +- src/components/home/AboutView.tsx | 41 +++ src/components/home/Home.sass | 16 +- .../home/JoinedRepositoriesCard.tsx | 2 +- src/components/home/LogsCard.tsx | 10 +- src/components/home/OwnedRepositoriesCard.tsx | 2 +- src/components/layout/Logo.tsx | 12 +- src/components/layout/MainMenu.tsx | 132 ++++--- src/components/organization/Organization.sass | 30 +- .../organization/OrganizationForm.tsx | 2 +- .../repository/ImportRepositoryForm.tsx | 62 ++-- src/components/repository/Repository.sass | 28 +- src/components/repository/RepositoryForm.tsx | 17 +- src/components/status/Status.sass | 12 +- src/components/status/Status.tsx | 19 +- src/components/tester/Tester.sass | 24 +- src/components/utils/Dialog.sass | 12 +- src/components/utils/Modal.sass | 12 +- src/components/utils/Pagination.sass | 4 +- src/components/utils/Popover.sass | 4 +- src/components/utils/PropertyEditor.sass | 8 +- src/components/utils/RChart.tsx | 2 +- src/components/utils/RModal.sass | 14 +- src/components/utils/Spin.tsx | 4 +- src/components/utils/TagsInput.sass | 4 +- src/components/utils/Utils.sass | 2 +- src/config/config.dev.ts | 3 +- src/config/config.prod.ts | 1 + src/config/index.ts | 1 + src/family/Family.tsx | 5 +- src/family/GlobalProvider.tsx | 2 +- src/family/handleLocation.ts | 3 + src/family/start.tsx | 40 ++- src/index.tsx | 3 + src/relatives/AccountRelative.ts | 60 +++- src/relatives/effects/interface.ts | 5 +- src/relatives/effects/repository.ts | 10 +- src/relatives/services/Repository.ts | 18 +- src/routes.tsx | 168 +++++---- src/types/index.d.ts | 17 + src/types/redux-api-middleware.d.ts | 148 ++++++++ src/utils/DateUtility.ts | 30 ++ src/utils/consts.ts | 26 ++ tsconfig.json | 9 +- 85 files changed, 1930 insertions(+), 749 deletions(-) create mode 100644 src/actions/rootAction.ts create mode 100644 src/components/account/MySettings.tsx create mode 100644 src/components/account/MySettingsView.tsx create mode 100644 src/components/account/ThemeChangeOverlay.tsx create mode 100644 src/components/common/NoData.tsx create mode 100644 src/components/editor/HistoryLogDrawer.tsx create mode 100644 src/components/home/AboutView.tsx create mode 100644 src/types/redux-api-middleware.d.ts create mode 100644 src/utils/DateUtility.ts diff --git a/package.json b/package.json index 06ca227..ee937d0 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,6 @@ "description": "", "main": "app.js", "scripts": { - "dev": "npm run start", "build-css": "node ./node_modules/sass/sass src/:src/ --quiet", "watch-css": "npm run build-css && node ./node_modules/sass/sass src/:src/ --watch", "start-js": "react-scripts start", @@ -13,41 +12,45 @@ "test-backup": "npm run lint && react-scripts test --env=jsdom", "test": "npm run lint", "eject": "react-scripts eject", - "lint": "tslint --project ./ -c tslint.json --fix", - "build-docker": "docker build --rm -f \"Dockerfile\" -t rapteam/rap2-dolores:latest ." + "dev": "npm run start", + "lint": "tslint --project ./ -c tslint.json --fix" }, "repository": { "type": "git", "url": "git@gitlab.alibaba-inc.com:thx/rap2-dolores.git" }, + "engines": { + "install-alinode": "v5.15.0" + }, "author": "mozhi.gyy@alibaba-inc.com", "license": "ISC", "dependencies": { - "@material-ui/core": "^4.4.3", - "@material-ui/icons": "^4.4.3", - "@material-ui/pickers": "^3.2.6", - "@material-ui/styles": "^4.4.3", + "@material-ui/core": "^4.11.0", + "@material-ui/icons": "^4.9.1", + "@material-ui/pickers": "^3.2.10", + "@material-ui/styles": "^4.10.0", "@types/json5": "^0.0.30", - "@welldone-software/why-did-you-render": "^4.0.3", + "@welldone-software/why-did-you-render": "^4.2.5", "animate.css": "3.7.2", "awesome-debounce-promise": "^2.1.0", - "chart.js": "^2.8.0", + "chart.js": "^2.9.3", "classnames": "^2.2.6", "clipboard-copy": "^3.1.0", "codemirror": "5.49.0", "connected-react-router": "^6.5.2", "debounce-promise": "^3.1.2", - "formik": "^1.5.8", - "formik-material-ui": "^0.0.22", + "formik": "^2.1.4", + "formik-material-ui": "^2.0.1", "graceful": "1.0.2", "history": "^4.10.1", "jquery": "^3.4.1", - "json5": "^2.1.0", + "json5": "^2.1.3", "koa": "2.8.1", "koa-router": "7.4.0", "koa-session": "5.12.3", "koa-static": "5.0.0", "lodash": "4.17.15", + "markdown-to-jsx": "^6.11.4", "mockjs": "1.1.0", "moment": "2.24.0", "node-fetch": "2.6.0", @@ -58,19 +61,21 @@ "popper.js": "^1.15.0", "prop-types": "15.7.2", "rc-tooltip": "^3.7.3", - "react": "^16.9.0", - "react-custom-scroll": "^4.2.0", - "react-dom": "^16.9.0", + "react": "^16.13.1", + "react-custom-scroll": "^4.2.1", + "react-dom": "^16.13.1", "react-hotkeys": "^2.0.0", "react-icons": "3.7.0", + "react-joyride": "^2.2.0", "react-modal": "3.10.1", - "react-redux": "^7.1.1", - "react-router": "5.1.0", - "react-router-config": "5.1.0", - "react-router-dom": "5.1.0", - "react-select": "^3.0.5", - "redux": "4.0.4", - "redux-saga": "1.1.1", + "react-redux": "^7.2.0", + "react-router": "5.2.0", + "react-router-config": "5.1.1", + "react-router-dom": "5.2.0", + "react-select": "^3.1.0", + "redux": "4.0.5", + "redux-api-middleware": "^3.2.1", + "redux-saga": "1.1.3", "reselect": "^4.0.0", "sortablejs": "1.10.0", "urijs": "1.19.1", @@ -86,7 +91,7 @@ ] }, "devDependencies": { - "@types/chart.js": "^2.8.5", + "@types/chart.js": "^2.9.22", "@types/classnames": "^2.2.9", "@types/codemirror": "^0.0.77", "@types/history": "^4.7.3", @@ -112,10 +117,10 @@ "pre-commit": "^1.2.2", "react-scripts": "^3.1.2", "standard": "14.3.1", - "tslint": "^5.20.0", - "tslint-react": "^4.1.0", - "tslint-react-hooks": "^2.2.1", - "typescript": "^3.8.3" + "tslint": "^6.1.2", + "tslint-react": "^5.0.0", + "tslint-react-hooks": "^2.2.2", + "typescript": "^3.9.6" }, "pre-commit": [ "lint" diff --git a/public/index.html b/public/index.html index 8814ea6..39ea839 100644 --- a/public/index.html +++ b/public/index.html @@ -13,7 +13,7 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - RAP2 + RAP接口管理平台
diff --git a/src/actions/account.ts b/src/actions/account.ts index 4b53fc9..f07e7b5 100644 --- a/src/actions/account.ts +++ b/src/actions/account.ts @@ -1,3 +1,9 @@ +import { THEME_TEMPLATE_KEY } from 'components/account/ThemeChangeOverlay' +import { CACHE_KEY } from 'utils/consts' +import { mergeRSAABase } from './rootAction' +import { RSAA } from 'redux-api-middleware' +import { serve } from 'relatives/services/constant' + // 登陆 export const login = (user: any, onResolved: any) => ({ type: 'USER_LOGIN', user, onResolved }) export const loginSucceeded = (user: any) => ({ type: 'USER_LOGIN_SUCCEEDED', user }) @@ -67,3 +73,89 @@ export const findpwdFailed = (message: any) => ({ type: 'USER_FINDPWD_FAILED', m export const resetpwd = (user: any, onResolved: any) => ({ type: 'USER_RESETPWD', user, onResolved }) export const resetpwdSucceeded = () => ({ type: 'USER_RESETPWD_SUCCEEDED' }) export const resetpwdFailed = (message: any) => ({ type: 'USER_RESETPWD_FAILED', message }) +export type CHANGE_THEME = 'CHANGE_THEME' +export const CHANGE_THEME: CHANGE_THEME = 'CHANGE_THEME' + +export const changeTheme = (themeId: THEME_TEMPLATE_KEY) => ({ + type: CHANGE_THEME, + payload: themeId, +}) + +export type UPDATE_USER_SETTING_REQUEST = 'UPDATE_USER_SETTING_REQUEST' +export const UPDATE_USER_SETTING_REQUEST: UPDATE_USER_SETTING_REQUEST = 'UPDATE_USER_SETTING_REQUEST' + +export type UPDATE_USER_SETTING_SUCCESS = 'UPDATE_USER_SETTING_SUCCESS' +export const UPDATE_USER_SETTING_SUCCESS: UPDATE_USER_SETTING_SUCCESS = 'UPDATE_USER_SETTING_SUCCESS' + +export type UPDATE_USER_SETTING_FAILURE = 'UPDATE_USER_SETTING_FAILURE' +export const UPDATE_USER_SETTING_FAILURE: UPDATE_USER_SETTING_FAILURE = 'UPDATE_USER_SETTING_FAILURE' + +export function updateUserSetting(key: CACHE_KEY, value: string) { + return { + [RSAA]: mergeRSAABase({ + endpoint: `${serve}/account/updateUserSetting/${key}`, + method: 'POST', + body: JSON.stringify(value ? { value } : {}), + types: [UPDATE_USER_SETTING_REQUEST, UPDATE_USER_SETTING_SUCCESS, UPDATE_USER_SETTING_SUCCESS], + }), + } +} + +export type DO_UPDATE_USER_SETTING = 'DO_UPDATE_USER_SETTING' +export const DO_UPDATE_USER_SETTING = 'DO_UPDATE_USER_SETTING' + +export const doUpdateUserSetting = (key: CACHE_KEY, value: string, cb: TCB) => ({ + type: DO_UPDATE_USER_SETTING, + payload: { + cb, + key, + value, + }, +}) + +export interface DoUpdateUserSettingAction { + type: DO_UPDATE_USER_SETTING + payload: { + cb: TCB + key: CACHE_KEY + value: string + } +} + +export type FETCH_USER_SETTINGS_REQUEST = 'FETCH_USER_SETTINGS_REQUEST' +export const FETCH_USER_SETTINGS_REQUEST: FETCH_USER_SETTINGS_REQUEST = 'FETCH_USER_SETTINGS_REQUEST' + +export type FETCH_USER_SETTINGS_SUCCESS = 'FETCH_USER_SETTINGS_SUCCESS' +export const FETCH_USER_SETTINGS_SUCCESS: FETCH_USER_SETTINGS_SUCCESS = 'FETCH_USER_SETTINGS_SUCCESS' + +export type FETCH_USER_SETTINGS_FAILURE = 'FETCH_USER_SETTINGS_FAILURE' +export const FETCH_USER_SETTINGS_FAILURE: FETCH_USER_SETTINGS_FAILURE = 'FETCH_USER_SETTINGS_FAILURE' + +export function fetchUserSettings(keys: CACHE_KEY[]) { + return { + [RSAA]: mergeRSAABase({ + endpoint: `${serve}/account/fetchUserSettings`, + method: 'POST', + body: JSON.stringify({ keys }), + types: [FETCH_USER_SETTINGS_REQUEST, FETCH_USER_SETTINGS_SUCCESS, FETCH_USER_SETTINGS_SUCCESS], + }), + } +} + +export type DO_FETCH_USER_SETTINGS = 'DO_FETCH_USER_SETTINGS' +export const DO_FETCH_USER_SETTINGS: DO_FETCH_USER_SETTINGS = 'DO_FETCH_USER_SETTINGS' + +export function doFetchUserSettings(keys: CACHE_KEY[], cb?: (isOk: boolean, payload?: any) => void): DoFetchUserSettingsAction { + return { + type: DO_FETCH_USER_SETTINGS, + payload: { keys, cb }, + } +} + +export interface DoFetchUserSettingsAction { + type: DO_FETCH_USER_SETTINGS + payload: { + keys: CACHE_KEY[] + cb?: (isOk: boolean, payload?: any) => void + } +} diff --git a/src/actions/rootAction.ts b/src/actions/rootAction.ts new file mode 100644 index 0000000..97cdcad --- /dev/null +++ b/src/actions/rootAction.ts @@ -0,0 +1,19 @@ +import { ApiError, IRSAA } from 'redux-api-middleware' + +export interface CommonFetchFailureAction { + payload: ApiError + error: true +} + +const RSAA_BASE: Partial = { + credentials: 'include', + method: 'GET', + headers: { 'Content-Type': 'application/json' }, +} + +export const mergeRSAABase = (options: Partial) => { + return { + ...RSAA_BASE, + ...options, + } as IRSAA +} diff --git a/src/actions/types.ts b/src/actions/types.ts index d9ea8b0..97c9cfd 100644 --- a/src/actions/types.ts +++ b/src/actions/types.ts @@ -1,4 +1,5 @@ import { RouterState } from 'connected-react-router' +import { THEME_TEMPLATE_KEY } from 'components/account/ThemeChangeOverlay' export interface RootState { auth: any @@ -17,6 +18,11 @@ export interface RootState { logs: any loading: boolean message: IMessage + + userSettings: { [key: string]: string } + userSettingsIsUpdating: boolean + + themeId: THEME_TEMPLATE_KEY } export interface Organization { @@ -103,7 +109,11 @@ export interface RepositoryFormData { collaboratorIdstring?: string + canUserEdit?: boolean + token?: string + + modules?: Module[] } export interface Repository { diff --git a/src/assets/components.sass b/src/assets/components.sass index 70235b2..3c0abfc 100644 --- a/src/assets/components.sass +++ b/src/assets/components.sass @@ -55,7 +55,7 @@ input[type="checkbox"] .btn line-height: 1.5 .rapfont - line-height: 1rem + line-height: 0.65rem margin-right: .5rem a.btn.btn-success color: white @@ -82,10 +82,10 @@ a.btn.btn-success // &:hover // background-color: $brand-hover // &.btn-rapfont -// padding-right: 2rem +// padding-right: 1.3rem // .rapfont -// font-size: 1rem -// margin-right: 0.5rem +// font-size: 0.65rem +// margin-right: 0.325rem // ---------------------------------------- // 表格 Table @@ -114,7 +114,7 @@ table.table // ---------------------------------------- // .panel -// margin-bottom: 1rem +// margin-bottom: 0.65rem // border: 1px solid $border // border-radius: 0.3rem // > .panel-header, @@ -137,7 +137,7 @@ table.table left: 50% top: 50% width: 20rem - height: 4rem + height: 2.6rem margin-left: -10rem margin-top: -2rem .Spin @@ -179,7 +179,7 @@ button:focus display: none float: left min-width: 10rem - padding: 0.5rem 0 + padding: 0.325rem 0 margin: 0.125rem 0 0 font-size: 1rem color: #212529 @@ -305,7 +305,7 @@ button:focus .dropdown-divider height: 0 - margin: 0.5rem 0 + margin: 0.325rem 0 overflow: hidden border-top: 1px solid #e9ecef @@ -338,9 +338,9 @@ button:focus .dropdown-header display: block - padding: 0.5rem 1.5rem + padding: 0.325rem 1.5rem margin-bottom: 0 - font-size: 0.875rem + font-size: 1rem color: #6c757d white-space: nowrap diff --git a/src/assets/index.css.map b/src/assets/index.css.map index e7a3521..7fc9f8c 100644 --- a/src/assets/index.css.map +++ b/src/assets/index.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["fonts.sass","components.sass","variables.sass","shortcuts.sass","index.sass"],"names":[],"mappings":";AAIA;AACE;EACA;EACA;EACA;;AACF;EACE;;;AAEF;AACE;EACA;EACA;EACA;;AACF;EACE;;;AAGF;EACE;EACA;EACA;;AACF;EACE;;;ACnBF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE,cCdU;EDeV;;;AAEJ;AAAA;EAEE;;;AAEF;AAAA;EAEE;;;AAGA;EACE;EACA;;AACF;EACE;EACA;EACA;;AACA;EACE;;;AAEN;EAEI;IACE;;;AAEN;EAEI;IACE;;;AAMN;EACE;;AACA;EACE;EACA;;;AACJ;EACE;;;AAoCI;EACE;EACA;EACA;;AAGF;EACE;;AACA;EACE;;AAGF;EACE;;;AAyBV;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;;;AAGJ;EACE;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;;;AAEJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;IACE;IACA;;;EACF;IACE;IACA;;;AAEJ;EACE;IACE;IACA;;;EACF;IACE;IACA;;;AAEJ;EACE;IACE;IACA;;;EACF;IACE;IACA;;;AAEJ;EACE;IACE;IACA;;;EACF;IACE;IACA;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;;;AAGJ;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;;AACF;EACE;;;AAGJ;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AACF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;;AACF;EACE;;;AAGJ;EACE;EACA;;;AAEJ;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AACF;EACE;EACA;EACA;;AACF;EACE;EACA;EACA;;;AAEJ;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AEvVF;EACE;;;AAEF;EACE;;;AAMF;EACE,ODbY;ECcZ;;AACA;EACE,ODhBU;;;ACuBd;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAGF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAOA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AAEJ;EACE;;;AACF;AAAA;EAEE;;;AACF;EACI;;;AACJ;EACE;;;AAOA;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAGF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AC5FJ;EACE;;;AACF;EACI;EACA;EACA;EACA;;;AAEJ;EACI;;;AAEJ;EACI;EACA;EACA;;;AAEJ;EACI;;;AAEJ;EACE;EACA;EACA,aFPY;EEQZ;EACE;EACF;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;;AACA;EACE;EACA;EACA;;AACA;EACE;EACA;EACA;;AACA;EACE;EACA;;AACF;EACE;EACA;EACA;;AACA;EACE;;;AAEV;EACE;EACA,aF1CY;EE2CZ;;;AAMA;EACE,OFrEU;EEsEV;EACA;;AACF;EAEE;EACA;;;AAGF;EACE;;;AAEJ;EACE;EACA;EACA;EACA;EACA,kBF/ES;EEgFT;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;;;AAGF;EACE;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AACA;EACE;EACA;;AACF;EACE;EACA;;AACJ;EACE;;AACF;EACE;EACA;;AACF;EACE;EACA;EACA;;AACF;EACE;EACA;EACA;;;AAEJ;EACE;;;AAEF;EACE","file":"index.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["fonts.sass","components.sass","variables.sass","shortcuts.sass","index.sass"],"names":[],"mappings":";AAIA;AACE;EACA;EACA;EACA;;AACF;EACE;;;AAEF;AACE;EACA;EACA;EACA;;AACF;EACE;;;AAGF;EACE;EACA;EACA;;AACF;EACE;;;ACnBF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE,cCdU;EDeV;;;AAEJ;AAAA;EAEE;;;AAEF;AAAA;EAEE;;;AAGA;EACE;EACA;;AACF;EACE;EACA;EACA;;AACA;EACE;;;AAEN;EAEI;IACE;;;AAEN;EAEI;IACE;;;AAMN;EACE;;AACA;EACE;EACA;;;AACJ;EACE;;;AAoCI;EACE;EACA;EACA;;AAGF;EACE;;AACA;EACE;;AAGF;EACE;;;AAyBV;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;;;AAGJ;EACE;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;;;AAEJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;IACE;IACA;;;EACF;IACE;IACA;;;AAEJ;EACE;IACE;IACA;;;EACF;IACE;IACA;;;AAEJ;EACE;IACE;IACA;;;EACF;IACE;IACA;;;AAEJ;EACE;IACE;IACA;;;EACF;IACE;IACA;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;;;AAGJ;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;;AACF;EACE;;;AAGJ;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AACF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;;AACF;EACE;;;AAGJ;EACE;EACA;;;AAEJ;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AACF;EACE;EACA;EACA;;AACF;EACE;EACA;EACA;;;AAEJ;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AEvVF;EACE;;;AAEF;EACE;;;AAMF;EACE,ODbY;ECcZ;;AACA;EACE,ODhBU;;;ACuBd;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAGF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAOA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AAEJ;EACE;;;AACF;AAAA;EAEE;;;AACF;EACI;;;AACJ;EACE;;;AAOA;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAnBF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AACF;EACE;;;AAGF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AAHF;EACE;;;AACF;EACE;;;AC5FJ;EACE;;;AACF;EACI;EACA;EACA;EACA;;;AAEJ;EACI;;;AAEJ;EACI;EACA;EACA;;;AAEJ;EACI;;;AAEJ;EACE;EACA;EACA,aFPY;EEQZ;EACE;EACF;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;;AACA;EACE;EACA;EACA;;AACA;EACE;EACA;EACA;;AACA;EACE;EACA;;AACF;EACE;EACA;EACA;;AACA;EACE;;;AAEV;EACE;EACA,aF1CY;EE2CZ;;;AAMA;EACE,OFrEU;EEsEV;EACA;;AACF;EAEE;EACA;;;AAGF;EACE;;;AAEJ;EACE;EACA;EACA;EACA;EACA,kBF/ES;EEgFT;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;;;AAGF;EACE;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AACA;EACE;EACA;;AACF;EACE;EACA;;AACJ;EACE;;AACF;EACE;EACA;;AACF;EACE;EACA;EACA;;AACF;EACE;EACA;EACA;;;AAEJ;EACE;;;AAEF;EACE","file":"index.css"} \ No newline at end of file diff --git a/src/assets/index.sass b/src/assets/index.sass index 705e0d0..b9111a2 100644 --- a/src/assets/index.sass +++ b/src/assets/index.sass @@ -7,7 +7,7 @@ @import "./shortcuts.sass" html - font-size: 62.5% // 10 ÷ 16 × 100% = 62.5% + font-size: 12px html font-family: sans-serif line-height: 1.15 @@ -26,7 +26,7 @@ img, svg vertical-align: middle body - font-size: 1.2rem + font-size: 1rem line-height: 1.5 font-family: $font-family -webkit-font-smoothing: antialiased @@ -62,7 +62,7 @@ html, body flex-grow: 1 button, input, optgroup, select, textarea - font-size: 1.2rem + font-size: 1rem font-family: $font-family -webkit-font-smoothing: antialiased @@ -85,7 +85,7 @@ a.text-decoration pre margin: 0 - padding: 0.5rem 0.75rem + padding: 0.325rem 0.75rem border: 1px solid $border border-radius: 0.4rem background-color: $bg @@ -129,6 +129,7 @@ pre border-radius: .25rem .card-header + font-size: 1.1rem padding: .75rem 1.25rem margin-bottom: 0 background-color: rgba(0,0,0,.03) @@ -168,20 +169,20 @@ code .alert position: relative padding: .75rem 1.25rem - margin-bottom: 1rem + margin-bottom: 0.65rem border: 1px solid transparent border-radius: .25rem margin-bottom: 0 .title - margin-right: 1rem + margin-right: 0.65rem .icon - font-size: 1.4rem + font-size: 1rem margin-right: .5rem .msg font-weight: bold - margin-right: 1rem + margin-right: 0.65rem a - margin-right: 1rem + margin-right: 0.65rem &.alert-warning color: #856404 background-color: #fff3cd diff --git a/src/components/account/LoginForm.sass b/src/components/account/LoginForm.sass index 3dd3239..24372ec 100644 --- a/src/components/account/LoginForm.sass +++ b/src/components/account/LoginForm.sass @@ -15,13 +15,13 @@ border: 1px solid #E6E6E6 border-radius: .5rem .header - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem border-bottom: 1px solid $border .title - font-size: 2rem + font-size: 1.3rem .body - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem .footer - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem border-top: 1px solid $border diff --git a/src/components/account/MySettings.tsx b/src/components/account/MySettings.tsx new file mode 100644 index 0000000..9741adf --- /dev/null +++ b/src/components/account/MySettings.tsx @@ -0,0 +1,57 @@ +import React, { useState } from 'react' +import { Paper, Theme, List, ListSubheader, makeStyles, ListItem, ListItemIcon, ListItemText, ListItemSecondaryAction, IconButton } from '@material-ui/core' +import Settings from '@material-ui/icons/Settings' +import Palette from '@material-ui/icons/Palette' +import ThemeChangeOverlay, { THEME_TEMPLATE_KEY } from './ThemeChangeOverlay' +import { CACHE_KEY } from 'utils/consts' + +const useStyles = makeStyles(({ spacing }: Theme) => ({ + root: { + padding: spacing(1), + maxWidth: 400, + }, +})) + +interface Props { + isFetching: boolean + data: { [key: string]: string } + onChange: (key: CACHE_KEY, val: string) => void +} + +function MySettings(props: Props) { + const classes = useStyles() + const { data, onChange, isFetching } = props + const [editingThemeTemplate, setEditingThemeTemplate] = useState(false) + + const themeId = data[CACHE_KEY.THEME_ID] as THEME_TEMPLATE_KEY || THEME_TEMPLATE_KEY.RED + + const handleClose = (themeId?: THEME_TEMPLATE_KEY) => { + setEditingThemeTemplate(false) + themeId && onChange(CACHE_KEY.THEME_ID, themeId) + } + + return ( + + 偏好设置}> + + + + + + + setEditingThemeTemplate(true)}> + + + + + + + + ) +} + +export default MySettings diff --git a/src/components/account/MySettingsView.tsx b/src/components/account/MySettingsView.tsx new file mode 100644 index 0000000..43f6609 --- /dev/null +++ b/src/components/account/MySettingsView.tsx @@ -0,0 +1,49 @@ +import React, { useEffect } from 'react' +import { makeStyles } from '@material-ui/styles' +import { useDispatch, useSelector } from 'react-redux' +import { CACHE_KEY } from 'utils/consts' +import MySettings from './MySettings' +import { RootState } from 'actions/types' +import { fetchUserSettings, doUpdateUserSetting } from 'actions/account' +import { Theme } from '@material-ui/core' + +const useStyles = makeStyles(({ spacing }: Theme ) => ({ + root: { + padding: spacing(2), + }, +})) + +const SETTING_KEYS: CACHE_KEY[] = [ + CACHE_KEY.THEME_ID, +] + +function MySettingsView() { + const classes = useStyles() + const dispatch = useDispatch() + const settings = useSelector((state: RootState) => state.userSettings) + const isFetching = useSelector((state: RootState) => state.userSettingsIsUpdating) + + useEffect(() => { + dispatch(fetchUserSettings(SETTING_KEYS)) + }, [dispatch]) + + const handleSettingChange = (key: CACHE_KEY, val: string) => { + dispatch(doUpdateUserSetting(key, val, isOk => { + if (isOk) { + fetchUserSettings(SETTING_KEYS) + } + })) + } + + return ( +
+ +
+ ) +} + +export default MySettingsView diff --git a/src/components/account/RegisterForm.sass b/src/components/account/RegisterForm.sass index 7c0783f..cbf252f 100644 --- a/src/components/account/RegisterForm.sass +++ b/src/components/account/RegisterForm.sass @@ -15,13 +15,13 @@ border: 1px solid #E6E6E6 border-radius: .5rem .header - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem border-bottom: 1px solid $border .title - font-size: 2rem + font-size: 1.3rem .body - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem .footer - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem border-top: 1px solid $border diff --git a/src/components/account/ThemeChangeOverlay.tsx b/src/components/account/ThemeChangeOverlay.tsx new file mode 100644 index 0000000..bf8fff8 --- /dev/null +++ b/src/components/account/ThemeChangeOverlay.tsx @@ -0,0 +1,247 @@ +import React, { useState, useEffect } from 'react' +import { ThemeOptions } from '@material-ui/core/styles/createMuiTheme' +import { grey, red, pink, purple, orange, blue, green, cyan, indigo } from '@material-ui/core/colors' +import { Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Button, Theme } from '@material-ui/core' +import { SimplePaletteColorOptions, makeStyles, createStyles } from '@material-ui/core/styles' +import { useDispatch } from 'react-redux' +import classnames from 'classnames' +import { changeTheme } from 'actions/account' + +export enum THEME_TEMPLATE_KEY { + INDIGO = 'INDIGO', // DEFAULT + RED = 'RED', + BLACK = 'BLACK', + BLUE = 'BLUE', + GREEN = 'GREEN', + PINK = 'PINK', + ORANGE = 'ORANGE', + PURPLE = 'PURPLE', + CYAN = 'CYAN', +} + +export const THEME_TEMPLATE_KEY_LIST = [ + THEME_TEMPLATE_KEY.INDIGO, + THEME_TEMPLATE_KEY.RED, + THEME_TEMPLATE_KEY.BLACK, + THEME_TEMPLATE_KEY.BLUE, + THEME_TEMPLATE_KEY.GREEN, + THEME_TEMPLATE_KEY.PINK, + THEME_TEMPLATE_KEY.ORANGE, + THEME_TEMPLATE_KEY.PURPLE, + THEME_TEMPLATE_KEY.CYAN, +] + +const useStyles = makeStyles(({ palette, spacing }: Theme) => createStyles({ + themeOptionList: { + display: 'flex', + flexDirection: 'row', + }, + themeOption: { + display: 'flex', + flexDirection: 'column', + marginRight: spacing(0.5), + }, + optionTitle: { + marginTop: spacing(0.5), + textAlign: 'center', + }, + optionColor: { + width: 50, + height: 50, + }, + themeOptionOn: { + color: '#FFFFFF', + backgroundColor: palette.primary.main, + }, +})) + +interface Props { + handleClose: (themeId?: THEME_TEMPLATE_KEY) => void + open: boolean + val: THEME_TEMPLATE_KEY +} + +function ThemeChangeOverlay(props: Props) { + const { handleClose, open, val } = props + const [themeId, setThemeId] = useState(THEME_TEMPLATE_KEY.INDIGO) + const dispatch = useDispatch() + const classes = useStyles() + const onChange = (themeId: THEME_TEMPLATE_KEY) => { + setThemeId(themeId) + dispatch(changeTheme(themeId)) + } + useEffect(() => { + setThemeId(val) + }, [val]) + return ( +
+ handleClose()} aria-labelledby="form-dialog-title"> + 换肤 + + 请选择喜爱的皮肤 +
+ {THEME_TEMPLATE_KEY_LIST.map(key => ({ ...THEME_TEMPLATES[key], key })).map(template => + )} +
+
+ + + + +
+
+ ) +} + + + +export const THEME_TEMPLATES: { [key: string]: { theme: ThemeOptions, name: string } } = { + [THEME_TEMPLATE_KEY.INDIGO]: { + name: '沉靛蓝', + theme: { + palette: { + primary: { + main: indigo[500], + light: indigo[300] + }, + secondary: pink, + } + } + }, + [THEME_TEMPLATE_KEY.RED]: { + name: '火焰红', + theme: { + palette: { + primary: { + main: red[600], + light: red[50], + }, + secondary: { + main: pink[400], + }, + }, + }, + }, + [THEME_TEMPLATE_KEY.BLACK]: { + name: '高级黑', + theme: { + palette: { + primary: { + main: grey[900], + light: grey[50], + }, + secondary: { + main: '#000000', + }, + }, + }, + }, + [THEME_TEMPLATE_KEY.BLUE]: { + name: '忧郁蓝', + theme: { + palette: { + primary: { + main: '#2196f3', + light: blue[50], + }, + secondary: { + main: '#1769aa', + }, + }, + }, + }, + [THEME_TEMPLATE_KEY.GREEN]: { + name: '原谅绿', + theme: { + palette: { + primary: { + main: '#357a38', + light: green[50], + }, + secondary: { + main: '#4caf50', + }, + }, + }, + }, + [THEME_TEMPLATE_KEY.PINK]: { + name: '公主粉', + theme: { + palette: { + primary: { + main: '#ed4b82', + light: pink[50], + }, + secondary: { + main: '#e91e63', + }, + }, + }, + }, + [THEME_TEMPLATE_KEY.ORANGE]: { + name: '动感橙', + theme: { + palette: { + primary: { + main: '#ff9800', + light: orange[50], + }, + secondary: { + main: '#b26a00', + }, + }, + }, + }, + [THEME_TEMPLATE_KEY.PURPLE]: { + name: '贵族紫', + theme: { + palette: { + primary: { + main: '#9500ae', + light: purple[50], + }, + secondary: { + main: '#d500f9', + }, + }, + }, + }, + [THEME_TEMPLATE_KEY.CYAN]: { + name: '成熟青', + theme: { + palette: { + primary: { + main: '#14a37f', + light: cyan[50], + }, + secondary: { + main: '#1de9b6', + }, + }, + }, + }, +} + +const ThemeTemplateOption = ({ ke, name, color, selected, onChange }: + { ke: THEME_TEMPLATE_KEY, name: string, color: string, selected: boolean, onChange: (themeId: THEME_TEMPLATE_KEY) => void }) => { + const classes = useStyles() + return ( +
onChange(ke)} className={classnames(classes.themeOption, selected ? classes.themeOptionOn : null)}> +
 
+
{name}
+
+ ) +} + +export default ThemeChangeOverlay diff --git a/src/components/account/UserList.sass b/src/components/account/UserList.sass index 484b268..eb07252 100644 --- a/src/components/account/UserList.sass +++ b/src/components/account/UserList.sass @@ -1,8 +1,8 @@ .UserList - padding: 2rem + padding: 1.3rem .header - margin-bottom: 2rem + margin-bottom: 1.3rem .title - font-size: 2rem + font-size: 1.3rem .toolbar - margin-bottom: 1rem + margin-bottom: 0.65rem diff --git a/src/components/api/API.sass b/src/components/api/API.sass index b03035b..24f9ab9 100644 --- a/src/components/api/API.sass +++ b/src/components/api/API.sass @@ -1,18 +1,18 @@ .APIList - padding: 2rem + padding: 1.3rem margin: 16px > .header - margin-bottom: 2rem + margin-bottom: 1.3rem .title - font-size: 2rem + font-size: 1.3rem > .body > .API - margin-bottom: 2rem + margin-bottom: 1.3rem > .title font-size: 1.6rem - margin-bottom: 1rem + margin-bottom: 0.65rem > ul - padding-left: 2rem + padding-left: 1.3rem li margin-bottom: .75rem .label @@ -20,5 +20,5 @@ code padding: .5rem .code-example - padding: 2rem - margin: 2rem + padding: 1.3rem + margin: 1.3rem diff --git a/src/components/checker/Checker.sass b/src/components/checker/Checker.sass index 7dc4d05..7e9646a 100644 --- a/src/components/checker/Checker.sass +++ b/src/components/checker/Checker.sass @@ -1,15 +1,15 @@ @import "../../assets/variables.sass" .Checker - padding: 2rem + padding: 1.3rem .card-mods, .card-itfs .card-title float: left - width: 5rem - font-size: 1.4rem + width: 3.25rem + font-size: 1rem a float: left - margin-right: 1rem + margin-right: 0.65rem width: 10rem overflow: hidden white-space: nowrap @@ -18,7 +18,7 @@ a.active color: $brand .card-result - margin-top: 1rem + margin-top: 0.65rem .card-title - font-size: 1.4rem - margin-bottom: 1rem + font-size: 1rem + margin-bottom: 0.65rem diff --git a/src/components/common/Footer.sass b/src/components/common/Footer.sass index e532f60..03b0570 100644 --- a/src/components/common/Footer.sass +++ b/src/components/common/Footer.sass @@ -1,7 +1,7 @@ @import "../../assets/variables.sass" .Footer - padding: 2rem 1rem 1rem 1rem + padding: 1.3rem 0.65rem 0.65rem 0.65rem border-top: 1px solid $border text-align: center ul.friend_links @@ -10,5 +10,5 @@ padding: 0 li display: inline-block - margin-right: 1rem + margin-right: 0.65rem diff --git a/src/components/common/Footer.tsx b/src/components/common/Footer.tsx index a653f1a..27b8886 100644 --- a/src/components/common/Footer.tsx +++ b/src/components/common/Footer.tsx @@ -9,6 +9,7 @@ const Footer = ({ counter = {} }: { counter: any }) => ( ) diff --git a/src/components/common/GlobalStyles.tsx b/src/components/common/GlobalStyles.tsx index 45c9636..802f2bc 100644 --- a/src/components/common/GlobalStyles.tsx +++ b/src/components/common/GlobalStyles.tsx @@ -8,6 +8,7 @@ const GlobalStyles = (theme: Theme) => ({ padding: 0, backgroundColor: grey[200], fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif;', + fontSize: '1rem', }, '.ml1': { marginLeft: theme.spacing(1), @@ -15,6 +16,12 @@ const GlobalStyles = (theme: Theme) => ({ '.mr1': { marginRight: theme.spacing(1), }, + '.mb1': { + marginBottom: theme.spacing(1), + }, + '.mt1': { + marginTop: theme.spacing(1), + }, 'ol': { padding: `0 ${theme.spacing(2)}px`, }, @@ -24,6 +31,14 @@ const GlobalStyles = (theme: Theme) => ({ 'li': { padding: `${theme.spacing(1)}px 0`, }, + '.g-link': { + color: theme.palette.primary.main, + cursor: 'pointer', + }, + 'a, a:hover, a:focus, a:active, a:visited': { + color: theme.palette.primary.main, + cursor: 'pointer', + }, }, }) as StyleRules diff --git a/src/components/common/LoadingButton.tsx b/src/components/common/LoadingButton.tsx index 0f1481e..32ec7cf 100644 --- a/src/components/common/LoadingButton.tsx +++ b/src/components/common/LoadingButton.tsx @@ -24,19 +24,17 @@ interface Props extends ButtonProps { label: string } -export default function LoadingButton(props: Props) { +export default React.forwardRef((props: Props, ref: any) => { const { children, label, ...rest } = props const classes = useStyles() const loading = props.disabled return ( -
- {loading && }
) -} +}) diff --git a/src/components/common/Message.tsx b/src/components/common/Message.tsx index b4b52c6..3d2321c 100644 --- a/src/components/common/Message.tsx +++ b/src/components/common/Message.tsx @@ -144,7 +144,6 @@ const Message = withStyles(styles)( const { timestamp, message, type } = messageInfo const Icon = getIcon(type) const className = this.getClassName(type) - console.log(messageInfo) return (
createMuiTheme({ + ...theme as ThemeOptions, + ...(options || {}) }) export default MuiTheme diff --git a/src/components/common/NoData.tsx b/src/components/common/NoData.tsx new file mode 100644 index 0000000..28004a7 --- /dev/null +++ b/src/components/common/NoData.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +function NoData() { + return ( +
+ 暂无数据 +
+ ) +} + +export default NoData diff --git a/src/components/editor/DefaultValueModal.tsx b/src/components/editor/DefaultValueModal.tsx index e370f58..50c698a 100644 --- a/src/components/editor/DefaultValueModal.tsx +++ b/src/components/editor/DefaultValueModal.tsx @@ -121,7 +121,7 @@ function DefaultValueModal({ open, handleClose, repositoryId, enqueueSnackbar }: {editingData.map((row, i) => ( - + onChange('name', i, e.target.value)} diff --git a/src/components/editor/HistoryLogDrawer.tsx b/src/components/editor/HistoryLogDrawer.tsx new file mode 100644 index 0000000..367701b --- /dev/null +++ b/src/components/editor/HistoryLogDrawer.tsx @@ -0,0 +1,137 @@ +import React, { useEffect, useState } from 'react' +import { List, ListItem, ListItemText, Drawer, makeStyles, Avatar, ListItemAvatar, ListItemSecondaryAction, IconButton, TablePagination, Button } from '@material-ui/core' +import { ENTITY_TYPE, TablePaginationProps } from 'utils/consts' +import RepositoryService from '../../relatives/services/Repository' +import DateUtility from 'utils/DateUtility' +import Markdown from 'markdown-to-jsx' +import NoData from 'components/common/NoData' +import DownloadIcon from '@material-ui/icons/GetApp' +import { serve } from 'relatives/services/constant' + +const useStyles = makeStyles({ + list: { + width: 650, + overflow: 'auto', + height: 'calc(100% - 50px)', + }, + fullList: { + width: 'auto', + }, + pager: { + height: 50, + marginBottom: 12, + }, +}) + +export interface HistoryLog { + id: number + user: { + fullname: string + id: number + empId: number + } + entityId: number + entityType: ENTITY_TYPE.INTERFACE | ENTITY_TYPE.REPOSITORY + changeLog: string + createdAt: string + + relatedJSONData?: string + jsonDataIsNull?: boolean +} + +export const LOG_SEPERATOR = '.|.' +export const LOG_SUB_SEPERATOR = '@|@' + +const FormattedRow = ({ row }: { row: HistoryLog }) => { + const [expanded, setExpanded] = useState(false) + const [showBtn, setShowBtn] = useState(false) + const formatter = () => row.changeLog + .split(LOG_SEPERATOR) + .map(x => x.split(LOG_SUB_SEPERATOR)) + .reduceRight((a, b) => [...a, ...b], []) + .map(x => `* ${x}`) + + const list = formatter() + + if (list.length > 5 && !expanded) { + list.length = 5 + if (!showBtn) { + setShowBtn(true) + } + } + + return ( +
+ {list.join('\n')} + {showBtn && ( + + )} +
+ ) +} + +const EMPTY = { rows: [], count: 0 } + +function HistoryLogDrawer({ entityId, entityType, open, onClose }: + { entityId: number, entityType: ENTITY_TYPE.INTERFACE | ENTITY_TYPE.REPOSITORY, open: boolean, onClose: () => void }) { + const classes = useStyles() + const [result, setResult] = useState>(EMPTY) + const [limit, setLimit] = useState(10) + const [page, setPage] = useState(0) + useEffect(() => { + if (open) { + RepositoryService.fetchHistoryLogs({ entityId, entityType, limit, offset: page * limit }).then(res => { + setResult(res) + }) + } + return () => { + setResult(EMPTY) + } + }, [entityId, entityType, open, limit, page]) + return ( + + {result.rows.length === 0 && } + + {result.rows.map(row => ( + + + + {String(row.user.empId)} + + + } secondary={`${DateUtility.formatDate(row.createdAt)} by ${row.user.fullname}`} /> + {!row.jsonDataIsNull && + + window.open(`${serve}/interface/history/JSONData/${row.id}`)}> + + + + } + + )) + } + + setPage(val)} + onChangeRowsPerPage={e => { setLimit(parseInt(e.target.value, 10)); setPage(0) }} + {...TablePaginationProps} + /> + + ) +} + +export default HistoryLogDrawer diff --git a/src/components/editor/Importer.tsx b/src/components/editor/Importer.tsx index 7d2e9d5..c7926e6 100644 --- a/src/components/editor/Importer.tsx +++ b/src/components/editor/Importer.tsx @@ -186,7 +186,7 @@ class Importer extends Component { type: any; rule: string; value: any; - descripton: string; + description: string; creator: any; repositoryId: any; moduleId: any; @@ -202,7 +202,7 @@ class Importer extends Component { type, rule, value, - descripton: '', + description: '', }, { creator: auth.id, @@ -239,7 +239,7 @@ class Importer extends Component { } if (result instanceof Array) { - result = { _root_: result } + result = { __root__: result } } const schema = Mock.toJSONSchema(result) const memoryProperties: any = [] diff --git a/src/components/editor/InterfaceEditor.tsx b/src/components/editor/InterfaceEditor.tsx index 16243c0..3aa720e 100644 --- a/src/components/editor/InterfaceEditor.tsx +++ b/src/components/editor/InterfaceEditor.tsx @@ -44,7 +44,6 @@ type InterfaceEditorState = { // TODO 2.x 支持复制整个接口到其他模块、其他项目 class InterfaceEditor extends Component { static childContextTypes = { - handleLockInterface: PropTypes.func.isRequired, handleUnlockInterface: PropTypes.func.isRequired, handleSaveInterfaceAndProperties: PropTypes.func.isRequired, handleMoveInterface: PropTypes.func.isRequired, @@ -91,6 +90,7 @@ class InterfaceEditor extends Component { const properties = [...this.state.properties] - const index = properties.findIndex(item => item.id === property.id) + const index = properties.findIndex((item) => item.id === property.id) if (index >= 0) { properties.splice(index, 1) @@ -235,7 +235,7 @@ class InterfaceEditor extends Component { const properties = [...this.state.properties] - const index = properties.findIndex(item => item.id === property.id) + const index = properties.findIndex((item) => item.id === property.id) if (index >= 0) { properties.splice(index, 1, property) this.setState({ properties }) @@ -278,9 +278,13 @@ class InterfaceEditor extends Component { /** empty */ } - handleLockInterface = () => { - const { itf, lockInterface } = this.props - lockInterface(itf.id) + handleEditInterface = () => { + const { lockInterface, fetchInterface } = this.props + fetchInterface(this.state.itf.id, (res: any) => { + if (!res.locker) { + lockInterface(res.id) + } + }) } handleUnlockInterface = () => { const { itf, unlockInterface } = this.props diff --git a/src/components/editor/InterfaceEditorToolbar.tsx b/src/components/editor/InterfaceEditorToolbar.tsx index 067041a..b9a5bec 100644 --- a/src/components/editor/InterfaceEditorToolbar.tsx +++ b/src/components/editor/InterfaceEditorToolbar.tsx @@ -1,5 +1,5 @@ -import React from 'react' -import { Button, makeStyles, Theme, createStyles } from '@material-ui/core' +import React, { useState } from 'react' +import { Button, makeStyles, Theme, createStyles, Tooltip } from '@material-ui/core' import LoadingButton from '../common/LoadingButton' import Create from '@material-ui/icons/Create' import KeyboardTab from '@material-ui/icons/KeyboardTab' @@ -7,6 +7,9 @@ import Save from '@material-ui/icons/Save' import Cancel from '@material-ui/icons/Cancel' import { useSelector } from 'react-redux' import { RootState } from 'actions/types' +import History from '@material-ui/icons/History' +import HistoryLogDrawer from './HistoryLogDrawer' +import { ENTITY_TYPE } from 'utils/consts' const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -35,14 +38,22 @@ interface Props { handleSaveInterfaceAndProperties: any handleUnlockInterface: any handleMoveInterface: any - handleLockInterface: any + handleEditInterface: any } function InterfaceEditorToolbar(props: Props) { - const { editable, locker, repository, handleLockInterface, handleMoveInterface, - handleSaveInterfaceAndProperties, handleUnlockInterface } = props + const { + editable, + locker, + repository, + handleEditInterface, + handleMoveInterface, + handleSaveInterfaceAndProperties, + handleUnlockInterface, + } = props const loading = useSelector((state: RootState) => state.loading) + const [showHistory, setShowHistory] = useState(false) const classes = useStyles() if (!repository.canUserEdit) { return null } @@ -76,13 +87,36 @@ function InterfaceEditorToolbar(props: Props) { } return (
- + + + - - - + + + + + + + + setShowHistory(false)} + entityId={props.itfId} + entityType={ENTITY_TYPE.INTERFACE} + />
) } diff --git a/src/components/editor/InterfaceForm.tsx b/src/components/editor/InterfaceForm.tsx index 7594f67..637e96b 100644 --- a/src/components/editor/InterfaceForm.tsx +++ b/src/components/editor/InterfaceForm.tsx @@ -173,7 +173,7 @@ function InterfaceForm(props: Props) {
({ + interface: { + border: `1px solid ${palette.primary.main}`, + }, + interfaceActive: { + borderLeft: `3px solid ${palette.primary.main}`, + }, + li: { + borderBottom: `1px solid ${palette.primary.main}`, + }, +})) function InterfaceList(props: InterfaceListProps) { const [interfaceFormOpen, setInterfaceFormOpen] = useState(false) const [moduleFormOpen, setModuleFormOpen] = useState(false) @@ -126,6 +137,7 @@ function InterfaceList(props: InterfaceListProps) { const confirm = useConfirm() const auth = useSelector((state: RootState) => state.auth) const { repository, itf, itfs = [], mod } = props + const classes = useStyles() const handleDeleteModule: MouseEventHandler = e => { e.preventDefault() @@ -160,6 +172,12 @@ function InterfaceList(props: InterfaceListProps) { }), ) } + + if (repository.modules.length === 0) { + return
请先添加模块
+ } + + return (
{repository.canUserEdit ? ( @@ -182,7 +200,7 @@ function InterfaceList(props: InterfaceListProps) { onClose={() => setInterfaceFormOpen(false)} /> - + @@ -216,14 +234,14 @@ function InterfaceList(props: InterfaceListProps) {
) : null} {itfs.length ? ( -
+
    {itfs.map((item: any) => (
) : ( -
暂无接口,请新建
- )} +
暂无接口,请新建
+ )} ) } diff --git a/src/components/editor/InterfacePreviewer.tsx b/src/components/editor/InterfacePreviewer.tsx index 2005686..e2bb727 100644 --- a/src/components/editor/InterfacePreviewer.tsx +++ b/src/components/editor/InterfacePreviewer.tsx @@ -51,8 +51,8 @@ class Previewer extends Component { const template = (scopedTemplate as any)[scope] let data = scopedData[scope] - if (data._root_) { - data = data._root_ + if (data.__root__) { + data = data.__root__ } // DONE 2.1 支持虚拟属性 __root__ √服务端 √前端 √迁移测试 @@ -137,7 +137,9 @@ class Previewer extends Component {
) } catch (ex) { - scopedData.response = `无法预览Mock数据,因为您编写规则导致如下错误:${ex.message}` + if (scopedData) { + scopedData.response = `无法预览Mock数据,因为您编写规则导致如下错误:${ex.message}` + } } return
发生错误...
} diff --git a/src/components/editor/InterfaceSummary.css.map b/src/components/editor/InterfaceSummary.css.map index c426380..b0c30c1 100644 --- a/src/components/editor/InterfaceSummary.css.map +++ b/src/components/editor/InterfaceSummary.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["InterfaceSummary.sass"],"names":[],"mappings":"AAAA;EACE;;;AACF;EACE;;;AAEA;EACE;;AACF;EACE;;AACF;EACE;EACA;;AACA;EACE;;AACF;EACE;;AACJ;EACE;;AACA;EACE;EACA;EACA;EACA;;AACJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;;AACA;EACE;;AACF;EACE;EACA;EACA;;AAEJ;EACE;;AACA;EACE;;AACF;EACE;EACA;EACA;;AACA;EACE;;AACF;EACE;EACA;EACA;;AACF;EACE;EACA;EACA;;AACJ;EACE;EACA;EACA;;AACF;EACE;EACA;EACA","file":"InterfaceSummary.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["InterfaceSummary.sass"],"names":[],"mappings":"AAAA;EACE;;;AACF;EACE;;;AACF;EACE;EACA;EACA;;AACA;EACE;EACA;;AACF;EACE;EACA;EACA;EACA;;AACF;EACE;;AACF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;;AACF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;;AACF;EACE;;AACF;EACE;EACA;;AACA;EACE;;AACF;EACE;;AACJ;EACE;;AACA;EACE;EACA;EACA;EACA;;AACJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;;AACA;EACE;;AACF;EACE;EACA;EACA;;AAEJ;EACE;;AACA;EACE;;AACF;EACE;EACA;EACA;;AACA;EACE;;AACF;EACE;EACA;EACA;;AACF;EACE;EACA;EACA;;AACJ;EACE;EACA;EACA;;AACF;EACE;EACA;EACA","file":"InterfaceSummary.css"} \ No newline at end of file diff --git a/src/components/editor/InterfaceSummary.sass b/src/components/editor/InterfaceSummary.sass index baa6e0f..dc0cd6e 100644 --- a/src/components/editor/InterfaceSummary.sass +++ b/src/components/editor/InterfaceSummary.sass @@ -2,6 +2,41 @@ float: left .ovh overflow: hidden +.SyncRoomDialog + min-width: 400px + min-height: 300px + padding: 1.64rem + ul + margin-top: 1.3rem + padding: 0 + li + display: block + border-radius: 5px + padding: 0.65rem + border: 1px solid #CCC + li + li + margin-top: 0.65rem + i + font-style: normal + color: #FFF + padding: 0 10px + background: #CCC + margin-left: 0.65rem + border-radius: 5px + zoom: .7 + p + margin-bottom: 0 + .button + float: right + margin-top: 7px + font-size: 14px + background: #28a745 + color: #FFF + line-height: 1.5 + user-select: none + padding: .375rem 1.3rem + border-radius: .25rem + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out .InterfaceSummary .dropdown display: inline-block @@ -32,7 +67,7 @@ .nav-link display: block - padding: 0.5rem 1rem + padding: 0.325rem 0.65rem cursor: pointer &:hover, &:focus text-decoration: none diff --git a/src/components/editor/InterfaceSummary.tsx b/src/components/editor/InterfaceSummary.tsx index 31ac239..1ab1fb6 100644 --- a/src/components/editor/InterfaceSummary.tsx +++ b/src/components/editor/InterfaceSummary.tsx @@ -2,25 +2,15 @@ import React, { Component } from 'react' import { connect } from 'react-redux' import copy from 'clipboard-copy' import { GlobalHotKeys } from 'react-hotkeys' -import { - replace, - StoreStateRouterLocationURI, - PropTypes -} from '../../family' +import { replace, StoreStateRouterLocationURI, PropTypes } from '../../family' import { serve } from '../../relatives/services/constant' import { METHODS, STATUS_LIST } from './InterfaceForm' import { CopyToClipboard } from '../utils/' import { getRelativeUrl } from '../../utils/URLUtils' import './InterfaceSummary.css' import { showMessage, MSG_TYPE } from 'actions/common' -import { - TextField, - Select, - FormControl, - InputLabel, - Input, - MenuItem -} from '@material-ui/core' +import { TextField, Select, InputLabel, Input, MenuItem } from '@material-ui/core' +import Markdown from 'markdown-to-jsx' export const BODY_OPTION = { FORM_DATA: 'FORM_DATA', @@ -106,7 +96,7 @@ type InterfaceSummaryState = { class InterfaceSummary extends Component< InterfaceSummaryProps, InterfaceSummaryState -> { + > { static contextTypes = { onDeleteInterface: PropTypes.func.isRequired, } @@ -211,8 +201,8 @@ class InterfaceSummary extends Component< )}
    {editable ? ( - <> -
  • +
    +
    -
  • -
  • +
+
- -
  • - - - 类型 - +
  • +
    +
    + 类型 - - - - 状态码 - +
    +
    + 状态码 - - -
  • - { - handleChangeInterface({ description: e.target.value }) - }} - margin="normal" - /> -
  • - +
    +
    + { + handleChangeInterface({ description: e.target.value }) + }} + margin="normal" + /> + ) : ( - <> -
  • - + <> +
  • - 地址: - - {itf.url} - + 接口ID: + {itf.id} - -
  • -
  • - +
  • +
  • + + + 地址: + + {itf.url} + + + +
  • +
  • 类型: {itf.method} - -
  • -
  • - +
  • +
  • 状态码: {itf.status} - -
  • - {itf.description && ( -
  • - - - - 简介: - - - {itf.description} - - -
  • - )} - - )} + + )} - {editable && ( -
      -
    • - -
    • -
    • - -
    • -
    • - -
    • -
    - )} - {editable && requestParamsType === REQUEST_PARAMS_TYPE.BODY_PARAMS ? ( -
    -
    - -
    - ) : null} -
    + ) : null + } + ) } handleDelete = (e: any, itf: any) => { diff --git a/src/components/editor/ModuleList.tsx b/src/components/editor/ModuleList.tsx index dc709d6..981fab4 100644 --- a/src/components/editor/ModuleList.tsx +++ b/src/components/editor/ModuleList.tsx @@ -1,11 +1,12 @@ import React, { useState } from 'react' import { connect, Link, replace, StoreStateRouterLocationURI } from '../../family' -import { RSortable } from '../utils' +import { RSortable } from '../utils' import ModuleForm from './ModuleForm' import { useSelector, useDispatch } from 'react-redux' import { GoPackage } from 'react-icons/go' import { deleteModule, sortModuleList } from '../../actions/module' import { Module, Repository, RootState, User } from '../../actions/types' +import { makeStyles, Theme } from '@material-ui/core' interface ModuleBaseProps { repository: Repository @@ -16,7 +17,7 @@ interface ModuleBaseProps { replace?: typeof replace } function ModuleBase(props: ModuleBaseProps) { - const { mod} = props + const { mod } = props const router = useSelector((state: RootState) => state.router) const uri = StoreStateRouterLocationURI(router).removeSearch('itf') const selectHref = uri.setSearch('mod', mod!.id.toString()).href() @@ -45,11 +46,19 @@ interface ModuleListProps { mod?: Module repository: Repository } + +const useStyles = makeStyles(({ palette }: Theme) => ({ + li: { + borderColor: `${palette.primary.main} #e1e4e8 transparent #e1e4e8 !important`, + }, +})) + function ModuleList(props: ModuleListProps) { const [open, setOpen] = useState(false) const dispatch = useDispatch() const auth = useSelector((state: RootState) => state.auth) const { repository, mods = [], mod } = props + const classes = useStyles() const handleSort = (_: any, sortable: any) => { dispatch(sortModuleList(sortable.toArray(), () => { /** empty */ @@ -61,7 +70,7 @@ function ModuleList(props: ModuleListProps) { {mods.map((item: any) => (
  • - setOpen(true)}> + setOpen(true)} className="g-link"> 新建模块 }, + ref: React.Ref, +) => { + return +}) + const codeTmpl = ({ projectId, token, rapperType, rapperPath }: { projectId: number - token?: string + token: string rapperType: RapperType rapperPath: string }) => { @@ -164,7 +172,7 @@ function RapperInstallerModal({ fullScreen={true} open={open} onClose={handleClose} - TransitionComponent={SlideUp} + TransitionComponent={Transition} > @@ -204,8 +212,8 @@ function RapperInstallerModal({ onChange={(event) => setRapperPath(event.target.value)} /> -

    1. 安装 rapper 到项目依赖

    -
    npm install rap --save
    +

    1. 安装 rapper 到项目的开发依赖

    +
    npm install rap --save-dev

    2. 给 package.json 的 scripts 对象下添加下面一行脚本

               {codeTmpl({ projectId: repository.id, token: repository.token, rapperType, rapperPath })}
    diff --git a/src/components/editor/RepositoryEditor.css.map b/src/components/editor/RepositoryEditor.css.map
    index f9eeb55..fe1a8e2 100644
    --- a/src/components/editor/RepositoryEditor.css.map
    +++ b/src/components/editor/RepositoryEditor.css.map
    @@ -1 +1 @@
    -{"version":3,"sourceRoot":"","sources":["RepositoryEditor.sass","../../assets/variables.sass"],"names":[],"mappings":"AAGE;EACE;EACA;EACA;;AACA;EACE;EACA;;AACA;EACE;;AACJ;EACE;;AACA;EACE;;AACJ;EACE;EACA;EACA;;;AAEN;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AACF;EACE;;AACJ;EACE;EACA;EACA;;;AAEJ;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;;AACF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEE;EACE;EACA;;AACF;EACE;EACA;;AACF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;;AACA;EACE;EACA,OC1EI;;AD4ER;EACE;;AACA;EACE;;AAEA;EACE;;;AAEZ;EACE;;AACA;EACE;;;AAGJ;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EAEE;EACA;EACA;EACA;;AACF;EACE;;AACF;EACE;;AACA;EACE;;AACF;EAEE;;AACA;EACE;EACA;EACA;;AACA;EACE,OC7HE;;AD+HV;EACI;;AAEF;EACE;;AACF;EACE;;;AAGR;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;;AACF;EACE;EACA;EACA;;;AAEJ;EACE;EACA;EACA;;AACA;EAGE;;AAFA;EACE;;AAEJ;EACE;EACA;;AACF;EACE;;AACF;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AACA;EACE;;AACF;EACE;EACA;;AACF;EACE;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;;AACA;EACE,OC3MA;;AD4MN;EACE;EACA,OCrMC;;ADuML;EACE;;AAGA;EACE;;AACA;EACE;;AACJ;EACE;;AACN;EACE;;;AAGN;EACE;EACA;;AACA;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AACF;EACE;EACA;EACA;EACA;EACA,kBCpOK;;ADqOP;EAEE,kBCzOK;;;AD2OX;EACE;;AACA;EACE;;AACA;EACE;EACA;;AACA;EACE;;AACJ;EACE;;AACJ;EACE;EACA;EACA;EACA;;AACA;EACE;;AACA;EACE;EACA;;;AAER;EACE;;AACA;EACE;;AACA;EACE;EACA;;AACF;EACE;;AACA;EACE;;AACF;EACE;;AACA;EACE;;AACR;EACE;;AAEA;EACE;EACA;EACA;EACA;;AACA;AAAA;EAEE;;AACA;AAAA;EACE;;AACA;AAAA;EACE;;AACJ;AAAA;EACE;EACA;EACA;;AACJ;EACE;EACA;EACA;;;AAER;EACE;IACE;;EACF;IACE;;EACF;IACE;;;AAKA;AAAA;EACE;;AAEE;AAAA;AAAA;AAAA;EACE;;AACJ;AAAA;AAAA;AAAA;EACE;EACA;EAEA;EACA;EACA;EACA;;AACF;AAAA;EAEE;EACA;;AACF;AAAA;EAEE;EACA;;AAEA;AAAA;AAAA;EACE;EACA;;AACF;AAAA;AAAA;EACE;EACA;;AACF;AAAA;AAAA;EACE;;AACF;AAAA;AAAA;EACE;;AACF;AAAA;AAAA;EACE;;AACF;AAAA;AAAA;EACE;;AAEF;AAAA;EACI;EACA;;AACA;AAAA;EACE,OCrWA;;ADuWN;AAAA;EACE;EACA;EACA;;AACA;AAAA;EACE;EACA;;AACA;AAAA;EACE;;AACF;AAAA;EACE,OCjXA;;ADkXN;AAAA;EACE;EACA;EACA;;AACF;AAAA;EACE;EACA;;AACA;AAAA;EACE;;AAEA;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACR;AAAA;EACE;EACA;EACA;EACA;;AACA;AAAA;EACE;EACA;;AACJ;AAAA;EACE;;AACF;AAAA;EACE;;;AAIJ;EACE;EACA;;AAEF;EACE;;AAGE;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AACR;EACE;EACA;;AACN;AAAA;AAAA;EAGE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;AACF;EACE","file":"RepositoryEditor.css"}
    \ No newline at end of file
    +{"version":3,"sourceRoot":"","sources":["RepositoryEditor.sass","../../assets/variables.sass"],"names":[],"mappings":"AAGE;EACE;EACA;EACA;;AACA;EACE;EACA;;AACA;EACE;;AACJ;EACE;;AACA;EACE;;AACJ;EACE;EACA;EACA;;;AAEN;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AACF;EACE;;AACJ;EACE;EACA;EACA;;;AAEJ;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;;AACF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEE;EACE;EACA;;AACF;EACE;EACA;;AACF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;;AACA;EACE;EACA,OC1EI;;AD4ER;EACE;;AACA;EACE;;AAEA;EACE;;;AAEZ;EACE;;AACA;EACE;;;AAGJ;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EAEE;EACA;EACA;;AACF;EACE;;AACF;EACE;;AACA;EACE;;AACF;EAEE;;AACA;EACE;EACA;EACA;;AACA;EACE,OC5HE;;AD8HV;EACI;;AAEF;EACE;;AACF;EACE;;;AAGR;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;;AACF;EACE;EACA;EACA;;;AAEJ;EACE;EACA;EACA;;AACA;EAGE;;AAFA;EACE;;AAEJ;EACE;;AACF;EACE;;AACF;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;;AACA;EACE;;AACF;EACE;EACA;;AACF;EACE;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;;AACA;EACE,OCxMA;;ADyMN;EACE;EACA,OClMC;;ADoML;EACE;;AAGA;EACE;;AACA;EACE;;AACJ;EACE;;;AAGV;EACE;EACA;;AACA;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AACF;EACE;EACA;EACA;EACA;EACA,kBC/NK;;ADgOP;EAEE,kBCpOK;;;ADsOX;EACE;;AACA;EACE;;AACA;EACE;EACA;;AACA;EACE;;AACJ;EACE;;AACJ;EACE;EACA;EACA;EACA;;AACA;EACE;;AACA;EACE;EACA;;;AAER;EACE;EACA;EACA;;AACA;EACE;;AACA;EACE;EACA;;AACF;EACE;;AACA;EACE;;AACF;EACE;;AACA;EACE;;AACR;EACE;;AAEA;EACE;EACA;EACA;EACA;;AACA;AAAA;EAEE;;AACA;AAAA;EACE;;AACA;AAAA;EACE;;AACJ;AAAA;EACE;EACA;EACA;;AACJ;EACE;EACA;EACA;;;AAER;EACE;IACE;;EACF;IACE;;EACF;IACE;;;AAKA;AAAA;EACE;;AAEE;AAAA;AAAA;AAAA;EACE;;AACJ;AAAA;AAAA;AAAA;EACE;EACA;EAEA;EACA;EACA;EACA;;AACF;AAAA;EAEE;EACA;;AACF;AAAA;EAEE;EACA;;AAEA;AAAA;AAAA;EACE;EACA;;AACF;AAAA;AAAA;EACE;EACA;;AACF;AAAA;AAAA;EACE;;AACF;AAAA;AAAA;EACE;;AACF;AAAA;AAAA;EACE;;AACF;AAAA;AAAA;EACE;;AAEF;AAAA;EACI;EACA;;AACA;AAAA;EACE,OClWA;;ADoWN;AAAA;EACE;EACA;EACA;;AACA;AAAA;EACE;EACA;;AACA;AAAA;EACE;;AACF;AAAA;EACE,OC9WA;;AD+WN;AAAA;EACE;EACA;EACA;;AACF;AAAA;EACE;EACA;;AACA;AAAA;EACE;;AAEA;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAXJ;AAAA;EACE;;AACA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACR;AAAA;EACE;EACA;EACA;EACA;;AACA;AAAA;EACE;EACA;;AACJ;AAAA;EACE;;AACF;AAAA;EACE;EACA;;;AAIJ;EACE;EACA;;AAEF;EACE;;AAGE;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AAHJ;EACE;;AACA;EACE;;AACR;EACE;EACA;;AACN;AAAA;AAAA;EAGE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;AACF;EACE","file":"RepositoryEditor.css"}
    \ No newline at end of file
    diff --git a/src/components/editor/RepositoryEditor.sass b/src/components/editor/RepositoryEditor.sass
    index 29da3d5..2d1e130 100644
    --- a/src/components/editor/RepositoryEditor.sass
    +++ b/src/components/editor/RepositoryEditor.sass
    @@ -3,34 +3,34 @@
     .RepositoryEditor
       > .header
         position: relative
    -    padding: 2rem 2rem 1rem 2rem
    +    padding: 1.3rem
         background-color: #fafbfc
         > .title
    -      font-size: 2rem
    -      margin-right: 1rem
    +      font-size: 1.6em
    +      margin-right: 0.65rem
           .slash
             color: #999
         > .toolbar
           display: inline-block
           a, .fake-link
    -        margin-right: 1rem
    +        margin-right: 0.65rem
         > .desc
           white-space: pre-wrap
    -      margin: 1rem 0 .5rem
    +      margin: 1rem 0 .5rem 0
           color: #666
     
     .RelatedProjects 
       display: flex
       flex-wrap: wrap
       align-items: stretch
    -  margin: 1rem 0 -1rem
    +  margin: 0.65rem 0 -1rem
       color: #888
       > .Project
         border: 1px solid #E6E6E6
         background: #FFF
    -    padding: 0 1rem
    -    margin-bottom: 1rem
    -    margin-right: 1rem
    +    padding: 0 0.65rem
    +    margin-bottom: 0.65rem
    +    margin-right: 0.65rem
         line-height: 2.44
         .title
           margin-right: .7rem
    @@ -43,8 +43,8 @@
     
     .RepositorySearcher.dropdown
       position: absolute
    -  top: 2rem
    -  right: 2rem
    +  top: 1.3rem
    +  right: 1.3rem
       left: auto
       > .dropdown-input
         margin-bottom: 0
    @@ -87,14 +87,14 @@
                 color: #FFF
     
     .DuplicatedInterfacesWarning
    -  margin-top: 1rem
    +  margin-top: 2rem
       .more-link
         float: right
     
     
     .ModuleList
       margin: 0
    -  padding: 0 2rem
    +  padding: 0 1.3rem
       list-style: none
       border-bottom: 1px solid #e1e4e8
       background-color: #fafbfc
    @@ -103,7 +103,7 @@
         display: block
         float: left
         margin-bottom: -1px
    -    padding: .8rem 1.2rem
    +    padding: .8rem 0.78rem
         border: 1px solid transparent
         border-width: 3px 1px 0px 1px
         border-radius: .4rem .4rem 0 0
    @@ -112,7 +112,6 @@
           border-bottom-color: transparent
           background-color: white
           cursor: default
    -      border-color: #3f51b5 #e1e4e8 transparent #e1e4e8
         &.active:hover
           background-color: white
         > .Module
    @@ -123,8 +122,8 @@
             // float: right
             display: inline-block
             a, .fake-link
    -          margin-left: 0.5rem
    -          font-size: 1.4rem
    +          margin-left: 0.325rem
    +          font-size: 1rem
               color: #999
               &:hover
                 color: $brand
    @@ -136,13 +135,13 @@
             color: #333
           .toolbar
             display: inline-block
    -        // font-size: 1.4rem
    +        // font-size: 1rem
     
     .InterfaceWrapper
       display: flex
       flex-direction: row
       background-color: #FFFFFF
    -  padding: 2rem
    +  padding: 1.3rem
       .InterfaceList
         width: 23rem
         flex-shrink: 0
    @@ -157,10 +156,9 @@
       height: calc(100vh - 10px)
       .header
         .newIntf
    -      margin-bottom: 1rem
    -    margin-bottom: 1rem
    +      margin-bottom: 0.65rem
    +    margin-bottom: 0.65rem
       .scrollWrapper
    -    border: 1px solid rgba(63, 81, 181, 0.5)
         border-radius: .4rem
       .rcs-inner-handle
         background-color: rgba(63, 81, 181, 0.3)
    @@ -171,8 +169,7 @@
         max-height: calc(100vh - 115px)
         li
           position: relative
    -      padding: 1rem 1rem
    -      border-bottom: 1px solid rgba(63, 81, 181, 0.5)
    +      padding: 0.65rem 0.65rem
           &:first-child
             border-top-left-radius: .3rem
           &:last-child
    @@ -180,10 +177,10 @@
             border-bottom-left-radius: .3rem
           .Interface
             position: relative
    -        padding-right: 4rem
    +        padding-right: 2.6rem
             .name
               position: relative
    -          font-size: 1.3rem
    +          font-size: 1.1rem
               width: 100%
               overflow: hidden
               white-space: nowrap
    @@ -200,14 +197,14 @@
               position: absolute
               right: 0
               top: 0
    -          font-size: 1.4rem
    +          font-size: 1rem
               a, .fake-link
    -            margin-left: 0.5rem
    +            margin-left: 0.325rem
                 color: #999
                 &:hover
                   color: $brand
             .locked
    -          font-size: 1.4rem
    +          font-size: 1rem
               color: $warning
         li:hover
           .toolbar
    @@ -220,12 +217,10 @@
                 color: #333
             .toolbar
               display: block
    -    li.active
    -      border-left: 2px solid #3f51b5
     
     
     .InterfaceEditor
    -  margin-left: 2rem
    +  margin-left: 1.3rem
       position: relative
       .InterfaceEditorToolbar
         position: absolute
    @@ -234,11 +229,11 @@
         text-align: center
         .btn.edit, .btn.save, .btn.cancel, .locker-success, .locker-warning
           display: block
    -      margin-bottom: 0.5rem
    +      margin-bottom: 0.325rem
           width: 12rem
         .locker-success
           display: inline-block
    -      padding: 0.5rem 1.5rem
    +      padding: 0.325rem 1.5rem
           border-radius: 0.4rem
           color: white
           background-color: $success
    @@ -247,12 +242,12 @@
           background-color: $warning
     
     .InterfaceSummary
    -  margin-bottom: 2rem
    +  margin-bottom: 1.3rem
       > .header
         margin-bottom: .5rem
         > .title
           font-size: 1.6rem
    -      margin-right: 1rem
    +      margin-right: 0.65rem
           .slash
             color: #999
         a.edit, a.delete
    @@ -269,12 +264,14 @@
             margin-right: .3rem
     
     .PropertyList
    -  margin-bottom: 3rem
    +  margin-bottom: 1.95rem
    +  padding-bottom: 1.95rem
    +  margin-top: 1rem
       > .header
    -    margin-bottom: 1rem
    +    margin-bottom: 0.65rem
         > .title
           font-size: 1.6rem
    -      margin-right: 1rem
    +      margin-right: 0.65rem
         > .toolbar
           float: right
           .checked-button
    @@ -284,13 +281,13 @@
             input
               margin-right: .5rem
       > .body
    -    margin-bottom: 1rem
    +    margin-bottom: 0.65rem
       > .footer
         > .Previewer
           display: flex
           justify-content: space-between
           flex-wrap: wrap
    -      margin-top: 1rem
    +      margin-top: 0.65rem
           > .result-template,
           > .result-mocked
             width: 49%
    @@ -342,7 +339,7 @@
           .th, .td
             &.operations
               padding: .5rem
    -          width: 1rem
    +          width: 0.65rem
             &.name
               width: 20rem
               flex-grow: 3
    @@ -383,7 +380,7 @@
                 flex-grow: 1
               @for $i from 1 through 42
                 &.depth-#{$i}
    -              padding-left: $i * 1rem + 0.75rem
    +              padding-left: $i * 0.65rem + 0.75rem
                   &:after
                     display: block
                     content: ''
    @@ -391,7 +388,7 @@
                     top: 0
                     bottom: 0
                     left: 0
    -                width: $i * 1rem
    +                width: $i * 0.65rem
                     opacity: .5
                     border-right: 1px dashed #707070
             &.payload.value
    @@ -406,6 +403,7 @@
               padding: 0
             &.payload.desc
               word-break: break-word
    +          white-space: pre-line
     .SortableTreeTable.editable
       .flex-row    
         .th, .td
    diff --git a/src/components/editor/RepositoryEditor.tsx b/src/components/editor/RepositoryEditor.tsx
    index b1949a9..28b3cf1 100644
    --- a/src/components/editor/RepositoryEditor.tsx
    +++ b/src/components/editor/RepositoryEditor.tsx
    @@ -8,49 +8,24 @@ import ModuleList from './ModuleList'
     import InterfaceList from './InterfaceList'
     import InterfaceEditor from './InterfaceEditor'
     import DuplicatedInterfacesWarning from './DuplicatedInterfacesWarning'
    -import RapperInstallerModal from './RapperInstallerModal'
    -import ImportSwaggerRepositoryForm from '../repository/ImportSwaggerRepositoryForm'
    -
    -import {
    -  addRepository,
    -  updateRepository,
    -  clearRepository,
    -  fetchRepository
    -} from '../../actions/repository'
    -import {
    -  addModule,
    -  updateModule,
    -  deleteModule,
    -  sortModuleList
    -} from '../../actions/module'
    -import {
    -  addInterface,
    -  updateInterface,
    -  deleteInterface,
    -  lockInterface,
    -  unlockInterface
    -} from '../../actions/interface'
    -import {
    -  addProperty,
    -  updateProperty,
    -  deleteProperty,
    -  updateProperties,
    -  sortPropertyList
    -} from '../../actions/property'
    -import {
    -  GoRepo,
    -  GoPlug,
    -  GoDatabase,
    -  GoCode,
    -  GoLinkExternal,
    -  GoPencil,
    -  GoEllipsis
    -} from 'react-icons/go'
    -
    +import { addRepository, updateRepository, clearRepository, fetchRepository } from '../../actions/repository'
    +import { addModule, updateModule, deleteModule, sortModuleList } from '../../actions/module'
    +import { addInterface, updateInterface, deleteInterface, lockInterface, unlockInterface } from '../../actions/interface'
    +import { addProperty, updateProperty, deleteProperty, updateProperties, sortPropertyList } from '../../actions/property'
    +import { GoRepo, GoVersions, GoPlug, GoDatabase, GoCode, GoLinkExternal, GoPencil, GoEllipsis } from 'react-icons/go'
    +import { FaHistory } from 'react-icons/fa'
     import './RepositoryEditor.css'
     import ExportPostmanForm from '../repository/ExportPostmanForm'
    -import { RootState, Repository, Module, Interface } from 'actions/types'
    +import ImportSwaggerRepositoryForm from '../repository/ImportSwaggerRepositoryForm'
    +import { RootState, Repository } from 'actions/types'
     import DefaultValueModal from './DefaultValueModal'
    +import RapperInstallerModal from './RapperInstallerModal'
    +import HistoryLogDrawer from './HistoryLogDrawer'
    +import Joyride from 'react-joyride'
    +import { Typography } from '@material-ui/core'
    +import { doFetchUserSettings, updateUserSetting } from 'actions/account'
    +import Markdown from 'markdown-to-jsx'
    +import { CACHE_KEY, ENTITY_TYPE } from 'utils/consts'
     
     // DONE 2.1 import Spin from '../utils/Spin'
     // TODO 2.2 缺少测试器
    @@ -62,17 +37,20 @@ interface Props {
       repository: any
       location: any
       onClearRepository: any
    -  room: any
       replace: any
       router: any
    +  doFetchUserSettings: typeof doFetchUserSettings
    +  updateUserSetting: typeof updateUserSetting
     }
     
     interface States {
       rapperInstallerModalOpen: boolean
       defaultValuesModalOpen: boolean
    +  historyLogDrawerOpen: boolean
       update: boolean
       exportPostman: boolean
       importSwagger: boolean
    +  guideOpen: boolean
     }
     
     // 展示组件
    @@ -110,15 +88,18 @@ class RepositoryEditor extends Component {
           rapperInstallerModalOpen: false,
           defaultValuesModalOpen: false,
           importSwagger: false,
    +      historyLogDrawerOpen: false,
    +      guideOpen: false,
         }
       }
    +
       getChildContext() {
         return _.pick(this.props, Object.keys(RepositoryEditor.childContextTypes))
       }
     
       changeDocumentTitle() {
         const repository = this.props.repository.data
    -    if (repository && repository.name) {
    +    if (repository.name) {
           document.title = `RAP2 ${repository.name}`
         }
       }
    @@ -129,6 +110,13 @@ class RepositoryEditor extends Component {
     
       componentDidMount() {
         this.changeDocumentTitle()
    +    this.props.doFetchUserSettings([CACHE_KEY.GUIDE_20200714], (isOk, payload) => {
    +      const open = !payload.data?.GUIDE_20200714
    +      if (open) {
    +        this.setState({ guideOpen: true })
    +        this.props.updateUserSetting(CACHE_KEY.GUIDE_20200714, '1')
    +      }
    +    })
       }
     
       componentWillUnmount() {
    @@ -152,14 +140,15 @@ class RepositoryEditor extends Component {
           document.title = `RAP2 ${repository.name}`
         }
     
    -    const mod: Module =
    +    const mod: any =
           repository && repository.modules && repository.modules.length
    -        ? repository.modules.find(item => item.id === +params.mod) || repository.modules[0]
    -        : ({} as Module)
    -    const itf: Interface =
    +        ? repository.modules.find((item: any) => item.id === +params.mod) || repository.modules[0]
    +        : {}
    +
    +    const itf =
           mod.interfaces && mod.interfaces.length
             ? mod.interfaces.find((item: any) => item.id === +params.itf) || mod.interfaces[0]
    -        : ({} as Interface)
    +        : {}
     
         const ownerlink = repository.organization
           ? `/organization/repository?organization=${repository.organization.id}`
    @@ -170,7 +159,7 @@ class RepositoryEditor extends Component {
             
    - + {repository.organization ? repository.organization.name : repository.owner.fullname} / @@ -180,7 +169,7 @@ class RepositoryEditor extends Component { {/* 编辑权限:拥有者或者成员 */} {repository.canUserEdit ? ( - this.setState({ update: true })}> + this.setState({ update: true })}> 编辑 ) : null} @@ -197,7 +186,7 @@ class RepositoryEditor extends Component { href={`${serve}/app/plugin/${repository.id}`} target="_blank" rel="noopener noreferrer" - className="api" + className="g-link" > 插件 @@ -205,12 +194,12 @@ class RepositoryEditor extends Component { href={`${serve}/repository/get?id=${repository.id}&token=${repository.token}`} target="_blank" rel="noopener noreferrer" - className="api" + className="g-link" > 数据 - this.setState({ importSwagger: true })}> - 从 Swagger 导入 + this.setState({ importSwagger: true })}> + Swagger导入 { orgId={(repository.organization || {}).id} mode="manual" /> - this.setState({ exportPostman: true })}> + this.setState({ exportPostman: true })}> 导出 { onClose={() => this.setState({ exportPostman: false })} /> this.setState({ defaultValuesModalOpen: true })} > - - 默认值 + 默认值 + + this.setState({ historyLogDrawerOpen: true })} + > + 历史 this.setState({ defaultValuesModalOpen: false })} repositoryId={repository.id} /> + this.setState({ historyLogDrawerOpen: false })} + entityId={repository?.id} + entityType={ENTITY_TYPE.REPOSITORY} + /> this.setState({ rapperInstallerModalOpen: true })} > - 试试点这里帮你生成 TypeScript 代码! + Rapper { />
    -
    {repository.description}
    +
    {repository.description}
    + {this.renderRelatedProjects()}
    @@ -267,7 +267,61 @@ class RepositoryEditor extends Component {
    - + 现在您可以查看项目修改历史了!, + placement: 'top', + target: '.guide-1', + }, + { + title: '历史记录上线', + disableBeacon: true, + content: 您也可以查看指定接口的所有改动记录。, + placement: 'top', + target: '.guide-2', + }, { + title: '皮肤自定义上线', + disableBeacon: true, + content: 在系统偏好设置里,选择一个喜爱的颜色吧!比如原谅绿?, + placement: 'top', + target: '.guide-3', + } + ]} + /> + + ) + } + renderRelatedProjects() { + const { repository } = this.props + const { collaborators } = repository.data + return ( +
    + {collaborators && + Array.isArray(collaborators) && + collaborators.map(collab => ( +
    + + + 协同 + + {collab.name} +
    + ))} +
    ) } handleUpdate = () => { @@ -302,5 +356,7 @@ const mapDispatchToProps = { onDeleteProperty: deleteProperty, onSortPropertyList: sortPropertyList, replace, + doFetchUserSettings, + updateUserSetting, } export default connect(mapStateToProps, mapDispatchToProps)(RepositoryEditor) diff --git a/src/components/editor/RepositorySearcher.tsx b/src/components/editor/RepositorySearcher.tsx index 9f7049e..6acdfc3 100644 --- a/src/components/editor/RepositorySearcher.tsx +++ b/src/components/editor/RepositorySearcher.tsx @@ -1,6 +1,8 @@ import React, { Component } from 'react' import { PropTypes, Link, StoreStateRouterLocationURI, connect } from '../../family' import AwesomeDebouncePromise from 'awesome-debounce-promise' +import { TextField, InputAdornment } from '@material-ui/core' +import Search from '@material-ui/icons/Search' class Highlight extends Component { static replace = (clip: any, seed: any) => { @@ -40,7 +42,8 @@ class DropdownMenuBase extends Component { const matchInterface = nextInterface.name.toLowerCase().indexOf(seed) !== -1 || nextInterface.url.toLowerCase().indexOf(seed) !== -1 || - nextInterface.method === seed + nextInterface.method === seed || + nextInterface.id === +seed if (matchInterface) { counter++ if (!matchModule) { @@ -139,15 +142,23 @@ class RepositorySearcher extends Component { return (
    - { const val = e.target.value this.setState({ seed: val }) this.debouncedInput(val) }} + style={{ backgroundColor: '#fafbfc', marginRight: 12 }} className="dropdown-input form-control" - placeholder="工作区搜索" + placeholder="检索名称或ID" + InputProps={{ + endAdornment: ( + + + + ), + }} /> {result && }
    diff --git a/src/components/home/AboutView.tsx b/src/components/home/AboutView.tsx new file mode 100644 index 0000000..8010f1b --- /dev/null +++ b/src/components/home/AboutView.tsx @@ -0,0 +1,41 @@ +import React from 'react' +import Markdown from 'markdown-to-jsx' +import { Paper, makeStyles, Theme } from '@material-ui/core' + +const useStyles = makeStyles(({ spacing }: Theme) => ({ + root: { + padding: spacing(2), + margin: spacing(2), + }, +})) + +function AboutView() { + const classes = useStyles() + const md = ` + # 关于我们 + + \`RAP2\`是在\`RAP1\`基础上重做的新项目,它能给你提供方便的接口文档管理、Mock、导出等功能,包含两个组件(对应两个 Github Repository)。 + + 目前RAP2由\`阿里妈妈前端团队\`研发,由多个合作团队(包括开源社区)在维护。详请请见GitHub贡献者列表。 + + GitHub仓库: + + rap2-delos: 后端服务器仓库 [link](http://github.com/thx/rap2-delos) + + rap2-dolores: 前端 React 项目仓库 [link](http://github.com/thx/rap2-dolores) + + 相关开源、部署建议,请关注GitHub仓库首页README + + 同时欢迎您前往 [GitHub Issues](https://github.com/thx/rap2-delos/issues) 提出宝贵意见! + + 钉钉群:11789704 + + ` + return ( + + {md} + + ) +} + +export default AboutView diff --git a/src/components/home/Home.sass b/src/components/home/Home.sass index a069f79..a57d7b5 100644 --- a/src/components/home/Home.sass +++ b/src/components/home/Home.sass @@ -1,23 +1,23 @@ @import "../../assets/variables.sass" .Home - padding: 2rem + padding: 1.3rem .Maiden flex-grow: 1 display: flex align-items: center justify-content: center .RepositoryCreateButton - padding: .4rem 1rem - font-size: 1.4rem + padding: .4rem 0.65rem + font-size: 1rem .card - margin-bottom: 2rem + margin-bottom: 1.3rem border: 1px solid $border border-radius: .5rem overflow: hidden .card-header border-bottom: 1px solid $border - font-size: 1.6rem + font-size: 1.2rem .card-block > p:last-child margin-bottom: 0 @@ -27,7 +27,7 @@ // margin-bottom: 0 .card.Logs .Log - padding: 1rem 0 + padding: 0.65rem 0 border-bottom: 1px solid #eff3f6 .Log-body float: left @@ -53,8 +53,8 @@ .Log-fromnow color: #666 - // padding: 4rem 1rem + // padding: 2.6rem 0.65rem // text-align: center - // font-size: 4rem + // font-size: 2.6rem .Log:last-child border-bottom: 0 diff --git a/src/components/home/JoinedRepositoriesCard.tsx b/src/components/home/JoinedRepositoriesCard.tsx index 2d3ee05..9a12d31 100644 --- a/src/components/home/JoinedRepositoriesCard.tsx +++ b/src/components/home/JoinedRepositoriesCard.tsx @@ -13,7 +13,7 @@ const JoinedRepositoriesCard = ({ repositories }: any) => ( )} {repositories.data.length === 0 ? - : null} {repositories.data.length > 10 - ? 查看全部 {repositories.data.length} 个仓库 + ? {'=>'} 查看全部 {repositories.data.length} 个仓库 : null } ) diff --git a/src/components/home/LogsCard.tsx b/src/components/home/LogsCard.tsx index 4811858..63e8eae 100644 --- a/src/components/home/LogsCard.tsx +++ b/src/components/home/LogsCard.tsx @@ -100,6 +100,9 @@ const LogView = ({ log }: any) => { if (log.type === 'join') { return } if (log.type === 'exit') { return } } + if (!log.repository) { + return null + } return (
    @@ -166,19 +169,18 @@ export const Log = ({ log }: any) => { targetLink = !log.repository.deletedAt ? {targetName} : targetName - } - if (log.repository && log.module && !log.interface) { // 模块 + } else if (log.repository && log.module && !log.interface) { // 模块 targetName = `${log.repository.name} / ${log.module.name}` targetLink = !log.repository.deletedAt && !log.module.deletedAt ? {targetName} : targetName - } - if (log.repository && log.module && log.interface) { // 接口 + } else if (log.repository && log.module && log.interface) { // 接口 targetName = `${log.repository.name} / ${log.module.name} / ${log.interface.name}` targetLink = !log.repository.deletedAt && !log.module.deletedAt && !log.interface.deletedAt ? {targetName} : targetName } + switch (log.type) { case 'create': return targetLink ? ( diff --git a/src/components/home/OwnedRepositoriesCard.tsx b/src/components/home/OwnedRepositoriesCard.tsx index 7149168..8080299 100644 --- a/src/components/home/OwnedRepositoriesCard.tsx +++ b/src/components/home/OwnedRepositoriesCard.tsx @@ -13,7 +13,7 @@ const OwnedRepositoriesCard = ({ repositories }: any) => ( )} {repositories.data.length === 0 ? - : null} {repositories.data.length > 10 - ? 查看全部 {repositories.data.length} 个仓库 + ? {'=>'} 查看全部 {repositories.data.length} 个仓库 : null }
    ) diff --git a/src/components/layout/Logo.tsx b/src/components/layout/Logo.tsx index 9d840af..5cb708d 100644 --- a/src/components/layout/Logo.tsx +++ b/src/components/layout/Logo.tsx @@ -1,9 +1,13 @@ import React from 'react' -export default function Logo(props: {color?: string}) { - const color = props.color || '#FFFFFF' +export default function Logo(_props: {color?: string}) { return ( - // tslint:disable-next-line: max-line-length - + logo ) } diff --git a/src/components/layout/MainMenu.tsx b/src/components/layout/MainMenu.tsx index f824c53..918c1df 100644 --- a/src/components/layout/MainMenu.tsx +++ b/src/components/layout/MainMenu.tsx @@ -5,7 +5,6 @@ import Toolbar from '@material-ui/core/Toolbar' import Button from '@material-ui/core/Button' import ClickAwayListener from '@material-ui/core/ClickAwayListener' import Grow from '@material-ui/core/Grow' -import Divider from '@material-ui/core/Divider' import Paper from '@material-ui/core/Paper' import Popper from '@material-ui/core/Popper' import MenuItem from '@material-ui/core/MenuItem' @@ -14,32 +13,73 @@ import ExpandMoreIcon from '@material-ui/icons/ExpandMore' import { Link } from 'react-router-dom' import { User } from 'actions/types' import Logo from './Logo' +import { push } from '../../family' import { useDispatch } from 'react-redux' import { logout } from 'actions/account' -const useAccountButtonStyles = makeStyles(({ spacing }: Theme) => ({ - accountName: { - padding: spacing(1), - textAlign: 'center', - fontSize: '1.3714285714285714rem', - }, -})) - const options = [{ + key: 'preferences', + text: '偏好设置', +}, { key: 'logout', text: '注销', }] +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + flexGrow: 1, + width: '100%', + }, + menuButton: { + marginRight: theme.spacing(2), + }, + title: { + flexGrow: 1, + }, + link: { + color: '#FFFFFF', + '&:hover': { + color: '#FFFFFF', + }, + }, + right: { + float: 'right', + }, + toolbar: { + display: 'flex', + justifyContent: 'space-between', + '& :not(.logo)': { + fontSize: '1.2rem', + }, + }, + links: { + display: 'flex', + alignItems: 'center', + }, + logo: { + display: 'block', + marginRight: theme.spacing(2), + padding: `${theme.spacing(1.5)}px 0 ${theme.spacing(1.5)}px 0`, + }, + accountName: { + color: '#FFFFFF', + }, + }), +) + function AccountButton({ user }: { user: User }) { const [open, setOpen] = React.useState(false) + const anchorRef = React.useRef(null) + const classes = useStyles() const dispatch = useDispatch() - const classes = useAccountButtonStyles() - const anchorRef = React.useRef(null) const handleMenuItemClick = (_event: React.MouseEvent, key: string) => { if (key === 'logout') { dispatch(logout()) + } else if (key === 'preferences') { + dispatch(push('/preferences')) } setOpen(false) } @@ -66,10 +106,10 @@ function AccountButton({ user }: { user: User }) { onClick={handleToggle} ref={anchorRef} > - + {user.fullname} - + {({ TransitionProps, placement }) => ( @@ -81,22 +121,16 @@ function AccountButton({ user }: { user: User }) { > -
    -
    - {user.fullname} -
    - - - {options.map(({ key, text }) => ( - handleMenuItemClick(event, key)} - > - {text} - - ))} - -
    + + {options.map(({ key, text }) => ( + handleMenuItemClick(event, key)} + > + {text} + + ))} +
    @@ -106,45 +140,6 @@ function AccountButton({ user }: { user: User }) { ) } -const useStyles = makeStyles((theme: Theme) => - createStyles({ - root: { - flexGrow: 1, - width: '100%', - }, - menuButton: { - marginRight: theme.spacing(2), - }, - title: { - flexGrow: 1, - }, - link: { - color: '#FFFFFF', - '&:hover': { - color: '#FFFFFF', - }, - }, - right: { - float: 'right', - }, - toolbar: { - display: 'flex', - justifyContent: 'space-between', - '& :not(.logo)': { - fontSize: '1.4rem', - }, - }, - links: { - display: 'flex', - alignItems: 'center', - }, - logo: { - display: 'block', - marginRight: theme.spacing(2), - padding: `${theme.spacing(1.5)}px 0 ${theme.spacing(1.5)}px 0`, - }, - }), -) interface Props { user: User @@ -165,6 +160,7 @@ export default function MainMenu(props: Props) { +
    diff --git a/src/components/organization/Organization.sass b/src/components/organization/Organization.sass index 7aed4c6..679d976 100644 --- a/src/components/organization/Organization.sass +++ b/src/components/organization/Organization.sass @@ -1,20 +1,20 @@ @import "../../assets/variables.sass" .OrganizationListWrapper - padding: 2rem + padding: 1.3rem > .header - margin-bottom: 2rem + margin-bottom: 1.3rem .title - font-size: 2rem + font-size: 1.3rem > .toolbar - margin-bottom: 2rem - padding-bottom: 2rem + margin-bottom: 1.3rem + padding-bottom: 1.3rem border-bottom: 1px solid #e1e4e8 select.OrganizationsTypeDropdown margin-right: .5rem - font-size: 1.4rem + font-size: 1rem button.OrganizationCreateButton - padding: .4rem 1rem - font-size: 1.4rem + padding: .4rem 0.65rem + font-size: 1rem .form-control margin-bottom: 0 @@ -24,15 +24,15 @@ grid-column-gap: 20px padding: 0 15px .Organization.card - margin-bottom: 1rem + margin-bottom: 0.65rem .card-block position: relative .name - font-size: 1.4rem + font-size: 1.2rem white-space: nowrap overflow: hidden .desc - margin-top: 1rem + margin-top: 0.65rem height: 6rem overflow: hidden color: #666 @@ -44,18 +44,18 @@ height: 2.5rem border-radius: 50% .avatar.owner - margin-right: 1rem + margin-right: 0.65rem .popover white-space: nowrap .toolbar // display: none position: absolute - top: 1.2rem + top: 0.78rem right: 1.25rem background-color: white > a, > .fake-link - margin: 0 0 0 0.5rem - font-size: 1.4rem + margin: 0 0 0 0.325rem + font-size: 1rem color: #999 &:hover color: $brand diff --git a/src/components/organization/OrganizationForm.tsx b/src/components/organization/OrganizationForm.tsx index 7a6fae3..4a357ff 100644 --- a/src/components/organization/OrganizationForm.tsx +++ b/src/components/organization/OrganizationForm.tsx @@ -98,7 +98,7 @@ function OrganizationForm(props: Props) { })) }} render={({ isSubmitting, setFieldValue, values }) => { - function loadUserOptions(input: string): Promise> { + function loadUserOptions(input: string): Promise<{ label: string, value: number }[]> { return new Promise(async (resolve) => { const users = await AccountService.fetchUserList({ name: input }) const options = _.differenceWith(users.data, values.members || [], _.isEqual) diff --git a/src/components/repository/ImportRepositoryForm.tsx b/src/components/repository/ImportRepositoryForm.tsx index 76fbacc..b9e5404 100644 --- a/src/components/repository/ImportRepositoryForm.tsx +++ b/src/components/repository/ImportRepositoryForm.tsx @@ -4,7 +4,7 @@ import { connect } from 'react-redux' import RadioList from '../utils/RadioList' import './ImportRepositoryForm.css' import { importRepository, fetchRepositoryList } from '../../actions/repository' -import { Button } from '@material-ui/core' +import { Button, TextField } from '@material-ui/core' class ImportRepositoryForm extends Component { static contextTypes = { @@ -21,11 +21,12 @@ class ImportRepositoryForm extends Component { version: 1, docUrl: '', disableSubmit: false, + projectData: '', } } render() { const { rmodal } = this.context - const { disableSubmit } = this.state + const { disableSubmit, version, projectData } = this.state return (
    @@ -34,19 +35,19 @@ class ImportRepositoryForm extends Component {
    - +
    this.setState({ version: val })} />
    -
    + {+version === 1 && (
    - +
    { autoFocus={true} required={true} data-parsley-maxlength="256" + style={{ width: 500 }} />
    -
    -
    @@ -90,15 +107,14 @@ class ImportRepositoryForm extends Component { disableSubmit: true, }) e.preventDefault() - const { docUrl, orgId } = this.state - this.props.importRepository({ docUrl, orgId }, (res: any) => { + const { docUrl, orgId, version, projectData } = this.state + this.props.importRepository({ docUrl, orgId, version, projectData }, (res: any) => { this.setState({ disableSubmit: false, }) if (res.isOk) { this.context.rmodal.resolve() } else { - console.log(res.message) } }) } diff --git a/src/components/repository/Repository.sass b/src/components/repository/Repository.sass index 34a0f84..ef6726e 100644 --- a/src/components/repository/Repository.sass +++ b/src/components/repository/Repository.sass @@ -1,26 +1,26 @@ @import "../../assets/variables.sass" .RepositoryListWrapper - padding: 2rem + padding: 1.3rem > .header - margin-bottom: 1rem + margin-bottom: 0.65rem .title - font-size: 2rem + font-size: 1.3rem > .toolbar - margin-bottom: 2rem - padding-bottom: 2rem + margin-bottom: 1.3rem + padding-bottom: 1.3rem border-bottom: 1px solid #e1e4e8 select.RepositoriesTypeDropdown margin-right: .5rem margin-bottom: .5rem - font-size: 1.4rem + font-size: 1rem button.RepositoryCreateButton - padding: .4rem 1rem - font-size: 1.4rem + padding: .4rem 0.65rem + font-size: 1rem .form-control margin-bottom: .5rem > .body - margin-bottom: 2rem + margin-bottom: 1.3rem .RepositoryList display: grid @@ -28,15 +28,15 @@ grid-column-gap: 20px padding: 0 15px .Repository.card - margin-bottom: 1rem + margin-bottom: 0.65rem .card-block position: relative .name - font-size: 1.4rem + font-size: 1.2rem white-space: nowrap overflow: hidden .desc - margin-top: 1rem + margin-top: 0.65rem height: 6rem overflow: hidden color: #666 @@ -50,11 +50,11 @@ .toolbar // display: none position: absolute - top: 1.2rem + top: 0.78rem right: 1.25rem background-color: white > a, > .fake-link - margin: 0 0 0 0.5rem + margin: 0 0 0 0.325rem font-size: 1.4rem color: #999 &:hover diff --git a/src/components/repository/RepositoryForm.tsx b/src/components/repository/RepositoryForm.tsx index 85e6fff..8a0d10e 100644 --- a/src/components/repository/RepositoryForm.tsx +++ b/src/components/repository/RepositoryForm.tsx @@ -6,7 +6,6 @@ import { TextField } from 'formik-material-ui' import * as Yup from 'yup' import { Button, Theme, Dialog, DialogContent, DialogTitle } from '@material-ui/core' import { makeStyles } from '@material-ui/styles' -import { SlideUp } from 'components/common/Transition' import { RepositoryFormData, RootState, Repository } from '../../actions/types' import UserList from '../common/UserList' import Select from '../common/Select' @@ -15,6 +14,7 @@ import * as _ from 'lodash' import { updateRepository, addRepository } from '../../actions/repository' import { fetchOwnedOrganizationList, fetchJoinedOrganizationList } from '../../actions/organization' import { refresh } from '../../actions/common' +import { SlideUp } from 'components/common/Transition' const useStyles = makeStyles(({ spacing }: Theme) => ({ root: {}, @@ -44,10 +44,8 @@ const useStyles = makeStyles(({ spacing }: Theme) => ({ }, })) -const schema = Yup.object().shape>({ - name: Yup.string() - .required(YUP_MSG.REQUIRED) - .max(20, YUP_MSG.MAX_LENGTH(20)), +const schema = Yup.object().shape>({ + name: Yup.string().required(YUP_MSG.REQUIRED).max(20, YUP_MSG.MAX_LENGTH(20)), description: Yup.string().max(1000, YUP_MSG.MAX_LENGTH(1000)), }) @@ -76,7 +74,7 @@ function RepositoryForm(props: Props) { } const auth = useSelector((state: RootState) => state.auth) const organizations = useSelector((state: RootState) => { - return _.uniqBy([...state.ownedOrganizations.data, ...state.joinedOrganizations.data], 'id') + return [...state.ownedOrganizations.data, ...state.joinedOrganizations.data] }).map(org => ({ label: org.name, value: org.id, @@ -88,7 +86,7 @@ function RepositoryForm(props: Props) { useEffect(() => { dispatch(fetchJoinedOrganizationList()) dispatch(fetchOwnedOrganizationList()) - }, []) + }, [dispatch]) if (repository) { repository = { ...FORM_STATE_INIT, ...repository } @@ -137,7 +135,7 @@ function RepositoryForm(props: Props) { render={({ isSubmitting, setFieldValue, values }) => { function loadUserOptions( input: string, - ): Promise> { + ): Promise<{ label: string; value: number }[]> { return new Promise(async resolve => { const users = await AccountService.fetchUserList({ name: input }) const options = _.differenceWith(users.data, values.members || [], _.isEqual) @@ -187,10 +185,11 @@ function RepositoryForm(props: Props) {
    diff --git a/src/components/status/Status.sass b/src/components/status/Status.sass index a53e8c4..5d0d76a 100644 --- a/src/components/status/Status.sass +++ b/src/components/status/Status.sass @@ -1,9 +1,9 @@ .Status - padding: 2rem + padding: 1.3rem > .header - margin-bottom: 3rem + margin-bottom:1.95rem > .title - font-size: 2rem + font-size: 1.3rem .body text-align: center .card @@ -12,7 +12,7 @@ .name font-size: 1rem .value - font-size: 5rem + font-size: 3.25rem .unit margin-left: 5px font-size: 1rem @@ -23,5 +23,5 @@ width: 40% height: 350px > .header > .title - font-size: 2rem - margin-bottom: 1rem + font-size: 1.3rem + margin-bottom: 0.65rem diff --git a/src/components/status/Status.tsx b/src/components/status/Status.tsx index 845608d..5996e3b 100644 --- a/src/components/status/Status.tsx +++ b/src/components/status/Status.tsx @@ -3,6 +3,7 @@ import { connect } from 'react-redux' import { RChart } from '../utils/' import './Status.css' import { Card } from '@material-ui/core' +import { withTheme } from '@material-ui/styles' // TODO 2.3 仓库曲线 接口曲线 // TODO 2.3 接口覆盖率 @@ -10,14 +11,16 @@ import { Card } from '@material-ui/core' // TODO 2.3 用户曲线 class Status extends Component { - static adapt(list: any, label: any) { + adapt(list: any, label: any) { + const theme = this.props.theme + const mainColor = theme.palette.primary.main return { labels: list.map((item: any) => item.label), datasets: [{ label: label || '-', data: list.map((item: any) => item.value), - backgroundColor: RChart.COLORS.blue, - borderColor: RChart.COLORS.blue, + backgroundColor: mainColor, + borderColor: mainColor, borderWidth: 1, fill: false, }], @@ -71,19 +74,19 @@ class Status extends Component {
    最近 30 天新建仓库数
    - +
    最近 30 天活跃仓库数
    - +
    最近 30 天活跃用户排行
    - +
    最近 30 天活跃仓库排行
    - +
    @@ -108,4 +111,4 @@ const mapDispatchToProps = ({}) export default connect( mapStateToProps, mapDispatchToProps -)(Status) +)(withTheme(Status)) diff --git a/src/components/tester/Tester.sass b/src/components/tester/Tester.sass index dce99d2..cc6c315 100644 --- a/src/components/tester/Tester.sass +++ b/src/components/tester/Tester.sass @@ -2,24 +2,24 @@ .Tester .header - padding: 2rem 2rem 1rem 2rem + padding: 1.3rem 1.3rem 0.65rem 1.3rem border-bottom: 1px solid #e1e4e8 background-color: #fafbfc .card-mods, .card-itfs display: flex - margin-bottom: 1rem + margin-bottom: 0.65rem > .card-title margin-bottom: 0 - width: 5rem - min-width: 5rem - font-size: 1.4rem + width: 3.25rem + min-width: 3.25rem + font-size: 1rem > ul margin-bottom: 0 padding-left: 0 list-style: none > li float: left - margin-right: 1rem + margin-right: 0.65rem padding: 2px 0 width: 10rem overflow: hidden @@ -31,23 +31,23 @@ a color: $brand .body - padding: 2rem + padding: 1.3rem .card-props - margin-bottom: 2rem + margin-bottom: 1.3rem ul.fields list-style: none padding-left: 0 > li.filed float: left - margin-right: 1rem + margin-right: 0.65rem width: 10rem .label margin-bottom: .5rem padding-left: .5rem font-weight: bold .card-result - margin-top: 1rem + margin-top: 0.65rem .card-title - font-size: 1.2rem - margin-bottom: 1rem + font-size: 1rem + margin-bottom: 0.65rem diff --git a/src/components/utils/Dialog.sass b/src/components/utils/Dialog.sass index d4d6216..2f10300 100644 --- a/src/components/utils/Dialog.sass +++ b/src/components/utils/Dialog.sass @@ -12,14 +12,14 @@ .dialog-close position: absolute - right: 1rem - top: 1rem + right: 0.65rem + top: 0.65rem border: none background-color: transparent opacity: .2 .rapfont - font-size: 3rem + font-size:1.95rem &:hover, &:focus color: #000 @@ -30,17 +30,17 @@ .dialog-content .dialog-header border-bottom: 1px solid $border - padding: 1.5rem 4rem 1.5rem 3rem + padding: 1.5rem 2.6rem 1.5rem 1.95rem text-align: left .dialog-title margin: 0 font-size: 1.8rem .dialog-body - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem .dialog-footer text-align: left border-top: 1px solid $border - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem .dialog-backdrop position: fixed diff --git a/src/components/utils/Modal.sass b/src/components/utils/Modal.sass index 6252ac4..d9b114c 100644 --- a/src/components/utils/Modal.sass +++ b/src/components/utils/Modal.sass @@ -14,8 +14,8 @@ button.close position: absolute - right: 1rem - top: 1rem + right: 0.65rem + top: 0.65rem border: none color: #000 background-color: transparent @@ -24,20 +24,20 @@ opacity: .5 text-decoration: none .rapfont - font-size: 3rem + font-size:1.95rem .modal-header border-bottom: 1px solid $border - padding: 1.5rem 4rem 1.5rem 3rem + padding: 1.5rem 2.6rem 1.5rem 1.95rem text-align: left .modal-title margin: 0 font-size: 1.8rem .modal-body - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem .modal-footer text-align: left border-top: 1px solid $border - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem .modal-backdrop position: fixed diff --git a/src/components/utils/Pagination.sass b/src/components/utils/Pagination.sass index dc45f42..123d818 100644 --- a/src/components/utils/Pagination.sass +++ b/src/components/utils/Pagination.sass @@ -5,7 +5,7 @@ width: 100% .summary align-self: center - padding: 0.5rem 0 + padding: 0.325rem 0 flex: 1 .page-list display: flex @@ -16,7 +16,7 @@ margin: 0 .2rem .page-link display: inline-block - padding: 0.5rem 1rem + padding: 0.325rem 0.65rem border-radius: 0.4rem &:hover color: white diff --git a/src/components/utils/Popover.sass b/src/components/utils/Popover.sass index 460dce2..3de8353 100644 --- a/src/components/utils/Popover.sass +++ b/src/components/utils/Popover.sass @@ -31,7 +31,7 @@ .popover-title margin: 0 - padding: 0.5rem 1rem // 8px 14px + padding: 0.325rem 0.65rem // 8px 14px border-bottom: 1px solid #ebebeb border-radius: .4rem .4px 0 0 font-size: 14px @@ -39,6 +39,6 @@ .popover-content margin: 0 - padding: 0.5rem 1rem // 8px 14px + padding: 0.325rem 0.65rem // 8px 14px font-size: 12px line-height: 22px diff --git a/src/components/utils/PropertyEditor.sass b/src/components/utils/PropertyEditor.sass index 5546f4f..bf8dd39 100644 --- a/src/components/utils/PropertyEditor.sass +++ b/src/components/utils/PropertyEditor.sass @@ -5,11 +5,11 @@ flex-basis: 10rem .rule-wrapper flex-basis: 10rem - padding-right: 1rem + padding-right: 0.65rem .range-wrapper - padding-right: 1rem + padding-right: 0.65rem .drange-wrapper - padding-right: 1rem + padding-right: 0.65rem .value-wrapper flex-basis: 15rem @@ -27,7 +27,7 @@ border-radius: .4rem box-shadow: none outline: none - width: 4rem + width: 2.6rem text-align: center input.value width: 8rem diff --git a/src/components/utils/RChart.tsx b/src/components/utils/RChart.tsx index 95e89d6..e9c70fa 100644 --- a/src/components/utils/RChart.tsx +++ b/src/components/utils/RChart.tsx @@ -28,7 +28,7 @@ class RChart extends Component { { this.$canvas = $canvas }} width={width} height={height} /> ) } - componentDidUpdate() { + componentDidMount() { const ctx = this.$canvas.getContext('2d') this.$chart = new Chart(ctx, { type: this.props.type, diff --git a/src/components/utils/RModal.sass b/src/components/utils/RModal.sass index 2f1a361..2ec49cd 100644 --- a/src/components/utils/RModal.sass +++ b/src/components/utils/RModal.sass @@ -23,8 +23,8 @@ button.close position: absolute - right: 1rem - top: 1.4rem + right: 0.65rem + top: 0.875rem border: none color: #000 background-color: transparent @@ -33,23 +33,23 @@ opacity: .5 text-decoration: none .gofont - font-size: 3rem + font-size:1.95rem .rmodal-header border-bottom: 1px solid $border - padding: 1.5rem 4rem 1.5rem 3rem + padding: 1.5rem 2.6rem 1.5rem 1.95rem text-align: left .rmodal-title margin: 0 .5rem 0 0 - font-size: 1.8rem + font-size: 1.2rem .rmodal-body - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem .rmodal-footer text-align: left border-top: 1px solid $border - padding: 1.5rem 3rem + padding: 1.5rem 1.95rem .rmodal-backdrop position: fixed diff --git a/src/components/utils/Spin.tsx b/src/components/utils/Spin.tsx index f10b78d..aff4808 100644 --- a/src/components/utils/Spin.tsx +++ b/src/components/utils/Spin.tsx @@ -4,9 +4,7 @@ import './Spin.css' export default () => (
    -
    -
    -
    + 拼命加载中...(*╹▽╹*)
    ) diff --git a/src/components/utils/TagsInput.sass b/src/components/utils/TagsInput.sass index 1b25b61..0ce6487 100644 --- a/src/components/utils/TagsInput.sass +++ b/src/components/utils/TagsInput.sass @@ -45,13 +45,13 @@ $input-padding: .2rem 0 margin-bottom: $tag-margin-bottom padding: $input-padding width: 6rem - height: 2rem + height: 1.3rem border: none outline: none .dropdown-menu position: absolute left: 0 - top: 2rem + top: 1.3rem display: block diff --git a/src/components/utils/Utils.sass b/src/components/utils/Utils.sass index ba1de14..1c7cac5 100644 --- a/src/components/utils/Utils.sass +++ b/src/components/utils/Utils.sass @@ -1,2 +1,2 @@ .Utils - padding: 2rem + padding: 1.3rem diff --git a/src/config/config.dev.ts b/src/config/config.dev.ts index 5c096fc..a1aa3a7 100644 --- a/src/config/config.dev.ts +++ b/src/config/config.dev.ts @@ -1,5 +1,6 @@ + const config: IConfig = { - serve: `http://${window.location.hostname}:8080`, + serve: 'http://127.0.0.1:8080', keys: ['some secret hurr'], session: { key: 'koa:sess', diff --git a/src/config/config.prod.ts b/src/config/config.prod.ts index 274f8df..57943f0 100644 --- a/src/config/config.prod.ts +++ b/src/config/config.prod.ts @@ -1,3 +1,4 @@ + const config: IConfig = { serve: 'http://rap2api.taobao.org', keys: ['some secret hurr'], diff --git a/src/config/index.ts b/src/config/index.ts index ab7e6bd..617bac1 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,3 +1,4 @@ + const config: IConfig = process.env.NODE_ENV === 'development' // development or production ? require('./config.dev').default diff --git a/src/family/Family.tsx b/src/family/Family.tsx index 6f47790..e237b93 100644 --- a/src/family/Family.tsx +++ b/src/family/Family.tsx @@ -3,6 +3,7 @@ import start from './start' import handleLocation from './handleLocation' import { createBrowserHistory as createHistory, History } from 'history' import { createStore, applyMiddleware, combineReducers, compose, Store } from 'redux' +import { apiMiddleware } from 'redux-api-middleware' import { routerMiddleware as createRouterMiddleware, connectRouter, @@ -109,8 +110,8 @@ const Family: { })) || compose const middlewares = logger - ? [loggerMiddleware, routerMiddleware, sagaMiddleware] - : [routerMiddleware, sagaMiddleware] + ? [loggerMiddleware, routerMiddleware, apiMiddleware, sagaMiddleware] + : [routerMiddleware, apiMiddleware, sagaMiddleware] const store = createStore( combineReducers({ ..._reducers, router: connectRouter(history) }), composeEnhancers(applyMiddleware(...middlewares)), diff --git a/src/family/GlobalProvider.tsx b/src/family/GlobalProvider.tsx index 0baff57..e2af0f3 100644 --- a/src/family/GlobalProvider.tsx +++ b/src/family/GlobalProvider.tsx @@ -30,7 +30,7 @@ export const GlobalContext = React.createContext({ export const GlobalProvider = ({ children }: { children: React.ReactNode }) => { const [options, setOptions] = useState({ ...defaultOptions }) - const [resolveReject, setResolveReject] = useState void>>([]) + const [resolveReject, setResolveReject] = useState<(() => void)[]>([]) const [resolve, reject] = resolveReject const confirm = useCallback((options: CallOptions) => { diff --git a/src/family/handleLocation.ts b/src/family/handleLocation.ts index 572f444..d6c7614 100644 --- a/src/family/handleLocation.ts +++ b/src/family/handleLocation.ts @@ -1,9 +1,12 @@ +import URI from 'urijs' + const handleLocation = ({ store, listeners, location, }: any) => { // TODO 2.x 统一控制日志 + location.params = URI(location.search || '').search(true) const auth = store.getState().auth const isLogined = !!(auth && auth.id) const { diff --git a/src/family/start.tsx b/src/family/start.tsx index d60fa76..41d8185 100644 --- a/src/family/start.tsx +++ b/src/family/start.tsx @@ -1,17 +1,19 @@ import React, { Component } from 'react' import { render } from 'react-dom' import { Store } from 'redux' -import { Provider } from 'react-redux' +import { connect, Provider } from 'react-redux' import { History } from 'history' import { ConnectedRouter } from 'connected-react-router' import { MuiThemeProvider } from '@material-ui/core/styles/' import { SnackbarProvider } from 'notistack' import { GlobalProvider } from './GlobalProvider' -import { withStyles } from '@material-ui/core' +import { ThemeProvider, CssBaseline } from '@material-ui/core' import GlobalStyles from '../components/common/GlobalStyles' import MuiTheme from '../components/common/MuiTheme' import Routes from 'routes' import { PropTypes } from 'family' +import { THEME_TEMPLATES } from 'components/account/ThemeChangeOverlay' +import { RootState } from 'actions/types' const start = ( container: any, @@ -26,24 +28,38 @@ const start = ( return { store } } render() { + const themeId = this.props.themeId + const theme = MuiTheme(THEME_TEMPLATES[themeId].theme) + theme.overrides = { + ...theme.overrides, + MuiCssBaseline: { + ...GlobalStyles(theme), + }, + } return ( - - - - + + + + + - - - - + + + + ) } } - const Root = withStyles(GlobalStyles)(RootBase) - render(, container) + const App = connect((state: RootState) => ({ themeId: state.themeId }), {})(RootBase) + + render(( + + + + ), container) } export default start diff --git a/src/index.tsx b/src/index.tsx index 033cfd4..81107b5 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -14,6 +14,8 @@ import EditorRelative from './relatives/EditorRelative' import Spin from './components/utils/Spin' import * as AccountAction from './actions/account' import AccountService from './relatives/services/Account' +import { CACHE_KEY } from 'utils/consts' +import { AnyAction } from 'redux' if (process.env.NODE_ENV !== 'production') { const whyDidYouRender = require('@welldone-software/why-did-you-render/dist/no-classes-transpile/umd/whyDidYouRender.min.js') @@ -41,6 +43,7 @@ function* authenticate() { const auth = yield call(AccountService.fetchLoginInfo) if (auth) { yield put(AccountAction.fetchLoginInfoSucceeded(auth)) + yield put(AccountAction.fetchUserSettings([CACHE_KEY.THEME_ID]) as AnyAction) } else { const { pathname, search, hash } = window.location // const uri = URI(pathname + search + hash) diff --git a/src/relatives/AccountRelative.ts b/src/relatives/AccountRelative.ts index 9fe7656..323803a 100644 --- a/src/relatives/AccountRelative.ts +++ b/src/relatives/AccountRelative.ts @@ -1,13 +1,52 @@ -import { call, put, select } from 'redux-saga/effects' +import { call, put, select, take } from 'redux-saga/effects' import * as AccountAction from '../actions/account' import * as CommonAction from '../actions/common' import AccountService from './services/Account' import { StoreStateRouterLocationURI, replace, push } from '../family' import { RootState } from '../actions/types' import { showMessage, MSG_TYPE } from 'actions/common' +import { THEME_TEMPLATE_KEY } from 'components/account/ThemeChangeOverlay' +import { CHANGE_THEME, DoUpdateUserSettingAction, updateUserSetting, UPDATE_USER_SETTING_SUCCESS, DO_UPDATE_USER_SETTING } from '../actions/account' +import { AnyAction } from 'redux' const relatives = { reducers: { + userSettings(state: RootState['userSettings'] = {}, action: any) { + switch (action.type) { + case AccountAction.FETCH_USER_SETTINGS_SUCCESS: { + if (action.payload.isOk) { + return { + ...state, + ...action.payload.data, + } + } + break + } + } + return state + }, + userSettingsIsUpdating(state: boolean = false, action: any) { + switch (action.type) { + case AccountAction.UPDATE_USER_SETTING_REQUEST: + case AccountAction.FETCH_USER_SETTINGS_REQUEST: + return true + case AccountAction.UPDATE_USER_SETTING_FAILURE: + case AccountAction.UPDATE_USER_SETTING_SUCCESS: + case AccountAction.FETCH_USER_SETTINGS_FAILURE: + case AccountAction.FETCH_USER_SETTINGS_SUCCESS: + return false + } + return state + }, + themeId(state: THEME_TEMPLATE_KEY = THEME_TEMPLATE_KEY.INDIGO, action: any) { + switch (action.type) { + case CHANGE_THEME: + return action.payload + + default: + return state + } + }, loading(state: boolean = false, action: any) { switch (action.type) { case 'INTERFACE_LOCK': @@ -87,6 +126,18 @@ const relatives = { }, }, sagas: { + *[AccountAction.DO_FETCH_USER_SETTINGS](action: AccountAction.DoFetchUserSettingsAction) { + const { keys, cb } = action.payload + yield put(AccountAction.fetchUserSettings(keys) as AnyAction) + const resultAction = yield take(AccountAction.FETCH_USER_SETTINGS_SUCCESS) + cb && cb(true, resultAction.payload) + }, + *[AccountAction.FETCH_USER_SETTINGS_SUCCESS](action: any) { + const themeId = action.payload?.data?.THEME_ID + if (themeId) { + yield put(AccountAction.changeTheme(themeId)) + } + }, *[CommonAction.refresh().type]() { const router = yield select((state: RootState) => state.router) const uri = StoreStateRouterLocationURI(router) @@ -210,6 +261,13 @@ const relatives = { yield put(AccountAction.resetpwdFailed(e.message)) } }, + *[DO_UPDATE_USER_SETTING](action: DoUpdateUserSettingAction) { + console.log('什么鬼啊') + const { key, value, cb } = action.payload + yield put(updateUserSetting(key, value) as AnyAction) + const opAction = yield take(UPDATE_USER_SETTING_SUCCESS) + cb && cb(opAction.payload.isOk) + }, }, listeners: { '/account': [AccountAction.fetchUserList], diff --git a/src/relatives/effects/interface.ts b/src/relatives/effects/interface.ts index 71a0a80..cda783e 100644 --- a/src/relatives/effects/interface.ts +++ b/src/relatives/effects/interface.ts @@ -12,10 +12,13 @@ import { StoreStateRouterLocationURI } from 'family' export function* fetchInterface(action: any) { try { + if (!action.id) { + return + } const payload = yield call(EditorService.fetchInterface, action.id) yield put(InterfaceAction.fetchInterfaceSucceeded(payload)) if (action.onResolved) { - action.onResolved() + action.onResolved(payload) } } catch (e) { console.error(e.message) diff --git a/src/relatives/effects/repository.ts b/src/relatives/effects/repository.ts index c716357..916118d 100644 --- a/src/relatives/effects/repository.ts +++ b/src/relatives/effects/repository.ts @@ -2,7 +2,6 @@ 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' // @@ -86,14 +85,7 @@ export function* importSwaggerRepository(action: any) { export function* fetchRepository(action: any) { try { - const router = yield select((state: RootState) => state.router) - const uri = StoreStateRouterLocationURI(router) - const params = uri.search(true) - const repository = yield call( - RepositoryService.fetchRepository, - action.repository || action.id, - params.token, - ) + const repository = yield call(RepositoryService.fetchRepository, action.repository || action.id) yield put(RepositoryAction.fetchRepositorySucceeded(repository)) } catch (e) { yield put(RepositoryAction.fetchRepositoryFailed(e.message)) diff --git a/src/relatives/services/Repository.ts b/src/relatives/services/Repository.ts index bd4e22e..84d74e2 100644 --- a/src/relatives/services/Repository.ts +++ b/src/relatives/services/Repository.ts @@ -1,5 +1,6 @@ import { CREDENTIALS, serve } from './constant' import { IDefaultVal } from 'components/editor/DefaultValueModal' +import { ENTITY_TYPE } from 'utils/consts' // 仓库 export default { @@ -11,7 +12,7 @@ export default { fetchRepositoryList({ user = '', organization = '', name = '', cursor = 1, limit = 100 }: any = {}) { return fetch(`${serve}/repository/list?user=${user}&organization=${organization}&name=${name}&cursor=${cursor}&limit=${limit}`, { ...CREDENTIALS }) .then(res => res.json()) - // .then(json => json.data) + // .then(json => json.data) }, fetchOwnedRepositoryList({ user = '', name = '' }: any = {}) { return fetch(`${serve}/repository/owned?user=${user}&name=${name}`, { ...CREDENTIALS }) @@ -23,13 +24,8 @@ export default { .then(res => res.json()) // .then(json => json.data) }, - fetchRepository(id: any, token?: string) { - return fetch( - `${serve}/repository/get?id=${id}&excludeProperty=true${ - token !== undefined ? `&token=${token}` : '' - }`, - { ...CREDENTIALS }, - ) + fetchRepository(id: any) { + return fetch(`${serve}/repository/get?id=${id}&excludeProperty=true`, { ...CREDENTIALS }) .then(res => res.json()) .then(json => json.data) }, @@ -97,4 +93,10 @@ export default { }) .then(res => res.json()) }, + fetchHistoryLogs({ entityId, entityType, limit, offset }: + { entityId: number, entityType: ENTITY_TYPE.INTERFACE | ENTITY_TYPE.REPOSITORY, limit: number, offset: number }) { + return fetch(`${serve}/${entityType === ENTITY_TYPE.INTERFACE ? 'interface' : 'repository'}/history/${entityId}?limit=${limit}&offset=${offset}`, { ...CREDENTIALS }) + .then(res => res.json()) + .then(json => json.data) + } } diff --git a/src/routes.tsx b/src/routes.tsx index 66f03b4..df52ef2 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -13,6 +13,8 @@ import ResetpwdForm from './components/account/ResetpwdForm' import Message from 'components/common/Message' import { useSelector } from 'react-redux' import { RootState } from 'actions/types' +import MySettingsView from './components/account/MySettingsView' +import AboutView from './components/home/AboutView' const UserList = lazy(() => import(/* webpackChunkName: "./components/account/UserList" */ './components/account/UserList')) @@ -55,7 +57,7 @@ const Routes = () => { if (!auth.id) { // 引导用户登陆,已经在 src/index 中实现。这里的代码用于支持没有接入 SSO 的情况。 return (
    - + @@ -68,85 +70,99 @@ const Routes = () => { return (
    -
    { console.log('hahaha'); window.scrollTo(0, 0) }}> +
    window.scrollTo(0, 0)}> 回到顶部
    - }> - - - ( - - - - - - - - - - - )} - /> - ( - - - - - - - - - )} - /> - ( - - - - - )} - /> - ( - - - - - - - - - - )} - /> - ( -
    - -
    - )} - /> - ( - - - - - )} - /> - -
    -
    + }> + + + ( + + + + + + + + + + + )} + /> + ( + + + + + + + + + )} + /> + ( + + + + + )} + /> + ( + + + + + + + + )} + /> + ( +
    + +
    + )} + /> + ( + + + + + )} + /> + ( + + + + )} + /> + ( + + + + )} + /> + +
    +