migrate frontend to api V2 (#2324)

This commit is contained in:
petitminion 2024-08-04 13:18:21 +00:00
parent 7c0ac160c5
commit a972708334
12 changed files with 70 additions and 22 deletions

View File

@ -25,7 +25,14 @@ urlpatterns = [
("funkwhale_api.federation.urls", "federation"), namespace="federation" ("funkwhale_api.federation.urls", "federation"), namespace="federation"
), ),
), ),
re_path(r"^api/v1/auth/", include("funkwhale_api.users.rest_auth_urls")), re_path(
r"^api/v1/auth/",
include("funkwhale_api.users.rest_auth_urls"),
),
re_path(
r"^api/v2/auth/",
include("funkwhale_api.users.rest_auth_urls"),
),
re_path(r"^accounts/", include("allauth.urls")), re_path(r"^accounts/", include("allauth.urls")),
] + plugins_patterns ] + plugins_patterns

View File

@ -3,6 +3,8 @@ from django.urls import re_path
from funkwhale_api.common import routers as common_routers from funkwhale_api.common import routers as common_routers
from . import api
router = common_routers.OptionalSlashRouter() router = common_routers.OptionalSlashRouter()
v2_patterns = router.urls v2_patterns = router.urls
@ -17,4 +19,18 @@ v2_patterns += [
), ),
] ]
v2_paths = {
pattern.pattern.regex.pattern
for pattern in v2_patterns
if hasattr(pattern.pattern, "regex")
}
filtered_v1_patterns = [
pattern
for pattern in api.v1_patterns
if pattern.pattern.regex.pattern not in v2_paths
]
v2_patterns += filtered_v1_patterns
urlpatterns = [re_path("", include((v2_patterns, "v2"), namespace="v2"))] urlpatterns = [re_path("", include((v2_patterns, "v2"), namespace="v2"))]

View File

@ -1,7 +1,14 @@
from django.urls import re_path from django.urls import re_path
from funkwhale_api.common import routers
from . import views from . import views
admin_router = routers.OptionalSlashRouter()
admin_router.register(r"admin/settings", views.AdminSettings, "admin-settings")
urlpatterns = [ urlpatterns = [
re_path(r"^nodeinfo/2.1/?$", views.NodeInfo21.as_view(), name="nodeinfo-2.1"), re_path(r"^nodeinfo/2.1/?$", views.NodeInfo21.as_view(), name="nodeinfo-2.1"),
] re_path(r"^settings/?$", views.InstanceSettings.as_view(), name="settings"),
re_path(r"^spa-manifest.json", views.SpaManifest.as_view(), name="spa-manifest"),
] + admin_router.urls

View File

@ -5,6 +5,7 @@ from . import views
router = routers.OptionalSlashRouter() router = routers.OptionalSlashRouter()
router.register(r"sessions", views.V2_RadioSessionViewSet, "sessions") router.register(r"sessions", views.V2_RadioSessionViewSet, "sessions")
router.register(r"radios", views.RadioViewSet, "radios")
router.register(r"tracks", views.V1_RadioSessionTrackViewSet, "tracks")
urlpatterns = router.urls urlpatterns = router.urls

View File

