Add labels and state to createArticle API

This commit is contained in:
Hongbo Wu 2023-03-06 15:26:04 +08:00
parent abd42f7064
commit 9857af27e2
8 changed files with 79 additions and 23 deletions

View file

@ -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'];
};

View file

@ -223,9 +223,11 @@ enum CreateArticleErrorCode {
input CreateArticleInput {
articleSavingRequestId: ID
labels: [CreateLabelInput!]
preparedDocument: PreparedDocumentInput
skipParsing: Boolean
source: String
state: ArticleSavingRequestStatus
uploadFileId: ID
url: String!
}

View file

@ -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,

View file

@ -488,6 +488,8 @@ const schema = gql`
uploadFileId: ID
skipParsing: Boolean
source: String
state: ArticleSavingRequestStatus
labels: [CreateLabelInput!]
}
enum CreateArticleErrorCode {
UNABLE_TO_FETCH

View file

@ -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,

View file

@ -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'

View file

@ -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'

View file

@ -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',