mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-03-15 13:40:59 -05:00
feat(ui): new hooks for plugins
This commit is contained in:
@@ -1075,6 +1075,66 @@ api.onPluginReload((project) => {
|
||||
})
|
||||
```
|
||||
|
||||
### onConfigRead
|
||||
|
||||
Called when a configuration screen is open or refreshed.
|
||||
|
||||
```js
|
||||
api.onConfigRead(({ config, data, onReadData, tabs, cwd }) => {
|
||||
console.log(config.id)
|
||||
})
|
||||
```
|
||||
|
||||
### onConfigWrite
|
||||
|
||||
Called when the user saves in a configuration screen.
|
||||
|
||||
```js
|
||||
api.onConfigWrite(({ config, data, changedFields, cwd }) => {
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
### onTaskOpen
|
||||
|
||||
Called when the user open a task details pane.
|
||||
|
||||
```js
|
||||
api.onTaskOpen(({ task, cwd }) => {
|
||||
console.log(task.id)
|
||||
})
|
||||
```
|
||||
|
||||
### onTaskRun
|
||||
|
||||
Called when the user run a task.
|
||||
|
||||
```js
|
||||
api.onTaskRun(({ task, args, child, cwd }) => {
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
### onTaskExit
|
||||
|
||||
Called when a task exists. It can be called both called on success or failure.
|
||||
|
||||
```js
|
||||
api.onTaskExit(({ task, args, child, signal, code, cwd }) => {
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
### onViewOpen
|
||||
|
||||
Called when the users open a view (like 'Plugins', 'Configurations' or 'Tasks').
|
||||
|
||||
```js
|
||||
api.onViewOpen(({ view, cwd }) => {
|
||||
console.log(view.id)
|
||||
})
|
||||
```
|
||||
|
||||
## Public static files
|
||||
|
||||
You may need to expose some static files over the cli-ui builtin HTTP server (typically if you want to specify an icon to a custom view).
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
|
||||
extends: [
|
||||
'plugin:vue/essential',
|
||||
'@vue/standard'
|
||||
],
|
||||
|
||||
globals: {
|
||||
ClientAddonApi: false
|
||||
},
|
||||
|
||||
plugins: [
|
||||
'graphql'
|
||||
]
|
||||
],
|
||||
|
||||
rules: {
|
||||
'vue/html-self-closing': 'error'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
>
|
||||
<div class="content">
|
||||
<VueGroup
|
||||
v-model="currentView"
|
||||
v-model="currentViewName"
|
||||
class="vertical small-indicator left-indicator primary"
|
||||
indicator
|
||||
>
|
||||
@@ -30,6 +30,7 @@ import VIEWS from '../graphql/views.gql'
|
||||
import VIEW_ADDED from '../graphql/viewAdded.gql'
|
||||
import VIEW_REMOVED from '../graphql/viewRemoved.gql'
|
||||
import VIEW_CHANGED from '../graphql/viewChanged.gql'
|
||||
import VIEW_OPEN from '../graphql/viewOpen.gql'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
@@ -90,12 +91,16 @@ export default {
|
||||
},
|
||||
|
||||
computed: {
|
||||
currentView: {
|
||||
currentView () {
|
||||
const currentRoute = this.$route
|
||||
return this.views.find(
|
||||
item => isIncludedRoute(currentRoute, this.$router.resolve({ name: item.name }).route)
|
||||
)
|
||||
},
|
||||
|
||||
currentViewName: {
|
||||
get () {
|
||||
const currentRoute = this.$route
|
||||
const view = this.views.find(
|
||||
item => isIncludedRoute(currentRoute, this.$router.resolve({ name: item.name }).route)
|
||||
)
|
||||
const view = this.currentView
|
||||
return view && view.name
|
||||
},
|
||||
set (name) {
|
||||
@@ -104,6 +109,22 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
currentView: {
|
||||
handler (value, oldValue) {
|
||||
if (!value) return
|
||||
if (oldValue && value.id === oldValue.id) return
|
||||
this.$apollo.mutate({
|
||||
mutation: VIEW_OPEN,
|
||||
variables: {
|
||||
id: value.id
|
||||
}
|
||||
})
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
</div>
|
||||
|
||||
<div class="view">
|
||||
<div ref="render" class="xterm-render"></div>
|
||||
<div ref="render" class="xterm-render"/>
|
||||
</div>
|
||||
|
||||
<resize-observer v-if="autoSize" @notify="fit"/>
|
||||
|
||||
@@ -21,8 +21,16 @@ class PluginApi {
|
||||
this.project = null
|
||||
this.plugins = plugins
|
||||
// Hooks
|
||||
this.projectOpenHooks = []
|
||||
this.pluginReloadHooks = []
|
||||
this.hooks = {
|
||||
projectOpen: [],
|
||||
pluginReload: [],
|
||||
configRead: [],
|
||||
configWrite: [],
|
||||
taskRun: [],
|
||||
taskExit: [],
|
||||
taskOpen: [],
|
||||
viewOpen: []
|
||||
}
|
||||
// Data
|
||||
this.configurations = []
|
||||
this.describedTasks = []
|
||||
@@ -43,7 +51,7 @@ class PluginApi {
|
||||
cb(this.project)
|
||||
return
|
||||
}
|
||||
this.projectOpenHooks.push(cb)
|
||||
this.hooks.projectOpen.push(cb)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +60,61 @@ class PluginApi {
|
||||
* @param {function} cb Handler
|
||||
*/
|
||||
onPluginReload (cb) {
|
||||
this.pluginReloadHooks.push(cb)
|
||||
this.hooks.pluginReload.push(cb)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an handler called when a config is red.
|
||||
*
|
||||
* @param {function} cb Handler
|
||||
*/
|
||||
onConfigRead (cb) {
|
||||
this.hooks.configRead.push(cb)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an handler called when a config is written.
|
||||
*
|
||||
* @param {function} cb Handler
|
||||
*/
|
||||
onConfigWrite (cb) {
|
||||
this.hooks.configWrite.push(cb)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an handler called when a task is run.
|
||||
*
|
||||
* @param {function} cb Handler
|
||||
*/
|
||||
onTaskRun (cb) {
|
||||
this.hooks.taskRun.push(cb)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an handler called when a task has exited.
|
||||
*
|
||||
* @param {function} cb Handler
|
||||
*/
|
||||
onTaskExit (cb) {
|
||||
this.hooks.taskExit.push(cb)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an handler called when the user opens one task details.
|
||||
*
|
||||
* @param {function} cb Handler
|
||||
*/
|
||||
onTaskOpen (cb) {
|
||||
this.hooks.taskOpen.push(cb)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an handler called when a view is open.
|
||||
*
|
||||
* @param {function} cb Handler
|
||||
*/
|
||||
onViewOpen (cb) {
|
||||
this.hooks.viewOpen.push(cb)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -156,18 +156,18 @@ async function getPromptTabs (id, context) {
|
||||
}
|
||||
|
||||
// API
|
||||
const configData = await config.onRead({
|
||||
const onReadData = await config.onRead({
|
||||
cwd: cwd.get(),
|
||||
data
|
||||
})
|
||||
|
||||
let tabs = configData.tabs
|
||||
let tabs = onReadData.tabs
|
||||
if (!tabs) {
|
||||
tabs = [
|
||||
{
|
||||
id: '__default',
|
||||
label: 'Default',
|
||||
prompts: configData.prompts
|
||||
prompts: onReadData.prompts
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -178,10 +178,19 @@ async function getPromptTabs (id, context) {
|
||||
tabId: tab.id
|
||||
}))
|
||||
}
|
||||
if (configData.answers) {
|
||||
await prompts.setAnswers(configData.answers)
|
||||
if (onReadData.answers) {
|
||||
await prompts.setAnswers(onReadData.answers)
|
||||
}
|
||||
await prompts.start()
|
||||
|
||||
plugins.callHook('configRead', [{
|
||||
config,
|
||||
data,
|
||||
onReadData,
|
||||
tabs,
|
||||
cwd: cwd.get()
|
||||
}], context)
|
||||
|
||||
return tabs
|
||||
}
|
||||
return []
|
||||
@@ -242,6 +251,14 @@ async function save (id, context) {
|
||||
})
|
||||
|
||||
writeData({ config, data, changedFields }, context)
|
||||
|
||||
plugins.callHook('configWrite', [{
|
||||
config,
|
||||
data,
|
||||
changedFields,
|
||||
cwd: cwd.get()
|
||||
}], context)
|
||||
|
||||
current = {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,12 +118,14 @@ function resetPluginApi (context) {
|
||||
if (!project) return
|
||||
if (projectId !== project.id) {
|
||||
projectId = project.id
|
||||
log('Hook onProjectOpen', pluginApi.projectOpenHooks.length, 'handlers')
|
||||
pluginApi.projectOpenHooks.forEach(fn => fn(project, projects.getLast(context)))
|
||||
callHook('projectOpen', [project, projects.getLast(context)], context)
|
||||
pluginApi.project = project
|
||||
} else {
|
||||
log('Hook onPluginReload', pluginApi.pluginReloadHooks.length, 'handlers')
|
||||
pluginApi.pluginReloadHooks.forEach(fn => fn(project))
|
||||
callHook('pluginReload', [project], context)
|
||||
|
||||
// View open hook
|
||||
const currentView = views.getCurrent()
|
||||
if (currentView) views.open(currentView.id)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -147,6 +149,12 @@ function runPluginApi (id, context, fileName = 'ui') {
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function callHook (id, args, context) {
|
||||
const fns = pluginApi.hooks[id]
|
||||
log(`Hook ${id}`, fns.length, 'handlers')
|
||||
fns.forEach(fn => fn(...args))
|
||||
}
|
||||
|
||||
function findOne (id, context) {
|
||||
return plugins.find(
|
||||
p => p.id === id
|
||||
@@ -472,5 +480,6 @@ module.exports = {
|
||||
getApi,
|
||||
finishInstall,
|
||||
callAction,
|
||||
callHook,
|
||||
serve
|
||||
}
|
||||
|
||||
@@ -348,6 +348,15 @@ async function run (id, context) {
|
||||
icon: 'done'
|
||||
})
|
||||
}
|
||||
|
||||
plugins.callHook('taskExit', [{
|
||||
task,
|
||||
args,
|
||||
child,
|
||||
cwd: cwd.get(),
|
||||
signal,
|
||||
code
|
||||
}], context)
|
||||
}
|
||||
|
||||
child.on('exit', onExit)
|
||||
@@ -360,6 +369,13 @@ async function run (id, context) {
|
||||
cwd: cwd.get()
|
||||
})
|
||||
}
|
||||
|
||||
plugins.callHook('taskRun', [{
|
||||
task,
|
||||
args,
|
||||
child,
|
||||
cwd: cwd.get()
|
||||
}], context)
|
||||
}
|
||||
return task
|
||||
}
|
||||
@@ -394,6 +410,15 @@ function clearLogs (id, context) {
|
||||
return task
|
||||
}
|
||||
|
||||
function open (id, context) {
|
||||
const task = findOne(id, context)
|
||||
plugins.callHook('taskOpen', [{
|
||||
task,
|
||||
cwd: cwd.get()
|
||||
}], context)
|
||||
return true
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
list,
|
||||
findOne,
|
||||
@@ -401,5 +426,6 @@ module.exports = {
|
||||
run,
|
||||
stop,
|
||||
updateOne,
|
||||
clearLogs
|
||||
clearLogs,
|
||||
open
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ const cwd = require('./cwd')
|
||||
// Subs
|
||||
const channels = require('../channels')
|
||||
|
||||
let currentView
|
||||
|
||||
function createViewsSet () {
|
||||
// Builtin views
|
||||
return [
|
||||
@@ -116,6 +118,17 @@ function removeBadge ({ viewId, badgeId }, context) {
|
||||
}
|
||||
}
|
||||
|
||||
function open (id, context) {
|
||||
const view = findOne(id)
|
||||
currentView = view
|
||||
const plugins = require('./plugins')
|
||||
plugins.callHook('viewOpen', [{
|
||||
view,
|
||||
cwd: cwd.get()
|
||||
}], context)
|
||||
return true
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
list,
|
||||
findOne,
|
||||
@@ -123,5 +136,7 @@ module.exports = {
|
||||
remove,
|
||||
update,
|
||||
addBadge,
|
||||
removeBadge
|
||||
removeBadge,
|
||||
open,
|
||||
getCurrent: () => currentView
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ extend type Mutation {
|
||||
taskRun (id: ID!): Task
|
||||
taskStop (id: ID!): Task
|
||||
taskLogsClear (id: ID!): Task
|
||||
taskOpen (id: ID!): Boolean
|
||||
}
|
||||
|
||||
extend type Subscription {
|
||||
@@ -79,7 +80,8 @@ exports.resolvers = {
|
||||
Mutation: {
|
||||
taskRun: (root, { id }, context) => tasks.run(id, context),
|
||||
taskStop: (root, { id }, context) => tasks.stop(id, context),
|
||||
taskLogsClear: (root, { id }, context) => tasks.clearLogs(id, context)
|
||||
taskLogsClear: (root, { id }, context) => tasks.clearLogs(id, context),
|
||||
taskOpen: (root, { id }, context) => tasks.open(id, context)
|
||||
},
|
||||
|
||||
Subscription: {
|
||||
|
||||
@@ -9,6 +9,10 @@ extend type Query {
|
||||
views: [View]
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
viewOpen (id: ID!): Boolean
|
||||
}
|
||||
|
||||
extend type Subscription {
|
||||
viewAdded: View
|
||||
viewRemoved: View
|
||||
@@ -47,6 +51,10 @@ exports.resolvers = {
|
||||
views: (root, args, context) => views.list(context)
|
||||
},
|
||||
|
||||
Mutation: {
|
||||
viewOpen: (root, { id }, context) => views.open(id, context)
|
||||
},
|
||||
|
||||
Subscription: {
|
||||
viewAdded: {
|
||||
subscribe: (parent, args, { pubsub }) => pubsub.asyncIterator(channels.VIEW_ADDED)
|
||||
|
||||
3
packages/@vue/cli-ui/src/graphql/taskOpen.gql
Normal file
3
packages/@vue/cli-ui/src/graphql/taskOpen.gql
Normal file
@@ -0,0 +1,3 @@
|
||||
mutation taskOpen ($id: ID!) {
|
||||
taskOpen (id: $id)
|
||||
}
|
||||
3
packages/@vue/cli-ui/src/graphql/viewOpen.gql
Normal file
3
packages/@vue/cli-ui/src/graphql/viewOpen.gql
Normal file
@@ -0,0 +1,3 @@
|
||||
mutation viewOpen ($id: ID!) {
|
||||
viewOpen (id: $id)
|
||||
}
|
||||
@@ -141,6 +141,7 @@ import TASK_RUN from '../graphql/taskRun.gql'
|
||||
import TASK_STOP from '../graphql/taskStop.gql'
|
||||
import TASK_LOGS_CLEAR from '../graphql/taskLogsClear.gql'
|
||||
import TASK_LOG_ADDED from '../graphql/taskLogAdded.gql'
|
||||
import TASK_OPEN from '../graphql/taskOpen.gql'
|
||||
|
||||
export default {
|
||||
name: 'ProjectTaskDetails',
|
||||
@@ -251,10 +252,24 @@ export default {
|
||||
this.showParameters = false
|
||||
this.currentView = '_output'
|
||||
this.$_init = false
|
||||
this.open()
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.open()
|
||||
},
|
||||
|
||||
methods: {
|
||||
open () {
|
||||
this.$apollo.mutate({
|
||||
mutation: TASK_OPEN,
|
||||
variables: {
|
||||
id: this.id
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
runTask () {
|
||||
this.$apollo.mutate({
|
||||
mutation: TASK_RUN,
|
||||
|
||||
@@ -39,4 +39,24 @@ module.exports = api => {
|
||||
|
||||
return 'meow'
|
||||
})
|
||||
|
||||
// Hooks
|
||||
api.onViewOpen(({ view }) => {
|
||||
console.log('onViewOpen', view.id)
|
||||
})
|
||||
api.onTaskOpen(({ task }) => {
|
||||
console.log('onTaskOpen', task.id)
|
||||
})
|
||||
api.onTaskRun(({ task }) => {
|
||||
console.log('onTaskRun', task.id)
|
||||
})
|
||||
api.onTaskExit(({ task }) => {
|
||||
console.log('onTaskExit', task.id)
|
||||
})
|
||||
api.onConfigRead(({ config }) => {
|
||||
console.log('onConfigRead', config.id)
|
||||
})
|
||||
api.onConfigWrite(({ config }) => {
|
||||
console.log('onConfigWrite', config.id)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@ module.exports = {
|
||||
apolloEngine: false,
|
||||
graphqlTimeout: 1000000
|
||||
},
|
||||
|
||||
configureWebpack: {
|
||||
resolve: {
|
||||
symlinks: false
|
||||
}
|
||||
},
|
||||
|
||||
chainWebpack: config => {
|
||||
config.module.rule('stylus').oneOf('vue').use('postcss-loader')
|
||||
.tap(options =>
|
||||
@@ -21,5 +23,7 @@ module.exports = {
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
lintOnSave: undefined
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user