mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
change archive and trash from folder to state
This commit is contained in:
parent
9afbe2c1a7
commit
c5a97c7a41
9 changed files with 111 additions and 35 deletions
|
|
@ -5,8 +5,9 @@
|
|||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||
import { Readability } from '@omnivore/readability'
|
||||
import graphqlFields from 'graphql-fields'
|
||||
import { IsNull } from 'typeorm'
|
||||
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'
|
||||
import { LibraryItem } from '../../entity/library_item'
|
||||
import { LibraryItem, LibraryItemState } from '../../entity/library_item'
|
||||
import { env } from '../../env'
|
||||
import {
|
||||
ArticleError,
|
||||
|
|
@ -390,7 +391,10 @@ export const getArticleResolver = authorized<
|
|||
const libraryItem = await authTrx((tx) =>
|
||||
tx.withRepository(libraryItemRepository).findOne({
|
||||
select: selectColumns,
|
||||
where,
|
||||
where: {
|
||||
...where,
|
||||
deletedAt: IsNull(),
|
||||
},
|
||||
relations: {
|
||||
labels: true,
|
||||
highlights: {
|
||||
|
|
@ -406,7 +410,7 @@ export const getArticleResolver = authorized<
|
|||
})
|
||||
)
|
||||
|
||||
if (!libraryItem || libraryItem.folder === InFilter.TRASH) {
|
||||
if (!libraryItem) {
|
||||
return { errorCodes: [ArticleErrorCode.NotFound] }
|
||||
}
|
||||
|
||||
|
|
@ -528,8 +532,8 @@ export const setBookmarkArticleResolver = authorized<
|
|||
const deletedLibraryItem = await updateLibraryItem(
|
||||
articleID,
|
||||
{
|
||||
folder: InFilter.TRASH,
|
||||
savedAt: new Date(),
|
||||
state: LibraryItemState.Deleted,
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
uid,
|
||||
pubsub
|
||||
|
|
@ -867,7 +871,7 @@ export const setFavoriteArticleResolver = authorized<
|
|||
})
|
||||
|
||||
const getUpdateReason = (libraryItem: LibraryItem, since: Date) => {
|
||||
if (libraryItem.folder === InFilter.TRASH) {
|
||||
if (libraryItem.deletedAt) {
|
||||
return UpdateReason.Deleted
|
||||
}
|
||||
if (libraryItem.createdAt >= since) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { LibraryItemState } from '../../entity/library_item'
|
||||
import { env } from '../../env'
|
||||
import {
|
||||
ArchiveLinkError,
|
||||
|
|
@ -8,7 +9,6 @@ import {
|
|||
import { updateLibraryItem } from '../../services/library_item'
|
||||
import { analytics } from '../../utils/analytics'
|
||||
import { authorized } from '../../utils/helpers'
|
||||
import { InFilter } from '../../utils/search'
|
||||
|
||||
// export const updateLinkShareInfoResolver = authorized<
|
||||
// UpdateLinkShareInfoSuccess,
|
||||
|
|
@ -54,9 +54,20 @@ export const setLinkArchivedResolver = authorized<
|
|||
ArchiveLinkError,
|
||||
MutationSetLinkArchivedArgs
|
||||
>(async (_obj, args, { uid }) => {
|
||||
let state = LibraryItemState.Archived
|
||||
let archivedAt: Date | null = new Date()
|
||||
let event = 'link_archived'
|
||||
|
||||
const isUnarchive = !args.input.archived
|
||||
if (isUnarchive) {
|
||||
state = LibraryItemState.Succeeded
|
||||
archivedAt = null
|
||||
event = 'link_unarchived'
|
||||
}
|
||||
|
||||
analytics.track({
|
||||
userId: uid,
|
||||
event: args.input.archived ? 'link_archived' : 'link_unarchived',
|
||||
event,
|
||||
properties: {
|
||||
env: env.server.apiEnv,
|
||||
},
|
||||
|
|
@ -66,8 +77,8 @@ export const setLinkArchivedResolver = authorized<
|
|||
await updateLibraryItem(
|
||||
args.input.linkId,
|
||||
{
|
||||
savedAt: new Date(),
|
||||
folder: args.input.archived ? InFilter.ARCHIVE : InFilter.INBOX,
|
||||
state,
|
||||
archivedAt,
|
||||
},
|
||||
uid
|
||||
)
|
||||
|
|
@ -80,6 +91,6 @@ export const setLinkArchivedResolver = authorized<
|
|||
|
||||
return {
|
||||
linkId: args.input.linkId,
|
||||
message: 'Link Archived',
|
||||
message: event,
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { LibraryItemState } from '../../entity/library_item'
|
||||
import {
|
||||
MutationUpdatePageArgs,
|
||||
UpdatePageError,
|
||||
|
|
@ -20,6 +21,9 @@ export const updatePageResolver = authorized<
|
|||
savedAt: input.savedAt ? new Date(input.savedAt) : undefined,
|
||||
publishedAt: input.publishedAt ? new Date(input.publishedAt) : undefined,
|
||||
thumbnail: input.previewImage ?? undefined,
|
||||
state: input.state
|
||||
? (input.state as unknown as LibraryItemState)
|
||||
: undefined,
|
||||
},
|
||||
uid
|
||||
)
|
||||
|
|
|
|||
|
|
@ -105,9 +105,24 @@ const buildWhereClause = (
|
|||
}
|
||||
|
||||
if (args.inFilter !== InFilter.ALL) {
|
||||
queryBuilder.andWhere('library_item.folder = :folder', {
|
||||
folder: args.inFilter,
|
||||
})
|
||||
switch (args.inFilter) {
|
||||
case InFilter.INBOX:
|
||||
queryBuilder.andWhere('library_item.archived_at IS NULL')
|
||||
break
|
||||
case InFilter.ARCHIVE:
|
||||
queryBuilder.andWhere('library_item.archived_at IS NOT NULL')
|
||||
break
|
||||
case InFilter.TRASH:
|
||||
// return only deleted pages within 14 days
|
||||
queryBuilder.andWhere(
|
||||
"library_item.deleted_at >= now() - interval '14 days'"
|
||||
)
|
||||
break
|
||||
default:
|
||||
queryBuilder.andWhere('library_item.folder = :folder', {
|
||||
folder: args.inFilter,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (args.readFilter !== ReadFilter.ALL) {
|
||||
|
|
@ -227,7 +242,7 @@ const buildWhereClause = (
|
|||
}
|
||||
|
||||
if (!args.includeDeleted && args.inFilter !== InFilter.TRASH) {
|
||||
queryBuilder.andWhere("library_item.folder <> 'trash'")
|
||||
queryBuilder.andWhere("library_item.state <> 'DELETED'")
|
||||
}
|
||||
|
||||
if (args.noFilters) {
|
||||
|
|
@ -365,6 +380,8 @@ export const restoreLibraryItem = async (
|
|||
{
|
||||
state: LibraryItemState.Succeeded,
|
||||
savedAt: new Date(),
|
||||
archivedAt: null,
|
||||
deletedAt: null,
|
||||
},
|
||||
userId,
|
||||
pubsub
|
||||
|
|
@ -382,6 +399,21 @@ export const updateLibraryItem = async (
|
|||
const itemRepo = tx.withRepository(libraryItemRepository)
|
||||
await itemRepo.update(id, 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
|
||||
}
|
||||
|
||||
return itemRepo.findOneByOrFail({ id })
|
||||
},
|
||||
undefined,
|
||||
|
|
@ -600,14 +632,14 @@ export const updateLibraryItems = async (
|
|||
switch (action) {
|
||||
case BulkActionType.Archive:
|
||||
values = {
|
||||
folder: InFilter.ARCHIVE,
|
||||
savedAt: new Date(),
|
||||
archivedAt: new Date(),
|
||||
state: LibraryItemState.Archived,
|
||||
}
|
||||
break
|
||||
case BulkActionType.Delete:
|
||||
values = {
|
||||
savedAt: new Date(),
|
||||
folder: InFilter.TRASH,
|
||||
state: LibraryItemState.Deleted,
|
||||
deletedAt: new Date(),
|
||||
}
|
||||
break
|
||||
case BulkActionType.AddLabels:
|
||||
|
|
|
|||
|
|
@ -261,6 +261,9 @@ export const parsedContentToLibraryItem = ({
|
|||
uploadFileId: uploadFileId || undefined,
|
||||
readingProgressTopPercent: 0,
|
||||
readingProgressHighestReadAnchor: 0,
|
||||
state: state
|
||||
? (state as unknown as LibraryItemState)
|
||||
: LibraryItemState.Succeeded,
|
||||
createdAt: validatedDate(saveTime),
|
||||
savedAt: validatedDate(saveTime),
|
||||
siteName: parsedContent?.siteName,
|
||||
|
|
@ -269,7 +272,6 @@ export const parsedContentToLibraryItem = ({
|
|||
wordCount: wordsCount(parsedContent?.textContent || ''),
|
||||
contentReader: contentReaderForLibraryItem(itemType, uploadFileId),
|
||||
subscription: rssFeedUrl,
|
||||
folder: state === ArticleSavingRequestStatus.Archived ? 'archive' : 'inbox',
|
||||
state: LibraryItemState.Succeeded,
|
||||
folder: 'inbox',
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ export const libraryItemToArticle = (item: LibraryItem): Article => ({
|
|||
state: item.state as unknown as ArticleSavingRequestStatus,
|
||||
content: item.readableContent,
|
||||
hash: item.textContentHash || '',
|
||||
isArchived: item.folder === InFilter.ARCHIVE,
|
||||
isArchived: !!item.archivedAt,
|
||||
recommendations: item.recommendations?.map(
|
||||
recommandationDataToRecommendation
|
||||
),
|
||||
|
|
@ -259,7 +259,7 @@ export const libraryItemToSearchItem = (item: LibraryItem): SearchItem => ({
|
|||
url: item.originalUrl,
|
||||
state: item.state as unknown as ArticleSavingRequestStatus,
|
||||
content: item.readableContent,
|
||||
isArchived: item.folder === InFilter.ARCHIVE,
|
||||
isArchived: !!item.archivedAt,
|
||||
pageType: item.itemType as unknown as PageType,
|
||||
readingProgressPercent: item.readingProgressBottomPercent,
|
||||
contentReader: item.contentReader as unknown as ContentReader,
|
||||
|
|
|
|||
|
|
@ -410,7 +410,8 @@ describe('Article API', () => {
|
|||
title,
|
||||
user: { id: user.id },
|
||||
originalUrl: url,
|
||||
folder: 'archive',
|
||||
archivedAt: new Date(),
|
||||
state: LibraryItemState.Archived,
|
||||
},
|
||||
user.id
|
||||
)
|
||||
|
|
@ -608,7 +609,7 @@ describe('Article API', () => {
|
|||
).expect(200)
|
||||
|
||||
const savedItem = await findLibraryItemByUrl(url, user.id)
|
||||
expect(savedItem?.folder).to.eql('archive')
|
||||
expect(savedItem?.archivedAt).to.not.be.null
|
||||
expect(savedItem?.labels?.map((l) => l.name)).to.eql(labels)
|
||||
})
|
||||
})
|
||||
|
|
@ -1030,7 +1031,8 @@ describe('Article API', () => {
|
|||
readableContent: '<p>test 1</p>',
|
||||
slug: 'test slug 1',
|
||||
originalUrl: `${url}/test1`,
|
||||
folder: 'archive',
|
||||
archivedAt: new Date(),
|
||||
state: LibraryItemState.Archived,
|
||||
},
|
||||
{
|
||||
user,
|
||||
|
|
@ -1038,7 +1040,8 @@ describe('Article API', () => {
|
|||
readableContent: '<p>test 2</p>',
|
||||
slug: 'test slug 2',
|
||||
originalUrl: `${url}/test2`,
|
||||
folder: 'archive',
|
||||
archivedAt: new Date(),
|
||||
state: LibraryItemState.Archived,
|
||||
},
|
||||
{
|
||||
user,
|
||||
|
|
@ -1173,7 +1176,8 @@ describe('Article API', () => {
|
|||
readableContent: '<p>test 3</p>',
|
||||
slug: 'test slug 3',
|
||||
originalUrl: `${url}/test3`,
|
||||
folder: 'archive',
|
||||
archivedAt: new Date(),
|
||||
state: LibraryItemState.Archived,
|
||||
},
|
||||
],
|
||||
user.id
|
||||
|
|
@ -1263,7 +1267,7 @@ describe('Article API', () => {
|
|||
slug: 'test slug 1',
|
||||
originalUrl: `${url}/test1`,
|
||||
itemType: PageType.File,
|
||||
folder: 'archive',
|
||||
archivedAt: new Date(),
|
||||
},
|
||||
{
|
||||
user,
|
||||
|
|
@ -1271,7 +1275,7 @@ describe('Article API', () => {
|
|||
readableContent: '<p>test 2</p>',
|
||||
slug: 'test slug 2',
|
||||
originalUrl: `${url}/test2`,
|
||||
folder: 'archive',
|
||||
archivedAt: new Date(),
|
||||
readingProgressBottomPercent: 100,
|
||||
},
|
||||
{
|
||||
|
|
@ -1313,7 +1317,7 @@ describe('Article API', () => {
|
|||
slug: 'test slug 1',
|
||||
originalUrl: `${url}/test1`,
|
||||
subscription: 'feed',
|
||||
folder: 'archive',
|
||||
archivedAt: new Date(),
|
||||
},
|
||||
{
|
||||
user,
|
||||
|
|
@ -1329,7 +1333,7 @@ describe('Article API', () => {
|
|||
readableContent: '<p>test 3</p>',
|
||||
slug: 'test slug 3',
|
||||
originalUrl: `${url}/test3`,
|
||||
folder: 'archive',
|
||||
archivedAt: new Date(),
|
||||
},
|
||||
],
|
||||
user.id
|
||||
|
|
@ -1362,7 +1366,7 @@ describe('Article API', () => {
|
|||
readableContent: '<p>test 1</p>',
|
||||
slug: 'test slug 1',
|
||||
originalUrl: `${url}/test1`,
|
||||
folder: 'trash',
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
{
|
||||
user,
|
||||
|
|
@ -1371,7 +1375,7 @@ describe('Article API', () => {
|
|||
slug: 'test slug 2',
|
||||
originalUrl: `${url}/test2`,
|
||||
readingProgressBottomPercent: 100,
|
||||
folder: 'trash',
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
{
|
||||
user,
|
||||
|
|
@ -1733,7 +1737,7 @@ describe('Article API', () => {
|
|||
for (let i = 0; i < 3; i++) {
|
||||
await updateLibraryItem(
|
||||
items[i].id,
|
||||
{ folder: 'trash', savedAt: new Date() },
|
||||
{ state: LibraryItemState.Deleted, deletedAt: new Date() },
|
||||
user.id
|
||||
)
|
||||
deletedItems.push(items[i])
|
||||
|
|
|
|||
9
packages/db/migrations/0148.do.update_folder_in_library_item.sql
Executable file
9
packages/db/migrations/0148.do.update_folder_in_library_item.sql
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
-- Type: DO
|
||||
-- Name: update_folder_in_library_item
|
||||
-- Description: Update folder column in library_item table
|
||||
|
||||
BEGIN;
|
||||
|
||||
UPDATE omnivore.library_item SET folder = 'inbox' WHERE folder = 'archive' OR folder = 'trash';
|
||||
|
||||
COMMIT;
|
||||
10
packages/db/migrations/0148.undo.update_folder_in_library_item.sql
Executable file
10
packages/db/migrations/0148.undo.update_folder_in_library_item.sql
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
-- Type: UNDO
|
||||
-- Name: update_folder_in_library_item
|
||||
-- Description: Update folder column in library_item table
|
||||
|
||||
BEGIN;
|
||||
|
||||
UPDATE omnivore.library_item SET folder = 'archive' WHERE archived_at IS NOT NULL;
|
||||
UPDATE omnivore.library_item SET folder = 'trash' WHERE deleted_at IS NOT NULL;
|
||||
|
||||
COMMIT;
|
||||
Loading…
Reference in a new issue