Add review workflows, tree-shaped workflows and a workflow editor
This commit is contained in:
@@ -1,15 +1,41 @@
|
||||
import ByreAPI
|
||||
import SwiftUI
|
||||
|
||||
private enum Editing: Equatable {
|
||||
case none, new, existing(String)
|
||||
}
|
||||
|
||||
struct WorkflowsView: View {
|
||||
@ViewState private var editing = Editing.none
|
||||
|
||||
var body: some View {
|
||||
switch editing {
|
||||
case .none:
|
||||
list
|
||||
case .new:
|
||||
WorkflowEditor(original: nil) { editing = .none }
|
||||
case .existing(let name):
|
||||
WorkflowEditor(original: name) { editing = .none }
|
||||
.id(name)
|
||||
}
|
||||
}
|
||||
|
||||
private var list: some View {
|
||||
ScrollView {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
Text("Workflows run a brief through stages, each its own task. Run asks your lead to start one, so you can add the project and the brief first.")
|
||||
.foregroundStyle(Palette.muted)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.top, 16)
|
||||
WorkflowList()
|
||||
HStack(alignment: .firstTextBaseline, spacing: 12) {
|
||||
Text("Workflows run a brief through stages, each its own task. Run asks your lead to start one, so you can add the project and the brief first.")
|
||||
.foregroundStyle(Palette.muted)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
Button("new") {
|
||||
editing = .new
|
||||
}
|
||||
.buttonStyle(SmallLinkButtonStyle())
|
||||
.help("Write a new workflow")
|
||||
}
|
||||
.padding(.top, 16)
|
||||
WorkflowList { editing = .existing($0) }
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.top, 8)
|
||||
@@ -22,6 +48,7 @@ struct WorkflowsView: View {
|
||||
}
|
||||
|
||||
private struct WorkflowList: View {
|
||||
let edit: (String) -> Void
|
||||
@Environment(Store.self) private var store
|
||||
@ViewState private var list: [WorkflowSummary]?
|
||||
@ViewState private var failure: String?
|
||||
@@ -35,7 +62,7 @@ private struct WorkflowList: View {
|
||||
hint("No saved workflows. Ask your lead to write one.")
|
||||
} else {
|
||||
ForEach(list.sorted { $0.name.localizedStandardCompare($1.name) == .orderedAscending }, id: \.name) { w in
|
||||
WorkflowRow(workflow: w)
|
||||
WorkflowRow(workflow: w) { edit(w.name) }
|
||||
}
|
||||
}
|
||||
} else if let failure {
|
||||
@@ -81,14 +108,20 @@ private struct WorkflowList: View {
|
||||
|
||||
private struct WorkflowRow: View {
|
||||
let workflow: WorkflowSummary
|
||||
let edit: () -> Void
|
||||
@Environment(Store.self) private var store
|
||||
@Environment(Overlays.self) private var overlays
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .firstTextBaseline, spacing: 12) {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(workflow.name)
|
||||
.font(Fonts.font(13, weight: 700))
|
||||
HStack(alignment: .firstTextBaseline, spacing: 6) {
|
||||
Text(workflow.name)
|
||||
.font(Fonts.font(13, weight: 700))
|
||||
if workflow.kind == .review {
|
||||
Text("reviews snapshots").font(Fonts.font(11)).foregroundStyle(Palette.muted)
|
||||
}
|
||||
}
|
||||
if !workflow.description.isEmpty {
|
||||
Text(workflow.description)
|
||||
.foregroundStyle(Palette.muted)
|
||||
@@ -97,11 +130,18 @@ private struct WorkflowRow: View {
|
||||
.textSelection(.enabled)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
Button("run") {
|
||||
run()
|
||||
Button("edit") {
|
||||
edit()
|
||||
}
|
||||
.buttonStyle(SmallLinkButtonStyle())
|
||||
.help("Open the Lead tab with a request to run this workflow in its composer")
|
||||
.help("See and change this workflow's steps and prompts")
|
||||
if workflow.kind == .task {
|
||||
Button("run") {
|
||||
run()
|
||||
}
|
||||
.buttonStyle(SmallLinkButtonStyle())
|
||||
.help("Open the Lead tab with a request to run this workflow in its composer")
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 6)
|
||||
.overlay(alignment: .top) {
|
||||
|
||||
Reference in New Issue
Block a user