mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-11-04 00:02:37 +01:00 
			
		
		
		
	MD012 no-multiple-blanks - Multiple consecutive blank lines https://github.com/DavidAnson/markdownlint/blob/main/doc/md012.md
		
			
				
	
	
		
			231 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			231 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# UI Development
 | 
						|
 | 
						|
The modern CloudStack UI is role-based progressive app that uses Vue.js and Ant Design.
 | 
						|
 | 
						|
JavaScript, Vue.js references:
 | 
						|
- https://www.w3schools.com/js/
 | 
						|
- https://www.geeksforgeeks.org/javascript-tutorial/
 | 
						|
- https://vuejs.org/v2/guide/
 | 
						|
- https://www.youtube.com/watch?v=Wy9q22isx3U
 | 
						|
 | 
						|
All the source is in the `src` directory with its entry point at `main.js`.
 | 
						|
The following tree shows the basic UI codebase filesystem:
 | 
						|
 | 
						|
```bash
 | 
						|
    src
 | 
						|
    ├── assests       # sprites, icons, images
 | 
						|
    ├── components    # Shared vue files used to render various generic / widely used components
 | 
						|
    ├── config        # Contains the layout details of the various routes / sections available in the UI
 | 
						|
    ├── locales       # Custom translation keys for the various supported languages
 | 
						|
    ├── store         # A key-value storage for all the application level state information such as user info, etc
 | 
						|
    ├── utils         # Collection of custom libraries
 | 
						|
    ├── views         # Custom vue files used to render specific components
 | 
						|
    ├── ...
 | 
						|
    └── main.js       # Main entry-point
 | 
						|
```
 | 
						|
 | 
						|
## Development
 | 
						|
 | 
						|
Clone the repository:
 | 
						|
 | 
						|
```
 | 
						|
git clone https://github.com/apache/cloudstack.git
 | 
						|
cd cloudstack/ui
 | 
						|
npm install
 | 
						|
```
 | 
						|
Override the default `CS_URL` to a running CloudStack management server:
 | 
						|
```
 | 
						|
cp .env.local.example .env.local
 | 
						|
```
 | 
						|
Change the `CS_URL` in the `.env.local` file
 | 
						|
To configure https, you may use `.env.local.https.example`.
 | 
						|
Build and run:
 | 
						|
```
 | 
						|
npm run serve
 | 
						|
```
 | 
						|
 | 
						|
## Implementation
 | 
						|
 | 
						|
## Defining a new Section
 | 
						|
 | 
						|
### Section Config Definition
 | 
						|
 | 
						|
A new section may be added in `src/config/section` and in `src/config/router.js`,
 | 
						|
import the new section's (newconfig.js as example) configuration file and rules to
 | 
						|
`asyncRouterMap` as:
 | 
						|
 | 
						|
    import newconfig from '@/config/section/newconfig'
 | 
						|
 | 
						|
    [ ... snipped ... ]
 | 
						|
 | 
						|
      generateRouterMap(newSection),
 | 
						|
 | 
						|
### Section
 | 
						|
 | 
						|
An existing or new section's config/js file must export the following parameters:
 | 
						|
 | 
						|
- `name`: Unique path in URL
 | 
						|
- `title`: The name to be displayed in navigation and breadcrumb
 | 
						|
- `icon`: The icon to be displayed, from AntD's icon set
 | 
						|
  https://vue.ant.design/components/icon/
 | 
						|
- `docHelp`: Allows to provide a link to a document to provide details on the
 | 
						|
  section
 | 
						|
- `searchFilters`: List of parameters by which the resources can be filtered
 | 
						|
  via the list API
 | 
						|
- `children`: (optional) Array of resources sub-navigation under the parent
 | 
						|
  group
 | 
						|
- `permission`: When children are not defined, the array of APIs to check against
 | 
						|
  allowed auto-discovered APIs
 | 
						|
- `columns`: When children is not defined, list of column keys
 | 
						|
- `component`: When children is not defined, the custom component for rendering
 | 
						|
  the route view
 | 
						|
 | 
						|
See `src/config/section/compute.js` and `src/config/section/project.js` for example.
 | 
						|
 | 
						|
The children should have:
 | 
						|
 | 
						|
- `name`: Unique path in the URL
 | 
						|
- `title`: The name to be displayed in navigation and breadcrumb
 | 
						|
- `icon`: The icon to be displayed, from AntD's icon set
 | 
						|
  https://vue.ant.design/components/icon/
 | 
						|
- `permission`: The array of APIs to check against auto-discovered APIs
 | 
						|
- `columns`: List of column keys for list view rendering
 | 
						|
- `details`: List of keys for detail list rendering for a resource
 | 
						|
- `tabs`: Array of custom components that will get rendered as tabs in the
 | 
						|
  resource view
 | 
						|
- `component`: The custom component for rendering the route view
 | 
						|
- `related`: A list of associated entity types that can be listed via passing
 | 
						|
  the current resource's id as a parameter in their respective list APIs
 | 
						|
- `actions`: Array of actions that can be performed on the resource
 | 
						|
 | 
						|
## Custom Actions
 | 
						|
 | 
						|
The actions defined for children show up as group of buttons on the default
 | 
						|
autogen view (that shows tables, actions etc.). Each action item should define:
 | 
						|
 | 
						|
- `api`: The CloudStack API for the action. The action button will be hidden if
 | 
						|
  the user does not have permission to execute the API
 | 
						|
- `icon`: The icon to be displayed, from AntD's icon set
 | 
						|
  https://vue.ant.design/components/icon/
 | 
						|
- `label`: The action button name label and modal header
 | 
						|
- `message`: The action button confirmation message
 | 
						|
- `docHelp`: Allows to provide a link to a document to provide details on the
 | 
						|
  action
 | 
						|
- `listView`: (boolean) Whether to show the action button in list view (table).
 | 
						|
  Defaults to false
 | 
						|
- `dataView`: (boolean) Whether to show the action button in resource/data view.
 | 
						|
  Defaults to false
 | 
						|
- `args`: List of API arguments to render/show on auto-generated action form.
 | 
						|
  Can be a function which returns a list of arguments
 | 
						|
- `show`: Function that takes in a records and returns a boolean to control if
 | 
						|
  the action button needs to be shown or hidden. Defaults to true
 | 
						|
- `groupShow`: Same as show but for group actions. Defaults to true
 | 
						|
- `popup`: (boolean) When true, displays any custom component in a popup modal
 | 
						|
  than in its separate route view. Defaults to false
 | 
						|
- `groupAction`: Whether the button supports groupable actions when multiple
 | 
						|
  items are selected in the table. Defaults to false
 | 
						|
- `mapping`: The relation of an arg to an api and the associated parameters to
 | 
						|
  be passed and filtered on the result (from which its id is used as a
 | 
						|
  select-option) or a given hardcoded list of select-options
 | 
						|
- `groupMap`: Function that maps the args and returns the list of parameters to
 | 
						|
  be passed to the api
 | 
						|
- `component`: The custom component to render the action (in a separate route
 | 
						|
  view under src/views/<component>). Uses an autogenerated form by default.
 | 
						|
  Examples of such views can be seen in the src/views/ directory
 | 
						|
 | 
						|
For Example:
 | 
						|
