mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Add labels and state to createArticle API
This commit is contained in:
parent
abd42f7064
commit
9857af27e2
8 changed files with 79 additions and 23 deletions
|
|
@ -265,9 +265,11 @@ export enum CreateArticleErrorCode {
|
|||
|
||||
export type CreateArticleInput = {
|
||||
articleSavingRequestId?: InputMaybe<Scalars['ID']>;
|
||||
labels?: InputMaybe<Array<CreateLabelInput>>;
|
||||
preparedDocument?: InputMaybe<PreparedDocumentInput>;
|
||||
skipParsing?: InputMaybe<Scalars['Boolean']>;
|
||||
source?: InputMaybe<Scalars['String']>;
|
||||
state?: InputMaybe<ArticleSavingRequestStatus>;
|
||||
uploadFileId?: InputMaybe<Scalars['ID']>;
|
||||
url: Scalars['String'];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -223,9 +223,11 @@ enum CreateArticleErrorCode {
|
|||
|
||||
input CreateArticleInput {
|
||||
articleSavingRequestId: ID
|
||||
labels: [CreateLabelInput!]
|
||||
preparedDocument: PreparedDocumentInput
|
||||
skipParsing: Boolean
|
||||
source: String
|
||||
state: ArticleSavingRequestStatus
|
||||
uploadFileId: ID
|
||||
url: String!
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ import {
|
|||
makeStorageFilePublic,
|
||||
} from '../../utils/uploads'
|
||||
import { WithDataSourcesContext } from '../types'
|
||||
import { createLabels } from '../../services/labels'
|
||||
|
||||
enum ArticleFormat {
|
||||
Markdown = 'markdown',
|
||||
|
|
@ -146,6 +147,8 @@ export const createArticleResolver = authorized<
|
|||
uploadFileId,
|
||||
skipParsing,
|
||||
source,
|
||||
state,
|
||||
labels: inputLabels,
|
||||
},
|
||||
},
|
||||
ctx
|
||||
|
|
@ -219,6 +222,19 @@ export const createArticleResolver = authorized<
|
|||
isArchived: false,
|
||||
},
|
||||
}
|
||||
// save state
|
||||
let archivedAt =
|
||||
state === ArticleSavingRequestStatus.Archived ? new Date() : null
|
||||
if (pageId) {
|
||||
const reminder = await models.reminder.getByRequestId(uid, pageId)
|
||||
if (reminder && reminder.archiveUntil) {
|
||||
archivedAt = new Date()
|
||||
}
|
||||
}
|
||||
// add labels to page
|
||||
const labels = inputLabels
|
||||
? await createLabels(ctx, inputLabels)
|
||||
: undefined
|
||||
|
||||
if (uploadFileId) {
|
||||
/* We do not trust the values from client, lookup upload file by querying
|
||||
|
|
@ -248,7 +264,7 @@ export const createArticleResolver = authorized<
|
|||
source !== 'puppeteer-parse' &&
|
||||
FORCE_PUPPETEER_URLS.some((regex) => regex.test(url))
|
||||
) {
|
||||
await createPageSaveRequest({ userId: uid, url })
|
||||
await createPageSaveRequest({ userId: uid, url, archivedAt, labels })
|
||||
return DUMMY_RESPONSE
|
||||
} else if (!skipParsing && preparedDocument?.document) {
|
||||
const parseResults = await traceAs<Promise<ParsedContentPuppeteer>>(
|
||||
|
|
@ -264,7 +280,7 @@ export const createArticleResolver = authorized<
|
|||
} else if (!preparedDocument?.document) {
|
||||
// We have a URL but no document, so we try to send this to puppeteer
|
||||
// and return a dummy response.
|
||||
await createPageSaveRequest({ userId: uid, url })
|
||||
await createPageSaveRequest({ userId: uid, url, archivedAt, labels })
|
||||
return DUMMY_RESPONSE
|
||||
}
|
||||
|
||||
|
|
@ -287,14 +303,6 @@ export const createArticleResolver = authorized<
|
|||
saveTime,
|
||||
})
|
||||
|
||||
let archive = false
|
||||
if (pageId) {
|
||||
const reminder = await models.reminder.getByRequestId(uid, pageId)
|
||||
if (reminder) {
|
||||
archive = reminder.archiveUntil || false
|
||||
}
|
||||
}
|
||||
|
||||
log.info('New article saving', {
|
||||
parsedArticle: Object.assign({}, articleToSave, {
|
||||
content: undefined,
|
||||
|
|
@ -308,7 +316,6 @@ export const createArticleResolver = authorized<
|
|||
},
|
||||
})
|
||||
|
||||
let uploadFileUrlOverride = ''
|
||||
if (uploadFileId) {
|
||||
const uploadFileData = await authTrx(async (tx) => {
|
||||
return models.uploadFile.setFileUploadComplete(uploadFileId, tx)
|
||||
|
|
@ -322,12 +329,11 @@ export const createArticleResolver = authorized<
|
|||
pageId
|
||||
)
|
||||
}
|
||||
uploadFileUrlOverride = await makeStorageFilePublic(
|
||||
uploadFileData.id,
|
||||
uploadFileData.fileName
|
||||
)
|
||||
await makeStorageFilePublic(uploadFileData.id, uploadFileData.fileName)
|
||||
}
|
||||
|
||||
// save page's state and labels
|
||||
articleToSave.archivedAt = archivedAt
|
||||
articleToSave.labels = labels
|
||||
if (
|
||||
pageId ||
|
||||
(pageId = (
|
||||
|
|
@ -338,7 +344,6 @@ export const createArticleResolver = authorized<
|
|||
)?.id)
|
||||
) {
|
||||
// update existing page's state from processing to succeeded
|
||||
articleToSave.archivedAt = archive ? saveTime : null
|
||||
const updated = await updatePage(pageId, articleToSave, {
|
||||
...ctx,
|
||||
uid,
|
||||
|
|
|
|||
|
|
@ -488,6 +488,8 @@ const schema = gql`
|
|||
uploadFileId: ID
|
||||
skipParsing: Boolean
|
||||
source: String
|
||||
state: ArticleSavingRequestStatus
|
||||
labels: [CreateLabelInput!]
|
||||
}
|
||||
enum CreateArticleErrorCode {
|
||||
UNABLE_TO_FETCH
|
||||
|
|
|
|||
|
|
@ -2,8 +2,15 @@ import { Knex } from 'knex'
|
|||
import { PubsubClient } from '../datalayer/pubsub'
|
||||
import { UserData } from '../datalayer/user/model'
|
||||
import { homePageURL } from '../env'
|
||||
import { SaveErrorCode, SaveFileInput, SaveResult } from '../generated/graphql'
|
||||
import {
|
||||
ArticleSavingRequestStatus,
|
||||
SaveErrorCode,
|
||||
SaveFileInput,
|
||||
SaveResult,
|
||||
} from '../generated/graphql'
|
||||
import { DataModels } from '../resolvers/types'
|
||||
import { createLabels } from './labels'
|
||||
import { updatePage } from '../elastic/pages'
|
||||
import { getStorageFileDetails } from '../utils/uploads'
|
||||
|
||||
type SaveContext = {
|
||||
|
|
@ -22,7 +29,7 @@ export const saveFile = async (
|
|||
input: SaveFileInput
|
||||
): Promise<SaveResult> => {
|
||||
console.log('saving file with input', input)
|
||||
|
||||
const pageId = input.clientRequestId
|
||||
const uploadFile = await ctx.models.uploadFile.getWhere({
|
||||
id: input.uploadFileId,
|
||||
userId: saver.id,
|
||||
|
|
@ -46,7 +53,29 @@ export const saveFile = async (
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: save labels and archive state
|
||||
// save state
|
||||
const archivedAt =
|
||||
input.state === ArticleSavingRequestStatus.Archived ? new Date() : null
|
||||
// add labels to page
|
||||
const labels = input.labels
|
||||
? await createLabels({ ...ctx, uid: saver.id }, input.labels)
|
||||
: undefined
|
||||
if (input.state || input.labels) {
|
||||
const updated = await updatePage(
|
||||
pageId,
|
||||
{
|
||||
archivedAt,
|
||||
labels,
|
||||
},
|
||||
ctx
|
||||
)
|
||||
if (!updated) {
|
||||
console.log('error updating page', pageId)
|
||||
return {
|
||||
errorCodes: [SaveErrorCode.Unknown],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
clientRequestId: input.clientRequestId,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import {
|
|||
} from '../util'
|
||||
import sinon from 'sinon'
|
||||
import * as createTask from '../../src/utils/createTask'
|
||||
import * as uploads from '../../src/utils/uploads'
|
||||
|
||||
chai.use(chaiString)
|
||||
|
||||
|
|
@ -643,6 +644,7 @@ describe('Article API', () => {
|
|||
})
|
||||
|
||||
it('saves the labels and archives the page', async () => {
|
||||
url = 'https://blog.omnivore.app/new-url-2'
|
||||
const state = ArticleSavingRequestStatus.Archived
|
||||
const labels = ['test name', 'test name 2']
|
||||
await graphqlRequest(
|
||||
|
|
@ -849,15 +851,27 @@ describe('Article API', () => {
|
|||
})
|
||||
})
|
||||
|
||||
xdescribe('SaveFile', () => {
|
||||
describe('SaveFile', () => {
|
||||
let query = ''
|
||||
let url = ''
|
||||
let uploadFileId = ''
|
||||
|
||||
before(() => {
|
||||
sinon.replace(
|
||||
uploads,
|
||||
'getStorageFileDetails',
|
||||
sinon.fake.resolves({ fileUrl: 'fake url', md5Hash: 'fake hash' })
|
||||
)
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
query = saveFileQuery(url, uploadFileId)
|
||||
})
|
||||
|
||||
after(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
context('when the file is not uploaded', () => {
|
||||
before(async () => {
|
||||
url = 'fake url'
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ describe('saveEmail', () => {
|
|||
})
|
||||
|
||||
it('doesnt fail if saved twice', async () => {
|
||||
nock('https://blog.omnivore.app').get('/fake-url').reply(404)
|
||||
nock('https://blog.omnivore.app').get('/fake-url').reply(200)
|
||||
|
||||
const url = 'https://blog.omnivore.app/fake-url'
|
||||
const title = 'fake title'
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ describe('saveNewsletterEmail', () => {
|
|||
})
|
||||
|
||||
it('adds the newsletter to the library', async () => {
|
||||
nock('https://blog.omnivore.app').get('/fake-url').reply(404)
|
||||
nock('https://blog.omnivore.app').get('/fake-url').reply(200)
|
||||
nock('https://blog.omnivore.app').head('/fake-url').reply(200)
|
||||
const url = 'https://blog.omnivore.app/fake-url'
|
||||
|
||||
await saveNewsletterEmail(
|
||||
|
|
@ -88,6 +89,7 @@ describe('saveNewsletterEmail', () => {
|
|||
})
|
||||
|
||||
it('adds a Newsletter label to that page', async () => {
|
||||
nock('https://blog.omnivore.app').get('/new-fake-url').reply(200)
|
||||
const url = 'https://blog.omnivore.app/new-fake-url'
|
||||
const newLabel = {
|
||||
name: 'Newsletter',
|
||||
|
|
|
|||
Loading…
Reference in a new issue