@ -0,0 +1 @@
Migrate frontend to api V2 (#2324)

View File

@ -1,7 +1,7 @@
Cypress.Commands.add('login', () => { Cypress.Commands.add('login', () => {
cy.fixture('testuser.json').then(({ username, password }) => { cy.fixture('testuser.json').then(({ username, password }) => {
// We need to request a page that sets the csrf cookie // We need to request a page that sets the csrf cookie
cy.request('/api/v1/instance/nodeinfo/2.0/') cy.request('/api/v2/instance/nodeinfo/2.1/')
cy.getCookie('csrftoken').then(($cookie) => { cy.getCookie('csrftoken').then(($cookie) => {
cy.request({ cy.request({

View File

@ -22,12 +22,20 @@ const longDescription = useMarkdown(() => get(nodeinfo.value, 'metadata.longDesc
const rules = useMarkdown(() => get(nodeinfo.value, 'metadata.rules', '')) const rules = useMarkdown(() => get(nodeinfo.value, 'metadata.rules', ''))
const terms = useMarkdown(() => get(nodeinfo.value, 'metadata.terms', '')) const terms = useMarkdown(() => get(nodeinfo.value, 'metadata.terms', ''))
const contactEmail = computed(() => get(nodeinfo.value, 'metadata.contactEmail')) const contactEmail = computed(() => get(nodeinfo.value, 'metadata.contactEmail'))
const anonymousCanListen = computed(() => get(nodeinfo.value, 'metadata.library.anonymousCanListen')) const anonymousCanListen = computed(() => {
const features = get(nodeinfo.value, 'metadata.metadata.feature', []) as string[]
const hasAnonymousCanListen = features.includes('anonymousCanListen')
return hasAnonymousCanListen
})
const allowListEnabled = computed(() => get(nodeinfo.value, 'metadata.allowList.enabled')) const allowListEnabled = computed(() => get(nodeinfo.value, 'metadata.allowList.enabled'))
const version = computed(() => get(nodeinfo.value, 'software.version')) const version = computed(() => get(nodeinfo.value, 'software.version'))
const openRegistrations = computed(() => get(nodeinfo.value, 'openRegistrations')) const openRegistrations = computed(() => get(nodeinfo.value, 'openRegistrations'))
const defaultUploadQuota = computed(() => get(nodeinfo.value, 'metadata.defaultUploadQuota')) const defaultUploadQuota = computed(() => get(nodeinfo.value, 'metadata.defaultUploadQuota'))
const federationEnabled = computed(() => get(nodeinfo.value, 'metadata.library.federationEnabled')) const federationEnabled = computed(() => {
const features = get(nodeinfo.value, 'metadata.metadata.feature', []) as string[]
const hasAnonymousCanListen = features.includes('federation')
return hasAnonymousCanListen
})
const onDesktop = computed(() => window.innerWidth > 800) const onDesktop = computed(() => window.innerWidth > 800)
@ -36,10 +44,10 @@ const stats = computed(() => {
const data = { const data = {
users: get(info, 'usage.users.activeMonth', null), users: get(info, 'usage.users.activeMonth', null),
hours: get(info, 'metadata.library.music.hours', null), hours: get(info, 'metadata.content.local.hoursOfContent', null),
artists: get(info, 'metadata.library.artists.total', null), artists: get(info, 'metadata.content.local.artists.total', null),
albums: get(info, 'metadata.library.albums.total', null), albums: get(info, 'metadata.content.local.albums.total', null),
tracks: get(info, 'metadata.library.tracks.total', null), tracks: get(info, 'metadata.content.local.tracks.total', null),
listenings: get(info, 'metadata.usage.listenings.total', null) listenings: get(info, 'metadata.usage.listenings.total', null)
} }

View File

@ -106,7 +106,7 @@ watchEffect(async () => {
isLoadingReportTypes.value = true isLoadingReportTypes.value = true
try { try {
const response = await axios.get('instance/nodeinfo/2.0/') const response = await axios.get('instance/nodeinfo/2.1/')
reportTypes.value = response.data.metadata.reportTypes ?? [] reportTypes.value = response.data.metadata.reportTypes ?? []
} catch (error) { } catch (error) {
store.commit('ui/addMessage', { store.commit('ui/addMessage', {

View File

@ -15,12 +15,12 @@ export const install: InitModule = async ({ store, router }) => {
const fetchNodeInfo = async () => { const fetchNodeInfo = async () => {
try { try {
const [{ data }] = await Promise.all([ const [{ data }] = await Promise.all([
axios.get<NodeInfo>('instance/nodeinfo/2.0/'), axios.get<NodeInfo>('instance/nodeinfo/2.1/'),
store.dispatch('instance/fetchSettings') store.dispatch('instance/fetchSettings')
]) ])
if (data.metadata.library.music?.hours) { if (data.metadata.content?.local.hoursOfContent) {
data.metadata.library.music.hours = Math.floor(data.metadata.library.music.hours) data.metadata.content.local.hoursOfContent = Math.floor(data.metadata.content?.local.hoursOfContent)
} }
store.commit('instance/nodeinfo', data) store.commit('instance/nodeinfo', data)

View File

@ -49,13 +49,20 @@ export interface NodeInfo {
nodeName: string nodeName: string
banner: string banner: string
defaultUploadQuota: number defaultUploadQuota: number
library: { content: {
federationEnabled: boolean federationEnabled: boolean
anonymousCanListen: boolean anonymousCanListen: boolean
local: {
tracks?: TotalCount tracks?: TotalCount
artists?: TotalCount artists?: TotalCount
albums?: TotalCount albums?: TotalCount
music?: { hours: number } hoursOfContent?: number }
}
topMusicCategories: []
topPodcastCategories: []
federation: {
followedInstances: number
followingInstances: number
} }
supportedUploadExtensions: string[] supportedUploadExtensions: string[]
allowList: { allowList: {
@ -79,6 +86,7 @@ export interface NodeInfo {
listenings: TotalCount listenings: TotalCount
downloads: TotalCount downloads: TotalCount
} }
features:[]
} }
} }
@ -223,7 +231,7 @@ const store: Module<State, RootState> = {
try { try {
const { href } = new URL(value) const { href } = new URL(value)
state.instanceUrl = href state.instanceUrl = href
axios.defaults.baseURL = `${href}api/v1/` axios.defaults.baseURL = `${href}api/v2/`
// append the URL to the list (and remove existing one if needed) // append the URL to the list (and remove existing one if needed)
const index = state.knownInstances.indexOf(href) const index = state.knownInstances.indexOf(href)

View File

@ -35,7 +35,7 @@ const checkAndSwitch = async (url: string) => {
try { try {
const instanceUrl = new URL(url.startsWith('https://') || url.startsWith('http://') ? url : `https://${url}`).origin const instanceUrl = new URL(url.startsWith('https://') || url.startsWith('http://') ? url : `https://${url}`).origin
await axios.get(instanceUrl + '/api/v1/instance/nodeinfo/2.0/') await axios.get(instanceUrl + '/api/v2/instance/nodeinfo/2.1/')
store.commit('ui/addMessage', { store.commit('ui/addMessage', {
content: t('views.ChooseInstance.message.newUrl', { url: instanceUrl }), content: t('views.ChooseInstance.message.newUrl', { url: instanceUrl }),

View File

@ -14,7 +14,7 @@ const labels = computed(() => ({
})) }))
const fetchNodeInfo = async () => { const fetchNodeInfo = async () => {
const response = await axios.get('instance/nodeinfo/2.0/') const response = await axios.get('instance/nodeinfo/2.1/')
allowListEnabled.value = get(response.data, 'metadata.allowList.enabled', false) allowListEnabled.value = get(response.data, 'metadata.allowList.enabled', false)
} }