migrate frontend to api V2 (#2324)
This commit is contained in:
parent
7c0ac160c5
commit
a972708334
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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"))]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Migrate frontend to api V2 (#2324)
|
|
@ -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({
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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', {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
tracks?: TotalCount
|
local: {
|
||||||
artists?: TotalCount
|
tracks?: TotalCount
|
||||||
albums?: TotalCount
|
artists?: TotalCount
|
||||||
music?: { hours: number }
|
albums?: TotalCount
|
||||||
|
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)
|
||||||
|
|
|
@ -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 }),
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue