frontends tab initial implementation, now you can (re)install frontends! yay!

This commit is contained in:
Henry Jameson 2023-03-29 00:58:07 +03:00
parent 3ac67ab727
commit 7bb28bb23c
9 changed files with 229 additions and 10 deletions

View File

@ -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;
} }

View File

@ -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

View File

@ -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%;
}
}

View File

@ -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>

View File

@ -43,7 +43,6 @@
.btn { .btn {
min-height: 2em; min-height: 2em;
min-width: 10em;
padding: 0 2em; padding: 0 2em;
} }
} }

View File

@ -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 () {

View File

@ -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": {

View File

@ -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 => {

View File

@ -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