Skip to content

Commit e01ed33

Browse files
authored
🐛 Fix inability to save library changes (#754)
1 parent e372bff commit e01ed33

File tree

5 files changed

+65
-9
lines changed

5 files changed

+65
-9
lines changed

packages/browser/src/components/library/createOrUpdate/schema.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,14 @@ export const buildSchema = (
116116
.string()
117117
.min(1, { message: 'Library name is required' })
118118
.refine(
119-
// return falsy value to indicate failure. In this case, if library name is already taken,
120-
// and we aren't editing that library, then it should fail.
121-
(val) => !(existingLibraries.some((l) => l.name === val) && library?.name !== val),
119+
// return falsy value to indicate failure.
120+
// If the library name is already taken -> fail
121+
// If the name is not changing -> pass (override the fail)
122+
(val) => {
123+
const isTaken = existingLibraries.some((l) => l.name === val)
124+
const isUnchanged = library?.name === val
125+
return !isTaken || isUnchanged
126+
},
122127
(val) => ({
123128
message: `You already have a library named ${val}.`,
124129
}),
@@ -127,11 +132,18 @@ export const buildSchema = (
127132
.string()
128133
.min(1, { message: 'Library path is required' })
129134
.refine(
130-
// check if path is parent to any existing library
131-
// if so, and we aren't editing that library, return falsy value to indicate failure
132-
(val) => !(existingLibraries.some((l) => l.path.startsWith(val)) && library?.path !== val),
135+
// return falsy value to indicate failure.
136+
// If the path is a parent to any existing library -> fail
137+
// If the path is a child to any existing library -> fail
138+
// If the path is not changing -> pass (override the fail)
139+
(val) => {
140+
const isParent = existingLibraries.some((l) => l.path.startsWith(val))
141+
const isChild = existingLibraries.some((l) => val.startsWith(l.path))
142+
const isUnchanged = library?.path === val
143+
return (!isParent && !isChild) || isUnchanged
144+
},
133145
() => ({
134-
message: 'Invalid library, parent directory already exists as library.',
146+
message: 'Invalid library path, a parent or sub-directory already exists as a library.',
135147
}),
136148
),
137149
processMetadata: z.boolean().default(true),

packages/browser/src/components/library/createOrUpdate/sections/BasicLibraryInformation.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default function BasicLibraryInformation({ onSetShowDirectoryPicker }: Pr
3030

3131
return (
3232
<div className="flex flex-grow flex-col gap-6">
33-
<div className="flex flex-col flex-wrap gap-y-6 md:flex-row md:gap-x-6 md:gap-y-0">
33+
<div className="flex flex-col flex-wrap gap-y-6 md:flex-row md:gap-x-6 md:gap-y-6">
3434
<Input
3535
variant="primary"
3636
label={t(getKey('name.label'))}

packages/browser/src/scenes/library/tabs/settings/basics/BasicSettingsScene.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { zodResolver } from '@hookform/resolvers/zod'
2+
import { useSDK, useSuspenseGraphQL } from '@stump/client'
23
import { Button, Form } from '@stump/components'
4+
import { graphql } from '@stump/graphql'
35
import { useCallback, useMemo, useState } from 'react'
46
import { useForm } from 'react-hook-form'
57

@@ -8,15 +10,34 @@ import {
810
buildSchema,
911
CreateOrUpdateLibrarySchema,
1012
formDefaults,
13+
intoThumbnailConfig,
1114
} from '@/components/library/createOrUpdate'
1215
import { BasicLibraryInformation } from '@/components/library/createOrUpdate/sections'
1316

1417
import { useLibraryManagement } from '../context'
1518

19+
const query = graphql(`
20+
query BasicSettingsSceneExistingLibraries {
21+
libraries(pagination: { none: { unpaginated: true } }) {
22+
nodes {
23+
id
24+
name
25+
path
26+
}
27+
}
28+
}
29+
`)
30+
1631
export default function BasicSettingsScene() {
1732
const { library, patch } = useLibraryManagement()
33+
const { sdk } = useSDK()
34+
const {
35+
data: {
36+
libraries: { nodes: libraries },
37+
},
38+
} = useSuspenseGraphQL(query, [sdk.cacheKeys.libraryCreateLibraryQuery])
1839

19-
const schema = useMemo(() => buildSchema([], library), [library])
40+
const schema = useMemo(() => buildSchema(libraries, library), [libraries, library])
2041
const form = useForm<CreateOrUpdateLibrarySchema>({
2142
defaultValues: formDefaults(library),
2243
reValidateMode: 'onChange',
@@ -42,6 +63,7 @@ export default function BasicSettingsScene() {
4263
const handleSubmit = useCallback(
4364
(values: CreateOrUpdateLibrarySchema) => {
4465
patch({
66+
config: { thumbnailConfig: intoThumbnailConfig(values.thumbnailConfig) },
4567
description: values.description,
4668
name: values.name,
4769
path: values.path,

packages/graphql/src/client/gql.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ type Documents = {
131131
"\n\tfragment LibrarySettingsConfig on Library {\n\t\tconfig {\n\t\t\tid\n\t\t\tconvertRarToZip\n\t\t\thardDeleteConversions\n\t\t\tdefaultReadingDir\n\t\t\tdefaultReadingMode\n\t\t\tdefaultReadingImageScaleFit\n\t\t\tgenerateFileHashes\n\t\t\tgenerateKoreaderHashes\n\t\t\tprocessMetadata\n\t\t\twatch\n\t\t\tlibraryPattern\n\t\t\tthumbnailConfig {\n\t\t\t\t__typename\n\t\t\t\tresizeMethod {\n\t\t\t\t\t__typename\n\t\t\t\t\t... on ScaleEvenlyByFactor {\n\t\t\t\t\t\tfactor\n\t\t\t\t\t}\n\t\t\t\t\t... on ExactDimensionResize {\n\t\t\t\t\t\twidth\n\t\t\t\t\t\theight\n\t\t\t\t\t}\n\t\t\t\t\t... on ScaledDimensionResize {\n\t\t\t\t\t\tdimension\n\t\t\t\t\t\tsize\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tformat\n\t\t\t\tquality\n\t\t\t\tpage\n\t\t\t}\n\t\t\tignoreRules\n\t\t}\n\t}\n": typeof types.LibrarySettingsConfigFragmentDoc,
132132
"\n\tmutation LibrarySettingsRouterEditLibraryMutation($id: ID!, $input: CreateOrUpdateLibraryInput!) {\n\t\tupdateLibrary(id: $id, input: $input) {\n\t\t\tid\n\t\t}\n\t}\n": typeof types.LibrarySettingsRouterEditLibraryMutationDocument,
133133
"\n\tmutation LibrarySettingsRouterScanLibraryMutation($id: ID!, $options: JSON) {\n\t\tscanLibrary(id: $id, options: $options)\n\t}\n": typeof types.LibrarySettingsRouterScanLibraryMutationDocument,
134+
"\n\tquery BasicSettingsSceneExistingLibraries {\n\t\tlibraries(pagination: { none: { unpaginated: true } }) {\n\t\t\tnodes {\n\t\t\t\tid\n\t\t\t\tname\n\t\t\t\tpath\n\t\t\t}\n\t\t}\n\t}\n": typeof types.BasicSettingsSceneExistingLibrariesDocument,
134135
"\n\tquery LibraryExclusionsUsersQuery {\n\t\tusers(pagination: { none: { unpaginated: true } }) {\n\t\t\tnodes {\n\t\t\t\tid\n\t\t\t\tusername\n\t\t\t}\n\t\t}\n\t}\n": typeof types.LibraryExclusionsUsersQueryDocument,
135136
"\n\tquery LibraryExclusionsQuery($id: ID!) {\n\t\tlibraryById(id: $id) {\n\t\t\texcludedUsers {\n\t\t\t\tid\n\t\t\t\tusername\n\t\t\t}\n\t\t}\n\t}\n": typeof types.LibraryExclusionsQueryDocument,
136137
"\n\tmutation UpdateLibraryExclusions($id: ID!, $userIds: [String!]!) {\n\t\tupdateLibraryExcludedUsers(id: $id, userIds: $userIds) {\n\t\t\tid\n\t\t\texcludedUsers {\n\t\t\t\tid\n\t\t\t\tusername\n\t\t\t}\n\t\t}\n\t}\n": typeof types.UpdateLibraryExclusionsDocument,
@@ -324,6 +325,7 @@ const documents: Documents = {
324325
"\n\tfragment LibrarySettingsConfig on Library {\n\t\tconfig {\n\t\t\tid\n\t\t\tconvertRarToZip\n\t\t\thardDeleteConversions\n\t\t\tdefaultReadingDir\n\t\t\tdefaultReadingMode\n\t\t\tdefaultReadingImageScaleFit\n\t\t\tgenerateFileHashes\n\t\t\tgenerateKoreaderHashes\n\t\t\tprocessMetadata\n\t\t\twatch\n\t\t\tlibraryPattern\n\t\t\tthumbnailConfig {\n\t\t\t\t__typename\n\t\t\t\tresizeMethod {\n\t\t\t\t\t__typename\n\t\t\t\t\t... on ScaleEvenlyByFactor {\n\t\t\t\t\t\tfactor\n\t\t\t\t\t}\n\t\t\t\t\t... on ExactDimensionResize {\n\t\t\t\t\t\twidth\n\t\t\t\t\t\theight\n\t\t\t\t\t}\n\t\t\t\t\t... on ScaledDimensionResize {\n\t\t\t\t\t\tdimension\n\t\t\t\t\t\tsize\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tformat\n\t\t\t\tquality\n\t\t\t\tpage\n\t\t\t}\n\t\t\tignoreRules\n\t\t}\n\t}\n": types.LibrarySettingsConfigFragmentDoc,
325326
"\n\tmutation LibrarySettingsRouterEditLibraryMutation($id: ID!, $input: CreateOrUpdateLibraryInput!) {\n\t\tupdateLibrary(id: $id, input: $input) {\n\t\t\tid\n\t\t}\n\t}\n": types.LibrarySettingsRouterEditLibraryMutationDocument,
326327
"\n\tmutation LibrarySettingsRouterScanLibraryMutation($id: ID!, $options: JSON) {\n\t\tscanLibrary(id: $id, options: $options)\n\t}\n": types.LibrarySettingsRouterScanLibraryMutationDocument,
328+
"\n\tquery BasicSettingsSceneExistingLibraries {\n\t\tlibraries(pagination: { none: { unpaginated: true } }) {\n\t\t\tnodes {\n\t\t\t\tid\n\t\t\t\tname\n\t\t\t\tpath\n\t\t\t}\n\t\t}\n\t}\n": types.BasicSettingsSceneExistingLibrariesDocument,
327329
"\n\tquery LibraryExclusionsUsersQuery {\n\t\tusers(pagination: { none: { unpaginated: true } }) {\n\t\t\tnodes {\n\t\t\t\tid\n\t\t\t\tusername\n\t\t\t}\n\t\t}\n\t}\n": types.LibraryExclusionsUsersQueryDocument,
328330
"\n\tquery LibraryExclusionsQuery($id: ID!) {\n\t\tlibraryById(id: $id) {\n\t\t\texcludedUsers {\n\t\t\t\tid\n\t\t\t\tusername\n\t\t\t}\n\t\t}\n\t}\n": types.LibraryExclusionsQueryDocument,
329331
"\n\tmutation UpdateLibraryExclusions($id: ID!, $userIds: [String!]!) {\n\t\tupdateLibraryExcludedUsers(id: $id, userIds: $userIds) {\n\t\t\tid\n\t\t\texcludedUsers {\n\t\t\t\tid\n\t\t\t\tusername\n\t\t\t}\n\t\t}\n\t}\n": types.UpdateLibraryExclusionsDocument,
@@ -865,6 +867,10 @@ export function graphql(source: "\n\tmutation LibrarySettingsRouterEditLibraryMu
865867
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
866868
*/
867869
export function graphql(source: "\n\tmutation LibrarySettingsRouterScanLibraryMutation($id: ID!, $options: JSON) {\n\t\tscanLibrary(id: $id, options: $options)\n\t}\n"): typeof import('./graphql').LibrarySettingsRouterScanLibraryMutationDocument;
870+
/**
871+
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
872+
*/
873+
export function graphql(source: "\n\tquery BasicSettingsSceneExistingLibraries {\n\t\tlibraries(pagination: { none: { unpaginated: true } }) {\n\t\t\tnodes {\n\t\t\t\tid\n\t\t\t\tname\n\t\t\t\tpath\n\t\t\t}\n\t\t}\n\t}\n"): typeof import('./graphql').BasicSettingsSceneExistingLibrariesDocument;
868874
/**
869875
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
870876
*/

packages/graphql/src/client/graphql.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4061,6 +4061,11 @@ export type LibrarySettingsRouterScanLibraryMutationMutationVariables = Exact<{
40614061

40624062
export type LibrarySettingsRouterScanLibraryMutationMutation = { __typename?: 'Mutation', scanLibrary: boolean };
40634063

4064+
export type BasicSettingsSceneExistingLibrariesQueryVariables = Exact<{ [key: string]: never; }>;
4065+
4066+
4067+
export type BasicSettingsSceneExistingLibrariesQuery = { __typename?: 'Query', libraries: { __typename?: 'PaginatedLibraryResponse', nodes: Array<{ __typename?: 'Library', id: string, name: string, path: string }> } };
4068+
40644069
export type LibraryExclusionsUsersQueryQueryVariables = Exact<{ [key: string]: never; }>;
40654070

40664071

@@ -6734,6 +6739,17 @@ export const LibrarySettingsRouterScanLibraryMutationDocument = new TypedDocumen
67346739
scanLibrary(id: $id, options: $options)
67356740
}
67366741
`) as unknown as TypedDocumentString<LibrarySettingsRouterScanLibraryMutationMutation, LibrarySettingsRouterScanLibraryMutationMutationVariables>;
6742+
export const BasicSettingsSceneExistingLibrariesDocument = new TypedDocumentString(`
6743+
query BasicSettingsSceneExistingLibraries {
6744+
libraries(pagination: {none: {unpaginated: true}}) {
6745+
nodes {
6746+
id
6747+
name
6748+
path
6749+
}
6750+
}
6751+
}
6752+
`) as unknown as TypedDocumentString<BasicSettingsSceneExistingLibrariesQuery, BasicSettingsSceneExistingLibrariesQueryVariables>;
67376753
export const LibraryExclusionsUsersQueryDocument = new TypedDocumentString(`
67386754
query LibraryExclusionsUsersQuery {
67396755
users(pagination: {none: {unpaginated: true}}) {

0 commit comments

Comments
 (0)