docs: Add English documents
Add English development documents Change-Id: I4b0e7dd346a6167df2a8a2f7380504cdbd32dc96
94
docs/en/develop/1-ready-to-work.md
Normal file
@ -0,0 +1,94 @@
|
||||
English | [Chinese](/docs/zh/develop/1-ready-to-work.md)
|
||||
|
||||
# Preparation before development
|
||||
|
||||
- Node environment
|
||||
- Requirement in package.json:`"node": ">=10.22.0"`
|
||||
- Verify nodejs version
|
||||
|
||||
```shell
|
||||
node -v
|
||||
```
|
||||
|
||||
- Yarn
|
||||
- Install yarn
|
||||
|
||||
```shell
|
||||
npm install -g yarn
|
||||
```
|
||||
|
||||
- Install dependencies
|
||||
- Execute in the project root directory, which is the same level as `package.json`, and wait patiently for the installation to complete
|
||||
|
||||
```shell
|
||||
yarn install
|
||||
```
|
||||
|
||||
- Prepare a usable backend
|
||||
- Prepare an accessible backend, for example: https://172.20.154.250
|
||||
- Modify the corresponding configuration in `config/webpack.dev.js`:
|
||||
|
||||
```javascript
|
||||
if (API === 'mock' || API === 'dev') {
|
||||
devServer.proxy = {
|
||||
'/api': {
|
||||
target: 'https://172.20.154.250',
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- Configure access host and port
|
||||
- Modify `devServer.host` and `devServer.port`
|
||||
- Modify the corresponding configuration in `config/webpack.dev.js`
|
||||
|
||||
```javascript
|
||||
const devServer = {
|
||||
host: '0.0.0.0',
|
||||
// host: 'localhost',
|
||||
port: 8088,
|
||||
contentBase: root('dist'),
|
||||
historyApiFallback: true,
|
||||
compress: true,
|
||||
hot: true,
|
||||
inline: true,
|
||||
disableHostCheck: true,
|
||||
// progress: true
|
||||
};
|
||||
```
|
||||
|
||||
- Completed
|
||||
- Execute in the project root directory, which is the same level as `package.json`
|
||||
|
||||
```shell
|
||||
yarn run dev
|
||||
```
|
||||
|
||||
- Use the `host` and `port` configured in `config/webpack.dev.js` to access, such as `http://localhost:8088`
|
||||
- The front-end real-time update environment used for development is done.
|
||||
|
||||
# Front-end package used in production environment
|
||||
|
||||
- Have the required `nodejs` and `yarn`
|
||||
- Execute in the project root directory, which is the same level as `package.json`
|
||||
|
||||
```shell
|
||||
yarn run build
|
||||
```
|
||||
|
||||
- The packaged files are in the `dist` directory and handed over to the deployment personnel.
|
||||
|
||||
# Front-end package used for testing
|
||||
|
||||
- Have the required `nodejs` and `yarn`
|
||||
- Execute in the project root directory, which is the same level as `package.json`
|
||||
|
||||
```shell
|
||||
yarn run build:test
|
||||
```
|
||||
|
||||
- The packaged files are in the `dist` directory
|
||||
- Attention! ! ! This test package is designed to measure code coverage
|
||||
- It is recommended to use nginx to complete the E2E test with code coverage.
|
380
docs/en/develop/2-catalog-introduction.md
Normal file
@ -0,0 +1,380 @@
|
||||
English | [Chinese](/docs/zh/develop/2-catalog-introduction.md)
|
||||
|
||||
# Introduction to the first-level directory
|
||||
|
||||
- `Gruntfile.js`:Used to collect i18n
|
||||
- `LICENSE`: This project uses Apache License
|
||||
- `Makefile`:
|
||||
- `README.md`: A brief description of the front-end startup, please refer to the docs for details
|
||||
- `config`: webpack configuration, which contains webpack configuration in public, development environment, test environment, and build environment
|
||||
- `cypress.json`: E2E test configuration file
|
||||
- `docker`: Contains the docker configuration used in the development environment, generation environment, and test environment
|
||||
- `docs`: Documentation introduction, including Chinese, English, development documentation, testing documentation, the en documentation is temporarily missing
|
||||
- `jest.config.js`: Unit test configuration file
|
||||
- `jsconfig.json`: javascript code configuration file
|
||||
- `package.json`: Configuration files such as installation packages and commands
|
||||
- `yarn.lock`: The version lock file of the package
|
||||
- `.babelrc`: Babel configuration file
|
||||
- `.dockerignore`: File configuration ignored by docker
|
||||
- `.eslintignore`: File configuration ignored by eslint
|
||||
- `.eslint`: Eslint configuration
|
||||
- `.gitignore`: File configuration ignored by git
|
||||
- `.gitreview`: Gitreview configuration
|
||||
- `.prettierignore`: File configuration ignored by prettier
|
||||
- `.prettierrc`: Prettier configuration
|
||||
- `src`: The folder where the development code is located! ! !
|
||||
- `test`: The folder where the test code is located! ! ! Contains e2e test code and basic code for unit testing
|
||||
- `tools`: Other tools folder, containing git tools
|
||||
|
||||
# Directory Introduction for src
|
||||
|
||||
- `src/components`: Public component
|
||||
- `src/api`: API, not used yet
|
||||
- `src/asset`: Images, template and other static files
|
||||
- `src/containers`:
|
||||
- Components with state
|
||||
- Basic class
|
||||
- [BaseList](3-1-BaseList-introduction.md)
|
||||
- [BaseDetail](3-3-BaseDetail-introduction.md)
|
||||
- [BaseForm](3-6-FormAction-introduction.md)
|
||||
- [BaseModalAction](3-7-ModalAction-introduction.md)
|
||||
- [BaseConfirmAction](3-8-ConfirmAction-introduction.md)
|
||||
- [BaseStepAction](3-9-StepAction-introduction.md)
|
||||
- `src/core`:
|
||||
- `index.js`: Entry file
|
||||
- `routes.js`: Routing configuration by module
|
||||
- `i18n.js`
|
||||
- `App.jsx`
|
||||
- `src/layouts`:
|
||||
- Define all the components of the overall page layout
|
||||
- Blank layout BlankLayout
|
||||
- Layout used for login page UserLayout
|
||||
- The layout used for the content page BaseLayout(Use of lists, details, forms, etc.)
|
||||
- `menu.jsx`: Menu configuration used by the console
|
||||
- `admin-menu.jsx`: Menu configuration used by the management platform
|
||||
- `src/locales`: i18n
|
||||
- `src/resources`:
|
||||
- Define the state/search items of each resource being shared
|
||||
- Define the table columns where each resource is shared
|
||||
- Define the reuse function of each resource
|
||||
- `src/stores`:
|
||||
- Data acquisition and operation of resources, etc.
|
||||
- Name the resource name according to lowercase letters and hyphens
|
||||
- The directory is divided into two levels: for example `nova/instances.js`, `cinder/volume.js`
|
||||
- `src/utils`:
|
||||
- Public function(time format、regexp、cookie、localStorage、......)
|
||||
- Corresponding unit test, ending with test.js or spec.js
|
||||
- `src/styles`: Basic styles, common styles, style variables, etc.
|
||||
- `src/pages`:
|
||||
- Progressively according to the page hierarchy (according to: menu item-secondary menu)
|
||||
- All directory names are lowercase and hyphenated. The directory contains two folders `containers` and `routers`, and one file `App.js`
|
||||
- Store pages corresponding to secondary directories under `containers`
|
||||
- `routes` is used to configure routing
|
||||
|
||||
# Directory Introduction for src/pages
|
||||
|
||||
- Divide the directory with the first and second level menus, the first level menu is listed under `src/pages`, and the corresponding second level menu page is under `src/pages/xxx/containers`, take "Compute-Instance" as an example , "Compute" corresponds to the `src/pages/compute` directory, and "Instance" corresponds to the `src/pages/compute/containers/Instance` directory
|
||||
- `src/pages/compute/containers/Instance/index.jsx`: Instance list page, inherited from [BaseList component](3-1-BaseList-introduction.md) (with Tab
|
||||
Page, just inherit the TabBaseList component)
|
||||
- `src/pages/compute/containers/Instance/Detail`
|
||||
- Instance detail page
|
||||
- `index.jsx`inherited from[BaseDetail Component](3-3-BaseDetail-introduction.md)
|
||||
- `src/pages/compute/containers/Instance/actions`
|
||||
- Instance operation
|
||||
- `Lock.jsx` Lock the instance, inherited from[BaseConfirmAction](3-8-ConfirmAction-introduction.md)
|
||||
- `AttachInterface.jsx` inherited from[BaseModalAction](3-7-ModalAction-introduction.md)
|
||||
- `StepCreate/index.jsx`inherited from[BaseStepAction](3-9-StepAction-introduction.md)
|
||||
- `src/pages/compute/routes`:
|
||||
- `index.js` Configure routing
|
||||
- It is agreed that whether the route contains "-admin" to determine whether it is the management platform or the console
|
||||
|
||||
# Directory Introduction for test
|
||||
|
||||
[English](/docs/en/test/2-catalog-introduction.md) | [Chinese](/docs/zh/test/2-catalog-introduction.md)
|
||||
|
||||
# Catalog Introduction-Image Version
|
||||
|
||||
```
|
||||
.
|
||||
├── Gruntfile.js (Used to collect i18n)
|
||||
├── LICENSE
|
||||
├── Makefile
|
||||
├── README.md
|
||||
├── config
|
||||
│ ├── theme.js
|
||||
│ ├── webpack.common.js
|
||||
│ ├── webpack.dev.js (Webpack configuration used during development)
|
||||
│ ├── webpack.e2e.js (The webpack configuration used during e2e testing can generate a package for testing coverage)
|
||||
│ └── webpack.prod.js (Webpack packaging configuration used by the generation environment)
|
||||
├── cypress.json (E2E configuration)
|
||||
├── docker
|
||||
│ ├── dev.dockerfile
|
||||
│ ├── nginx.conf
|
||||
│ ├── prod.dockerfile
|
||||
│ └── test.dockerfile
|
||||
├── docs (Documents)
|
||||
├── jest.config.js (Unit testing configuration)
|
||||
├── jsconfig.json
|
||||
├── package.json
|
||||
├── src
|
||||
│ ├── api (Api summary, not used yet)
|
||||
│ ├── asset
|
||||
│ │ ├── image (Images placement)
|
||||
│ │ └── template
|
||||
│ │ └── index.html
|
||||
│ ├── components (Public components)
|
||||
│ ├── containers
|
||||
│ │ ├── Action
|
||||
│ │ │ ├── ConfirmAction (Confirmed action base class)
|
||||
│ │ │ ├── FormAction (Single page action base class)
|
||||
│ │ │ ├── ModalAction (Pop-up action base class)
|
||||
│ │ │ ├── StepAction (Multi-step single-page action, for example: create a cloud host)
|
||||
│ │ │ └── index.jsx
|
||||
│ │ ├── BaseDetail (Detail page base class with detailed information)
|
||||
│ │ ├── List (The base class of the list page, for example: cloud host)
|
||||
│ │ ├── TabDetail (The base class of the detail page with tab switching, for example: instance details)
|
||||
│ │ └── TabList (List page with tab switch)
|
||||
│ ├── core
|
||||
│ │ ├── App.jsx
|
||||
│ │ ├── i18n.js
|
||||
│ │ ├── index.jsx (Entry)
|
||||
│ │ └── routes.js (Routing configuration by module)
|
||||
│ ├── layouts
|
||||
│ │ ├── Base (Layout used after login)
|
||||
│ │ ├── Blank (Blank layout)
|
||||
│ │ ├── User (Layout used for login)
|
||||
│ │ ├── admin-menu.jsx (Menu configuration used by the management platform)
|
||||
│ │ └── menu.jsx (Menu configuration used by the console)
|
||||
│ ├── locales (Translation)
|
||||
│ │ ├── en.json
|
||||
│ │ ├── index.js
|
||||
│ │ └── zh.json
|
||||
│ ├── pages (The page-directory structure is assigned according to: menu item-secondary menu, where the pages of the secondary menu are placed in the containers folder)
|
||||
│ │ ├── base
|
||||
│ │ │ ├── App.jsx
|
||||
│ │ │ ├── containers
|
||||
│ │ │ │ ├── 404 (404 page)
|
||||
│ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ ├── AdminOverview (Management platform home page)
|
||||
│ │ │ │ │ ├── components
|
||||
│ │ │ │ │ │ ├── ComputeService.jsx
|
||||
│ │ │ │ │ │ ├── NetworkService.jsx
|
||||
│ │ │ │ │ │ ├── PlatformInfo.jsx
|
||||
│ │ │ │ │ │ ├── ResourceOverview.jsx
|
||||
│ │ │ │ │ │ └── VirtualResource.jsx
|
||||
│ │ │ │ │ ├── index.jsx
|
||||
│ │ │ │ │ └── style.less
|
||||
│ │ │ │ └── Overview (Console home page)
|
||||
│ │ │ │ ├── components
|
||||
│ │ │ │ │ ├── ProjectInfo.jsx
|
||||
│ │ │ │ │ ├── QuotaOverview.jsx
|
||||
│ │ │ │ │ └── ResourceStatistic.jsx
|
||||
│ │ │ │ ├── index.jsx
|
||||
│ │ │ │ └── style.less
|
||||
│ │ │ └── routes (Routing configuration)
|
||||
│ │ │ └── index.js
|
||||
│ │ ├── compute
|
||||
│ │ │ ├── App.jsx
|
||||
│ │ │ ├── containers
|
||||
│ │ │ │ ├── BareMetalNode (Bare metal configuration)
|
||||
│ │ │ │ ├── Flavor (Instance type)
|
||||
│ │ │ │ ├── HostAggregate (Host Aggregate)
|
||||
│ │ │ │ │ ├── Aggregate (Host Aggregate)
|
||||
│ │ │ │ │ ├── AvailabilityZone (Availability zone)
|
||||
│ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ ├── Hypervisors (Hypervisors management)
|
||||
│ │ │ │ │ ├── ComputeHost (Compute host)
|
||||
│ │ │ │ │ ├── Hypervisor (Hypervisor manager)
|
||||
│ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ ├── Image (Image)
|
||||
│ │ │ │ ├── Instance (Intance)
|
||||
│ │ │ │ │ ├── Detail (Detail page)
|
||||
│ │ │ │ │ │ ├── BaseDetail (Base info)
|
||||
│ │ │ │ │ │ ├── SecurityGroup (Security group)
|
||||
│ │ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ │ ├── actions (Actions)
|
||||
│ │ │ │ │ │ ├── AssociateFip.jsx (Associate fip ip)
|
||||
│ │ │ │ │ │ ├── AttachInterface.jsx (Attach interface)
|
||||
│ │ │ │ │ │ ├── AttachIsoVolume.jsx (Attach iso volume)
|
||||
│ │ │ │ │ │ ├── AttachVolume.jsx (Attach volume)
|
||||
│ │ │ │ │ │ ├── ChangePassword.jsx (Change password)
|
||||
│ │ │ │ │ │ ├── Console.jsx (Console)
|
||||
│ │ │ │ │ │ ├── CreateImage.jsx (Create Image)
|
||||
│ │ │ │ │ │ ├── CreateIronic (Create ironic-Step-by-step Form)
|
||||
│ │ │ │ │ │ │ ├── BaseStep
|
||||
│ │ │ │ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ │ │ │ ├── ConfirmStep
|
||||
│ │ │ │ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ │ │ │ ├── NetworkStep
|
||||
│ │ │ │ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ │ │ │ ├── SystemStep
|
||||
│ │ │ │ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ │ │ │ ├── index.jsx
|
||||
│ │ │ │ │ │ │ └── index.less
|
||||
│ │ │ │ │ │ ├── CreateSnapshot.jsx (Create snapshot)
|
||||
│ │ │ │ │ │ ├── Delete.jsx (Delete instance)
|
||||
│ │ │ │ │ │ ├── DeleteIronic.jsx (Delete ironic)
|
||||
│ │ │ │ │ │ ├── DetachInterface.jsx (Detach interface)
|
||||
│ │ │ │ │ │ ├── DetachIsoVolume.jsx (Detach iso volume)
|
||||
│ │ │ │ │ │ ├── DetachVolume.jsx (Detach volume)
|
||||
│ │ │ │ │ │ ├── DisassociateFip.jsx (Disassociate fip iP)
|
||||
│ │ │ │ │ │ ├── Edit.jsx (Edit instance)
|
||||
│ │ │ │ │ │ ├── ExtendRootVolume.jsx (Expand the root disk)
|
||||
│ │ │ │ │ │ ├── LiveMigrate.jsx (Live migrate)
|
||||
│ │ │ │ │ │ ├── Lock.jsx (Lock instance)
|
||||
│ │ │ │ │ │ ├── ManageSecurityGroup.jsx (Manage security group)
|
||||
│ │ │ │ │ │ ├── Migrate.jsx (Migrate)
|
||||
│ │ │ │ │ │ ├── Pause.jsx (Pause instance)
|
||||
│ │ │ │ │ │ ├── Reboot.jsx (Reboot instance)
|
||||
│ │ │ │ │ │ ├── Rebuild.jsx (Rebuild instance)
|
||||
│ │ │ │ │ │ ├── RebuildSelect.jsx (Select the image to rebuild the instance)
|
||||
│ │ │ │ │ │ ├── Resize.jsx (Change configuration)
|
||||
│ │ │ │ │ │ ├── ResizeOnline.jsx (Modify configuration online)
|
||||
│ │ │ │ │ │ ├── Resume.jsx (Resume instance)
|
||||
│ │ │ │ │ │ ├── Shelve.jsx (Shelve instance)
|
||||
│ │ │ │ │ │ ├── SoftDelete.jsx (Soft delete instance)
|
||||
│ │ │ │ │ │ ├── SoftReboot.jsx (Soft reboot instance)
|
||||
│ │ │ │ │ │ ├── Start.jsx (Start instance)
|
||||
│ │ │ │ │ │ ├── StepCreate (Create a instance-step by step creation)
|
||||
│ │ │ │ │ │ │ ├── BaseStep
|
||||
│ │ │ │ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ │ │ │ ├── ConfirmStep
|
||||
│ │ │ │ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ │ │ │ ├── NetworkStep
|
||||
│ │ │ │ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ │ │ │ ├── SystemStep
|
||||
│ │ │ │ │ │ │ │ └── index.jsx
|
||||
│ │ │ │ │ │ │ ├── index.jsx
|
||||
│ │ │ │ │ │ │ └── index.less
|
||||
│ │ │ │ │ │ ├── Stop.jsx (Stop instance)
|
||||
│ │ │ │ │ │ ├── Suspend.jsx (Suspend instance)
|
||||
│ │ │ │ │ │ ├── Unlock.jsx (Unlock instance)
|
||||
│ │ │ │ │ │ ├── Unpause.jsx (Unpause instance)
|
||||
│ │ │ │ │ │ ├── Unshelve.jsx (Unshelve instance)
|
||||
│ │ │ │ │ │ ├── index.jsx
|
||||
│ │ │ │ │ │ └── index.less
|
||||
│ │ │ │ │ ├── components (Component)
|
||||
│ │ │ │ │ │ ├── FlavorSelectTable.jsx
|
||||
│ │ │ │ │ │ └── index.less
|
||||
│ │ │ │ │ ├── index.jsx
|
||||
│ │ │ │ │ └── index.less
|
||||
│ │ │ │ ├── Keypair (Key pair)
|
||||
│ │ │ │ └── ServerGroup (Instance group)
|
||||
│ │ │ └── routes (Routing configuration under the compute menu)
|
||||
│ │ │ └── index.js
|
||||
│ │ ├── configuration (Platform configuration)
|
||||
│ │ │ ├── App.jsx
|
||||
│ │ │ ├── containers
|
||||
│ │ │ │ ├── Metadata (Metadata definition)
|
||||
│ │ │ │ ├── Setting (System configuration)
|
||||
│ │ │ │ └── SystemInfo (System info)
|
||||
│ │ │ └── routes (Routing configuration under the platform configuration menu)
|
||||
│ │ │ └── index.js
|
||||
│ │ ├── heat (Resource orchestration)
|
||||
│ │ │ ├── App.jsx
|
||||
│ │ │ ├── containers
|
||||
│ │ │ │ └── Stack (Stack)
|
||||
│ │ │ └── routes (Routing configuration under the resource arrangement menu)
|
||||
│ │ │ └── index.js
|
||||
│ │ ├── identity (Identity management)
|
||||
│ │ │ ├── App.jsx
|
||||
│ │ │ ├── containers
|
||||
│ │ │ │ ├── Domain (Domian)
|
||||
│ │ │ │ ├── Project (Project)
|
||||
│ │ │ │ ├── Role (Role)
|
||||
│ │ │ │ ├── User (User)
|
||||
│ │ │ │ └── UserGroup (User group)
|
||||
│ │ │ └── routes (Routing configuration)
|
||||
│ │ │ └── index.js
|
||||
│ │ ├── management (Operation and maintenance management)
|
||||
│ │ │ ├── App.jsx
|
||||
│ │ │ ├── containers
|
||||
│ │ │ │ └── RecycleBin (Recycle bin)
|
||||
│ │ │ └── routes (Routing configuration)
|
||||
│ │ │ └── index.js
|
||||
│ │ ├── network (Network)
|
||||
│ │ │ ├── App.jsx
|
||||
│ │ │ ├── containers
|
||||
│ │ │ │ ├── FloatingIp (Floating ip)
|
||||
│ │ │ │ ├── LoadBalancers (Load balancing)
|
||||
│ │ │ │ ├── Network (Network)
|
||||
│ │ │ │ ├── QoSPolicy (Qos policy)
|
||||
│ │ │ │ ├── Router (Routing)
|
||||
│ │ │ │ ├── SecurityGroup (Security group)
|
||||
│ │ │ │ ├── Topology (Network topology)
|
||||
│ │ │ │ ├── VPN (VPN)
|
||||
│ │ │ │ └── VirtualAdapter (Virtual Adapter)
|
||||
│ │ │ └── routes (Routing configuration)
|
||||
│ │ │ └── index.js
|
||||
│ │ ├── storage (Storage)
|
||||
│ │ │ ├── App.jsx
|
||||
│ │ │ ├── containers
|
||||
│ │ │ │ ├── Backup (Backup)
|
||||
│ │ │ │ ├── Snapshot (Volume snapshot)
|
||||
│ │ │ │ ├── Storage (Storage backend)
|
||||
│ │ │ │ ├── Volume (Volume)
|
||||
│ │ │ │ └── VolumeType (Volume type)
|
||||
│ │ │ │ ├── QosSpec (QoS)
|
||||
│ │ │ │ ├── VolumeType (Volume type)
|
||||
│ │ │ │ └── index.jsx
|
||||
│ │ │ └── routes ()
|
||||
│ │ │ └── index.js
|
||||
│ │ └── user (Login page)
|
||||
│ │ ├── App.jsx
|
||||
│ │ ├── containers
|
||||
│ │ │ ├── ChangePassword (Change password-according to system configuration)
|
||||
│ │ │ │ ├── index.jsx
|
||||
│ │ │ │ └── index.less
|
||||
│ │ │ └── Login (Login)
|
||||
│ │ │ ├── index.jsx
|
||||
│ │ │ └── index.less
|
||||
│ │ └── routes (Routing configuration)
|
||||
│ │ └── index.js
|
||||
│ ├── resources (Store the public functions and status of each resource used by itself)
|
||||
│ ├── stores (Data processing, divide folders by resource type)
|
||||
│ │ ├── base-list.js (Base class for list data)
|
||||
│ │ ├── base.js (Base class for data manipulation)
|
||||
│ │ ├── cinder
|
||||
│ │ ├── glance
|
||||
│ │ ├── heat
|
||||
│ │ ├── ironic
|
||||
│ │ ├── keystone
|
||||
│ │ ├── neutron
|
||||
│ │ ├── nova
|
||||
│ │ ├── octavia
|
||||
│ │ ├── overview-admin.js
|
||||
│ │ ├── project.js
|
||||
│ │ ├── root.js
|
||||
│ │ └── skyline
|
||||
│ ├── styles (Public styles)
|
||||
│ │ ├── base.less
|
||||
│ │ ├── main.less
|
||||
│ │ ├── reset.less
|
||||
│ │ └── variables.less
|
||||
│ └── utils (Public functions)
|
||||
│ ├── RouterConfig.jsx
|
||||
│ ├── constants.js
|
||||
│ ├── cookie.js
|
||||
│ ├── file.js
|
||||
│ ├── file.spec.js
|
||||
│ ├── index.js
|
||||
│ ├── index.test.js (Unit testing)
|
||||
│ ├── local-storage.js
|
||||
│ ├── local-storage.spec.js (Unit testing)
|
||||
│ ├── request.js
|
||||
│ ├── table.jsx
|
||||
│ ├── time.js
|
||||
│ ├── time.spec.js
|
||||
│ ├── translate.js
|
||||
│ ├── translate.spec.js
|
||||
│ ├── validate.js
|
||||
│ ├── yaml.js
|
||||
│ └── yaml.spec.js
|
||||
├── test
|
||||
│ ├── e2e (E2E testing)
|
||||
│ └── unit (Unit testing)
|
||||
├── tools
|
||||
│ └── git_config
|
||||
│ └── commit_message.txt
|
||||
└── yarn.lock
|
||||
```
|
114
docs/en/develop/3-0-how-to-develop.md
Normal file
@ -0,0 +1,114 @@
|
||||
English | [Chinese](/docs/zh/develop/3-0-how-to-develop.md)
|
||||
|
||||
# Develop a new resource list page
|
||||
|
||||
- Step 1: Confirm the code location and directory structure
|
||||
- Place it under Containers according to the expected position in the menu item
|
||||
- Take the instance as an example, the corresponding menu item is `Compute-Instance`, then create the folder `src/pages/compute/containers/Instance`, create the file `src/pages/compute/containers/Instance/index.jsx `
|
||||
- Step 2: Write the Store code
|
||||
- Refer to [3-5-BaseStore-introduction](3-5-BaseStore-introduction.md), copy the corresponding function
|
||||
- Step 3: Code the list page
|
||||
- Refer to [3-1-BaseList-introduction](3-1-BaseList-introduction.md), copy the corresponding function
|
||||
- Step 4: Configure routing
|
||||
- Refer to [3-13-Route-introduction](3-13-Route-introduction.md)
|
||||
- In the `routes/index.js` file of the parent directory in step 1, configure routing
|
||||
- If it is a brand new module, you also need to import it in `src/pages/storage/routes/index.js`
|
||||
- Step 5: Configure menu
|
||||
- Refer to [3-12-Menu-introduction](3-12-Menu-introduction.md)
|
||||
- Configure the menu items of the console, which are configured in `src/layouts/menu.jsx`
|
||||
- Configure the menu items of the management platform, configured in `src/layouts/admin-menu.jsx`
|
||||
- Step 6: i18n
|
||||
- Refer to [3-14-I18n-introduction](3-14-I18n-introduction.md), Complete the corresponding translation
|
||||
- If the product requirement list page is a page containing `Tab`, please refer to [3-2-BaseTabList-introduction](3-2-BaseTabList-introduction.md), usually `Tab` is configured in `index.jsx` , Please refer to the mirror page code `src/pages/compute/containers/Image/index.jsx`
|
||||
|
||||
# Develop a new resource details page
|
||||
|
||||
- Step 1: Confirm the code location and directory structure
|
||||
- Place it under Containers according to the expected position in the menu item
|
||||
- Take the instance as an example, the corresponding menu item is `Compute-Instance`, then create the folder `src/pages/compute/containers/Instance/Detail/index.jsx`,`src/pages/compute/containers/Instance/Detail/BaseDetail.jsx`
|
||||
- Step 2: Write the Store code
|
||||
- Refer to [3-5-BaseStore-introduction](3-5-BaseStore-introduction.md), copy the corresponding function
|
||||
- Step 3: Write the code of the detail page
|
||||
- Refer to [3-3-BaseDetail-introduction](3-3-BaseDetail-introduction.md), copy the corresponding function
|
||||
- Step 4:Write detail page-details Tab code
|
||||
- Refer to [3-4-BaseDetailInfo-introduction](3-4-BaseDetailInfo-introduction.md), copy the corresponding function
|
||||
- Step 5: Configure routing
|
||||
- Refer to [3-13-Route-introduction](3-13-Route-introduction.md)
|
||||
- In the `routes/index.js` file of the parent directory in step 1, configure routing
|
||||
- If it is a brand new module, you also need to import it in `src/pages/storage/routes/index.js`
|
||||
- Step 6: Configure menu
|
||||
- Refer to [3-12-Menu-introduction](3-12-Menu-introduction.md)
|
||||
- Configure the menu items of the console, which are configured in `src/layouts/menu.jsx`
|
||||
- Configure the menu items of the management platform, configured in `src/layouts/admin-menu.jsx`
|
||||
- Step 7: i18n
|
||||
- Refer to [3-14-I18n-introduction](3-14-I18n-introduction.md), Complete the corresponding translation
|
||||
|
||||
# Develop a new operation
|
||||
|
||||
## Develop a page-level operation
|
||||
|
||||
- Step 1: Confirm the code location and directory structure
|
||||
- Place it under Containers according to the expected position in the menu item
|
||||
- Take the instance as an example, the corresponding menu item is `Storage-Volume-Create Volume`, then create the folder `src/pages/storage/containers/Volume/actions/Create/index.jsx`
|
||||
- Step 2: Write the Store code
|
||||
- Refer to [3-5-BaseStore-introduction](3-5-BaseStore-introduction.md), Copy or add the corresponding function
|
||||
- Step 3: Write the FormAction code
|
||||
- Refer to [3-6-FormAction-introduction](3-6-FormAction-introduction.md), copy the corresponding function
|
||||
- Step 4: Configure Action
|
||||
- Refer to [3-11-Action-introduction](3-11-Action-introduction.md), Configure to the corresponding position
|
||||
- Step 5: Configure routing
|
||||
- Refer to [3-13-Route-introduction](3-13-Route-introduction.md), Configure the corresponding route
|
||||
- Step 6: Configure the menu
|
||||
- Refer to [3-12-Menu-introduction](3-12-Menu-introduction.md)
|
||||
- Configure the menu items of the console, which are configured in `src/layouts/menu.jsx`
|
||||
- Configure the menu items of the management platform, configured in `src/layouts/admin-menu.jsx`
|
||||
- Step 7: i18n
|
||||
- Refer to [3-14-I18n-introduction](3-14-I18n-introduction.md),Complete the corresponding translation
|
||||
|
||||
## Develop a confirmation operation
|
||||
|
||||
- Step 1: Confirm the code location and directory structure
|
||||
- Place it under Containers according to the expected position in the menu item
|
||||
- Take the instance as an example, the corresponding menu item is `Storage-Volume-Delete Volume`, then create the folder `src/pages/storage/containers/Volume/actions/Delete.jsx`
|
||||
- Step 2: Write the Store code
|
||||
- Refer to [3-5-BaseStore-introduction](3-5-BaseStore-introduction.md), Copy or add the corresponding function
|
||||
- Step 3: Write ConfirmAction code
|
||||
- Refer to [3-8-ConfirmAction-introduction](3-8-ConfirmAction-introduction.md),copy the corresponding function
|
||||
- Step 4: Configure Action
|
||||
- Refer to [3-11-Action-introduction](3-11-Action-introduction.md), Configure to the corresponding position
|
||||
- Step 5: i18n
|
||||
- Refer to [3-14-I18n-introduction](3-14-I18n-introduction.md),Complete the corresponding translation
|
||||
|
||||
## Develop a pop-up operation
|
||||
|
||||
- Step 1: Confirm the code location and directory structure
|
||||
- Place it under Containers according to the expected position in the menu item
|
||||
- Take the instance as an example, the corresponding menu item is `Storage-Volume-Edit Volume`, then create the folder `src/pages/storage/containers/Volume/actions/Edit.jsx`
|
||||
- Step 2: Write the Store code
|
||||
- Refer to [3-5-BaseStore-introduction](3-5-BaseStore-introduction.md), Copy or add the corresponding function
|
||||
- Step 3: Write ModalAction code
|
||||
- Refer to [3-7-ModalAction-introduction](3-7-ModalAction-introduction.md),copy the corresponding function
|
||||
- Step 4: Configure Action
|
||||
- Refer to [3-11-Action-introduction](3-11-Action-introduction.md), Configure to the corresponding position
|
||||
- Step 5: i18n
|
||||
- Refer to [3-14-I18n-introduction](3-14-I18n-introduction.md),Complete the corresponding translation
|
||||
|
||||
## Develop a step-by-step page-level operation
|
||||
|
||||
- Step 1: Confirm the code location and directory structure
|
||||
- Place it under Containers according to the expected position in the menu item
|
||||
- Take the instance as an example, the corresponding menu item is `Compute-Instance-Create Instance`, then create the folder `src/pages/compute/containers/Instance/actions/StepCreate/index.jsx`
|
||||
- Step 2: Write the Store code
|
||||
- Refer to [3-5-BaseStore-introduction](3-5-BaseStore-introduction.md), Copy or add the corresponding function
|
||||
- Step 3: Write StepAction code
|
||||
- Refer to [3-9-StepAction-introduction](3-9-StepAction-introduction.md),copy the corresponding function
|
||||
- Step 4: Configure Action
|
||||
- Refer to [3-11-Action-introduction](3-11-Action-introduction.md), Configure to the corresponding position
|
||||
- Step 5: Configure routing
|
||||
- Refer to [3-13-Route-introduction](3-13-Route-introduction.md), Configure the corresponding route
|
||||
- Step 6: Configure the menu
|
||||
- Refer to [3-12-Menu-introduction](3-12-Menu-introduction.md)
|
||||
- Configure the menu items of the console, which are configured in `src/layouts/menu.jsx`
|
||||
- Configure the menu items of the management platform, configured in `src/layouts/admin-menu.jsx`
|
||||
- Step 7: i18n
|
||||
- Refer to [3-14-I18n-introduction](3-14-I18n-introduction.md),Complete the corresponding translation
|
563
docs/en/develop/3-1-BaseList-introduction.md
Normal file
@ -0,0 +1,563 @@
|
||||
English | [Chinese](/docs/zh/develop/3-1-BaseList-introduction.md)
|
||||
|
||||
# Application
|
||||
|
||||
- The base class of each resource list page
|
||||
|
||||
![List page](/docs/en/develop/images/list/volumes.png)
|
||||
|
||||
- Support data paging
|
||||
|
||||
![List page pagination](/docs/en/develop/images/list/pagination.png)
|
||||
|
||||
- Support search
|
||||
|
||||
![List page search](/docs/en/develop/images/list/search.png)
|
||||
|
||||
- Support manual refresh of data
|
||||
|
||||
![List page fresh](/docs/en/develop/images/list/fresh.png)
|
||||
|
||||
- Support data download
|
||||
|
||||
![List page download](/docs/en/develop/images/list/download.png)
|
||||
|
||||
- Support batch operation
|
||||
|
||||
![List page batch](/docs/en/develop/images/list/batch.png)
|
||||
|
||||
- With automatic data refresh function (automatically refresh the list data every 60 seconds, if the user does not operate, no automatic refresh after 30 minutes, the automatic refresh function can be paused)
|
||||
|
||||
![List page auto-refresh](/docs/en/develop/images/list/stop-auto-refresh.png)
|
||||
|
||||
- Configurable list header
|
||||
|
||||
![List page table columns hide/show](/docs/en/develop/images/list/hide.png)
|
||||
|
||||
- Each resource list page can be completed by copy function
|
||||
|
||||
# BaseList code file
|
||||
|
||||
- `src/containers/List/index.jsx`
|
||||
|
||||
# BaseList Introduction to properties and function definitions
|
||||
|
||||
- The resource list inherits from the BaseList component
|
||||
- Only need to copy some functions to complete the development of the page
|
||||
- Properties and functions are divided into the following four types,
|
||||
- The poprs and functions that usually need to be overridden mainly include:
|
||||
- Page permissions
|
||||
- Resource name of the page
|
||||
- The configuration of the columns of the table
|
||||
- Search term for table
|
||||
- Operation items of the table, etc.
|
||||
- `store` corresponding to the table
|
||||
- Functions and properties for on-demand overridden, mainly include:
|
||||
- Resource data paging uses front-end paging or back-end paging
|
||||
- Resource data sorting uses front-end sorting or back-end sorting
|
||||
- Functions and properties that do not need to be overridden, mainly include:
|
||||
- Whether the current page is a management platform page
|
||||
- Whether the current page is the resource list in the details page
|
||||
- The basic functions in the base class mainly include:
|
||||
- Render the page
|
||||
- Handling download
|
||||
- Handling automatic refresh
|
||||
- Hide/show some table columns
|
||||
- Handling search
|
||||
- Handling data request and display after the change of pagination information
|
||||
- See below for a more detailed and comprehensive introduction
|
||||
|
||||
## Properties and functions that usually need to be overridden
|
||||
|
||||
- `policy`:
|
||||
- The function must be overridden
|
||||
- The permission corresponding to the page, if the permission verification fails, data cannot be requested.
|
||||
- Take the volume `src/pages/storage/containers/Volume/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get policy() {
|
||||
return 'volume:get_all';
|
||||
}
|
||||
```
|
||||
|
||||
- `name`
|
||||
- The function must be overridden
|
||||
- The name corresponding to the page resource.
|
||||
- Take the volume `src/pages/storage/containers/Volume/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get name() {
|
||||
return t('volumes');
|
||||
}
|
||||
```
|
||||
|
||||
- `actionConfigs`
|
||||
- Various operations to configure resources
|
||||
- Main button operations, such as: create
|
||||
- Batch operation
|
||||
- Operation of each row of data
|
||||
- The configuration is defined in the actions directory of the resource
|
||||
- Take the keypair `src/pages/compute/containers/Keypair/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
import actionConfigs from './actions';
|
||||
get actionConfigs() {
|
||||
return actionConfigs;
|
||||
}
|
||||
```
|
||||
|
||||
- `searchFilters`
|
||||
- Configure search terms for resources
|
||||
- Support string-based search
|
||||
- Support selected search, such as: state-based search
|
||||
- Support multiple search conditions that need to be met
|
||||
- Returns an array of configurations, each configuration represents a search condition
|
||||
- Each configuration needs to meet the following conditions:
|
||||
- `label`, Required item, search title
|
||||
- `name`, Required item, the parameter `Key` corresponding to the search item
|
||||
- `options`, Optional
|
||||
- If the `options` attribute is not set, it means that the search is based on the input string, such as: search for names
|
||||
- If you set the `options` property, you need to select from `options` in the page
|
||||
- The format of `options`:
|
||||
- `key`: required item, the value corresponding to `option`
|
||||
- `label`: required item, the text corresponding to `option`, which is the content seen on the page
|
||||
- Take the volume `src/pages/storage/containers/Volume/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get searchFilters() {
|
||||
return [
|
||||
{
|
||||
label: t('Name'),
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
label: t('Status'),
|
||||
name: 'status',
|
||||
options: ['available', 'in-use', 'error'].map((it) => ({
|
||||
key: it,
|
||||
label: volumeStatus[it],
|
||||
})),
|
||||
},
|
||||
{
|
||||
label: t('Shared'),
|
||||
name: 'multiattach',
|
||||
options: yesNoOptions,
|
||||
},];
|
||||
}
|
||||
```
|
||||
|
||||
- `getColumns`
|
||||
- Back to the configuration information list of the list table
|
||||
- The settings of each configuration item:
|
||||
- `title`, Required item, the title of the header
|
||||
- `dataIndex`, Required item, the key value of the corresponding back-end data
|
||||
- `hidden`, Optional, whether the column can be hidden, the default value is `false`
|
||||
- `sorter`, Whether the column can be sorted, it can be sorted by default
|
||||
- `stringify`, Optional. When downloading to `csv`, the content displayed in the data in this column, because some columns have additional styles or UI processing, which will cause problems with the result of the string conversion of this column, you need to write at this time The function
|
||||
- `render`, Optional, the default is to display the content based on `dataIndex`, using this attribute, the table content can be rendered based on the result of `render`
|
||||
- `valueRender`, Optional, use existing functions to automatically process data
|
||||
- `sinceTime`, Processing time, displayed as "XX hours ago"
|
||||
- `keepTime`, To display the remaining time
|
||||
- `yesNo`, Process the `Boolean` value and display it as "Yes" or "No"
|
||||
- `GBValue`, Processing size, displayed as "XXXGB"
|
||||
- `noValue`, When there is no value, it is displayed as "-"
|
||||
- `bytes`, Processing size
|
||||
- `uppercase`, capital
|
||||
- `formatSize`, Processing size, such as "2.32 GB", "56.68 MB"
|
||||
- `toLocalTime`, Processing time, such as "2021-06-17 04:13:07"
|
||||
- `toLocalTimeMoment`, Processing time, such as "2021-06-17 04:13:07"
|
||||
- `linkPrefix`, Optional, when `dataIndex=name`, the `linkPrefix` attribute is used to process the prefix of the link corresponding to the name
|
||||
-Take the mirror `src/pages/compute/containers/Image/Image.jsx` as an example
|
||||
- The table contains columns: ID/name, project ID/name (displayed in the management platform), description, usage type, type, status, visibility, hard disk format, capacity, created in
|
||||
|
||||
```javascript
|
||||
getColumns = () => [
|
||||
{
|
||||
title: t('ID/Name'),
|
||||
dataIndex: 'name',
|
||||
linkPrefix: `/compute/${this.getUrl('image')}/detail`,
|
||||
},
|
||||
{
|
||||
title: t('Project ID/Name'),
|
||||
dataIndex: 'project_name',
|
||||
hidden: !this.isAdminPage && this.tab !== 'all',
|
||||
sorter: false,
|
||||
},
|
||||
{
|
||||
title: t('Description'),
|
||||
dataIndex: 'description',
|
||||
isHideable: true,
|
||||
sorter: false,
|
||||
},
|
||||
{
|
||||
title: t('Use Type'),
|
||||
dataIndex: 'usage_type',
|
||||
isHideable: true,
|
||||
render: (value) => imageUsage[value] || '-',
|
||||
sorter: false,
|
||||
},
|
||||
{
|
||||
title: t('Type'),
|
||||
dataIndex: 'os_distro',
|
||||
isHideable: true,
|
||||
render: (value) => <ImageType type={value} title={value} />,
|
||||
width: 80,
|
||||
sorter: false,
|
||||
},
|
||||
{
|
||||
title: t('Status'),
|
||||
dataIndex: 'status',
|
||||
render: (value) => imageStatus[value] || '-',
|
||||
},
|
||||
{
|
||||
title: t('Visibility'),
|
||||
dataIndex: 'visibility',
|
||||
render: (value) => imageVisibility[value] || '-',
|
||||
sorter: false,
|
||||
},
|
||||
{
|
||||
title: t('Disk Format'),
|
||||
dataIndex: 'disk_format',
|
||||
isHideable: true,
|
||||
render: (value) => imageFormats[value] || '-',
|
||||
},
|
||||
{
|
||||
title: t('Size'),
|
||||
dataIndex: 'size',
|
||||
isHideable: true,
|
||||
valueRender: 'formatSize',
|
||||
},
|
||||
{
|
||||
title: t('Created At'),
|
||||
dataIndex: 'created_at',
|
||||
isHideable: true,
|
||||
valueRender: 'sinceTime',
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
- `init`
|
||||
- The function to configure the Store. In this function, the Store used to process data requests and the Store used to download data are configured
|
||||
- Usually a singleton Store is used, but for the list page under some detail pages, use `new XXXStore()`
|
||||
- `this.store` and `this.downloadStore` can be configured in `init`
|
||||
- `this.store` is used to process list data
|
||||
- `this.downloadStore` is used to process download data
|
||||
- If you use the front-end page, only configure `this.store`, because all the data is obtained at once, and the downloaded data is equal to the data in the list, that is, at this time, `this.downloadStore = this.store`
|
||||
- Take the project `src/pages/identity/containers/Project/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
init() {
|
||||
this.store = globalProjectStore;
|
||||
}
|
||||
```
|
||||
|
||||
- If you use back-end paging, you need to configure `this.store` and `this.downloadStore` separately
|
||||
- Take the router `src/pages/network/containers/Router/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
init() {
|
||||
this.store = new RouterStore();
|
||||
this.downloadStore = new RouterStore();
|
||||
}
|
||||
```
|
||||
|
||||
## Properties and functions for on-demand overridden
|
||||
|
||||
- `alsoRefreshDetail`
|
||||
- When the list data in the detail page is refreshed, do you need to refresh the detail data synchronously?
|
||||
- Default synchronous refresh, if you don't need to refresh synchronously, override this function
|
||||
|
||||
```javascript
|
||||
get alsoRefreshDetail() {
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
- `list`
|
||||
- Data in the store of the page object
|
||||
- The default value is `this.store.list`
|
||||
- `rowKey`
|
||||
- Key for unique identification of list data
|
||||
- The default value is `id`
|
||||
- Take the key Keypair `src/pages/compute/containers/Keypair/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get rowKey() {
|
||||
return 'name';
|
||||
}
|
||||
```
|
||||
|
||||
- `hasTab`
|
||||
- Whether the list page is the list page under Tab
|
||||
- The default value is `false`
|
||||
- The height of the table will be adjusted according to the changed value
|
||||
- Take `src/pages/configuration/containers/SystemInfo/Catalog.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get hasTab() {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
![List page Tab](/docs/en/develop/images/list/tab-service.png)
|
||||
|
||||
- `hideCustom`
|
||||
- Whether to display the header configuration icon
|
||||
- The default value is `true`
|
||||
- Take `src/pages/configuration/containers/Setting/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get hideCustom() {
|
||||
return 'name';
|
||||
}
|
||||
```
|
||||
|
||||
- `hideSearch`
|
||||
- Whether to show the search box
|
||||
- Default Display
|
||||
- Take resource arrangement-stack-detail page-log `src/pages/heat/containers/Stack/Detail/Event.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get hideSearch() {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
- `hideRefresh`
|
||||
- Whether to show the automatic refresh button
|
||||
- Default Display
|
||||
- If not displayed, the list does not have the function of automatically refreshing data
|
||||
- `hideDownload`
|
||||
- Whether to show the download button
|
||||
- Default Display
|
||||
- `checkEndpoint`
|
||||
- Do you need to detect endpoints
|
||||
- Not required by default
|
||||
- Some services may not be deployed and require secondary verification. Once the test is not deployed, the "not open" style page will be displayed
|
||||
- Take VPN `src/pages/network/containers/VPN/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get checkEndpoint() {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
- `endpoint`
|
||||
- Used when `checkEndpoint` is `true`
|
||||
- Take VPN`src/pages/network/containers/VPN/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get endpoint() {
|
||||
return vpnEndpoint();
|
||||
}
|
||||
```
|
||||
|
||||
- `isFilterByBackend`
|
||||
- Whether to page by the backend
|
||||
- The default value is `false`, that is, using front-end paging
|
||||
- When using front-end paging, all data is obtained from the back-end at one time, and then the data is displayed according to the page number and the number of single pages in the page
|
||||
- When using back-end paging, request the corresponding amount of data from the back-end in the number of pages and single pages
|
||||
- Take the router `src/pages/network/containers/Router/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get isFilterByBackend() {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
- `isSortByBackend`
|
||||
- Whether to be sorted by the backend
|
||||
- The default value is `false`, that is, using front-end sorting
|
||||
- When using front-end sorting, sort based on the size of the data in the list (customizable sorting function)
|
||||
- If you use front-end paging + front-end sorting, you can sort based on all data
|
||||
- If you use back-end paging + front-end sorting, you can only sort data based on the current page
|
||||
- When using back-end paging, request data from the back-end according to the sort item and sort direction set in the list
|
||||
- Take the router `src/pages/network/containers/Router/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get isSortByBackend() {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
- When `isSortByBackend` is set to `true`, it is usually necessary to rewrite the `updateParamsSortPage` function in the corresponding `store`
|
||||
- Take `src/stores/neutron/router.js` as an example
|
||||
|
||||
```javascript
|
||||
updateParamsSortPage = (params, sortKey, sortOrder) => {
|
||||
if (sortKey && sortOrder) {
|
||||
params.sort_key = sortKey;
|
||||
params.sort_dir = sortOrder === 'descend' ? 'desc' : 'asc';
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
- `adminPageHasProjectFilter`
|
||||
- Does the search item of the management platform contain the search based on the project ID?
|
||||
- The default value is `false`
|
||||
- Take the instance `src/pages/compute/containers/Instance/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get adminPageHasProjectFilter() {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
- `transitionStatusList`
|
||||
- The corresponding state value list when the data is in the transition state
|
||||
- The default value is an empty list of `[]`
|
||||
- When the data is in a transitional state, the automatic refresh of the page will speed up and become once every 30 seconds
|
||||
- The default value is `false`
|
||||
- Take the volume `src/pages/storage/containers/Volume/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
const volumeTransitionStatuses = [
|
||||
'creating',
|
||||
'extending',
|
||||
'downloading',
|
||||
'attaching',
|
||||
'detaching',
|
||||
'deleting',
|
||||
'backing-up',
|
||||
'restoring-backup',
|
||||
'awaiting-transfer',
|
||||
'uploading',
|
||||
'rollbacking',
|
||||
'retyping',
|
||||
];
|
||||
get transitionStatusList() {
|
||||
return volumeTransitionStatuses;
|
||||
}
|
||||
```
|
||||
|
||||
- `fetchDataByAllProjects`
|
||||
- When the management platform requests data, whether it is with the `all_projects` parameter
|
||||
- The default value is `true`
|
||||
- Take the volume type `src/pages/storage/containers/VolumeType/VolumeType/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get fetchDataByAllProjects() {
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
- `fetchDataByCurrentProject`
|
||||
- Whether to include the `project_id` parameter when the console requests data
|
||||
- The default value is `false`
|
||||
- Take floating ip `src/pages/network/containers/FloatingIp/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get fetchDataByCurrentProject() {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
- `defaultSortKey`
|
||||
- When using backend sorting, the default sort Key
|
||||
- Take the router `src/pages/network/containers/Router/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get defaultSortKey() {
|
||||
return 'status';
|
||||
}
|
||||
```
|
||||
|
||||
- `clearListUnmount`
|
||||
- When the page is switched, do you need the list data in the current store?
|
||||
- Generally speaking, the resource list page uses `GlobalXXStore`, which is a singleton store. When the page is switched, the list data will not be cleared. When returning to the page, the previous data will be displayed first, and then the page will automatically refresh to obtain the new data
|
||||
- The default value is `false`, The data is not cleared when the page is switched
|
||||
- `ableAutoFresh`
|
||||
- Whether to refresh automatically
|
||||
- The default value is `true`
|
||||
- `projectFilterKey`
|
||||
- When requested, the key value corresponding to the project
|
||||
- The default value is `project_id`
|
||||
- Take the image `src/pages/compute/containers/Image/Image.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get projectFilterKey() {
|
||||
return 'owner';
|
||||
}
|
||||
```
|
||||
|
||||
- `getCheckboxProps`
|
||||
- Whether the data in the list can be selected, and batch operations can be performed after selection
|
||||
- Both can be selected by default
|
||||
- Take the instance `src/pages/compute/containers/Instance/index.jsx` as an example
|
||||
- Bare metal instances cannot be selected
|
||||
|
||||
```javascript
|
||||
getCheckboxProps(record) {
|
||||
return {
|
||||
disabled: isIronicInstance(record),
|
||||
name: record.name,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- `getData`
|
||||
- Functions for processing data requests
|
||||
- By default, use the `store.fetchList` or `store.fetchListByPage` method to get data from the server
|
||||
- It is not recommended to copy this function
|
||||
- `fetchDataByPage`
|
||||
- When using back-end paging, the function to process data requests
|
||||
- Use the `store.fetchListByPage` method to fetch data by default
|
||||
- It is not recommended to copy this function
|
||||
- `fetchData`
|
||||
- When using front-end paging, the function to process data requests
|
||||
- Use the `store.fetchList` method to get data by default
|
||||
- It is not recommended to copy this function
|
||||
- `updateFetchParamsByPage`
|
||||
- When using back-end paging, a function to adjust request parameters based on the base class
|
||||
- If the default parameters of the base class cannot meet the request, it is recommended to copy the function and synchronously modify the `listDidFetch` method in the corresponding `store` to complete the data request
|
||||
- `updateFetchParams`
|
||||
- When using front-end paging, the function to adjust request parameters based on the base class
|
||||
- If the default parameters of the base class cannot meet the request, it is recommended to copy the function and synchronously modify the `listDidFetch` method in the corresponding `store` to complete the data request
|
||||
- `updateHints`
|
||||
- Tips on the form
|
||||
|
||||
## Properties and functions that do not need to be overridden
|
||||
|
||||
- `isInDetailPage`
|
||||
- Identifies whether the current page is a list page under the details page
|
||||
- `location`
|
||||
- Page routing information
|
||||
- `isAdminPage`
|
||||
- Is the current page a "management platform" page
|
||||
- `hasAdminRole`
|
||||
- Whether the logged-in user role has an administrator role
|
||||
- `getUrl`
|
||||
- Function to generate page URL
|
||||
- For example, it is necessary to provide a jump function to the associated resources of the list page. Using this function, you can jump to the corresponding address of the console in the console, and jump to the corresponding address of the management platform in the management platform.
|
||||
- `params`
|
||||
- Parameter information carried by the route
|
||||
- Generally used to generate the parameters of the page request API
|
||||
- `routing`
|
||||
- Routing information corresponding to the page
|
||||
- `isLoading`
|
||||
- Whether the current page is updating data, the loading style will be displayed when updating
|
||||
- `endpointError`
|
||||
- Determine whether Endpoint is valid
|
||||
- `hintHeight`
|
||||
- The height of the prompt in the page
|
||||
- `tableTopHeight`
|
||||
- The height occupied above the table
|
||||
- Based on prompt, Tab calculation
|
||||
- `tableHeight`
|
||||
- Table height
|
||||
- `currentProjectId`
|
||||
- Project ID to which the currently logged-in user belongs
|
||||
- `defaultSortOrder`
|
||||
- When using backend sorting, the default sorting direction is descending `descend`
|
||||
- `itemInTransitionFunction`
|
||||
- Determine whether there is data in the transition state, if there is data in the transition state, the time interval for automatically refreshing the data is changed from 60 seconds to 30 seconds
|
||||
- `primaryActions`
|
||||
- Main button operation list
|
||||
- `batchActions`
|
||||
- Batch operation list
|
||||
- `itemActions`
|
||||
- List of operations corresponding to each row of data
|
||||
|
||||
## Basic functions in the base class
|
||||
|
||||
- It is recommended to check the code understanding, `src/containers/List/index.jsx`
|
123
docs/en/develop/3-2-BaseTabList-introduction.md
Normal file
@ -0,0 +1,123 @@
|
||||
English | [Chinese](/docs/zh/develop/3-2-BaseTabList-introduction.md)
|
||||
|
||||
# Application
|
||||
|
||||
- The base class of each switchable list page
|
||||
|
||||
![Tab list page](/docs/en/develop/images/list/tab-list.png)
|
||||
|
||||
- Support automatic processing of data display when switching
|
||||
|
||||
# BaseTabList Code file
|
||||
|
||||
- `src/containers/TabList/index.jsx`
|
||||
|
||||
# BaseTabList Introduction to attribute and function definitions
|
||||
|
||||
- The resource list with Tab switch inherits from BaseTabList
|
||||
- Only need to copy some functions to complete the development of the page
|
||||
- Attributes and functions are divided into the following four types,
|
||||
- The attributes and functions that need to be overridden mainly include:
|
||||
- `Tab` configuration in the page
|
||||
- Functions and attributes for on-demand overridden, mainly include:
|
||||
- Permission configuration in the page
|
||||
- Functions and attributes that do not need to be overridden, mainly include:
|
||||
- Whether the current page is a management platform page
|
||||
- The basic functions in the base class mainly include:
|
||||
- Render the page
|
||||
- Handle routing changes when switching tabs
|
||||
- See below for a more detailed and comprehensive introduction
|
||||
|
||||
## Properties and functions that need to be overridden
|
||||
|
||||
- `tabs`:
|
||||
- Need to replicate the function
|
||||
- Used to configure the tab in the page
|
||||
- Configuration items of each Tab:
|
||||
- `title`, the title on the Tab tag
|
||||
- `key`, the unique identifier of each Tab
|
||||
- `component`, the component corresponding to each Tab is basically a resource list component inherited from `BaseList`
|
||||
- Return to the list of Tab configuration
|
||||
- The page displays the first `component` in the Tab list by default
|
||||
- Take image `src/pages/compute/containers/Image/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get tabs() {
|
||||
const tabs = [
|
||||
{
|
||||
title: t('Current Project Image'),
|
||||
key: 'project',
|
||||
component: Image,
|
||||
},
|
||||
{
|
||||
title: t('Public Image'),
|
||||
key: 'public',
|
||||
component: Image,
|
||||
},
|
||||
{
|
||||
title: t('Shared Image'),
|
||||
key: 'shared',
|
||||
component: Image,
|
||||
},
|
||||
];
|
||||
if (this.hasAdminRole) {
|
||||
tabs.push({
|
||||
title: t('All Image'),
|
||||
key: 'all',
|
||||
component: Image,
|
||||
});
|
||||
}
|
||||
return tabs;
|
||||
}
|
||||
```
|
||||
|
||||
## Properties and functions for on-demand overridden
|
||||
|
||||
- The attributes and functions involved in the following generally do not need to be configured
|
||||
- Currently it is only used on the VPN page (`src/pages/network/containers/VPN/index.jsx`). This page uses these configurations to determine permissions and displays when the determination fails.
|
||||
- `name`
|
||||
- The full name of the entire Tab page
|
||||
- Take the vpn `src/pages/network/containers/VPN/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get name() {
|
||||
return t('VPN');
|
||||
}
|
||||
```
|
||||
|
||||
- `checkEndpoint`
|
||||
- Do you need to verify the endpoint of the service corresponding to the page
|
||||
- The default value is `false`
|
||||
- Take the vpn `src/pages/network/containers/VPN/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get checkEndpoint() {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
- `endpoint`
|
||||
- The endpoint of the service corresponding to this page
|
||||
- Only useful when `checkEndpoint=true`
|
||||
- Take the vpn `src/pages/network/containers/VPN/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get endpoint() {
|
||||
return vpnEndpoint();
|
||||
}
|
||||
```
|
||||
|
||||
## Properties and functions that do not need to be overridden
|
||||
- `location`
|
||||
- Page routing information
|
||||
- `isAdminPage`
|
||||
- Is the current page a "management platform" page
|
||||
- `hasAdminRole`
|
||||
- Whether the logged-in user role has an administrator role
|
||||
- `getUrl`
|
||||
- Function to generate page URL
|
||||
- For example, it is necessary to provide a jump function for the associated resources of the list page. Using this function, you can jump to the corresponding address of the console in the console, and jump to the corresponding address of the management platform in the management platform.
|
||||
|
||||
## Basic functions in the base class
|
||||
|
||||
- It is recommended to check the code understanding, `src/containers/TabList/index.jsx`
|
259
docs/en/develop/3-3-BaseDetail-introduction.md
Normal file
@ -0,0 +1,259 @@
|
||||
English | [Chinese](/docs/zh/develop/3-3-BaseDetail-introduction.md)
|
||||
|
||||
# Application
|
||||
|
||||
![Details page](/docs/en/develop/images/detail/volume.png)
|
||||
|
||||
- The base class of each resource detail page
|
||||
- Support return to list page
|
||||
- Support data operations consistent with the list page
|
||||
- Support the display and folding of the header of the detail page
|
||||
- Support basic information and related resource information displayed in tab form
|
||||
- Support up and down display schemes
|
||||
- Need to copy some functions to complete the development of the page
|
||||
|
||||
# BaseDetail Code file
|
||||
|
||||
- `src/containers/TabDetail/index.jsx`
|
||||
|
||||
# BaseDetail Introduction to attribute and function definitions
|
||||
|
||||
- Resource details are inherited from BaseDetail component
|
||||
- Code location: `pages/xxxx/containers/XXXX/Detail/index.jsx`
|
||||
- Need to copy some functions to complete the development of the page
|
||||
- Attributes and functions are divided into the following four types,
|
||||
- The attributes and functions that usually need to be overridden mainly include:
|
||||
- Details page permissions
|
||||
- Resource name of the detail page
|
||||
- List page corresponding to the detail page
|
||||
- Operation configuration of the detail page
|
||||
- Information configuration at the top of the detail page
|
||||
- Tab page configuration at the bottom of the detail page
|
||||
- The `store` corresponding to the details page
|
||||
- Functions and attributes for on-demand overridden, mainly include:
|
||||
- Data corresponding to details page operations
|
||||
- Parameters for obtaining detailed data
|
||||
- Function to get detailed data
|
||||
- Functions and attributes that do not need to be overridden, mainly include:
|
||||
- Whether the current page is a management platform page
|
||||
- The basic functions in the base class mainly include:
|
||||
- Render the page
|
||||
- Automatic refresh of detailed data when the data on the list page below changes
|
||||
- Collapse/expand header information
|
||||
- See below for a more detailed and comprehensive introduction
|
||||
|
||||
## Properties and functions that usually need to be overridden
|
||||
|
||||
- `policy`:
|
||||
- The function must be overridden
|
||||
- The permission corresponding to the page, if the permission verification fails, data cannot be requested.
|
||||
- Take the volume `src/pages/storage/containers/Volume/Detail/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get policy() {
|
||||
return 'volume:get';
|
||||
}
|
||||
```
|
||||
|
||||
- `name`
|
||||
- The function must be overridden
|
||||
- The name corresponding to the page resource.
|
||||
- Take the volume `src/pages/storage/containers/Volume/Detail/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get name() {
|
||||
return t('volume');
|
||||
}
|
||||
```
|
||||
|
||||
- `listUrl`
|
||||
- The resource list page corresponding to the detail page
|
||||
- Take the volume `src/pages/storage/containers/Volume/Detail/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get listUrl() {
|
||||
return this.getUrl('/storage/volume');
|
||||
}
|
||||
```
|
||||
|
||||
- `actionConfigs`
|
||||
- Various operations to configure resources
|
||||
- Operations on data
|
||||
- The configuration is defined in the actions directory of the resource
|
||||
- Generally, you can directly use the configuration consistent with the resource list page
|
||||
- Take the keypair `src/pages/compute/containers/Keypair/Detail/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
import actionConfigs from '../actions';
|
||||
get actionConfigs() {
|
||||
return actionConfigs;
|
||||
}
|
||||
```
|
||||
|
||||
- `detailInfos`
|
||||
- Information at the top of the details page
|
||||
- Is a configuration list
|
||||
- Per configuration
|
||||
- `title`, required item, title
|
||||
- `dataIndex`, required item, corresponding to the Key of the data
|
||||
- `render`, optional, the default is to display content based on `dataIndex`, using this attribute, table content can be rendered based on the result of `render`
|
||||
- `valueRender`, optional, generate show data based on `dataIndex` and `valueRender`
|
||||
- `sinceTime`, processing time, showed as "XX hours ago"
|
||||
- `keepTime`, show the remaining time
|
||||
- `yesNo`, handle the `Boolean` value and display it as "yes" or "no"
|
||||
- `GBValue`, processing size, displayed as "XXXGB"
|
||||
- `noValue`, when there is no value, it is displayed as "-"
|
||||
- `bytes`, processing size
|
||||
- `uppercase`, uppercase
|
||||
- `formatSize`, processing size, such as "2.32 GB", "56.68 MB"
|
||||
- `toLocalTime`, processing time, shown as "2021-06-17 04:13:07"
|
||||
- `toLocalTimeMoment`, processing time, shown as "2021-06-17 04:13:07"
|
||||
- Take the volume `src/pages/storage/containers/Volume/Detail/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get detailInfos() {
|
||||
return [
|
||||
{
|
||||
title: t('Name'),
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: t('Description'),
|
||||
dataIndex: 'description',
|
||||
},
|
||||
{
|
||||
title: t('Shared'),
|
||||
dataIndex: 'multiattach',
|
||||
valueRender: 'yesNo',
|
||||
},
|
||||
{
|
||||
title: t('Status'),
|
||||
dataIndex: 'status',
|
||||
render: (value) => volumeStatus[value] || '-',
|
||||
},
|
||||
{
|
||||
title: t('Size'),
|
||||
dataIndex: 'size',
|
||||
},
|
||||
{
|
||||
title: t('Created At'),
|
||||
dataIndex: 'created_at',
|
||||
valueRender: 'toLocalTime',
|
||||
},
|
||||
{
|
||||
title: t('Type'),
|
||||
dataIndex: 'volume_type',
|
||||
},
|
||||
{
|
||||
title: t('Encrypted'),
|
||||
dataIndex: 'encrypted',
|
||||
valueRender: 'yesNo',
|
||||
},
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
- `tabs`
|
||||
- Tab configuration at the bottom of the details page
|
||||
- Configuration items of each Tab:
|
||||
- `title`, the title on the Tab tag
|
||||
- `key`, the unique identifier of each Tab
|
||||
- `component`, the component corresponding to each Tab is basically a resource list component inherited from `BaseList`
|
||||
- Return to the list of Tab configuration
|
||||
- The page displays the first `component` in the Tab list by default
|
||||
- Usually, the basic information is inherited from the `BaseDetail` class
|
||||
- Usually, the resource list page in the detail page can directly reuse the resource list, and you only need to synchronize the parameter request in the next list page.
|
||||
- Take the backup list of volume details `src/pages/storage/containers/Backup/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
updateFetchParamsByPage = (params) => {
|
||||
if (this.isInDetailPage) {
|
||||
const { id, ...rest } = params;
|
||||
return {
|
||||
volume_id: id,
|
||||
...rest,
|
||||
};
|
||||
}
|
||||
return params;
|
||||
};
|
||||
```
|
||||
|
||||
- Take the volume `src/pages/storage/containers/Volume/Detail/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get tabs() {
|
||||
const tabs = [
|
||||
{
|
||||
title: t('Detail'),
|
||||
key: 'base',
|
||||
component: BaseDetail,
|
||||
},
|
||||
{
|
||||
title: t('Backup'),
|
||||
key: 'backup',
|
||||
component: Backup,
|
||||
},
|
||||
{
|
||||
title: t('Snapshot'),
|
||||
key: 'snapshot',
|
||||
component: Snapshot,
|
||||
},
|
||||
];
|
||||
return tabs;
|
||||
}
|
||||
```
|
||||
|
||||
- `init`
|
||||
- The function to configure the Store, in this function to configure the Store used to process data requests
|
||||
- Generally used is the form of `new XXXStore()`
|
||||
- Take the volume `src/pages/storage/containers/Volume/Detail/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
init() {
|
||||
this.store = new VolumeStore();
|
||||
}
|
||||
```
|
||||
|
||||
## Properties and functions for on-demand overridden
|
||||
|
||||
- `fetchData`
|
||||
- Function to get data in the details page
|
||||
- It is not recommended to rewrite this method
|
||||
- Use `this.store.fetchDetail` to get data by default
|
||||
- `updateFetchParams`
|
||||
- Update the parameters of the data request
|
||||
- Generally used with `detailDidFetch` in the store
|
||||
- Take the instance `src/pages/compute/containers/Instance/Detail/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
updateFetchParams = (params) => ({
|
||||
...params,
|
||||
isRecycleBinDetail: this.isRecycleBinDetail,
|
||||
});
|
||||
```
|
||||
|
||||
## Properties and functions that do not need to be overridden
|
||||
|
||||
- `params`
|
||||
- The parameter information of the route
|
||||
- Generally used to generate the parameters of the page request API
|
||||
- `id`
|
||||
- `id` in routing information
|
||||
- `isAdminPage`
|
||||
- Is the current page a "management platform" page
|
||||
- `getUrl`
|
||||
- Function to generate page URL
|
||||
- For example, it is necessary to provide a jump function to the associated resource. Using this function, you can jump to the corresponding address of the console in the console, and jump to the corresponding address of the management platform in the management platform.
|
||||
- `routing`
|
||||
- Routing information corresponding to the page
|
||||
- `isLoading`
|
||||
- Whether the current page is updating data, the loading style will be displayed when updating
|
||||
- `tab`
|
||||
- Currently displayed information on the lower Tab page
|
||||
- `detailData`
|
||||
- Data information displayed on the page
|
||||
- From `this.store.detail`
|
||||
|
||||
## Basic functions in the base class
|
||||
|
||||
- It is recommended to check the code understanding, `src/containers/TabDetail/index.jsx`
|
144
docs/en/develop/3-4-BaseDetailInfo-introduction.md
Normal file
@ -0,0 +1,144 @@
|
||||
English | [Chinese](/docs/zh/develop/3-4-BaseDetailInfo-introduction.md)
|
||||
|
||||
# Application
|
||||
|
||||
![Details page](/docs/en/develop/images/detail/image-detail-info.png)
|
||||
|
||||
- The base class of components in the Details Tab of each resource detail page
|
||||
- Left and right structure display
|
||||
- Display in the form of Card
|
||||
- The display of the page content can be completed by configuring the Card
|
||||
|
||||
# BaseDetailInfo Code file
|
||||
|
||||
- `src/containers/BaseDetail/index.jsx`
|
||||
|
||||
# BaseDetailInfo Introduction to attribute and function definitions
|
||||
|
||||
- Resource details are inherited from BaseDetailInfo
|
||||
- Code location:`pages/xxxx/containers/XXXX/Detail/BaseDetail.jsx`
|
||||
- Only need to copy some functions to complete the development of the page
|
||||
- Attributes and functions are divided into the following four types,
|
||||
- The attributes and functions that usually need to be overridden mainly include:
|
||||
- Card list on the left
|
||||
- Functions and attributes for on-demand overridden, mainly include:
|
||||
- Card list on the right
|
||||
- Function to get data
|
||||
- Source of display data
|
||||
- Functions and attributes that do not need to be overridden, mainly include:
|
||||
- Whether the current page is a management platform page
|
||||
- The basic functions in the base class mainly include:
|
||||
- Render the page
|
||||
- See below for a more detailed and comprehensive introduction
|
||||
|
||||
## Card configuration
|
||||
|
||||
- The Cards on the left and right sides of the page use the same configuration
|
||||
- The configuration of each Card is as follows,
|
||||
- `title`, required item, the title of the Card
|
||||
- `titleHelp`, optional, the prompt message displayed next to the title of the Card
|
||||
- `render`, optional, if it exists, the content of Card will be rendered based on `render`
|
||||
- `options`, options, the configuration list of each line in Card, each option configuration is as follows,
|
||||
- `label`, required item, label in the row
|
||||
- `dataIndex`, a required item, corresponding to the key in `this.detailData`, the default is to display the data in the row based on `dataIndex`
|
||||
- `render`, optional, can render the content in the line based on the result of `render`
|
||||
- `valueRender`, optional, based on `dataIndex` and `valueRender` to generate in-line display data
|
||||
- `sinceTime`, processing time, displayed as "XX hours ago"
|
||||
- `keepTime`, display the remaining time
|
||||
- `yesNo`, handle the `Boolean` value and display it as "yes" or "no"
|
||||
- `GBValue`, processing size, displayed as "XXXGB"
|
||||
- `noValue`, when there is no value, it is displayed as "-"
|
||||
- `bytes`, processing size
|
||||
- `uppercase`, uppercase
|
||||
- `formatSize`, processing size, such as "2.32 GB", "56.68 MB"
|
||||
- `toLocalTime`, processing time, shown as "2021-06-17 04:13:07"
|
||||
- `toLocalTimeMoment`, processing time, shown as "2021-06-17 04:13:07"
|
||||
- `copyable`, optional, whether the data in the row can be overridden, if it can be overridden, the copy icon will be displayed
|
||||
- Take the keypair `src/pages/compute/containers/Keypair/Detail/BaseDetail.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get keypairInfoCard() {
|
||||
const options = [
|
||||
{
|
||||
label: t('Fingerprint'),
|
||||
dataIndex: 'fingerprint',
|
||||
},
|
||||
{
|
||||
label: t('Public Key'),
|
||||
dataIndex: 'public_key',
|
||||
copyable: true,
|
||||
},
|
||||
{
|
||||
label: t('User ID'),
|
||||
dataIndex: 'user_id',
|
||||
},
|
||||
];
|
||||
return {
|
||||
title: t('Keypair Info'),
|
||||
options,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Properties and functions that usually need to be overridden
|
||||
|
||||
- `leftCards`:
|
||||
- The function must be overridden
|
||||
- Card list shown on the left
|
||||
- Take the mirror `src/pages/compute/containers/Image/Detail/BaseDetail.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get leftCards() {
|
||||
const cards = [this.baseInfoCard, this.securityCard];
|
||||
return this.isImageDetail ? cards : [this.InstanceCard, ...cards];
|
||||
}
|
||||
```
|
||||
|
||||
- `init`
|
||||
- Configure the function of the Store, in this function, configure the function used to process the data request
|
||||
Store, if this function is configured, it will initiate a data request when the page is displayed, but sometimes when the page is displayed, no additional request is required, just use `this.props.detail`
|
||||
- Generally used is the form of `new XXXStore()`
|
||||
- Take the mirror `src/pages/compute/containers/Image/Detail/BaseDetail.jsx` as an example
|
||||
|
||||
```javascript
|
||||
init() {
|
||||
this.store = new ImageStore();
|
||||
}
|
||||
```
|
||||
|
||||
## Properties and functions for on-demand overridden
|
||||
|
||||
- `rightCards`
|
||||
- Card list shown on the right
|
||||
- `fetchData`
|
||||
- Function to get Card data
|
||||
- Generally do not need to copy the function
|
||||
- `detailData`
|
||||
- Data source of page Card
|
||||
- The default is `this.props.detail || toJS(this.store.detail)`
|
||||
- Generally do not need to copy the function
|
||||
- Take Qos of volume type `src/pages/storage/containers/VolumeType/QosSpec/Detail/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get detailData() {
|
||||
return this.store.detail.qos_specs;
|
||||
}
|
||||
```
|
||||
|
||||
## Properties and functions that do not need to be overridden
|
||||
|
||||
- `id`
|
||||
- `id` in routing information
|
||||
- `isAdminPage`
|
||||
- Is the current page a "management platform" page
|
||||
- `getUrl`
|
||||
- Function to generate page URL
|
||||
- For example, it is necessary to provide a jump function to the associated resource. Using this function, you can jump to the corresponding address of the console in the console, and jump to the corresponding address of the management platform in the management platform.
|
||||
- `routing`
|
||||
- Routing information corresponding to the page
|
||||
- `isLoading`
|
||||
- Whether the current page is updating data, the loading style will be displayed when updating
|
||||
|
||||
## Basic functions in the base class
|
||||
|
||||
- It is recommended to check the code understanding,`src/containers/BaseDetail/index.jsx`
|
554
docs/en/develop/3-5-BaseStore-introduction.md
Normal file
@ -0,0 +1,554 @@
|
||||
English | [Chinese](/docs/zh/develop/3-5-BaseStore-introduction.md)
|
||||
|
||||
# Application
|
||||
|
||||
- Processing of data requests
|
||||
- Support to obtain all data
|
||||
- Support paging to get data
|
||||
- Support various request processing for data (PUT, POST, GET, PATCH, DELETE, HEAD, etc.)
|
||||
|
||||
# BaseStore Code file
|
||||
|
||||
- `src/stores/base.js`
|
||||
|
||||
# BaseStore Introduction to attribute and function definitions
|
||||
|
||||
- The Store of resource data inherits from the BaseStore class
|
||||
- Code location: `src/stores/xxx/xxx.js`, such as the store corresponding to the cloud host in `src/stores/nova/instance.js`
|
||||
- Only need to copy some functions to complete the data request operation
|
||||
- Attributes and functions are divided into the following four types,
|
||||
- The attributes and functions that usually need to be overridden mainly include:
|
||||
- Properties and functions related to generating url
|
||||
- Functions and attributes for on-demand overridden, mainly include:
|
||||
- List data reprocessing
|
||||
- Reprocessing of detailed data
|
||||
- Handling of request parameters
|
||||
- URL processing
|
||||
- Functions and attributes that do not need to be overridden, mainly include:
|
||||
- Clear data
|
||||
- Processing of project information when encapsulating data
|
||||
- The basic functions in the base class mainly include:
|
||||
- Marker for processing paging data
|
||||
- See below for a more detailed and comprehensive introduction
|
||||
|
||||
## Noun description
|
||||
|
||||
- Front end paging
|
||||
- Get all list data from the backend at once
|
||||
- The front-end displays data based on the total amount of data obtained, the current number of pages configured in the page, and the number of pages per page (`BaseList` component processing)
|
||||
- Backend paging
|
||||
- Request data from the backend with the current page number and the number of pages
|
||||
- Front-end sorting
|
||||
- When using front-end paging, sort all data according to the set sorting information
|
||||
- When using backend paging, sort the data in the current page according to the set sort information
|
||||
- Backend sorting
|
||||
- Request data from the backend with current page number, number of pages, and current sort information
|
||||
- There is no such combination of front-end paging + back-end sorting
|
||||
|
||||
## Properties and functions that usually need to be overridden
|
||||
|
||||
- `module`:
|
||||
- The function must be overridden
|
||||
- Resource corresponding module
|
||||
- This function is used to generate the requested url
|
||||
- Take the instance `src/stores/nova/instance.js` as an example
|
||||
|
||||
```javascript
|
||||
get module() {
|
||||
return 'servers';
|
||||
}
|
||||
```
|
||||
|
||||
- `apiVersion`
|
||||
- The function must be overridden
|
||||
- The api prefix corresponding to the resource
|
||||
- Because all requests need to be forwarded by the server, the prefix of the api needs to be generated based on the information in the profile
|
||||
- Take the instance `src/stores/nova/instance.js` as an example
|
||||
|
||||
```javascript
|
||||
get apiVersion() {
|
||||
return novaBase();
|
||||
}
|
||||
```
|
||||
|
||||
- `responseKey`
|
||||
- The function must be overridden
|
||||
- Used to generate the key returned by the data, the created key, etc.
|
||||
- Take the instance `src/stores/nova/instance.js` as an example
|
||||
|
||||
```javascript
|
||||
get responseKey() {
|
||||
return 'server';
|
||||
}
|
||||
```
|
||||
|
||||
![Request](/docs/en/develop/images/store/response-key.png)
|
||||
|
||||
## Properties and functions for on-demand overridden
|
||||
|
||||
- `listDidFetch`
|
||||
- Functions used for secondary processing of list data
|
||||
- After requesting other APIs, data can be integrated
|
||||
- Filterable data
|
||||
- When requesting a snapshot list of a specified cloud disk, you can filter the data again based on the parameters in `filters`
|
||||
- Take snapshot of volume `src/stores/cinder/snapshot.js` as an example
|
||||
|
||||
```javascript
|
||||
async listDidFetch(items, allProjects, filters) {
|
||||
if (items.length === 0) {
|
||||
return items;
|
||||
}
|
||||
const { id } = filters;
|
||||
const datas = id ? items.filter((it) => it.volume_id === id) : items;
|
||||
return datas;
|
||||
}
|
||||
```
|
||||
|
||||
- If you need to display encrypted information, you need to initiate an additional request to integrate the data
|
||||
- Take volume type `src/stores/cinder/volume-type.js` as an example
|
||||
|
||||
```javascript
|
||||
async listDidFetch(items, allProjects, filters) {
|
||||
const { showEncryption } = filters;
|
||||
if (items.length === 0) {
|
||||
return items;
|
||||
}
|
||||
if (!showEncryption) {
|
||||
return items;
|
||||
}
|
||||
const promiseList = items.map((i) =>
|
||||
request.get(`${this.getDetailUrl({ id: i.id })}/encryption`)
|
||||
);
|
||||
const encryptionList = await Promise.all(promiseList);
|
||||
const result = items.map((i) => {
|
||||
const { id } = i;
|
||||
const encryption = encryptionList.find((e) => e.volume_type_id === id);
|
||||
return {
|
||||
...i,
|
||||
encryption,
|
||||
};
|
||||
});
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
- `detailDidFetch`
|
||||
- Function used for secondary processing of detailed data
|
||||
- After requesting other APIs, data can be integrated
|
||||
- Take the snapshot of volume `src/stores/cinder/snapshot.js` as an example
|
||||
|
||||
```javascript
|
||||
async detailDidFetch(item) {
|
||||
const { volume_id } = item;
|
||||
const volumeUrl = `${cinderBase()}/${
|
||||
globals.user.project.id
|
||||
}/volumes/${volume_id}`;
|
||||
const { volume } = await request.get(volumeUrl);
|
||||
item.volume = volume;
|
||||
return item;
|
||||
}
|
||||
```
|
||||
|
||||
- `listResponseKey`
|
||||
- Return of list data Key
|
||||
- The default value is `${this.responseKey}s`
|
||||
- Take the snapshot of volume `src/stores/cinder/snapshot.js` as an example
|
||||
|
||||
```javascript
|
||||
get responseKey() {
|
||||
return 'snapshot';
|
||||
}
|
||||
|
||||
get listResponseKey() {
|
||||
return 'volume_snapshots';
|
||||
}
|
||||
```
|
||||
|
||||
- `getListUrl`
|
||||
- Url used for request data
|
||||
- When the front-end page requests list data (that is, get all the data at once), the first use of `this.getListDetailUrl()`
|
||||
- When the back-end page requests list data, the priority is `this.getListPageUrl()`> `this.getListDetailUrl()`> `this.getListUrl()`
|
||||
- The default is
|
||||
|
||||
```javascript
|
||||
getListUrl = () => `${this.apiVersion}/${this.module}`;
|
||||
```
|
||||
|
||||
- Take the log `src/stores/heat/event.js` of Heat's stack as an example
|
||||
|
||||
```javascript
|
||||
getListUrl = ({ id, name }) =>
|
||||
`${this.apiVersion}/${this.module}/${name}/${id}/events`;
|
||||
```
|
||||
|
||||
- `getListDetailUrl`
|
||||
- Url used for request data
|
||||
- When the front-end page requests list data (that is, get all the data at once), the first use of `this.getListDetailUrl()`
|
||||
- When the back-end page requests list data, the priority is `this.getListPageUrl()`> `this.getListDetailUrl()`> `this.getListUrl()`
|
||||
- The default is
|
||||
|
||||
```javascript
|
||||
getListDetailUrl = () => '';
|
||||
```
|
||||
|
||||
- Take the volume `src/stores/cinder/volume.js` as an example
|
||||
|
||||
```javascript
|
||||
getListDetailUrl = () => `${skylineBase()}/extension/volumes`;
|
||||
```
|
||||
|
||||
- `getListPageUrl`
|
||||
- The url used by the backend paging data
|
||||
- When the back-end page requests list data, the priority is `this.getListPageUrl()`> `this.getListDetailUrl()`> `this.getListUrl()`
|
||||
- The default value is
|
||||
|
||||
```javascript
|
||||
getListPageUrl = () => '';
|
||||
```
|
||||
|
||||
- Take the volume `src/stores/cinder/volume.js` as an example
|
||||
|
||||
```javascript
|
||||
getListPageUrl = () => `${skylineBase()}/extension/volumes`;
|
||||
```
|
||||
|
||||
- `getDetailUrl`
|
||||
- The url corresponding to the detailed data
|
||||
- Use rest style API, so the url is also the url corresponding to put, delete, patch
|
||||
- The default value is
|
||||
|
||||
```javascript
|
||||
getDetailUrl = ({ id }) => `${this.getListUrl()}/${id}`;
|
||||
```
|
||||
|
||||
- Take the stack `src/stores/heat/stack.js` as an example
|
||||
|
||||
```javascript
|
||||
getDetailUrl = ({ id, name }) => `${this.getListUrl()}/${name}/${id}`;
|
||||
```
|
||||
|
||||
- `needGetProject`
|
||||
- Whether the data returned by the server needs to be processed for the project information
|
||||
- Generally, the data returned by the Openstack API is only `project_id` information. According to the requirements of the page display, the project name needs to be displayed on the management platform
|
||||
- The default value is `true`
|
||||
- Take the metadata `src/stores/glance/metadata.js` as an example
|
||||
|
||||
```javascript
|
||||
get needGetProject() {
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
- `mapper`
|
||||
- Perform secondary processing on the list and detailed data returned by the server
|
||||
- Generally for more convenient display of data usage in the resource list and resource details
|
||||
- The default value is
|
||||
|
||||
```javascript
|
||||
get mapper() {
|
||||
return (data) => data;
|
||||
}
|
||||
```
|
||||
|
||||
- Take the volume `src/stores/cinder/volume.js` as an example
|
||||
|
||||
```javascript
|
||||
get mapper() {
|
||||
return (volume) => ({
|
||||
...volume,
|
||||
disk_tag: isOsDisk(volume) ? 'os_disk' : 'data_disk',
|
||||
description: volume.description || (volume.origin_data || {}).description,
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
- `mapperBeforeFetchProject`
|
||||
- Before processing the project information, perform secondary processing on the list and detailed data returned by the server
|
||||
- Generally used to process the item information in the returned data
|
||||
- The default value is
|
||||
|
||||
```javascript
|
||||
get mapperBeforeFetchProject() {
|
||||
return (data) => data;
|
||||
}
|
||||
```
|
||||
|
||||
- Take the image `src/stores/glance/image.js` as an example
|
||||
|
||||
```javascript
|
||||
get mapperBeforeFetchProject() {
|
||||
return (data, filters, isDetail) => {
|
||||
if (isDetail) {
|
||||
return {
|
||||
...data,
|
||||
project_id: data.owner,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...data,
|
||||
project_id: data.owner,
|
||||
project_name: data.owner_project_name || data.project_name,
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- `paramsFunc`
|
||||
- When the front-end paging request (ie `fetchList`), update the request parameters
|
||||
- The default is to filter the parameters when using `fetchList` from the resource list code (`pages/xxxx/xxx/index.jsx`)
|
||||
- The default value is
|
||||
|
||||
```javascript
|
||||
get paramsFunc() {
|
||||
if (this.filterByApi) {
|
||||
return (params) => params;
|
||||
}
|
||||
return (params) => {
|
||||
const reservedKeys = [
|
||||
'all_data',
|
||||
'all_projects',
|
||||
'device_id',
|
||||
'network_id',
|
||||
'floating_network_id',
|
||||
'start_at_gt',
|
||||
'start_at_lt',
|
||||
'binary',
|
||||
'fixed_ip_address',
|
||||
'device_owner',
|
||||
'project_id',
|
||||
'type',
|
||||
'sort',
|
||||
'security_group_id',
|
||||
'id',
|
||||
'security_group_id',
|
||||
'owner_id',
|
||||
'status',
|
||||
'fingerprint',
|
||||
'resource_types',
|
||||
'floating_ip_address',
|
||||
'uuid',
|
||||
'loadbalancer_id',
|
||||
'ikepolicy_id',
|
||||
'ipsecpolicy_id',
|
||||
'endpoint_id',
|
||||
'peer_ep_group_id',
|
||||
'local_ep_group_id',
|
||||
'vpnservice_id',
|
||||
];
|
||||
const newParams = {};
|
||||
Object.keys(params).forEach((key) => {
|
||||
if (reservedKeys.indexOf(key) >= 0) {
|
||||
newParams[key] = params[key];
|
||||
}
|
||||
});
|
||||
return newParams;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- Take the volume `src/stores/cinder/volume.js` as an example
|
||||
|
||||
```javascript
|
||||
get paramsFunc() {
|
||||
return (params) => {
|
||||
const { serverId, ...rest } = params;
|
||||
return rest;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- `paramsFuncPage`
|
||||
- When the back-end paging request (ie `fetchListByPage`), update the request parameters
|
||||
- The default is to filter the parameters when using `fetchListByPage` from the resource list code (`pages/xxxx/xxx/index.jsx`)
|
||||
- The default value is
|
||||
|
||||
```javascript
|
||||
get paramsFuncPage() {
|
||||
return (params) => {
|
||||
const { current, ...rest } = params;
|
||||
return rest;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- Take the volume type `src/stores/cinder/volume-type.js` as an example
|
||||
|
||||
```javascript
|
||||
get paramsFuncPage() {
|
||||
return (params) => {
|
||||
const { current, showEncryption, ...rest } = params;
|
||||
return rest;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- `fetchListByLimit`
|
||||
- When the front-end page requests all data, whether to initiate multiple requests based on `limit`, and finally achieve all data acquisition
|
||||
- The Openstack API returns 1000 data by default. For some resource data, you need to use this configuration to get all the data.
|
||||
- The default value is `false`
|
||||
- Take the image `src/stores/glance/image.js` as an example
|
||||
|
||||
```javascript
|
||||
get fetchListByLimit() {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
- `markerKey`
|
||||
- The source of the marker when the back-end page requests data
|
||||
- Because the request to Openstack is forwarded by the backend, the URL that should be used for the next page of data spliced by Openstack returned by the list data is not directly used, but the `marker` is parsed based on the returned data.
|
||||
- The default value is `id`
|
||||
- Usually does not need to be replicated
|
||||
- Take the keypair `src/stores/nova/keypair.js` as an example
|
||||
|
||||
```javascript
|
||||
get markerKey() {
|
||||
return 'keypair.name';
|
||||
}
|
||||
```
|
||||
|
||||
- `requestListByMarker`
|
||||
- When backend paging, use `marker` to request the data under paging
|
||||
- Usually does not need to be replicated
|
||||
- The default value is
|
||||
|
||||
```javascript
|
||||
async requestListByMarker(url, params, limit, marker) {
|
||||
const newParams = {
|
||||
...params,
|
||||
limit,
|
||||
};
|
||||
if (marker) {
|
||||
newParams.marker = marker;
|
||||
}
|
||||
return request.get(url, newParams);
|
||||
}
|
||||
```
|
||||
|
||||
- Take the server group `src/stores/nova/server-group.js` as an example
|
||||
|
||||
```javascript
|
||||
async requestListByMarker(url, params, limit, marker) {
|
||||
const newParams = {
|
||||
...params,
|
||||
limit,
|
||||
};
|
||||
if (marker) {
|
||||
newParams.offset = marker;
|
||||
}
|
||||
return request.get(url, newParams);
|
||||
}
|
||||
```
|
||||
|
||||
- `requestListAllByLimit`
|
||||
- When `this.fetchListByLimit=true`, the front-end paging uses this method to get all data
|
||||
- Usually does not need to be replicated
|
||||
- `updateUrl`
|
||||
- The url of the update list data request
|
||||
- Uncommonly used
|
||||
- `updateParamsSortPage`
|
||||
- When using back-end sorting, the processing of sorting parameters
|
||||
- When using back-end sorting, the corresponding request parameters will be automatically generated in the resource list code `pages/xxx/XXX/index.jsx`. Store often needs to sort these parameters again, otherwise it will not meet the API parameter requirements
|
||||
- Take the volume `src/stores/cinder/volume.js` as an example
|
||||
|
||||
```javascript
|
||||
updateParamsSortPage = (params, sortKey, sortOrder) => {
|
||||
if (sortKey && sortOrder) {
|
||||
params.sort_keys = sortKey;
|
||||
params.sort_dirs = sortOrder === 'descend' ? 'desc' : 'asc';
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
- `listFilterByProject`
|
||||
- Does the list data need to be filtered based on project information
|
||||
- Some Openstack resources under the `admin` authority (such as `neutron`) will return the data of all projects by default, so when the resources are displayed in the console, the data will be filtered according to the configuration
|
||||
- The default value is `false`
|
||||
- Take the vpn `src/stores/neutron/vpn-service.js` as an example
|
||||
|
||||
```javascript
|
||||
get listFilterByProject() {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
- `fetchList`
|
||||
- The list page under `pages` usually uses `this.store.fetchList` to get the front-end paging data
|
||||
- It is not recommended to copy this function, if you need to reprocess the data, it is recommended to use `listDidFetch`
|
||||
- This function will update the relevant data in the `this.list` property, and the resource list component under `pages` is also based on `this.list` for data display
|
||||
- `fetchListByPage`
|
||||
- List pages under `pages` usually use `this.store.fetchList` to get back-end paging data
|
||||
- It is not recommended to copy this function, if you need to reprocess the data, it is recommended to use `listDidFetch`
|
||||
- This function will update the relevant data in the `this.list` property, and the resource list component under `pages` is also based on `this.list` for data display
|
||||
- `getCountForPage`
|
||||
- Get the total amount of list data
|
||||
- Usually rewriteable in back-end paging
|
||||
- `getDetailParams`
|
||||
- Parameters when requesting update details
|
||||
- The default value is
|
||||
|
||||
```javascript
|
||||
getDetailParams = () => undefined;
|
||||
```
|
||||
|
||||
- `fetchDetail`
|
||||
- The detail page under `pages` usually uses `this.store.fetchDetail` to get detailed data
|
||||
- Usually does not need to be replicated
|
||||
- Data reprocessing is usually to rewrite `mapper` or `detailDidFetch`
|
||||
- `create`
|
||||
- Create resources
|
||||
- Use `POST` api
|
||||
- Usually does not need to be replicated
|
||||
- Use `this.submitting` to ensure that the page is in the `loading` state when the request is sent
|
||||
- `edit`
|
||||
- Update resources
|
||||
- Use `PUT` api
|
||||
- Usually does not need to be replicated
|
||||
- Use `this.submitting` to ensure that the page is in the `loading` state when the request is sent
|
||||
- `patch`
|
||||
- Update resources
|
||||
- Use `PATCH` api
|
||||
- Usually does not need to be replicated
|
||||
- Use `this.submitting` to ensure that the page is in the `loading` state when the request is sent
|
||||
- `delete`
|
||||
- Delete resources
|
||||
- Use `DELETE` api
|
||||
- Usually does not need to be replicated
|
||||
- Use `this.submitting` to ensure that the page is in the `loading` state when the request is sent
|
||||
|
||||
## Properties and functions that do not need to be overridden
|
||||
|
||||
- `submitting`
|
||||
- For data creation and data update
|
||||
- Change `this.isSubmitting` according to the response of the request, the corresponding Form, list page, etc. will display the Loading status
|
||||
- `currentProject`
|
||||
- Project ID of the current user login
|
||||
- `itemInCurrentProject`
|
||||
- Does the data belong to the project logged in by the current user
|
||||
- `listDidFetchProject`
|
||||
- Add item information to list data
|
||||
- `requestListAll`
|
||||
- Front-end paging to get all data
|
||||
- `requestListByPage`
|
||||
- Back-end pagination of all current page data
|
||||
- `pureFetchList`
|
||||
- List data request function
|
||||
- Return the original data without processing the returned data from the API
|
||||
- `parseMarker`
|
||||
- When using back-end paging, parse out the `marker` from the returned data, which is used when requesting the previous and next pages of data
|
||||
- `updateMarker`
|
||||
- Update `markers` of `list`
|
||||
- `list.markers` is an array, each element corresponds to the `marker` of the `subscript+1` page
|
||||
- `getMarker`
|
||||
- Get the `marker` corresponding to the specified page
|
||||
- `getListDataFromResult`
|
||||
- Get the list data from the return value of the API
|
||||
- Use `this.listResponseKey` to get
|
||||
- `setSelectRowKeys`
|
||||
- The selected record of the data item in the resource list component list under `pages`
|
||||
- `clearData`
|
||||
- Clear `list` data
|
||||
|
||||
## Basic functions in the base class
|
||||
|
||||
- It is recommended to check the code understanding,`src/stores/base.js`
|
391
docs/en/develop/3-6-FormAction-introduction.md
Normal file
@ -0,0 +1,391 @@
|
||||
English | [Chinese](/docs/zh/develop/3-6-FormAction-introduction.md)
|
||||
|
||||
# Application
|
||||
|
||||
![Form single page](/docs/en/develop/images/form/page.png)
|
||||
|
||||
- After the operation button is clicked, a single page displays the Form form
|
||||
- There is an independent route for access
|
||||
- Generally used to create resources, or form with more form content
|
||||
- After clicking the `Confirm` button, the status of `loading` will be displayed according to the sending status of the request. After the request is successful, it will automatically jump to the corresponding resource list page
|
||||
- After clicking the `Cancel` button, it will automatically jump to the corresponding resource list page
|
||||
- If the request is sent successfully, a message indicating that the operation was successful will be displayed in the upper right corner, and the message will automatically disappear after a few seconds
|
||||
|
||||
![Form single page](/docs/en/develop/images/form/create-success.png)
|
||||
|
||||
- If the request fails, an error message will be displayed in the upper right corner of the form page, which can only disappear after clicking the close button
|
||||
|
||||
# FormAction Code file
|
||||
|
||||
- `src/containers/Action/FormAction/index.jsx`
|
||||
|
||||
# FormAction Introduction to attribute and function definitions
|
||||
|
||||
- Single page forms are inherited from FormAction component
|
||||
- Code location:`pages/xxxx/containers/XXXX/actions/xxx.jsx`
|
||||
- Only need to copy some functions to complete the development of the page
|
||||
- Attributes and functions are divided into the following four types,
|
||||
- The attributes and functions that must be replicated include:
|
||||
- Operation ID
|
||||
- Operation Title
|
||||
- The path corresponding to the page
|
||||
- The path corresponding to the resource list page
|
||||
- Operation corresponding permissions
|
||||
- Judgment on whether to disable the operation
|
||||
- Configuration of form items
|
||||
- Function to send request
|
||||
- Functions and attributes for on-demand overridden, mainly include:
|
||||
- The default value is of the form
|
||||
- Functions and attributes that do not need to be overridden, mainly include:
|
||||
- Whether the current page is a management platform page
|
||||
- The basic functions in the base class mainly include:
|
||||
- Render the page
|
||||
- Display of request status
|
||||
- Display of request results
|
||||
- See below for a more detailed and comprehensive introduction
|
||||
|
||||
## Properties and functions that must be overridden
|
||||
|
||||
- `id`
|
||||
- Static properties
|
||||
- ID of resource operation
|
||||
- Need to be unique, only for all operations in the `actions` of the resource to be unique
|
||||
- This attribute must be overridden
|
||||
- Take the volume creating `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
static id = 'volume-create';
|
||||
```
|
||||
|
||||
- `title`
|
||||
- Static properties
|
||||
- Title of resource operation
|
||||
- Take the volume creating `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
static title = t('Create Volume');
|
||||
```
|
||||
|
||||
- `path`
|
||||
- Corresponding routing for resource operations
|
||||
- Static properties or static functions
|
||||
- In the case of a static function, the parameters are
|
||||
- Parameter `item`, item data in the resource list
|
||||
- Parameter `containerProps`, the `props` property of the parent container (that is, the resource list page where the button is located)
|
||||
- Take the image creating `src/pages/compute/containers/Image/actions/Create.jsx` as an example
|
||||
- The path to the management platform is `/compute/image-admin/create`
|
||||
- The path to the console is `/compute/image/create`
|
||||
|
||||
```javascript
|
||||
static path = (_, containerProp) => {
|
||||
const { isAdminPage } = containerProp;
|
||||
return isAdminPage
|
||||
? '/compute/image-admin/create'
|
||||
: '/compute/image/create';
|
||||
};
|
||||
```
|
||||
|
||||
- Static properties,Take the volume creating `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
static path = '/storage/volume/create';
|
||||
```
|
||||
|
||||
- `policy`
|
||||
- Static properties
|
||||
- The permission corresponding to the page. If the permission verification fails, the operation button will not be displayed on the resource list page
|
||||
- Take the volume `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
static policy = 'volume:create';
|
||||
```
|
||||
|
||||
- `allowed`
|
||||
- Static functions
|
||||
- Determine whether the operation needs to be disabled
|
||||
- Return `Promise`
|
||||
- Write directly without using disabled buttons
|
||||
|
||||
```javascript
|
||||
static allowed() {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
```
|
||||
|
||||
- The parameter `item`, the item data in the resource list, is generally used to determine the operation of the item in the resource list
|
||||
- The parameter `containerProps`, the `props` property of the parent container (that is, the resource list page where the button is located), is generally used to determine the operation of related resources under the details page
|
||||
- Take user creating `src/pages/identity/containers/User/actions/Create.jsx` as an example
|
||||
- If it is a user list in the domain details, the create user button will not be displayed
|
||||
|
||||
```javascript
|
||||
static allowed(item, containerProps) {
|
||||
const {
|
||||
match: { path },
|
||||
} = containerProps;
|
||||
if (path.indexOf('domain-admin/detail') >= 0) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
```
|
||||
|
||||
- `name`
|
||||
- The name of the operation
|
||||
- Use the name in the prompt after the request
|
||||
- Take the volume `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get name() {
|
||||
return t('create volume');
|
||||
}
|
||||
```
|
||||
|
||||
- `listUrl`
|
||||
- Resource list page corresponding to this operation
|
||||
- After the operation request is successful, it will automatically enter the resource list page
|
||||
- Take the volume `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get listUrl() {
|
||||
return this.getUrl('/storage/volume');
|
||||
}
|
||||
```
|
||||
|
||||
- `formItems`
|
||||
- The form item configuration list corresponding to the operation form
|
||||
- For the configuration information of each form item, please refer to [3-10-FormItem Introduction](3-10-FormItem-introduction.md)
|
||||
- Take the domain creating `src/pages/identity/containers/Domain/actions/Create.jsx` as an example
|
||||
- The form contains name, description, status
|
||||
|
||||
```javascript
|
||||
get formItems() {
|
||||
return [
|
||||
{
|
||||
name: 'name',
|
||||
label: t('Name'),
|
||||
type: 'input',
|
||||
placeholder: t('Please input name'),
|
||||
required: true,
|
||||
help: t('The name cannot be modified after creation'),
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
label: t('Description'),
|
||||
type: 'textarea',
|
||||
},
|
||||
{
|
||||
name: 'enabled',
|
||||
label: t('Status'),
|
||||
type: 'radio',
|
||||
optionType: 'default',
|
||||
options: statusTypes,
|
||||
required: true,
|
||||
isWrappedValue: true,
|
||||
help: t(
|
||||
'Forbidden the domain will have a negative impact, all project and user in domain will be forbidden'
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
- `onSubmit`
|
||||
- The request function of the operation
|
||||
- After the operation request is successful, it will automatically enter the resource list page
|
||||
- After the operation fails, an error message will be displayed on the form page
|
||||
- Return `Promise`
|
||||
- Returns the function in the `store` corresponding to the form
|
||||
- Take the domain creating `src/pages/identity/containers/Domain/actions/Create.jsx` as an example
|
||||
|
||||
```javascript
|
||||
onSubmit = (values) => {
|
||||
values.enabled = values.enabled.value;
|
||||
return this.store.create(values);
|
||||
};
|
||||
```
|
||||
|
||||
## Properties and functions for on-demand overridden
|
||||
|
||||
- `init`
|
||||
- Initial operation
|
||||
- Define `this.store` in it, the display of `loading` status is based on `this.store.isSubmitting`
|
||||
- Call the function to obtain other data required by the form in it
|
||||
- Update to the attributes in `this.state`
|
||||
- Take the volume creating `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
- Obtain quota information, available domain data, mirrored data, cloud disk type
|
||||
- Update the initial value in `this.state`
|
||||
|
||||
```javascript
|
||||
init() {
|
||||
this.snapshotStore = globalSnapshotStore;
|
||||
this.imageStore = globalImageStore;
|
||||
this.volumeStore = globalVolumeStore;
|
||||
this.volumeTypeStore = globalVolumeTypeStore;
|
||||
this.backupstore = globalBackupStore;
|
||||
this.getQuota();
|
||||
this.getAvailZones();
|
||||
this.getImages();
|
||||
this.getVolumeTypes();
|
||||
this.state = {
|
||||
...this.state,
|
||||
count: 1,
|
||||
sharedDisabled: false,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- `defaultValue`
|
||||
- The initial value of the form
|
||||
- The default value is `{}`
|
||||
- Take the volume creating `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
- Set the default source, size, project, available domain, and volume type of the form
|
||||
|
||||
```javascript
|
||||
get defaultValue() {
|
||||
const size = this.quotaIsLimit && this.maxSize < 10 ? this.maxSize : 10;
|
||||
const { initVolumeType } = this.state;
|
||||
const values = {
|
||||
source: this.sourceTypes[0],
|
||||
size,
|
||||
project: this.currentProjectName,
|
||||
availableZone: (this.availableZones[0] || []).value,
|
||||
volume_type: initVolumeType,
|
||||
};
|
||||
return values;
|
||||
}
|
||||
```
|
||||
|
||||
- `nameForStateUpdate`
|
||||
- When the content of the form item changes, update to the form key-value pair in `this.state`
|
||||
- These key-value pairs stored in `this.store` often affect the display of form items and need to be used in conjunction with the code in `get formItems`
|
||||
- Such as expand and hide more configuration items
|
||||
- Such as the mandatory changes of some form items
|
||||
- By default, changes to the form items of `radio`, `more` type are saved to `this.state`
|
||||
- Take the volume creating `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
- When `source=image`, display the image selection list, and set the minimum volume capacity based on the image selection
|
||||
- When `source=snapshot`, display the cloud disk snapshot list, and set the minimum value of the volume capacity based on the image selection
|
||||
|
||||
```javascript
|
||||
get nameForStateUpdate() {
|
||||
return ['source', 'image', 'snapshot'];
|
||||
}
|
||||
```
|
||||
|
||||
- `renderFooterLeft`
|
||||
- Rendering of the inner left at the bottom of the form
|
||||
- The default value is `null`
|
||||
- Take the volume creating `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
- Show the number of batches created
|
||||
- Determine whether the current form is correct based on the entered quantity and remaining quota
|
||||
|
||||
```javascript
|
||||
const { count = 1 } = this.state;
|
||||
const configs = {
|
||||
min: 1,
|
||||
max: 100,
|
||||
precision: 0,
|
||||
onChange: this.onCountChange,
|
||||
formatter: (value) => `$ ${value}`.replace(/\D/g, ''),
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<span>{t('Count')}</span>
|
||||
<InputNumber
|
||||
{...configs}
|
||||
value={count}
|
||||
className={classnames(styles.input, 'volume-count')}
|
||||
/>
|
||||
{this.renderBadge()}
|
||||
</div>
|
||||
);
|
||||
```
|
||||
|
||||
- `errorText`
|
||||
- Display of error messages
|
||||
- Generally do not need to overridden
|
||||
- Take the volume creating `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
- Displays the error message that the quota verification fails. When the quota verification fails, the request is not sent, but the error message is displayed directly
|
||||
|
||||
```javascript
|
||||
get errorText() {
|
||||
const { status } = this.state;
|
||||
if (status === 'error') {
|
||||
return t(
|
||||
'Unable to create volume: insufficient quota to create resources.'
|
||||
);
|
||||
}
|
||||
return super.errorText;
|
||||
}
|
||||
```
|
||||
|
||||
- `instanceName`
|
||||
- After the request is sent, the resource name in the prompt message
|
||||
- The default value is `this.values.name`
|
||||
- Take the volume creating `src/pages/storage/containers/Volume/actions/Create/index.jsx` as an example
|
||||
- If you are creating cloud disks in batches, display the names in the form of `${name}-${index + 1}`
|
||||
|
||||
```javascript
|
||||
get instanceName() {
|
||||
const { name } = this.values || {};
|
||||
const { count = 1 } = this.state;
|
||||
if (count === 1) {
|
||||
return name;
|
||||
}
|
||||
return new Array(count)
|
||||
.fill(count)
|
||||
.map((_, index) => `${name}-${index + 1}`)
|
||||
.join(', ');
|
||||
}
|
||||
```
|
||||
|
||||
- `labelCol`
|
||||
- Configure the layout of the labels on the left side of the form
|
||||
- The default value is
|
||||
|
||||
```javascript
|
||||
get labelCol() {
|
||||
return {
|
||||
xs: { span: 5 },
|
||||
sm: { span: 3 },
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- Take the image creating `src/pages/compute/containers/Image/actions/Create.jsx` as an example
|
||||
|
||||
```javascript
|
||||
get labelCol() {
|
||||
return {
|
||||
xs: { span: 6 },
|
||||
sm: { span: 5 },
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- `wrapperCol`
|
||||
- Configure the layout of the content on the right side of the form
|
||||
- The default value is
|
||||
|
||||
```javascript
|
||||
get wrapperCol() {
|
||||
return {
|
||||
xs: { span: 10 },
|
||||
sm: { span: 8 },
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Properties and functions that do not need to be overridden
|
||||
|
||||
- `values`
|
||||
- After the form is successfully validated, the updated form value
|
||||
- `isAdminPage`
|
||||
- Is the current page a "management platform" page
|
||||
- `getUrl`
|
||||
- Function to generate page URL
|
||||
- For example, it is necessary to provide a jump function to the associated resource. Using this function, you can jump to the corresponding address of the console in the console, and jump to the corresponding address of the management platform in the management platform.
|
||||
|
||||
## Basic functions in the base class
|
||||
|
||||
- `FormAction` inherits from `BaseForm`
|
||||
- It is recommended to check the code understanding,`src/components/Form/index.jsx`
|
BIN
docs/en/develop/images/detail/image-detail-info.png
Normal file
After Width: | Height: | Size: 210 KiB |
BIN
docs/en/develop/images/detail/volume.png
Normal file
After Width: | Height: | Size: 192 KiB |
BIN
docs/en/develop/images/form/create-success.png
Normal file
After Width: | Height: | Size: 149 KiB |
BIN
docs/en/develop/images/form/page.png
Normal file
After Width: | Height: | Size: 126 KiB |
BIN
docs/en/develop/images/list/batch.png
Normal file
After Width: | Height: | Size: 126 KiB |
BIN
docs/en/develop/images/list/download.png
Normal file
After Width: | Height: | Size: 1009 B |
BIN
docs/en/develop/images/list/fresh.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
docs/en/develop/images/list/hide.png
Normal file
After Width: | Height: | Size: 132 KiB |
BIN
docs/en/develop/images/list/pagination.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
docs/en/develop/images/list/search-example.png
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
docs/en/develop/images/list/search.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
docs/en/develop/images/list/stop-auto-refresh.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
docs/en/develop/images/list/tab-list.png
Normal file
After Width: | Height: | Size: 171 KiB |
BIN
docs/en/develop/images/list/tab-service.png
Normal file
After Width: | Height: | Size: 178 KiB |
BIN
docs/en/develop/images/list/volumes.png
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
docs/en/develop/images/store/response-key.png
Executable file
After Width: | Height: | Size: 36 KiB |
@ -18,7 +18,7 @@
|
||||
- `.dockerignore`: docker 忽略的文件配置
|
||||
- `.eslintignore`: eslint 忽略的文件配置
|
||||
- `.eslint`: eslint 配置
|
||||
- `.gitignore`: git 忽悠的文件配置
|
||||
- `.gitignore`: git 忽略的文件配置
|
||||
- `.gitreview`: gitreview 配置
|
||||
- `.prettierignore`: prettier 忽略的文件配置
|
||||
- `.prettierrc`: prettier 的配置
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
- 可配置列表表头
|
||||
|
||||
![列表页自动刷新](/docs/zh/develop/images/list/hide.png)
|
||||
![列表页表头隐藏/展示](/docs/zh/develop/images/list/hide.png)
|
||||
|
||||
- 各资源列表页通过复写函数即可完成
|
||||
|
||||
|