frontends tab initial implementation, now you can (re)install frontends! yay!
This commit is contained in:
parent
3ac67ab727
commit
7bb28bb23c
22
src/App.scss
22
src/App.scss
|
@ -645,6 +645,19 @@ option {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cards-list {
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: row dense;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
|
||||||
|
li {
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--inputRadius);
|
||||||
|
padding: 0.5em;
|
||||||
|
margin: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.btn-block {
|
.btn-block {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -655,16 +668,19 @@ option {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
||||||
button {
|
button,
|
||||||
|
.button-dropdown {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
|
||||||
&:not(:last-child) {
|
&:not(:last-child),
|
||||||
|
&:not(:last-child) .button-default {
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(:first-child) {
|
&:not(:first-child),
|
||||||
|
&:not(:first-child) .button-default {
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
import BooleanSetting from '../helpers/boolean_setting.vue'
|
||||||
|
import ChoiceSetting from '../helpers/choice_setting.vue'
|
||||||
|
import IntegerSetting from '../helpers/integer_setting.vue'
|
||||||
|
import StringSetting from '../helpers/string_setting.vue'
|
||||||
|
import GroupSetting from '../helpers/group_setting.vue'
|
||||||
|
import Popover from 'src/components/popover/popover.vue'
|
||||||
|
|
||||||
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||||
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
import {
|
||||||
|
faGlobe
|
||||||
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
library.add(
|
||||||
|
faGlobe
|
||||||
|
)
|
||||||
|
|
||||||
|
const FrontendsTab = {
|
||||||
|
provide () {
|
||||||
|
return {
|
||||||
|
defaultDraftMode: true,
|
||||||
|
defaultSource: 'admin'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
BooleanSetting,
|
||||||
|
ChoiceSetting,
|
||||||
|
IntegerSetting,
|
||||||
|
StringSetting,
|
||||||
|
GroupSetting,
|
||||||
|
Popover
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
if (this.user.rights.admin) {
|
||||||
|
this.$store.dispatch('loadFrontendsStuff')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
frontends () {
|
||||||
|
return this.$store.state.adminSettings.frontends
|
||||||
|
},
|
||||||
|
...SharedComputedObject()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
update (frontend, suggestRef) {
|
||||||
|
const ref = suggestRef || frontend.refs[0]
|
||||||
|
const { name } = frontend
|
||||||
|
const payload = { name, ref }
|
||||||
|
|
||||||
|
this.$store.state.api.backendInteractor.installFrontend({ payload })
|
||||||
|
.then((externalUser) => {
|
||||||
|
this.$store.dispatch('loadFrontendsStuff')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FrontendsTab
|
|
@ -0,0 +1,13 @@
|
||||||
|
.frontends-tab {
|
||||||
|
.cards-list {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
word-wrap: nowrap;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: hidden;
|
||||||
|
max-width: 80%;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
<template>
|
||||||
|
<div class="frontends-tab" :label="$t('admin_dash.tabs.frontends')">
|
||||||
|
<div class="setting-item">
|
||||||
|
<h2>{{ $t('admin_dash.tabs.frontends') }}</h2>
|
||||||
|
<ul class="setting-list cards-list">
|
||||||
|
<li v-for="frontend in frontends" :key="frontend.name">
|
||||||
|
<strong>{{ frontend.name }}</strong>
|
||||||
|
<dl>
|
||||||
|
<dt>{{ $t('admin_dash.frontend.repository') }}</dt>
|
||||||
|
<dd><a :href="frontend.git">{{ frontend.git }}</a></dd>
|
||||||
|
<dt v-if="expertLevel">{{ $t('admin_dash.frontend.versions') }}</dt>
|
||||||
|
<dd v-if="expertLevel">{{ frontend.refs }}</dd>
|
||||||
|
<dt v-if="expertLevel">{{ $t('admin_dash.frontend.build_url') }}</dt>
|
||||||
|
<dd v-if="expertLevel">{{ frontend.build_url }}</dd>
|
||||||
|
</dl>
|
||||||
|
<div>
|
||||||
|
<span class="btn-group">
|
||||||
|
<button
|
||||||
|
class="button button-default btn"
|
||||||
|
type="button"
|
||||||
|
:title="$t('admin_dash.frontend.update')"
|
||||||
|
@click="update(frontend)"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
frontend.installed
|
||||||
|
? $t('admin_dash.frontend.reinstall')
|
||||||
|
: $t('admin_dash.frontend.install')
|
||||||
|
}}
|
||||||
|
</button>
|
||||||
|
<Popover
|
||||||
|
v-if="frontend.refs.length > 1"
|
||||||
|
trigger="click"
|
||||||
|
class="button-dropdown"
|
||||||
|
placement="bottom"
|
||||||
|
>
|
||||||
|
<template #content>
|
||||||
|
<div class="dropdown-menu">
|
||||||
|
<button
|
||||||
|
v-for="ref in frontend.refs"
|
||||||
|
:key="ref"
|
||||||
|
class="button-default dropdown-item"
|
||||||
|
@click="update(frontend, ref)"
|
||||||
|
>
|
||||||
|
<i18n-t keypath="admin_dash.frontend.install_version">
|
||||||
|
<template #version>
|
||||||
|
<code>{{ ref }}</code>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #trigger>
|
||||||
|
<button
|
||||||
|
class="button button-default btn"
|
||||||
|
type="button"
|
||||||
|
:title="$t('admin_dash.frontend.update')"
|
||||||
|
>
|
||||||
|
<FAIcon icon="chevron-down" />
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
</Popover>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./frontends_tab.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss" src="./frontends_tab.scss"></style>
|
|
@ -43,7 +43,6 @@
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
min-height: 2em;
|
min-height: 2em;
|
||||||
min-width: 10em;
|
|
||||||
padding: 0 2em;
|
padding: 0 2em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
|
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
|
||||||
|
|
||||||
import DataImportExportTab from './tabs/data_import_export_tab.vue'
|
|
||||||
import MutesAndBlocksTab from './tabs/mutes_and_blocks_tab.vue'
|
|
||||||
import InstanceTab from './admin_tabs/instance_tab.vue'
|
import InstanceTab from './admin_tabs/instance_tab.vue'
|
||||||
import LimitsTab from './admin_tabs/limits_tab.vue'
|
import LimitsTab from './admin_tabs/limits_tab.vue'
|
||||||
|
import FrontendsTab from './admin_tabs/frontends_tab.vue'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
|
@ -32,10 +31,9 @@ const SettingsModalAdminContent = {
|
||||||
components: {
|
components: {
|
||||||
TabSwitcher,
|
TabSwitcher,
|
||||||
|
|
||||||
DataImportExportTab,
|
|
||||||
MutesAndBlocksTab,
|
|
||||||
InstanceTab,
|
InstanceTab,
|
||||||
LimitsTab
|
LimitsTab,
|
||||||
|
FrontendsTab
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
user () {
|
user () {
|
||||||
|
|
|
@ -873,6 +873,14 @@
|
||||||
"users": "User profile limits",
|
"users": "User profile limits",
|
||||||
"profile_fields": "Profile fields limits",
|
"profile_fields": "Profile fields limits",
|
||||||
"user_uploads": "Profile media limits"
|
"user_uploads": "Profile media limits"
|
||||||
|
},
|
||||||
|
"frontend": {
|
||||||
|
"repository": "Repository link",
|
||||||
|
"versions": "Available versions",
|
||||||
|
"build_url": "Build URL",
|
||||||
|
"reinstall": "Reinstall",
|
||||||
|
"install": "Install",
|
||||||
|
"install_version": "Install version {version}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { set, get, cloneDeep, differenceWith, isEqual, flatten } from 'lodash'
|
import { set, get, cloneDeep, differenceWith, isEqual, flatten } from 'lodash'
|
||||||
|
|
||||||
export const defaultState = {
|
export const defaultState = {
|
||||||
|
frontends: [],
|
||||||
loaded: false,
|
loaded: false,
|
||||||
needsReboot: null,
|
needsReboot: null,
|
||||||
config: null,
|
config: null,
|
||||||
|
@ -23,6 +24,16 @@ const adminSettingsStorage = {
|
||||||
state.loaded = false
|
state.loaded = false
|
||||||
state.dbConfigEnabled = false
|
state.dbConfigEnabled = false
|
||||||
},
|
},
|
||||||
|
setAvailableFrontends (state, { frontends }) {
|
||||||
|
state.frontends = frontends.map(f => {
|
||||||
|
if (f.name === 'pleroma-fe') {
|
||||||
|
f.refs = ['master', 'develop']
|
||||||
|
} else {
|
||||||
|
f.refs = [f.ref]
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
})
|
||||||
|
},
|
||||||
updateAdminSettings (state, { config, modifiedPaths }) {
|
updateAdminSettings (state, { config, modifiedPaths }) {
|
||||||
state.loaded = true
|
state.loaded = true
|
||||||
state.dbConfigEnabled = true
|
state.dbConfigEnabled = true
|
||||||
|
@ -48,6 +59,10 @@ const adminSettingsStorage = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
loadFrontendsStuff ({ state, rootState, dispatch, commit }) {
|
||||||
|
rootState.api.backendInteractor.fetchAvailableFrontends()
|
||||||
|
.then(frontends => commit('setAvailableFrontends', { frontends }))
|
||||||
|
},
|
||||||
loadAdminStuff ({ state, rootState, dispatch, commit }) {
|
loadAdminStuff ({ state, rootState, dispatch, commit }) {
|
||||||
rootState.api.backendInteractor.fetchInstanceDBConfig()
|
rootState.api.backendInteractor.fetchInstanceDBConfig()
|
||||||
.then(backendDbConfig => {
|
.then(backendDbConfig => {
|
||||||
|
|
|
@ -110,6 +110,8 @@ const PLEROMA_DELETE_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcemen
|
||||||
|
|
||||||
const PLEROMA_ADMIN_CONFIG_URL = '/api/pleroma/admin/config'
|
const PLEROMA_ADMIN_CONFIG_URL = '/api/pleroma/admin/config'
|
||||||
const PLEROMA_ADMIN_DESCRIPTIONS_URL = '/api/pleroma/admin/config/descriptions'
|
const PLEROMA_ADMIN_DESCRIPTIONS_URL = '/api/pleroma/admin/config/descriptions'
|
||||||
|
const PLEROMA_ADMIN_FRONTENDS_URL = '/api/pleroma/admin/frontends'
|
||||||
|
const PLEROMA_ADMIN_FRONTENDS_INSTALL_URL = '/api/pleroma/admin/frontends/install'
|
||||||
|
|
||||||
const oldfetch = window.fetch
|
const oldfetch = window.fetch
|
||||||
|
|
||||||
|
@ -1693,6 +1695,21 @@ const fetchInstanceConfigDescriptions = ({ credentials }) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchAvailableFrontends = ({ credentials }) => {
|
||||||
|
return fetch(PLEROMA_ADMIN_FRONTENDS_URL, {
|
||||||
|
headers: authHeaders(credentials)
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json()
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
error: response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const pushInstanceDBConfig = ({ credentials, payload }) => {
|
const pushInstanceDBConfig = ({ credentials, payload }) => {
|
||||||
return fetch(PLEROMA_ADMIN_CONFIG_URL, {
|
return fetch(PLEROMA_ADMIN_CONFIG_URL, {
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -1714,6 +1731,27 @@ const pushInstanceDBConfig = ({ credentials, payload }) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const installFrontend = ({ credentials, payload }) => {
|
||||||
|
return fetch(PLEROMA_ADMIN_FRONTENDS_INSTALL_URL, {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
...authHeaders(credentials)
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json()
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
error: response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const apiService = {
|
const apiService = {
|
||||||
verifyCredentials,
|
verifyCredentials,
|
||||||
fetchTimeline,
|
fetchTimeline,
|
||||||
|
@ -1830,7 +1868,9 @@ const apiService = {
|
||||||
adminFetchAnnouncements,
|
adminFetchAnnouncements,
|
||||||
fetchInstanceDBConfig,
|
fetchInstanceDBConfig,
|
||||||
fetchInstanceConfigDescriptions,
|
fetchInstanceConfigDescriptions,
|
||||||
pushInstanceDBConfig
|
fetchAvailableFrontends,
|
||||||
|
pushInstanceDBConfig,
|
||||||
|
installFrontend
|
||||||
}
|
}
|
||||||
|
|
||||||
export default apiService
|
export default apiService
|
||||||
|
|
Loading…
Reference in New Issue