Merge pull request #2445 from omnivore-app/feature/create-labels

feat: create labels if not exist when setting labels
This commit is contained in:
Hongbo Wu 2023-07-03 16:54:15 +08:00 committed by GitHub
commit a413521e3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 97 additions and 42 deletions

View file

@ -1,7 +1,7 @@
import { Label, PageContext } from './types'
import { client, INDEX_ALIAS } from './index'
import { EntityType } from '../datalayer/pubsub'
import { ResponseError } from '@elastic/elasticsearch/lib/errors'
import { EntityType } from '../datalayer/pubsub'
import { client, INDEX_ALIAS } from './index'
import { Label, PageContext } from './types'
export const addLabelInPage = async (
pageId: string,
@ -273,7 +273,8 @@ export const updateLabel = async (
export const setLabelsForHighlight = async (
highlightId: string,
labels: Label[],
ctx: PageContext
ctx: PageContext,
labelsToAdd?: Label[]
): Promise<boolean> => {
try {
const { body } = await client.updateByQuery({
@ -304,14 +305,17 @@ export const setLabelsForHighlight = async (
conflicts: 'proceed', // ignore conflicts
})
if (body.updated > 0) {
for (const label of labels) {
await ctx.pubsub.entityCreated<Label & { highlightId: string }>(
EntityType.LABEL,
{ highlightId, ...label },
ctx.uid
if (labelsToAdd) {
// publish labels to be added
await Promise.all(
labelsToAdd.map((label) =>
ctx.pubsub.entityCreated<Label & { highlightId: string }>(
EntityType.LABEL,
{ highlightId, ...label },
ctx.uid
)
)
}
)
}
return true

View file

@ -2481,11 +2481,13 @@ export enum SetLabelsErrorCode {
export type SetLabelsForHighlightInput = {
highlightId: Scalars['ID'];
labelIds: Array<Scalars['ID']>;
labelIds?: InputMaybe<Array<Scalars['ID']>>;
labels?: InputMaybe<Array<CreateLabelInput>>;
};
export type SetLabelsInput = {
labelIds: Array<Scalars['ID']>;
labelIds?: InputMaybe<Array<Scalars['ID']>>;
labels?: InputMaybe<Array<CreateLabelInput>>;
pageId: Scalars['ID'];
};

View file

@ -1850,11 +1850,13 @@ enum SetLabelsErrorCode {
input SetLabelsForHighlightInput {
highlightId: ID!
labelIds: [ID!]!
labelIds: [ID!]
labels: [CreateLabelInput!]
}
input SetLabelsInput {
labelIds: [ID!]!
labelIds: [ID!]
labels: [CreateLabelInput!]
pageId: ID!
}

View file

@ -41,6 +41,7 @@ import {
import { AppDataSource } from '../../server'
import {
createLabel,
createLabels,
getLabelByName,
getLabelsByIds,
} from '../../services/labels'
@ -210,7 +211,14 @@ export const setLabelsResolver = authorized<
>(async (_, { input }, { claims: { uid }, log, pubsub }) => {
log.info('setLabelsResolver')
const { pageId, labelIds } = input
const { pageId, labelIds, labels } = input
if (!labelIds && !labels) {
log.info('labelIds or labels must be provided')
return {
errorCodes: [SetLabelsErrorCode.BadRequest],
}
}
try {
const user = await getRepository(User).findOneBy({ id: uid })
@ -232,25 +240,35 @@ export const setLabelsResolver = authorized<
}
}
const labels = await getLabelsByIds(uid, labelIds)
if (labels.length !== labelIds.length) {
return {
errorCodes: [SetLabelsErrorCode.NotFound],
const ctx = {
uid,
pubsub,
refresh: true,
}
let labelsSet: Label[] = []
if (labels && labels.length > 0) {
// for new clients that send label names
// create labels if they don't exist
labelsSet = await createLabels(ctx, labels)
} else if (labelIds && labelIds.length > 0) {
// for old clients that send labelIds
labelsSet = await getLabelsByIds(uid, labelIds)
if (labelsSet.length !== labelIds.length) {
return {
errorCodes: [SetLabelsErrorCode.NotFound],
}
}
}
// filter out labels that are already set
const labelsToAdd = labels.filter(
const labelsToAdd = labelsSet.filter(
(label) => !page.labels?.some((pageLabel) => pageLabel.id === label.id)
)
// update labels in the page
const updated = await updateLabelsInPage(
pageId,
labels,
{
pubsub,
uid,
refresh: true,
},
labelsSet,
ctx,
labelsToAdd
)
if (!updated) {
@ -270,7 +288,7 @@ export const setLabelsResolver = authorized<
})
return {
labels,
labels: labelsSet,
}
} catch (error) {
log.error(error)
@ -361,7 +379,14 @@ export const setLabelsForHighlightResolver = authorized<
>(async (_, { input }, { claims: { uid }, log, pubsub }) => {
log.info('setLabelsForHighlightResolver')
const { highlightId, labelIds } = input
const { highlightId, labelIds, labels } = input
if (!labelIds && !labels) {
log.info('labelIds or labels must be provided')
return {
errorCodes: [SetLabelsErrorCode.BadRequest],
}
}
try {
const user = await getRepository(User).findOneBy({ id: uid })
@ -383,19 +408,39 @@ export const setLabelsForHighlightResolver = authorized<
}
}
const labels = await getLabelsByIds(uid, labelIds)
if (labels.length !== labelIds.length) {
return {
errorCodes: [SetLabelsErrorCode.NotFound],
const ctx = {
uid,
pubsub,
refresh: true,
}
let labelsSet: Label[] = []
if (labels && labels.length > 0) {
// for new clients that send label names
// create labels if they don't exist
labelsSet = await createLabels(ctx, labels)
} else if (labelIds && labelIds.length > 0) {
// for old clients that send labelIds
labelsSet = await getLabelsByIds(uid, labelIds)
if (labelsSet.length !== labelIds.length) {
return {
errorCodes: [SetLabelsErrorCode.NotFound],
}
}
}
// filter out labels that are already set
const labelsToAdd = labelsSet.filter(
(label) =>
!highlight.labels?.some(
(highlightLabel) => highlightLabel.id === label.id
)
)
// set labels in the highlights
const updated = await setLabelsForHighlight(highlightId, labels, {
pubsub,
uid,
refresh: true,
})
const updated = await setLabelsForHighlight(
highlightId,
labelsSet,
ctx,
labelsToAdd
)
if (!updated) {
return {
errorCodes: [SetLabelsErrorCode.NotFound],
@ -413,7 +458,7 @@ export const setLabelsForHighlightResolver = authorized<
})
return {
labels,
labels: labelsSet,
}
} catch (error) {
log.error(error)

View file

@ -1504,7 +1504,8 @@ const schema = gql`
input SetLabelsInput {
pageId: ID!
labelIds: [ID!]!
labelIds: [ID!]
labels: [CreateLabelInput!]
}
union SetLabelsResult = SetLabelsSuccess | SetLabelsError
@ -1837,7 +1838,8 @@ const schema = gql`
input SetLabelsForHighlightInput {
highlightId: ID!
labelIds: [ID!]!
labelIds: [ID!]
labels: [CreateLabelInput!]
}
union TypeaheadSearchResult = TypeaheadSearchSuccess | TypeaheadSearchError