mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-02-06 15:08:27 -06:00
feat(ui): PluginApi: configurations
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
module.exports = api => {
|
||||
// Config file
|
||||
api.describeConfig({
|
||||
id: 'eslintrc',
|
||||
name: 'ESLint configuration',
|
||||
description: 'Error checking & Code quality',
|
||||
link: 'https://eslint.org',
|
||||
icon: '.eslintrc.json',
|
||||
files: {
|
||||
json: ['eslintrc', 'eslintrc.json'],
|
||||
js: ['eslintrc.js'],
|
||||
json: ['.eslintrc', '.eslintrc.json'],
|
||||
js: ['.eslintrc.js'],
|
||||
package: 'eslintConfig'
|
||||
},
|
||||
onRead: ({ data }) => {
|
||||
@@ -21,7 +23,7 @@ module.exports = api => {
|
||||
choices: [
|
||||
{
|
||||
name: 'Off',
|
||||
value: 'off'
|
||||
value: JSON.stringify('off')
|
||||
},
|
||||
{
|
||||
name: 'Never',
|
||||
@@ -40,14 +42,14 @@ module.exports = api => {
|
||||
value: JSON.stringify(['error', 'only-multiline'])
|
||||
}
|
||||
],
|
||||
value: JSON.stringify(data.rules['comma-dangle'] || ['error', 'never'])
|
||||
value: JSON.stringify(data.rules && data.rules['comma-dangle'] || ['error', 'never'])
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
onWrite: ({ file, answers }) => {
|
||||
file.assignData({
|
||||
'rules.comma-dangle': answers.rules.commaDangle
|
||||
file.setData({
|
||||
'rules.comma-dangle': JSON.parse(answers.rules.commaDangle)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
"plugin:vue/essential",
|
||||
"@vue/standard"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"name": "@vue/cli-ui",
|
||||
"version": "3.0.0-beta.6",
|
||||
"author": "Guillaume Chau",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
@@ -19,8 +21,10 @@
|
||||
"apollo-link-state": "^0.4.0",
|
||||
"apollo-link-ws": "^1.0.0",
|
||||
"apollo-utilities": "^1.0.9",
|
||||
"clone": "^1.0.4",
|
||||
"file-icons-js": "^1.0.3",
|
||||
"graphql": "^0.13.0",
|
||||
"js-yaml": "^3.11.0",
|
||||
"lowdb": "^1.0.0",
|
||||
"lru-cache": "^4.1.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
|
||||
64
packages/@vue/cli-ui/src/components/ConfigurationItem.vue
Normal file
64
packages/@vue/cli-ui/src/components/ConfigurationItem.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div
|
||||
class="configuration-item list-item"
|
||||
:class="{
|
||||
selected
|
||||
}"
|
||||
>
|
||||
<div class="content">
|
||||
<ItemLogo
|
||||
:file-icon="iconClass"
|
||||
/>
|
||||
|
||||
<ListItemInfo
|
||||
:name="configuration.name"
|
||||
:description="configuration.description"
|
||||
:selected="selected"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import icons from 'file-icons-js'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
configuration: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
|
||||
selected: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
iconClass () {
|
||||
return icons.getClassWithColor(this.configuration.icon || this.configuration.id) || 'gear-icon medium-blue'
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@import "~@/style/imports"
|
||||
|
||||
.configuration-item
|
||||
padding $padding-item
|
||||
|
||||
.content
|
||||
h-box()
|
||||
box-center()
|
||||
|
||||
.list-item-info
|
||||
flex 100% 1 1
|
||||
width 0
|
||||
|
||||
>>> .description
|
||||
white-space nowrap
|
||||
overflow hidden
|
||||
text-overflow ellipsis
|
||||
</style>
|
||||
@@ -21,6 +21,11 @@
|
||||
@load="loaded = true"
|
||||
@error="error = true"
|
||||
>
|
||||
<div
|
||||
v-else-if="fileIcon"
|
||||
class="dynamic-file-icon"
|
||||
:class="fileIcon"
|
||||
/>
|
||||
<VueIcon
|
||||
v-else
|
||||
:icon="icon"
|
||||
@@ -42,6 +47,11 @@ export default {
|
||||
default: 'widgets'
|
||||
},
|
||||
|
||||
fileIcon: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
|
||||
selected: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
@@ -92,6 +102,10 @@ export default {
|
||||
>>> svg
|
||||
fill rgba($color-text-light, .3)
|
||||
|
||||
.dynamic-file-icon
|
||||
&::before
|
||||
font-size 24px
|
||||
|
||||
&.vuejs
|
||||
.wrapper
|
||||
background lighten($vue-ui-color-primary, 70%)
|
||||
|
||||
@@ -29,7 +29,7 @@ const BUILTIN_ROUTES = [
|
||||
tooltip: 'plugins'
|
||||
},
|
||||
{
|
||||
name: 'project-configuration',
|
||||
name: 'project-configurations',
|
||||
icon: 'settings_applications',
|
||||
tooltip: 'configuration'
|
||||
},
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const yaml = require('js-yaml')
|
||||
const clone = require('clone')
|
||||
// Connectors
|
||||
const cwd = require('./cwd')
|
||||
const plugins = require('./plugins')
|
||||
const folders = require('./folders')
|
||||
const prompts = require('./prompts')
|
||||
// Utils
|
||||
const { set } = require('../../util/object')
|
||||
|
||||
const fileTypes = ['js', 'json', 'yaml']
|
||||
let current = {}
|
||||
|
||||
function list (context) {
|
||||
return plugins.getApi().configurations
|
||||
}
|
||||
|
||||
function findOne (id, context) {
|
||||
return list(context).find(
|
||||
c => c.id === id
|
||||
)
|
||||
}
|
||||
|
||||
function findFile (config, context) {
|
||||
if (config.files.package) {
|
||||
const pkg = folders.readPackage(cwd.get(), context)
|
||||
const data = pkg[config.files.package]
|
||||
if (data) {
|
||||
return { type: 'package', path: path.join(cwd.get(), 'package.json') }
|
||||
}
|
||||
}
|
||||
|
||||
for (const type of fileTypes) {
|
||||
const files = config.files[type]
|
||||
if (files) {
|
||||
for (const file of files) {
|
||||
const resolvedFile = path.resolve(cwd.get(), file)
|
||||
if (fs.existsSync(resolvedFile)) {
|
||||
return { type, path: resolvedFile }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function readData (config, context) {
|
||||
const file = findFile(config, context)
|
||||
if (file) {
|
||||
if (file.type === 'package') {
|
||||
const pkg = folders.readPackage(cwd.get(), context)
|
||||
return pkg[config.files.package]
|
||||
} else {
|
||||
const rawContent = fs.readFileSync(file.path, { encoding: 'utf8' })
|
||||
if (file.type === 'json') {
|
||||
return JSON.parse(rawContent)
|
||||
} else if (file.type === 'yaml') {
|
||||
return yaml.safeLoad(rawContent)
|
||||
} else if (file.type === 'js') {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeData ({ config, data }, context) {
|
||||
const file = findFile(config, context)
|
||||
if (file) {
|
||||
let rawContent
|
||||
if (file.type === 'package') {
|
||||
const pkg = folders.readPackage(cwd.get(), context)
|
||||
pkg[config.files.package] = data
|
||||
rawContent = JSON.stringify(pkg, null, 2)
|
||||
} else {
|
||||
if (file.type === 'json') {
|
||||
rawContent = JSON.stringify(data, null, 2)
|
||||
} else if (file.type === 'yaml') {
|
||||
rawContent = yaml.safeDump(data)
|
||||
} else if (file.type === 'js') {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(file.path, rawContent, { encoding: 'utf8' })
|
||||
}
|
||||
}
|
||||
|
||||
function getPrompts (id, context) {
|
||||
const config = findOne(id, context)
|
||||
if (config) {
|
||||
if (current.config !== config) {
|
||||
const data = readData(config, context)
|
||||
current = {
|
||||
config,
|
||||
data
|
||||
}
|
||||
const configData = config.onRead({
|
||||
data
|
||||
})
|
||||
prompts.reset()
|
||||
configData.prompts.forEach(prompts.add)
|
||||
if (configData.answers) {
|
||||
prompts.setAnswers(configData.answers)
|
||||
}
|
||||
prompts.start()
|
||||
}
|
||||
return prompts.list()
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
function save (id, context) {
|
||||
const config = findOne(id, context)
|
||||
if (config) {
|
||||
if (current.config === config) {
|
||||
const answers = prompts.getAnswers()
|
||||
let data = clone(current.data)
|
||||
config.onWrite({
|
||||
answers,
|
||||
data,
|
||||
file: {
|
||||
...config.file,
|
||||
assignData: newData => {
|
||||
Object.assign(data, newData)
|
||||
},
|
||||
setData: newData => {
|
||||
Object.keys(newData).forEach(key => {
|
||||
set(data, key, newData[key])
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
writeData({ config, data }, context)
|
||||
current = {}
|
||||
}
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
function cancel (id, context) {
|
||||
const config = findOne(id, context)
|
||||
if (config) {
|
||||
current = {}
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
list,
|
||||
findOne,
|
||||
getPrompts,
|
||||
save,
|
||||
cancel
|
||||
}
|
||||
@@ -80,7 +80,6 @@ function runPluginApi (id, context) {
|
||||
const module = loadModule(`${id}/ui`, cwd.get(), true)
|
||||
if (module) {
|
||||
module(pluginApi)
|
||||
console.log(`PluginApi called for ${id}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
const ObjectUtil = require('../../util/object')
|
||||
|
||||
let answers = {}
|
||||
let prompts = []
|
||||
|
||||
@@ -103,53 +105,15 @@ function getChoices (prompt) {
|
||||
}
|
||||
|
||||
function setAnswer (id, value) {
|
||||
const fields = id.split('.')
|
||||
let obj = answers
|
||||
const l = fields.length
|
||||
for (let i = 0; i < l - 1; i++) {
|
||||
const key = fields[i]
|
||||
if (!obj[key]) {
|
||||
obj[key] = {}
|
||||
}
|
||||
obj = obj[key]
|
||||
}
|
||||
obj[fields[l - 1]] = value
|
||||
ObjectUtil.set(answers, id, value)
|
||||
}
|
||||
|
||||
function getAnswer (id) {
|
||||
const fields = id.split('.')
|
||||
let obj = answers
|
||||
const l = fields.length
|
||||
for (let i = 0; i < l - 1; i++) {
|
||||
const key = fields[i]
|
||||
if (!obj[key]) {
|
||||
return undefined
|
||||
}
|
||||
obj = obj[key]
|
||||
}
|
||||
return obj[fields[l - 1]]
|
||||
ObjectUtil.get(answers, id)
|
||||
}
|
||||
|
||||
function removeAnswer (id) {
|
||||
const fields = id.split('.')
|
||||
let obj = answers
|
||||
const l = fields.length
|
||||
const objs = []
|
||||
for (let i = 0; i < l - 1; i++) {
|
||||
const key = fields[i]
|
||||
if (!obj[key]) {
|
||||
return
|
||||
}
|
||||
objs.splice(0, 0, { obj, key, value: obj[key] })
|
||||
obj = obj[key]
|
||||
}
|
||||
delete obj[fields[l - 1]]
|
||||
// Clear empty objects
|
||||
for (const { obj, key, value } of objs) {
|
||||
if (!Object.keys(value).length) {
|
||||
delete obj[key]
|
||||
}
|
||||
}
|
||||
ObjectUtil.remove(answers, id)
|
||||
}
|
||||
|
||||
function generatePrompt (data) {
|
||||
|
||||
@@ -113,11 +113,11 @@ function getPrompts (id, context) {
|
||||
|
||||
prompts.reset()
|
||||
task.prompts.forEach(prompts.add)
|
||||
|
||||
const data = getSavedData(id, context)
|
||||
if (data) {
|
||||
prompts.setAnswers(data.answers)
|
||||
}
|
||||
prompts.start()
|
||||
}
|
||||
|
||||
return prompts.list()
|
||||
|
||||
@@ -11,6 +11,7 @@ const progress = require('./connectors/progress')
|
||||
const logs = require('./connectors/logs')
|
||||
const plugins = require('./connectors/plugins')
|
||||
const tasks = require('./connectors/tasks')
|
||||
const configurations = require('./connectors/configurations')
|
||||
|
||||
// Prevent code from exiting server process
|
||||
exit.exitProcess = false
|
||||
@@ -38,6 +39,10 @@ module.exports = {
|
||||
prompts: (task, args, context) => tasks.getPrompts(task.id, context)
|
||||
},
|
||||
|
||||
Configuration: {
|
||||
prompts: (configuration, args, context) => configurations.getPrompts(configuration.id, context)
|
||||
},
|
||||
|
||||
Query: {
|
||||
cwd: () => cwd.get(),
|
||||
consoleLogs: (root, args, context) => logs.list(context),
|
||||
@@ -51,7 +56,9 @@ module.exports = {
|
||||
pluginInstallation: (root, args, context) => plugins.getInstallation(context),
|
||||
plugin: (root, { id }, context) => plugins.findOne(id, context),
|
||||
tasks: (root, args, context) => tasks.list(context),
|
||||
task: (root, { id }, context) => tasks.findOne(id, context)
|
||||
task: (root, { id }, context) => tasks.findOne(id, context),
|
||||
configurations: (root, args, context) => configurations.list(context),
|
||||
configuration: (root, { id }, context) => configurations.findOne(id, context)
|
||||
},
|
||||
|
||||
Mutation: {
|
||||
@@ -77,7 +84,9 @@ module.exports = {
|
||||
pluginUpdate: (root, { id }, context) => plugins.update(id, context),
|
||||
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),
|
||||
configurationSave: (root, { id }, context) => configurations.save(id, context),
|
||||
configurationCancel: (root, { id }, context) => configurations.cancel(id, context)
|
||||
},
|
||||
|
||||
Subscription: {
|
||||
|
||||
@@ -239,6 +239,8 @@ type Mutation {
|
||||
taskRun (id: ID!): Task
|
||||
taskStop (id: ID!): Task
|
||||
taskLogsClear (id: ID!): Task
|
||||
configurationSave (id: ID!): Configuration
|
||||
configurationCancel (id: ID!): Configuration
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
|
||||
12
packages/@vue/cli-ui/src/graphql/configuration.gql
Normal file
12
packages/@vue/cli-ui/src/graphql/configuration.gql
Normal file
@@ -0,0 +1,12 @@
|
||||
#import "./configurationFragment.gql"
|
||||
#import "./promptFragment.gql"
|
||||
|
||||
query configuration ($id: ID!) {
|
||||
configuration(id: $id) {
|
||||
...configuration
|
||||
link
|
||||
prompts {
|
||||
...prompt
|
||||
}
|
||||
}
|
||||
}
|
||||
7
packages/@vue/cli-ui/src/graphql/configurationCancel.gql
Normal file
7
packages/@vue/cli-ui/src/graphql/configurationCancel.gql
Normal file
@@ -0,0 +1,7 @@
|
||||
#import "./configurationFragment.gql"
|
||||
|
||||
mutation configurationCancel ($id: ID!) {
|
||||
configurationCancel (id: $id) {
|
||||
...configuration
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fragment configuration on Configuration {
|
||||
id
|
||||
name
|
||||
description
|
||||
icon
|
||||
}
|
||||
7
packages/@vue/cli-ui/src/graphql/configurationSave.gql
Normal file
7
packages/@vue/cli-ui/src/graphql/configurationSave.gql
Normal file
@@ -0,0 +1,7 @@
|
||||
#import "./configurationFragment.gql"
|
||||
|
||||
mutation configurationSave ($id: ID!) {
|
||||
configurationSave (id: $id) {
|
||||
...configuration
|
||||
}
|
||||
}
|
||||
7
packages/@vue/cli-ui/src/graphql/configurations.gql
Normal file
7
packages/@vue/cli-ui/src/graphql/configurations.gql
Normal file
@@ -0,0 +1,7 @@
|
||||
#import "./configurationFragment.gql"
|
||||
|
||||
query configurations {
|
||||
configurations {
|
||||
...configuration
|
||||
}
|
||||
}
|
||||
@@ -236,9 +236,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"project-configuration": {
|
||||
"project-configurations": {
|
||||
"title": "Project configuration"
|
||||
},
|
||||
"project-configuration-details": {
|
||||
"actions": {
|
||||
"cancel": "Cancel changes",
|
||||
"save": "Save changes"
|
||||
}
|
||||
},
|
||||
"project-tasks": {
|
||||
"title": "Project tasks"
|
||||
},
|
||||
|
||||
@@ -236,7 +236,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"project-configuration": {
|
||||
"project-configurations": {
|
||||
"title": "Configuration du projet"
|
||||
},
|
||||
"project-tasks": {
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"project-configuration": {
|
||||
"project-configurations": {
|
||||
"title": "プロジェクト設定"
|
||||
},
|
||||
"project-tasks": {
|
||||
|
||||
@@ -16,6 +16,12 @@ export default function ({
|
||||
).length === 0
|
||||
},
|
||||
|
||||
hasPromptsChanged () {
|
||||
return !!this.visiblePrompts.find(
|
||||
prompt => prompt.valueChanged
|
||||
)
|
||||
},
|
||||
|
||||
visiblePrompts () {
|
||||
if (!this[field]) {
|
||||
return []
|
||||
|
||||
@@ -5,7 +5,8 @@ import { apolloClient } from './vue-apollo'
|
||||
import ProjectHome from './views/ProjectHome.vue'
|
||||
import ProjectPlugins from './views/ProjectPlugins.vue'
|
||||
import ProjectPluginsAdd from './views/ProjectPluginsAdd.vue'
|
||||
import ProjectConfiguration from './views/ProjectConfiguration.vue'
|
||||
import ProjectConfigurations from './views/ProjectConfigurations.vue'
|
||||
import ProjectConfigurationDetails from './views/ProjectConfigurationDetails.vue'
|
||||
import ProjectTasks from './views/ProjectTasks.vue'
|
||||
import ProjectTaskDetails from './views/ProjectTaskDetails.vue'
|
||||
import ProjectSelect from './views/ProjectSelect.vue'
|
||||
@@ -43,8 +44,16 @@ const router = new Router({
|
||||
},
|
||||
{
|
||||
path: 'configuration',
|
||||
name: 'project-configuration',
|
||||
component: ProjectConfiguration
|
||||
name: 'project-configurations',
|
||||
component: ProjectConfigurations,
|
||||
children: [
|
||||
{
|
||||
path: ':id',
|
||||
name: 'project-configuration-details',
|
||||
component: ProjectConfigurationDetails,
|
||||
props: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'tasks',
|
||||
|
||||
49
packages/@vue/cli-ui/src/util/object.js
Normal file
49
packages/@vue/cli-ui/src/util/object.js
Normal file
@@ -0,0 +1,49 @@
|
||||
exports.set = function (target, path, value) {
|
||||
const fields = path.split('.')
|
||||
let obj = target
|
||||
const l = fields.length
|
||||
for (let i = 0; i < l - 1; i++) {
|
||||
const key = fields[i]
|
||||
if (!obj[key]) {
|
||||
obj[key] = {}
|
||||
}
|
||||
obj = obj[key]
|
||||
}
|
||||
obj[fields[l - 1]] = value
|
||||
}
|
||||
|
||||
exports.get = function (target, path) {
|
||||
const fields = path.split('.')
|
||||
let obj = target
|
||||
const l = fields.length
|
||||
for (let i = 0; i < l - 1; i++) {
|
||||
const key = fields[i]
|
||||
if (!obj[key]) {
|
||||
return undefined
|
||||
}
|
||||
obj = obj[key]
|
||||
}
|
||||
return obj[fields[l - 1]]
|
||||
}
|
||||
|
||||
exports.remove = function (target, path) {
|
||||
const fields = path.split('.')
|
||||
let obj = target
|
||||
const l = fields.length
|
||||
const objs = []
|
||||
for (let i = 0; i < l - 1; i++) {
|
||||
const key = fields[i]
|
||||
if (!obj[key]) {
|
||||
return
|
||||
}
|
||||
objs.splice(0, 0, { obj, key, value: obj[key] })
|
||||
obj = obj[key]
|
||||
}
|
||||
delete obj[fields[l - 1]]
|
||||
// Clear empty objects
|
||||
for (const { obj, key, value } of objs) {
|
||||
if (!Object.keys(value).length) {
|
||||
delete obj[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<template>
|
||||
<div class="project-configuration page">
|
||||
<ContentView
|
||||
:title="$t('views.project-configuration.title')"
|
||||
class="limit-width"
|
||||
>
|
||||
WIP
|
||||
</ContentView>
|
||||
</div>
|
||||
</template>
|
||||
109
packages/@vue/cli-ui/src/views/ProjectConfigurationDetails.vue
Normal file
109
packages/@vue/cli-ui/src/views/ProjectConfigurationDetails.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<div class="project-configuration-details">
|
||||
<div class="content">
|
||||
<PromptsList
|
||||
:prompts="visiblePrompts"
|
||||
@answer="answerPrompt"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="actions-bar space-between">
|
||||
<VueButton
|
||||
:disabled="!hasPromptsChanged"
|
||||
icon-left="cancel"
|
||||
class="big"
|
||||
:label="$t('views.project-configuration-details.actions.cancel')"
|
||||
@click="cancel()"
|
||||
/>
|
||||
|
||||
<VueButton
|
||||
:disabled="!hasPromptsChanged"
|
||||
icon-left="save"
|
||||
class="primary big"
|
||||
:label="$t('views.project-configuration-details.actions.save')"
|
||||
@click="save()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Prompts from '../mixins/Prompts'
|
||||
|
||||
import CONFIGURATION from '../graphql/configuration.gql'
|
||||
import CONFIGURATION_SAVE from '../graphql/configurationSave.gql'
|
||||
import CONFIGURATION_CANCEL from '../graphql/configurationCancel.gql'
|
||||
|
||||
export default {
|
||||
mixins: [
|
||||
Prompts({
|
||||
field: 'configuration',
|
||||
query: CONFIGURATION
|
||||
})
|
||||
],
|
||||
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
configuration: null
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
configuration: {
|
||||
query: CONFIGURATION,
|
||||
variables () {
|
||||
return {
|
||||
id: this.id
|
||||
}
|
||||
},
|
||||
fetchPolicy: 'cache-and-network'
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async cancel () {
|
||||
await this.$apollo.mutate({
|
||||
mutation: CONFIGURATION_CANCEL,
|
||||
variables: {
|
||||
id: this.id
|
||||
}
|
||||
})
|
||||
|
||||
this.$apollo.queries.configuration.refetch()
|
||||
},
|
||||
|
||||
async save () {
|
||||
await this.$apollo.mutate({
|
||||
mutation: CONFIGURATION_SAVE,
|
||||
variables: {
|
||||
id: this.id
|
||||
}
|
||||
})
|
||||
|
||||
this.$apollo.queries.configuration.refetch()
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@import "~@/style/imports"
|
||||
|
||||
.project-configuration-details
|
||||
v-box()
|
||||
align-items stretch
|
||||
height 100%
|
||||
|
||||
.content
|
||||
flex 100% 1 1
|
||||
height 0
|
||||
overflow-x hidden
|
||||
overflow-y auto
|
||||
</style>
|
||||
59
packages/@vue/cli-ui/src/views/ProjectConfigurations.vue
Normal file
59
packages/@vue/cli-ui/src/views/ProjectConfigurations.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<div class="project-configurations page">
|
||||
<ContentView
|
||||
:title="$t('views.project-configurations.title')"
|
||||
class="limit-width"
|
||||
>
|
||||
<ApolloQuery
|
||||
:query="require('../graphql/configurations.gql')"
|
||||
fetch-policy="cache-and-network"
|
||||
class="fill-height"
|
||||
>
|
||||
<template slot-scope="{ result: { data, loading } }">
|
||||
<VueLoadingIndicator
|
||||
v-if="loading"
|
||||
class="overlay"
|
||||
/>
|
||||
|
||||
<NavContent
|
||||
v-else-if="data"
|
||||
:items="generateItems(data.configurations)"
|
||||
class="configurations"
|
||||
>
|
||||
<ConfigurationItem
|
||||
slot-scope="{ item, selected }"
|
||||
:configuration="item.configuration"
|
||||
:selected="selected"
|
||||
/>
|
||||
</NavContent>
|
||||
</template>
|
||||
</ApolloQuery>
|
||||
</ContentView>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import RestoreRoute from '../mixins/RestoreRoute'
|
||||
|
||||
export default {
|
||||
mixins: [
|
||||
RestoreRoute()
|
||||
],
|
||||
|
||||
methods: {
|
||||
generateItems (configurations) {
|
||||
return configurations.map(
|
||||
configuration => ({
|
||||
route: {
|
||||
name: 'project-configuration-details',
|
||||
params: {
|
||||
id: configuration.id
|
||||
}
|
||||
},
|
||||
configuration
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -2162,6 +2162,10 @@ clone@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f"
|
||||
|
||||
clone@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
||||
|
||||
cmd-shim@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb"
|
||||
@@ -6128,7 +6132,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
|
||||
|
||||
js-yaml@^3.10.0, js-yaml@^3.4.3, js-yaml@^3.5.2, js-yaml@^3.7.0, js-yaml@^3.8.1, js-yaml@^3.9.0, js-yaml@^3.9.1:
|
||||
js-yaml@^3.10.0, js-yaml@^3.11.0, js-yaml@^3.4.3, js-yaml@^3.5.2, js-yaml@^3.7.0, js-yaml@^3.8.1, js-yaml@^3.9.0, js-yaml@^3.9.1:
|
||||
version "3.11.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user