fix(fc3b): SourceFormDialog + SubscriptionsView read platforms store; drop sources.loadPlatforms

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 18:39:44 -04:00
parent a0203f4727
commit 408971a798
4 changed files with 20 additions and 25 deletions
@@ -20,7 +20,13 @@
Adding source for <strong>{{ initialArtist.name }}</strong> Adding source for <strong>{{ initialArtist.name }}</strong>
</div> </div>
<v-select v-model="platform" :items="store.platforms" label="Platform" /> <v-select
v-model="platform"
:items="platformsItems"
item-value="value"
item-title="title"
label="Platform"
/>
<v-text-field v-model="url" label="URL" :error-messages="urlError" /> <v-text-field v-model="url" label="URL" :error-messages="urlError" />
<v-switch v-model="enabled" label="Enabled" color="accent" hide-details /> <v-switch v-model="enabled" label="Enabled" color="accent" hide-details />
@@ -65,6 +71,7 @@
<script setup> <script setup>
import { computed, ref, watch } from 'vue' import { computed, ref, watch } from 'vue'
import { useSourcesStore } from '../../stores/sources.js' import { useSourcesStore } from '../../stores/sources.js'
import { usePlatformsStore } from '../../stores/platforms.js'
const props = defineProps({ const props = defineProps({
modelValue: { type: Boolean, default: false }, modelValue: { type: Boolean, default: false },
@@ -73,6 +80,11 @@ const props = defineProps({
}) })
const emit = defineEmits(['update:modelValue', 'saved']) const emit = defineEmits(['update:modelValue', 'saved'])
const store = useSourcesStore() const store = useSourcesStore()
const platformsStore = usePlatformsStore()
const platformsItems = computed(() =>
platformsStore.list.map(p => ({ value: p.key, title: p.name }))
)
const artistChoice = ref(null) const artistChoice = ref(null)
const artistMatches = ref([]) const artistMatches = ref([])
@@ -128,7 +140,7 @@ const canSave = computed(() => !jsonError.value && !!url.value.trim())
watch(() => props.modelValue, async (open) => { watch(() => props.modelValue, async (open) => {
if (!open) return if (!open) return
urlError.value = ''; jsonError.value = '' urlError.value = ''; jsonError.value = ''
await store.loadPlatforms() await platformsStore.loadAll()
if (props.source) { if (props.source) {
platform.value = props.source.platform platform.value = props.source.platform
url.value = props.source.url url.value = props.source.url
@@ -139,7 +151,7 @@ watch(() => props.modelValue, async (open) => {
jsonText.value = JSON.stringify(co, null, 2) jsonText.value = JSON.stringify(co, null, 2)
artistChoice.value = { id: props.source.artist_id, name: props.source.artist_name } artistChoice.value = { id: props.source.artist_id, name: props.source.artist_name }
} else { } else {
platform.value = store.platforms[0] || 'patreon' platform.value = platformsStore.list[0]?.key || 'patreon'
url.value = ''; enabled.value = true url.value = ''; enabled.value = true
structuredVideos.value = true; structuredSince.value = '' structuredVideos.value = true; structuredSince.value = ''
jsonText.value = '{}' jsonText.value = '{}'
+2 -11
View File
@@ -7,8 +7,6 @@ export const useSourcesStore = defineStore('sources', () => {
// keyed cache: null => all sources, number => artist_id filtered // keyed cache: null => all sources, number => artist_id filtered
const byArtist = ref(new Map()) const byArtist = ref(new Map())
const platforms = ref([])
const platformsLoaded = ref(false)
const loading = ref(false) const loading = ref(false)
const error = ref(null) const error = ref(null)
@@ -40,13 +38,6 @@ export const useSourcesStore = defineStore('sources', () => {
} }
} }
async function loadPlatforms() {
if (platformsLoaded.value) return
const body = await api.get('/api/sources/platforms')
platforms.value = body.platforms
platformsLoaded.value = true
}
function _invalidate(artistId) { function _invalidate(artistId) {
byArtist.value.delete(null) byArtist.value.delete(null)
if (artistId != null) byArtist.value.delete(artistId) if (artistId != null) byArtist.value.delete(artistId)
@@ -99,9 +90,9 @@ export const useSourcesStore = defineStore('sources', () => {
} }
return { return {
byArtist, platforms, platformsLoaded, loading, error, byArtist, loading, error,
allSources, allSources,
loadAll, loadForArtist, loadPlatforms, loadAll, loadForArtist,
create, update, remove, create, update, remove,
findOrCreateArtist, autocompleteArtist, findOrCreateArtist, autocompleteArtist,
sourcesByArtistGrouped, sourcesByArtistGrouped,
+3 -1
View File
@@ -52,12 +52,14 @@
import { computed, onMounted, ref, watch } from 'vue' import { computed, onMounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { useSourcesStore } from '../stores/sources.js' import { useSourcesStore } from '../stores/sources.js'
import { usePlatformsStore } from '../stores/platforms.js'
import ArtistSection from '../components/subscriptions/ArtistSection.vue' import ArtistSection from '../components/subscriptions/ArtistSection.vue'
import SourceFormDialog from '../components/subscriptions/SourceFormDialog.vue' import SourceFormDialog from '../components/subscriptions/SourceFormDialog.vue'
import ArtistCreateDialog from '../components/subscriptions/ArtistCreateDialog.vue' import ArtistCreateDialog from '../components/subscriptions/ArtistCreateDialog.vue'
const route = useRoute() const route = useRoute()
const store = useSourcesStore() const store = useSourcesStore()
const platformsStore = usePlatformsStore()
const artistFilter = computed(() => { const artistFilter = computed(() => {
const raw = route.query.artist_id const raw = route.query.artist_id
@@ -73,7 +75,7 @@ const showArtistDialog = ref(false)
async function refresh() { async function refresh() {
await store.loadAll() await store.loadAll()
await store.loadPlatforms() await platformsStore.loadAll()
if (artistFilter.value != null) { if (artistFilter.value != null) {
openSections.value = new Set([artistFilter.value]) openSections.value = new Set([artistFilter.value])
expandAll.value = false expandAll.value = false
-10
View File
@@ -41,16 +41,6 @@ describe('sources store', () => {
expect(calls[0]).toContain('artist_id=7') expect(calls[0]).toContain('artist_id=7')
}) })
it('loadPlatforms caches the platforms list', async () => {
const s = useSourcesStore()
let n = 0
stubFetch(() => { n++; return { status: 200, body: { platforms: ['patreon'] } } })
await s.loadPlatforms()
await s.loadPlatforms() // second call should hit cache
expect(n).toBe(1)
expect(s.platforms).toEqual(['patreon'])
})
it('create invalidates the all-cache and the artist-cache', async () => { it('create invalidates the all-cache and the artist-cache', async () => {
const s = useSourcesStore() const s = useSourcesStore()
s.byArtist.set(null, []) s.byArtist.set(null, [])