```
 | 
						|
{
 | 
						|
  api: 'startVirtualMachine',
 | 
						|
  icon: 'caret-right',
 | 
						|
  label: 'label.action.start.instance',
 | 
						|
  message: 'message.action.start.instance',
 | 
						|
  docHelp: 'adminguide/virtual_machines.html#stopping-and-starting-vms',
 | 
						|
  dataView: true,
 | 
						|
  groupAction: true,
 | 
						|
  groupMap: (selection) => { return selection.map(x => { return { id: x } }) },
 | 
						|
  show: (record) => { return ['Stopped'].includes(record.state) },
 | 
						|
  args: (record, store) => {
 | 
						|
    var fields = []
 | 
						|
    if (store.userInfo.roletype === 'Admin') {
 | 
						|
      fields = ['podid', 'clusterid', 'hostid']
 | 
						|
    }
 | 
						|
    if (record.hypervisor === 'VMware') {
 | 
						|
      if (store.apis.startVirtualMachine.params.filter(x => x.name === 'bootintosetup').length > 0) {
 | 
						|
        fields.push('bootintosetup')
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return fields
 | 
						|
  },
 | 
						|
  response: (result) => { return result.virtualmachine && result.virtualmachine.password ? `Password of the VM is ${result.virtualmachine.password}` : null }
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
## Resource List View
 | 
						|
 | 
						|
After having, defined a section and the actions that can be performed in the
 | 
						|
 particular section; on navigating to the section, we can have a list of
 | 
						|
 resources available, for example, on navigating to **Compute > Instances**
 | 
						|
 section, we see a list of all the VM instances (each instance referred to as a
 | 
						|
 resource).
 | 
						|
 | 
						|
The columns that should be made available while displaying the list of
 | 
						|
  resources can be defined in the section's configuration file under the
 | 
						|
  columns attribute (as mentioned above). **columns** maybe defined as an array
 | 
						|
  or a function in case we need to selectively (i.e., based on certain
 | 
						|
  conditions) restrict the view of certain columns.
 | 
						|
 | 
						|
It also contains router-links to the resource and other related data such as the
 | 
						|
  account, domain, etc of the resource if present
 | 
						|
 | 
						|
For example:
 | 
						|
 | 
						|
```
 | 
						|
    ...
 | 
						|
    // columns defined as an array
 | 
						|
    columns: ['name', 'state', 'displaytext', 'account', 'domain'],
 | 
						|
 | 
						|
    // columns can also be defined as a function, so as to conditionally restrict view of certain columns
 | 
						|
    columns: () => {
 | 
						|
        var fields = ['name', 'hypervisor', 'ostypename']
 | 
						|
        if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
 | 
						|
          fields.push('account')
 | 
						|
        }
 | 
						|
        ...
 | 
						|
    }
 | 
						|
```
 | 
						|
 | 
						|
## Resource Detail View Customization
 | 
						|
 | 
						|
From the List View of the resources, on can navigate to the individual
 | 
						|
  resource's detail view, which in CloudStack UI we refer to as the
 | 
						|
  *Resource View* by click on the specific resource.
 | 
						|
The Resource View has 2 sections:
 | 
						|
- InfoCard to the left that has basic / minimal details of that resource along
 | 
						|
  with the related entities
 | 
						|
- DetailsTab to the right which provide the basic details about the resource.
 | 
						|
 | 
						|
Custom tabs to render custom details, additional information of the resource
 | 
						|
  The list of fields to be displayed maybe defined as an array
 | 
						|
  or a function in case we need to selectively (i.e., based on certain
 | 
						|
  conditions) restrict the view of certain columns. The names specified in the
 | 
						|
  details array should correspond to the api parameters
 | 
						|
 | 
						|
For example,
 | 
						|
 | 
						|
```
 | 
						|
    ...
 | 
						|
    details: ['name', 'id', 'displaytext', 'projectaccountname', 'account', 'domain'],
 | 
						|
    ...
 | 
						|
    // To render the above mentioned details in the right section of the Resource View, we must import the DetailsTab
 | 
						|
    tabs: [
 | 
						|
    {
 | 
						|
      name: 'details',
 | 
						|
      component: () => import('@/components/view/DetailsTab.vue')
 | 
						|
    },
 | 
						|
    ...
 | 
						|
    ]
 | 
						|
```
 | 
						|
 | 
						|
Additional tabs can be defined by adding on to the tabs section.
 |