Skip to content

Commit 1c8f195

Browse files
authored
refactor(ui): Config & task icons (#1450)
BREAKING CHANGE: - `file-icon` for the configurations is removed - Configuration objects `icon` option changed and is now working differently: you can either use a material icon code or a custom image (see Public static files in the UI Plugin docs). - Task objects have a new `icon` option wich works exactly the same - By default, if no icon is provided for either the config or the task, the corresponding vue-cli plugin logo will be used instead (if any).
1 parent 0ba111e commit 1c8f195

File tree

21 files changed

+91
-68
lines changed

21 files changed

+91
-68
lines changed

docs/plugin-dev-ui.md

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,18 @@ api.describeConfig({
114114

115115
#### Config icon
116116

117-
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.
117+
It can be either a [Material icon](https://material.io/tools/icons) code or a custom image (see [Public static files](#public-static-files)):
118118

119119
```js
120120
api.describeConfig({
121121
/* ... */
122-
// Icon generated using file-icons
123-
icon: '.eslintrc.json'
122+
// Config icon
123+
icon: 'application_settings'
124124
})
125125
```
126126

127+
If you don't specify an icon, the plugin logo will be displayed if any (see [Logo](#logo)).
128+
127129
#### Config file
128130

129131
By default, a configuration UI might read and write to a configuration file, for example `.eslintrc.js`.
@@ -253,6 +255,20 @@ api.describeTask({
253255
})
254256
```
255257

258+
#### Task icon
259+
260+
It can be either a [Material icon](https://material.io/tools/icons) code or a custom image (see [Public static files](#public-static-files)):
261+
262+
```js
263+
api.describeTask({
264+
/* ... */
265+
// Task icon
266+
icon: 'application_settings'
267+
})
268+
```
269+
270+
If you don't specify an icon, the plugin logo will be displayed if any (see [Logo](#logo)).
271+
256272
#### Tasks parameters
257273

258274
You can add prompts to modify the command arguments. They will be displayed in a 'Parameters' modal.
@@ -912,4 +928,12 @@ You may need to expose some static files over the cli-ui builtin HTTP server (ty
912928

913929
Any file in an optional `ui-public` folder in the root of the plugin package folder will be exposed to the `/_plugin/:id/*` HTTP route.
914930

915-
For example, if you put a `my-logo.png` file into the `my-package/ui-public/` folder, it will be available with the `http://localhost:8000/_plugin/my-package/my-logo.png` URL when the cli-ui loads the plugin.
931+
For example, if you put a `my-logo.png` file into the `my-package/ui-public/` folder, it will be available with the `/_plugin/my-package/my-logo.png` URL when the cli-ui loads the plugin.
932+
933+
```js
934+
api.describeConfig({
935+
/* ... */
936+
// Custom image
937+
icon: '/_plugin/my-package/my-logo.png'
938+
})
939+
```

packages/@vue/cli-plugin-eslint/ui.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ module.exports = api => {
55
name: 'ESLint configuration',
66
description: 'eslint.config.eslint.description',
77
link: 'https://github.com/vuejs/eslint-plugin-vue',
8-
icon: '.eslintrc.json',
98
files: {
109
json: ['.eslintrc', '.eslintrc.json'],
1110
js: ['.eslintrc.js'],
@@ -181,7 +180,6 @@ module.exports = api => {
181180
name: 'ESLint extra',
182181
description: 'eslint.config.eslint-extra.description',
183182
link: 'https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint#configuration',
184-
icon: '.eslintrc.json',
185183
files: {
186184
js: ['vue.config.js']
187185
},

packages/@vue/cli-plugin-pwa/ui.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ module.exports = api => {
3232
name: 'PWA',
3333
description: 'pwa.config.pwa.description',
3434
link: 'https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa#configuration',
35-
icon: 'mobile.xm',
3635
files: {
3736
js: ['vue.config.js']
3837
},
Loading
Loading

packages/@vue/cli-service/ui.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ module.exports = api => {
4848
match: /vue-cli-service serve/,
4949
description: 'vue-webpack.tasks.serve.description',
5050
link: 'https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#serve',
51+
icon: '/_plugin/%40vue%2Fcli-service/webpack-logo.png',
5152
prompts: [
5253
{
5354
name: 'open',
@@ -120,6 +121,7 @@ module.exports = api => {
120121
match: /vue-cli-service build/,
121122
description: 'vue-webpack.tasks.build.description',
122123
link: 'https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#build',
124+
icon: '/_plugin/%40vue%2Fcli-service/webpack-logo.png',
123125
prompts: [
124126
{
125127
name: 'mode',
@@ -210,6 +212,7 @@ module.exports = api => {
210212
command: 'vue-cli-service inspect',
211213
description: 'vue-webpack.tasks.inspect.description',
212214
link: 'https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md#inspecting-the-projects-webpack-config',
215+
icon: '/_plugin/%40vue%2Fcli-service/webpack-inspect-logo.png',
213216
prompts: [
214217
{
215218
name: 'mode',

packages/@vue/cli-ui/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
"cross-env": "^5.1.5",
5555
"eslint": "^4.16.0",
5656
"eslint-plugin-graphql": "^2.1.1",
57-
"file-icons-js": "^1.0.3",
5857
"lint-staged": "^6.0.0",
5958
"portal-vue": "^1.3.0",
6059
"rimraf": "^2.6.2",

packages/@vue/cli-ui/src/App.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ export default {
3030

3131
<style lang="stylus">
3232
@import "~@vue/ui/dist/vue-ui.css"
33-
@import "~file-icons-js/css/style.css"
3433
@import "~@/style/main"
3534
</style>
3635

packages/@vue/cli-ui/src/components/ConfigurationItem.vue

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
>
99
<div class="content">
1010
<ItemLogo
11-
:file-icon="iconClass"
11+
:image="configuration.icon || (configuration.plugin && configuration.plugin.logo)"
12+
fallback-icon="settings_applications"
1213
/>
1314

1415
<ListItemInfo
@@ -21,8 +22,6 @@
2122
</template>
2223

2324
<script>
24-
import icons from 'file-icons-js'
25-
2625
export default {
2726
props: {
2827
configuration: {
@@ -34,21 +33,6 @@ export default {
3433
type: Boolean,
3534
default: false
3635
}
37-
},
38-
39-
computed: {
40-
iconClass () {
41-
return icons.getClassWithColor(this.getFileName(this.configuration.icon) || this.configuration.id) || 'gear-icon medium-blue'
42-
}
43-
},
44-
45-
methods: {
46-
getFileName (icon) {
47-
if (icon) {
48-
if (!icon.includes('.')) return `f.${icon}`
49-
return icon
50-
}
51-
}
5236
}
5337
}
5438
</script>

packages/@vue/cli-ui/src/components/ItemLogo.vue

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,16 @@
1414
icon="done"
1515
/>
1616
<img
17-
v-else-if="imageEnabled && !error"
17+
v-else-if="!isMaterialIcon && !error"
1818
class="image"
19-
:src="imageUrl"
20-
:key="imageUrl"
19+
:src="image"
20+
:key="image"
2121
@load="loaded = true"
2222
@error="error = true"
2323
>
24-
<div
25-
v-else-if="fileIcon"
26-
class="dynamic-file-icon"
27-
:class="fileIcon"
28-
/>
2924
<VueIcon
3025
v-else
31-
:icon="icon"
26+
:icon="error || !image ? fallbackIcon : image"
3227
/>
3328
</div>
3429
</div>
@@ -38,18 +33,13 @@
3833
export default {
3934
props: {
4035
image: {
41-
type: String,
42-
default: null
43-
},
44-
45-
icon: {
4636
type: String,
4737
default: 'widgets'
4838
},
4939
50-
fileIcon: {
40+
fallbackIcon: {
5141
type: String,
52-
default: null
42+
default: 'image'
5343
},
5444
5545
selected: {
@@ -66,12 +56,8 @@ export default {
6656
},
6757
6858
computed: {
69-
imageEnabled () {
70-
return this.image || (this.icon && this.icon.indexOf('.') !== -1)
71-
},
72-
73-
imageUrl () {
74-
return this.image || this.icon
59+
isMaterialIcon () {
60+
return /^[a-z0-9_]+$/.test(this.image)
7561
}
7662
},
7763
@@ -112,10 +98,6 @@ export default {
11298
>>> svg
11399
fill rgba($color-text-light, .3)
114100
115-
.dynamic-file-icon
116-
&::before
117-
font-size 24px
118-
119101
&.vuejs
120102
.wrapper
121103
background lighten($vue-ui-color-primary, 70%)

packages/@vue/cli-ui/src/components/ProjectPluginItem.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
<template>
22
<div class="project-plugin-item list-item">
33
<div class="content">
4-
<ItemLogo :image="pluginLogo && pluginLogo.logo"/>
4+
<ItemLogo
5+
:image="pluginLogo && pluginLogo.logo"
6+
fallback-icon="widgets"
7+
/>
58

69
<ListItemInfo
710
:name="plugin.id"

packages/@vue/cli-ui/src/components/TaskItem.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
>
1212
<div class="content">
1313
<ItemLogo
14-
:icon="iconData.icon"
14+
:image="logo ? logo : iconData.icon"
1515
:class="iconData.class"
1616
v-tooltip="status"
1717
/>
@@ -56,6 +56,10 @@ export default {
5656
5757
iconData () {
5858
return icons[this.task.status]
59+
},
60+
61+
logo () {
62+
return this.task.icon || (this.task.plugin && this.task.plugin.logo)
5963
}
6064
},
6165

packages/@vue/cli-ui/src/graphql-api/api/PluginApi.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ class PluginApi {
5959
describeConfig (options) {
6060
try {
6161
validateConfiguration(options)
62-
this.configurations.push(options)
62+
this.configurations.push({
63+
...options,
64+
pluginId: this.pluginId
65+
})
6366
} catch (e) {
6467
logs.add({
6568
type: 'error',
@@ -79,7 +82,10 @@ class PluginApi {
7982
describeTask (options) {
8083
try {
8184
validateDescribeTask(options)
82-
this.describedTasks.push(options)
85+
this.describedTasks.push({
86+
...options,
87+
pluginId: this.pluginId
88+
})
8389
} catch (e) {
8490
logs.add({
8591
type: 'error',
@@ -111,7 +117,10 @@ class PluginApi {
111117
addTask (options) {
112118
try {
113119
validateAddTask(options)
114-
this.addedTasks.push(options)
120+
this.addedTasks.push({
121+
...options,
122+
pluginId: this.pluginId
123+
})
115124
} catch (e) {
116125
logs.add({
117126
type: 'error',
@@ -143,7 +152,10 @@ class PluginApi {
143152
if (options.url && options.path) {
144153
throw new Error(`'url' and 'path' can't be defined at the same time.`)
145154
}
146-
this.clientAddons.push(options)
155+
this.clientAddons.push({
156+
...options,
157+
pluginId: this.pluginId
158+
})
147159
} catch (e) {
148160
logs.add({
149161
type: 'error',
@@ -164,7 +176,10 @@ class PluginApi {
164176
addView (options) {
165177
try {
166178
validateView(options)
167-
this.views.push(options)
179+
this.views.push({
180+
...options,
181+
pluginId: this.pluginId
182+
})
168183
} catch (e) {
169184
logs.add({
170185
type: 'error',

packages/@vue/cli-ui/src/graphql-api/api/task.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const { createSchema, validateSync } = require('@vue/cli-shared-utils')
33
const schema = joi => ({
44
description: joi.string(),
55
link: joi.string().uri(),
6+
icon: joi.string(),
67
prompts: joi.array(),
78
views: joi.array().items(joi.object({
89
id: joi.string().required(),

packages/@vue/cli-ui/src/graphql-api/connectors/client-addons.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ function getUrl (addon, context) {
4545

4646
function serve (req, res) {
4747
const { id, 0: file } = req.params
48-
const addon = findOne(id)
48+
const addon = findOne(decodeURIComponent(id))
4949
if (addon && addon.path) {
5050
const basePath = resolveModuleRoot(require.resolve(addon.path))
5151
if (basePath) {

packages/@vue/cli-ui/src/graphql-api/connectors/plugins.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ async function callAction ({ id, params }, context) {
404404

405405
function serve (req, res) {
406406
const { id, 0: file } = req.params
407-
const basePath = id === '.' ? cwd.get() : getPath(id)
407+
const basePath = id === '.' ? cwd.get() : getPath(decodeURIComponent(id))
408408
if (basePath) {
409409
res.sendFile(path.join(basePath, 'ui-public', file))
410410
return

packages/@vue/cli-ui/src/graphql-api/schema/configuration.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const gql = require('graphql-tag')
22
// Connectors
33
const configurations = require('../connectors/configurations')
4+
const plugins = require('../connectors/plugins')
45

56
exports.types = gql`
67
extend type Query {
@@ -20,12 +21,14 @@ type Configuration implements DescribedEntity {
2021
link: String
2122
icon: String
2223
prompts: [Prompt]
24+
plugin: Plugin
2325
}
2426
`
2527

2628
exports.resolvers = {
2729
Configuration: {
28-
prompts: (configuration, args, context) => configurations.getPrompts(configuration.id, context)
30+
prompts: (configuration, args, context) => configurations.getPrompts(configuration.id, context),
31+
plugin: (configuration, args, context) => plugins.findOne(configuration.pluginId, context)
2932
},
3033

3134
Query: {

0 commit comments

Comments
 (0)