@@ -158,7 +158,9 @@ export default {
data () {
return {
- queries: ['appscatalog?full&with_categories'],
+ queries: [
+ ['GET', 'appscatalog?full&with_categories']
+ ],
// Data
apps: undefined,
@@ -280,7 +282,7 @@ export default {
return 'danger'
},
- formatAppData (data) {
+ onQueriesResponse (data) {
// APPS
const apps = []
for (const key in data.apps) {
diff --git a/app/src/views/app/AppConfigPanel.vue b/app/src/views/app/AppConfigPanel.vue
index d380e654..3edc1672 100644
--- a/app/src/views/app/AppConfigPanel.vue
+++ b/app/src/views/app/AppConfigPanel.vue
@@ -1,41 +1,30 @@
-
+
{{ $t('experimental_warning') }}
-
-
-
-
- {{ panel.name }} {{ panel.help }}
+
+
+
+
-
-
- {{ $t('words.collapse') }}
-
-
-
+
+ {{ section.name }} {{ section.help }}
-
-
- {{ section.name }} {{ section.help }}
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
@@ -46,14 +35,18 @@
diff --git a/app/src/views/domain/DomainAdd.vue b/app/src/views/domain/DomainAdd.vue
index c2fc6f02..6213d38f 100644
--- a/app/src/views/domain/DomainAdd.vue
+++ b/app/src/views/domain/DomainAdd.vue
@@ -8,30 +8,32 @@
diff --git a/app/src/views/service/ServiceInfo.vue b/app/src/views/service/ServiceInfo.vue
index f222ccbf..1e8d7f0f 100644
--- a/app/src/views/service/ServiceInfo.vue
+++ b/app/src/views/service/ServiceInfo.vue
@@ -1,6 +1,6 @@
@@ -82,8 +82,8 @@ export default {
data () {
return {
queries: [
- 'services/' + this.name,
- `services/${this.name}/log?number=50`
+ ['GET', 'services/' + this.name],
+ ['GET', `services/${this.name}/log?number=50`]
],
// Service data
infos: undefined,
@@ -96,7 +96,7 @@ export default {
},
methods: {
- formatServiceData (
+ onQueriesResponse (
// eslint-disable-next-line
{ status, description, start_on_boot, last_state_change, configuration },
logs
@@ -126,7 +126,6 @@ export default {
? `services/${this.name}/restart`
: 'services/' + this.name
- // FIXME API doesn't return anything to the PUT so => json err
api[method](uri).then(this.$refs.view.fetchQueries)
},
diff --git a/app/src/views/service/ServiceList.vue b/app/src/views/service/ServiceList.vue
index dae22900..0f6348f5 100644
--- a/app/src/views/service/ServiceList.vue
+++ b/app/src/views/service/ServiceList.vue
@@ -6,7 +6,7 @@
:filtered-items="filteredServices"
items-name="services"
:queries="queries"
- @queries-response="formatServices"
+ @queries-response="onQueriesResponse"
>
{
const service = services[name]
if (service.last_state_change === 'unknown') {
diff --git a/app/src/views/tool/ToolAdminpw.vue b/app/src/views/tool/ToolAdminpw.vue
index 1426421a..d8f25c3d 100644
--- a/app/src/views/tool/ToolAdminpw.vue
+++ b/app/src/views/tool/ToolAdminpw.vue
@@ -11,7 +11,7 @@
import api from '@/api'
import { validationMixin } from 'vuelidate'
-import { PasswordForm } from '@/components/reusableForms'
+import { PasswordForm } from '@/views/_partials'
import { required, minLength } from '@/helpers/validators'
export default {
@@ -40,20 +40,24 @@ export default {
},
methods: {
- onSubmit ({ password, currentPassword }) {
+ onSubmit ({ currentPassword, password }) {
this.serverError = ''
- // Use `api.fetch` to avoid automatic redirect on 401 (Unauthorized).
- api.fetch('POST', 'login', { password: currentPassword }).then(response => {
- if (response.status === 401) {
- // Dispatch `SERVER_RESPONDED` to hide waiting overlay and display error.
- this.$store.dispatch('SERVER_RESPONDED', true)
+
+ api.fetchAll(
+ [['POST', 'login', { password: currentPassword }, { websocket: false }],
+ ['PUT', 'admisnpw', { new_password: password }]],
+ { wait: true }
+ ).then(() => {
+ this.$store.dispatch('DISCONNECT')
+ }).catch(err => {
+ if (err.name === 'APIUnauthorizedError') {
+ // Prevent automatic disconnect if error in current password.
this.serverError = this.$i18n.t('wrong_password')
- } else if (response.ok) {
- api.put('adminpw', { new_password: password }).then(() => {
- this.$store.dispatch('DISCONNECT')
- }).catch(error => {
- this.serverError = error.message
- })
+ } else if (err.name === 'APIBadRequestError') {
+ // Display form error
+ this.serverError = err.message
+ } else {
+ throw err
}
})
}
diff --git a/app/src/views/tool/ToolFirewall.vue b/app/src/views/tool/ToolFirewall.vue
index ac8fc41e..2ba645c2 100644
--- a/app/src/views/tool/ToolFirewall.vue
+++ b/app/src/views/tool/ToolFirewall.vue
@@ -1,6 +1,6 @@
@@ -98,7 +98,9 @@ export default {
data () {
return {
- queries: ['/firewall?raw'],
+ queries: [
+ ['GET', '/firewall?raw']
+ ],
serverError: '',
// Ports tables data
@@ -145,7 +147,7 @@ export default {
},
methods: {
- formatFirewallData (data) {
+ onQueriesResponse (data) {
const ports = Object.values(data).reduce((ports, protocols) => {
for (const type of ['TCP', 'UDP']) {
for (const port of protocols[type]) {
@@ -181,7 +183,11 @@ export default {
).then(confirmed => {
if (confirmed) {
const method = action === 'open' ? 'post' : 'delete'
- api[method](`/firewall/port?${connection}_only`, { port, protocol }).then(() => {
+ api[method](
+ `/firewall/port?${connection}_only`,
+ { port, protocol },
+ { wait: false }
+ ).then(() => {
resolve(confirmed)
}).catch(error => {
reject(error)
@@ -198,10 +204,11 @@ export default {
const confirmed = await this.$askConfirmation(this.$i18n.t('confirm_upnp_' + action))
if (!confirmed) return
- api.get('firewall/upnp?action=' + action).then(() => {
+ api.get('firewall/upnp?action=' + action, null, { websocket: true, wait: true }).then(() => {
// FIXME Couldn't test when it works.
this.$refs.view.fetchQueries()
}).catch(err => {
+ if (err.name !== 'APIBadRequestError') throw err
this.upnpError = err.message
})
},
diff --git a/app/src/views/tool/ToolLog.vue b/app/src/views/tool/ToolLog.vue
index 512fdfe2..26fdb5a9 100644
--- a/app/src/views/tool/ToolLog.vue
+++ b/app/src/views/tool/ToolLog.vue
@@ -1,6 +1,6 @@
@@ -90,12 +90,12 @@ export default {
with_suboperations: '',
number: this.numberOfLines
})
- return [`logs/${this.name}?${queryString}`]
+ return [['GET', `logs/${this.name}?${queryString}`]]
}
},
methods: {
- formatLogData (log) {
+ onQueriesResponse (log) {
if (log.logs.length === this.numberOfLines) {
this.moreLogsAvailable = true
this.numberOfLines *= 10
@@ -125,7 +125,7 @@ export default {
},
shareLogs () {
- api.get(`/logs/${this.name}?share`).then(({ url }) => {
+ api.get(`logs/${this.name}?share`, null, { websocket: true }).then(({ url }) => {
window.open(url, '_blank')
})
}
diff --git a/app/src/views/tool/ToolLogs.vue b/app/src/views/tool/ToolLogs.vue
index d167f493..7b0abbd7 100644
--- a/app/src/views/tool/ToolLogs.vue
+++ b/app/src/views/tool/ToolLogs.vue
@@ -5,7 +5,7 @@
:filtered-items="filteredOperations"
items-name="logs"
:queries="queries"
- @queries-response="formatLogsData"
+ @queries-response="onQueriesResponse"
skeleton="card-list-skeleton"
>
@@ -32,7 +32,9 @@ export default {
data () {
return {
- queries: [`logs?limit=${25}&with_details`],
+ queries: [
+ ['GET', `logs?limit=${25}&with_details`]
+ ],
search: '',
operations: undefined
}
@@ -50,7 +52,7 @@ export default {
},
methods: {
- formatLogsData ({ operation }) {
+ onQueriesResponse ({ operation }) {
operation.forEach((log, index) => {
if (log.success === '?') {
operation[index].icon = 'question'
diff --git a/app/src/views/tool/ToolMigrations.vue b/app/src/views/tool/ToolMigrations.vue
index 7c781178..400b3627 100644
--- a/app/src/views/tool/ToolMigrations.vue
+++ b/app/src/views/tool/ToolMigrations.vue
@@ -1,5 +1,5 @@
-
+
@@ -90,8 +90,8 @@ export default {
data () {
return {
queries: [
- 'migrations?pending',
- 'migrations?done'
+ ['GET', 'migrations?pending'],
+ ['GET', 'migrations?done']
],
pending: undefined,
done: undefined,
@@ -100,7 +100,7 @@ export default {
},
methods: {
- formatMigrationsData ({ migrations: pending }, { migrations: done }) {
+ onQueriesResponse ({ migrations: pending }, { migrations: done }) {
this.done = done.length ? done.reverse() : null
pending.forEach(migration => {
if (migration.disclaimer) {
diff --git a/app/src/views/tool/ToolPower.vue b/app/src/views/tool/ToolPower.vue
index 4ced6afa..ff496bf7 100644
--- a/app/src/views/tool/ToolPower.vue
+++ b/app/src/views/tool/ToolPower.vue
@@ -1,16 +1,17 @@
-
+
+
+
+
+
+
{{ $t(action === 'reboot' ? 'tools_rebooting' : 'tools_shuttingdown') }}
-
-
-
-
@@ -45,6 +46,10 @@ import LoginView from '@/views/Login'
export default {
name: 'ToolPower',
+ components: {
+ LoginView
+ },
+
data () {
return {
action: '',
@@ -65,29 +70,29 @@ export default {
// Use 'RESET_CONNECTED' and not 'DISCONNECT' else user will be redirect to login
this.$store.dispatch('RESET_CONNECTED')
this.inProcess = true
- this.tryToReconnect()
+ return this.tryToReconnect(4000)
+ }).then(() => {
+ this.canReconnect = true
})
},
- tryToReconnect () {
+ tryToReconnect (delay = 2000) {
// FIXME need to be tested out of webpack-dev-server
- setTimeout(() => {
- // Try to get a response from the server after boot/reboot
- // use `api.fetch` to not trigger base response handlers
- api.fetch('GET', 'logout').then(response => {
- // Server responds with `Unauthorized`, we can display the login input
- if (response.status === 401) {
- this.canReconnect = true
- } else {
- this.tryToReconnect()
- }
- }).catch(() => {
- this.tryToReconnect()
- })
- }, 1000)
+ return new Promise(resolve => {
+ setTimeout(() => {
+ // Try to get a response from the server after boot/reboot
+ api.get('logout').catch(err => {
+ if (err.name === 'APIUnauthorizedError') {
+ // Means the server is accessible
+ resolve()
+ } else {
+ // FIXME could be improved by checking error types since yunohost
+ resolve(this.tryToReconnect())
+ }
+ })
+ }, delay)
+ })
}
- },
-
- components: { LoginView }
+ }
}
diff --git a/app/src/views/update/SystemUpdate.vue b/app/src/views/update/SystemUpdate.vue
index 8f244b0d..37c717ce 100644
--- a/app/src/views/update/SystemUpdate.vue
+++ b/app/src/views/update/SystemUpdate.vue
@@ -1,5 +1,8 @@
-
+
@@ -69,7 +72,10 @@ export default {
data () {
return {
- loading: true,
+ queries: [
+ ['GET', 'migrations?pending'],
+ ['PUT', 'update']
+ ],
// API data
migrationsNotDone: undefined,
system: undefined,
@@ -78,6 +84,12 @@ export default {
},
methods: {
+ onQueriesResponse ({ migrations }, { apps, system }) {
+ this.migrationsNotDone = migrations.length !== 0
+ this.apps = apps.length ? apps : null
+ this.system = system.length ? system : null
+ },
+
async performUpgrade ({ type, id = null }) {
const confirmMsg = this.$i18n.t('confirm_update_' + type, id ? { app: id } : {})
const confirmed = await this.$askConfirmation(confirmMsg)
@@ -91,20 +103,6 @@ export default {
this.$router.push({ name: 'tool-logs' })
})
}
- },
-
- created () {
- // Since we need to query a `PUT` method, we won't use ViewBase's `queries` prop and
- // its automatic loading handling.
- Promise.all([
- api.get('migrations?pending'),
- api.put('update')
- ]).then(([{ migrations }, { apps, system }]) => {
- this.migrationsNotDone = migrations.length !== 0
- this.apps = apps.length ? apps : null
- this.system = system.length ? system : null
- this.loading = false
- })
}
}
diff --git a/app/src/views/user/UserCreate.vue b/app/src/views/user/UserCreate.vue
index c2488d30..13cfa5f8 100644
--- a/app/src/views/user/UserCreate.vue
+++ b/app/src/views/user/UserCreate.vue
@@ -60,6 +60,7 @@