summaryrefslogtreecommitdiff
path: root/DomainDig/WorkflowsView.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-22 11:46:52 -0500
committerChristian Cleberg <[email protected]>2026-04-22 11:46:52 -0500
commit37b02e5ee360d61751951b77b7b556165a3af1fc (patch)
treec2e30f32c4e8d2fcdf7035f97e9e353f09859114 /DomainDig/WorkflowsView.swift
parentceac99c05f180d9008b75c9329822466ff60255b (diff)
downloaddomain-dig-37b02e5ee360d61751951b77b7b556165a3af1fc.tar.gz
domain-dig-37b02e5ee360d61751951b77b7b556165a3af1fc.tar.bz2
domain-dig-37b02e5ee360d61751951b77b7b556165a3af1fc.zip
feat(v3.0.0): unify platform architecture and introduce feature tiers
* consolidate DomainReport as canonical data model * add feature tier system (free/pro/data+ scaffolding) * apply clean feature gating across workflows and tracking * refactor app structure for maintainability * standardize navigation and settings * add data lifecycle controls * ensure consistency across UI, export, and CLI * stabilize internal inspection API
Diffstat (limited to 'DomainDig/WorkflowsView.swift')
-rw-r--r--DomainDig/WorkflowsView.swift159
1 files changed, 96 insertions, 63 deletions
diff --git a/DomainDig/WorkflowsView.swift b/DomainDig/WorkflowsView.swift
index b870409..9d99b02 100644
--- a/DomainDig/WorkflowsView.swift
+++ b/DomainDig/WorkflowsView.swift
@@ -15,57 +15,18 @@ struct WorkflowsView: View {
var body: some View {
List {
- if viewModel.batchLookupSource == .workflow, (!viewModel.batchResults.isEmpty || viewModel.batchLookupRunning) {
- Section("Workflow Run") {
- VStack(alignment: .leading, spacing: 8) {
- ProgressView(
- value: Double(viewModel.batchCompletedCount),
- total: Double(max(viewModel.batchTotalCount, 1))
- )
- .tint(.cyan)
-
- HStack {
- Text(viewModel.batchProgressLabel)
- .font(appDensity.font(.caption))
- .foregroundStyle(.secondary)
- Spacer()
- if viewModel.batchLookupRunning {
- Button("Cancel") {
- viewModel.cancelBatchLookup()
- }
- .buttonStyle(.bordered)
- .font(appDensity.font(.caption2))
- }
- }
- }
- .padding(.vertical, 4)
- }
- .listRowBackground(Color(.systemGray6).opacity(0.5))
- }
-
- if viewModel.workflows.isEmpty {
+ if FeatureAccessService.hasAccess(to: .workflows) {
+ workflowContent
+ } else {
Section {
EmptyStateCardView(
- title: "No Workflows Yet",
- message: "Workflows save a reusable set of domains so repeat inspections take one tap instead of rebuilding the same batch each time.",
- suggestion: "Create a workflow for a weekly audit set, customer domains, or a monitoring group.",
+ title: "Workflows",
+ message: "Reusable workflow sets are scaffolded for this release and will unlock with Pro.",
+ suggestion: FeatureAccessService.upgradeMessage(for: .workflows),
systemImage: "square.stack.3d.down.right"
)
}
.listRowBackground(Color(.systemGray6).opacity(0.5))
- } else {
- ForEach(viewModel.workflows) { workflow in
- NavigationLink {
- WorkflowDetailView(viewModel: viewModel, workflowID: workflow.id)
- } label: {
- WorkflowRowView(workflow: workflow)
- }
- .listRowBackground(Color(.systemGray6).opacity(0.5))
- }
- .onDelete { offsets in
- let workflows = offsets.map { viewModel.workflows[$0] }
- workflows.forEach(viewModel.deleteWorkflow)
- }
}
}
.scrollContentBackground(.hidden)
@@ -75,15 +36,17 @@ struct WorkflowsView: View {
}
.navigationTitle("Workflows")
.toolbar {
- ToolbarItemGroup(placement: .topBarTrailing) {
- Button {
- showingCreateWorkflow = true
- } label: {
- Image(systemName: "plus.circle")
- }
+ if FeatureAccessService.hasAccess(to: .workflows) {
+ ToolbarItemGroup(placement: .topBarTrailing) {
+ Button {
+ showingCreateWorkflow = true
+ } label: {
+ Image(systemName: "plus.circle")
+ }
- if !viewModel.workflows.isEmpty {
- EditButton()
+ if !viewModel.workflows.isEmpty {
+ EditButton()
+ }
}
}
}
@@ -102,6 +65,62 @@ struct WorkflowsView: View {
set: { viewModel.latestWorkflowRunSummary = $0 }
)
}
+
+ @ViewBuilder
+ private var workflowContent: some View {
+ if viewModel.batchLookupSource == .workflow, (!viewModel.batchResults.isEmpty || viewModel.batchLookupRunning) {
+ Section("Workflow Run") {
+ VStack(alignment: .leading, spacing: 8) {
+ ProgressView(
+ value: Double(viewModel.batchCompletedCount),
+ total: Double(max(viewModel.batchTotalCount, 1))
+ )
+ .tint(.cyan)
+
+ HStack {
+ Text(viewModel.batchProgressLabel)
+ .font(appDensity.font(.caption))
+ .foregroundStyle(.secondary)
+ Spacer()
+ if viewModel.batchLookupRunning {
+ Button("Cancel") {
+ viewModel.cancelBatchLookup()
+ }
+ .buttonStyle(.bordered)
+ .font(appDensity.font(.caption2))
+ }
+ }
+ }
+ .padding(.vertical, 4)
+ }
+ .listRowBackground(Color(.systemGray6).opacity(0.5))
+ }
+
+ if viewModel.workflows.isEmpty {
+ Section {
+ EmptyStateCardView(
+ title: "No Workflows Yet",
+ message: "Workflows save a reusable set of domains so repeat inspections take one tap instead of rebuilding the same batch each time.",
+ suggestion: "Create a workflow for a weekly audit set, customer domains, or a monitoring group.",
+ systemImage: "square.stack.3d.down.right"
+ )
+ }
+ .listRowBackground(Color(.systemGray6).opacity(0.5))
+ } else {
+ ForEach(viewModel.workflows) { workflow in
+ NavigationLink {
+ WorkflowDetailView(viewModel: viewModel, workflowID: workflow.id)
+ } label: {
+ WorkflowRowView(workflow: workflow)
+ }
+ .listRowBackground(Color(.systemGray6).opacity(0.5))
+ }
+ .onDelete { offsets in
+ let workflows = offsets.map { viewModel.workflows[$0] }
+ workflows.forEach(viewModel.deleteWorkflow)
+ }
+ }
+ }
}
private struct WorkflowRowView: View {
@@ -197,11 +216,18 @@ struct WorkflowDetailView: View {
Button("Export TXT") {
shareWorkflowResults(format: .text)
}
- Button("Export CSV") {
- shareWorkflowResults(format: .csv)
- }
- Button("Export JSON") {
- shareWorkflowResults(format: .json)
+ if FeatureAccessService.hasAccess(to: .advancedExports) {
+ Button("Export CSV") {
+ shareWorkflowResults(format: .csv)
+ }
+ Button("Export JSON") {
+ shareWorkflowResults(format: .json)
+ }
+ } else {
+ Button("CSV Export • Available in Pro") {}
+ .disabled(true)
+ Button("JSON Export • Available in Pro") {}
+ .disabled(true)
}
} label: {
Label("Export Results", systemImage: "square.and.arrow.up")
@@ -478,11 +504,18 @@ struct WorkflowRunSummaryView: View {
Button("Export TXT") {
share(format: .text)
}
- Button("Export CSV") {
- share(format: .csv)
- }
- Button("Export JSON") {
- share(format: .json)
+ if FeatureAccessService.hasAccess(to: .advancedExports) {
+ Button("Export CSV") {
+ share(format: .csv)
+ }
+ Button("Export JSON") {
+ share(format: .json)
+ }
+ } else {
+ Button("CSV Export • Available in Pro") {}
+ .disabled(true)
+ Button("JSON Export • Available in Pro") {}
+ .disabled(true)
}
} label: {
Image(systemName: "square.and.arrow.up")