Skip to content

Commit

Permalink
add/edit/delete radio stations
Browse files Browse the repository at this point in the history
closes #106
  • Loading branch information
tamland committed Aug 27, 2023
1 parent f8c1b7f commit 6b8db53
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 15 deletions.
68 changes: 66 additions & 2 deletions src/library/radio/RadioStations.vue
Original file line number Diff line number Diff line change
@@ -1,26 +1,68 @@
<template>
<ContentLoader v-slot :loading="items === null">
<h1>Radio</h1>
<TrackList v-if="items.length > 0" :tracks="items" no-artist no-album no-duration />
<div class="d-flex justify-content-between align-items-center mb-2">
<h1 class="mb-0 mr-2 text-truncate">
Radio
</h1>
<b-button variant="link" :disabled="unsupported" @click="openAddModal">
<Icon icon="plus" />
</b-button>
</div>

<TrackList v-if="items.length > 0" :tracks="items" no-artist no-album no-duration>
<template #context-menu="{ item }">
<ContextMenuItem icon="edit" @click="openEditModal(item)">
Edit
</ContextMenuItem>
<b-dropdown-divider />
<ContextMenuItem icon="x" variant="danger" @click="deleteRadioStation(item)">
Delete
</ContextMenuItem>
</template>
</TrackList>
<EmptyIndicator v-else-if="unsupported" label="Not supported" />
<EmptyIndicator v-else />

<EditModal :visible.sync="modalVisible" :item="editItem" @confirm="saveRadioStation">
<template #title="{ item }">
{{ item?.id ? "Edit" : "Add" }} Radio Station
</template>
<template #default="{ item }">
<div class="form-group">
<label>Name</label>
<input v-model="item.title" class="form-control" type="text">
</div>
<div class="form-group">
<label>Stream URL</label>
<input v-model="item.url" class="form-control" type="text">
</div>
<div class="form-group">
<label class="mb-0">Home Page URL</label>
<input v-model="item.description" class="form-control" type="text">
</div>
</template>
</EditModal>
</ContentLoader>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { RadioStation, UnsupportedOperationError } from '@/shared/api'
import ContentLoader from '@/shared/components/ContentLoader.vue'
import EditModal from '@/shared/components/EditModal.vue'
import TrackList from '@/library/track/TrackList.vue'

export default defineComponent({
components: {
TrackList,
ContentLoader,
EditModal,
},
data() {
return {
items: null as null | RadioStation[],
unsupported: false,
modalVisible: false,
editItem: {},
}
},
async created() {
Expand All @@ -35,5 +77,27 @@
throw err
}
},
methods: {
openAddModal() {
this.editItem = {}
this.modalVisible = true
},
openEditModal(item: RadioStation) {
this.editItem = item
this.modalVisible = true
},
deleteRadioStation(item: RadioStation) {
this.$api.deleteRadioStation(item.id)
this.items = this.items!.filter(x => x.id !== item.id)

Check warning on line 91 in src/library/radio/RadioStations.vue

View workflow job for this annotation

GitHub Actions / build

Forbidden non-null assertion
},
async saveRadioStation(item: RadioStation) {
this.editItem = {}
if (item.id) {
this.items = await this.$api.updateRadioStation(item)
} else {
this.items = await this.$api.addRadioStation(item.title, item.url, item.description)
}
},
},
})
</script>
27 changes: 14 additions & 13 deletions src/shared/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,29 +320,29 @@ export class API {
.map(this.normalizeRadioStation, this)
}

async addRadioStation(title: string, url: string): Promise<RadioStation> {
async addRadioStation(title: string, url: string, description?: string): Promise<RadioStation[]> {
const params = {
name: title,
name: title ?? '',
streamUrl: url,
homepageUrl: description?.trim() === '' ? undefined : description,
}
return this
.fetch('rest/createInternetRadioStation', params)
.then(this.normalizeRadioStation)
await this.fetch('rest/createInternetRadioStation', params)
return await this.getRadioStations()
}

async updateRadioStation(item: RadioStation): Promise<RadioStation> {
async updateRadioStation(item: RadioStation): Promise<RadioStation[]> {
const params = {
id: item.id,
name: item.title,
id: item.id.replace('radio-', ''),
name: item.title ?? '',
streamUrl: item.url,
homepageUrl: item.description?.trim() === '' ? undefined : item.description
}
return this
.fetch('rest/updateInternetRadioStation', params)
.then(this.normalizeRadioStation)
await this.fetch('rest/updateInternetRadioStation', params)
return await this.getRadioStations()
}

async deleteRadioStation(id: string): Promise<void> {
return this.fetch('rest/deleteInternetRadioStation', { id })
return this.fetch('rest/deleteInternetRadioStation', { id: id.replace('radio-', '') })
}

async getPodcasts(): Promise<any[]> {
Expand Down Expand Up @@ -383,7 +383,8 @@ export class API {
return {
id: `radio-${item.id}`,
title: item.name,
description: item.homePageUrl,
// Workaround: airsonic-advanced does not use correct name
description: item.homepageUrl || item.homePageUrl,
album: item.name,
track: item.track,
url: item.streamUrl,
Expand Down
1 change: 1 addition & 0 deletions src/shared/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export function trackListEquals(a: Track[], b: Track[]): boolean {

export function toQueryString(params: Record<string, string | string[]>): string {
const list = Object.entries(params)
.filter(([, value]) => value !== undefined)
.map(([key, value]) => Array.isArray(value) ? value.map((x) => [key, x]) : [[key, value]])
.flat()
return new URLSearchParams(list).toString()
Expand Down

0 comments on commit 6b8db53

Please sign in to comment.