Skip to content

Commit

Permalink
add Field VM
Browse files Browse the repository at this point in the history
  • Loading branch information
georgeef committed Nov 5, 2024
1 parent 0fcda6b commit cdef7b4
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 4 deletions.
12 changes: 12 additions & 0 deletions MMEX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
925EAC222CDAB03B003CEAB3 /* AttachmentReload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925EAC212CDAB03B003CEAB3 /* AttachmentReload.swift */; };
925EAC242CDAB100003CEAB3 /* AttachmentListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925EAC232CDAB100003CEAB3 /* AttachmentListView.swift */; };
925EAC272CDAB134003CEAB3 /* AttachmentEditView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925EAC262CDAB134003CEAB3 /* AttachmentEditView.swift */; };
925EAC292CDABF9F003CEAB3 /* FieldList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925EAC282CDABF9F003CEAB3 /* FieldList.swift */; };
925EAC2B2CDAC10D003CEAB3 /* FieldGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925EAC2A2CDAC10D003CEAB3 /* FieldGroup.swift */; };
925EAC2D2CDAC36F003CEAB3 /* FieldSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925EAC2C2CDAC36F003CEAB3 /* FieldSearch.swift */; };
929EF65F2C9FF2DE0051A3E6 /* AssetData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929EF65E2C9FF2DE0051A3E6 /* AssetData.swift */; };
929EF6612C9FF2FD0051A3E6 /* StockData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929EF6602C9FF2FD0051A3E6 /* StockData.swift */; };
929EF6632C9FF3ED0051A3E6 /* AssetRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929EF6622C9FF3ED0051A3E6 /* AssetRepository.swift */; };
Expand Down Expand Up @@ -281,6 +284,9 @@
925EAC212CDAB03B003CEAB3 /* AttachmentReload.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentReload.swift; sourceTree = "<group>"; };
925EAC232CDAB100003CEAB3 /* AttachmentListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentListView.swift; sourceTree = "<group>"; };
925EAC262CDAB134003CEAB3 /* AttachmentEditView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentEditView.swift; sourceTree = "<group>"; };
925EAC282CDABF9F003CEAB3 /* FieldList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FieldList.swift; sourceTree = "<group>"; };
925EAC2A2CDAC10D003CEAB3 /* FieldGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FieldGroup.swift; sourceTree = "<group>"; };
925EAC2C2CDAC36F003CEAB3 /* FieldSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FieldSearch.swift; sourceTree = "<group>"; };
929EF65E2C9FF2DE0051A3E6 /* AssetData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetData.swift; sourceTree = "<group>"; };
929EF6602C9FF2FD0051A3E6 /* StockData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StockData.swift; sourceTree = "<group>"; };
929EF6622C9FF3ED0051A3E6 /* AssetRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetRepository.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -461,6 +467,7 @@
925EAB9C2CCDD67C003CEAB3 /* CategoryGroup.swift */,
924353362CCD2DDA0052E4BC /* PayeeGroup.swift */,
925EAC0C2CDA89BD003CEAB3 /* TagGroup.swift */,
925EAC2A2CDAC10D003CEAB3 /* FieldGroup.swift */,
925EAC1B2CDAA900003CEAB3 /* AttachmentGroup.swift */,
);
path = Group;
Expand All @@ -477,6 +484,7 @@
925EAB9E2CCDDD77003CEAB3 /* CategorySearch.swift */,
924353402CCD2FFA0052E4BC /* PayeeSearch.swift */,
925EAC0E2CDA8B1A003CEAB3 /* TagSearch.swift */,
925EAC2C2CDAC36F003CEAB3 /* FieldSearch.swift */,
925EAC1D2CDAAD3F003CEAB3 /* AttachmentSearch.swift */,
);
path = Search;
Expand All @@ -496,6 +504,7 @@
925EABB72CD6FAC7003CEAB3 /* TransactionList.swift */,
925EABB92CD6FBF7003CEAB3 /* ScheduledList.swift */,
925EAC0A2CDA8903003CEAB3 /* TagList.swift */,
925EAC282CDABF9F003CEAB3 /* FieldList.swift */,
925EAC192CDAA813003CEAB3 /* AttachmentList.swift */,
9243531C2CC5201C0052E4BC /* ManageList.swift */,
);
Expand Down Expand Up @@ -904,6 +913,7 @@
929EF6612C9FF2FD0051A3E6 /* StockData.swift in Sources */,
9243534D2CCD38830052E4BC /* AssetList.swift in Sources */,
925EAB9D2CCDD67C003CEAB3 /* CategoryGroup.swift in Sources */,
925EAC2B2CDAC10D003CEAB3 /* FieldGroup.swift in Sources */,
925EAC272CDAB134003CEAB3 /* AttachmentEditView.swift in Sources */,
925EAC1A2CDAA813003CEAB3 /* AttachmentList.swift in Sources */,
A37E7D922C9AC60000B4ECFC /* ContactSupportView.swift in Sources */,
Expand All @@ -913,6 +923,7 @@
925EABB82CD6FAC7003CEAB3 /* TransactionList.swift in Sources */,
A3C142502C8B366400D3CEC0 /* PayeeListView.swift in Sources */,
925EABBA2CD6FBF7003CEAB3 /* ScheduledList.swift in Sources */,
925EAC2D2CDAC36F003CEAB3 /* FieldSearch.swift in Sources */,
925EABB22CCFFC2E003CEAB3 /* Reload.swift in Sources */,
A337428A2CA8E72C00698466 /* InsightsSummary.swift in Sources */,
A3C142672C8F2AF500D3CEC0 /* TransactionData.swift in Sources */,
Expand Down Expand Up @@ -962,6 +973,7 @@
924353492CCD36890052E4BC /* CurrencyList.swift in Sources */,
924352FA2CB355CF0052E4BC /* SettingsThemeView.swift in Sources */,
925EABAC2CCF826F003CEAB3 /* CategoryValidation.swift in Sources */,
925EAC292CDABF9F003CEAB3 /* FieldList.swift in Sources */,
9208240A2CA4C2AD00388AB2 /* YearData.swift in Sources */,
924353392CCD2F310052E4BC /* CurrencySearch.swift in Sources */,
925EAC152CDA8EEA003CEAB3 /* TagListView.swift in Sources */,
Expand Down
6 changes: 3 additions & 3 deletions MMEX/Repository/FieldRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ struct FieldRepository: RepositoryProtocol {
}

