Skip to content

Commit

Permalink
feat: 🎸 Data Table for new design
Browse files Browse the repository at this point in the history
  • Loading branch information
ShawnMa16 committed Apr 23, 2021
1 parent 8761c1c commit f4cc19d
Show file tree
Hide file tree
Showing 22 changed files with 1,907 additions and 0 deletions.
44 changes: 44 additions & 0 deletions Apps/Examples/Examples.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@
8AF60E3324D34CF2003889A8 /* TimelineCardSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AF60E3224D34CF2003889A8 /* TimelineCardSnapshotTests.swift */; };
975CB76B256C5A7400DB7A15 /* SignatureCaptureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 975CB76A256C5A7400DB7A15 /* SignatureCaptureView.swift */; };
97CEF8AB2553D714008BFBEF /* SignatureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97CEF8AA2553D714008BFBEF /* SignatureView.swift */; };
AB988B102631270300483D87 /* DataTableExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB988B0F2631270300483D87 /* DataTableExample.swift */; };
B80DA9BA260BBF8600C0B2E9 /* SingleActionProfiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80DA9B9260BBF8600C0B2E9 /* SingleActionProfiles.swift */; };
B80DA9BC260BED9400C0B2E9 /* SingleActionCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80DA9BB260BED9400C0B2E9 /* SingleActionCollectionView.swift */; };
B80DA9BE260C1CC200C0B2E9 /* ListDataProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80DA9BD260C1CC200C0B2E9 /* ListDataProtocol.swift */; };
B80DA9C0260C1DAB00C0B2E9 /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80DA9BF260C1DAB00C0B2E9 /* View+Extensions.swift */; };
B80DA9C2260D04FB00C0B2E9 /* SingleActionLongFollowButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80DA9C1260D04FB00C0B2E9 /* SingleActionLongFollowButton.swift */; };
B80DA9C62612A54E00C0B2E9 /* ActivationScreenSample.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80DA9C42612A54E00C0B2E9 /* ActivationScreenSample.swift */; };
B80DA9C72612A54E00C0B2E9 /* WelcomeScreenSample.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80DA9C52612A54E00C0B2E9 /* WelcomeScreenSample.swift */; };
B8355ED525225A52001AB341 /* AreaChartSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8355ED425225A52001AB341 /* AreaChartSnapshotTests.swift */; };
B8355ED725227D1B001AB341 /* StackedColumnChartSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8355ED625227D1B001AB341 /* StackedColumnChartSnapshotTests.swift */; };
B8355ED925227E7E001AB341 /* BarChartSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8355ED825227E7E001AB341 /* BarChartSnapshotTests.swift */; };
Expand Down Expand Up @@ -261,6 +269,14 @@
8AF60E3224D34CF2003889A8 /* TimelineCardSnapshotTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimelineCardSnapshotTests.swift; sourceTree = "<group>"; };
975CB76A256C5A7400DB7A15 /* SignatureCaptureView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignatureCaptureView.swift; sourceTree = "<group>"; };
97CEF8AA2553D714008BFBEF /* SignatureView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignatureView.swift; sourceTree = "<group>"; };
AB988B0F2631270300483D87 /* DataTableExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataTableExample.swift; sourceTree = "<group>"; };
B80DA9B9260BBF8600C0B2E9 /* SingleActionProfiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleActionProfiles.swift; sourceTree = "<group>"; };
B80DA9BB260BED9400C0B2E9 /* SingleActionCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleActionCollectionView.swift; sourceTree = "<group>"; };
B80DA9BD260C1CC200C0B2E9 /* ListDataProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDataProtocol.swift; sourceTree = "<group>"; };
B80DA9BF260C1DAB00C0B2E9 /* View+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extensions.swift"; sourceTree = "<group>"; };
B80DA9C1260D04FB00C0B2E9 /* SingleActionLongFollowButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleActionLongFollowButton.swift; sourceTree = "<group>"; };
B80DA9C42612A54E00C0B2E9 /* ActivationScreenSample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivationScreenSample.swift; sourceTree = "<group>"; };
B80DA9C52612A54E00C0B2E9 /* WelcomeScreenSample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WelcomeScreenSample.swift; sourceTree = "<group>"; };
B8355ED425225A52001AB341 /* AreaChartSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AreaChartSnapshotTests.swift; sourceTree = "<group>"; };
B8355ED625227D1B001AB341 /* StackedColumnChartSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackedColumnChartSnapshotTests.swift; sourceTree = "<group>"; };
B8355ED825227E7E001AB341 /* BarChartSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarChartSnapshotTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -502,6 +518,14 @@
isa = PBXGroup;
children = (
97CEF8A92553D6F1008BFBEF /* SignatureView */,
AB988B11263128C400483D87 /* DataTable */,
691DE21725F2A2F000094D4A /* KPI */,
B8D4376B25F97EC50024EE7D /* ObjectItem */,
1F3C939B25E05E0200A99A07 /* FioriButton */,
8A5579C924C1293C0098003A /* SegmentedControl */,
1F3C92EF25DF12A100A99A07 /* FormCells */,
8A6D64AF25AE656400D2D76C /* Experimental */,
B80DA9C32612A54E00C0B2E9 /* Onboarding */,
8A557A2124C12C9B0098003A /* CoreContentView.swift */,
8A5579C924C1293C0098003A /* SegmentedControl */,
);
Expand Down Expand Up @@ -572,6 +596,24 @@
sourceTree = "<group>";
};
97CEF8A92553D6F1008BFBEF /* SignatureView */ = {
AB988B11263128C400483D87 /* DataTable */ = {
isa = PBXGroup;
children = (
AB988B0F2631270300483D87 /* DataTableExample.swift */,
);
path = DataTable;
sourceTree = "<group>";
};
B80DA9C32612A54E00C0B2E9 /* Onboarding */ = {
isa = PBXGroup;
children = (
B80DA9C42612A54E00C0B2E9 /* ActivationScreenSample.swift */,
B80DA9C52612A54E00C0B2E9 /* WelcomeScreenSample.swift */,
);
path = Onboarding;
sourceTree = "<group>";
};
B8D4376B25F97EC50024EE7D /* ObjectItem */ = {
isa = PBXGroup;
children = (
97CEF8AA2553D714008BFBEF /* SignatureView.swift */,
Expand Down Expand Up @@ -747,6 +789,8 @@
files = (
8A55795724C1286E0098003A /* AppDelegate.swift in Sources */,
8A3C4E0424EB4A7B0084451B /* DataRequestTestCases.swift in Sources */,
691DE21925F2A30B00094D4A /* KPIViewExample.swift in Sources */,
AB988B102631270300483D87 /* DataTableExample.swift in Sources */,
8A557A0824C1293C0098003A /* BundleTestCases.swift in Sources */,
8A557A2424C12F380098003A /* ChartDetailView.swift in Sources */,
8A5579D024C1293C0098003A /* SettingsLine.swift in Sources */,
Expand Down
5 changes: 5 additions & 0 deletions Apps/Examples/Examples/FioriSwiftUICore/CoreContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import SwiftUI
struct CoreContentView: View {
var body: some View {
List {
NavigationLink(
destination: DataTableExample()) {
Text("Data Table")
}

NavigationLink(
destination: SegmentedControl_Chart()) {
Text("Segmented Control")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import FioriSwiftUICore
import Foundation
import SwiftUI

public enum TestRowData {
static func generateRowData(count: Int, for row: Int) -> TableRowItem {
var data: [DataItem] = []
for i in 0 ..< count {
let textItem = DataTextItem("\(row), \(i)")
let imageItem = DataImageItem(Image(systemName: "checkmark.circle.fill"))
data.append(i == 0 ? imageItem : textItem)
}
let lAccessories: [AccessoryItem] = [.icon(Image(systemName: "arrow.triangle.2.circlepath"))]

let tAccessory: AccessoryItem = .button(.init(image: Image(systemName: "chevron.forward"), title: "", action: {
print("trailing accessory tapped: \(row) tapped")
}))

let output = TableRowItem(leadingAccessories: lAccessories, trailingAccessory: tAccessory, data: data)

return output
}

static func generateNewRow(column: Int) -> TableRowItem {
var data: [DataItem] = []
for _ in 0 ..< column {
let textItem = DataTextItem("new item new item new item")
textItem.lineLimit = 2
data.append(textItem)
}
return TableRowItem(leadingAccessories: [], trailingAccessory: nil, data: data)
}

static func generateColumnAttributes(column: Int) -> [ColumnAttribute] {
var output: [ColumnAttribute] = []
for i in 0 ..< column {
let alignment: TextAlignment = i % 2 == 0 ? .leading : .trailing
let width: ColumnAttribute.Width = i % 2 == 0 ? .flexible : .fixed(80)
let att = ColumnAttribute(textAlignment: alignment, width: width)
output.append(att)
}
return output
}

static func generateData(row: Int, column: Int) -> TableModel {
var res: [TableRowItem] = []
var titles: [DataTextItem] = []
for k in 0 ..< column {
let title = k == 0 ? "" : "Long Header Title: \(k)"
titles.append(DataTextItem(title))
}
for i in 0 ..< row {
res.append(self.generateRowData(count: column, for: i))
}
let header = TableRowItem(leadingAccessories: [], trailingAccessory: nil, data: titles)
let model = TableModel(headerData: header, rowData: res, isFirstRowSticky: true, isFirstColumnSticky: true, showListView: true)
model.columnAttributes = self.generateColumnAttributes(column: 12)
model.didSelectRowAt = { _ in
print(model.selectedIndexes)
}
model.selectedIndexes = [2, 3]

return model
}
}

public struct DataTableExample: View {
var model: TableModel = TestRowData.generateData(row: 30, column: 12)
@State var isEditing: Bool = false

public init() {}

public var body: some View {
makeBody()
}

func makeBody() -> some View {
var view = DataTable(model: self.model)
return
NavigationView {
view
// .environmentObject(self.model)
.navigationBarTitle("Data Table", displayMode: .inline)
.navigationBarItems(leading:
Button("Add a row") {
DispatchQueue.main.async {
self.model.rowData.insert(TestRowData.generateNewRow(column: 12), at: 0)
}
}, trailing:
Button(self.isEditing ? "Delete" : "Edit") {
DispatchQueue.main.async {
self.isEditing = !self.isEditing
view.isEditing = self.isEditing
if !self.isEditing {
let indexSet = IndexSet(self.model.selectedIndexes)
self.model.rowData.remove(atOffsets: indexSet)
self.model.selectedIndexes = []
}
}
})
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
17 changes: 17 additions & 0 deletions Sources/FioriSwiftUICore/DataTable/ColumnAttribute.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Foundation
import SwiftUI

public struct ColumnAttribute {
public enum Width {
case fixed(CGFloat)
case flexible
}

public var textAlignment: TextAlignment = .leading
public var width: Width = .flexible

public init(textAlignment: TextAlignment = .leading, width: Width = .flexible) {
self.textAlignment = textAlignment
self.width = width
}
}
14 changes: 14 additions & 0 deletions Sources/FioriSwiftUICore/DataTable/DataImageItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import SwiftUI

open class DataImageItem: DataItem {
public var type: DataItemType
public var mapping: ObjectViewProperty.Image?

var image: Image

public init(_ image: Image, _ mapping: ObjectViewProperty.Image? = nil) {
self.image = image.resizable()
self.type = .image
self.mapping = mapping
}
}
39 changes: 39 additions & 0 deletions Sources/FioriSwiftUICore/DataTable/DataItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import SwiftUI

// MARK: - Public Enums

/// An enum representing the different item styles that a `FUIGridRowItem` can have.
public enum DataItemType {
/// Indicating this `FUIGridRowItem` represents a text.
case text
/// Indicating this `FUIGridRowItem` represents a image.
case image
}

/// A protocol defines style of a `FUIGridRowItem`.
public protocol DataItem: AnyObject {
/// Returns the `FUIGridRowItemStyle` enum value for the item.
var type: DataItemType { get }
}

public enum ObjectViewProperty {
/// Binding definitions for text in object view layout
public enum Text {
/// Object view headline area
case title
/// Object view subheadline area
case subtitle
/// Object view footnote area
case footnote
/// Object view status area
case status
/// Object view substatus area
case substatus
}

/// Binding definitions for images in object view layout
public enum Image {
/// Object view detailImage area
case detailImage
}
}
45 changes: 45 additions & 0 deletions Sources/FioriSwiftUICore/DataTable/DataTable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import SwiftUI

public struct DataTable: View {
@ObservedObject public var model: TableModel

@Environment(\.horizontalSizeClass) var horizontalSizeClass
@Environment(\.verticalSizeClass) var verticalSizeClass

public var isEditing: Bool = false {
didSet {
self.model.isEditing = self.isEditing
}
}

public init(model: TableModel) {
self.model = model
}

public var body: some View {
GeometryReader { proxy in
self.makeBody(in: proxy.frame(in: .local))
}
}

func makeBody(in rect: CGRect) -> some View {
let layoutManager = TableLayoutManager(model: self.model)
let dataManager = TableDataManager(selectedIndexes: self.model.selectedIndexes)
layoutManager.sizeClass = self.horizontalSizeClass ?? .compact
layoutManager.rect = rect

return Group {
if self.horizontalSizeClass == .compact, self.verticalSizeClass == .regular, self.model.showListView {
let listView = TableListView(layoutManager: layoutManager)
listView
} else {
let gridView = GridTableView(layoutManager: layoutManager)
gridView
.frame(minWidth: 300, idealWidth: UIScreen.main.bounds.width, maxWidth: .infinity, minHeight: 300, idealHeight: UIScreen.main.bounds.height, maxHeight: .infinity, alignment: .center)
.clipped()
}
}
.environmentObject(layoutManager)
.environmentObject(dataManager)
}
}
Loading

0 comments on commit f4cc19d

Please sign in to comment.