diff --git a/src/App.scss b/src/App.scss
index 3f352e8d91..149d640ff6 100644
--- a/src/App.scss
+++ b/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 {
display: block;
width: 100%;
@@ -655,16 +668,19 @@ option {
display: inline-flex;
vertical-align: middle;
- button {
+ button,
+ .button-dropdown {
position: relative;
flex: 1 1 auto;
- &:not(:last-child) {
+ &:not(:last-child),
+ &:not(:last-child) .button-default {
border-top-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-bottom-left-radius: 0;
}
diff --git a/src/components/settings_modal/admin_tabs/frontends_tab.js b/src/components/settings_modal/admin_tabs/frontends_tab.js
new file mode 100644
index 0000000000..a5d33cbe35
--- /dev/null
+++ b/src/components/settings_modal/admin_tabs/frontends_tab.js
@@ -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
diff --git a/src/components/settings_modal/admin_tabs/frontends_tab.scss b/src/components/settings_modal/admin_tabs/frontends_tab.scss
new file mode 100644
index 0000000000..1e1881ff8a
--- /dev/null
+++ b/src/components/settings_modal/admin_tabs/frontends_tab.scss
@@ -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%;
+ }
+}
diff --git a/src/components/settings_modal/admin_tabs/frontends_tab.vue b/src/components/settings_modal/admin_tabs/frontends_tab.vue
new file mode 100644
index 0000000000..48649dfba9
--- /dev/null
+++ b/src/components/settings_modal/admin_tabs/frontends_tab.vue
@@ -0,0 +1,72 @@
+
+
+
+
{{ $t('admin_dash.tabs.frontends') }}
+
+ -
+ {{ frontend.name }}
+
+ - {{ $t('admin_dash.frontend.repository') }}
+ - {{ frontend.git }}
+ - {{ $t('admin_dash.frontend.versions') }}
+ - {{ frontend.refs }}
+ - {{ $t('admin_dash.frontend.build_url') }}
+ - {{ frontend.build_url }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/settings_modal/settings_modal.scss b/src/components/settings_modal/settings_modal.scss
index 4cb506f930..98de736bfb 100644
--- a/src/components/settings_modal/settings_modal.scss
+++ b/src/components/settings_modal/settings_modal.scss
@@ -43,7 +43,6 @@
.btn {
min-height: 2em;
- min-width: 10em;
padding: 0 2em;
}
}
diff --git a/src/components/settings_modal/settings_modal_admin_content.js b/src/components/settings_modal/settings_modal_admin_content.js
index 1c239e595b..b7c0de576a 100644
--- a/src/components/settings_modal/settings_modal_admin_content.js
+++ b/src/components/settings_modal/settings_modal_admin_content.js
@@ -1,9 +1,8 @@
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 LimitsTab from './admin_tabs/limits_tab.vue'
+import FrontendsTab from './admin_tabs/frontends_tab.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@@ -32,10 +31,9 @@ const SettingsModalAdminContent = {
components: {
TabSwitcher,
- DataImportExportTab,
- MutesAndBlocksTab,
InstanceTab,
- LimitsTab
+ LimitsTab,
+ FrontendsTab
},
computed: {
user () {
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 86ae7f06d9..ede5d4942b 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -873,6 +873,14 @@
"users": "User profile limits",
"profile_fields": "Profile fields 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": {
diff --git a/src/modules/adminSettings.js b/src/modules/adminSettings.js
index b8265949f3..cad9c0ca4d 100644
--- a/src/modules/adminSettings.js
+++ b/src/modules/adminSettings.js
@@ -1,6 +1,7 @@
import { set, get, cloneDeep, differenceWith, isEqual, flatten } from 'lodash'
export const defaultState = {
+ frontends: [],
loaded: false,
needsReboot: null,
config: null,
@@ -23,6 +24,16 @@ const adminSettingsStorage = {
state.loaded = 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 }) {
state.loaded = true
state.dbConfigEnabled = true
@@ -48,6 +59,10 @@ const adminSettingsStorage = {
}
},
actions: {
+ loadFrontendsStuff ({ state, rootState, dispatch, commit }) {
+ rootState.api.backendInteractor.fetchAvailableFrontends()
+ .then(frontends => commit('setAvailableFrontends', { frontends }))
+ },
loadAdminStuff ({ state, rootState, dispatch, commit }) {
rootState.api.backendInteractor.fetchInstanceDBConfig()
.then(backendDbConfig => {
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 073f40a34d..56e7de714c 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -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_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
@@ -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 }) => {
return fetch(PLEROMA_ADMIN_CONFIG_URL, {
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 = {
verifyCredentials,
fetchTimeline,
@@ -1830,7 +1868,9 @@ const apiService = {
adminFetchAnnouncements,
fetchInstanceDBConfig,
fetchInstanceConfigDescriptions,
- pushInstanceDBConfig
+ fetchAvailableFrontends,
+ pushInstanceDBConfig,
+ installFrontend
}
export default apiService