mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
fix recovered deleted items still shown in trash
This commit is contained in:
parent
7bf3f1bbf4
commit
3b8b48bc21
10 changed files with 68 additions and 74 deletions
|
|
@ -5,13 +5,13 @@
|
|||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
import { Readability } from '@omnivore/readability'
|
||||
import graphqlFields from 'graphql-fields'
|
||||
import { DeepPartial } from 'typeorm'
|
||||
import { Not } from 'typeorm'
|
||||
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'
|
||||
import { LibraryItem, LibraryItemState } from '../../entity/library_item'
|
||||
import { env } from '../../env'
|
||||
import {
|
||||
ArticleError,
|
||||
ArticleErrorCode,
|
||||
ArticleSavingRequestStatus,
|
||||
ArticleSuccess,
|
||||
BulkActionError,
|
||||
BulkActionErrorCode,
|
||||
|
|
@ -58,6 +58,7 @@ import {
|
|||
addLabelsToLibraryItem,
|
||||
findLabelsByIds,
|
||||
findOrCreateLabels,
|
||||
saveLabelsInLibraryItem,
|
||||
} from '../../services/labels'
|
||||
import {
|
||||
createLibraryItem,
|
||||
|
|
@ -287,6 +288,7 @@ export const createArticleResolver = authorized<
|
|||
uploadFileHash,
|
||||
canonicalUrl,
|
||||
uploadFileId,
|
||||
state,
|
||||
})
|
||||
|
||||
log.info('New article saving', {
|
||||
|
|
@ -311,13 +313,6 @@ export const createArticleResolver = authorized<
|
|||
await makeStorageFilePublic(uploadFileData.id, uploadFileData.fileName)
|
||||
}
|
||||
|
||||
// save page's state and labels
|
||||
libraryItemToSave.archivedAt =
|
||||
state === ArticleSavingRequestStatus.Archived ? new Date() : null
|
||||
if (inputLabels) {
|
||||
libraryItemToSave.labels = await findOrCreateLabels(inputLabels, uid)
|
||||
}
|
||||
|
||||
let libraryItemToReturn: LibraryItem
|
||||
|
||||
const existingLibraryItem = await findLibraryItemByUrl(
|
||||
|
|
@ -326,15 +321,15 @@ export const createArticleResolver = authorized<
|
|||
)
|
||||
articleSavingRequestId = existingLibraryItem?.id || articleSavingRequestId
|
||||
if (articleSavingRequestId) {
|
||||
// update existing page's state from processing to succeeded
|
||||
// update existing item's state from processing to succeeded
|
||||
libraryItemToReturn = await updateLibraryItem(
|
||||
articleSavingRequestId,
|
||||
libraryItemToSave,
|
||||
libraryItemToSave as QueryDeepPartialEntity<LibraryItem>,
|
||||
uid,
|
||||
pubsub
|
||||
)
|
||||
} else {
|
||||
// create new page in database
|
||||
// create new item in database
|
||||
libraryItemToReturn = await createLibraryItem(
|
||||
libraryItemToSave,
|
||||
uid,
|
||||
|
|
@ -342,6 +337,12 @@ export const createArticleResolver = authorized<
|
|||
)
|
||||
}
|
||||
|
||||
// save labels in item
|
||||
if (inputLabels) {
|
||||
const labels = await findOrCreateLabels(inputLabels, user.id)
|
||||
await saveLabelsInLibraryItem(labels, libraryItemToReturn.id, user.id)
|
||||
}
|
||||
|
||||
log.info(
|
||||
'item created in database',
|
||||
libraryItemToReturn.id,
|
||||
|
|
@ -524,7 +525,7 @@ export const setBookmarkArticleResolver = authorized<
|
|||
SetBookmarkArticleError,
|
||||
MutationSetBookmarkArticleArgs
|
||||
>(async (_, { input: { articleID } }, { uid, log, pubsub }) => {
|
||||
// delete the page and its metadata
|
||||
// delete the item and its metadata
|
||||
const deletedLibraryItem = await updateLibraryItem(
|
||||
articleID,
|
||||
{
|
||||
|
|
@ -545,7 +546,7 @@ export const setBookmarkArticleResolver = authorized<
|
|||
})
|
||||
|
||||
log.info('Article unbookmarked', {
|
||||
page: Object.assign({}, deletedLibraryItem, {
|
||||
item: Object.assign({}, deletedLibraryItem, {
|
||||
readableContent: undefined,
|
||||
originalContent: undefined,
|
||||
}),
|
||||
|
|
@ -601,7 +602,7 @@ export const saveArticleReadingProgressResolver = authorized<
|
|||
: undefined
|
||||
// If setting to zero we accept the update, otherwise we require it
|
||||
// be greater than the current reading progress.
|
||||
const updatedPart: DeepPartial<LibraryItem> = {
|
||||
const updatedPart: QueryDeepPartialEntity<LibraryItem> = {
|
||||
readingProgressBottomPercent:
|
||||
readingProgressPercent === 0
|
||||
? 0
|
||||
|
|
@ -834,7 +835,7 @@ export const setFavoriteArticleResolver = authorized<
|
|||
}
|
||||
|
||||
const labels = await findOrCreateLabels([label], uid)
|
||||
// adds Favorites label to page
|
||||
// adds Favorites label to item
|
||||
await addLabelsToLibraryItem(labels, id, uid)
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -125,15 +125,13 @@ export const uploadFileRequestResolver = authorized<
|
|||
let createdItemId: string | undefined = undefined
|
||||
if (input.createPageEntry) {
|
||||
// If we have a file:// URL, don't try to match it
|
||||
// and create a copy of the page, just create a
|
||||
// and create a copy of the item, just create a
|
||||
// new item.
|
||||
const item = await findLibraryItemByUrl(input.url, uid)
|
||||
if (item) {
|
||||
await updateLibraryItem(
|
||||
item.id,
|
||||
{
|
||||
savedAt: new Date(),
|
||||
archivedAt: null,
|
||||
state: LibraryItemState.Processing,
|
||||
},
|
||||
uid
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import {
|
|||
createLibraryItem,
|
||||
findLibraryItemById,
|
||||
findLibraryItemByUrl,
|
||||
updateLibraryItem,
|
||||
restoreLibraryItem,
|
||||
} from '../services/library_item'
|
||||
import { addRecommendation } from '../services/recommendation'
|
||||
import { getTokenByRequest } from '../utils/auth'
|
||||
|
|
@ -105,18 +105,8 @@ export function pageRouter() {
|
|||
const item = await findLibraryItemByUrl(url, claims.uid)
|
||||
|
||||
if (item) {
|
||||
logger.info('updating page')
|
||||
await updateLibraryItem(
|
||||
item.id,
|
||||
{
|
||||
savedAt: new Date(),
|
||||
archivedAt: null,
|
||||
state: LibraryItemState.Succeeded,
|
||||
},
|
||||
claims.uid
|
||||
)
|
||||
await restoreLibraryItem(item.id, claims.uid)
|
||||
} else {
|
||||
logger.info('creating page')
|
||||
await createLibraryItem(
|
||||
{
|
||||
originalUrl: signedUrl,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import express from 'express'
|
||||
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'
|
||||
import { LibraryItem, LibraryItemState } from '../../entity/library_item'
|
||||
import { readPushSubscription } from '../../pubsub'
|
||||
import { authTrx } from '../../repository'
|
||||
|
|
@ -81,7 +82,9 @@ export function contentServiceRouter() {
|
|||
return
|
||||
}
|
||||
|
||||
const itemToUpdate: Partial<LibraryItem> = { originalContent: msg.content }
|
||||
const itemToUpdate: QueryDeepPartialEntity<LibraryItem> = {
|
||||
originalContent: msg.content,
|
||||
}
|
||||
if (msg.title) itemToUpdate.title = msg.title
|
||||
if (msg.author) itemToUpdate.author = msg.author
|
||||
if (msg.description) itemToUpdate.description = msg.description
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ export const createPageSaveRequest = async ({
|
|||
if (!libraryItem) {
|
||||
logger.info('libraryItem does not exist', { url })
|
||||
|
||||
// create processing page
|
||||
// create processing item
|
||||
libraryItem = await createLibraryItem(
|
||||
{
|
||||
id: articleSavingRequestId,
|
||||
|
|
@ -145,7 +145,7 @@ export const createPageSaveRequest = async ({
|
|||
// get priority by checking rate limit if not specified
|
||||
priority = priority || (await getPriorityByRateLimit(userId))
|
||||
|
||||
// enqueue task to parse page
|
||||
// enqueue task to parse item
|
||||
await enqueueParseRequest({
|
||||
url,
|
||||
userId,
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ export const findLibraryItemByUrl = async (
|
|||
)
|
||||
}
|
||||
|
||||
export const refreshLibraryItem = async (
|
||||
export const restoreLibraryItem = async (
|
||||
id: string,
|
||||
userId: string,
|
||||
pubsub = createPubSubClient()
|
||||
|
|
@ -353,6 +353,7 @@ export const refreshLibraryItem = async (
|
|||
state: LibraryItemState.Succeeded,
|
||||
savedAt: new Date(),
|
||||
archivedAt: null,
|
||||
deletedAt: null,
|
||||
},
|
||||
userId,
|
||||
pubsub
|
||||
|
|
@ -361,17 +362,30 @@ export const refreshLibraryItem = async (
|
|||
|
||||
export const updateLibraryItem = async (
|
||||
id: string,
|
||||
libraryItem: DeepPartial<LibraryItem>,
|
||||
libraryItem: QueryDeepPartialEntity<LibraryItem>,
|
||||
userId: string,
|
||||
pubsub = createPubSubClient()
|
||||
): Promise<LibraryItem> => {
|
||||
const updatedLibraryItem = await authTrx(
|
||||
async (tx) => {
|
||||
const itemRepo = tx.withRepository(libraryItemRepository)
|
||||
await itemRepo.update(
|
||||
id,
|
||||
libraryItem as QueryDeepPartialEntity<LibraryItem>
|
||||
)
|
||||
|
||||
// reset deletedAt and archivedAt
|
||||
switch (libraryItem.state) {
|
||||
case LibraryItemState.Archived:
|
||||
libraryItem.archivedAt = new Date()
|
||||
break
|
||||
case LibraryItemState.Deleted:
|
||||
libraryItem.deletedAt = new Date()
|
||||
break
|
||||
case LibraryItemState.Processing:
|
||||
case LibraryItemState.Succeeded:
|
||||
libraryItem.archivedAt = null
|
||||
libraryItem.deletedAt = null
|
||||
break
|
||||
}
|
||||
|
||||
await itemRepo.update(id, libraryItem)
|
||||
|
||||
return itemRepo.findOneByOrFail({ id })
|
||||
},
|
||||
|
|
@ -379,7 +393,7 @@ export const updateLibraryItem = async (
|
|||
userId
|
||||
)
|
||||
|
||||
await pubsub.entityUpdated<DeepPartial<LibraryItem>>(
|
||||
await pubsub.entityUpdated<QueryDeepPartialEntity<LibraryItem>>(
|
||||
EntityType.PAGE,
|
||||
{ ...libraryItem, id },
|
||||
userId
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { findOrCreateLabels, saveLabelsInLibraryItem } from './labels'
|
|||
import {
|
||||
createLibraryItem,
|
||||
findLibraryItemByUrl,
|
||||
updateLibraryItem,
|
||||
restoreLibraryItem,
|
||||
} from './library_item'
|
||||
import { updateReceivedEmail } from './received_emails'
|
||||
import { saveSubscription } from './subscriptions'
|
||||
|
|
@ -72,12 +72,8 @@ export const saveEmail = async (
|
|||
input.userId
|
||||
)
|
||||
if (existingLibraryItem) {
|
||||
const updatedLibraryItem = await updateLibraryItem(
|
||||
const updatedLibraryItem = await restoreLibraryItem(
|
||||
existingLibraryItem.id,
|
||||
{
|
||||
archivedAt: null,
|
||||
state: LibraryItemState.Succeeded,
|
||||
},
|
||||
input.userId
|
||||
)
|
||||
logger.info('updated page from email', updatedLibraryItem)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
import { LibraryItemState } from '../entity/library_item'
|
||||
import { User } from '../entity/user'
|
||||
import { homePageURL } from '../env'
|
||||
import {
|
||||
ArticleSavingRequestStatus,
|
||||
SaveErrorCode,
|
||||
SaveFileInput,
|
||||
SaveResult,
|
||||
} from '../generated/graphql'
|
||||
import { SaveErrorCode, SaveFileInput, SaveResult } from '../generated/graphql'
|
||||
import { getStorageFileDetails } from '../utils/uploads'
|
||||
import { findOrCreateLabels } from './labels'
|
||||
import { findOrCreateLabels, saveLabelsInLibraryItem } from './labels'
|
||||
import { updateLibraryItem } from './library_item'
|
||||
import { findUploadFileById, setFileUploadComplete } from './upload_file'
|
||||
|
||||
|
|
@ -34,24 +29,20 @@ export const saveFile = async (
|
|||
}
|
||||
|
||||
if (input.state || input.labels) {
|
||||
// save state
|
||||
const archivedAt =
|
||||
input.state === ArticleSavingRequestStatus.Archived ? new Date() : null
|
||||
// add labels to page
|
||||
const labels = input.labels
|
||||
? await findOrCreateLabels(input.labels, user.id)
|
||||
: undefined
|
||||
await updateLibraryItem(
|
||||
input.clientRequestId,
|
||||
{
|
||||
archivedAt,
|
||||
labels,
|
||||
state: input.state
|
||||
? (input.state as unknown as LibraryItemState)
|
||||
: LibraryItemState.Succeeded,
|
||||
},
|
||||
user.id
|
||||
)
|
||||
// add labels to item
|
||||
if (input.labels) {
|
||||
const labels = await findOrCreateLabels(input.labels, user.id)
|
||||
await saveLabelsInLibraryItem(labels, input.clientRequestId, user.id)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Readability } from '@omnivore/readability'
|
||||
import { DeepPartial } from 'typeorm'
|
||||
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'
|
||||
import { LibraryItem, LibraryItemState } from '../entity/library_item'
|
||||
import { User } from '../entity/user'
|
||||
import { homePageURL } from '../env'
|
||||
|
|
@ -85,7 +86,7 @@ export const savePage = async (
|
|||
itemType: parseResult.pageType,
|
||||
originalHtml: parseResult.domContent,
|
||||
canonicalUrl: parseResult.canonicalUrl,
|
||||
saveTime: input.savedAt ? new Date(input.savedAt) : undefined,
|
||||
saveTime: input.savedAt ? new Date(input.savedAt) : new Date(),
|
||||
publishedAt: input.publishedAt ? new Date(input.publishedAt) : undefined,
|
||||
state: input.state || undefined,
|
||||
rssFeedUrl: input.rssFeedUrl,
|
||||
|
|
@ -109,11 +110,7 @@ export const savePage = async (
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// save state
|
||||
itemToSave.archivedAt =
|
||||
input.state === ArticleSavingRequestStatus.Archived ? new Date() : null
|
||||
|
||||
// check if the page already exists
|
||||
// check if the item already exists
|
||||
const existingLibraryItem = await authTrx((t) =>
|
||||
t.getRepository(LibraryItem).findOneBy({
|
||||
user: { id: user.id },
|
||||
|
|
@ -121,7 +118,7 @@ export const savePage = async (
|
|||
})
|
||||
)
|
||||
if (existingLibraryItem) {
|
||||
// we don't want to update an rss feed page if rss-feeder is tring to re-save it
|
||||
// we don't want to update an rss feed item if rss-feeder is tring to re-save it
|
||||
if (existingLibraryItem.subscription === input.rssFeedUrl) {
|
||||
return {
|
||||
clientRequestId,
|
||||
|
|
@ -131,14 +128,18 @@ export const savePage = async (
|
|||
|
||||
clientRequestId = existingLibraryItem.id
|
||||
slug = existingLibraryItem.slug
|
||||
await updateLibraryItem(clientRequestId, itemToSave, user.id)
|
||||
await updateLibraryItem(
|
||||
clientRequestId,
|
||||
itemToSave as QueryDeepPartialEntity<LibraryItem>,
|
||||
user.id
|
||||
)
|
||||
} else {
|
||||
// do not publish a pubsub event if the page is imported
|
||||
// do not publish a pubsub event if the item is imported
|
||||
const newItem = await createLibraryItem(itemToSave, user.id)
|
||||
clientRequestId = newItem.id
|
||||
}
|
||||
|
||||
// add labels to page
|
||||
// save labels in item
|
||||
if (input.labels) {
|
||||
const labels = await findOrCreateLabels(input.labels, user.id)
|
||||
await saveLabelsInLibraryItem(labels, clientRequestId, user.id)
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ export const libraryItemToSearchItem = (item: LibraryItem): SearchItem => ({
|
|||
|
||||
export const isParsingTimeout = (libraryItem: LibraryItem): boolean => {
|
||||
return (
|
||||
// page processed more than 30 seconds ago
|
||||
// item processed more than 30 seconds ago
|
||||
libraryItem.state === LibraryItemState.Processing &&
|
||||
libraryItem.savedAt.getTime() < new Date().getTime() - 1000 * 30
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue