mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Merge pull request #2445 from omnivore-app/feature/create-labels
feat: create labels if not exist when setting labels
This commit is contained in:
commit
a413521e3b
5 changed files with 97 additions and 42 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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'];
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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!
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue