201 lines
6.9 KiB
Swift
201 lines
6.9 KiB
Swift
import SwiftUI
|
|
import SFSafeSymbols
|
|
|
|
struct GenerationContentView: View {
|
|
|
|
@Environment(\.language)
|
|
private var language
|
|
|
|
@EnvironmentObject
|
|
private var content: Content
|
|
|
|
@EnvironmentObject
|
|
private var selection: SelectedContent
|
|
|
|
@Environment(\.dismiss)
|
|
private var dismiss
|
|
|
|
var draftPages: Set<Page> {
|
|
Set(content.pages.filter { $0.isDraft })
|
|
}
|
|
|
|
var draftPosts: Set<Post> {
|
|
Set(content.posts.filter { $0.isDraft })
|
|
}
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading) {
|
|
Text("Website Generation")
|
|
.font(.largeTitle)
|
|
.bold()
|
|
Text("Regenerate the website and monitor the output")
|
|
.foregroundStyle(.secondary)
|
|
.padding(.bottom, 30)
|
|
|
|
HStack {
|
|
Button {
|
|
if content.isGeneratingWebsite {
|
|
content.endCurrentGeneration()
|
|
} else {
|
|
content.generateWebsiteInAllLanguages()
|
|
}
|
|
} label: {
|
|
Text(content.isGeneratingWebsite ? "Cancel" : "Generate")
|
|
}
|
|
.disabled(content.isGeneratingWebsite != content.shouldGenerateWebsite)
|
|
if content.isGeneratingWebsite {
|
|
ProgressView()
|
|
.progressViewStyle(.circular)
|
|
.scaleEffect(0.6)
|
|
.frame(height: 16)
|
|
}
|
|
Spacer()
|
|
}
|
|
Text(content.generationStatus)
|
|
.padding(.vertical, 5)
|
|
GenerationStringIssuesView(
|
|
text: "output files",
|
|
statusWhenNonEmpty: .nominal,
|
|
items: content.results.outputFiles)
|
|
GenerationResultsIssueView(
|
|
text: "\(content.results.imagesToGenerate.count) images",
|
|
status: .nominal,
|
|
items: { [] })
|
|
GenerationResultsIssueView(
|
|
text: "\(content.results.resultCount) items processed",
|
|
status: .nominal,
|
|
items: { [] })
|
|
GenerationStringIssuesView(
|
|
text: "external links",
|
|
statusWhenNonEmpty: .nominal,
|
|
items: content.results.externalLinks)
|
|
GenerationStringIssuesView(
|
|
text: "required files",
|
|
statusWhenNonEmpty: .nominal,
|
|
items: content.results.requiredFiles) { $0.id }
|
|
GenerationStringIssuesView(
|
|
text: "external files",
|
|
statusWhenNonEmpty: .nominal,
|
|
items: content.results.externalFiles) { $0.id }
|
|
GenerationIssuesView(
|
|
text: "empty pages",
|
|
statusWhenNonEmpty: .warning,
|
|
items: $content.results.emptyPages) { pageId in
|
|
HStack {
|
|
Text("\(pageId.pageId) (\(pageId.language))")
|
|
Spacer()
|
|
Button("Show") {
|
|
show(page: pageId.pageId,
|
|
language: pageId.language)
|
|
}
|
|
}
|
|
}
|
|
|
|
GenerationIssuesActionView(
|
|
title: "draft pages",
|
|
statusWhenNonEmpty: .warning,
|
|
items: draftPages,
|
|
buttonText: "Show",
|
|
itemText: { $0.id },
|
|
action: { show($0) })
|
|
GenerationIssuesActionView(
|
|
title: "draft posts",
|
|
statusWhenNonEmpty: .warning,
|
|
items: draftPosts,
|
|
buttonText: "Show",
|
|
itemText: { $0.id },
|
|
action: { show($0) })
|
|
GenerationIssuesView(
|
|
text: "additional output files",
|
|
statusWhenNonEmpty: .warning,
|
|
items: $content.results.unusedFilesInOutput) { filePath in
|
|
HStack {
|
|
Text(filePath)
|
|
Spacer()
|
|
Button("Delete", action: { delete(unusedFile: filePath) })
|
|
}
|
|
}
|
|
GenerationStringIssuesView(
|
|
text: "inaccessible files",
|
|
items: content.results.inaccessibleFiles) { $0.id }
|
|
GenerationStringIssuesView(
|
|
text: "unparsable files",
|
|
items: content.results.unparsableFiles) { $0.id }
|
|
GenerationStringIssuesView(
|
|
text: "unsaved output files",
|
|
items: content.results.unsavedOutputFiles)
|
|
GenerationStringIssuesView(
|
|
text: "failed image generations",
|
|
items: content.results.failedImages) { $0.outputPath }
|
|
GenerationStringIssuesView(
|
|
text: "missing files",
|
|
items: content.results.missingFiles)
|
|
GenerationStringIssuesView(
|
|
text: "missing tags",
|
|
items: content.results.missingTags)
|
|
GenerationStringIssuesView(
|
|
text: "missing pages",
|
|
items: content.results.missingPages) { pageId in
|
|
let sources = content.results.sources(forMissingPage: pageId)
|
|
.map { "\($0.page): \($0.source)"}
|
|
.joined(separator: ", ")
|
|
|
|
return "\(pageId) (\(sources))"
|
|
}
|
|
GenerationStringIssuesView(
|
|
text: "invalid commands",
|
|
items: content.results.invalidCommands)
|
|
GenerationStringIssuesView(
|
|
text: "invalid blocks",
|
|
items: content.results.invalidBlocks)
|
|
GenerationStringIssuesView(
|
|
text: "warnings",
|
|
statusWhenNonEmpty: .warning,
|
|
items: content.results.warnings)
|
|
HorizontalCenter {
|
|
Button(action: { dismiss() }) {
|
|
Text("Close")
|
|
}
|
|
}
|
|
}.padding()
|
|
}
|
|
|
|
private func delete(unusedFile: String) {
|
|
guard content.storage.deleteInOutputFolder(unusedFile) else {
|
|
return
|
|
}
|
|
content.results.unusedFilesInOutput.remove(unusedFile)
|
|
}
|
|
|
|
private func show(page pageId: String, language: ContentLanguage? = nil) {
|
|
guard let page = content.page(pageId) else {
|
|
return
|
|
}
|
|
show(page, language: language)
|
|
}
|
|
|
|
private func show(_ page: Page, language: ContentLanguage? = nil) {
|
|
selection.page = page
|
|
if let language {
|
|
selection.language = language
|
|
}
|
|
selection.tab = .pages
|
|
dismiss()
|
|
}
|
|
|
|
private func show(_ post: Post, language: ContentLanguage? = nil) {
|
|
selection.post = post
|
|
if let language {
|
|
selection.language = language
|
|
}
|
|
selection.tab = .posts
|
|
dismiss()
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
GenerationContentView()
|
|
.environmentObject(Content.mock)
|
|
.padding()
|
|
}
|