feat: ui tweaks & fixes (#1409)

* refactor(ui): use fetchPolic: 'cache-and-network' by default

* feat(ui): don't display loader if cached data

* fix(ui): eslint errors

* feat(ui): new top bar design

* fix(ui): remove work icon in top bar

* fix(ui): logger view item hover background

* feat(ui): Projects list show open project

* feat(ui): top bar: responsive + no favorites message

* fix(ui): Cannot set property consoleLogLast of #<a> which has only a getter

* fix(ui): loading prompts folder when installing plugin

* feat(ui): help translating button + docs

* docs(ui): fix local. docs

* fix(ui): Help translate button

* docs(ui): plugin ui dev docs improvements

* docs(ui): typo

* docs(ui): typo

* docs(ui): typo

* feat(ui): auto locale now tries full code + short code

* docs(ui): fix missing ref locale link
This commit is contained in:
Guillaume Chau
2018-05-31 20:10:05 +02:00
committed by Evan You
parent af1151a494
commit 73545252e0
34 changed files with 460 additions and 145 deletions
+133 -27
View File
@@ -10,6 +10,7 @@ This guide will walk you through the development of cli-ui specific features for
- [Dev mode](#dev-mode)
- [Project configurations](#project-configurations)
- [Project tasks](#project-tasks)
- [Prompts](#prompts)
- [Client addon](#client-addon)
- [Custom views](#custom-views)
- [Shared data](#shared-data)
@@ -111,6 +112,8 @@ api.describeConfig({
})
```
#### Config icon
Specify an icon with either a file type (like `'json'`) or a file name (like `.babelrc` to get the babel icon). This is powered by file-icons.
```js
@@ -121,7 +124,11 @@ api.describeConfig({
})
```
Then you can specify which files will be read when loading the configuration and then written to:
#### Config file
By default, a configuration UI might read and write to a configuration file, for example `.eslintrc.js`.
You can provide what are the possible files to be detected in the user project:
```js
api.describeConfig({
@@ -138,6 +145,10 @@ api.describeConfig({
Supported types: `json`, `yaml`, `js`, `package`.
**⚠️ Currently, only 1 file can be read and written to at a time.**
#### Display config prompts
Use the `onRead` hook to return a list of prompts to be displayed for the configuration:
```js
@@ -151,25 +162,13 @@ api.describeConfig({
})
```
The prompt objects must be valid [inquirer](https://github.com/SBoudrias/Inquirer.js) prompts with the following additional fields (which are optional):
Those prompts will be displayed in the configuration details pane.
```js
{
/* ... */
// Used to group the prompts into sections
group: 'Strongly recommended',
// Additional description
description: 'Enforce attribute naming style in template (`my-prop` or `myProp`)',
// "More info" link
link: 'https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/attribute-hyphenation.md',
}
```
See [Prompts](#prompts) for more info.
Supported inquirer types: `checkbox`, `confirm`, `input`, `password`, `list`, `rawlist`.
#### Save config changes
In addition to those, the UI supports special types that only works with it: `color`.
Use the `onWrite` hook to write the data to the configuration file (or execute any node code):
Use the `onWrite` hook to write the data to the configuration file (or execute any nodejs code):
```js
api.describeConfig({
@@ -182,12 +181,12 @@ api.describeConfig({
Arguments:
- `prompts`: current prompts runtime objects
- `prompts`: current prompts runtime objects (see below)
- `answers`: answers data from the user inputs
- `data`: read-only initial data read from the file
- `file`: descriptor of the found file (`{ type: 'json', path: '...' }`)
- `cwd`: current working directory
- `api`: onWrite API
- `api`: `onWrite API` (see below)
Prompts runtime objects:
@@ -213,11 +212,28 @@ Prompts runtime objects:
}
```
onWrite API:
`onWrite` API:
- `assignData(newData)`: use `Object.assign` to update the config data before writing.
- `setData(newData)`: each key of `newData` will be deeply set (or removed if `undefined` value) to the config data before writing.
- `async getAnswer(id, mapper)`: retrieve answer for a given prompt id and map it through `mapper` function if provide (for example `JSON.parse`).
- `async getAnswer(id, mapper)`: retrieve answer for a given prompt id and map it through `mapper` function if provided (for example `JSON.parse`).
Example (from the ESLint plugin):
```js
api.describeConfig({
// ...
onWrite: async ({ api, prompts }) => {
// Update ESLint rules
const result = {}
for (const prompt of prompts) {
result[`rules.${prompt.id}`] = await api.getAnswer(prompt.id, JSON.parse)
}
api.setData(result)
}
})
```
### Project tasks
@@ -233,7 +249,20 @@ api.describeTask({
match: /vue-cli-service serve/,
description: 'Compiles and hot-reloads for development',
// "More info" link
link: 'https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#serve',
link: 'https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#serve'
})
```
#### Tasks parameters
You can add prompts to modify the command arguments. They will be displayed in a 'Parameters' modal.
Example:
```js
api.describeTask({
// ...
// Optional parameters (inquirer prompts)
prompts: [
{
@@ -262,7 +291,26 @@ api.describeTask({
],
description: 'Specify env mode'
}
],
]
})
```
See [Prompts](#prompts) for more info.
#### Task hooks
Several hooks are available:
- `onBeforeRun`
- `onRun`
- `onExit`
For example, you can use the answers to the prompts (see above) to add new arguments to the command:
```js
api.describeTask({
// ...
// Hooks
// Modify arguments here
onBeforeRun: async ({ answers, args }) => {
@@ -279,7 +327,18 @@ api.describeTask({
onExit: async ({ args, child, cwd, code, signal }) => {
// code: exit code
// signal: kill signal used if any
},
}
})
```
#### Task views
You can display custom views in the task details pane using the `ClientAddon` API:
```js
api.describeTask({
// ...
// Additional views (for example the webpack dashboard)
// By default, there is the 'output' view which displays the terminal output
views: [
@@ -299,9 +358,16 @@ api.describeTask({
})
```
See [Client addon](#client-addon) for more info.
#### Add new tasks
You can also add entirely new tasks which aren't in the `package.json` scripts. Those tasks will only appear in the cli UI:
You can also add entirely new tasks which aren't in the `package.json` scripts with `api.addTask` instead of `api.describeTask`. Those tasks will only appear in the cli UI.
**You need to provide a `command` option instead of `match`.**
Example:
```js
api.addTask({
@@ -323,6 +389,36 @@ api.addTask({
**⚠️ The `command` will run a node context. This means you can call node bin commands like you would normally do in the `package.json` scripts.**
### Prompts
The prompt objects must be valid [inquirer](https://github.com/SBoudrias/Inquirer.js) objects.
However, you can add the following additional fields (which are optional and only used by the UI):
```js
{
/* ... */
// Used to group the prompts into sections
group: 'Strongly recommended',
// Additional description
description: 'Enforce attribute naming style in template (`my-prop` or `myProp`)',
// "More info" link
link: 'https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/attribute-hyphenation.md',
}
```
Supported inquirer types: `checkbox`, `confirm`, `input`, `password`, `list`, `rawlist`.
In addition to those, the UI supports special types that only works with it:
- `color`: displays a color picker.
#### Prompts for invocation
In your vue-cli plugin, you may already have a `prompts.js` file which asks the user a few questions when installing the plugin (with the CLI or the UI). You can add the additional UI-only fields (see above) to those prompt objects as well so they will provide more information if the user is using the UI.
**⚠️ Currently, the inquirer types which aren't supported (see above) whill not work properly in the UI.**
### Client addon
A Client addon is a JS bundle which is dynamically loaded into the cli-ui. It is useful to load custom components and routes.
@@ -518,7 +614,9 @@ ClientAddonApi.addRoutes('vue-webpack', [
Use Shared data to communicate info with custom components in an easy way.
In the plugin `ui.js`:
> For example, the Webpack dashboard shares the build stats between the UI client and the UI server using this API.
In the plugin `ui.js` (nodejs):
```js
// Set or update
@@ -554,7 +652,8 @@ const {
In the custom component:
```js
{
// Vue component
export default {
// Sync Shared data
sharedData () {
return {
@@ -605,6 +704,8 @@ This is very usefull if you create a settings component for example.
Plugin actions are calls sent between the cli-ui (browser) and plugins (nodejs).
> For example, you might have a button in a custom component (see [Client addon](#client-addon)) which calls some nodejs code on the server using this API.
In the `ui.js` file in the plugin (nodejs), you can use two methods from `PluginApi`:
```js
@@ -632,6 +733,7 @@ const { onAction, callAction } = api.namespace('vue-webpack-')
In the client addon components (browser), you have access to `$onPluginActionCalled`, `$onPluginActionResolved` and `$callPluginAction`:
```js
// Vue component
export default {
created () {
this.$onPluginActionCalled(action => {
@@ -780,6 +882,10 @@ locales.keys().forEach(key => {
})
```
#### Help translate the main UI!
See [how to help translating the main UI](./localization.md).
### Hooks
Hooks allows to react to certain cli-ui events.