static func filterUsed(_ table: SQLite.Table) -> SQLite.Table {
typealias FC = FieldValueRepository
let cond = "EXISTS (" + (FC.table.select(1).where(
FC.table[FC.col_fieldId] == Self.table[Self.col_id]
typealias FV = FieldValueRepository
let cond = "EXISTS (" + (FV.table.select(1).where(
FV.table[FV.col_fieldId] == Self.table[Self.col_id]
) ).expression.description + ")"
return table.filter(SQLite.Expression<Bool>(literal: cond))
}
Expand Down
87 changes: 87 additions & 0 deletions MMEX/ViewModel/Group/FieldGroup.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//
// FieldGroup.swift
// MMEX
//
// 2024-11-05: Created by George Ef ([email protected])
//

import SwiftUI

enum FieldGroupChoice: String, GroupChoiceProtocol {
case all = "All"
case used = "Used"
case refType = "Ref. Type"
case type = "Field Type"
static let defaultValue = Self.all
static let isSingleton: Set<Self> = [.all]
}

struct FieldGroup: GroupProtocol {
typealias MainRepository = FieldRepository
typealias GroupChoice = FieldGroupChoice
let idleValue: ValueType = []

var choice: GroupChoice = .defaultValue
var state: LoadState = .init()
var value: ValueType

init() {
self.value = idleValue
}

static let groupUsed: [Bool] = [
true, false
]

static let groupRefType: [RefType] = [
.transaction, .scheduled
]

static let groupType: [FieldType] = [
.string, .integer, .decimal, .boolean, .date, .time,
.singleChoice, .multiChoice, .unknown
]
}

extension ViewModel {
func loadFieldGroup(choice: FieldGroupChoice) {
guard
let listData = fieldList.data.readyValue,
let listUsed = fieldList.used.readyValue,
let listOrder = fieldList.order.readyValue
else { return }

guard fieldGroup.state.loading() else { return }
log.trace("DEBUG: ViewModel.loadFieldGroup(\(choice.rawValue), main=\(Thread.isMainThread))")

fieldGroup.choice = choice

switch choice {
case .all:
fieldGroup.append("All", listOrder, true, true)
case .used:
let dict = Dictionary(grouping: listOrder) { listUsed.contains($0) }
for g in FieldGroup.groupUsed {
let name = g ? "Used" : "Other"
fieldGroup.append(name, dict[g] ?? [], true, g)
}
case .refType:
let dict = Dictionary(grouping: listOrder) { listData[$0]!.refType }
for g in FieldGroup.groupRefType {
fieldGroup.append(g.rawValue, dict[g] ?? [], dict[g] != nil, true)
}
case .type:
let dict = Dictionary(grouping: listOrder) { listData[$0]!.type }
for g in FieldGroup.groupType {
fieldGroup.append(g.rawValue, dict[g] ?? [], dict[g] != nil, true)
}
}

fieldGroup.state.loaded()
log.info("INFO: ViewModel.loadFieldGroup(\(choice.rawValue), main=\(Thread.isMainThread))")
}

func unloadFieldGroup() {
fieldGroup.unload()
}
}
5 changes: 4 additions & 1 deletion MMEX/ViewModel/Group/GroupProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ extension ViewModel {
else if MainRepository.self == C.self { loadCategoryGroup(choice: choice as! CategoryGroupChoice) }
else if MainRepository.self == P.self { loadPayeeGroup(choice: choice as! PayeeGroupChoice) }
else if MainRepository.self == G.self { loadTagGroup(choice: choice as! TagGroupChoice) }
else if MainRepository.self == F.self { loadFieldGroup(choice: choice as! FieldGroupChoice) }
else if MainRepository.self == D.self { loadAttachmentGroup(choice: choice as! AttachmentGroupChoice) }
}

Expand All @@ -70,6 +71,7 @@ extension ViewModel {
else if MainRepository.self == C.self { unloadCategoryGroup() }
else if MainRepository.self == P.self { unloadPayeeGroup() }
else if MainRepository.self == G.self { unloadTagGroup() }
else if MainRepository.self == F.self { unloadFieldGroup() }
else if MainRepository.self == D.self { unloadAttachmentGroup() }
}

Expand All @@ -80,8 +82,9 @@ extension ViewModel {
unloadStockGroup()
unloadCategoryGroup()
unloadPayeeGroup()
unloadAttachmentGroup()
unloadTagGroup()
unloadFieldGroup()
unloadAttachmentGroup()
}

func unloadAll() {
Expand Down
44 changes: 44 additions & 0 deletions MMEX/ViewModel/List/FieldList.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// FieldList.swift
// MMEX
//
// 2024-11-05: Created by George Ef ([email protected])
//

import SwiftUI
import SQLite

struct FieldList: ListProtocol {
typealias MainRepository = FieldRepository

var state : LoadState = .init()
var count : LoadMainCount<MainRepository> = .init()
var data : LoadMainData<MainRepository> = .init()
var used : LoadMainUsed<MainRepository> = .init()
var order : LoadMainOrder<MainRepository> = .init(order: [
MainRepository.col_refType, MainRepository.col_description
])
}

extension ViewModel {
func loadFieldList() async {
guard fieldList.reloading() else { return }
let ok = await withTaskGroup(of: Bool.self) { taskGroup -> Bool in
let ok = [
load(&taskGroup, keyPath: \Self.fieldList.data),
load(&taskGroup, keyPath: \Self.fieldList.used),
load(&taskGroup, keyPath: \Self.fieldList.order)
].allSatisfy { $0 }
return await taskGroupOk(taskGroup, ok)
}
fieldList.loaded(ok: ok)
}

func unloadFieldList() {
guard fieldList.unloading() else { return }
fieldList.data.unload()
fieldList.used.unload()
fieldList.order.unload()
fieldList.unloaded()
}
}
4 changes: 4 additions & 0 deletions MMEX/ViewModel/List/ListProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ extension ViewModel {
else if MainRepository.self == C.self { await loadCategoryList() }
else if MainRepository.self == P.self { await loadPayeeList() }
else if MainRepository.self == G.self { await loadTagList() }
else if MainRepository.self == F.self { await loadFieldList() }
else if MainRepository.self == D.self { await loadAttachmentList() }
}

Expand All @@ -89,6 +90,7 @@ extension ViewModel {
else if MainRepository.self == C.self { unloadCategoryList() }
else if MainRepository.self == P.self { unloadPayeeList() }
else if MainRepository.self == G.self { unloadTagList() }
else if MainRepository.self == F.self { unloadFieldList() }
else if MainRepository.self == D.self { unloadAttachmentList() }
}

Expand All @@ -101,6 +103,7 @@ extension ViewModel {
await loadCategoryList()
await loadPayeeList()
await loadTagList()
await loadFieldList()
await loadAttachmentList()
await loadManageList()
}
Expand All @@ -114,6 +117,7 @@ extension ViewModel {
unloadCategoryList()
unloadPayeeList()
unloadTagList()
unloadFieldList()
unloadAttachmentList()
unloadManegeList()
}
Expand Down
2 changes: 2 additions & 0 deletions MMEX/ViewModel/List/ManageList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ extension ViewModel {
load(&taskGroup, keyPath: \Self.transactionList.count),
load(&taskGroup, keyPath: \Self.scheduledList.count),
load(&taskGroup, keyPath: \Self.tagList.count),
load(&taskGroup, keyPath: \Self.fieldList.count),
load(&taskGroup, keyPath: \Self.attachmentList.count),
].allSatisfy { $0 }
return await taskGroupOk(taskGroup, ok)
Expand All @@ -49,6 +50,7 @@ extension ViewModel {
transactionList.count.unload()
scheduledList.count.unload()
tagList.count.unload()
fieldList.count.unload()
attachmentList.count.unload()
manageList.unloaded()
}
Expand Down
45 changes: 45 additions & 0 deletions MMEX/ViewModel/Search/FieldSearch.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// FieldSaerch.swift
// MMEX
//
// 2024-11-05: Created by George Ef ([email protected])
//

import SwiftUI

struct FieldSearch: SearchProtocol {
var area: [SearchArea<FieldData>] = [
("Description", true, {[ $0.description ]}, nil),
("Properties", false, {[ $0.properties ]}, nil),
]
var key: String = ""
}

extension ViewModel {
func fieldGroupIsVisible(_ g: Int, search: FieldSearch
) -> Bool? {
guard
let listData = fieldList.data.readyValue,
let groupData = fieldGroup.readyValue
else { return nil }

if search.isEmpty {
return switch fieldGroup.choice {
case .refType, .type: !groupData[g].dataId.isEmpty
default: true
}
}
return groupData[g].dataId.first(where: { search.match(self, listData[$0]!) }) != nil
}

func searchFieldGroup(search: FieldSearch, expand: Bool = false ) {
guard fieldGroup.state == .ready else { return }
for g in 0 ..< fieldGroup.value.count {
guard let isVisible = fieldGroupIsVisible(g, search: search) else { return }
fieldGroup.value[g].isVisible = isVisible
if (expand || !search.isEmpty) && isVisible {
fieldGroup.value[g].isExpanded = true
}
}
}
}
2 changes: 2 additions & 0 deletions MMEX/ViewModel/Search/SearchProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ extension ViewModel {
searchPayeeGroup(search: search as! PayeeSearch, expand: expand)
} else if GroupType.MainRepository.self == G.self {
searchTagGroup(search: search as! TagSearch, expand: expand)
} else if GroupType.MainRepository.self == F.self {
searchFieldGroup(search: search as! FieldSearch, expand: expand)
} else if GroupType.MainRepository.self == D.self {
searchAttachmentGroup(search: search as! AttachmentSearch, expand: expand)
}
Expand Down
2 changes: 2 additions & 0 deletions MMEX/ViewModel/ViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ class ViewModel: ObservableObject {

typealias F = FieldRepository
typealias FV = FieldValueRepository
@Published var fieldList : FieldList = .init()
@Published var fieldGroup : FieldGroup = .init()

typealias D = AttachmentRepository
@Published var attachmentList : AttachmentList = .init()
Expand Down

0 comments on commit cdef7b4

Please sign in to comment.