mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Merge pull request #1406 from omnivore-app/set-voice-in-user-personalization
set voice in user personalization
This commit is contained in:
commit
a78074b0da
10 changed files with 81 additions and 30 deletions
|
|
@ -22,7 +22,7 @@ export class NewsletterEmail {
|
|||
user!: User
|
||||
|
||||
@Column('varchar', { nullable: true })
|
||||
confirmationCode?: string
|
||||
confirmationCode?: string | null
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt!: Date
|
||||
|
|
|
|||
|
|
@ -19,34 +19,34 @@ export class UserPersonalization {
|
|||
user!: User
|
||||
|
||||
@Column('text', { nullable: true })
|
||||
fontFamily?: string
|
||||
fontFamily?: string | null
|
||||
|
||||
@Column('integer', { nullable: true })
|
||||
fontSize?: number
|
||||
fontSize?: number | null
|
||||
|
||||
@Column('text', { nullable: true })
|
||||
margin?: number
|
||||
margin?: number | null
|
||||
|
||||
@Column('text', { nullable: true })
|
||||
theme?: string
|
||||
theme?: string | null
|
||||
|
||||
@Column('text', { nullable: true })
|
||||
libraryLayoutType?: string
|
||||
libraryLayoutType?: string | null
|
||||
|
||||
@Column('text', { nullable: true })
|
||||
librarySortOrder?: string
|
||||
librarySortOrder?: string | null
|
||||
|
||||
@Column('text', { nullable: true })
|
||||
speechVoice?: string
|
||||
speechVoice?: string | null
|
||||
|
||||
@Column('text', { nullable: true })
|
||||
speechSecondaryVoice?: string
|
||||
speechSecondaryVoice?: string | null
|
||||
|
||||
@Column('text', { nullable: true })
|
||||
speechRate?: string
|
||||
speechRate?: string | null
|
||||
|
||||
@Column('text', { nullable: true })
|
||||
speechVolume?: string
|
||||
speechVolume?: string | null
|
||||
|
||||
@CreateDateColumn({ default: () => 'CURRENT_TIMESTAMP' })
|
||||
createdAt!: Date
|
||||
|
|
|
|||
|
|
@ -1936,6 +1936,7 @@ export type SetUserPersonalizationError = {
|
|||
};
|
||||
|
||||
export enum SetUserPersonalizationErrorCode {
|
||||
NotFound = 'NOT_FOUND',
|
||||
Unauthorized = 'UNAUTHORIZED'
|
||||
}
|
||||
|
||||
|
|
@ -1945,6 +1946,10 @@ export type SetUserPersonalizationInput = {
|
|||
libraryLayoutType?: InputMaybe<Scalars['String']>;
|
||||
librarySortOrder?: InputMaybe<SortOrder>;
|
||||
margin?: InputMaybe<Scalars['Int']>;
|
||||
speechRate?: InputMaybe<Scalars['String']>;
|
||||
speechSecondaryVoice?: InputMaybe<Scalars['String']>;
|
||||
speechVoice?: InputMaybe<Scalars['String']>;
|
||||
speechVolume?: InputMaybe<Scalars['String']>;
|
||||
theme?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
|
@ -2458,6 +2463,10 @@ export type UserPersonalization = {
|
|||
libraryLayoutType?: Maybe<Scalars['String']>;
|
||||
librarySortOrder?: Maybe<SortOrder>;
|
||||
margin?: Maybe<Scalars['Int']>;
|
||||
speechRate?: Maybe<Scalars['String']>;
|
||||
speechSecondaryVoice?: Maybe<Scalars['String']>;
|
||||
speechVoice?: Maybe<Scalars['String']>;
|
||||
speechVolume?: Maybe<Scalars['String']>;
|
||||
theme?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
|
@ -4767,6 +4776,10 @@ export type UserPersonalizationResolvers<ContextType = ResolverContext, ParentTy
|
|||
libraryLayoutType?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
librarySortOrder?: Resolver<Maybe<ResolversTypes['SortOrder']>, ParentType, ContextType>;
|
||||
margin?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
|
||||
speechRate?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
speechSecondaryVoice?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
speechVoice?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
speechVolume?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
theme?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1432,6 +1432,7 @@ type SetUserPersonalizationError {
|
|||
}
|
||||
|
||||
enum SetUserPersonalizationErrorCode {
|
||||
NOT_FOUND
|
||||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
|
|
@ -1441,6 +1442,10 @@ input SetUserPersonalizationInput {
|
|||
libraryLayoutType: String
|
||||
librarySortOrder: SortOrder
|
||||
margin: Int
|
||||
speechRate: String
|
||||
speechSecondaryVoice: String
|
||||
speechVoice: String
|
||||
speechVolume: String
|
||||
theme: String
|
||||
}
|
||||
|
||||
|
|
@ -1911,6 +1916,10 @@ type UserPersonalization {
|
|||
libraryLayoutType: String
|
||||
librarySortOrder: SortOrder
|
||||
margin: Int
|
||||
speechRate: String
|
||||
speechSecondaryVoice: String
|
||||
speechVoice: String
|
||||
speechVolume: String
|
||||
theme: String
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +1,45 @@
|
|||
import {
|
||||
GetUserPersonalizationResult,
|
||||
GetUserPersonalizationError,
|
||||
SetUserPersonalizationSuccess,
|
||||
SetUserPersonalizationError,
|
||||
GetUserPersonalizationResult,
|
||||
MutationSetUserPersonalizationArgs,
|
||||
SetUserPersonalizationError,
|
||||
SetUserPersonalizationErrorCode,
|
||||
SetUserPersonalizationSuccess,
|
||||
SortOrder,
|
||||
} from '../../generated/graphql'
|
||||
import { authorized } from '../../utils/helpers'
|
||||
import { UserPersonalization } from '../../entity/user_personalization'
|
||||
import { AppDataSource } from '../../server'
|
||||
import { getRepository, setClaims } from '../../entity/utils'
|
||||
|
||||
export const setUserPersonalizationResolver = authorized<
|
||||
SetUserPersonalizationSuccess,
|
||||
SetUserPersonalizationError,
|
||||
MutationSetUserPersonalizationArgs
|
||||
>(async (_, { input }, { models, authTrx, claims: { uid } }) => {
|
||||
const updatedUserPersonalization = await authTrx((tx) =>
|
||||
models.userPersonalization.upsert(
|
||||
>(async (_, { input }, { claims: { uid }, log }) => {
|
||||
log.info('setUserPersonalizationResolver', { uid, input })
|
||||
|
||||
const result = await AppDataSource.transaction(async (entityManager) => {
|
||||
await setClaims(entityManager, uid)
|
||||
|
||||
return entityManager.getRepository(UserPersonalization).upsert(
|
||||
{
|
||||
userId: uid,
|
||||
user: { id: uid },
|
||||
...input,
|
||||
},
|
||||
tx
|
||||
['user']
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
if (result.identifiers.length === 0) {
|
||||
return {
|
||||
errorCodes: [SetUserPersonalizationErrorCode.NotFound],
|
||||
}
|
||||
}
|
||||
|
||||
const updatedUserPersonalization = await getRepository(
|
||||
UserPersonalization
|
||||
).findOneBy({ id: result.identifiers[0].id as string })
|
||||
|
||||
// Cast SortOrder from string to enum
|
||||
const librarySortOrder = updatedUserPersonalization?.librarySortOrder as
|
||||
|
|
|
|||
|
|
@ -963,6 +963,10 @@ const schema = gql`
|
|||
margin: Int
|
||||
libraryLayoutType: String
|
||||
librarySortOrder: SortOrder
|
||||
speechVoice: String
|
||||
speechSecondaryVoice: String
|
||||
speechRate: String
|
||||
speechVolume: String
|
||||
}
|
||||
|
||||
# Query: UserPersonalization
|
||||
|
|
@ -985,6 +989,7 @@ const schema = gql`
|
|||
| SetUserPersonalizationError
|
||||
enum SetUserPersonalizationErrorCode {
|
||||
UNAUTHORIZED
|
||||
NOT_FOUND
|
||||
}
|
||||
type SetUserPersonalizationError {
|
||||
errorCodes: [SetUserPersonalizationErrorCode!]!
|
||||
|
|
@ -999,6 +1004,10 @@ const schema = gql`
|
|||
margin: Int
|
||||
libraryLayoutType: String @sanitize
|
||||
librarySortOrder: SortOrder
|
||||
speechVoice: String
|
||||
speechSecondaryVoice: String
|
||||
speechRate: String
|
||||
speechVolume: String
|
||||
}
|
||||
|
||||
# Type: ArticleSavingRequest
|
||||
|
|
|
|||
|
|
@ -106,9 +106,7 @@ const validateInvite = async (
|
|||
return false
|
||||
}
|
||||
const membershipRepo = entityManager.getRepository(GroupMembership)
|
||||
const numMembers = await membershipRepo.count({
|
||||
where: { invite: invite },
|
||||
})
|
||||
const numMembers = await membershipRepo.countBy({ invite: { id: invite.id } })
|
||||
if (numMembers >= invite.maxMembers) {
|
||||
console.log('rejecting invite, too many users', invite, numMembers)
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import { env } from '../env'
|
||||
|
||||
export const corsConfig = {
|
||||
credentials: true,
|
||||
// allow https://studio.apollographql.com for local env
|
||||
origin: [
|
||||
'https://omnivore.app',
|
||||
'https://dev.omnivore.app',
|
||||
|
|
@ -9,5 +12,6 @@ export const corsConfig = {
|
|||
'https://web-demo.omnivore.app',
|
||||
'http://localhost:3000',
|
||||
'lsp://logseq.io',
|
||||
env.dev.isLocal && 'https://studio.apollographql.com',
|
||||
],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import sinon, { SinonFakeTimers } from 'sinon'
|
|||
import { env } from '../../src/env'
|
||||
import { Like } from 'typeorm'
|
||||
|
||||
describe('features resolvers', () => {
|
||||
xdescribe('features resolvers', () => {
|
||||
let loginUser: User
|
||||
let authToken: string
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ describe('Integrations resolvers', () => {
|
|||
|
||||
before(async () => {
|
||||
existingIntegration = await getRepository(Integration).save({
|
||||
user: loginUser,
|
||||
user: { id: loginUser.id },
|
||||
type: DataIntegrationType.Readwise,
|
||||
token: 'fakeToken',
|
||||
})
|
||||
|
|
@ -138,7 +138,7 @@ describe('Integrations resolvers', () => {
|
|||
|
||||
afterEach(async () => {
|
||||
await getRepository(Integration).delete({
|
||||
user: loginUser,
|
||||
user: { id: loginUser.id },
|
||||
type: integrationType,
|
||||
})
|
||||
})
|
||||
|
|
@ -191,7 +191,7 @@ describe('Integrations resolvers', () => {
|
|||
before(async () => {
|
||||
otherUser = await createTestUser('otherUser')
|
||||
existingIntegration = await getRepository(Integration).save({
|
||||
user: otherUser,
|
||||
user: { id: otherUser.id },
|
||||
type: DataIntegrationType.Readwise,
|
||||
token: 'fakeToken',
|
||||
})
|
||||
|
|
@ -219,7 +219,7 @@ describe('Integrations resolvers', () => {
|
|||
context('when integration belongs to the user', () => {
|
||||
before(async () => {
|
||||
existingIntegration = await getRepository(Integration).save({
|
||||
user: loginUser,
|
||||
user: { id: loginUser.id },
|
||||
type: DataIntegrationType.Readwise,
|
||||
token: 'fakeToken',
|
||||
})
|
||||
|
|
@ -321,7 +321,7 @@ describe('Integrations resolvers', () => {
|
|||
|
||||
before(async () => {
|
||||
existingIntegration = await getRepository(Integration).save({
|
||||
user: loginUser,
|
||||
user: { id: loginUser.id },
|
||||
type: DataIntegrationType.Readwise,
|
||||
token: 'fakeToken',
|
||||
})
|
||||
|
|
@ -367,7 +367,7 @@ describe('Integrations resolvers', () => {
|
|||
|
||||
beforeEach(async () => {
|
||||
existingIntegration = await getRepository(Integration).save({
|
||||
user: loginUser,
|
||||
user: { id: loginUser.id },
|
||||
type: DataIntegrationType.Readwise,
|
||||
token: 'fakeToken',
|
||||
taskName: 'some task name',
|
||||
|
|
|
|||
Loading…
Reference in a new issue