199 lines
7.2 KiB
Vue
199 lines
7.2 KiB
Vue
<script setup lang="ts">
|
|
import { Head, router } from '@inertiajs/vue3';
|
|
import { route } from 'ziggy-js';
|
|
import { computed, ref } from 'vue';
|
|
import MainLayout from '@/layouts/MainLayout.vue';
|
|
import SectionHeading from '@/components/SectionHeading.vue';
|
|
import CategoryDialog from '@/components/Settings/Categories/CategoryDialog.vue';
|
|
import type { Category, Feed } from '@/types/types';
|
|
|
|
defineOptions({ layout: MainLayout });
|
|
|
|
const props = defineProps<{
|
|
categories: Category[];
|
|
}>();
|
|
|
|
const dialogOpen = ref(false);
|
|
const editingCategory = ref<Category | null>(null);
|
|
const dialogDefaultParentId = ref<number | null>(null);
|
|
|
|
const parentOptions = computed(() =>
|
|
props.categories.map((c) => ({ title: c.title, value: c.id })),
|
|
);
|
|
|
|
const openCreate = (parentId: number | null = null) => {
|
|
editingCategory.value = null;
|
|
dialogDefaultParentId.value = parentId;
|
|
dialogOpen.value = true;
|
|
};
|
|
|
|
const openEdit = (category: Category) => {
|
|
editingCategory.value = category;
|
|
dialogOpen.value = true;
|
|
};
|
|
|
|
const destroy = (category: Category) => {
|
|
if (
|
|
!confirm(
|
|
`Delete "${category.title}"? This also deletes its subcategories and feeds.`,
|
|
)
|
|
)
|
|
return;
|
|
router.delete(route('categories.destroy', category.id), {
|
|
preserveScroll: true,
|
|
});
|
|
};
|
|
|
|
const feedLabel = (feed: Feed) => feed.type.toUpperCase();
|
|
</script>
|
|
|
|
<template>
|
|
<Head title="Feeds" />
|
|
|
|
<VContainer class="py-8" style="max-width: 720px">
|
|
<div class="d-flex align-center justify-space-between mb-6">
|
|
<SectionHeading
|
|
eyebrow="Settings"
|
|
title="Feed categories"
|
|
subtitle="Organize the RSS feeds you follow into categories and subcategories."
|
|
/>
|
|
<VBtn color="primary" @click="openCreate()">New category</VBtn>
|
|
</div>
|
|
|
|
<p v-if="!categories.length" class="text-body-2 text-medium-emphasis">
|
|
No categories yet. Create one to start adding feeds.
|
|
</p>
|
|
|
|
<VCard
|
|
v-for="category in categories"
|
|
:key="category.id"
|
|
variant="outlined"
|
|
class="mb-4"
|
|
>
|
|
<VCardText class="pa-4">
|
|
<div class="d-flex align-start justify-space-between">
|
|
<div>
|
|
<h3 class="text-h6 font-weight-bold mb-1">
|
|
{{ category.title }}
|
|
</h3>
|
|
<p
|
|
v-if="category.description"
|
|
class="text-body-2 text-medium-emphasis mb-2"
|
|
>
|
|
{{ category.description }}
|
|
</p>
|
|
<div
|
|
v-for="feed in category.feeds"
|
|
:key="feed.id"
|
|
class="d-flex align-center ga-2 mb-1"
|
|
>
|
|
<span class="text-caption text-medium-emphasis">{{
|
|
feed.url
|
|
}}</span>
|
|
<VChip size="x-small" variant="outlined">{{
|
|
feedLabel(feed)
|
|
}}</VChip>
|
|
<VChip
|
|
v-if="feed.paywall"
|
|
size="x-small"
|
|
color="warning"
|
|
variant="outlined"
|
|
>
|
|
Paywalled
|
|
</VChip>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex ga-1">
|
|
<VBtn
|
|
icon="mdi-pencil"
|
|
size="small"
|
|
variant="text"
|
|
@click="openEdit(category)"
|
|
/>
|
|
<VBtn
|
|
icon="mdi-delete"
|
|
size="small"
|
|
variant="text"
|
|
@click="destroy(category)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<VDivider v-if="category.children?.length" class="my-4" />
|
|
|
|
<div
|
|
v-for="child in category.children"
|
|
:key="child.id"
|
|
class="mb-3 ml-4"
|
|
>
|
|
<div class="d-flex align-start justify-space-between">
|
|
<div>
|
|
<h4 class="text-subtitle-1 font-weight-medium mb-1">
|
|
{{ child.title }}
|
|
</h4>
|
|
<p
|
|
v-if="child.description"
|
|
class="text-body-2 text-medium-emphasis mb-2"
|
|
>
|
|
{{ child.description }}
|
|
</p>
|
|
<div
|
|
v-for="feed in child.feeds"
|
|
:key="feed.id"
|
|
class="d-flex align-center ga-2 mb-1"
|
|
>
|
|
<span
|
|
class="text-caption text-medium-emphasis"
|
|
>{{ feed.url }}</span
|
|
>
|
|
<VChip size="x-small" variant="outlined">{{
|
|
feedLabel(feed)
|
|
}}</VChip>
|
|
<VChip
|
|
v-if="feed.paywall"
|
|
size="x-small"
|
|
color="warning"
|
|
variant="outlined"
|
|
>
|
|
Paywalled
|
|
</VChip>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex ga-1">
|
|
<VBtn
|
|
icon="mdi-pencil"
|
|
size="small"
|
|
variant="text"
|
|
@click="openEdit(child)"
|
|
/>
|
|
<VBtn
|
|
icon="mdi-delete"
|
|
size="small"
|
|
variant="text"
|
|
@click="destroy(child)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<VBtn
|
|
variant="text"
|
|
size="small"
|
|
color="primary"
|
|
class="ml-4"
|
|
@click="openCreate(category.id)"
|
|
>
|
|
Add subcategory
|
|
</VBtn>
|
|
</VCardText>
|
|
</VCard>
|
|
|
|
<CategoryDialog
|
|
v-model="dialogOpen"
|
|
:category="editingCategory"
|
|
:parent-options="parentOptions"
|
|
:default-parent-id="dialogDefaultParentId"
|
|
/>
|
|
</VContainer>
|
|
</template>
|