@@ -188,6 +188,12 @@ struct JSONImportSheet: View {
188188 HStack {
189189 Button ( " Cancel " ) { isPresented = false }
190190 . keyboardShortcut ( . cancelAction)
191+ if let message = validationMessage {
192+ Text ( message)
193+ . font ( . caption)
194+ . foregroundStyle ( . red)
195+ . lineLimit ( 2 )
196+ }
191197 Spacer ( )
192198 Button ( " Import " ) { performImport ( ) }
193199 . buttonStyle ( . borderedProminent)
@@ -233,12 +239,12 @@ struct JSONImportSheet: View {
233239 ScrollView {
234240 Grid ( alignment: . leading, horizontalSpacing: 12 , verticalSpacing: 6 ) {
235241 GridRow {
236- Text ( " Import " )
237- Text ( " JSON field " )
238- Text ( " Column " )
242+ Toggle ( " " , isOn: allMappingsIncluded)
243+ . labelsHidden ( )
244+ . help ( String ( localized: " Import all fields " ) )
245+ Text ( " JSON field " ) . font ( . caption) . foregroundStyle ( . secondary)
246+ Text ( " Column " ) . font ( . caption) . foregroundStyle ( . secondary)
239247 }
240- . font ( . caption)
241- . foregroundStyle ( . secondary)
242248 Divider ( ) . gridCellColumns ( 3 )
243249
244250 ForEach ( mappings) { row in
@@ -271,15 +277,15 @@ struct JSONImportSheet: View {
271277 ScrollView {
272278 Grid ( alignment: . leading, horizontalSpacing: 10 , verticalSpacing: 6 ) {
273279 GridRow {
274- Text ( " Create " )
275- Text ( " Column " )
276- Text ( " Type " )
277- Text ( " Key " )
278- Text ( " Null " )
279- Text ( " Default " )
280+ Toggle ( " " , isOn: allColumnsIncluded)
281+ . labelsHidden ( )
282+ . help ( String ( localized: " Create all columns " ) )
283+ Text ( " Column " ) . font ( . caption) . foregroundStyle ( . secondary)
284+ Text ( " Type " ) . font ( . caption) . foregroundStyle ( . secondary)
285+ Text ( " Key " ) . font ( . caption) . foregroundStyle ( . secondary)
286+ Text ( " Null " ) . font ( . caption) . foregroundStyle ( . secondary)
287+ Text ( " Default " ) . font ( . caption) . foregroundStyle ( . secondary)
280288 }
281- . font ( . caption)
282- . foregroundStyle ( . secondary)
283289 Divider ( ) . gridCellColumns ( 6 )
284290
285291 ForEach ( newColumns) { row in
@@ -327,6 +333,42 @@ struct JSONImportSheet: View {
327333 return $newColumns [ index]
328334 }
329335
336+ private var allMappingsIncluded : Binding < Bool > {
337+ Binding (
338+ get: { !mappings. isEmpty && mappings. allSatisfy ( \. include) } ,
339+ set: { value in for index in mappings. indices { mappings [ index] . include = value } }
340+ )
341+ }
342+
343+ private var allColumnsIncluded : Binding < Bool > {
344+ Binding (
345+ get: { !newColumns. isEmpty && newColumns. allSatisfy ( \. include) } ,
346+ set: { value in for index in newColumns. indices { newColumns [ index] . include = value } }
347+ )
348+ }
349+
350+ private var validationMessage : String ? {
351+ switch destination {
352+ case . existingTable:
353+ let columns = mappings. filter { $0. include } . compactMap { $0. targetColumn? . lowercased ( ) }
354+ if Set ( columns) . count != columns. count {
355+ return String ( localized: " Each column can be mapped from only one field. " )
356+ }
357+ return nil
358+ case . newTable:
359+ let names = newColumns
360+ . filter { $0. include }
361+ . map { $0. name. trimmingCharacters ( in: . whitespaces) . lowercased ( ) }
362+ if names. contains ( where: \. isEmpty) {
363+ return String ( localized: " Every included column needs a name. " )
364+ }
365+ if Set ( names) . count != names. count {
366+ return String ( localized: " Column names must be unique. " )
367+ }
368+ return nil
369+ }
370+ }
371+
330372 private var dialectTypes : [ String ] {
331373 PluginManager . shared. columnTypesByCategory ( for: connection. type)
332374 . values
@@ -356,7 +398,7 @@ struct JSONImportSheet: View {
356398 }
357399
358400 private var canImport : Bool {
359- guard !( importService? . state. isImporting ?? false ) else { return false }
401+ guard !( importService? . state. isImporting ?? false ) , validationMessage == nil else { return false }
360402 switch destination {
361403 case . existingTable:
362404 return selectedTargetTable != nil && mappings. contains { $0. include && $0. targetColumn != nil }
0 commit comments