mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Merge pull request #2572 from omnivore-app/feature/pause-rss-feed
add a button to pause rss feed
This commit is contained in:
commit
55e378c9b5
6 changed files with 119 additions and 41 deletions
|
|
@ -3031,6 +3031,7 @@ export type UpdateSubscriptionInput = {
|
|||
id: Scalars['ID'];
|
||||
lastFetchedAt?: InputMaybe<Scalars['Date']>;
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
status?: InputMaybe<SubscriptionStatus>;
|
||||
};
|
||||
|
||||
export type UpdateSubscriptionResult = UpdateSubscriptionError | UpdateSubscriptionSuccess;
|
||||
|
|
|
|||
|
|
@ -2353,6 +2353,7 @@ input UpdateSubscriptionInput {
|
|||
id: ID!
|
||||
lastFetchedAt: Date
|
||||
name: String
|
||||
status: SubscriptionStatus
|
||||
}
|
||||
|
||||
union UpdateSubscriptionResult = UpdateSubscriptionError | UpdateSubscriptionSuccess
|
||||
|
|
|
|||
|
|
@ -47,49 +47,61 @@ export const subscriptionsResolver = authorized<
|
|||
SubscriptionsSuccessPartial,
|
||||
SubscriptionsError,
|
||||
QuerySubscriptionsArgs
|
||||
>(async (_obj, { sort, type: subscriptionType }, { claims: { uid }, log }) => {
|
||||
log.info('subscriptionsResolver')
|
||||
>(
|
||||
async (
|
||||
_obj,
|
||||
{ sort, type = SubscriptionType.Newsletter }, // default to newsletter
|
||||
{ claims: { uid }, log }
|
||||
) => {
|
||||
log.info('subscriptionsResolver')
|
||||
|
||||
analytics.track({
|
||||
userId: uid,
|
||||
event: 'subscriptions',
|
||||
properties: {
|
||||
env: env.server.apiEnv,
|
||||
},
|
||||
})
|
||||
analytics.track({
|
||||
userId: uid,
|
||||
event: 'subscriptions',
|
||||
properties: {
|
||||
env: env.server.apiEnv,
|
||||
},
|
||||
})
|
||||
|
||||
try {
|
||||
const sortBy =
|
||||
sort?.by === SortBy.UpdatedTime ? 'lastFetchedAt' : 'createdAt'
|
||||
const sortOrder = sort?.order === SortOrder.Ascending ? 'ASC' : 'DESC'
|
||||
const user = await getRepository(User).findOneBy({ id: uid })
|
||||
if (!user) {
|
||||
return {
|
||||
errorCodes: [SubscriptionsErrorCode.Unauthorized],
|
||||
}
|
||||
}
|
||||
|
||||
const queryBuilder = getRepository(Subscription)
|
||||
.createQueryBuilder('subscription')
|
||||
.leftJoinAndSelect('subscription.newsletterEmail', 'newsletterEmail')
|
||||
.where({
|
||||
user: { id: uid },
|
||||
type,
|
||||
})
|
||||
|
||||
// only return active subscriptions for newsletter
|
||||
if (type === SubscriptionType.Newsletter) {
|
||||
queryBuilder.andWhere({ status: SubscriptionStatus.Active })
|
||||
}
|
||||
|
||||
const subscriptions = await queryBuilder
|
||||
.orderBy('subscription.' + sortBy, sortOrder)
|
||||
.getMany()
|
||||
|
||||
try {
|
||||
const sortBy =
|
||||
sort?.by === SortBy.UpdatedTime ? 'lastFetchedAt' : 'createdAt'
|
||||
const sortOrder = sort?.order === SortOrder.Ascending ? 'ASC' : 'DESC'
|
||||
const user = await getRepository(User).findOneBy({ id: uid })
|
||||
if (!user) {
|
||||
return {
|
||||
errorCodes: [SubscriptionsErrorCode.Unauthorized],
|
||||
subscriptions,
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(error)
|
||||
return {
|
||||
errorCodes: [SubscriptionsErrorCode.BadRequest],
|
||||
}
|
||||
}
|
||||
|
||||
const subscriptions = await getRepository(Subscription)
|
||||
.createQueryBuilder('subscription')
|
||||
.leftJoinAndSelect('subscription.newsletterEmail', 'newsletterEmail')
|
||||
.where({
|
||||
user: { id: uid },
|
||||
status: SubscriptionStatus.Active,
|
||||
type: subscriptionType || SubscriptionType.Newsletter, // default to newsletter
|
||||
})
|
||||
.orderBy('subscription.' + sortBy, sortOrder)
|
||||
.getMany()
|
||||
|
||||
return {
|
||||
subscriptions,
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(error)
|
||||
return {
|
||||
errorCodes: [SubscriptionsErrorCode.BadRequest],
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
export type UnsubscribeSuccessPartial = Merge<
|
||||
UnsubscribeSuccess,
|
||||
|
|
@ -318,7 +330,6 @@ export const updateSubscriptionResolver = authorized<
|
|||
const subscription = await getRepository(Subscription).findOneBy({
|
||||
id: input.id,
|
||||
user: { id: uid },
|
||||
status: SubscriptionStatus.Active,
|
||||
})
|
||||
if (!subscription) {
|
||||
log.info('subscription not found')
|
||||
|
|
@ -335,6 +346,7 @@ export const updateSubscriptionResolver = authorized<
|
|||
lastFetchedAt: input.lastFetchedAt
|
||||
? new Date(input.lastFetchedAt)
|
||||
: undefined,
|
||||
status: input.status || undefined,
|
||||
})
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -2511,6 +2511,7 @@ const schema = gql`
|
|||
name: String
|
||||
description: String
|
||||
lastFetchedAt: Date
|
||||
status: SubscriptionStatus
|
||||
}
|
||||
|
||||
union UpdateSubscriptionResult =
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import { gql } from 'graphql-request'
|
||||
import { gqlFetcher } from '../networkHelpers'
|
||||
import { Subscription } from '../queries/useGetSubscriptionsQuery'
|
||||
import {
|
||||
Subscription,
|
||||
SubscriptionStatus,
|
||||
} from '../queries/useGetSubscriptionsQuery'
|
||||
|
||||
interface UpdateSubscriptionResult {
|
||||
updateSubscription: UpdateSubscription
|
||||
|
|
@ -22,6 +25,7 @@ interface UpdateSubscriptionInput {
|
|||
lastFetchedAt?: Date
|
||||
name?: string
|
||||
description?: string
|
||||
status?: SubscriptionStatus
|
||||
}
|
||||
|
||||
export async function updateSubscriptionMutation(
|
||||
|
|
|
|||
|
|
@ -8,15 +8,16 @@ import { ConfirmationModal } from '../../../components/patterns/ConfirmationModa
|
|||
import {
|
||||
EmptySettingsRow,
|
||||
SettingsTable,
|
||||
SettingsTableRow,
|
||||
SettingsTableRow
|
||||
} from '../../../components/templates/settings/SettingsTable'
|
||||
import { theme } from '../../../components/tokens/stitches.config'
|
||||
import { formattedDateTime } from '../../../lib/dateFormatting'
|
||||
import { unsubscribeMutation } from '../../../lib/networking/mutations/unsubscribeMutation'
|
||||
import { updateSubscriptionMutation } from '../../../lib/networking/mutations/updateSubscriptionMutation'
|
||||
import {
|
||||
SubscriptionStatus,
|
||||
SubscriptionType,
|
||||
useGetSubscriptionsQuery,
|
||||
useGetSubscriptionsQuery
|
||||
} from '../../../lib/networking/queries/useGetSubscriptionsQuery'
|
||||
import { applyStoredTheme } from '../../../lib/themeUpdater'
|
||||
import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
|
||||
|
|
@ -30,6 +31,8 @@ export default function Rss(): JSX.Element {
|
|||
const [onDeleteId, setOnDeleteId] = useState<string>('')
|
||||
const [onEditId, setOnEditId] = useState('')
|
||||
const [onEditName, setOnEditName] = useState('')
|
||||
const [onPauseId, setOnPauseId] = useState('')
|
||||
const [onEditStatus, setOnEditStatus] = useState<SubscriptionStatus>()
|
||||
|
||||
async function updateSubscription(): Promise<void> {
|
||||
const result = await updateSubscriptionMutation({
|
||||
|
|
@ -61,6 +64,27 @@ export default function Rss(): JSX.Element {
|
|||
revalidate()
|
||||
}
|
||||
|
||||
async function onPause(
|
||||
id: string,
|
||||
status: SubscriptionStatus = 'UNSUBSCRIBED'
|
||||
): Promise<void> {
|
||||
const result = await updateSubscriptionMutation({
|
||||
id,
|
||||
status,
|
||||
})
|
||||
|
||||
const action = status == 'UNSUBSCRIBED' ? 'pause' : 'resume'
|
||||
|
||||
if (result) {
|
||||
showSuccessToast(`RSS feed ${action}d`, {
|
||||
position: 'bottom-right',
|
||||
})
|
||||
} else {
|
||||
showErrorToast(`Failed to ${action}`, { position: 'bottom-right' })
|
||||
}
|
||||
revalidate()
|
||||
}
|
||||
|
||||
applyStoredTheme(false)
|
||||
|
||||
return (
|
||||
|
|
@ -152,7 +176,14 @@ export default function Rss(): JSX.Element {
|
|||
console.log('onDelete triggered: ', subscription.id)
|
||||
setOnDeleteId(subscription.id)
|
||||
}}
|
||||
onEdit={() => {
|
||||
setOnEditStatus(
|
||||
subscription.status == 'ACTIVE' ? 'UNSUBSCRIBED' : 'ACTIVE'
|
||||
)
|
||||
setOnPauseId(subscription.id)
|
||||
}}
|
||||
deleteTitle="Delete"
|
||||
editTitle={subscription.status === 'ACTIVE' ? 'Pause' : 'Resume'}
|
||||
sublineElement={
|
||||
<StyledText
|
||||
css={{
|
||||
|
|
@ -171,6 +202,15 @@ export default function Rss(): JSX.Element {
|
|||
onClick={() => {
|
||||
router.push(`/home?q=in:inbox rss:"${subscription.url}"`)
|
||||
}}
|
||||
extraElement={
|
||||
<StyledText
|
||||
css={{
|
||||
fontSize: '12px',
|
||||
}}
|
||||
>
|
||||
{subscription.status === 'ACTIVE' ? 'Active' : 'Paused'}
|
||||
</StyledText>
|
||||
}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
|
@ -188,6 +228,25 @@ export default function Rss(): JSX.Element {
|
|||
onOpenChange={() => setOnDeleteId('')}
|
||||
/>
|
||||
)}
|
||||
|
||||
{onPauseId && (
|
||||
<ConfirmationModal
|
||||
message={`RSS feed will be ${
|
||||
onEditStatus === 'UNSUBSCRIBED' ? 'paused' : 'resumed'
|
||||
}. You can ${
|
||||
onEditStatus === 'UNSUBSCRIBED' ? 'resume' : 'pause'
|
||||
} it at any time.`}
|
||||
onAccept={async () => {
|
||||
await onPause(onPauseId, onEditStatus)
|
||||
setOnPauseId('')
|
||||
setOnEditStatus(undefined)
|
||||
}}
|
||||
onOpenChange={() => {
|
||||
setOnPauseId('')
|
||||
setOnEditStatus(undefined)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</SettingsTable>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue