From 6b9b4454a6d742f79a4990bb0e88d3ef16018346 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Mon, 14 Jun 2021 16:10:26 +0900 Subject: [PATCH 01/91] =?UTF-8?q?feat:=20[#44]=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=B6=94=EA=B0=80=20=EB=B2=84=ED=8A=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Main/Label/LabelViewController.swift | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/LabelViewController.swift index 1bac5c5a8..907571f45 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/LabelViewController.swift @@ -9,12 +9,34 @@ import UIKit class LabelViewController: UIViewController { + private lazy var addLabelButton: UIButton = { + let button = UIButton() + let plusImage = UIImage(systemName: "plus") + button.setImage(plusImage, for: .normal) + button.tintColor = Colors.mainGrape + button.setTitle("추가", for: .normal) + button.setTitleColor(Colors.mainGrape, for: .normal) + button.semanticContentAttribute = .forceRightToLeft + button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 0) + button.addTarget(self, action: #selector(addLabelTouched), for: .touchUpInside) + return button + }() + private var loginInfo: LoginInfo? override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.white title = "레이블" + addNavigationButton() + } + + private func addNavigationButton() { + navigationItem.rightBarButtonItem = UIBarButtonItem(customView: addLabelButton) + } + + @objc private func addLabelTouched(_ sender: UIButton) { + } } From 4242bd224a7c89d8f72d0e730d1e89f435df5fe1 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Mon, 14 Jun 2021 16:42:13 +0900 Subject: [PATCH 02/91] =?UTF-8?q?feat:=20[#44]=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EB=B7=B0=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 레이블 테이블 셀 생성 --- .../issue-tracker.xcodeproj/project.pbxproj | 4 + .../Main/Label/LabelTableViewCell.swift | 112 ++++++++++++++++++ .../Main/Label/LabelViewController.swift | 43 +++++++ 3 files changed, 159 insertions(+) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/LabelTableViewCell.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 7b6a125e6..2af279829 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD121267093590071B436 /* MilestoneViewController.swift */; }; E42AD124267093700071B436 /* MyAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD123267093700071B436 /* MyAccountViewController.swift */; }; E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD12526709C010071B436 /* UIViewControllerExtension.swift */; }; + E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -63,6 +64,7 @@ E42AD121267093590071B436 /* MilestoneViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MilestoneViewController.swift; sourceTree = ""; }; E42AD123267093700071B436 /* MyAccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountViewController.swift; sourceTree = ""; }; E42AD12526709C010071B436 /* UIViewControllerExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerExtension.swift; sourceTree = ""; }; + E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -212,6 +214,7 @@ isa = PBXGroup; children = ( E42AD11F267093430071B436 /* LabelViewController.swift */, + E46E11232677391B005375A1 /* LabelTableViewCell.swift */, ); path = Label; sourceTree = ""; @@ -339,6 +342,7 @@ E426DABC2670EC5E0069E77D /* LoginInfo.swift in Sources */, E42AD1182670886F0071B436 /* IssueTrackerTabBarController.swift in Sources */, E42AD102266E52FB0071B436 /* LoginViewController.swift in Sources */, + E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */, FAC6D88D2671D8A100A9E5F9 /* SocialLoginManagable.swift in Sources */, E42AD124267093700071B436 /* MyAccountViewController.swift in Sources */, FAEB30AC266F5E9700C17BE9 /* Colors.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/LabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Label/LabelTableViewCell.swift new file mode 100644 index 000000000..e5dbb3a9c --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/LabelTableViewCell.swift @@ -0,0 +1,112 @@ +// +// LabelTableViewCell.swift +// issue-tracker +// +// Created by Song on 2021/06/14. +// + +import UIKit + +class LabelTableViewCell: UITableViewCell { + + private lazy var labelTitleView: UIView = { + let view = UIView() + view.layer.cornerRadius = labelHeight * 0.5 + view.backgroundColor = Colors.mainGrape + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + private lazy var labelTitle: UILabel = { + let label = UILabel() + label.textColor = UIColor.white + label.textAlignment = .center + label.text = "레이블" + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + private lazy var labelDescription: UILabel = { + let label = UILabel() + label.textColor = UIColor.systemGray2 + label.numberOfLines = 1 + label.text = "No description provided" + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + private lazy var spacing: CGFloat = { + return frame.width * 0.05 + }() + + private lazy var labelHeight: CGFloat = { + return spacing * 2 + }() + + static var reuseID: String { + return String(describing: self) + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setViews() + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setViews() + } + + private func setViews() { + backgroundColor = UIColor.white + addLabelTitle() + addLabelDescription() + } + + private func addLabelTitle() { + configureLabelTitleView() + addSubview(labelTitleView) + + NSLayoutConstraint.activate([ + labelTitleView.widthAnchor.constraint(equalTo: labelTitle.widthAnchor, constant: spacing * 1.8), + labelTitleView.heightAnchor.constraint(equalToConstant: labelHeight), + labelTitleView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), + labelTitleView.topAnchor.constraint(equalTo: topAnchor, constant: spacing * 1.5) + ]) + } + + private func configureLabelTitleView() { + labelTitleView.addSubview(labelTitle) + + NSLayoutConstraint.activate([ + labelTitle.centerXAnchor.constraint(equalTo: labelTitleView.centerXAnchor), + labelTitle.centerYAnchor.constraint(equalTo: labelTitleView.centerYAnchor) + ]) + } + + private func addLabelDescription() { + addSubview(labelDescription) + + NSLayoutConstraint.activate([ + labelDescription.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), + labelDescription.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -spacing), + labelDescription.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -spacing * 1.5) + ]) + } + + func configure(with colorCode: String,_ title: String,_ description: String?) { + self.labelTitleView.backgroundColor = hexCodeToColor(colorCode) + self.labelTitle.text = title + self.labelTitle.textColor = textColor(from: colorCode) + self.labelDescription.text = description + } + + private func hexCodeToColor(_ hex: String) -> UIColor { + return UIColor.black + } + + private func textColor(from backgroundcolorCode: String) -> UIColor { + return UIColor.white + } + +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/LabelViewController.swift index 907571f45..77b77b9a0 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/LabelViewController.swift @@ -22,6 +22,16 @@ class LabelViewController: UIViewController { return button }() + private lazy var labelTableView: UITableView = { + let tableView = UITableView() + let cellID = LabelTableViewCell.reuseID + tableView.register(LabelTableViewCell.self, forCellReuseIdentifier: cellID) + tableView.backgroundColor = Colors.background + tableView.allowsSelection = false + tableView.translatesAutoresizingMaskIntoConstraints = false + return tableView + }() + private var loginInfo: LoginInfo? override func viewDidLoad() { @@ -29,12 +39,27 @@ class LabelViewController: UIViewController { view.backgroundColor = UIColor.white title = "레이블" addNavigationButton() + addTableView() + + labelTableView.dataSource = self + labelTableView.delegate = self } private func addNavigationButton() { navigationItem.rightBarButtonItem = UIBarButtonItem(customView: addLabelButton) } + private func addTableView() { + view.addSubview(labelTableView) + + NSLayoutConstraint.activate([ + labelTableView.topAnchor.constraint(equalTo: view.topAnchor), + labelTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + labelTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + labelTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + @objc private func addLabelTouched(_ sender: UIButton) { } @@ -46,3 +71,21 @@ extension LabelViewController: LoginInfoContainer { self.loginInfo = loginInfo } } + +extension LabelViewController: UITableViewDelegate { + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return view.frame.height * 0.135 + } +} + +extension LabelViewController: UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 5 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cellID = LabelTableViewCell.reuseID + let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? LabelTableViewCell ?? LabelTableViewCell() + return cell + } +} From 2267ec5bcf5eea435b54de848f2c546bad65805b Mon Sep 17 00:00:00 2001 From: Song Lee Date: Mon, 14 Jun 2021 20:12:04 +0900 Subject: [PATCH 03/91] =?UTF-8?q?refactor:=20[#44]=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EB=B7=B0=20subclassing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 재사용 위해 분리 --- .../issue-tracker.xcodeproj/project.pbxproj | 20 ++++++ .../Main/Common/View/LabelView.swift | 61 +++++++++++++++++++ .../Main/Label/LabelTableViewCell.swift | 47 +++----------- 3 files changed, 89 insertions(+), 39 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 2af279829..5227766b0 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD121267093590071B436 /* MilestoneViewController.swift */; }; E42AD124267093700071B436 /* MyAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD123267093700071B436 /* MyAccountViewController.swift */; }; E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD12526709C010071B436 /* UIViewControllerExtension.swift */; }; + E43912C726776D8F003CD344 /* LabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912C626776D8F003CD344 /* LabelView.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -64,6 +65,7 @@ E42AD121267093590071B436 /* MilestoneViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MilestoneViewController.swift; sourceTree = ""; }; E42AD123267093700071B436 /* MyAccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountViewController.swift; sourceTree = ""; }; E42AD12526709C010071B436 /* UIViewControllerExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerExtension.swift; sourceTree = ""; }; + E43912C626776D8F003CD344 /* LabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelView.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -188,6 +190,7 @@ E42AD11A26708EC00071B436 /* Label */, E42AD11B26708EC80071B436 /* Milestone */, E42AD11C26708ED50071B436 /* MyAccount */, + E43912C826776D95003CD344 /* Common */, ); path = Main; sourceTree = ""; @@ -235,6 +238,22 @@ path = MyAccount; sourceTree = ""; }; + E43912C826776D95003CD344 /* Common */ = { + isa = PBXGroup; + children = ( + E43912C926776DA0003CD344 /* View */, + ); + path = Common; + sourceTree = ""; + }; + E43912C926776DA0003CD344 /* View */ = { + isa = PBXGroup; + children = ( + E43912C626776D8F003CD344 /* LabelView.swift */, + ); + path = View; + sourceTree = ""; + }; FA8840422671F9B000ECCF7A /* Apple */ = { isa = PBXGroup; children = ( @@ -346,6 +365,7 @@ FAC6D88D2671D8A100A9E5F9 /* SocialLoginManagable.swift in Sources */, E42AD124267093700071B436 /* MyAccountViewController.swift in Sources */, FAEB30AC266F5E9700C17BE9 /* Colors.swift in Sources */, + E43912C726776D8F003CD344 /* LabelView.swift in Sources */, E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E426DAC22671B1C60069E77D /* LoginKeyChainManager.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift new file mode 100644 index 000000000..f8d523131 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift @@ -0,0 +1,61 @@ +// +// LabelView.swift +// issue-tracker +// +// Created by Song on 2021/06/14. +// + +import UIKit + +class LabelView: UIView { + + private lazy var labelTitle: UILabel = { + let label = UILabel() + label.textColor = UIColor.white + label.textAlignment = .center + label.text = "레이블" + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + private let spacing: CGFloat = 15 + + private lazy var labelHeight: CGFloat = { + return spacing * 2 + }() + + required init?(coder: NSCoder) { + super.init(coder: coder) + configure() + } + + override init(frame: CGRect) { + super.init(frame: frame) + configure() + } + + private func configure() { + layer.cornerRadius = labelHeight * 0.5 + backgroundColor = Colors.mainGrape + translatesAutoresizingMaskIntoConstraints = false + + addLabelTitle() + } + + private func addLabelTitle() { + addSubview(labelTitle) + + NSLayoutConstraint.activate([ + labelTitle.centerXAnchor.constraint(equalTo: centerXAnchor), + labelTitle.centerYAnchor.constraint(equalTo: centerYAnchor), + widthAnchor.constraint(equalTo: labelTitle.widthAnchor, constant: spacing * 1.8), + heightAnchor.constraint(equalToConstant: labelHeight) + ]) + } + + func configure(with backgroundColor: UIColor,_ textColor: UIColor,_ title: String) { + self.backgroundColor = backgroundColor + labelTitle.textColor = textColor + labelTitle.text = title + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/LabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Label/LabelTableViewCell.swift index e5dbb3a9c..e77890f62 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/LabelTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/LabelTableViewCell.swift @@ -9,22 +9,7 @@ import UIKit class LabelTableViewCell: UITableViewCell { - private lazy var labelTitleView: UIView = { - let view = UIView() - view.layer.cornerRadius = labelHeight * 0.5 - view.backgroundColor = Colors.mainGrape - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - private lazy var labelTitle: UILabel = { - let label = UILabel() - label.textColor = UIColor.white - label.textAlignment = .center - label.text = "레이블" - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() + private lazy var labelView: LabelView = LabelView() private lazy var labelDescription: UILabel = { let label = UILabel() @@ -39,10 +24,6 @@ class LabelTableViewCell: UITableViewCell { return frame.width * 0.05 }() - private lazy var labelHeight: CGFloat = { - return spacing * 2 - }() - static var reuseID: String { return String(describing: self) } @@ -64,23 +45,11 @@ class LabelTableViewCell: UITableViewCell { } private func addLabelTitle() { - configureLabelTitleView() - addSubview(labelTitleView) + addSubview(labelView) NSLayoutConstraint.activate([ - labelTitleView.widthAnchor.constraint(equalTo: labelTitle.widthAnchor, constant: spacing * 1.8), - labelTitleView.heightAnchor.constraint(equalToConstant: labelHeight), - labelTitleView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), - labelTitleView.topAnchor.constraint(equalTo: topAnchor, constant: spacing * 1.5) - ]) - } - - private func configureLabelTitleView() { - labelTitleView.addSubview(labelTitle) - - NSLayoutConstraint.activate([ - labelTitle.centerXAnchor.constraint(equalTo: labelTitleView.centerXAnchor), - labelTitle.centerYAnchor.constraint(equalTo: labelTitleView.centerYAnchor) + labelView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), + labelView.topAnchor.constraint(equalTo: topAnchor, constant: spacing * 1.5) ]) } @@ -95,9 +64,10 @@ class LabelTableViewCell: UITableViewCell { } func configure(with colorCode: String,_ title: String,_ description: String?) { - self.labelTitleView.backgroundColor = hexCodeToColor(colorCode) - self.labelTitle.text = title - self.labelTitle.textColor = textColor(from: colorCode) + let backgroundColor = hexCodeToColor(colorCode) + let textColor = textColor(from: colorCode) + labelView.configure(with: backgroundColor, textColor, title) + self.labelDescription.text = description } @@ -108,5 +78,4 @@ class LabelTableViewCell: UITableViewCell { private func textColor(from backgroundcolorCode: String) -> UIColor { return UIColor.white } - } From 24e80ce19386032b4913f52b4b597c8706003ff9 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Mon, 14 Jun 2021 20:21:51 +0900 Subject: [PATCH 04/91] =?UTF-8?q?chore:=20[#44]=20=EB=94=94=EB=A0=89?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20=EB=B6=84=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 32 +++++++++++++++++-- .../Main/Common/View/LabelView.swift | 2 +- .../LabelViewController.swift | 2 +- .../Main/Label/Model/ColorConverter.swift | 10 ++++++ .../Label/{ => View}/LabelTableViewCell.swift | 2 +- 5 files changed, 43 insertions(+), 5 deletions(-) rename iOS/issue-tracker/issue-tracker/Main/Label/{ => Controller}/LabelViewController.swift (98%) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Model/ColorConverter.swift rename iOS/issue-tracker/issue-tracker/Main/Label/{ => View}/LabelTableViewCell.swift (97%) diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 5227766b0..410083fbd 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -29,6 +29,7 @@ E42AD124267093700071B436 /* MyAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD123267093700071B436 /* MyAccountViewController.swift */; }; E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD12526709C010071B436 /* UIViewControllerExtension.swift */; }; E43912C726776D8F003CD344 /* LabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912C626776D8F003CD344 /* LabelView.swift */; }; + E43912CE26777310003CD344 /* ColorConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912CD26777310003CD344 /* ColorConverter.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -66,6 +67,7 @@ E42AD123267093700071B436 /* MyAccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountViewController.swift; sourceTree = ""; }; E42AD12526709C010071B436 /* UIViewControllerExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerExtension.swift; sourceTree = ""; }; E43912C626776D8F003CD344 /* LabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelView.swift; sourceTree = ""; }; + E43912CD26777310003CD344 /* ColorConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorConverter.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -216,8 +218,9 @@ E42AD11A26708EC00071B436 /* Label */ = { isa = PBXGroup; children = ( - E42AD11F267093430071B436 /* LabelViewController.swift */, - E46E11232677391B005375A1 /* LabelTableViewCell.swift */, + E43912CC267772E4003CD344 /* Model */, + E43912CA267772D3003CD344 /* View */, + E43912CB267772DA003CD344 /* Controller */, ); path = Label; sourceTree = ""; @@ -254,6 +257,30 @@ path = View; sourceTree = ""; }; + E43912CA267772D3003CD344 /* View */ = { + isa = PBXGroup; + children = ( + E46E11232677391B005375A1 /* LabelTableViewCell.swift */, + ); + path = View; + sourceTree = ""; + }; + E43912CB267772DA003CD344 /* Controller */ = { + isa = PBXGroup; + children = ( + E42AD11F267093430071B436 /* LabelViewController.swift */, + ); + path = Controller; + sourceTree = ""; + }; + E43912CC267772E4003CD344 /* Model */ = { + isa = PBXGroup; + children = ( + E43912CD26777310003CD344 /* ColorConverter.swift */, + ); + path = Model; + sourceTree = ""; + }; FA8840422671F9B000ECCF7A /* Apple */ = { isa = PBXGroup; children = ( @@ -359,6 +386,7 @@ E426DAD126730DC50069E77D /* OAuthResponseDTO.swift in Sources */, FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */, E426DABC2670EC5E0069E77D /* LoginInfo.swift in Sources */, + E43912CE26777310003CD344 /* ColorConverter.swift in Sources */, E42AD1182670886F0071B436 /* IssueTrackerTabBarController.swift in Sources */, E42AD102266E52FB0071B436 /* LoginViewController.swift in Sources */, E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift index f8d523131..00dadf33f 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift @@ -7,7 +7,7 @@ import UIKit -class LabelView: UIView { +final class LabelView: UIView { private lazy var labelTitle: UILabel = { let label = UILabel() diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift similarity index 98% rename from iOS/issue-tracker/issue-tracker/Main/Label/LabelViewController.swift rename to iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index 77b77b9a0..ac0dc2551 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -7,7 +7,7 @@ import UIKit -class LabelViewController: UIViewController { +final class LabelViewController: UIViewController { private lazy var addLabelButton: UIButton = { let button = UIButton() diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Model/ColorConverter.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Model/ColorConverter.swift new file mode 100644 index 000000000..9f774017d --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Model/ColorConverter.swift @@ -0,0 +1,10 @@ +// +// ColorConverter.swift +// issue-tracker +// +// Created by Song on 2021/06/14. +// + +import Foundation + + diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/LabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift similarity index 97% rename from iOS/issue-tracker/issue-tracker/Main/Label/LabelTableViewCell.swift rename to iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift index e77890f62..ca4c95f00 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/LabelTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift @@ -7,7 +7,7 @@ import UIKit -class LabelTableViewCell: UITableViewCell { +final class LabelTableViewCell: UITableViewCell { private lazy var labelView: LabelView = LabelView() From 22940b64c2519f3386999ddb7c9ec5f347905ce9 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 15 Jun 2021 15:00:27 +0900 Subject: [PATCH 05/91] =?UTF-8?q?feat:=20[#44]=20hex=EB=A5=BC=20=EC=BB=AC?= =?UTF-8?q?=EB=9F=AC=EB=A1=9C=20=EB=B3=80=ED=99=98=ED=95=98=EC=97=AC=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 배경색상에 맞춰 title 색상을 흰색 or 검정색으로 표시 --- .../issue-tracker.xcodeproj/project.pbxproj | 16 +++++++--- .../Controller/LabelViewController.swift | 9 +++++- .../Main/Label/Model/ColorConverter.swift | 10 ------ .../Main/Label/Model/HexColorCode.swift | 31 +++++++++++++++++++ .../Label/Model/HexColorConvertable.swift | 13 ++++++++ .../Main/Label/Model/HexColorConverter.swift | 25 +++++++++++++++ .../Main/Label/View/LabelTableViewCell.swift | 16 ++-------- 7 files changed, 92 insertions(+), 28 deletions(-) delete mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Model/ColorConverter.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorCode.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorConvertable.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorConverter.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 410083fbd..fbe645e31 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -29,7 +29,9 @@ E42AD124267093700071B436 /* MyAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD123267093700071B436 /* MyAccountViewController.swift */; }; E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD12526709C010071B436 /* UIViewControllerExtension.swift */; }; E43912C726776D8F003CD344 /* LabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912C626776D8F003CD344 /* LabelView.swift */; }; - E43912CE26777310003CD344 /* ColorConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912CD26777310003CD344 /* ColorConverter.swift */; }; + E43912CE26777310003CD344 /* HexColorConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912CD26777310003CD344 /* HexColorConverter.swift */; }; + E43912D0267878BF003CD344 /* HexColorConvertable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912CF267878BF003CD344 /* HexColorConvertable.swift */; }; + E43912D2267878F4003CD344 /* HexColorCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D1267878F4003CD344 /* HexColorCode.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -67,7 +69,9 @@ E42AD123267093700071B436 /* MyAccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountViewController.swift; sourceTree = ""; }; E42AD12526709C010071B436 /* UIViewControllerExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerExtension.swift; sourceTree = ""; }; E43912C626776D8F003CD344 /* LabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelView.swift; sourceTree = ""; }; - E43912CD26777310003CD344 /* ColorConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorConverter.swift; sourceTree = ""; }; + E43912CD26777310003CD344 /* HexColorConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HexColorConverter.swift; sourceTree = ""; }; + E43912CF267878BF003CD344 /* HexColorConvertable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HexColorConvertable.swift; sourceTree = ""; }; + E43912D1267878F4003CD344 /* HexColorCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HexColorCode.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -276,7 +280,9 @@ E43912CC267772E4003CD344 /* Model */ = { isa = PBXGroup; children = ( - E43912CD26777310003CD344 /* ColorConverter.swift */, + E43912CF267878BF003CD344 /* HexColorConvertable.swift */, + E43912CD26777310003CD344 /* HexColorConverter.swift */, + E43912D1267878F4003CD344 /* HexColorCode.swift */, ); path = Model; sourceTree = ""; @@ -386,10 +392,11 @@ E426DAD126730DC50069E77D /* OAuthResponseDTO.swift in Sources */, FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */, E426DABC2670EC5E0069E77D /* LoginInfo.swift in Sources */, - E43912CE26777310003CD344 /* ColorConverter.swift in Sources */, + E43912CE26777310003CD344 /* HexColorConverter.swift in Sources */, E42AD1182670886F0071B436 /* IssueTrackerTabBarController.swift in Sources */, E42AD102266E52FB0071B436 /* LoginViewController.swift in Sources */, E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */, + E43912D0267878BF003CD344 /* HexColorConvertable.swift in Sources */, FAC6D88D2671D8A100A9E5F9 /* SocialLoginManagable.swift in Sources */, E42AD124267093700071B436 /* MyAccountViewController.swift in Sources */, FAEB30AC266F5E9700C17BE9 /* Colors.swift in Sources */, @@ -397,6 +404,7 @@ E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E426DAC22671B1C60069E77D /* LoginKeyChainManager.swift in Sources */, + E43912D2267878F4003CD344 /* HexColorCode.swift in Sources */, E426DAC72671F6A00069E77D /* LoginError.swift in Sources */, E426DAC42671D95D0069E77D /* LoginService.swift in Sources */, E426DACB267206D10069E77D /* LoginInfoContainer.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index ac0dc2551..b07902dad 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -34,6 +34,9 @@ final class LabelViewController: UIViewController { private var loginInfo: LoginInfo? + private let colorConverter: HexColorConvertable = HexColorConverter() + private let colors = ["#558776", "#F3F0D7", "#FFC107", "#FFD8CC", "#CEE5D0", "#231E23"] + override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.white @@ -80,12 +83,16 @@ extension LabelViewController: UITableViewDelegate { extension LabelViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 5 + return 6 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cellID = LabelTableViewCell.reuseID let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? LabelTableViewCell ?? LabelTableViewCell() + let hex = HexColorCode(from: colors[indexPath.row]) + let backgroundColor = colorConverter.convertHex(hex) + let titleColor = colorConverter.isColorDark(hex: hex) ? UIColor.white : UIColor.black + cell.configure(with: backgroundColor, titleColor, "졸력", "졸린 오후") return cell } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Model/ColorConverter.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Model/ColorConverter.swift deleted file mode 100644 index 9f774017d..000000000 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Model/ColorConverter.swift +++ /dev/null @@ -1,10 +0,0 @@ -// -// ColorConverter.swift -// issue-tracker -// -// Created by Song on 2021/06/14. -// - -import Foundation - - diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorCode.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorCode.swift new file mode 100644 index 000000000..638490e7e --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorCode.swift @@ -0,0 +1,31 @@ +// +// HexColorCode.swift +// issue-tracker +// +// Created by Song on 2021/06/15. +// + +import UIKit + +struct HexColorCode { + let red: CGFloat + let green: CGFloat + let blue: CGFloat + let alpha: CGFloat + + init(from hexInString: String) { + let hexNums = hexInString.filter{ $0 != "#" }.map{ String($0) } + + let hexRedString = hexNums.count >= 2 ? hexNums[0...1].joined() : "00" + self.red = CGFloat(Int(hexRedString, radix: 16) ?? 255) + + let hexGreenString = hexNums.count >= 4 ? hexNums[2...3].joined() : "00" + self.green = CGFloat(Int(hexGreenString, radix: 16) ?? 255) + + let hexBlueString = hexNums.count >= 6 ? hexNums[4...5].joined() : "00" + self.blue = CGFloat(Int(hexBlueString, radix: 16) ?? 255) + + let hexAlphaString = hexNums.count == 8 ? hexNums[6...7].joined() : "FF" + self.alpha = CGFloat(Int(hexAlphaString, radix: 16) ?? 255) + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorConvertable.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorConvertable.swift new file mode 100644 index 000000000..f340e7c8b --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorConvertable.swift @@ -0,0 +1,13 @@ +// +// ColorConvertable.swift +// issue-tracker +// +// Created by Song on 2021/06/15. +// + +import UIKit + +protocol HexColorConvertable { + func convertHex(_ hex: HexColorCode) -> UIColor + func isColorDark(hex: HexColorCode) -> Bool +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorConverter.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorConverter.swift new file mode 100644 index 000000000..16aadd8a5 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Model/HexColorConverter.swift @@ -0,0 +1,25 @@ +// +// ColorConverter.swift +// issue-tracker +// +// Created by Song on 2021/06/14. +// + +import UIKit + +final class HexColorConverter: HexColorConvertable { + func convertHex(_ hex: HexColorCode) -> UIColor { + let red = hex.red / 255 + let green = hex.green / 255 + let blue = hex.blue / 255 + let alpha = hex.alpha / 255 + return UIColor(red: red, green: green, blue: blue, alpha: alpha) + } + + func isColorDark(hex: HexColorCode) -> Bool { + let red = hex.red + let green = hex.green + let blue = hex.blue + return (red * 0.299 + green * 0.587 + blue * 0.114) <= 186 + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift index ca4c95f00..3f4aa4c05 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift @@ -63,19 +63,9 @@ final class LabelTableViewCell: UITableViewCell { ]) } - func configure(with colorCode: String,_ title: String,_ description: String?) { - let backgroundColor = hexCodeToColor(colorCode) - let textColor = textColor(from: colorCode) - labelView.configure(with: backgroundColor, textColor, title) - + func configure(with backgroundColor: UIColor,_ titleColor: UIColor, _ title: String,_ description: String?) { + labelView.configure(with: backgroundColor, titleColor, title) self.labelDescription.text = description } - - private func hexCodeToColor(_ hex: String) -> UIColor { - return UIColor.black - } - - private func textColor(from backgroundcolorCode: String) -> UIColor { - return UIColor.white - } + } From a6c3e0299aa90ccb5fe63da004d50f542f4a9a4b Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Mon, 14 Jun 2021 16:00:09 +0900 Subject: [PATCH 06/91] =?UTF-8?q?feat:=20[#51]=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=A0=95=EB=B3=B4=20=ED=82=A4=EC=B2=B4=EC=9D=B8=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Login/Model/Apple/AppleAuthorizationManager.swift | 8 ++++---- .../Login/Model/Github/GithubAuthorizationManager.swift | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift index ce04b9a56..450141932 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift @@ -44,11 +44,11 @@ extension AppleAuthorizationManager: ASAuthorizationControllerDelegate { let userID = appleIDCredential.user let loginInfo = LoginInfo(userID: userID, jwt: tokenInString, avatarURL: nil, name: name) - if !keyChainSaver.save(loginInfo) { - let saveError = LoginError.keyChainSave - delegate?.didSocialLoginFail(with: saveError) - } else { + if keyChainSaver.save(loginInfo) { delegate?.didSocialLoginSuccess(with: loginInfo) + } else { + let saveError = LoginError.keyChainSave + delegate?.didSocialLoginFail(with: saveError) } } diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift index 7c9f45b7f..ee771e938 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift @@ -60,11 +60,11 @@ extension GithubAuthorizationManager: SocialLoginManagable { jwt: response.jwt, avatarURL: response.avatarUrl, name: response.loginId) - if !self.keyChainSaver.save(loginInfo) { + if self.keyChainSaver.save(loginInfo) { + self.delegate?.didSocialLoginSuccess(with: loginInfo) + } else { let saveError = LoginError.keyChainSave self.delegate?.didSocialLoginFail(with: saveError) - } else { - self.delegate?.didSocialLoginSuccess(with: loginInfo) } case .failure: let githubLoginError = LoginError.githubIDAccess From 7daa7253da672456bf415f8e4cefedeb3a58bc9d Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Mon, 14 Jun 2021 17:58:43 +0900 Subject: [PATCH 07/91] =?UTF-8?q?feat:=20[#51]=20Github=20DTO=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Model/Github/GithubAuthorizationManager.swift | 2 +- .../Login/Model/Github/OAuthResponseDTO.swift | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift index ee771e938..03c3e0e50 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift @@ -57,7 +57,7 @@ extension GithubAuthorizationManager: SocialLoginManagable { switch result { case .success(let response): let loginInfo = LoginInfo(userID: nil, - jwt: response.jwt, + jwt: response.jwt.jwt, avatarURL: response.avatarUrl, name: response.loginId) if self.keyChainSaver.save(loginInfo) { diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift index e9728640e..28048bccb 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift @@ -7,8 +7,18 @@ import Foundation -struct OAuthResponseDTO: Decodable { +struct JWT: Decodable { let jwt: String + let tokenType: String + + enum CodingKeys: String, CodingKey { + case jwt + case tokenType + } +} + +struct OAuthResponseDTO: Decodable { + let jwt: JWT let avatarUrl: String let loginId: String From f618172949613ef34410b415c43089e0ad749ab0 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Mon, 14 Jun 2021 18:45:40 +0900 Subject: [PATCH 08/91] =?UTF-8?q?fix=20:=20[#35]=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=82=AC=EC=A7=84=20=EB=B6=88=EB=9F=AC=EC=99=80?= =?UTF-8?q?=EC=84=9C=20=EB=B3=B4=EC=97=AC=EC=A3=BC=EA=B8=B0=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TabBar/IssueTrackerTabBarController.swift | 40 ++++++++++++++----- .../TabBar/IssueTrackerTabBarCreator.swift | 3 +- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift index adc1d21c7..776dfbe4a 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift @@ -8,10 +8,10 @@ import UIKit class IssueTrackerTabBarController: UITabBarController { - + private var loginInfo: LoginInfo? private let imageLoadManager = ImageLoadManager() - + override func viewDidLoad() { super.viewDidLoad() tabBar.tintColor = Colors.mainGrape @@ -19,6 +19,10 @@ class IssueTrackerTabBarController: UITabBarController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() updateUserImage() } @@ -27,20 +31,34 @@ class IssueTrackerTabBarController: UITabBarController { } private func updateUserImage() { - guard let imageURL = self.loginInfo?.avatarURL, - let viewControllers = self.viewControllers, - let myAccountViewController = viewControllers.compactMap({ $0 as? MyAccountViewController }).first else { return } + guard let imageURL = self.loginInfo?.avatarURL else { return } imageLoadManager.load(from: imageURL) { cachePath in - guard let userImage = UIImage(contentsOfFile: cachePath), - let iconSize = myAccountViewController.tabBarItem.image?.size else { return } - - let resizedUserImage = userImage.resizedImage(size: iconSize) - + guard let userImage = UIImage(contentsOfFile: cachePath) else {return} DispatchQueue.main.async { - myAccountViewController.tabBarItem.image = resizedUserImage + self.addSubviewToLastTabItem(userImage) } } } +} + +extension UITabBarController { + func addSubviewToLastTabItem(_ image: UIImage) { + + if let lastTabBarButton = self.tabBar.subviews.last, let tabItemImageView = lastTabBarButton.subviews.first { + if let accountTabBarItem = self.tabBar.items?.last { + accountTabBarItem.selectedImage = nil + accountTabBarItem.image = nil + } + let imgView = UIImageView() + imgView.frame = tabItemImageView.frame + imgView.layer.cornerRadius = tabItemImageView.frame.height/2 + imgView.layer.masksToBounds = true + imgView.contentMode = .scaleAspectFill + imgView.clipsToBounds = true + imgView.image = image + self.tabBar.subviews.last?.addSubview(imgView) + } + } } diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift index 4add32723..ca4b77979 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift @@ -59,8 +59,7 @@ final class IssueTrackerTabBarCreator { extension IssueTrackerTabBarCreator { func create() -> IssueTrackerTabBarController { let issueTrackerTabBarController = IssueTrackerTabBarController() - issueTrackerTabBarController.configure(loginInfo: loginInfo) - + issueTrackerTabBarController.configure(loginInfo: loginInfo) let childs = childInfos.map{ generateChild(with: $0) } issueTrackerTabBarController.setViewControllers(childs, animated: true) return issueTrackerTabBarController From 8f95fc65b1520bed132992c10b307941557277f8 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Mon, 14 Jun 2021 19:20:59 +0900 Subject: [PATCH 09/91] =?UTF-8?q?feat:=20[#51]=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=95=84=EC=9B=83=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MyAccount/MyAccountViewController.swift | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift index e481a08b2..29e282903 100644 --- a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift @@ -9,6 +9,7 @@ import UIKit class MyAccountViewController: UIViewController { + private lazy var welcomeLabel: UILabel = { let label = UILabel() label.font = .systemFont(ofSize: 30, weight: .medium) @@ -32,7 +33,10 @@ class MyAccountViewController: UIViewController { private let spacing: CGFloat = 16 private var loginInfo: LoginInfo? + + override func viewDidLoad() { + super.viewDidLoad() view.backgroundColor = .white title = "내 계정" @@ -69,8 +73,30 @@ class MyAccountViewController: UIViewController { } @objc private func didLogoutTouched(_ sender: UIButton) { - let logoutErrorText = LoginError.logout.description - presentAlert(with: logoutErrorText) +// let logoutErrorText = LoginError.logout.description +// presentAlert(with: logoutErrorText) + + var loginManager: LoginKeyChainManager? + + for loginService in LoginService.allCases { + loginManager = LoginKeyChainManager(loginService: loginService) + loginInfo = loginManager?.read() + if loginInfo != nil { + break + } + } + guard let loginManager = loginManager else { return } + + print("삭제 전 정보 = ", loginManager.read()) + + let _ = loginManager.delete() + + print("삭제 된거 맞나? = ", loginManager.read()) + + let loginViewController = LoginViewController() + loginViewController.modalPresentationStyle = .fullScreen + self.present(loginViewController, animated: true, completion: nil) + } } From 3f21cd59323111dd0122bebd990cf884a9dd602a Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Mon, 14 Jun 2021 19:31:43 +0900 Subject: [PATCH 10/91] =?UTF-8?q?chore:=20[#51]=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Login/Controller/LoginViewController.swift | 2 +- .../Main/MyAccount/MyAccountViewController.swift | 9 +-------- .../Main/TabBar/IssueTrackerTabBarController.swift | 1 + 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift b/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift index ac24c35e8..e3a0a8a16 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift @@ -109,7 +109,7 @@ class LoginViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - addLoginStackViewDivisionLine() + addLoginStackViewDivisionLine() } private func socialLoginButton(with image: UIImage?, _ title: String) -> UIButton { diff --git a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift index 29e282903..e5329a497 100644 --- a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift @@ -33,8 +33,6 @@ class MyAccountViewController: UIViewController { private let spacing: CGFloat = 16 private var loginInfo: LoginInfo? - - override func viewDidLoad() { super.viewDidLoad() @@ -86,13 +84,8 @@ class MyAccountViewController: UIViewController { } } guard let loginManager = loginManager else { return } - - print("삭제 전 정보 = ", loginManager.read()) - let _ = loginManager.delete() - - print("삭제 된거 맞나? = ", loginManager.read()) - + let loginViewController = LoginViewController() loginViewController.modalPresentationStyle = .fullScreen self.present(loginViewController, animated: true, completion: nil) diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift index 776dfbe4a..292181b1d 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift @@ -15,6 +15,7 @@ class IssueTrackerTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() tabBar.tintColor = Colors.mainGrape + definesPresentationContext = true } override func viewDidAppear(_ animated: Bool) { From ac3849f3da77710f170716731b41ceb5ad10dbde Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Mon, 14 Jun 2021 21:36:16 +0900 Subject: [PATCH 11/91] =?UTF-8?q?fix=20:[#35]=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=EC=A6=88=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TabBar/IssueTrackerTabBarController.swift | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift index 292181b1d..0011d0353 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift @@ -44,22 +44,19 @@ class IssueTrackerTabBarController: UITabBarController { } extension UITabBarController { - func addSubviewToLastTabItem(_ image: UIImage) { + //tabBar.tabBar.items?.last = MyAccountViewController + guard let myAccountTabBarItem = self.tabBar.items?.last else {return} + myAccountTabBarItem.image = nil - if let lastTabBarButton = self.tabBar.subviews.last, let tabItemImageView = lastTabBarButton.subviews.first { - if let accountTabBarItem = self.tabBar.items?.last { - accountTabBarItem.selectedImage = nil - accountTabBarItem.image = nil - } - let imgView = UIImageView() - imgView.frame = tabItemImageView.frame - imgView.layer.cornerRadius = tabItemImageView.frame.height/2 - imgView.layer.masksToBounds = true - imgView.contentMode = .scaleAspectFill - imgView.clipsToBounds = true - imgView.image = image - self.tabBar.subviews.last?.addSubview(imgView) - } + let imgView = UIImageView() + + imgView.frame = CGRect(x: 34.3333, y: 7.33333, width: 25.3333, height: 24.3333) //하드코딩값. 실제 myAccountTabBarItem.image.size를 정확하게 가져올 방법을 못찾음. + imgView.layer.cornerRadius = 10 + imgView.layer.masksToBounds = true + imgView.contentMode = .scaleAspectFill + imgView.clipsToBounds = true + imgView.image = image + self.tabBar.subviews.last?.addSubview(imgView) } } From 060c152dd6d0c7a34b8c66bbfb8efaac921d6dcc Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 15 Jun 2021 11:15:38 +0900 Subject: [PATCH 12/91] =?UTF-8?q?fix=20:=20[#29]=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=9D=B4=ED=9B=84=20=EC=9E=90=EB=8F=99=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=A0=84=ED=99=98=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/issue-tracker/issue-tracker/Common/Colors.swift | 2 +- iOS/issue-tracker/issue-tracker/LifeCycle/SceneDelegate.swift | 2 -- .../issue-tracker/Login/Controller/LoginViewController.swift | 1 - .../issue-tracker/Main/MyAccount/MyAccountViewController.swift | 3 +-- .../Main/TabBar/IssueTrackerTabBarController.swift | 3 +-- 5 files changed, 3 insertions(+), 8 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Common/Colors.swift b/iOS/issue-tracker/issue-tracker/Common/Colors.swift index 3dbabec9b..a0133edc7 100644 --- a/iOS/issue-tracker/issue-tracker/Common/Colors.swift +++ b/iOS/issue-tracker/issue-tracker/Common/Colors.swift @@ -13,5 +13,5 @@ enum Colors { static let closeCarrot = UIColor(named: "CloseCarrot") ?? UIColor.orange static let deleteSunnyside = UIColor(named: "DeleteSunnyside") ?? UIColor.yellow static let openBrocoli = UIColor(named: "OpenBrocoli") ?? UIColor.purple - static let mainGrape = UIColor(named: "MainGrape") ?? UIColor.purple + static let mainGrape = UIColor(named: "MainGrape") ?? UIColor.purple } diff --git a/iOS/issue-tracker/issue-tracker/LifeCycle/SceneDelegate.swift b/iOS/issue-tracker/issue-tracker/LifeCycle/SceneDelegate.swift index 426bb40ff..91d2b9003 100644 --- a/iOS/issue-tracker/issue-tracker/LifeCycle/SceneDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/LifeCycle/SceneDelegate.swift @@ -41,7 +41,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } else { straightToIssueTrackerScene(with: loginManager, loginInfo) } - } private func straightToIssueTrackerScene(with loginManager: LoginKeyChainManager,_ loginInfo: LoginInfo) { @@ -51,5 +50,4 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { self.window?.rootViewController = issueTrackerTabBarController } } - } diff --git a/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift b/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift index e3a0a8a16..fd73da149 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift @@ -104,7 +104,6 @@ class LoginViewController: UIViewController { addLoginStackView() addLoginButtons() addSocialLoginButtons() - definesPresentationContext = true } override func viewDidAppear(_ animated: Bool) { diff --git a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift index e5329a497..781e521a5 100644 --- a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift @@ -74,8 +74,7 @@ class MyAccountViewController: UIViewController { // let logoutErrorText = LoginError.logout.description // presentAlert(with: logoutErrorText) - var loginManager: LoginKeyChainManager? - + var loginManager: LoginKeyChainManager? for loginService in LoginService.allCases { loginManager = LoginKeyChainManager(loginService: loginService) loginInfo = loginManager?.read() diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift index 0011d0353..e8e40df25 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift @@ -14,8 +14,7 @@ class IssueTrackerTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() - tabBar.tintColor = Colors.mainGrape - definesPresentationContext = true + tabBar.tintColor = Colors.mainGrape } override func viewDidAppear(_ animated: Bool) { From 281a09ec1cbfac808f9b07b8552ee871223fc2fb Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 15 Jun 2021 12:07:04 +0900 Subject: [PATCH 13/91] =?UTF-8?q?feat=20:[#35]=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=82=AC=EC=A7=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EB=A6=AC=EC=82=AC=EC=9D=B4=EC=A7=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Main/TabBar/IssueTrackerTabBarController.swift | 14 +++++++++----- .../Main/TabBar/IssueTrackerTabBarCreator.swift | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift index e8e40df25..cbdc80c6c 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift @@ -14,7 +14,7 @@ class IssueTrackerTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() - tabBar.tintColor = Colors.mainGrape + tabBar.tintColor = Colors.mainGrape } override func viewDidAppear(_ animated: Bool) { @@ -36,21 +36,25 @@ class IssueTrackerTabBarController: UITabBarController { imageLoadManager.load(from: imageURL) { cachePath in guard let userImage = UIImage(contentsOfFile: cachePath) else {return} DispatchQueue.main.async { - self.addSubviewToLastTabItem(userImage) + self.addSubviewToMyAccountTabItem(userImage) } } } } extension UITabBarController { - func addSubviewToLastTabItem(_ image: UIImage) { + func addSubviewToMyAccountTabItem(_ image: UIImage) { //tabBar.tabBar.items?.last = MyAccountViewController guard let myAccountTabBarItem = self.tabBar.items?.last else {return} myAccountTabBarItem.image = nil + - let imgView = UIImageView() +// myAccountTabBarItem.image = image.resizedImage(size: CGSize(width: 28, height: 28))?.withRenderingMode(.alwaysOriginal) +// myAccountTabBarItem.selectedImage = myAccountTabBarItem.image +// - imgView.frame = CGRect(x: 34.3333, y: 7.33333, width: 25.3333, height: 24.3333) //하드코딩값. 실제 myAccountTabBarItem.image.size를 정확하게 가져올 방법을 못찾음. + let imgView = UIImageView() + imgView.frame = CGRect(x: 34.3333, y: 7.66667, width: 24.3333, height: 23.6667) //하드코딩값. 실제 myAccountTabBarItem.image.size를 정확하게 가져올 방법을 못찾음. imgView.layer.cornerRadius = 10 imgView.layer.masksToBounds = true imgView.contentMode = .scaleAspectFill diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift index ca4b77979..8951d817a 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift @@ -36,7 +36,7 @@ final class IssueTrackerTabBarCreator { let label = TabBarChildInfo(title: Title.label, imageName: SystemImageName.label, type: LabelViewController.self) let milestone = TabBarChildInfo(title: Title.milestone, imageName: SystemImageName.milestone, type: MilestoneViewController.self) let myAccount = TabBarChildInfo(title: Title.myAccount, imageName: SystemImageName.myAccount, type: MyAccountViewController.self) - self.init(childInfos: [issue, label, milestone, myAccount], loginInfo: loginInfo) + self.init(childInfos: [issue, label, milestone, myAccount], loginInfo: loginInfo) } private func generateChild(with info: TabBarChildInfo) -> UIViewController { From e5356861e6d0fa310d4f09d29216f67c44bb0d9f Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 15 Jun 2021 14:36:04 +0900 Subject: [PATCH 14/91] =?UTF-8?q?feat=20:[#29]=20=EC=9E=90=EB=8F=99=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EC=A0=84=ED=99=98=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=A0=95=EB=B3=B4=20=EC=B2=B4=ED=81=AC=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Login/Model/Github/GithubAuthorizationManager.swift | 7 +++++++ .../Main/TabBar/IssueTrackerTabBarController.swift | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift index 03c3e0e50..9253fed74 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift @@ -35,6 +35,12 @@ final class GithubAuthorizationManager: NSObject, ASWebAuthenticationPresentatio extension GithubAuthorizationManager: SocialLoginManagable { func login(){ + + if let loginInfo = keyChainSaver.read() { + self.delegate?.didSocialLoginSuccess(with: loginInfo) + return + } + var components = URLComponents(string: url)! components.queryItems = [ URLQueryItem(name: "client_id", value: client_id), @@ -60,6 +66,7 @@ extension GithubAuthorizationManager: SocialLoginManagable { jwt: response.jwt.jwt, avatarURL: response.avatarUrl, name: response.loginId) + if self.keyChainSaver.save(loginInfo) { self.delegate?.didSocialLoginSuccess(with: loginInfo) } else { diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift index cbdc80c6c..7ce9ca31e 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift @@ -12,12 +12,12 @@ class IssueTrackerTabBarController: UITabBarController { private var loginInfo: LoginInfo? private let imageLoadManager = ImageLoadManager() - override func viewDidLoad() { + override func viewDidLoad() { super.viewDidLoad() - tabBar.tintColor = Colors.mainGrape } override func viewDidAppear(_ animated: Bool) { + tabBar.tintColor = Colors.mainGrape super.viewDidAppear(animated) } From 1e670cddeba1efa5ddbfa618ca6f1df5f221002a Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 15 Jun 2021 14:51:57 +0900 Subject: [PATCH 15/91] =?UTF-8?q?chore=20:=20[#66]=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Main/MyAccount/MyAccountViewController.swift | 5 +---- .../Main/TabBar/IssueTrackerTabBarController.swift | 11 ++--------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift index 781e521a5..f19053e92 100644 --- a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift @@ -71,10 +71,7 @@ class MyAccountViewController: UIViewController { } @objc private func didLogoutTouched(_ sender: UIButton) { -// let logoutErrorText = LoginError.logout.description -// presentAlert(with: logoutErrorText) - - var loginManager: LoginKeyChainManager? + var loginManager: LoginKeyChainManager? for loginService in LoginService.allCases { loginManager = LoginKeyChainManager(loginService: loginService) loginInfo = loginManager?.read() diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift index 7ce9ca31e..c5e2f0a74 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift @@ -12,7 +12,7 @@ class IssueTrackerTabBarController: UITabBarController { private var loginInfo: LoginInfo? private let imageLoadManager = ImageLoadManager() - override func viewDidLoad() { + override func viewDidLoad() { super.viewDidLoad() } @@ -44,17 +44,10 @@ class IssueTrackerTabBarController: UITabBarController { extension UITabBarController { func addSubviewToMyAccountTabItem(_ image: UIImage) { - //tabBar.tabBar.items?.last = MyAccountViewController guard let myAccountTabBarItem = self.tabBar.items?.last else {return} myAccountTabBarItem.image = nil - - -// myAccountTabBarItem.image = image.resizedImage(size: CGSize(width: 28, height: 28))?.withRenderingMode(.alwaysOriginal) -// myAccountTabBarItem.selectedImage = myAccountTabBarItem.image -// - let imgView = UIImageView() - imgView.frame = CGRect(x: 34.3333, y: 7.66667, width: 24.3333, height: 23.6667) //하드코딩값. 실제 myAccountTabBarItem.image.size를 정확하게 가져올 방법을 못찾음. + imgView.frame = CGRect(x: 34.3333, y: 7.66667, width: 24.3333, height: 23.6667) imgView.layer.cornerRadius = 10 imgView.layer.masksToBounds = true imgView.contentMode = .scaleAspectFill From 537a014e9318a77bb64ad019c2d3cd314bd9bb17 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 15 Jun 2021 15:16:33 +0900 Subject: [PATCH 16/91] =?UTF-8?q?fix=20:=20[#66]=20=EA=B3=84=EC=A0=95?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EC=9D=B4=EB=A6=84=20=EC=9E=98=EB=A6=AC?= =?UTF-8?q?=EB=8A=94=20=ED=98=84=EC=83=81=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker/Main/MyAccount/MyAccountViewController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift index f19053e92..4136b6b40 100644 --- a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift @@ -13,8 +13,9 @@ class MyAccountViewController: UIViewController { private lazy var welcomeLabel: UILabel = { let label = UILabel() label.font = .systemFont(ofSize: 30, weight: .medium) - label.text = "\(userName) 님, 환영합니다!" + label.text = "\(userName) 님, \n환영합니다!" label.translatesAutoresizingMaskIntoConstraints = false + label.numberOfLines = 2 return label }() From 1371dd858804626fb6cf404bba5c9477a09fe4e3 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 15 Jun 2021 16:36:26 +0900 Subject: [PATCH 17/91] =?UTF-8?q?refactor:=20[#44]=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=9E=AC=EC=82=AC=EC=9A=A9=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EC=84=9C=EB=B8=8C=ED=81=B4=EB=9E=98=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 4 ++ .../Main/Common/View/ImageBarButton.swift | 43 +++++++++++++++++++ .../Controller/LabelViewController.swift | 12 ++---- 3 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index fbe645e31..32ad8b6dc 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ E43912CE26777310003CD344 /* HexColorConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912CD26777310003CD344 /* HexColorConverter.swift */; }; E43912D0267878BF003CD344 /* HexColorConvertable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912CF267878BF003CD344 /* HexColorConvertable.swift */; }; E43912D2267878F4003CD344 /* HexColorCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D1267878F4003CD344 /* HexColorCode.swift */; }; + E43912D426788CC3003CD344 /* ImageBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D326788CC3003CD344 /* ImageBarButton.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -72,6 +73,7 @@ E43912CD26777310003CD344 /* HexColorConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HexColorConverter.swift; sourceTree = ""; }; E43912CF267878BF003CD344 /* HexColorConvertable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HexColorConvertable.swift; sourceTree = ""; }; E43912D1267878F4003CD344 /* HexColorCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HexColorCode.swift; sourceTree = ""; }; + E43912D326788CC3003CD344 /* ImageBarButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageBarButton.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -256,6 +258,7 @@ E43912C926776DA0003CD344 /* View */ = { isa = PBXGroup; children = ( + E43912D326788CC3003CD344 /* ImageBarButton.swift */, E43912C626776D8F003CD344 /* LabelView.swift */, ); path = View; @@ -404,6 +407,7 @@ E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E426DAC22671B1C60069E77D /* LoginKeyChainManager.swift in Sources */, + E43912D426788CC3003CD344 /* ImageBarButton.swift in Sources */, E43912D2267878F4003CD344 /* HexColorCode.swift in Sources */, E426DAC72671F6A00069E77D /* LoginError.swift in Sources */, E426DAC42671D95D0069E77D /* LoginService.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift new file mode 100644 index 000000000..52ed932b3 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift @@ -0,0 +1,43 @@ +// +// AddButton.swift +// issue-tracker +// +// Created by Song on 2021/06/15. +// + +import UIKit + +final class ImageBarButton: UIButton { + + override init(frame: CGRect) { + super.init(frame: frame) + configure() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + configure() + } + + private func configure() { + tintColor = Colors.mainGrape + setTitleColor(Colors.mainGrape, for: .normal) + semanticContentAttribute = .forceRightToLeft + imageEdgeInsets = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 0) + } + + func configure(with systemImageName: String,_ buttonTitle: String) { + setImage(of: systemImageName) + setTitle(buttonTitle, for: .normal) + } + + private func setImage(of systemName: String) { + let image = UIImage(systemName: systemName) + setImage(image, for: .normal) + } + + func moveImageToLeft() { + semanticContentAttribute = .forceLeftToRight + imageEdgeInsets = UIEdgeInsets(top: 0, left: -4, bottom: 0, right: 0) + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index b07902dad..da1bddac5 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -9,15 +9,9 @@ import UIKit final class LabelViewController: UIViewController { - private lazy var addLabelButton: UIButton = { - let button = UIButton() - let plusImage = UIImage(systemName: "plus") - button.setImage(plusImage, for: .normal) - button.tintColor = Colors.mainGrape - button.setTitle("추가", for: .normal) - button.setTitleColor(Colors.mainGrape, for: .normal) - button.semanticContentAttribute = .forceRightToLeft - button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 0) + private lazy var addLabelButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "plus", "추가") button.addTarget(self, action: #selector(addLabelTouched), for: .touchUpInside) return button }() From 4cd4d42a567279a9251697b6877d25cf254056cb Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 15 Jun 2021 17:24:51 +0900 Subject: [PATCH 18/91] =?UTF-8?q?refactor:=20[#44]=20=EB=84=A4=ED=8A=B8?= =?UTF-8?q?=EC=9B=8C=ED=81=AC=20=EB=AA=A8=EB=93=88=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 재사용을 위해 request manager 생성 --- .../issue-tracker.xcodeproj/project.pbxproj | 8 +++++ .../Github/GithubAuthorizationManager.swift | 7 +++-- .../Login/Model/Github/OAuthResponseDTO.swift | 6 ++++ .../issue-tracker/Network/EndPoint.swift | 12 ++++++++ .../Network/NetworkManager.swift | 19 ++++++------ .../Network/RequestManager.swift | 30 +++++++++++++++++++ 6 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Network/EndPoint.swift create mode 100644 iOS/issue-tracker/issue-tracker/Network/RequestManager.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 32ad8b6dc..c26fbdf13 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -33,6 +33,8 @@ E43912D0267878BF003CD344 /* HexColorConvertable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912CF267878BF003CD344 /* HexColorConvertable.swift */; }; E43912D2267878F4003CD344 /* HexColorCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D1267878F4003CD344 /* HexColorCode.swift */; }; E43912D426788CC3003CD344 /* ImageBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D326788CC3003CD344 /* ImageBarButton.swift */; }; + E43912D626789812003CD344 /* RequestManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D526789812003CD344 /* RequestManager.swift */; }; + E43912D826789A83003CD344 /* EndPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D726789A83003CD344 /* EndPoint.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -74,6 +76,8 @@ E43912CF267878BF003CD344 /* HexColorConvertable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HexColorConvertable.swift; sourceTree = ""; }; E43912D1267878F4003CD344 /* HexColorCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HexColorCode.swift; sourceTree = ""; }; E43912D326788CC3003CD344 /* ImageBarButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageBarButton.swift; sourceTree = ""; }; + E43912D526789812003CD344 /* RequestManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestManager.swift; sourceTree = ""; }; + E43912D726789A83003CD344 /* EndPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndPoint.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -310,6 +314,8 @@ FAEB30B22670B75200C17BE9 /* Network */ = { isa = PBXGroup; children = ( + E43912D726789A83003CD344 /* EndPoint.swift */, + E43912D526789812003CD344 /* RequestManager.swift */, FAEB30B32670B76200C17BE9 /* NetworkManager.swift */, E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */, ); @@ -410,9 +416,11 @@ E43912D426788CC3003CD344 /* ImageBarButton.swift in Sources */, E43912D2267878F4003CD344 /* HexColorCode.swift in Sources */, E426DAC72671F6A00069E77D /* LoginError.swift in Sources */, + E43912D626789812003CD344 /* RequestManager.swift in Sources */, E426DAC42671D95D0069E77D /* LoginService.swift in Sources */, E426DACB267206D10069E77D /* LoginInfoContainer.swift in Sources */, E42AD120267093430071B436 /* LabelViewController.swift in Sources */, + E43912D826789A83003CD344 /* EndPoint.swift in Sources */, E426DABE2670EC830069E77D /* SocialLoginManagerDelegate.swift in Sources */, E42AD0FE266E52FB0071B436 /* AppDelegate.swift in Sources */, E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift index 9253fed74..e9dfbe0d0 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift @@ -56,9 +56,12 @@ extension GithubAuthorizationManager: SocialLoginManagable { .first? .value else { return } - let networkmanager = NetworkManager() + let url = EndPoint.OAuth.rawValue + let parameter = ["code": code] + let requestManager = RequestManager(url: url, parameters: parameter) + let networkmanager = NetworkManager(requestManager: requestManager) - networkmanager.setInfoGithub(with: code) { [weak self] (result: Result) in + networkmanager.get { [weak self] (result: Result) in guard let self = self else { return } switch result { case .success(let response): diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift index 28048bccb..c166435ac 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift @@ -17,6 +17,12 @@ struct JWT: Decodable { } } +extension JWT: CustomStringConvertible { + var description: String { + return "\(tokenType) \(jwt)" + } +} + struct OAuthResponseDTO: Decodable { let jwt: JWT let avatarUrl: String diff --git a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift new file mode 100644 index 000000000..da86b70df --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift @@ -0,0 +1,12 @@ +// +// EndPoint.swift +// issue-tracker +// +// Created by Song on 2021/06/15. +// + +import Foundation + +enum EndPoint: String { + case OAuth = "http://3.34.122.67/api/login/ios" +} diff --git a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift index f43a6d0d9..fb08b9c83 100644 --- a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift +++ b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift @@ -9,21 +9,22 @@ import Foundation import Alamofire protocol NetworkManagerOperations { - func setInfoGithub(with code: String, completion: @escaping (Result) -> Void) + func get(completion: @escaping (Result) -> Void) } -class NetworkManager: NetworkManagerOperations { +final class NetworkManager: NetworkManagerOperations { - let accessTokenURL = "http://3.34.122.67/api/login/ios" + private let requestManager: RequestManager - func setInfoGithub(with code: String, completion: @escaping (Result) -> Void) { + init(requestManager: RequestManager) { + self.requestManager = requestManager + } + + func get(completion: @escaping (Result) -> Void) { - let param: Parameters = [ - "code" : code - ] + let request = requestManager.create(method: .get) - AF.request(accessTokenURL, method: .get, parameters: param) - .responseDecodable(of: T.self) { response in + request.responseDecodable(of: T.self) { response in switch response.result { case .success(let data): completion(.success(data)) diff --git a/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift b/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift new file mode 100644 index 000000000..33e104fa8 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift @@ -0,0 +1,30 @@ +// +// RequestManager.swift +// issue-tracker +// +// Created by Song on 2021/06/15. +// + +import Foundation +import Alamofire + +final class RequestManager { + + private var url: String + private var parameters: [String: Any]? + private var headers: HTTPHeaders? + + init(url: String, parameters: [String: Any]? = nil, headers: HTTPHeaders? = nil) { + self.url = url + self.parameters = parameters + self.headers = headers + } + + func create(method: HTTPMethod) -> DataRequest { + return AF.request(self.url, + method: method, + parameters: self.parameters, + headers: self.headers) + } + +} From 8b9c86bd3aa426df37bb67301fcaeaca227f784d Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 15 Jun 2021 17:28:37 +0900 Subject: [PATCH 19/91] =?UTF-8?q?feat=20:[#68]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20=EC=B6=94=EA=B0=80=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?View=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 26 +++++++++++- .../Controller/MilestoneViewController.swift | 41 +++++++++++++++++++ .../Milestone/MilestoneViewController.swift | 26 ------------ 3 files changed, 66 insertions(+), 27 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift delete mode 100644 iOS/issue-tracker/issue-tracker/Main/Milestone/MilestoneViewController.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 32ad8b6dc..9e2467ba5 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -234,7 +234,9 @@ E42AD11B26708EC80071B436 /* Milestone */ = { isa = PBXGroup; children = ( - E42AD121267093590071B436 /* MilestoneViewController.swift */, + FAB2C36626789ADD009F879C /* Model */, + FAB2C36726789AE3009F879C /* View */, + FAB2C36826789AE6009F879C /* Controller */, ); path = Milestone; sourceTree = ""; @@ -298,6 +300,28 @@ path = Apple; sourceTree = ""; }; + FAB2C36626789ADD009F879C /* Model */ = { + isa = PBXGroup; + children = ( + ); + path = Model; + sourceTree = ""; + }; + FAB2C36726789AE3009F879C /* View */ = { + isa = PBXGroup; + children = ( + ); + path = View; + sourceTree = ""; + }; + FAB2C36826789AE6009F879C /* Controller */ = { + isa = PBXGroup; + children = ( + E42AD121267093590071B436 /* MilestoneViewController.swift */, + ); + path = Controller; + sourceTree = ""; + }; FAC6D8922671E1A800A9E5F9 /* Github */ = { isa = PBXGroup; children = ( diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift new file mode 100644 index 000000000..7e99c9fb5 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift @@ -0,0 +1,41 @@ +// +// MilestoneViewController.swift +// issue-tracker +// +// Created by Song on 2021/06/09. +// + +import UIKit + +class MilestoneViewController: UIViewController { + + private lazy var addMileStoneButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "plus", "추가") + button.addTarget(self, action: #selector(addMileStoneTouched), for: .touchUpInside) + return button + }() + + @objc private func addMileStoneTouched(_ sender: UIButton) { + print("마일스톤 추가해줘잉") + } + + private var loginInfo: LoginInfo? + + override func viewDidLoad() { + super.viewDidLoad() + view.backgroundColor = UIColor.white + title = "마일스톤" + addNavigationButton() + } + + private func addNavigationButton() { + navigationItem.rightBarButtonItem = UIBarButtonItem(customView: addMileStoneButton) + } +} + +extension MilestoneViewController: LoginInfoContainer { + func setup(loginInfo: LoginInfo) { + self.loginInfo = loginInfo + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/MilestoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/MilestoneViewController.swift deleted file mode 100644 index 3402dc85e..000000000 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/MilestoneViewController.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// MilestoneViewController.swift -// issue-tracker -// -// Created by Song on 2021/06/09. -// - -import UIKit - -class MilestoneViewController: UIViewController { - - private var loginInfo: LoginInfo? - - override func viewDidLoad() { - super.viewDidLoad() - view.backgroundColor = UIColor.yellow - title = "마일스톤" - } - -} - -extension MilestoneViewController: LoginInfoContainer { - func setup(loginInfo: LoginInfo) { - self.loginInfo = loginInfo - } -} From 54e4808a7ebe6df5bca26a74ca0e06e22324adf0 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 15 Jun 2021 17:48:12 +0900 Subject: [PATCH 20/91] =?UTF-8?q?feat=20:=20[#68]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20=EC=B6=94=EA=B0=80=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?View=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 4 ++ .../Controller/MilestoneViewController.swift | 47 ++++++++++++++++++- .../View/MileStoneTableViewCell.swift | 29 ++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 9e2467ba5..4c08d2b1c 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -37,6 +37,7 @@ E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; + FAB2C36A26789D41009F879C /* MileStoneTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB2C36926789D40009F879C /* MileStoneTableViewCell.swift */; }; FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC6D88A2671D5A100A9E5F9 /* GithubAuthorizationManager.swift */; }; FAC6D88D2671D8A100A9E5F9 /* SocialLoginManagable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC6D88C2671D8A100A9E5F9 /* SocialLoginManagable.swift */; }; FAEB30AC266F5E9700C17BE9 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAEB30AB266F5E9700C17BE9 /* Colors.swift */; }; @@ -78,6 +79,7 @@ E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; + FAB2C36926789D40009F879C /* MileStoneTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneTableViewCell.swift; sourceTree = ""; }; FAC6D88A2671D5A100A9E5F9 /* GithubAuthorizationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GithubAuthorizationManager.swift; sourceTree = ""; }; FAC6D88C2671D8A100A9E5F9 /* SocialLoginManagable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialLoginManagable.swift; sourceTree = ""; }; FAEB30AB266F5E9700C17BE9 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = ""; }; @@ -310,6 +312,7 @@ FAB2C36726789AE3009F879C /* View */ = { isa = PBXGroup; children = ( + FAB2C36926789D40009F879C /* MileStoneTableViewCell.swift */, ); path = View; sourceTree = ""; @@ -416,6 +419,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + FAB2C36A26789D41009F879C /* MileStoneTableViewCell.swift in Sources */, E426DAD126730DC50069E77D /* OAuthResponseDTO.swift in Sources */, FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */, E426DABC2670EC5E0069E77D /* LoginInfo.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift index 7e99c9fb5..47fbe180c 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift @@ -16,6 +16,16 @@ class MilestoneViewController: UIViewController { return button }() + private lazy var mileStoneTableView: UITableView = { + let tableView = UITableView() + let cellID = MileStoneTableViewCell.reuseID + tableView.register(MileStoneTableViewCell.self, forCellReuseIdentifier: cellID) + tableView.backgroundColor = Colors.background + tableView.allowsSelection = true // 테스트 + tableView.translatesAutoresizingMaskIntoConstraints = false + return tableView + }() + @objc private func addMileStoneTouched(_ sender: UIButton) { print("마일스톤 추가해줘잉") } @@ -26,12 +36,27 @@ class MilestoneViewController: UIViewController { super.viewDidLoad() view.backgroundColor = UIColor.white title = "마일스톤" - addNavigationButton() + addNavigationButton() + addTableView() + + mileStoneTableView.dataSource = self + mileStoneTableView.delegate = self } private func addNavigationButton() { navigationItem.rightBarButtonItem = UIBarButtonItem(customView: addMileStoneButton) } + + private func addTableView() { + view.addSubview(mileStoneTableView) + + NSLayoutConstraint.activate([ + mileStoneTableView.topAnchor.constraint(equalTo: view.topAnchor), + mileStoneTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + mileStoneTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + mileStoneTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } } extension MilestoneViewController: LoginInfoContainer { @@ -39,3 +64,23 @@ extension MilestoneViewController: LoginInfoContainer { self.loginInfo = loginInfo } } + + +extension MilestoneViewController: UITableViewDelegate { + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return view.frame.height * 0.336 + } +} + +extension MilestoneViewController: UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 3 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cellID = MileStoneTableViewCell.reuseID + let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? MileStoneTableViewCell ?? MileStoneTableViewCell() + + return cell + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift new file mode 100644 index 000000000..f5f055a1e --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -0,0 +1,29 @@ +// +// MileStoneTableViewCell.swift +// issue-tracker +// +// Created by jinseo park on 6/15/21. +// + +import UIKit + +class MileStoneTableViewCell: UITableViewCell { + + static var reuseID: String { + return String(describing: self) + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setViews() + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setViews() + } + + private func setViews() { + backgroundColor = Colors.mainGrape + } +} From c6c196dbf6962a52085870087bdc7ddfa0646a8c Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 15 Jun 2021 18:20:05 +0900 Subject: [PATCH 21/91] =?UTF-8?q?feat:=20[#44]=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EB=AA=A9=EB=A1=9D=20=EB=B6=88=EB=9F=AC=EC=98=A4?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 레이블 탭 진입 시 네트워크에서 레이블 목록 불러오도록 구현 --- .../issue-tracker.xcodeproj/project.pbxproj | 12 ++++++ .../Apple/AppleAuthorizationManager.swift | 3 +- .../Github/GithubAuthorizationManager.swift | 8 ++-- .../Login/Model/Github/JWT.swift | 24 +++++++++++ .../Login/Model/Github/OAuthResponseDTO.swift | 18 +------- .../issue-tracker/Login/Model/LoginInfo.swift | 2 +- .../Controller/LabelViewController.swift | 43 ++++++++++++++++--- .../Main/Label/Model/Label.swift | 39 +++++++++++++++++ .../Main/Label/View/LabelTableViewCell.swift | 8 ++-- .../issue-tracker/Network/EndPoint.swift | 1 + .../issue-tracker/Network/RequestKeys.swift | 30 +++++++++++++ .../Network/RequestManager.swift | 4 +- 12 files changed, 159 insertions(+), 33 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Login/Model/Github/JWT.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift create mode 100644 iOS/issue-tracker/issue-tracker/Network/RequestKeys.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index c26fbdf13..865a52c40 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -35,6 +35,9 @@ E43912D426788CC3003CD344 /* ImageBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D326788CC3003CD344 /* ImageBarButton.swift */; }; E43912D626789812003CD344 /* RequestManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D526789812003CD344 /* RequestManager.swift */; }; E43912D826789A83003CD344 /* EndPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D726789A83003CD344 /* EndPoint.swift */; }; + E43912DA26789E16003CD344 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D926789E16003CD344 /* Label.swift */; }; + E43912DC2678A737003CD344 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DB2678A737003CD344 /* JWT.swift */; }; + E43912DE2678A76D003CD344 /* RequestKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DD2678A76D003CD344 /* RequestKeys.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -78,6 +81,9 @@ E43912D326788CC3003CD344 /* ImageBarButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageBarButton.swift; sourceTree = ""; }; E43912D526789812003CD344 /* RequestManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestManager.swift; sourceTree = ""; }; E43912D726789A83003CD344 /* EndPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndPoint.swift; sourceTree = ""; }; + E43912D926789E16003CD344 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; + E43912DB2678A737003CD344 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = ""; }; + E43912DD2678A76D003CD344 /* RequestKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestKeys.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -290,6 +296,7 @@ E43912CF267878BF003CD344 /* HexColorConvertable.swift */, E43912CD26777310003CD344 /* HexColorConverter.swift */, E43912D1267878F4003CD344 /* HexColorCode.swift */, + E43912D926789E16003CD344 /* Label.swift */, ); path = Model; sourceTree = ""; @@ -305,6 +312,7 @@ FAC6D8922671E1A800A9E5F9 /* Github */ = { isa = PBXGroup; children = ( + E43912DB2678A737003CD344 /* JWT.swift */, E426DAD026730DC50069E77D /* OAuthResponseDTO.swift */, FAC6D88A2671D5A100A9E5F9 /* GithubAuthorizationManager.swift */, ); @@ -315,6 +323,7 @@ isa = PBXGroup; children = ( E43912D726789A83003CD344 /* EndPoint.swift */, + E43912DD2678A76D003CD344 /* RequestKeys.swift */, E43912D526789812003CD344 /* RequestManager.swift */, FAEB30B32670B76200C17BE9 /* NetworkManager.swift */, E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */, @@ -403,6 +412,7 @@ E426DABC2670EC5E0069E77D /* LoginInfo.swift in Sources */, E43912CE26777310003CD344 /* HexColorConverter.swift in Sources */, E42AD1182670886F0071B436 /* IssueTrackerTabBarController.swift in Sources */, + E43912DE2678A76D003CD344 /* RequestKeys.swift in Sources */, E42AD102266E52FB0071B436 /* LoginViewController.swift in Sources */, E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */, E43912D0267878BF003CD344 /* HexColorConvertable.swift in Sources */, @@ -427,10 +437,12 @@ FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */, E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */, E42AD11E267093320071B436 /* IssueViewController.swift in Sources */, + E43912DC2678A737003CD344 /* JWT.swift in Sources */, E426DABA2670EC2D0069E77D /* AppleAuthorizationManager.swift in Sources */, FAEB30AE266F6A7800C17BE9 /* UIImageExtension.swift in Sources */, E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */, E42AD100266E52FB0071B436 /* SceneDelegate.swift in Sources */, + E43912DA26789E16003CD344 /* Label.swift in Sources */, E426DAC92671F7760069E77D /* AlertFactory.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift index 450141932..62b7afc4b 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift @@ -42,7 +42,8 @@ extension AppleAuthorizationManager: ASAuthorizationControllerDelegate { } let userID = appleIDCredential.user - let loginInfo = LoginInfo(userID: userID, jwt: tokenInString, avatarURL: nil, name: name) + let jwt = JWT(jwt: tokenInString, tokenType: "Bearer") + let loginInfo = LoginInfo(userID: userID, jwt: jwt, avatarURL: nil, name: name) if keyChainSaver.save(loginInfo) { delegate?.didSocialLoginSuccess(with: loginInfo) diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift index e9dfbe0d0..0a8b645d3 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift @@ -51,13 +51,15 @@ extension GithubAuthorizationManager: SocialLoginManagable { guard error == nil, let successURL = callbackURL else { return } + let codeKey = Parameter.code.key() + guard let code = NSURLComponents(string: (successURL.absoluteString))? - .queryItems?.filter({$0.name == "code"}) + .queryItems?.filter({$0.name == codeKey}) .first? .value else { return } let url = EndPoint.OAuth.rawValue - let parameter = ["code": code] + let parameter = [codeKey: code] let requestManager = RequestManager(url: url, parameters: parameter) let networkmanager = NetworkManager(requestManager: requestManager) @@ -66,7 +68,7 @@ extension GithubAuthorizationManager: SocialLoginManagable { switch result { case .success(let response): let loginInfo = LoginInfo(userID: nil, - jwt: response.jwt.jwt, + jwt: response.jwt, avatarURL: response.avatarUrl, name: response.loginId) diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/JWT.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/JWT.swift new file mode 100644 index 000000000..5e6ee1918 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/JWT.swift @@ -0,0 +1,24 @@ +// +// JWT.swift +// issue-tracker +// +// Created by Song on 2021/06/15. +// + +import Foundation + +struct JWT: Codable { + let jwt: String + let tokenType: String + + enum CodingKeys: String, CodingKey { + case jwt + case tokenType + } +} + +extension JWT: CustomStringConvertible { + var description: String { + return "\(tokenType) \(jwt)" + } +} diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift index c166435ac..1b0e0cc5e 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/OAuthResponseDTO.swift @@ -7,23 +7,7 @@ import Foundation -struct JWT: Decodable { - let jwt: String - let tokenType: String - - enum CodingKeys: String, CodingKey { - case jwt - case tokenType - } -} - -extension JWT: CustomStringConvertible { - var description: String { - return "\(tokenType) \(jwt)" - } -} - -struct OAuthResponseDTO: Decodable { +struct OAuthResponseDTO: Codable { let jwt: JWT let avatarUrl: String let loginId: String diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/LoginInfo.swift b/iOS/issue-tracker/issue-tracker/Login/Model/LoginInfo.swift index 401c83dcf..044027191 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/LoginInfo.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/LoginInfo.swift @@ -9,7 +9,7 @@ import Foundation struct LoginInfo: Codable { let userID: String? - let jwt: String + let jwt: JWT let avatarURL: String? let name: String } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index da1bddac5..065389103 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -26,20 +26,25 @@ final class LabelViewController: UIViewController { return tableView }() - private var loginInfo: LoginInfo? - private let colorConverter: HexColorConvertable = HexColorConverter() - private let colors = ["#558776", "#F3F0D7", "#FFC107", "#FFD8CC", "#CEE5D0", "#231E23"] + private var networkManager: NetworkManagerOperations? + + private var loginInfo: LoginInfo? + private var labels: [Label]? override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.white title = "레이블" + addNavigationButton() addTableView() labelTableView.dataSource = self labelTableView.delegate = self + + setNetworkManager() + loadLabels() } private func addNavigationButton() { @@ -57,6 +62,29 @@ final class LabelViewController: UIViewController { ]) } + private func setNetworkManager() { + guard let loginInfo = loginInfo else { return } + let url = EndPoint.allLabels.rawValue + let headers = [Header.authorization.key(): loginInfo.jwt.description] + let requestManager = RequestManager(url: url, headers: headers) + networkManager = NetworkManager(requestManager: requestManager) + } + + private func loadLabels() { + networkManager?.get(completion: { [weak self] (result: Result) in + switch result { + case .success(let result): + let labels = result.data + self?.labels = labels + DispatchQueue.main.async { + self?.labelTableView.reloadData() + } + case .failure(let error): + print(error) + } + }) + } + @objc private func addLabelTouched(_ sender: UIButton) { } @@ -77,16 +105,19 @@ extension LabelViewController: UITableViewDelegate { extension LabelViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 6 + return labels?.count ?? 0 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cellID = LabelTableViewCell.reuseID let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? LabelTableViewCell ?? LabelTableViewCell() - let hex = HexColorCode(from: colors[indexPath.row]) + + guard let labels = labels else { return cell } + let label = labels[indexPath.row] + let hex = HexColorCode(from: label.hexColorCode) let backgroundColor = colorConverter.convertHex(hex) let titleColor = colorConverter.isColorDark(hex: hex) ? UIColor.white : UIColor.black - cell.configure(with: backgroundColor, titleColor, "졸력", "졸린 오후") + cell.configure(with: backgroundColor, titleColor, label.title, label.body) return cell } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift new file mode 100644 index 000000000..a99a381b0 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift @@ -0,0 +1,39 @@ +// +// Label.swift +// issue-tracker +// +// Created by Song on 2021/06/15. +// + +import Foundation + +struct LabelDTO: Decodable { + let data: [Label]? + let message: String? + + enum CodingKeys: String, CodingKey { + case data + case message = "msg" + } +} + +class Label: Decodable { + private(set) var id: Int + private(set) var title: String + private(set) var body: String + private(set) var hexColorCode: String + + init(id: Int, title: String, body: String, hexColorCode: String) { + self.id = id + self.title = title + self.body = body + self.hexColorCode = hexColorCode + } + + enum CodingKeys: String, CodingKey { + case id + case title = "name" + case body = "content" + case hexColorCode = "color_code" + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift index 3f4aa4c05..7d2e0e655 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift @@ -15,7 +15,7 @@ final class LabelTableViewCell: UITableViewCell { let label = UILabel() label.textColor = UIColor.systemGray2 label.numberOfLines = 1 - label.text = "No description provided" + label.text = placeholder label.translatesAutoresizingMaskIntoConstraints = false return label }() @@ -24,6 +24,8 @@ final class LabelTableViewCell: UITableViewCell { return frame.width * 0.05 }() + private let placeholder = "No description provided" + static var reuseID: String { return String(describing: self) } @@ -63,9 +65,9 @@ final class LabelTableViewCell: UITableViewCell { ]) } - func configure(with backgroundColor: UIColor,_ titleColor: UIColor, _ title: String,_ description: String?) { + func configure(with backgroundColor: UIColor,_ titleColor: UIColor, _ title: String,_ description: String) { labelView.configure(with: backgroundColor, titleColor, title) - self.labelDescription.text = description + self.labelDescription.text = description.count != 0 ? description : placeholder } } diff --git a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift index da86b70df..18435e8ea 100644 --- a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift +++ b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift @@ -9,4 +9,5 @@ import Foundation enum EndPoint: String { case OAuth = "http://3.34.122.67/api/login/ios" + case allLabels = "http://3.34.122.67/api/labels" } diff --git a/iOS/issue-tracker/issue-tracker/Network/RequestKeys.swift b/iOS/issue-tracker/issue-tracker/Network/RequestKeys.swift new file mode 100644 index 000000000..410009b44 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Network/RequestKeys.swift @@ -0,0 +1,30 @@ +// +// RequestKeys.swift +// issue-tracker +// +// Created by Song on 2021/06/15. +// + +import Foundation + +enum Parameter { + case code + + func key() -> String { + switch self { + case .code: + return "code" + } + } +} + +enum Header { + case authorization + + func key() -> String { + switch self { + case .authorization: + return "Authorization" + } + } +} diff --git a/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift b/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift index 33e104fa8..cb4394ddc 100644 --- a/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift +++ b/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift @@ -14,10 +14,10 @@ final class RequestManager { private var parameters: [String: Any]? private var headers: HTTPHeaders? - init(url: String, parameters: [String: Any]? = nil, headers: HTTPHeaders? = nil) { + init(url: String, parameters: [String: Any]? = nil, headers: [String: String]? = nil) { self.url = url self.parameters = parameters - self.headers = headers + self.headers = HTTPHeaders(headers ?? [:]) } func create(method: HTTPMethod) -> DataRequest { From 269b52ce3a0d5f3b2da9e08a8e167da1b2b60d70 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 15 Jun 2021 18:26:34 +0900 Subject: [PATCH 22/91] =?UTF-8?q?refactor:=20[#44]=20EndPoint=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EA=B5=AC=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 확장성을 고려한 Enum 타입으로 구축 --- .../Github/GithubAuthorizationManager.swift | 2 +- .../Controller/LabelViewController.swift | 2 +- .../issue-tracker/Network/EndPoint.swift | 24 ++++++++++++++++--- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift index 0a8b645d3..495ec1fdc 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift @@ -58,7 +58,7 @@ extension GithubAuthorizationManager: SocialLoginManagable { .first? .value else { return } - let url = EndPoint.OAuth.rawValue + let url = EndPoint.OAuth.fullAddress() let parameter = [codeKey: code] let requestManager = RequestManager(url: url, parameters: parameter) let networkmanager = NetworkManager(requestManager: requestManager) diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index 065389103..d6d55fa54 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -64,7 +64,7 @@ final class LabelViewController: UIViewController { private func setNetworkManager() { guard let loginInfo = loginInfo else { return } - let url = EndPoint.allLabels.rawValue + let url = EndPoint.label.fullAddress() let headers = [Header.authorization.key(): loginInfo.jwt.description] let requestManager = RequestManager(url: url, headers: headers) networkManager = NetworkManager(requestManager: requestManager) diff --git a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift index 18435e8ea..5797c7fc9 100644 --- a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift +++ b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift @@ -7,7 +7,25 @@ import Foundation -enum EndPoint: String { - case OAuth = "http://3.34.122.67/api/login/ios" - case allLabels = "http://3.34.122.67/api/labels" +enum EndPoint { + static let baseAddress = "http://3.34.122.67/api" + + case OAuth + case label + case milestone + + func fullAddress() -> String { + switch self { + case .OAuth: + return EndPoint.baseAddress + "/login/ios" + case .label: + return EndPoint.baseAddress + "/labels" + case .milestone: + return EndPoint.baseAddress + "/milestones" + } + } + + func fullAddress(with id: Int) -> String { + return fullAddress() + "\(id)" + } } From e2e1509b923e68a7a739c98f10348f835d27273e Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 15 Jun 2021 18:33:52 +0900 Subject: [PATCH 23/91] =?UTF-8?q?feat=20:[#68]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20Cell=20=EC=8A=A4=ED=83=9D=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/MilestoneViewController.swift | 1 - .../View/MileStoneTableViewCell.swift | 50 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift index 47fbe180c..648a5a129 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift @@ -65,7 +65,6 @@ extension MilestoneViewController: LoginInfoContainer { } } - extension MilestoneViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return view.frame.height * 0.336 diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index f5f055a1e..8a94262ae 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -9,6 +9,46 @@ import UIKit class MileStoneTableViewCell: UITableViewCell { + private let spacing: CGFloat = 16 + + //스택을 만들고 UIEdge = 24 + private lazy var mileStoneStackView: UIStackView = { + let superStackView = UIStackView() //커다란 SuperStack + superStackView.axis = .vertical + superStackView.distribution = .fillProportionally + superStackView.translatesAutoresizingMaskIntoConstraints = false + + let firstSubStackView = UIStackView() + firstSubStackView.axis = .horizontal + firstSubStackView.spacing = spacing * 0.5 + firstSubStackView.distribution = .fillProportionally + firstSubStackView.layoutMargins = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: spacing) + firstSubStackView.isLayoutMarginsRelativeArrangement = true + + + let titleLabel = UILabel() + titleLabel.text = "잭잭잭" + titleLabel.font = .systemFont(ofSize: 17) + let completenessLabel = UILabel() + completenessLabel.text = "100%" + completenessLabel.font = .systemFont(ofSize: 17) + + firstSubStackView.addArrangedSubview(titleLabel) + firstSubStackView.addArrangedSubview(completenessLabel) + + superStackView.addArrangedSubview(firstSubStackView) + //1 : sub스택 + // -1 Title 라벨 + // -2 몇 %인지 보이는 두개의 라벨 + //2 : 마일스톤에 대한 설명 라벨 + //3 : 완료일 라벨 + //4 : sub스택 + // -1 열린 이슈 라벨 + // -2 닫힌 이슈 라벨 + + return superStackView + }() + static var reuseID: String { return String(describing: self) } @@ -25,5 +65,15 @@ class MileStoneTableViewCell: UITableViewCell { private func setViews() { backgroundColor = Colors.mainGrape + addMileStoneStackView() + } + + private func addMileStoneStackView() { + addSubview(mileStoneStackView) + + NSLayoutConstraint.activate([ + mileStoneStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), + mileStoneStackView.topAnchor.constraint(equalTo: topAnchor, constant: spacing * 1.5) + ]) } } From 881d1ae70498e2ff5de135667b4078ee88a32ca7 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 15 Jun 2021 18:49:14 +0900 Subject: [PATCH 24/91] =?UTF-8?q?refactor:=20[#44]=20datasource=20/=20dele?= =?UTF-8?q?gate=20=EA=B0=9D=EC=B2=B4=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 8 +++ .../Label/Controller/LabelTableDelegate.swift | 21 ++++++++ .../Controller/LabelTableViewDatasource.swift | 33 +++++++++++++ .../Controller/LabelViewController.swift | 49 ++++++------------- 4 files changed, 78 insertions(+), 33 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 865a52c40..637d2b6ad 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -38,6 +38,8 @@ E43912DA26789E16003CD344 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912D926789E16003CD344 /* Label.swift */; }; E43912DC2678A737003CD344 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DB2678A737003CD344 /* JWT.swift */; }; E43912DE2678A76D003CD344 /* RequestKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DD2678A76D003CD344 /* RequestKeys.swift */; }; + E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */; }; + E43912E22678AEB3003CD344 /* LabelTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -84,6 +86,8 @@ E43912D926789E16003CD344 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; E43912DB2678A737003CD344 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = ""; }; E43912DD2678A76D003CD344 /* RequestKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestKeys.swift; sourceTree = ""; }; + E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewDatasource.swift; sourceTree = ""; }; + E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableDelegate.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -286,6 +290,8 @@ isa = PBXGroup; children = ( E42AD11F267093430071B436 /* LabelViewController.swift */, + E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */, + E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */, ); path = Controller; sourceTree = ""; @@ -420,6 +426,7 @@ E42AD124267093700071B436 /* MyAccountViewController.swift in Sources */, FAEB30AC266F5E9700C17BE9 /* Colors.swift in Sources */, E43912C726776D8F003CD344 /* LabelView.swift in Sources */, + E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */, E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E426DAC22671B1C60069E77D /* LoginKeyChainManager.swift in Sources */, @@ -438,6 +445,7 @@ E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */, E42AD11E267093320071B436 /* IssueViewController.swift in Sources */, E43912DC2678A737003CD344 /* JWT.swift in Sources */, + E43912E22678AEB3003CD344 /* LabelTableDelegate.swift in Sources */, E426DABA2670EC2D0069E77D /* AppleAuthorizationManager.swift in Sources */, FAEB30AE266F6A7800C17BE9 /* UIImageExtension.swift in Sources */, E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift new file mode 100644 index 000000000..50cbca84a --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift @@ -0,0 +1,21 @@ +// +// LabelTableDelegate.swift +// issue-tracker +// +// Created by Song on 2021/06/15. +// + +import UIKit + +final class LabelTableDelegate: NSObject, UITableViewDelegate { + + private let superViewFrame: CGRect + + init(superViewFrame: CGRect) { + self.superViewFrame = superViewFrame + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return superViewFrame.height * 0.135 + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift new file mode 100644 index 000000000..be33db80e --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift @@ -0,0 +1,33 @@ +// +// LabelTableViewDatasource.swift +// issue-tracker +// +// Created by Song on 2021/06/15. +// + +import UIKit + +final class LabelTableViewDatasource: NSObject, UITableViewDataSource { + + private var labels = [Label]() + private let colorConverter = HexColorConverter() + + func update(labels: [Label]) { + self.labels = labels + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return labels.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cellID = LabelTableViewCell.reuseID + let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? LabelTableViewCell ?? LabelTableViewCell() + let label = labels[indexPath.row] + let hex = HexColorCode(from: label.hexColorCode) + let backgroundColor = colorConverter.convertHex(hex) + let titleColor = colorConverter.isColorDark(hex: hex) ? UIColor.white : UIColor.black + cell.configure(with: backgroundColor, titleColor, label.title, label.body) + return cell + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index d6d55fa54..53c305d66 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -28,9 +28,10 @@ final class LabelViewController: UIViewController { private let colorConverter: HexColorConvertable = HexColorConverter() private var networkManager: NetworkManagerOperations? + private var labelTableDatasource: LabelTableViewDatasource? + private var labelTableDelegate: LabelTableDelegate? private var loginInfo: LoginInfo? - private var labels: [Label]? override func viewDidLoad() { super.viewDidLoad() @@ -40,8 +41,11 @@ final class LabelViewController: UIViewController { addNavigationButton() addTableView() - labelTableView.dataSource = self - labelTableView.delegate = self + labelTableDatasource = LabelTableViewDatasource() + labelTableView.dataSource = labelTableDatasource + + labelTableDelegate = LabelTableDelegate(superViewFrame: view.frame) + labelTableView.delegate = labelTableDelegate setNetworkManager() loadLabels() @@ -74,17 +78,21 @@ final class LabelViewController: UIViewController { networkManager?.get(completion: { [weak self] (result: Result) in switch result { case .success(let result): - let labels = result.data - self?.labels = labels - DispatchQueue.main.async { - self?.labelTableView.reloadData() - } + guard let labels = result.data else { return } + self?.labelTableDatasource?.update(labels: labels) + self?.reloadTableView() case .failure(let error): print(error) } }) } + private func reloadTableView() { + DispatchQueue.main.async { + self.labelTableView.reloadData() + } + } + @objc private func addLabelTouched(_ sender: UIButton) { } @@ -96,28 +104,3 @@ extension LabelViewController: LoginInfoContainer { self.loginInfo = loginInfo } } - -extension LabelViewController: UITableViewDelegate { - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return view.frame.height * 0.135 - } -} - -extension LabelViewController: UITableViewDataSource { - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return labels?.count ?? 0 - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cellID = LabelTableViewCell.reuseID - let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? LabelTableViewCell ?? LabelTableViewCell() - - guard let labels = labels else { return cell } - let label = labels[indexPath.row] - let hex = HexColorCode(from: label.hexColorCode) - let backgroundColor = colorConverter.convertHex(hex) - let titleColor = colorConverter.isColorDark(hex: hex) ? UIColor.white : UIColor.black - cell.configure(with: backgroundColor, titleColor, label.title, label.body) - return cell - } -} From 8f8f14d0609eaf01d737b65c798bcbde895ad4e5 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 15 Jun 2021 18:49:20 +0900 Subject: [PATCH 25/91] =?UTF-8?q?feat=20:[#68]=20=EC=B9=BC=EB=9D=BC=20?= =?UTF-8?q?=EC=85=8B=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MileStoneSuccess.colorset/Contents.json | 38 +++++++++++++++++++ .../issue-tracker/Common/Colors.swift | 1 + .../View/MileStoneTableViewCell.swift | 20 ++++++---- 3 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Assets.xcassets/MileStoneSuccess.colorset/Contents.json diff --git a/iOS/issue-tracker/issue-tracker/Assets.xcassets/MileStoneSuccess.colorset/Contents.json b/iOS/issue-tracker/issue-tracker/Assets.xcassets/MileStoneSuccess.colorset/Contents.json new file mode 100644 index 000000000..d3187d8b9 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Assets.xcassets/MileStoneSuccess.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.349", + "green" : "0.780", + "red" : "0.204" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.349", + "green" : "0.780", + "red" : "0.204" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/issue-tracker/issue-tracker/Common/Colors.swift b/iOS/issue-tracker/issue-tracker/Common/Colors.swift index a0133edc7..a94b18f8d 100644 --- a/iOS/issue-tracker/issue-tracker/Common/Colors.swift +++ b/iOS/issue-tracker/issue-tracker/Common/Colors.swift @@ -14,4 +14,5 @@ enum Colors { static let deleteSunnyside = UIColor(named: "DeleteSunnyside") ?? UIColor.yellow static let openBrocoli = UIColor(named: "OpenBrocoli") ?? UIColor.purple static let mainGrape = UIColor(named: "MainGrape") ?? UIColor.purple + static let mileStoneSuceess = UIColor(named: "MileStoneSuccess") ?? UIColor.green } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index 8a94262ae..90be143b3 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -18,6 +18,12 @@ class MileStoneTableViewCell: UITableViewCell { superStackView.distribution = .fillProportionally superStackView.translatesAutoresizingMaskIntoConstraints = false + + //1 : sub스택 + // -1 Title 라벨 + // -2 몇 %인지 보이는 두개의 라벨 + + let firstSubStackView = UIStackView() firstSubStackView.axis = .horizontal firstSubStackView.spacing = spacing * 0.5 @@ -27,25 +33,25 @@ class MileStoneTableViewCell: UITableViewCell { let titleLabel = UILabel() - titleLabel.text = "잭잭잭" - titleLabel.font = .systemFont(ofSize: 17) + titleLabel.text = "제목" + titleLabel.font = UIFont.boldSystemFont(ofSize: 22) + let completenessLabel = UILabel() completenessLabel.text = "100%" - completenessLabel.font = .systemFont(ofSize: 17) + completenessLabel.textColor = Colors.mileStoneSuceess + completenessLabel.font = UIFont.boldSystemFont(ofSize: 22) firstSubStackView.addArrangedSubview(titleLabel) firstSubStackView.addArrangedSubview(completenessLabel) - superStackView.addArrangedSubview(firstSubStackView) - //1 : sub스택 - // -1 Title 라벨 - // -2 몇 %인지 보이는 두개의 라벨 //2 : 마일스톤에 대한 설명 라벨 //3 : 완료일 라벨 //4 : sub스택 // -1 열린 이슈 라벨 // -2 닫힌 이슈 라벨 + superStackView.addArrangedSubview(firstSubStackView) + return superStackView }() From 0be209599804578f8332f842c8749088468557a3 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 16 Jun 2021 10:27:41 +0900 Subject: [PATCH 26/91] =?UTF-8?q?fix:=20[#44]=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=85=80=20=EC=98=A4=ED=86=A0=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=95=84=EC=9B=83=20=EB=AC=B8=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 고정 높이 지정 --- .../Main/Label/Controller/LabelTableDelegate.swift | 9 +-------- .../Main/Label/Controller/LabelViewController.swift | 2 +- .../Main/Label/View/LabelTableViewCell.swift | 6 +++--- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift index 50cbca84a..a43d56ef2 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift @@ -8,14 +8,7 @@ import UIKit final class LabelTableDelegate: NSObject, UITableViewDelegate { - - private let superViewFrame: CGRect - - init(superViewFrame: CGRect) { - self.superViewFrame = superViewFrame - } - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return superViewFrame.height * 0.135 + return 118 } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index 53c305d66..7e81cf07f 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -44,7 +44,7 @@ final class LabelViewController: UIViewController { labelTableDatasource = LabelTableViewDatasource() labelTableView.dataSource = labelTableDatasource - labelTableDelegate = LabelTableDelegate(superViewFrame: view.frame) + labelTableDelegate = LabelTableDelegate() labelTableView.delegate = labelTableDelegate setNetworkManager() diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift index 7d2e0e655..f79526e05 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift @@ -21,7 +21,7 @@ final class LabelTableViewCell: UITableViewCell { }() private lazy var spacing: CGFloat = { - return frame.width * 0.05 + return frame.height * 0.25 }() private let placeholder = "No description provided" @@ -51,7 +51,7 @@ final class LabelTableViewCell: UITableViewCell { NSLayoutConstraint.activate([ labelView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), - labelView.topAnchor.constraint(equalTo: topAnchor, constant: spacing * 1.5) + labelView.topAnchor.constraint(equalTo: topAnchor, constant: spacing * 2.2) ]) } @@ -61,7 +61,7 @@ final class LabelTableViewCell: UITableViewCell { NSLayoutConstraint.activate([ labelDescription.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), labelDescription.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -spacing), - labelDescription.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -spacing * 1.5) + labelDescription.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -spacing * 2.2) ]) } From 894deb0d73578ee33e8035257c47577c003976dd Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 16 Jun 2021 16:59:25 +0900 Subject: [PATCH 27/91] =?UTF-8?q?feat:=20[#70]=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=B6=94=EA=B0=80=20=ED=99=94=EB=A9=B4=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 4 + .../Main/Common/View/ImageBarButton.swift | 1 + .../Main/Common/View/LabelView.swift | 7 +- .../Controller/AddLabelViewController.swift | 224 ++++++++++++++++++ .../Controller/LabelViewController.swift | 5 +- 5 files changed, 237 insertions(+), 4 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 637d2b6ad..a6ae28b82 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -40,6 +40,7 @@ E43912DE2678A76D003CD344 /* RequestKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DD2678A76D003CD344 /* RequestKeys.swift */; }; E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */; }; E43912E22678AEB3003CD344 /* LabelTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */; }; + E43912E42679C0DA003CD344 /* AddLabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E32679C0DA003CD344 /* AddLabelViewController.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -88,6 +89,7 @@ E43912DD2678A76D003CD344 /* RequestKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestKeys.swift; sourceTree = ""; }; E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewDatasource.swift; sourceTree = ""; }; E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableDelegate.swift; sourceTree = ""; }; + E43912E32679C0DA003CD344 /* AddLabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddLabelViewController.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -292,6 +294,7 @@ E42AD11F267093430071B436 /* LabelViewController.swift */, E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */, E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */, + E43912E32679C0DA003CD344 /* AddLabelViewController.swift */, ); path = Controller; sourceTree = ""; @@ -444,6 +447,7 @@ FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */, E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */, E42AD11E267093320071B436 /* IssueViewController.swift in Sources */, + E43912E42679C0DA003CD344 /* AddLabelViewController.swift in Sources */, E43912DC2678A737003CD344 /* JWT.swift in Sources */, E43912E22678AEB3003CD344 /* LabelTableDelegate.swift in Sources */, E426DABA2670EC2D0069E77D /* AppleAuthorizationManager.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift index 52ed932b3..2f48b6b3b 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift @@ -22,6 +22,7 @@ final class ImageBarButton: UIButton { private func configure() { tintColor = Colors.mainGrape setTitleColor(Colors.mainGrape, for: .normal) + setTitleColor(UIColor.lightGray, for: .disabled) semanticContentAttribute = .forceRightToLeft imageEdgeInsets = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 0) } diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift index 00dadf33f..e41cb82e8 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift @@ -53,9 +53,12 @@ final class LabelView: UIView { ]) } - func configure(with backgroundColor: UIColor,_ textColor: UIColor,_ title: String) { + func configure(with backgroundColor: UIColor,_ textColor: UIColor,_ title: String?) { self.backgroundColor = backgroundColor labelTitle.textColor = textColor - labelTitle.text = title + + if let title = title { + labelTitle.text = title + } } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift new file mode 100644 index 000000000..1810a7378 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift @@ -0,0 +1,224 @@ +// +// AddLabelViewController.swift +// issue-tracker +// +// Created by Song on 2021/06/16. +// + +import UIKit + +final class AddLabelViewController: UIViewController { + + private lazy var cancelButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "chevron.backward", "취소") + button.moveImageToLeft() + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(cancelButtonTouched), for: .touchUpInside) + return button + }() + + private lazy var saveButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "", "저장") + button.isEnabled = false + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(saveButtonTouched), for: .touchUpInside) + return button + }() + + private lazy var newLabelEditStackView: UIStackView = { + let viewWidth = view.frame.width + let stackViewFrame = CGRect(x: 0, y: 0, width: viewWidth, height: singleLineHeight * 3) + let stackView = UIStackView(frame: stackViewFrame) + stackView.backgroundColor = UIColor.white + stackView.axis = .vertical + stackView.distribution = .fillEqually + stackView.translatesAutoresizingMaskIntoConstraints = false + + let categories = ["제목", "설명", "배경색"] + let contentViews: [UIView] = [titleTextfield, descriptionTextfield, backgroundLabel] + + categories.enumerated().forEach { (idx, category) in + let containerFrame = CGRect(x: 0, y: 0, width: viewWidth, height: singleLineHeight) + let container = UIView(frame: containerFrame) + + let titleLabel = UILabel() + titleLabel.text = category + titleLabel.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing), + titleLabel.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) + ]) + + let contentView = contentViews[idx] + contentView.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(contentView) + NSLayoutConstraint.activate([ + contentView.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing * 5), + contentView.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), + contentView.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) + ]) + stackView.addArrangedSubview(container) + } + guard let backgroundEditView = stackView.arrangedSubviews.last else { return stackView } + + backgroundEditView.addSubview(randomColorButton) + NSLayoutConstraint.activate([ + randomColorButton.widthAnchor.constraint(equalToConstant: singleLineHeight * 0.9), + randomColorButton.heightAnchor.constraint(equalTo: randomColorButton.safeAreaLayoutGuide.widthAnchor), + randomColorButton.trailingAnchor.constraint(equalTo: backgroundEditView.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), + randomColorButton.centerYAnchor.constraint(equalTo: backgroundEditView.safeAreaLayoutGuide.centerYAnchor) + ]) + return stackView + }() + + private lazy var titleTextfield: UITextField = { + let textField = UITextField() + textField.placeholder = "(필수 입력)" + return textField + }() + + private lazy var descriptionTextfield: UITextField = { + let textField = UITextField() + textField.placeholder = "(선택 사항)" + return textField + }() + + private lazy var backgroundLabel: UILabel = { + let label = UILabel() + label.text = "#000000" + return label + }() + + private lazy var randomColorButton: UIButton = { + let button = UIButton() + let refreshImage = UIImage(systemName: "arrow.clockwise") + button.setImage(refreshImage, for: .normal) + button.tintColor = UIColor.black + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(randomColorButtonTouched), for: .touchUpInside) + return button + }() + + private lazy var previewLabel: LabelView = { + let labelView = LabelView() + labelView.configure(with: UIColor.black, UIColor.white, "레이블") + labelView.translatesAutoresizingMaskIntoConstraints = false + return labelView + }() + + private lazy var singleLineHeight: CGFloat = { + return view.frame.height * 0.05 + }() + + private lazy var spacing: CGFloat = { + return singleLineHeight * 0.5 + }() + + private let sceneTitle = "새로운 레이블" + + override func viewDidLoad() { + super.viewDidLoad() + view.backgroundColor = Colors.background + + addTopButtons() + addEditStackView() + addLabelPreview() + } + + private func addTopButtons() { + let container = UIView() + container.translatesAutoresizingMaskIntoConstraints = false + + view.addSubview(container) + NSLayoutConstraint.activate([ + container.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + container.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + container.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: spacing), + container.heightAnchor.constraint(equalToConstant: singleLineHeight) + ]) + + container.addSubview(saveButton) + NSLayoutConstraint.activate([ + saveButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), + saveButton.widthAnchor.constraint(equalToConstant: spacing * 2), + saveButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), + saveButton.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing) + ]) + + container.addSubview(cancelButton) + NSLayoutConstraint.activate([ + cancelButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), + cancelButton.widthAnchor.constraint(equalToConstant: spacing * 2), + cancelButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), + cancelButton.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing) + ]) + + let titleLabel = UILabel() + titleLabel.text = sceneTitle + titleLabel.font = .systemFont(ofSize: 18, weight: .bold) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.centerXAnchor.constraint(equalTo: container.centerXAnchor), + titleLabel.centerYAnchor.constraint(equalTo: container.centerYAnchor) + ]) + } + + private func addEditStackView() { + view.addSubview(newLabelEditStackView) + + NSLayoutConstraint.activate([ + newLabelEditStackView.heightAnchor.constraint(equalToConstant: singleLineHeight * 3), + newLabelEditStackView.topAnchor.constraint(equalTo: saveButton.safeAreaLayoutGuide.bottomAnchor, constant: 40), + newLabelEditStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + newLabelEditStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) + ]) + addLoginStackViewDivisionLine() + } + + private func addLoginStackViewDivisionLine() { + let borderColor = Colors.border.cgColor + let borderWidth: CGFloat = 1 + let size = CGSize(width: view.frame.width - spacing, height: borderWidth) + + for i in 1...2 { + let line = CALayer() + let origin = CGPoint(x: spacing, y: singleLineHeight * CGFloat(i) - borderWidth) + line.frame = CGRect(origin: origin, size: size) + line.backgroundColor = borderColor + newLabelEditStackView.layer.addSublayer(line) + } + } + + private func addLabelPreview() { + let backgroundView = UIView() + backgroundView.backgroundColor = UIColor.systemGray5 + backgroundView.layer.cornerRadius = view.frame.width * 0.07 + backgroundView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(backgroundView) + backgroundView.addSubview(previewLabel) + NSLayoutConstraint.activate([ + backgroundView.widthAnchor.constraint(equalToConstant: view.frame.width - spacing * 2), + backgroundView.heightAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.widthAnchor, multiplier: 0.75), + backgroundView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), + backgroundView.topAnchor.constraint(equalTo: newLabelEditStackView.safeAreaLayoutGuide.bottomAnchor, constant: 24), + previewLabel.centerXAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.centerXAnchor), + previewLabel.centerYAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.centerYAnchor) + ]) + } + + @objc private func cancelButtonTouched(_ sender: UIBarButtonItem) { + + } + + @objc private func saveButtonTouched(_ sender: UIBarButtonItem) { + + } + + @objc private func randomColorButtonTouched(_ sender: UIButton) { + + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index 7e81cf07f..9cfddca8f 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -94,9 +94,10 @@ final class LabelViewController: UIViewController { } @objc private func addLabelTouched(_ sender: UIButton) { - + let addLabelViewController = AddLabelViewController() + addLabelViewController.modalPresentationStyle = .formSheet + present(addLabelViewController, animated: true, completion: nil) } - } extension LabelViewController: LoginInfoContainer { From 76a9beb20deea6f2e00b78b19d9f299986c3d409 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 16 Jun 2021 17:14:47 +0900 Subject: [PATCH 28/91] =?UTF-8?q?chore:=20[#70]=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/AddLabelViewController.swift | 75 ++++++++++--------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift index 1810a7378..440108d90 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift @@ -9,6 +9,37 @@ import UIKit final class AddLabelViewController: UIViewController { + private lazy var topMenuView: UIView = { + let container = UIView() + container.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(saveButton) + NSLayoutConstraint.activate([ + saveButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), + saveButton.widthAnchor.constraint(equalToConstant: spacing * 2), + saveButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), + saveButton.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing) + ]) + + container.addSubview(cancelButton) + NSLayoutConstraint.activate([ + cancelButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), + cancelButton.widthAnchor.constraint(equalToConstant: spacing * 2), + cancelButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), + cancelButton.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing) + ]) + + let titleLabel = UILabel() + titleLabel.text = sceneTitle + titleLabel.font = .systemFont(ofSize: 18, weight: .bold) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.centerXAnchor.constraint(equalTo: container.centerXAnchor), + titleLabel.centerYAnchor.constraint(equalTo: container.centerYAnchor) + ]) + return container + }() + private lazy var cancelButton: ImageBarButton = { let button = ImageBarButton() button.configure(with: "chevron.backward", "취소") @@ -123,47 +154,19 @@ final class AddLabelViewController: UIViewController { super.viewDidLoad() view.backgroundColor = Colors.background - addTopButtons() + addTopMenu() addEditStackView() addLabelPreview() } - private func addTopButtons() { - let container = UIView() - container.translatesAutoresizingMaskIntoConstraints = false - - view.addSubview(container) - NSLayoutConstraint.activate([ - container.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), - container.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), - container.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: spacing), - container.heightAnchor.constraint(equalToConstant: singleLineHeight) - ]) - - container.addSubview(saveButton) - NSLayoutConstraint.activate([ - saveButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), - saveButton.widthAnchor.constraint(equalToConstant: spacing * 2), - saveButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), - saveButton.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing) - ]) - - container.addSubview(cancelButton) - NSLayoutConstraint.activate([ - cancelButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), - cancelButton.widthAnchor.constraint(equalToConstant: spacing * 2), - cancelButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), - cancelButton.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing) - ]) + private func addTopMenu() { + view.addSubview(topMenuView) - let titleLabel = UILabel() - titleLabel.text = sceneTitle - titleLabel.font = .systemFont(ofSize: 18, weight: .bold) - titleLabel.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(titleLabel) NSLayoutConstraint.activate([ - titleLabel.centerXAnchor.constraint(equalTo: container.centerXAnchor), - titleLabel.centerYAnchor.constraint(equalTo: container.centerYAnchor) + topMenuView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + topMenuView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + topMenuView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: spacing), + topMenuView.heightAnchor.constraint(equalToConstant: singleLineHeight) ]) } @@ -172,7 +175,7 @@ final class AddLabelViewController: UIViewController { NSLayoutConstraint.activate([ newLabelEditStackView.heightAnchor.constraint(equalToConstant: singleLineHeight * 3), - newLabelEditStackView.topAnchor.constraint(equalTo: saveButton.safeAreaLayoutGuide.bottomAnchor, constant: 40), + newLabelEditStackView.topAnchor.constraint(equalTo: topMenuView.safeAreaLayoutGuide.bottomAnchor, constant: 40), newLabelEditStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), newLabelEditStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) ]) From c9f9ec09528991f0b7f7dae8a27769ed6d902ca9 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 16 Jun 2021 17:26:18 +0900 Subject: [PATCH 29/91] =?UTF-8?q?feat:=20[#70]=20=EB=9E=9C=EB=8D=A4=20?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EB=B8=94=20=EC=BB=AC=EB=9F=AC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 레이블 컬러 버튼 터치 시 레이블 컬러 변경 --- .../Controller/AddLabelViewController.swift | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift index 440108d90..1ffdb0d8c 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift @@ -149,6 +149,7 @@ final class AddLabelViewController: UIViewController { }() private let sceneTitle = "새로운 레이블" + private let colorConverter = HexColorConverter() override func viewDidLoad() { super.viewDidLoad() @@ -222,6 +223,27 @@ final class AddLabelViewController: UIViewController { } @objc private func randomColorButtonTouched(_ sender: UIButton) { + let hexColor = randomColor() + backgroundLabel.text = hexColor + changePreviewLabel(with: hexColor) + } + + private func randomColor() -> String { + let colorRange = 0...255 + let randomRed = Int.random(in: colorRange) + let randomGreen = Int.random(in: colorRange) + let randomBlue = Int.random(in: colorRange) + let hexRed = String(randomRed, radix: 16) + let hexGreen = String(randomGreen, radix: 16) + let hexBlue = String(randomBlue, radix: 16) + return "#\(hexRed)\(hexGreen)\(hexBlue)" + } + + private func changePreviewLabel(with hexColorString: String) { + let hex = HexColorCode(from: hexColorString) + let backgroundColor = colorConverter.convertHex(hex) + let titleColor = colorConverter.isColorDark(hex: hex) ? UIColor.white : UIColor.black + previewLabel.configure(with: backgroundColor, titleColor, nil) } } From 573b5a2f57615e821b2f0544e7dcedc1c31dbf34 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Wed, 16 Jun 2021 17:55:51 +0900 Subject: [PATCH 30/91] =?UTF-8?q?feat=20[#68]=20=EC=99=84=EB=A3=8C?= =?UTF-8?q?=EC=9D=BC=EA=B9=8C=EC=A7=80=20=EC=8A=A4=ED=83=9D=EB=B7=B0?= =?UTF-8?q?=EB=A1=9C=20=EC=B6=94=EA=B0=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Description.colorset/Contents.json | 38 +++++ .../issue-tracker/Common/Colors.swift | 2 + .../Github/GithubAuthorizationManager.swift | 2 +- .../View/MileStoneTableViewCell.swift | 161 +++++++++++++----- 4 files changed, 163 insertions(+), 40 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Assets.xcassets/Description.colorset/Contents.json diff --git a/iOS/issue-tracker/issue-tracker/Assets.xcassets/Description.colorset/Contents.json b/iOS/issue-tracker/issue-tracker/Assets.xcassets/Description.colorset/Contents.json new file mode 100644 index 000000000..7fec4023b --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Assets.xcassets/Description.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.576", + "green" : "0.557", + "red" : "0.557" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.576", + "green" : "0.557", + "red" : "0.557" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/issue-tracker/issue-tracker/Common/Colors.swift b/iOS/issue-tracker/issue-tracker/Common/Colors.swift index a94b18f8d..b0d0b5f94 100644 --- a/iOS/issue-tracker/issue-tracker/Common/Colors.swift +++ b/iOS/issue-tracker/issue-tracker/Common/Colors.swift @@ -15,4 +15,6 @@ enum Colors { static let openBrocoli = UIColor(named: "OpenBrocoli") ?? UIColor.purple static let mainGrape = UIColor(named: "MainGrape") ?? UIColor.purple static let mileStoneSuceess = UIColor(named: "MileStoneSuccess") ?? UIColor.green + static let description = UIColor(named: "Description") ?? UIColor.systemGray2 + } diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift index 9253fed74..f8d90f8c0 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift @@ -55,7 +55,7 @@ extension GithubAuthorizationManager: SocialLoginManagable { .queryItems?.filter({$0.name == "code"}) .first? .value else { return } - + let networkmanager = NetworkManager() networkmanager.setInfoGithub(with: code) { [weak self] (result: Result) in diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index 90be143b3..124e61b78 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -8,51 +8,82 @@ import UIKit class MileStoneTableViewCell: UITableViewCell { - + private let spacing: CGFloat = 16 +// +// mileStoneStackView스택을 만들고 +// 1 : sub스택 +// -1 Title 라벨 +// -2 몇 %인지 보이는 두개의 라벨 +// 2 : 마일스톤에 대한 설명 라벨 +// 3 : 데이트 라벨 +// 4 : sub스택 +// -1 열린 이슈 라벨 +// -2 닫힌 이슈 라벨 - //스택을 만들고 UIEdge = 24 private lazy var mileStoneStackView: UIStackView = { let superStackView = UIStackView() //커다란 SuperStack superStackView.axis = .vertical superStackView.distribution = .fillProportionally superStackView.translatesAutoresizingMaskIntoConstraints = false + superStackView.spacing = 1 + return superStackView + }() + + private lazy var firstSubStackView: UIStackView = { + let stackView = UIStackView() + stackView.axis = .horizontal + stackView.distribution = .fill + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + + private lazy var secondSubStackView: UIStackView = { + let stackView = UIStackView() + stackView.axis = .horizontal + stackView.distribution = .fillProportionally + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.text = "제목" + label.font = UIFont.boldSystemFont(ofSize: 22) + return label + }() + + private lazy var completenessLabel: UILabel = { + let label = UILabel() + label.text = "100%" + label.textColor = Colors.mileStoneSuceess + label.font = UIFont.boldSystemFont(ofSize: 22) + return label + }() + + private lazy var descriptionLabel: UILabel = { + let label = UILabel() + label.textColor = Colors.description + label.text = "마일스톤에 대한 설명(한 줄만 보여짐, 생략 가능)" + label.font = .systemFont(ofSize: 17) + return label + }() + + private lazy var dateLabel: UILabel = { + let label = UILabel() + var dateText = "완료일(생략가능)" + let attributedString = NSMutableAttributedString(string: "") + let imageAttachment = NSTextAttachment() + imageAttachment.image = UIImage(systemName: "calendar") + + let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 18), NSAttributedString.Key.foregroundColor : Colors.description] + let dateString = NSMutableAttributedString(string:dateText, attributes:attrs) - //1 : sub스택 - // -1 Title 라벨 - // -2 몇 %인지 보이는 두개의 라벨 - - - let firstSubStackView = UIStackView() - firstSubStackView.axis = .horizontal - firstSubStackView.spacing = spacing * 0.5 - firstSubStackView.distribution = .fillProportionally - firstSubStackView.layoutMargins = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: spacing) - firstSubStackView.isLayoutMarginsRelativeArrangement = true - - - let titleLabel = UILabel() - titleLabel.text = "제목" - titleLabel.font = UIFont.boldSystemFont(ofSize: 22) - - let completenessLabel = UILabel() - completenessLabel.text = "100%" - completenessLabel.textColor = Colors.mileStoneSuceess - completenessLabel.font = UIFont.boldSystemFont(ofSize: 22) - - firstSubStackView.addArrangedSubview(titleLabel) - firstSubStackView.addArrangedSubview(completenessLabel) - - //2 : 마일스톤에 대한 설명 라벨 - //3 : 완료일 라벨 - //4 : sub스택 - // -1 열린 이슈 라벨 - // -2 닫힌 이슈 라벨 - - superStackView.addArrangedSubview(firstSubStackView) - - return superStackView + attributedString.append(NSAttributedString(attachment: imageAttachment)) + attributedString.append(dateString) + label.attributedText = attributedString + return label }() static var reuseID: String { @@ -68,7 +99,7 @@ class MileStoneTableViewCell: UITableViewCell { super.init(style: style, reuseIdentifier: reuseIdentifier) setViews() } - + private func setViews() { backgroundColor = Colors.mainGrape addMileStoneStackView() @@ -76,10 +107,62 @@ class MileStoneTableViewCell: UITableViewCell { private func addMileStoneStackView() { addSubview(mileStoneStackView) + NSLayoutConstraint.activate([ + mileStoneStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16), + mileStoneStackView.topAnchor.constraint(equalTo: topAnchor, constant: 24), + mileStoneStackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -24), + mileStoneStackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16) + ]) + + //MARK: 1 : sub스택 + // -1 Title 라벨 + // -2 몇 %인지 보이는 두개의 라벨 + mileStoneStackView.addArrangedSubview(firstSubStackView) NSLayoutConstraint.activate([ - mileStoneStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), - mileStoneStackView.topAnchor.constraint(equalTo: topAnchor, constant: spacing * 1.5) + firstSubStackView.leadingAnchor.constraint(equalTo: mileStoneStackView.leadingAnchor), + firstSubStackView.trailingAnchor.constraint(equalTo: mileStoneStackView.trailingAnchor) ]) + + firstSubStackView + .addArrangedSubview(titleLabel) + firstSubStackView + .addArrangedSubview(completenessLabel) + + //MARK: 2 : 마일스톤에 대한 설명 라벨 + mileStoneStackView.addArrangedSubview(descriptionLabel) + + //MARK: 3 : 완료일 스택 or Label with Img + mileStoneStackView.addArrangedSubview(dateLabel) + } } + +/* + + let firstSubStackView = UIStackView() + firstSubStackView.axis = .horizontal + firstSubStackView.spacing = spacing * 0.5 + firstSubStackView.distribution = .fill + // firstSubStackView.layoutMargins = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: spacing) + firstSubStackView.isLayoutMarginsRelativeArrangement = true + + + let titleLabel = UILabel() + titleLabel.text = "제목" + titleLabel.font = UIFont.boldSystemFont(ofSize: 22) + // titleLabel.leadingAnchor.constraint(equalTo: firstSubStackView.leadingAnchor, constant: 16).isActive = true + + // titleLabel.layoutMargins = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 0) + + let completenessLabel = UILabel() + completenessLabel.text = "100%" + completenessLabel.textColor = Colors.mileStoneSuceess + completenessLabel.font = UIFont.boldSystemFont(ofSize: 22) + // completenessLabel.trailingAnchor.constraint(equalTo: firstSubStackView.trailingAnchor, constant: 16).isActive = true + // completenessLabel.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 16) + + firstSubStackView.addArrangedSubview(titleLabel) + firstSubStackView.addArrangedSubview(completenessLabel) + // superStackView.addArrangedSubview(firstSubStackView) + */ From cc88bf4527782688288c6d73331f968340e81ab7 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 16 Jun 2021 21:05:49 +0900 Subject: [PATCH 31/91] =?UTF-8?q?feat:=20[#70]=20=EC=83=88=20=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EB=B8=94=20=EC=84=9C=EB=B2=84=20POST?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Save 버튼 터치 시 새로 작성한 레이블을 서버에 저장 - label table 새로 로드 --- .../issue-tracker.xcodeproj/project.pbxproj | 4 ++ .../Controller/AddLabelViewController.swift | 52 ++++++++++++++++++- .../Controller/LabelViewController.swift | 13 ++++- .../Main/Label/Model/NewLabelDTO.swift | 20 +++++++ .../Network/NetworkManager.swift | 12 ++++- .../Network/RequestManager.swift | 14 ++++- 6 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Model/NewLabelDTO.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index a6ae28b82..083beecee 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -41,6 +41,7 @@ E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */; }; E43912E22678AEB3003CD344 /* LabelTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */; }; E43912E42679C0DA003CD344 /* AddLabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E32679C0DA003CD344 /* AddLabelViewController.swift */; }; + E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -90,6 +91,7 @@ E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewDatasource.swift; sourceTree = ""; }; E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableDelegate.swift; sourceTree = ""; }; E43912E32679C0DA003CD344 /* AddLabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddLabelViewController.swift; sourceTree = ""; }; + E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewLabelDTO.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -306,6 +308,7 @@ E43912CD26777310003CD344 /* HexColorConverter.swift */, E43912D1267878F4003CD344 /* HexColorCode.swift */, E43912D926789E16003CD344 /* Label.swift */, + E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */, ); path = Model; sourceTree = ""; @@ -417,6 +420,7 @@ buildActionMask = 2147483647; files = ( E426DAD126730DC50069E77D /* OAuthResponseDTO.swift in Sources */, + E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */, FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */, E426DABC2670EC5E0069E77D /* LoginInfo.swift in Sources */, E43912CE26777310003CD344 /* HexColorConverter.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift index 1ffdb0d8c..9feeed1b1 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift @@ -148,8 +148,11 @@ final class AddLabelViewController: UIViewController { return singleLineHeight * 0.5 }() + private var loginInfo: LoginInfo? private let sceneTitle = "새로운 레이블" - private let colorConverter = HexColorConverter() + private let colorConverter: HexColorConvertable = HexColorConverter() + private var networkManager: NetworkManagerOperations? + private var dismissOperation: (() -> Void)? override func viewDidLoad() { super.viewDidLoad() @@ -158,6 +161,8 @@ final class AddLabelViewController: UIViewController { addTopMenu() addEditStackView() addLabelPreview() + + titleTextfield.delegate = self } private func addTopMenu() { @@ -214,12 +219,31 @@ final class AddLabelViewController: UIViewController { ]) } + func setUpDismissOperation(_ operation: @escaping () -> Void) { + self.dismissOperation = operation + } + @objc private func cancelButtonTouched(_ sender: UIBarButtonItem) { - + dismiss(animated: true, completion: nil) } @objc private func saveButtonTouched(_ sender: UIBarButtonItem) { + guard let labelTitle = titleTextfield.text, let colorCode = backgroundLabel.text else { return } + let newLabel = NewLabelDTO(name: labelTitle, + content: descriptionTextfield.text ?? "", + colorCode: colorCode) + + postNewLabel(newLabel) + } + + private func postNewLabel(_ newLabel: NewLabelDTO) { + networkManager?.post(requestBody: newLabel, completion: { [weak self] in + self?.dismiss(animated: true, completion: { + guard let dismissOperation = self?.dismissOperation else { return } + dismissOperation() + }) + }) } @objc private func randomColorButtonTouched(_ sender: UIButton) { @@ -247,3 +271,27 @@ final class AddLabelViewController: UIViewController { previewLabel.configure(with: backgroundColor, titleColor, nil) } } + +extension AddLabelViewController: LoginInfoContainer { + func setup(loginInfo: LoginInfo) { + self.loginInfo = loginInfo + setNetworkManager() + } + + private func setNetworkManager() { + guard let loginInfo = loginInfo else { return } + let url = EndPoint.label.fullAddress() + let headers = [Header.authorization.key(): loginInfo.jwt.description] + let requestManager = RequestManager(url: url, parameters: nil, headers: headers) + networkManager = NetworkManager(requestManager: requestManager) + } +} + +extension AddLabelViewController: UITextFieldDelegate { + func textFieldDidChangeSelection(_ textField: UITextField) { + guard let text = textField.text else { return } + DispatchQueue.main.async { + self.saveButton.isEnabled = text.count > 0 + } + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index 9cfddca8f..a51889a5c 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -48,7 +48,11 @@ final class LabelViewController: UIViewController { labelTableView.delegate = labelTableDelegate setNetworkManager() - loadLabels() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + loadData() } private func addNavigationButton() { @@ -74,7 +78,7 @@ final class LabelViewController: UIViewController { networkManager = NetworkManager(requestManager: requestManager) } - private func loadLabels() { + func loadData() { networkManager?.get(completion: { [weak self] (result: Result) in switch result { case .success(let result): @@ -94,8 +98,13 @@ final class LabelViewController: UIViewController { } @objc private func addLabelTouched(_ sender: UIButton) { + guard let loginInfo = loginInfo else { return } let addLabelViewController = AddLabelViewController() + addLabelViewController.setup(loginInfo: loginInfo) addLabelViewController.modalPresentationStyle = .formSheet + addLabelViewController.setUpDismissOperation { [weak self] in + self?.loadData() + } present(addLabelViewController, animated: true, completion: nil) } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Model/NewLabelDTO.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Model/NewLabelDTO.swift new file mode 100644 index 000000000..4d1b84881 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Model/NewLabelDTO.swift @@ -0,0 +1,20 @@ +// +// NewLabelDTO.swift +// issue-tracker +// +// Created by Song on 2021/06/16. +// + +import Foundation + +struct NewLabelDTO: Encodable { + let name: String + let content: String + let colorCode: String + + enum CodingKeys: String, CodingKey { + case name + case content + case colorCode = "color_code" + } +} diff --git a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift index fb08b9c83..6ebc3a838 100644 --- a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift +++ b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift @@ -10,6 +10,7 @@ import Alamofire protocol NetworkManagerOperations { func get(completion: @escaping (Result) -> Void) + func post(requestBody: T, completion: @escaping () -> Void) } final class NetworkManager: NetworkManagerOperations { @@ -21,7 +22,6 @@ final class NetworkManager: NetworkManagerOperations { } func get(completion: @escaping (Result) -> Void) { - let request = requestManager.create(method: .get) request.responseDecodable(of: T.self) { response in @@ -33,4 +33,14 @@ final class NetworkManager: NetworkManagerOperations { } } } + + func post(requestBody: T, completion: @escaping () -> Void) { + let request = requestManager.create(method: .post, encodableParameters: requestBody) + + request.response { data in + guard let statusCode = data.response?.statusCode else { return } + completion() + print(statusCode) + } + } } diff --git a/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift b/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift index cb4394ddc..828e40276 100644 --- a/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift +++ b/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift @@ -20,10 +20,20 @@ final class RequestManager { self.headers = HTTPHeaders(headers ?? [:]) } - func create(method: HTTPMethod) -> DataRequest { + func create(method: HTTPMethod, parameters: [String: Any]? = nil) -> DataRequest { + let params = parameters != nil ? parameters : self.parameters + + return AF.request(self.url, + method: method, + parameters: params, + headers: self.headers) + } + + func create(method: HTTPMethod, encodableParameters: T) -> DataRequest { return AF.request(self.url, method: method, - parameters: self.parameters, + parameters: encodableParameters, + encoder: JSONParameterEncoder(), headers: self.headers) } From ad10c4855a009ebe68ef98fa87accbe243313ad1 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 16 Jun 2021 21:31:39 +0900 Subject: [PATCH 32/91] =?UTF-8?q?feat:=20[#74:]=20=EB=84=A4=ED=8A=B8?= =?UTF-8?q?=EC=9B=8C=ED=81=AC=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 네트워크 에러 타입 생성 - 네트워크 에러 발생 시 alert 띄우도록 개선 --- .../issue-tracker.xcodeproj/project.pbxproj | 4 ++ .../Github/GithubAuthorizationManager.swift | 2 +- .../Controller/AddLabelViewController.swift | 14 ++++++- .../Controller/LabelViewController.swift | 11 ++++- .../issue-tracker/Network/NetworkError.swift | 33 +++++++++++++++ .../Network/NetworkManager.swift | 40 ++++++++++++++----- 6 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Network/NetworkError.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 083beecee..42aef00d3 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -42,6 +42,7 @@ E43912E22678AEB3003CD344 /* LabelTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */; }; E43912E42679C0DA003CD344 /* AddLabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E32679C0DA003CD344 /* AddLabelViewController.swift */; }; E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */; }; + E43912EA267A2351003CD344 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E9267A2351003CD344 /* NetworkError.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -92,6 +93,7 @@ E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableDelegate.swift; sourceTree = ""; }; E43912E32679C0DA003CD344 /* AddLabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddLabelViewController.swift; sourceTree = ""; }; E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewLabelDTO.swift; sourceTree = ""; }; + E43912E9267A2351003CD344 /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -336,6 +338,7 @@ children = ( E43912D726789A83003CD344 /* EndPoint.swift */, E43912DD2678A76D003CD344 /* RequestKeys.swift */, + E43912E9267A2351003CD344 /* NetworkError.swift */, E43912D526789812003CD344 /* RequestManager.swift */, FAEB30B32670B76200C17BE9 /* NetworkManager.swift */, E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */, @@ -434,6 +437,7 @@ FAEB30AC266F5E9700C17BE9 /* Colors.swift in Sources */, E43912C726776D8F003CD344 /* LabelView.swift in Sources */, E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */, + E43912EA267A2351003CD344 /* NetworkError.swift in Sources */, E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E426DAC22671B1C60069E77D /* LoginKeyChainManager.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift index 495ec1fdc..6494c009a 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift @@ -63,7 +63,7 @@ extension GithubAuthorizationManager: SocialLoginManagable { let requestManager = RequestManager(url: url, parameters: parameter) let networkmanager = NetworkManager(requestManager: requestManager) - networkmanager.get { [weak self] (result: Result) in + networkmanager.get { [weak self] (result: Result) in guard let self = self else { return } switch result { case .success(let response): diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift index 9feeed1b1..386140d1c 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift @@ -238,7 +238,12 @@ final class AddLabelViewController: UIViewController { } private func postNewLabel(_ newLabel: NewLabelDTO) { - networkManager?.post(requestBody: newLabel, completion: { [weak self] in + networkManager?.post(requestBody: newLabel, completion: { [weak self] error in + guard error != nil else { + self?.presentAlert(with: error!.description) + return + } + self?.dismiss(animated: true, completion: { guard let dismissOperation = self?.dismissOperation else { return } dismissOperation() @@ -246,6 +251,13 @@ final class AddLabelViewController: UIViewController { }) } + private func presentAlert(with errorMessage: String) { + DispatchQueue.main.async { + let alert = AlertFactory.create(body: errorMessage) + self.present(alert, animated: true, completion: nil) + } + } + @objc private func randomColorButtonTouched(_ sender: UIButton) { let hexColor = randomColor() backgroundLabel.text = hexColor diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index a51889a5c..ee274c99a 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -79,14 +79,14 @@ final class LabelViewController: UIViewController { } func loadData() { - networkManager?.get(completion: { [weak self] (result: Result) in + networkManager?.get(completion: { [weak self] (result: Result) in switch result { case .success(let result): guard let labels = result.data else { return } self?.labelTableDatasource?.update(labels: labels) self?.reloadTableView() case .failure(let error): - print(error) + self?.presentAlert(with: error.description) } }) } @@ -97,6 +97,13 @@ final class LabelViewController: UIViewController { } } + private func presentAlert(with errorMessage: String) { + DispatchQueue.main.async { + let alert = AlertFactory.create(body: errorMessage) + self.present(alert, animated: true, completion: nil) + } + } + @objc private func addLabelTouched(_ sender: UIButton) { guard let loginInfo = loginInfo else { return } let addLabelViewController = AddLabelViewController() diff --git a/iOS/issue-tracker/issue-tracker/Network/NetworkError.swift b/iOS/issue-tracker/issue-tracker/Network/NetworkError.swift new file mode 100644 index 000000000..7efe8b0a6 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Network/NetworkError.swift @@ -0,0 +1,33 @@ +// +// NetworkError.swift +// issue-tracker +// +// Created by Song on 2021/06/16. +// + +import Foundation + +enum NetworkError: Error { + case internet + case noResult + case notAllowed + case server + case unknown +} + +extension NetworkError: CustomStringConvertible { + var description: String { + switch self { + case .internet: + return "인터넷 연결을 확인해주세요 :(" + case .noResult: + return "검색 결과를 찾을 수 없습니다 :(" + case .notAllowed: + return "잘못된 접근입니다 :(" + case .server: + return "서버 상태가 불안정합니다 :(" + case .unknown: + return "알 수 없는 문제가 발생했습니다 :(" + } + } +} diff --git a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift index 6ebc3a838..ba1f69dda 100644 --- a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift +++ b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift @@ -9,8 +9,8 @@ import Foundation import Alamofire protocol NetworkManagerOperations { - func get(completion: @escaping (Result) -> Void) - func post(requestBody: T, completion: @escaping () -> Void) + func get(completion: @escaping (Result) -> Void) + func post(requestBody: T, completion: @escaping (NetworkError?) -> Void) } final class NetworkManager: NetworkManagerOperations { @@ -21,26 +21,44 @@ final class NetworkManager: NetworkManagerOperations { self.requestManager = requestManager } - func get(completion: @escaping (Result) -> Void) { + func get(completion: @escaping (Result) -> Void) { let request = requestManager.create(method: .get) - request.responseDecodable(of: T.self) { response in + request.responseDecodable(of: T.self) { [weak self] response in switch response.result { case .success(let data): completion(.success(data)) - case .failure(let error): - print(error.localizedDescription) + case .failure(_): + let statusCode = response.response?.statusCode + let error = self?.networkError(for: statusCode) ?? NetworkError.unknown + completion(.failure(error)) } } } - func post(requestBody: T, completion: @escaping () -> Void) { + func post(requestBody: T, completion: @escaping (NetworkError?) -> Void) { let request = requestManager.create(method: .post, encodableParameters: requestBody) - request.response { data in - guard let statusCode = data.response?.statusCode else { return } - completion() - print(statusCode) + request.response { [weak self] response in + let statusCode = response.response?.statusCode + completion(self?.networkError(for: statusCode)) + } + } + + private func networkError(for statusCode: Int?) -> NetworkError? { + guard let statusCode = statusCode else { return NetworkError.internet } + + switch statusCode { + case 200..<300: + return nil + case 300..<400: + return NetworkError.noResult + case 400..<500: + return NetworkError.notAllowed + case 500...: + return NetworkError.server + default: + return NetworkError.unknown } } } From b085f4ea8dfcd350ad6c7cbf9230c42e8fbb7944 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Wed, 16 Jun 2021 22:36:08 +0900 Subject: [PATCH 33/91] =?UTF-8?q?feat[#68]=20=EB=A7=88=EC=9D=BC=EC=8A=A4?= =?UTF-8?q?=ED=86=A4UILabelView=20=EC=A0=9C=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 12 +++ .../MileStoneLabelView.swift | 81 +++++++++++++++++++ .../View/MileStoneTableViewCell.swift | 71 ++++++++-------- 3 files changed, 132 insertions(+), 32 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 4c08d2b1c..c4eaba537 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -38,6 +38,7 @@ E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; FAB2C36A26789D41009F879C /* MileStoneTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB2C36926789D40009F879C /* MileStoneTableViewCell.swift */; }; + FAB2C36C2679F6CC009F879C /* MileStoneLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB2C36B2679F6CC009F879C /* MileStoneLabelView.swift */; }; FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC6D88A2671D5A100A9E5F9 /* GithubAuthorizationManager.swift */; }; FAC6D88D2671D8A100A9E5F9 /* SocialLoginManagable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC6D88C2671D8A100A9E5F9 /* SocialLoginManagable.swift */; }; FAEB30AC266F5E9700C17BE9 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAEB30AB266F5E9700C17BE9 /* Colors.swift */; }; @@ -80,6 +81,7 @@ E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; FAB2C36926789D40009F879C /* MileStoneTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneTableViewCell.swift; sourceTree = ""; }; + FAB2C36B2679F6CC009F879C /* MileStoneLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneLabelView.swift; sourceTree = ""; }; FAC6D88A2671D5A100A9E5F9 /* GithubAuthorizationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GithubAuthorizationManager.swift; sourceTree = ""; }; FAC6D88C2671D8A100A9E5F9 /* SocialLoginManagable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialLoginManagable.swift; sourceTree = ""; }; FAEB30AB266F5E9700C17BE9 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = ""; }; @@ -262,6 +264,7 @@ E43912C926776DA0003CD344 /* View */ = { isa = PBXGroup; children = ( + FAB2C36D2679FB74009F879C /* MileStoneLabelView */, E43912D326788CC3003CD344 /* ImageBarButton.swift */, E43912C626776D8F003CD344 /* LabelView.swift */, ); @@ -325,6 +328,14 @@ path = Controller; sourceTree = ""; }; + FAB2C36D2679FB74009F879C /* MileStoneLabelView */ = { + isa = PBXGroup; + children = ( + FAB2C36B2679F6CC009F879C /* MileStoneLabelView.swift */, + ); + path = MileStoneLabelView; + sourceTree = ""; + }; FAC6D8922671E1A800A9E5F9 /* Github */ = { isa = PBXGroup; children = ( @@ -437,6 +448,7 @@ E426DAC22671B1C60069E77D /* LoginKeyChainManager.swift in Sources */, E43912D426788CC3003CD344 /* ImageBarButton.swift in Sources */, E43912D2267878F4003CD344 /* HexColorCode.swift in Sources */, + FAB2C36C2679F6CC009F879C /* MileStoneLabelView.swift in Sources */, E426DAC72671F6A00069E77D /* LoginError.swift in Sources */, E426DAC42671D95D0069E77D /* LoginService.swift in Sources */, E426DACB267206D10069E77D /* LoginInfoContainer.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift new file mode 100644 index 000000000..ab0c2165a --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift @@ -0,0 +1,81 @@ +// +// mileStoneLabelView.swift +// issue-tracker +// +// Created by jinseo park on 6/16/21. +// + +import UIKit + +final class MileStoneLabelView: UIView { + + var chooseNum: Int? + let texts = ["열린 이슈","닫힌 이슈"] + let fontColors = [UIColor.blue, UIColor.purple] + let backgroundColors = [UIColor.red, UIColor.green] + let systemImgName = ["exclamationmark.circle","archivebox"] + var issueCount = 0 + + private lazy var labelTitle: UILabel = { + let label = UILabel() + + let attributedString = NSMutableAttributedString(string: "") + let imageAttachment = NSTextAttachment() + imageAttachment.image = UIImage(systemName: systemImgName[chooseNum!]) + + let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : fontColors[chooseNum!]] + let dateString = NSMutableAttributedString(string:texts[chooseNum!]+" \(issueCount)개", attributes:attrs) + + attributedString.append(NSAttributedString(attachment: imageAttachment)) + attributedString.append(dateString) + label.attributedText = attributedString + return label + }() + + private let spacing: CGFloat = 15 + + private lazy var labelHeight: CGFloat = { + return spacing * 2 + }() + + required init?(coder: NSCoder) { + super.init(coder: coder) + configure() + } + + override init(frame: CGRect) { + super.init(frame: frame) + configure() + } + + required init(chooseNum: Int) { + self.chooseNum = chooseNum + super.init(frame: .zero) + configure() + } + + private func configure() { + + layer.cornerRadius = labelHeight * 0.5 + translatesAutoresizingMaskIntoConstraints = false + + addLabelTitle() + } + + private func addLabelTitle() { + + addSubview(labelTitle) + + NSLayoutConstraint.activate([ + labelTitle.centerXAnchor.constraint(equalTo: centerXAnchor), + labelTitle.centerYAnchor.constraint(equalTo: centerYAnchor), + widthAnchor.constraint(equalTo: labelTitle.widthAnchor, constant: spacing), + heightAnchor.constraint(equalToConstant: labelHeight) + ]) + } + + func updateIssueCount(_ issueCount: Int) { + self.issueCount = issueCount + } + +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index 124e61b78..33700a7e9 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -41,7 +41,7 @@ class MileStoneTableViewCell: UITableViewCell { private lazy var secondSubStackView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal - stackView.distribution = .fillProportionally + stackView.distribution = .fillEqually stackView.translatesAutoresizingMaskIntoConstraints = false return stackView }() @@ -64,7 +64,7 @@ class MileStoneTableViewCell: UITableViewCell { private lazy var descriptionLabel: UILabel = { let label = UILabel() label.textColor = Colors.description - label.text = "마일스톤에 대한 설명(한 줄만 보여짐, 생략 가능)" + label.text = "마일스톤에 대한 설명(한 줄만 보여짐, 생략 가능)" label.font = .systemFont(ofSize: 17) return label }() @@ -72,7 +72,6 @@ class MileStoneTableViewCell: UITableViewCell { private lazy var dateLabel: UILabel = { let label = UILabel() var dateText = "완료일(생략가능)" - let attributedString = NSMutableAttributedString(string: "") let imageAttachment = NSTextAttachment() imageAttachment.image = UIImage(systemName: "calendar") @@ -86,6 +85,17 @@ class MileStoneTableViewCell: UITableViewCell { return label }() + private lazy var openMileStoneLabelView: MileStoneLabelView = { + let mileStoneLabelView = MileStoneLabelView(chooseNum: 0) + return mileStoneLabelView + }() + + private lazy var closedMileStoneLabelView: MileStoneLabelView = { + let mileStoneLabelView = MileStoneLabelView(chooseNum: 1) + + return mileStoneLabelView + }() + static var reuseID: String { return String(describing: self) } @@ -106,6 +116,7 @@ class MileStoneTableViewCell: UITableViewCell { } private func addMileStoneStackView() { + addSubview(mileStoneStackView) NSLayoutConstraint.activate([ mileStoneStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16), @@ -117,6 +128,9 @@ class MileStoneTableViewCell: UITableViewCell { //MARK: 1 : sub스택 // -1 Title 라벨 // -2 몇 %인지 보이는 두개의 라벨 + + //titleLabel, titleLabel 자체에 너비를 비율을 맞추어놓고 설정을 해주기. + //firstSubStackView를 .fillProptionally로 바꾸어주기. mileStoneStackView.addArrangedSubview(firstSubStackView) NSLayoutConstraint.activate([ @@ -135,34 +149,27 @@ class MileStoneTableViewCell: UITableViewCell { //MARK: 3 : 완료일 스택 or Label with Img mileStoneStackView.addArrangedSubview(dateLabel) + //MARK: 4 : sub스택 + //-1 열린 이슈 라벨 + //-2 닫힌 이슈 라벨 + mileStoneStackView.addArrangedSubview(secondSubStackView) + + NSLayoutConstraint.activate([ + secondSubStackView.leadingAnchor.constraint(equalTo: mileStoneStackView.leadingAnchor), + secondSubStackView.trailingAnchor.constraint(equalTo: mileStoneStackView.trailingAnchor) + ]) + + secondSubStackView + .addArrangedSubview(openMileStoneLabelView) + secondSubStackView + .addArrangedSubview(closedMileStoneLabelView) + + NSLayoutConstraint.activate([ + openMileStoneLabelView.widthAnchor.constraint(equalTo: secondSubStackView.widthAnchor,constant: 1/2), + +// openMileStoneLabelView.leadingAnchor.constraint(equalTo: secondSubStackView.leadingAnchor), +// +// closedMileStoneLabelView.leadingAnchor.constraint(equalTo: openMileStoneLabelView.leadingAnchor), + ]) } } - -/* - - let firstSubStackView = UIStackView() - firstSubStackView.axis = .horizontal - firstSubStackView.spacing = spacing * 0.5 - firstSubStackView.distribution = .fill - // firstSubStackView.layoutMargins = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: spacing) - firstSubStackView.isLayoutMarginsRelativeArrangement = true - - - let titleLabel = UILabel() - titleLabel.text = "제목" - titleLabel.font = UIFont.boldSystemFont(ofSize: 22) - // titleLabel.leadingAnchor.constraint(equalTo: firstSubStackView.leadingAnchor, constant: 16).isActive = true - - // titleLabel.layoutMargins = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 0) - - let completenessLabel = UILabel() - completenessLabel.text = "100%" - completenessLabel.textColor = Colors.mileStoneSuceess - completenessLabel.font = UIFont.boldSystemFont(ofSize: 22) - // completenessLabel.trailingAnchor.constraint(equalTo: firstSubStackView.trailingAnchor, constant: 16).isActive = true - // completenessLabel.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 16) - - firstSubStackView.addArrangedSubview(titleLabel) - firstSubStackView.addArrangedSubview(completenessLabel) - // superStackView.addArrangedSubview(firstSubStackView) - */ From 2df9e1b2ddcaceb892c00a3a0a064e7a46ab4a9b Mon Sep 17 00:00:00 2001 From: Song Lee Date: Thu, 17 Jun 2021 10:56:59 +0900 Subject: [PATCH 34/91] =?UTF-8?q?feat:=20=EC=9D=BC=EB=B6=80=20=EC=98=A4?= =?UTF-8?q?=ED=86=A0=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EC=A1=B0?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Main/Label/Controller/AddLabelViewController.swift | 4 ++-- .../issue-tracker/Main/Label/View/LabelTableViewCell.swift | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift index 386140d1c..f31897d48 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift @@ -15,7 +15,7 @@ final class AddLabelViewController: UIViewController { container.addSubview(saveButton) NSLayoutConstraint.activate([ saveButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), - saveButton.widthAnchor.constraint(equalToConstant: spacing * 2), + saveButton.widthAnchor.constraint(greaterThanOrEqualToConstant: spacing * 2), saveButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), saveButton.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing) ]) @@ -23,7 +23,7 @@ final class AddLabelViewController: UIViewController { container.addSubview(cancelButton) NSLayoutConstraint.activate([ cancelButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), - cancelButton.widthAnchor.constraint(equalToConstant: spacing * 2), + cancelButton.widthAnchor.constraint(greaterThanOrEqualToConstant: spacing * 2), cancelButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), cancelButton.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing) ]) diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift index f79526e05..bbf3bf7a1 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift @@ -21,7 +21,7 @@ final class LabelTableViewCell: UITableViewCell { }() private lazy var spacing: CGFloat = { - return frame.height * 0.25 + return frame.height * 0.35 }() private let placeholder = "No description provided" @@ -51,7 +51,7 @@ final class LabelTableViewCell: UITableViewCell { NSLayoutConstraint.activate([ labelView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), - labelView.topAnchor.constraint(equalTo: topAnchor, constant: spacing * 2.2) + labelView.topAnchor.constraint(equalTo: topAnchor, constant: spacing * 1.6) ]) } @@ -61,7 +61,7 @@ final class LabelTableViewCell: UITableViewCell { NSLayoutConstraint.activate([ labelDescription.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), labelDescription.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -spacing), - labelDescription.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -spacing * 2.2) + labelDescription.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -spacing * 1.6) ]) } From 0ebf8684c02676d1f7c51830eb825772b4a4c5b3 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Thu, 17 Jun 2021 12:48:37 +0900 Subject: [PATCH 35/91] =?UTF-8?q?refactor:=20[#74]=20=E1=84=82=E1=85=A6?= =?UTF-8?q?=E1=84=90=E1=85=B3=E1=84=8B=E1=85=AF=E1=84=8F=E1=85=B3=20?= =?UTF-8?q?=E1=84=85=E1=85=A6=E1=84=8B=E1=85=B5=E1=84=8B=E1=85=A5=20?= =?UTF-8?q?=E1=84=80=E1=85=A2=E1=84=89=E1=85=A5=E1=86=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - NetworkManager, RequestManager 재사용성 개선 --- .../Github/GithubAuthorizationManager.swift | 4 +-- .../Controller/AddLabelViewController.swift | 20 +++++++------- .../issue-tracker/Network/EndPoint.swift | 2 +- .../Network/NetworkManager.swift | 26 +++++++++++-------- .../Network/RequestManager.swift | 15 +++++------ 5 files changed, 35 insertions(+), 32 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift index 6494c009a..8cb14376b 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift @@ -60,10 +60,10 @@ extension GithubAuthorizationManager: SocialLoginManagable { let url = EndPoint.OAuth.fullAddress() let parameter = [codeKey: code] - let requestManager = RequestManager(url: url, parameters: parameter) + let requestManager = RequestManager(url: url) let networkmanager = NetworkManager(requestManager: requestManager) - networkmanager.get { [weak self] (result: Result) in + networkmanager.get(queryParameters: parameter) { [weak self] (result: Result) in guard let self = self else { return } switch result { case .success(let response): diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift index f31897d48..94972050d 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift @@ -238,16 +238,16 @@ final class AddLabelViewController: UIViewController { } private func postNewLabel(_ newLabel: NewLabelDTO) { - networkManager?.post(requestBody: newLabel, completion: { [weak self] error in - guard error != nil else { - self?.presentAlert(with: error!.description) - return + networkManager?.post(requestBody: newLabel, completion: { [weak self] result in + switch result { + case .success(_): + self?.dismiss(animated: true, completion: { + guard let dismissOperation = self?.dismissOperation else { return } + dismissOperation() + }) + case .failure(let error): + self?.presentAlert(with: error.description) } - - self?.dismiss(animated: true, completion: { - guard let dismissOperation = self?.dismissOperation else { return } - dismissOperation() - }) }) } @@ -294,7 +294,7 @@ extension AddLabelViewController: LoginInfoContainer { guard let loginInfo = loginInfo else { return } let url = EndPoint.label.fullAddress() let headers = [Header.authorization.key(): loginInfo.jwt.description] - let requestManager = RequestManager(url: url, parameters: nil, headers: headers) + let requestManager = RequestManager(url: url, headers: headers) networkManager = NetworkManager(requestManager: requestManager) } } diff --git a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift index 5797c7fc9..ae9d9f1ed 100644 --- a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift +++ b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift @@ -26,6 +26,6 @@ enum EndPoint { } func fullAddress(with id: Int) -> String { - return fullAddress() + "\(id)" + return fullAddress() + "/\(id)" } } diff --git a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift index ba1f69dda..e95224e5d 100644 --- a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift +++ b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift @@ -9,8 +9,8 @@ import Foundation import Alamofire protocol NetworkManagerOperations { - func get(completion: @escaping (Result) -> Void) - func post(requestBody: T, completion: @escaping (NetworkError?) -> Void) + func get(queryParameters: [String: Any]?, completion: @escaping (Result) -> Void) + func post(requestBody: T, completion: @escaping (Result) -> Void) } final class NetworkManager: NetworkManagerOperations { @@ -21,8 +21,8 @@ final class NetworkManager: NetworkManagerOperations { self.requestManager = requestManager } - func get(completion: @escaping (Result) -> Void) { - let request = requestManager.create(method: .get) + func get(queryParameters: [String: Any]?, completion: @escaping (Result) -> Void) { + let request = requestManager.create(method: .get, queryParameters: queryParameters) request.responseDecodable(of: T.self) { [weak self] response in switch response.result { @@ -33,24 +33,28 @@ final class NetworkManager: NetworkManagerOperations { let error = self?.networkError(for: statusCode) ?? NetworkError.unknown completion(.failure(error)) } - } + } } - func post(requestBody: T, completion: @escaping (NetworkError?) -> Void) { + func post(requestBody: T, completion: @escaping (Result) -> Void) { let request = requestManager.create(method: .post, encodableParameters: requestBody) request.response { [weak self] response in - let statusCode = response.response?.statusCode - completion(self?.networkError(for: statusCode)) + switch response.result { + case .success(_): + completion(.success(())) + case .failure(_): + let statusCode = response.response?.statusCode + let error = self?.networkError(for: statusCode) ?? NetworkError.unknown + completion(.failure(error)) + } } } - private func networkError(for statusCode: Int?) -> NetworkError? { + private func networkError(for statusCode: Int?) -> NetworkError { guard let statusCode = statusCode else { return NetworkError.internet } switch statusCode { - case 200..<300: - return nil case 300..<400: return NetworkError.noResult case 400..<500: diff --git a/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift b/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift index 828e40276..0d8db6200 100644 --- a/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift +++ b/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift @@ -11,22 +11,21 @@ import Alamofire final class RequestManager { private var url: String - private var parameters: [String: Any]? private var headers: HTTPHeaders? + private let successCodeRange = 200..<300 - init(url: String, parameters: [String: Any]? = nil, headers: [String: String]? = nil) { + init(url: String, headers: [String: String]? = nil) { self.url = url - self.parameters = parameters self.headers = HTTPHeaders(headers ?? [:]) } - func create(method: HTTPMethod, parameters: [String: Any]? = nil) -> DataRequest { - let params = parameters != nil ? parameters : self.parameters - + func create(method: HTTPMethod, queryParameters: [String: Any]?) -> DataRequest { return AF.request(self.url, method: method, - parameters: params, + parameters: queryParameters, + encoding: URLEncoding.queryString, headers: self.headers) + .validate(statusCode: successCodeRange) } func create(method: HTTPMethod, encodableParameters: T) -> DataRequest { @@ -35,6 +34,6 @@ final class RequestManager { parameters: encodableParameters, encoder: JSONParameterEncoder(), headers: self.headers) + .validate(statusCode: successCodeRange) } - } From 6311f241c1d52f3db860896a0179adcd35deb305 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Thu, 17 Jun 2021 15:45:53 +0900 Subject: [PATCH 36/91] =?UTF-8?q?refactor:=20[#74]=20=EC=9C=A0=EC=A0=80=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=8B=B1=EA=B8=80=ED=86=A4=ED=8C=A8?= =?UTF-8?q?=ED=84=B4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #74 --- .../issue-tracker.xcodeproj/project.pbxproj | 10 ++--- .../LifeCycle/SceneDelegate.swift | 10 +++-- .../Controller/LoginViewController.swift | 39 ++++++++----------- .../Apple/AppleAuthorizationManager.swift | 8 ++-- .../Github/GithubAuthorizationManager.swift | 6 +-- .../Login/Model/LoginError.swift | 2 +- .../issue-tracker/Login/Model/LoginInfo.swift | 30 +++++++++++--- .../Login/Model/LoginInfoDTO.swift | 15 +++++++ .../Login/Model/LoginKeyChainManager.swift | 10 ++--- .../Protocol/SocialLoginManagerDelegate.swift | 2 +- .../Main/Issue/IssueViewController.swift | 8 ---- .../Controller/AddLabelViewController.swift | 14 ++----- .../Controller/LabelViewController.swift | 18 +++------ .../Main/LoginInfoContainer.swift | 12 ------ .../Milestone/MilestoneViewController.swift | 11 +----- .../MyAccount/MyAccountViewController.swift | 36 ++++++----------- .../TabBar/IssueTrackerTabBarController.swift | 13 ++----- .../TabBar/IssueTrackerTabBarCreator.swift | 17 +++----- 18 files changed, 114 insertions(+), 147 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Login/Model/LoginInfoDTO.swift delete mode 100644 iOS/issue-tracker/issue-tracker/Main/LoginInfoContainer.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 42aef00d3..e6a2ad901 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -14,7 +14,6 @@ E426DAC42671D95D0069E77D /* LoginService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E426DAC32671D95D0069E77D /* LoginService.swift */; }; E426DAC72671F6A00069E77D /* LoginError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E426DAC62671F6A00069E77D /* LoginError.swift */; }; E426DAC92671F7760069E77D /* AlertFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E426DAC82671F7760069E77D /* AlertFactory.swift */; }; - E426DACB267206D10069E77D /* LoginInfoContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E426DACA267206D10069E77D /* LoginInfoContainer.swift */; }; E426DAD126730DC50069E77D /* OAuthResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E426DAD026730DC50069E77D /* OAuthResponseDTO.swift */; }; E42AD0FE266E52FB0071B436 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD0FD266E52FB0071B436 /* AppDelegate.swift */; }; E42AD100266E52FB0071B436 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD0FF266E52FB0071B436 /* SceneDelegate.swift */; }; @@ -43,6 +42,7 @@ E43912E42679C0DA003CD344 /* AddLabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E32679C0DA003CD344 /* AddLabelViewController.swift */; }; E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */; }; E43912EA267A2351003CD344 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E9267A2351003CD344 /* NetworkError.swift */; }; + E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912EB267B1A4E003CD344 /* LoginInfoDTO.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -63,7 +63,6 @@ E426DAC32671D95D0069E77D /* LoginService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginService.swift; sourceTree = ""; }; E426DAC62671F6A00069E77D /* LoginError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginError.swift; sourceTree = ""; }; E426DAC82671F7760069E77D /* AlertFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertFactory.swift; sourceTree = ""; }; - E426DACA267206D10069E77D /* LoginInfoContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginInfoContainer.swift; sourceTree = ""; }; E426DAD026730DC50069E77D /* OAuthResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthResponseDTO.swift; sourceTree = ""; }; E42AD0FA266E52FB0071B436 /* issue-tracker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "issue-tracker.app"; sourceTree = BUILT_PRODUCTS_DIR; }; E42AD0FD266E52FB0071B436 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -94,6 +93,7 @@ E43912E32679C0DA003CD344 /* AddLabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddLabelViewController.swift; sourceTree = ""; }; E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewLabelDTO.swift; sourceTree = ""; }; E43912E9267A2351003CD344 /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; }; + E43912EB267B1A4E003CD344 /* LoginInfoDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginInfoDTO.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -120,8 +120,9 @@ E426DACC267301010069E77D /* Model */ = { isa = PBXGroup; children = ( - E426DAC32671D95D0069E77D /* LoginService.swift */, E426DABB2670EC5E0069E77D /* LoginInfo.swift */, + E43912EB267B1A4E003CD344 /* LoginInfoDTO.swift */, + E426DAC32671D95D0069E77D /* LoginService.swift */, E426DAC62671F6A00069E77D /* LoginError.swift */, E426DACD267302BA0069E77D /* Protocol */, FAC6D8922671E1A800A9E5F9 /* Github */, @@ -213,7 +214,6 @@ isa = PBXGroup; children = ( E42AD116267087F40071B436 /* TabBar */, - E426DACA267206D10069E77D /* LoginInfoContainer.swift */, E42AD11926708EBA0071B436 /* Issue */, E42AD11A26708EC00071B436 /* Label */, E42AD11B26708EC80071B436 /* Milestone */, @@ -440,13 +440,13 @@ E43912EA267A2351003CD344 /* NetworkError.swift in Sources */, E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, + E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */, E426DAC22671B1C60069E77D /* LoginKeyChainManager.swift in Sources */, E43912D426788CC3003CD344 /* ImageBarButton.swift in Sources */, E43912D2267878F4003CD344 /* HexColorCode.swift in Sources */, E426DAC72671F6A00069E77D /* LoginError.swift in Sources */, E43912D626789812003CD344 /* RequestManager.swift in Sources */, E426DAC42671D95D0069E77D /* LoginService.swift in Sources */, - E426DACB267206D10069E77D /* LoginInfoContainer.swift in Sources */, E42AD120267093430071B436 /* LabelViewController.swift in Sources */, E43912D826789A83003CD344 /* EndPoint.swift in Sources */, E426DABE2670EC830069E77D /* SocialLoginManagerDelegate.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/LifeCycle/SceneDelegate.swift b/iOS/issue-tracker/issue-tracker/LifeCycle/SceneDelegate.swift index 91d2b9003..bea57751c 100644 --- a/iOS/issue-tracker/issue-tracker/LifeCycle/SceneDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/LifeCycle/SceneDelegate.swift @@ -11,17 +11,19 @@ import AuthenticationServices class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? + private let loginInfo = LoginInfo.shared func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { var loginManager: LoginKeyChainManager? - var loginInfo: LoginInfo? + var loginInfo: LoginInfoDTO? for loginService in LoginService.allCases { loginManager = LoginKeyChainManager(loginService: loginService) loginInfo = loginManager?.read() if loginInfo != nil { + self.loginInfo.service = loginService break } } @@ -43,9 +45,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } - private func straightToIssueTrackerScene(with loginManager: LoginKeyChainManager,_ loginInfo: LoginInfo) { + private func straightToIssueTrackerScene(with loginManager: LoginKeyChainManager,_ loginInfoDTO: LoginInfoDTO) { + loginInfo.store(loginInfoDTO: loginInfoDTO) + DispatchQueue.main.async { - let issueTrackerTabBarControllerCreator = IssueTrackerTabBarCreator(loginInfo: loginInfo) + let issueTrackerTabBarControllerCreator = IssueTrackerTabBarCreator() let issueTrackerTabBarController = issueTrackerTabBarControllerCreator.create() self.window?.rootViewController = issueTrackerTabBarController } diff --git a/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift b/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift index fd73da149..5e4c0d557 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift @@ -96,6 +96,7 @@ class LoginViewController: UIViewController { private let borderWidth: CGFloat = 1 private var socialLoginManager: SocialLoginManagable? + private let loginInfo = LoginInfo.shared override func viewDidLoad() { super.viewDidLoad() @@ -187,9 +188,9 @@ class LoginViewController: UIViewController { ]) } - private func presentIssueViewController(with loginInfo: LoginInfo) { + private func presentIssueViewController() { DispatchQueue.main.async { - let issueTrackerTabBarControllerCreator = IssueTrackerTabBarCreator(loginInfo: loginInfo) + let issueTrackerTabBarControllerCreator = IssueTrackerTabBarCreator() let issueTrackerTabBarController = issueTrackerTabBarControllerCreator.create() issueTrackerTabBarController.modalPresentationStyle = .fullScreen self.present(issueTrackerTabBarController, animated: true, completion: nil) @@ -204,38 +205,30 @@ class LoginViewController: UIViewController { } @objc private func loginWithGithubTouched(_ sender: UIButton) { - configureGithubLoginManager() + configureLoginManager(service: .github) socialLoginManager?.login() } @objc private func loginWithAppleTouched(_ sender: UIButton) { - configureAppleLoginManager() + configureLoginManager(service: .apple) socialLoginManager?.login() } - private func configureGithubLoginManager() { - guard socialLoginManager as? GithubAuthorizationManager == nil else { return } - let githubKeyChainManager = LoginKeyChainManager(loginService: .github) - let githubLoginManager = GithubAuthorizationManager(viewController: self, - delegate: self, - keyChainSaver: githubKeyChainManager) - self.socialLoginManager = githubLoginManager + private func configureLoginManager(service: LoginService) { + let keyChainManager = LoginKeyChainManager(loginService: service) + loginInfo.service = service + let loginManager = GithubAuthorizationManager(viewController: self, + delegate: self, + keyChainSaver: keyChainManager) + self.socialLoginManager = loginManager } - - private func configureAppleLoginManager() { - guard socialLoginManager as? AppleAuthorizationManager == nil else { return } - let appleKeyChainManager = LoginKeyChainManager(loginService: .apple) - let appleLoginManager = AppleAuthorizationManager(viewController: self, - delegate: self, - keyChainSaver: appleKeyChainManager) - self.socialLoginManager = appleLoginManager - } - } extension LoginViewController: SocialLoginManagerDelegate { - func didSocialLoginSuccess(with loginInfo: LoginInfo) { - presentIssueViewController(with: loginInfo) + func didSocialLoginSuccess(with loginInfoDTO: LoginInfoDTO) { + let loginInfo = LoginInfo.shared + loginInfo.store(loginInfoDTO: loginInfoDTO) + presentIssueViewController() } func didSocialLoginFail(with error: LoginError) { diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift index 62b7afc4b..368356ae5 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Apple/AppleAuthorizationManager.swift @@ -8,7 +8,7 @@ import AuthenticationServices final class AppleAuthorizationManager: NSObject, SocialLoginManagable { - + private weak var viewController: UIViewController? private weak var delegate: SocialLoginManagerDelegate? private var keyChainSaver: LoginKeyChainManager @@ -43,10 +43,10 @@ extension AppleAuthorizationManager: ASAuthorizationControllerDelegate { let userID = appleIDCredential.user let jwt = JWT(jwt: tokenInString, tokenType: "Bearer") - let loginInfo = LoginInfo(userID: userID, jwt: jwt, avatarURL: nil, name: name) + let loginInfoDTO = LoginInfoDTO(userID: userID, jwt: jwt, avatarURL: nil, name: name) - if keyChainSaver.save(loginInfo) { - delegate?.didSocialLoginSuccess(with: loginInfo) + if keyChainSaver.save(loginInfoDTO) { + delegate?.didSocialLoginSuccess(with: loginInfoDTO) } else { let saveError = LoginError.keyChainSave delegate?.didSocialLoginFail(with: saveError) diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift index 8cb14376b..c25c49813 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift @@ -67,13 +67,13 @@ extension GithubAuthorizationManager: SocialLoginManagable { guard let self = self else { return } switch result { case .success(let response): - let loginInfo = LoginInfo(userID: nil, + let loginInfoDTO = LoginInfoDTO(userID: nil, jwt: response.jwt, avatarURL: response.avatarUrl, name: response.loginId) - if self.keyChainSaver.save(loginInfo) { - self.delegate?.didSocialLoginSuccess(with: loginInfo) + if self.keyChainSaver.save(loginInfoDTO) { + self.delegate?.didSocialLoginSuccess(with: loginInfoDTO) } else { let saveError = LoginError.keyChainSave self.delegate?.didSocialLoginFail(with: saveError) diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/LoginError.swift b/iOS/issue-tracker/issue-tracker/Login/Model/LoginError.swift index 49f68f139..c186bd31c 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/LoginError.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/LoginError.swift @@ -24,7 +24,7 @@ extension LoginError: CustomStringConvertible { case .keyChainSave: return "로그인 정보 저장에 실패했습니다. \n로그인을 다시 시도해주세요." case .logout: - return "로그아웃 기능은 제공되지 않습니다🥺" + return "로그아웃에 실패했습니다🙉" } } } diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/LoginInfo.swift b/iOS/issue-tracker/issue-tracker/Login/Model/LoginInfo.swift index 044027191..eb94327e6 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/LoginInfo.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/LoginInfo.swift @@ -7,9 +7,29 @@ import Foundation -struct LoginInfo: Codable { - let userID: String? - let jwt: JWT - let avatarURL: String? - let name: String +class LoginInfo { + static let shared = LoginInfo() + + var service: LoginService? + var userID: String? + var jwt: JWT? + var avatarURL: String? + var name: String? + + private init() {} + + func store(loginInfoDTO: LoginInfoDTO) { + userID = loginInfoDTO.userID + jwt = loginInfoDTO.jwt + avatarURL = loginInfoDTO.avatarURL + name = loginInfoDTO.name + } + + func clear() { + service = nil + userID = nil + jwt = nil + avatarURL = nil + name = nil + } } diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/LoginInfoDTO.swift b/iOS/issue-tracker/issue-tracker/Login/Model/LoginInfoDTO.swift new file mode 100644 index 000000000..34497cdeb --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Login/Model/LoginInfoDTO.swift @@ -0,0 +1,15 @@ +// +// LoginInfoDTO.swift +// issue-tracker +// +// Created by Song on 2021/06/17. +// + +import Foundation + +struct LoginInfoDTO: Codable { + let userID: String? + let jwt: JWT + let avatarURL: String? + let name: String +} diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/LoginKeyChainManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/LoginKeyChainManager.swift index 2abf2a873..e8cb46fdd 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/LoginKeyChainManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/LoginKeyChainManager.swift @@ -16,8 +16,8 @@ final class LoginKeyChainManager { self.loginService = loginService.description } - func save(_ loginInfo: LoginInfo) -> Bool { - guard let loginInfo = try? JSONEncoder().encode(loginInfo) else { return false } + func save(_ loginInfoDTO: LoginInfoDTO) -> Bool { + guard let loginInfo = try? JSONEncoder().encode(loginInfoDTO) else { return false } let saveQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword, kSecAttrService: loginService, @@ -26,7 +26,7 @@ final class LoginKeyChainManager { return SecItemAdd(saveQuery as CFDictionary, nil) == errSecSuccess } - func read() -> LoginInfo? { + func read() -> LoginInfoDTO? { let readQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword, kSecAttrService: loginService, kSecMatchLimit: kSecMatchLimitOne, @@ -38,9 +38,9 @@ final class LoginKeyChainManager { guard SecItemCopyMatching(readQuery as CFDictionary, &item) == errSecSuccess, let existingItem = item as? [String: Any], let data = existingItem[kSecAttrGeneric as String] as? Data, - let loginInfo = try? JSONDecoder().decode(LoginInfo.self, from: data) else { return nil } + let loginInfoDTO = try? JSONDecoder().decode(LoginInfoDTO.self, from: data) else { return nil } - return loginInfo + return loginInfoDTO } func delete() -> Bool { diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Protocol/SocialLoginManagerDelegate.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Protocol/SocialLoginManagerDelegate.swift index ceb9e3087..a6febb029 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Protocol/SocialLoginManagerDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Protocol/SocialLoginManagerDelegate.swift @@ -8,6 +8,6 @@ import Foundation protocol SocialLoginManagerDelegate: AnyObject { - func didSocialLoginSuccess(with loginInfo: LoginInfo) + func didSocialLoginSuccess(with loginInfo: LoginInfoDTO) func didSocialLoginFail(with error: LoginError) } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift index 803fb619c..cc3a5dc1d 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift @@ -9,18 +9,10 @@ import UIKit class IssueViewController: UIViewController { - private var loginInfo: LoginInfo? - override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.red title = "이슈 선택" } - -} -extension IssueViewController: LoginInfoContainer { - func setup(loginInfo: LoginInfo) { - self.loginInfo = loginInfo - } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift index 94972050d..fee8e83aa 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift @@ -161,7 +161,7 @@ final class AddLabelViewController: UIViewController { addTopMenu() addEditStackView() addLabelPreview() - + setNetworkManager() titleTextfield.delegate = self } @@ -282,18 +282,12 @@ final class AddLabelViewController: UIViewController { let titleColor = colorConverter.isColorDark(hex: hex) ? UIColor.white : UIColor.black previewLabel.configure(with: backgroundColor, titleColor, nil) } -} - -extension AddLabelViewController: LoginInfoContainer { - func setup(loginInfo: LoginInfo) { - self.loginInfo = loginInfo - setNetworkManager() - } private func setNetworkManager() { - guard let loginInfo = loginInfo else { return } + let loginInfo = LoginInfo.shared + guard let jwt = loginInfo.jwt else { return } let url = EndPoint.label.fullAddress() - let headers = [Header.authorization.key(): loginInfo.jwt.description] + let headers = [Header.authorization.key(): jwt.description] let requestManager = RequestManager(url: url, headers: headers) networkManager = NetworkManager(requestManager: requestManager) } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index ee274c99a..b0aa92c7d 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -31,8 +31,6 @@ final class LabelViewController: UIViewController { private var labelTableDatasource: LabelTableViewDatasource? private var labelTableDelegate: LabelTableDelegate? - private var loginInfo: LoginInfo? - override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.white @@ -71,15 +69,16 @@ final class LabelViewController: UIViewController { } private func setNetworkManager() { - guard let loginInfo = loginInfo else { return } + let loginInfo = LoginInfo.shared + guard let jwt = loginInfo.jwt else { return } let url = EndPoint.label.fullAddress() - let headers = [Header.authorization.key(): loginInfo.jwt.description] + let headers = [Header.authorization.key(): jwt.description] let requestManager = RequestManager(url: url, headers: headers) networkManager = NetworkManager(requestManager: requestManager) } func loadData() { - networkManager?.get(completion: { [weak self] (result: Result) in + networkManager?.get(queryParameters: nil, completion: { [weak self] (result: Result) in switch result { case .success(let result): guard let labels = result.data else { return } @@ -105,9 +104,7 @@ final class LabelViewController: UIViewController { } @objc private func addLabelTouched(_ sender: UIButton) { - guard let loginInfo = loginInfo else { return } - let addLabelViewController = AddLabelViewController() - addLabelViewController.setup(loginInfo: loginInfo) + let addLabelViewController = AddLabelViewController() addLabelViewController.modalPresentationStyle = .formSheet addLabelViewController.setUpDismissOperation { [weak self] in self?.loadData() @@ -116,8 +113,3 @@ final class LabelViewController: UIViewController { } } -extension LabelViewController: LoginInfoContainer { - func setup(loginInfo: LoginInfo) { - self.loginInfo = loginInfo - } -} diff --git a/iOS/issue-tracker/issue-tracker/Main/LoginInfoContainer.swift b/iOS/issue-tracker/issue-tracker/Main/LoginInfoContainer.swift deleted file mode 100644 index 5dabea894..000000000 --- a/iOS/issue-tracker/issue-tracker/Main/LoginInfoContainer.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// LoginInfoContainer.swift -// issue-tracker -// -// Created by Song on 2021/06/10. -// - -import Foundation - -protocol LoginInfoContainer { - func setup(loginInfo: LoginInfo) -} diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/MilestoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/MilestoneViewController.swift index 3402dc85e..a7e26549c 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/MilestoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/MilestoneViewController.swift @@ -7,10 +7,7 @@ import UIKit -class MilestoneViewController: UIViewController { - - private var loginInfo: LoginInfo? - +class MilestoneViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.yellow @@ -18,9 +15,3 @@ class MilestoneViewController: UIViewController { } } - -extension MilestoneViewController: LoginInfoContainer { - func setup(loginInfo: LoginInfo) { - self.loginInfo = loginInfo - } -} diff --git a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift index 4136b6b40..8d2d18266 100644 --- a/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/MyAccount/MyAccountViewController.swift @@ -32,13 +32,12 @@ class MyAccountViewController: UIViewController { private var userName = "unknown" private let spacing: CGFloat = 16 - private var loginInfo: LoginInfo? - override func viewDidLoad() { - + override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white title = "내 계정" + updateWelcomeLabel() addWelcomeLabel() addLogoutButton() } @@ -72,34 +71,23 @@ class MyAccountViewController: UIViewController { } @objc private func didLogoutTouched(_ sender: UIButton) { - var loginManager: LoginKeyChainManager? - for loginService in LoginService.allCases { - loginManager = LoginKeyChainManager(loginService: loginService) - loginInfo = loginManager?.read() - if loginInfo != nil { - break - } + let loginInfo = LoginInfo.shared + guard let service = loginInfo.service else { return } + let loginManager = LoginKeyChainManager(loginService: service) + guard loginManager.delete() else { + let logoutError = LoginError.logout + presentAlert(with: logoutError.description) + return } - guard let loginManager = loginManager else { return } - let _ = loginManager.delete() - + loginInfo.clear() let loginViewController = LoginViewController() loginViewController.modalPresentationStyle = .fullScreen self.present(loginViewController, animated: true, completion: nil) - - } - -} - -extension MyAccountViewController: LoginInfoContainer { - - func setup(loginInfo: LoginInfo) { - self.loginInfo = loginInfo - updateWelcomeLabel() } private func updateWelcomeLabel() { - guard let userName = loginInfo?.name else { return } + let loginInfo = LoginInfo.shared + guard let userName = loginInfo.name else { return } self.userName = userName } diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift index c5e2f0a74..40cb3e1d0 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarController.swift @@ -8,8 +8,7 @@ import UIKit class IssueTrackerTabBarController: UITabBarController { - - private var loginInfo: LoginInfo? + private let imageLoadManager = ImageLoadManager() override func viewDidLoad() { @@ -25,14 +24,10 @@ class IssueTrackerTabBarController: UITabBarController { super.viewDidLayoutSubviews() updateUserImage() } - - func configure(loginInfo: LoginInfo) { - self.loginInfo = loginInfo - } - + private func updateUserImage() { - - guard let imageURL = self.loginInfo?.avatarURL else { return } + let loginInfo = LoginInfo.shared + guard let imageURL = loginInfo.avatarURL else { return } imageLoadManager.load(from: imageURL) { cachePath in guard let userImage = UIImage(contentsOfFile: cachePath) else {return} DispatchQueue.main.async { diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift index 8951d817a..780570145 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift @@ -10,7 +10,7 @@ import UIKit final class IssueTrackerTabBarCreator { private let childInfos: [TabBarChildInfo] - private var loginInfo: LoginInfo +// private var loginInfo: LoginInfo enum Title { static let issue = "이슈" @@ -26,17 +26,17 @@ final class IssueTrackerTabBarCreator { static let myAccount = "person.circle" } - init(childInfos: [TabBarChildInfo], loginInfo: LoginInfo) { + init(childInfos: [TabBarChildInfo]) { self.childInfos = childInfos - self.loginInfo = loginInfo +// self.loginInfo = loginInfo } - convenience init(loginInfo: LoginInfo) { + convenience init() { let issue = TabBarChildInfo(title: Title.issue, imageName: SystemImageName.issue, type: IssueViewController.self) let label = TabBarChildInfo(title: Title.label, imageName: SystemImageName.label, type: LabelViewController.self) let milestone = TabBarChildInfo(title: Title.milestone, imageName: SystemImageName.milestone, type: MilestoneViewController.self) let myAccount = TabBarChildInfo(title: Title.myAccount, imageName: SystemImageName.myAccount, type: MyAccountViewController.self) - self.init(childInfos: [issue, label, milestone, myAccount], loginInfo: loginInfo) + self.init(childInfos: [issue, label, milestone, myAccount]) } private func generateChild(with info: TabBarChildInfo) -> UIViewController { @@ -44,10 +44,6 @@ final class IssueTrackerTabBarCreator { let childViewController = info.type.create() childViewController.tabBarItem = tabBarItem - if let loginInfoContainer = childViewController as? LoginInfoContainer { - loginInfoContainer.setup(loginInfo: self.loginInfo) - } - let navigationController = UINavigationController() navigationController.navigationBar.prefersLargeTitles = true navigationController.pushViewController(childViewController, animated: false) @@ -58,8 +54,7 @@ final class IssueTrackerTabBarCreator { extension IssueTrackerTabBarCreator { func create() -> IssueTrackerTabBarController { - let issueTrackerTabBarController = IssueTrackerTabBarController() - issueTrackerTabBarController.configure(loginInfo: loginInfo) + let issueTrackerTabBarController = IssueTrackerTabBarController() let childs = childInfos.map{ generateChild(with: $0) } issueTrackerTabBarController.setViewControllers(childs, animated: true) return issueTrackerTabBarController From 09cc8e92e51593a8cbefba45dcb5ef191dda8a1a Mon Sep 17 00:00:00 2001 From: Song Lee Date: Thu, 17 Jun 2021 16:55:32 +0900 Subject: [PATCH 37/91] =?UTF-8?q?fix:=20[#68]=20=EC=8A=A4=ED=83=9D?= =?UTF-8?q?=EB=B7=B0=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/MileStoneTableViewCell.swift | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index 33700a7e9..afb1366ec 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -92,7 +92,6 @@ class MileStoneTableViewCell: UITableViewCell { private lazy var closedMileStoneLabelView: MileStoneLabelView = { let mileStoneLabelView = MileStoneLabelView(chooseNum: 1) - return mileStoneLabelView }() @@ -143,6 +142,15 @@ class MileStoneTableViewCell: UITableViewCell { firstSubStackView .addArrangedSubview(completenessLabel) + firstSubStackView.spacing = 16 + completenessLabel.textAlignment = .right + + NSLayoutConstraint.activate([ + titleLabel.widthAnchor.constraint(greaterThanOrEqualTo: firstSubStackView.widthAnchor, multiplier: 0.6), + completenessLabel.widthAnchor.constraint(equalTo: firstSubStackView.widthAnchor, multiplier: 0.2) + ]) + + //MARK: 2 : 마일스톤에 대한 설명 라벨 mileStoneStackView.addArrangedSubview(descriptionLabel) @@ -152,6 +160,7 @@ class MileStoneTableViewCell: UITableViewCell { //MARK: 4 : sub스택 //-1 열린 이슈 라벨 //-2 닫힌 이슈 라벨 + /* mileStoneStackView.addArrangedSubview(secondSubStackView) NSLayoutConstraint.activate([ @@ -167,9 +176,10 @@ class MileStoneTableViewCell: UITableViewCell { NSLayoutConstraint.activate([ openMileStoneLabelView.widthAnchor.constraint(equalTo: secondSubStackView.widthAnchor,constant: 1/2), -// openMileStoneLabelView.leadingAnchor.constraint(equalTo: secondSubStackView.leadingAnchor), -// -// closedMileStoneLabelView.leadingAnchor.constraint(equalTo: openMileStoneLabelView.leadingAnchor), + openMileStoneLabelView.leadingAnchor.constraint(equalTo: secondSubStackView.leadingAnchor), + closedMileStoneLabelView.leadingAnchor.constraint(equalTo: openMileStoneLabelView.leadingAnchor), ]) + + */ } } From 4f2341ab80dfaf999ed12dfd73880cc0355dbc2e Mon Sep 17 00:00:00 2001 From: Song Lee Date: Fri, 18 Jun 2021 11:34:11 +0900 Subject: [PATCH 38/91] =?UTF-8?q?feat:=20[#73]=20=E1=84=82=E1=85=A6?= =?UTF-8?q?=E1=84=90=E1=85=B3=E1=84=8B=E1=85=AF=E1=84=8F=E1=85=B3=20?= =?UTF-8?q?=E1=84=85=E1=85=A6=E1=84=8B=E1=85=B5=E1=84=8B=E1=85=A5=20?= =?UTF-8?q?=E1=84=89=E1=85=A1=E1=86=A8=E1=84=8C=E1=85=A6=20=E1=84=86?= =?UTF-8?q?=E1=85=A6=E1=84=89=E1=85=A9=E1=84=83=E1=85=B3=20=E1=84=8E?= =?UTF-8?q?=E1=85=AE=E1=84=80=E1=85=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 네트워크 메소드 호출 시 endpoint를 매개변수로 받도록 수정 --- .../Github/GithubAuthorizationManager.swift | 7 +++-- .../Controller/AddLabelViewController.swift | 7 +++-- .../issue-tracker/Network/EndPoint.swift | 15 ++++++----- .../Network/NetworkManager.swift | 26 +++++++++++++------ .../Network/RequestManager.swift | 14 +++++----- 5 files changed, 40 insertions(+), 29 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift index c25c49813..c59312a97 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Model/Github/GithubAuthorizationManager.swift @@ -58,12 +58,11 @@ extension GithubAuthorizationManager: SocialLoginManagable { .first? .value else { return } - let url = EndPoint.OAuth.fullAddress() let parameter = [codeKey: code] - let requestManager = RequestManager(url: url) - let networkmanager = NetworkManager(requestManager: requestManager) + let networkmanager = NetworkManager(baseAddress: EndPoint.baseAddress) + let OAuthEndpoint = EndPoint.OAuth.path() - networkmanager.get(queryParameters: parameter) { [weak self] (result: Result) in + networkmanager.get(endpoint: OAuthEndpoint, queryParameters: parameter) { [weak self] (result: Result) in guard let self = self else { return } switch result { case .success(let response): diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift index fee8e83aa..370c62e01 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift @@ -238,7 +238,8 @@ final class AddLabelViewController: UIViewController { } private func postNewLabel(_ newLabel: NewLabelDTO) { - networkManager?.post(requestBody: newLabel, completion: { [weak self] result in + let newLabelEndpoint = EndPoint.label.path() + networkManager?.post(endpoint: newLabelEndpoint, requestBody: newLabel, completion: { [weak self] result in switch result { case .success(_): self?.dismiss(animated: true, completion: { @@ -286,10 +287,8 @@ final class AddLabelViewController: UIViewController { private func setNetworkManager() { let loginInfo = LoginInfo.shared guard let jwt = loginInfo.jwt else { return } - let url = EndPoint.label.fullAddress() let headers = [Header.authorization.key(): jwt.description] - let requestManager = RequestManager(url: url, headers: headers) - networkManager = NetworkManager(requestManager: requestManager) + networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) } } diff --git a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift index ae9d9f1ed..549463b78 100644 --- a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift +++ b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift @@ -13,19 +13,22 @@ enum EndPoint { case OAuth case label case milestone + case none - func fullAddress() -> String { + func path() -> String { switch self { case .OAuth: - return EndPoint.baseAddress + "/login/ios" + return "/login/ios" case .label: - return EndPoint.baseAddress + "/labels" + return "/labels" case .milestone: - return EndPoint.baseAddress + "/milestones" + return "/milestones" + case .none: + return "" } } - func fullAddress(with id: Int) -> String { - return fullAddress() + "/\(id)" + func path(with id: Int) -> String { + return path() + "/\(id)" } } diff --git a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift index e95224e5d..6faed6ba9 100644 --- a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift +++ b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift @@ -9,20 +9,22 @@ import Foundation import Alamofire protocol NetworkManagerOperations { - func get(queryParameters: [String: Any]?, completion: @escaping (Result) -> Void) - func post(requestBody: T, completion: @escaping (Result) -> Void) + func get(endpoint: String, queryParameters: [String: Any]?, completion: @escaping (Result) -> Void) + func delete(endpoint: String, queryParameters: [String: Any]?, completion: @escaping (Result) -> Void) + func post(endpoint: String, requestBody: T, completion: @escaping (Result) -> Void) } final class NetworkManager: NetworkManagerOperations { private let requestManager: RequestManager - init(requestManager: RequestManager) { + init(baseAddress: String, headers: [String: String]? = nil) { + let requestManager = RequestManager(baseAddress: baseAddress, headers: headers) self.requestManager = requestManager } - func get(queryParameters: [String: Any]?, completion: @escaping (Result) -> Void) { - let request = requestManager.create(method: .get, queryParameters: queryParameters) + func get(endpoint: String, queryParameters: [String: Any]?, completion: @escaping (Result) -> Void) { + let request = requestManager.create(endpoint: endpoint, method: .get, queryParameters: queryParameters) request.responseDecodable(of: T.self) { [weak self] response in switch response.result { @@ -36,9 +38,17 @@ final class NetworkManager: NetworkManagerOperations { } } - func post(requestBody: T, completion: @escaping (Result) -> Void) { - let request = requestManager.create(method: .post, encodableParameters: requestBody) - + func delete(endpoint: String, queryParameters: [String: Any]?, completion: @escaping (Result) -> Void) { + let request = requestManager.create(endpoint: endpoint, method: .delete, queryParameters: queryParameters) + executeVoidRequest(request: request, completion: completion) + } + + func post(endpoint: String, requestBody: T, completion: @escaping (Result) -> Void) { + let request = requestManager.create(endpoint: endpoint, method: .post, encodableParameters: requestBody) + executeVoidRequest(request: request, completion: completion) + } + + private func executeVoidRequest(request: DataRequest, completion: @escaping (Result) -> Void) { request.response { [weak self] response in switch response.result { case .success(_): diff --git a/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift b/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift index 0d8db6200..ae4a2196b 100644 --- a/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift +++ b/iOS/issue-tracker/issue-tracker/Network/RequestManager.swift @@ -10,17 +10,17 @@ import Alamofire final class RequestManager { - private var url: String + private var baseAddress: String private var headers: HTTPHeaders? private let successCodeRange = 200..<300 - init(url: String, headers: [String: String]? = nil) { - self.url = url + init(baseAddress: String, headers: [String: String]? = nil) { + self.baseAddress = baseAddress self.headers = HTTPHeaders(headers ?? [:]) } - func create(method: HTTPMethod, queryParameters: [String: Any]?) -> DataRequest { - return AF.request(self.url, + func create(endpoint: String = "", method: HTTPMethod, queryParameters: [String: Any]?) -> DataRequest { + return AF.request(self.baseAddress + endpoint, method: method, parameters: queryParameters, encoding: URLEncoding.queryString, @@ -28,8 +28,8 @@ final class RequestManager { .validate(statusCode: successCodeRange) } - func create(method: HTTPMethod, encodableParameters: T) -> DataRequest { - return AF.request(self.url, + func create(endpoint: String = "", method: HTTPMethod, encodableParameters: T) -> DataRequest { + return AF.request(self.baseAddress + endpoint, method: method, parameters: encodableParameters, encoder: JSONParameterEncoder(), From 4caccc5e7ebc610ea8f3e9b9da7dc23fd1a20d92 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Fri, 18 Jun 2021 11:34:43 +0900 Subject: [PATCH 39/91] =?UTF-8?q?feat:=20[#73]=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=82=AD=EC=A0=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 4 +++ .../Main/Common/CellAction.swift | 25 +++++++++++++ .../Label/Controller/LabelTableDelegate.swift | 23 ++++++++++++ .../Controller/LabelTableViewDatasource.swift | 2 +- .../Controller/LabelViewController.swift | 35 ++++++++++++++++--- 5 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Common/CellAction.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index e6a2ad901..3ba9b7f60 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -43,6 +43,7 @@ E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */; }; E43912EA267A2351003CD344 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E9267A2351003CD344 /* NetworkError.swift */; }; E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912EB267B1A4E003CD344 /* LoginInfoDTO.swift */; }; + E43912EE267C3C0E003CD344 /* CellAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912ED267C3C0E003CD344 /* CellAction.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -94,6 +95,7 @@ E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewLabelDTO.swift; sourceTree = ""; }; E43912E9267A2351003CD344 /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; }; E43912EB267B1A4E003CD344 /* LoginInfoDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginInfoDTO.swift; sourceTree = ""; }; + E43912ED267C3C0E003CD344 /* CellAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellAction.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -271,6 +273,7 @@ isa = PBXGroup; children = ( E43912C926776DA0003CD344 /* View */, + E43912ED267C3C0E003CD344 /* CellAction.swift */, ); path = Common; sourceTree = ""; @@ -451,6 +454,7 @@ E43912D826789A83003CD344 /* EndPoint.swift in Sources */, E426DABE2670EC830069E77D /* SocialLoginManagerDelegate.swift in Sources */, E42AD0FE266E52FB0071B436 /* AppDelegate.swift in Sources */, + E43912EE267C3C0E003CD344 /* CellAction.swift in Sources */, E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */, FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */, E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/CellAction.swift b/iOS/issue-tracker/issue-tracker/Main/Common/CellAction.swift new file mode 100644 index 000000000..406b3340e --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Common/CellAction.swift @@ -0,0 +1,25 @@ +// +// CellAction.swift +// issue-tracker +// +// Created by Song on 2021/06/18. +// + +import Foundation + +enum CellAction { + case delete + case edit + case close + + func buttonTitle() -> String { + switch self { + case .delete: + return "삭제" + case .edit: + return "수정" + case .close: + return "닫기" + } + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift index a43d56ef2..0592dca94 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift @@ -8,7 +8,30 @@ import UIKit final class LabelTableDelegate: NSObject, UITableViewDelegate { + + typealias CellActionHandler = (Int, CellAction) -> Void + private var cellActionHandler: CellActionHandler + + init(cellActionHandler: @escaping CellActionHandler) { + self.cellActionHandler = cellActionHandler + } + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 118 } + + func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { + let deleteAction = UIContextualAction(style: .destructive, + title: CellAction.delete.buttonTitle()) { [weak self] _, _, _ in + self?.cellActionHandler(indexPath.row, .delete) + } + deleteAction.image = UIImage(systemName: "trash") + + let editAction = UIContextualAction(style: .normal, + title: CellAction.edit.buttonTitle()) { [weak self] _, _, _ in + self?.cellActionHandler(indexPath.row, .edit) + } + editAction.image = UIImage(systemName: "pencil") + return UISwipeActionsConfiguration(actions: [editAction, deleteAction]) + } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift index be33db80e..2d87fc187 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift @@ -9,7 +9,7 @@ import UIKit final class LabelTableViewDatasource: NSObject, UITableViewDataSource { - private var labels = [Label]() + private(set) var labels = [Label]() private let colorConverter = HexColorConverter() func update(labels: [Label]) { diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index b0aa92c7d..b77a3bd49 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -42,7 +42,7 @@ final class LabelViewController: UIViewController { labelTableDatasource = LabelTableViewDatasource() labelTableView.dataSource = labelTableDatasource - labelTableDelegate = LabelTableDelegate() + labelTableDelegate = LabelTableDelegate(cellActionHandler: swipeActionHandler) labelTableView.delegate = labelTableDelegate setNetworkManager() @@ -68,17 +68,42 @@ final class LabelViewController: UIViewController { ]) } + private func swipeActionHandler(_ index: Int, _ action: CellAction) { + guard let targetId = labelTableDatasource?.labels[index].id else { return } + + switch action { + case .delete: + deleteLabel(for: targetId) + case .edit: + print("수정") + default: + assert(false) + } + } + + private func deleteLabel(for id: Int) { + let deleteLabelEndpoint = EndPoint.label.path(with: id) + networkManager?.delete(endpoint: deleteLabelEndpoint, queryParameters: nil, completion: { (result: Result) in + switch result { + case .success(_): + self.loadData() + case .failure(let error): + self.presentAlert(with: error.description) + } + }) + } + private func setNetworkManager() { let loginInfo = LoginInfo.shared guard let jwt = loginInfo.jwt else { return } - let url = EndPoint.label.fullAddress() let headers = [Header.authorization.key(): jwt.description] - let requestManager = RequestManager(url: url, headers: headers) - networkManager = NetworkManager(requestManager: requestManager) + networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) } func loadData() { - networkManager?.get(queryParameters: nil, completion: { [weak self] (result: Result) in + let labelListEndpoint = EndPoint.label.path() + networkManager?.get(endpoint: labelListEndpoint, queryParameters: nil, + completion: { [weak self] (result: Result) in switch result { case .success(let result): guard let labels = result.data else { return } From 1890fa29f269f4c0ba6d437f194e057788818cbb Mon Sep 17 00:00:00 2001 From: Song Lee Date: Fri, 18 Jun 2021 12:07:09 +0900 Subject: [PATCH 40/91] =?UTF-8?q?feat:=20[#73]=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=88=98=EC=A0=95=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 새 레이블 추가 / 기존 레이블 수정 View Controller의 중복 코드를 SuperClass로 두고 각각 SubClassing함 - 코드 재사용성 극대화를 위해 위와 같이 수정 --- .../issue-tracker.xcodeproj/project.pbxproj | 8 + .../Controller/AddLabelViewController.swift | 273 +---------------- .../Controller/EditLabelViewController.swift | 49 +++ .../LabelControlViewController.swift | 285 ++++++++++++++++++ .../Controller/LabelViewController.swift | 34 ++- .../Network/NetworkManager.swift | 6 + 6 files changed, 377 insertions(+), 278 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Controller/EditLabelViewController.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 3ba9b7f60..0c8236837 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -44,6 +44,8 @@ E43912EA267A2351003CD344 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E9267A2351003CD344 /* NetworkError.swift */; }; E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912EB267B1A4E003CD344 /* LoginInfoDTO.swift */; }; E43912EE267C3C0E003CD344 /* CellAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912ED267C3C0E003CD344 /* CellAction.swift */; }; + E43912F0267C3EED003CD344 /* LabelControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912EF267C3EED003CD344 /* LabelControlViewController.swift */; }; + E43912F2267C423A003CD344 /* EditLabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F1267C423A003CD344 /* EditLabelViewController.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -96,6 +98,8 @@ E43912E9267A2351003CD344 /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; }; E43912EB267B1A4E003CD344 /* LoginInfoDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginInfoDTO.swift; sourceTree = ""; }; E43912ED267C3C0E003CD344 /* CellAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellAction.swift; sourceTree = ""; }; + E43912EF267C3EED003CD344 /* LabelControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelControlViewController.swift; sourceTree = ""; }; + E43912F1267C423A003CD344 /* EditLabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditLabelViewController.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -301,7 +305,9 @@ E42AD11F267093430071B436 /* LabelViewController.swift */, E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */, E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */, + E43912EF267C3EED003CD344 /* LabelControlViewController.swift */, E43912E32679C0DA003CD344 /* AddLabelViewController.swift */, + E43912F1267C423A003CD344 /* EditLabelViewController.swift */, ); path = Controller; sourceTree = ""; @@ -431,6 +437,7 @@ E426DABC2670EC5E0069E77D /* LoginInfo.swift in Sources */, E43912CE26777310003CD344 /* HexColorConverter.swift in Sources */, E42AD1182670886F0071B436 /* IssueTrackerTabBarController.swift in Sources */, + E43912F0267C3EED003CD344 /* LabelControlViewController.swift in Sources */, E43912DE2678A76D003CD344 /* RequestKeys.swift in Sources */, E42AD102266E52FB0071B436 /* LoginViewController.swift in Sources */, E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */, @@ -460,6 +467,7 @@ E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */, E42AD11E267093320071B436 /* IssueViewController.swift in Sources */, E43912E42679C0DA003CD344 /* AddLabelViewController.swift in Sources */, + E43912F2267C423A003CD344 /* EditLabelViewController.swift in Sources */, E43912DC2678A737003CD344 /* JWT.swift in Sources */, E43912E22678AEB3003CD344 /* LabelTableDelegate.swift in Sources */, E426DABA2670EC2D0069E77D /* AppleAuthorizationManager.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift index 370c62e01..dd9a6db1e 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift @@ -7,233 +7,14 @@ import UIKit -final class AddLabelViewController: UIViewController { - - private lazy var topMenuView: UIView = { - let container = UIView() - container.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(saveButton) - NSLayoutConstraint.activate([ - saveButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), - saveButton.widthAnchor.constraint(greaterThanOrEqualToConstant: spacing * 2), - saveButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), - saveButton.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing) - ]) - - container.addSubview(cancelButton) - NSLayoutConstraint.activate([ - cancelButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), - cancelButton.widthAnchor.constraint(greaterThanOrEqualToConstant: spacing * 2), - cancelButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), - cancelButton.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing) - ]) - - let titleLabel = UILabel() - titleLabel.text = sceneTitle - titleLabel.font = .systemFont(ofSize: 18, weight: .bold) - titleLabel.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.centerXAnchor.constraint(equalTo: container.centerXAnchor), - titleLabel.centerYAnchor.constraint(equalTo: container.centerYAnchor) - ]) - return container - }() - - private lazy var cancelButton: ImageBarButton = { - let button = ImageBarButton() - button.configure(with: "chevron.backward", "취소") - button.moveImageToLeft() - button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(cancelButtonTouched), for: .touchUpInside) - return button - }() - - private lazy var saveButton: ImageBarButton = { - let button = ImageBarButton() - button.configure(with: "", "저장") - button.isEnabled = false - button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(saveButtonTouched), for: .touchUpInside) - return button - }() - - private lazy var newLabelEditStackView: UIStackView = { - let viewWidth = view.frame.width - let stackViewFrame = CGRect(x: 0, y: 0, width: viewWidth, height: singleLineHeight * 3) - let stackView = UIStackView(frame: stackViewFrame) - stackView.backgroundColor = UIColor.white - stackView.axis = .vertical - stackView.distribution = .fillEqually - stackView.translatesAutoresizingMaskIntoConstraints = false - - let categories = ["제목", "설명", "배경색"] - let contentViews: [UIView] = [titleTextfield, descriptionTextfield, backgroundLabel] - - categories.enumerated().forEach { (idx, category) in - let containerFrame = CGRect(x: 0, y: 0, width: viewWidth, height: singleLineHeight) - let container = UIView(frame: containerFrame) - - let titleLabel = UILabel() - titleLabel.text = category - titleLabel.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing), - titleLabel.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) - ]) - - let contentView = contentViews[idx] - contentView.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(contentView) - NSLayoutConstraint.activate([ - contentView.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing * 5), - contentView.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), - contentView.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) - ]) - stackView.addArrangedSubview(container) - } - guard let backgroundEditView = stackView.arrangedSubviews.last else { return stackView } - - backgroundEditView.addSubview(randomColorButton) - NSLayoutConstraint.activate([ - randomColorButton.widthAnchor.constraint(equalToConstant: singleLineHeight * 0.9), - randomColorButton.heightAnchor.constraint(equalTo: randomColorButton.safeAreaLayoutGuide.widthAnchor), - randomColorButton.trailingAnchor.constraint(equalTo: backgroundEditView.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), - randomColorButton.centerYAnchor.constraint(equalTo: backgroundEditView.safeAreaLayoutGuide.centerYAnchor) - ]) - return stackView - }() - - private lazy var titleTextfield: UITextField = { - let textField = UITextField() - textField.placeholder = "(필수 입력)" - return textField - }() - - private lazy var descriptionTextfield: UITextField = { - let textField = UITextField() - textField.placeholder = "(선택 사항)" - return textField - }() - - private lazy var backgroundLabel: UILabel = { - let label = UILabel() - label.text = "#000000" - return label - }() - - private lazy var randomColorButton: UIButton = { - let button = UIButton() - let refreshImage = UIImage(systemName: "arrow.clockwise") - button.setImage(refreshImage, for: .normal) - button.tintColor = UIColor.black - button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(randomColorButtonTouched), for: .touchUpInside) - return button - }() - - private lazy var previewLabel: LabelView = { - let labelView = LabelView() - labelView.configure(with: UIColor.black, UIColor.white, "레이블") - labelView.translatesAutoresizingMaskIntoConstraints = false - return labelView - }() - - private lazy var singleLineHeight: CGFloat = { - return view.frame.height * 0.05 - }() - - private lazy var spacing: CGFloat = { - return singleLineHeight * 0.5 - }() - - private var loginInfo: LoginInfo? - private let sceneTitle = "새로운 레이블" - private let colorConverter: HexColorConvertable = HexColorConverter() - private var networkManager: NetworkManagerOperations? - private var dismissOperation: (() -> Void)? - - override func viewDidLoad() { - super.viewDidLoad() - view.backgroundColor = Colors.background - - addTopMenu() - addEditStackView() - addLabelPreview() - setNetworkManager() - titleTextfield.delegate = self - } - - private func addTopMenu() { - view.addSubview(topMenuView) - - NSLayoutConstraint.activate([ - topMenuView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), - topMenuView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), - topMenuView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: spacing), - topMenuView.heightAnchor.constraint(equalToConstant: singleLineHeight) - ]) - } - - private func addEditStackView() { - view.addSubview(newLabelEditStackView) - - NSLayoutConstraint.activate([ - newLabelEditStackView.heightAnchor.constraint(equalToConstant: singleLineHeight * 3), - newLabelEditStackView.topAnchor.constraint(equalTo: topMenuView.safeAreaLayoutGuide.bottomAnchor, constant: 40), - newLabelEditStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), - newLabelEditStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) - ]) - addLoginStackViewDivisionLine() - } - - private func addLoginStackViewDivisionLine() { - let borderColor = Colors.border.cgColor - let borderWidth: CGFloat = 1 - let size = CGSize(width: view.frame.width - spacing, height: borderWidth) - - for i in 1...2 { - let line = CALayer() - let origin = CGPoint(x: spacing, y: singleLineHeight * CGFloat(i) - borderWidth) - line.frame = CGRect(origin: origin, size: size) - line.backgroundColor = borderColor - newLabelEditStackView.layer.addSublayer(line) - } - } - - private func addLabelPreview() { - let backgroundView = UIView() - backgroundView.backgroundColor = UIColor.systemGray5 - backgroundView.layer.cornerRadius = view.frame.width * 0.07 - backgroundView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(backgroundView) - backgroundView.addSubview(previewLabel) - NSLayoutConstraint.activate([ - backgroundView.widthAnchor.constraint(equalToConstant: view.frame.width - spacing * 2), - backgroundView.heightAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.widthAnchor, multiplier: 0.75), - backgroundView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), - backgroundView.topAnchor.constraint(equalTo: newLabelEditStackView.safeAreaLayoutGuide.bottomAnchor, constant: 24), - previewLabel.centerXAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.centerXAnchor), - previewLabel.centerYAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.centerYAnchor) - ]) - } - - func setUpDismissOperation(_ operation: @escaping () -> Void) { - self.dismissOperation = operation - } - - @objc private func cancelButtonTouched(_ sender: UIBarButtonItem) { - dismiss(animated: true, completion: nil) - } - - @objc private func saveButtonTouched(_ sender: UIBarButtonItem) { +final class AddLabelViewController: LabelControlViewController { + override func saveButtonTouched(_ sender: UIBarButtonItem) { + super.saveButtonTouched(sender) guard let labelTitle = titleTextfield.text, let colorCode = backgroundLabel.text else { return } let newLabel = NewLabelDTO(name: labelTitle, content: descriptionTextfield.text ?? "", colorCode: colorCode) - postNewLabel(newLabel) } @@ -251,52 +32,4 @@ final class AddLabelViewController: UIViewController { } }) } - - private func presentAlert(with errorMessage: String) { - DispatchQueue.main.async { - let alert = AlertFactory.create(body: errorMessage) - self.present(alert, animated: true, completion: nil) - } - } - - @objc private func randomColorButtonTouched(_ sender: UIButton) { - let hexColor = randomColor() - backgroundLabel.text = hexColor - changePreviewLabel(with: hexColor) - } - - private func randomColor() -> String { - let colorRange = 0...255 - let randomRed = Int.random(in: colorRange) - let randomGreen = Int.random(in: colorRange) - let randomBlue = Int.random(in: colorRange) - - let hexRed = String(randomRed, radix: 16) - let hexGreen = String(randomGreen, radix: 16) - let hexBlue = String(randomBlue, radix: 16) - return "#\(hexRed)\(hexGreen)\(hexBlue)" - } - - private func changePreviewLabel(with hexColorString: String) { - let hex = HexColorCode(from: hexColorString) - let backgroundColor = colorConverter.convertHex(hex) - let titleColor = colorConverter.isColorDark(hex: hex) ? UIColor.white : UIColor.black - previewLabel.configure(with: backgroundColor, titleColor, nil) - } - - private func setNetworkManager() { - let loginInfo = LoginInfo.shared - guard let jwt = loginInfo.jwt else { return } - let headers = [Header.authorization.key(): jwt.description] - networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) - } -} - -extension AddLabelViewController: UITextFieldDelegate { - func textFieldDidChangeSelection(_ textField: UITextField) { - guard let text = textField.text else { return } - DispatchQueue.main.async { - self.saveButton.isEnabled = text.count > 0 - } - } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/EditLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/EditLabelViewController.swift new file mode 100644 index 000000000..beaf84e7f --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/EditLabelViewController.swift @@ -0,0 +1,49 @@ +// +// EditLabelViewController.swift +// issue-tracker +// +// Created by Song on 2021/06/18. +// + +import UIKit + +class EditLabelViewController: LabelControlViewController { + + private var labelToEdit: Label? + + func setLabelToEdit(label: Label) { + self.labelToEdit = label + + titleTextfield.text = label.title + descriptionTextfield.text = label.body + backgroundLabel.text = label.hexColorCode + } + + override func saveButtonTouched(_ sender: UIBarButtonItem) { + super.saveButtonTouched(sender) + guard let labelTitle = titleTextfield.text, let colorCode = backgroundLabel.text else { return } + + let editedLabel = NewLabelDTO(name: labelTitle, + content: descriptionTextfield.text ?? "", + colorCode: colorCode) + putLabel(editedLabel) + } + + private func putLabel(_ editedLabel: NewLabelDTO) { + guard let labelId = labelToEdit?.id else { return } + let editLabelEndpoint = EndPoint.label.path(with: labelId) + + networkManager?.put(endpoint: editLabelEndpoint, requestBody: editedLabel, completion: { [weak self] result in + switch result { + case .success(_): + self?.dismiss(animated: true, completion: { + guard let dismissOperation = self?.dismissOperation else { return } + dismissOperation() + }) + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } + +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift new file mode 100644 index 000000000..a2421d86f --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift @@ -0,0 +1,285 @@ +// +// LabelControlViewController.swift +// issue-tracker +// +// Created by Song on 2021/06/18. +// + +import UIKit + +class LabelControlViewController: UIViewController { + + private lazy var topMenuView: UIView = { + let container = UIView() + container.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(saveButton) + NSLayoutConstraint.activate([ + saveButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), + saveButton.widthAnchor.constraint(greaterThanOrEqualToConstant: spacing * 2), + saveButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), + saveButton.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing) + ]) + + container.addSubview(cancelButton) + NSLayoutConstraint.activate([ + cancelButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), + cancelButton.widthAnchor.constraint(greaterThanOrEqualToConstant: spacing * 2), + cancelButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), + cancelButton.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing) + ]) + + let titleLabel = UILabel() + titleLabel.text = sceneTitle + titleLabel.font = .systemFont(ofSize: 18, weight: .bold) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.centerXAnchor.constraint(equalTo: container.centerXAnchor), + titleLabel.centerYAnchor.constraint(equalTo: container.centerYAnchor) + ]) + return container + }() + + private lazy var cancelButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "chevron.backward", "취소") + button.moveImageToLeft() + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(cancelButtonTouched), for: .touchUpInside) + return button + }() + + private lazy var saveButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "", "저장") + button.isEnabled = false + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(saveButtonTouched), for: .touchUpInside) + return button + }() + + private lazy var newLabelEditStackView: UIStackView = { + let viewWidth = view.frame.width + let stackViewFrame = CGRect(x: 0, y: 0, width: viewWidth, height: singleLineHeight * 3) + let stackView = UIStackView(frame: stackViewFrame) + stackView.backgroundColor = UIColor.white + stackView.axis = .vertical + stackView.distribution = .fillEqually + stackView.translatesAutoresizingMaskIntoConstraints = false + + let categories = ["제목", "설명", "배경색"] + let contentViews: [UIView] = [titleTextfield, descriptionTextfield, backgroundLabel] + + categories.enumerated().forEach { (idx, category) in + let containerFrame = CGRect(x: 0, y: 0, width: viewWidth, height: singleLineHeight) + let container = UIView(frame: containerFrame) + + let titleLabel = UILabel() + titleLabel.text = category + titleLabel.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing), + titleLabel.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) + ]) + + let contentView = contentViews[idx] + contentView.translatesAutoresizingMaskIntoConstraints = false + container.addSubview(contentView) + NSLayoutConstraint.activate([ + contentView.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing * 5), + contentView.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), + contentView.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) + ]) + stackView.addArrangedSubview(container) + } + guard let backgroundEditView = stackView.arrangedSubviews.last else { return stackView } + + backgroundEditView.addSubview(randomColorButton) + NSLayoutConstraint.activate([ + randomColorButton.widthAnchor.constraint(equalToConstant: singleLineHeight * 0.9), + randomColorButton.heightAnchor.constraint(equalTo: randomColorButton.safeAreaLayoutGuide.widthAnchor), + randomColorButton.trailingAnchor.constraint(equalTo: backgroundEditView.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), + randomColorButton.centerYAnchor.constraint(equalTo: backgroundEditView.safeAreaLayoutGuide.centerYAnchor) + ]) + return stackView + }() + + lazy var titleTextfield: UITextField = { + let textField = UITextField() + textField.placeholder = "(필수 입력)" + return textField + }() + + lazy var descriptionTextfield: UITextField = { + let textField = UITextField() + textField.placeholder = "(선택 사항)" + return textField + }() + + lazy var backgroundLabel: UILabel = { + let label = UILabel() + label.text = "#000000" + return label + }() + + private lazy var randomColorButton: UIButton = { + let button = UIButton() + let refreshImage = UIImage(systemName: "arrow.clockwise") + button.setImage(refreshImage, for: .normal) + button.tintColor = UIColor.black + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(randomColorButtonTouched), for: .touchUpInside) + return button + }() + + private lazy var previewLabel: LabelView = { + let labelView = LabelView() + labelView.configure(with: UIColor.black, UIColor.white, "레이블") + labelView.translatesAutoresizingMaskIntoConstraints = false + return labelView + }() + + private lazy var singleLineHeight: CGFloat = { + return view.frame.height * 0.05 + }() + + private lazy var spacing: CGFloat = { + return singleLineHeight * 0.5 + }() + + private var loginInfo: LoginInfo? + var sceneTitle: String? + + private let colorConverter: HexColorConvertable = HexColorConverter() + var networkManager: NetworkManagerOperations? + var dismissOperation: (() -> Void)? + + override func viewDidLoad() { + super.viewDidLoad() + view.backgroundColor = Colors.background + + addTopMenu() + addEditStackView() + addLabelPreview() + setNetworkManager() + titleTextfield.delegate = self + } + + private func addTopMenu() { + view.addSubview(topMenuView) + + NSLayoutConstraint.activate([ + topMenuView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + topMenuView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + topMenuView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: spacing), + topMenuView.heightAnchor.constraint(equalToConstant: singleLineHeight) + ]) + } + + private func addEditStackView() { + view.addSubview(newLabelEditStackView) + + NSLayoutConstraint.activate([ + newLabelEditStackView.heightAnchor.constraint(equalToConstant: singleLineHeight * 3), + newLabelEditStackView.topAnchor.constraint(equalTo: topMenuView.safeAreaLayoutGuide.bottomAnchor, constant: 40), + newLabelEditStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + newLabelEditStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) + ]) + addLoginStackViewDivisionLine() + } + + private func addLoginStackViewDivisionLine() { + let borderColor = Colors.border.cgColor + let borderWidth: CGFloat = 1 + let size = CGSize(width: view.frame.width - spacing, height: borderWidth) + + for i in 1...2 { + let line = CALayer() + let origin = CGPoint(x: spacing, y: singleLineHeight * CGFloat(i) - borderWidth) + line.frame = CGRect(origin: origin, size: size) + line.backgroundColor = borderColor + newLabelEditStackView.layer.addSublayer(line) + } + } + + private func addLabelPreview() { + let backgroundView = UIView() + backgroundView.backgroundColor = UIColor.systemGray5 + backgroundView.layer.cornerRadius = view.frame.width * 0.07 + backgroundView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(backgroundView) + backgroundView.addSubview(previewLabel) + NSLayoutConstraint.activate([ + backgroundView.widthAnchor.constraint(equalToConstant: view.frame.width - spacing * 2), + backgroundView.heightAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.widthAnchor, multiplier: 0.75), + backgroundView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), + backgroundView.topAnchor.constraint(equalTo: newLabelEditStackView.safeAreaLayoutGuide.bottomAnchor, constant: 24), + previewLabel.centerXAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.centerXAnchor), + previewLabel.centerYAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.centerYAnchor) + ]) + } + + func setSceneTitle(title: String) { + self.sceneTitle = title + } + + func setUpDismissOperation(_ operation: @escaping () -> Void) { + self.dismissOperation = operation + } + + @objc private func cancelButtonTouched(_ sender: UIBarButtonItem) { + dismiss(animated: true, completion: nil) + } + + ///이 메소드를 오버라이드하여 레이블 생성 or 수정 구현 + @objc func saveButtonTouched(_ sender: UIBarButtonItem) { } + + func presentAlert(with errorMessage: String) { + DispatchQueue.main.async { + let alert = AlertFactory.create(body: errorMessage) + self.present(alert, animated: true, completion: nil) + } + } + + @objc private func randomColorButtonTouched(_ sender: UIButton) { + let hexColor = randomColor() + backgroundLabel.text = hexColor + changePreviewLabel(with: hexColor) + } + + private func randomColor() -> String { + let colorRange = 0...255 + let randomRed = Int.random(in: colorRange) + let randomGreen = Int.random(in: colorRange) + let randomBlue = Int.random(in: colorRange) + + let hexRed = String(randomRed, radix: 16) + let hexGreen = String(randomGreen, radix: 16) + let hexBlue = String(randomBlue, radix: 16) + return "#\(hexRed)\(hexGreen)\(hexBlue)" + } + + private func changePreviewLabel(with hexColorString: String) { + let hex = HexColorCode(from: hexColorString) + let backgroundColor = colorConverter.convertHex(hex) + let titleColor = colorConverter.isColorDark(hex: hex) ? UIColor.white : UIColor.black + previewLabel.configure(with: backgroundColor, titleColor, nil) + } + + private func setNetworkManager() { + let loginInfo = LoginInfo.shared + guard let jwt = loginInfo.jwt else { return } + let headers = [Header.authorization.key(): jwt.description] + networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) + } +} + +extension LabelControlViewController: UITextFieldDelegate { + func textFieldDidChangeSelection(_ textField: UITextField) { + guard let text = textField.text else { return } + DispatchQueue.main.async { + self.saveButton.isEnabled = text.count > 0 + } + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index b77a3bd49..fe26b8814 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -69,13 +69,13 @@ final class LabelViewController: UIViewController { } private func swipeActionHandler(_ index: Int, _ action: CellAction) { - guard let targetId = labelTableDatasource?.labels[index].id else { return } + guard let targetLabel = labelTableDatasource?.labels[index] else { return } switch action { case .delete: - deleteLabel(for: targetId) + deleteLabel(for: targetLabel.id) case .edit: - print("수정") + presentEditLabelViewController(for: targetLabel) default: assert(false) } @@ -83,16 +83,30 @@ final class LabelViewController: UIViewController { private func deleteLabel(for id: Int) { let deleteLabelEndpoint = EndPoint.label.path(with: id) - networkManager?.delete(endpoint: deleteLabelEndpoint, queryParameters: nil, completion: { (result: Result) in + networkManager?.delete(endpoint: deleteLabelEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in switch result { case .success(_): - self.loadData() + self?.loadData() case .failure(let error): - self.presentAlert(with: error.description) + self?.presentAlert(with: error.description) } }) } + private func presentEditLabelViewController(for targetLabel: Label) { + let editLabelViewController = EditLabelViewController() + editLabelViewController.setSceneTitle(title: "레이블 수정하기") + editLabelViewController.setLabelToEdit(label: targetLabel) + editLabelViewController.modalPresentationStyle = .formSheet + editLabelViewController.setUpDismissOperation { [weak self] in + self?.loadData() + } + + DispatchQueue.main.async { + self.present(editLabelViewController, animated: true, completion: nil) + } + } + private func setNetworkManager() { let loginInfo = LoginInfo.shared guard let jwt = loginInfo.jwt else { return } @@ -129,12 +143,16 @@ final class LabelViewController: UIViewController { } @objc private func addLabelTouched(_ sender: UIButton) { - let addLabelViewController = AddLabelViewController() + let addLabelViewController = AddLabelViewController() + addLabelViewController.setSceneTitle(title: "새로운 레이블") addLabelViewController.modalPresentationStyle = .formSheet addLabelViewController.setUpDismissOperation { [weak self] in self?.loadData() } - present(addLabelViewController, animated: true, completion: nil) + + DispatchQueue.main.async { + self.present(addLabelViewController, animated: true, completion: nil) + } } } diff --git a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift index 6faed6ba9..34fa2a837 100644 --- a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift +++ b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift @@ -12,6 +12,7 @@ protocol NetworkManagerOperations { func get(endpoint: String, queryParameters: [String: Any]?, completion: @escaping (Result) -> Void) func delete(endpoint: String, queryParameters: [String: Any]?, completion: @escaping (Result) -> Void) func post(endpoint: String, requestBody: T, completion: @escaping (Result) -> Void) + func put(endpoint: String, requestBody: T, completion: @escaping (Result) -> Void) } final class NetworkManager: NetworkManagerOperations { @@ -48,6 +49,11 @@ final class NetworkManager: NetworkManagerOperations { executeVoidRequest(request: request, completion: completion) } + func put(endpoint: String, requestBody: T, completion: @escaping (Result) -> Void) { + let request = requestManager.create(endpoint: endpoint, method: .put, encodableParameters: requestBody) + executeVoidRequest(request: request, completion: completion) + } + private func executeVoidRequest(request: DataRequest, completion: @escaping (Result) -> Void) { request.response { [weak self] response in switch response.result { From f58181e777bb6273d228597e0806b1b99cbabc3b Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Fri, 18 Jun 2021 12:08:44 +0900 Subject: [PATCH 41/91] =?UTF-8?q?feat:=20[#68]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20=EB=84=A4=ED=8A=B8=EC=9B=8C=ED=81=AC=20GET?= =?UTF-8?q?=ED=86=B5=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 12 ++ .../OpenMileStoneBG.colorset/Contents.json | 38 +++++ .../closeMileStoneBG.colorset/Contents.json | 38 +++++ .../closeMileStoneTint.colorset/Contents.json | 38 +++++ .../openMileStoneTint.colorset/Contents.json | 38 +++++ .../issue-tracker/Common/Colors.swift | 5 +- .../Controller/MileStoneTableDelegate.swift | 13 ++ .../MilestoneTableViewDataSource.swift | 31 ++++ .../Controller/MilestoneViewController.swift | 63 ++++--- .../Main/Milestone/Model/Milestone.swift | 34 ++++ .../View/MileStoneTableViewCell.swift | 158 +++++++++++++----- 11 files changed, 410 insertions(+), 58 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Assets.xcassets/OpenMileStoneBG.colorset/Contents.json create mode 100644 iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneBG.colorset/Contents.json create mode 100644 iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneTint.colorset/Contents.json create mode 100644 iOS/issue-tracker/issue-tracker/Assets.xcassets/openMileStoneTint.colorset/Contents.json create mode 100644 iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index e64f99460..59c4090bd 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -47,6 +47,9 @@ E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; + FA733A2E267C3D77005A40C8 /* Milestone.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A2D267C3D77005A40C8 /* Milestone.swift */; }; + FA733A30267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A2F267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift */; }; + FA733A32267C3EAA005A40C8 /* MileStoneTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A31267C3EAA005A40C8 /* MileStoneTableDelegate.swift */; }; FAB2C36A26789D41009F879C /* MileStoneTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB2C36926789D40009F879C /* MileStoneTableViewCell.swift */; }; FAB2C36C2679F6CC009F879C /* MileStoneLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB2C36B2679F6CC009F879C /* MileStoneLabelView.swift */; }; FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC6D88A2671D5A100A9E5F9 /* GithubAuthorizationManager.swift */; }; @@ -100,6 +103,9 @@ E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; + FA733A2D267C3D77005A40C8 /* Milestone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Milestone.swift; sourceTree = ""; }; + FA733A2F267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MilestoneTableViewDataSource.swift; sourceTree = ""; }; + FA733A31267C3EAA005A40C8 /* MileStoneTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneTableDelegate.swift; sourceTree = ""; }; FAB2C36926789D40009F879C /* MileStoneTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneTableViewCell.swift; sourceTree = ""; }; FAB2C36B2679F6CC009F879C /* MileStoneLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneLabelView.swift; sourceTree = ""; }; FAC6D88A2671D5A100A9E5F9 /* GithubAuthorizationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GithubAuthorizationManager.swift; sourceTree = ""; }; @@ -333,6 +339,7 @@ FAB2C36626789ADD009F879C /* Model */ = { isa = PBXGroup; children = ( + FA733A2D267C3D77005A40C8 /* Milestone.swift */, ); path = Model; sourceTree = ""; @@ -349,6 +356,8 @@ isa = PBXGroup; children = ( E42AD121267093590071B436 /* MilestoneViewController.swift */, + FA733A2F267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift */, + FA733A31267C3EAA005A40C8 /* MileStoneTableDelegate.swift */, ); path = Controller; sourceTree = ""; @@ -475,9 +484,11 @@ E42AD124267093700071B436 /* MyAccountViewController.swift in Sources */, FAEB30AC266F5E9700C17BE9 /* Colors.swift in Sources */, E43912C726776D8F003CD344 /* LabelView.swift in Sources */, + FA733A32267C3EAA005A40C8 /* MileStoneTableDelegate.swift in Sources */, E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */, E43912EA267A2351003CD344 /* NetworkError.swift in Sources */, E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */, + FA733A2E267C3D77005A40C8 /* Milestone.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */, E426DAC22671B1C60069E77D /* LoginKeyChainManager.swift in Sources */, @@ -490,6 +501,7 @@ E42AD120267093430071B436 /* LabelViewController.swift in Sources */, E43912D826789A83003CD344 /* EndPoint.swift in Sources */, E426DABE2670EC830069E77D /* SocialLoginManagerDelegate.swift in Sources */, + FA733A30267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift in Sources */, E42AD0FE266E52FB0071B436 /* AppDelegate.swift in Sources */, E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */, FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Assets.xcassets/OpenMileStoneBG.colorset/Contents.json b/iOS/issue-tracker/issue-tracker/Assets.xcassets/OpenMileStoneBG.colorset/Contents.json new file mode 100644 index 000000000..4f0dc6688 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Assets.xcassets/OpenMileStoneBG.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.922", + "red" : "0.780" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.922", + "red" : "0.780" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneBG.colorset/Contents.json b/iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneBG.colorset/Contents.json new file mode 100644 index 000000000..0cb94da62 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneBG.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.831", + "red" : "0.800" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.831", + "red" : "0.800" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneTint.colorset/Contents.json b/iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneTint.colorset/Contents.json new file mode 100644 index 000000000..85ef47f86 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneTint.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.906", + "green" : "0.145", + "red" : "0.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.906", + "green" : "0.145", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/issue-tracker/issue-tracker/Assets.xcassets/openMileStoneTint.colorset/Contents.json b/iOS/issue-tracker/issue-tracker/Assets.xcassets/openMileStoneTint.colorset/Contents.json new file mode 100644 index 000000000..805e83152 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Assets.xcassets/openMileStoneTint.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.478", + "red" : "0.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.478", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/issue-tracker/issue-tracker/Common/Colors.swift b/iOS/issue-tracker/issue-tracker/Common/Colors.swift index b0d0b5f94..4721a689e 100644 --- a/iOS/issue-tracker/issue-tracker/Common/Colors.swift +++ b/iOS/issue-tracker/issue-tracker/Common/Colors.swift @@ -16,5 +16,8 @@ enum Colors { static let mainGrape = UIColor(named: "MainGrape") ?? UIColor.purple static let mileStoneSuceess = UIColor(named: "MileStoneSuccess") ?? UIColor.green static let description = UIColor(named: "Description") ?? UIColor.systemGray2 - + static let openMileStoneTint = UIColor(named: "OpenMileStoneTint") ?? UIColor.black + static let openMileStoneBG = UIColor(named: "OpenMileStoneBG") ?? UIColor.purple + static let closeMileStoneTint = UIColor(named: "CloseMileStoneTint") ?? UIColor.black + static let closeMileStoneBG = UIColor(named: "CloseMileStoneBG") ?? UIColor.blue } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift new file mode 100644 index 000000000..bc46708e7 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift @@ -0,0 +1,13 @@ +// +// MileStoneTableDelegate.swift +// issue-tracker +// +// Created by jinseo park on 6/18/21. +// +import UIKit + +class MileStoneTableDelegate: NSObject, UITableViewDelegate { + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return tableView.frame.height * 0.336 + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift new file mode 100644 index 000000000..f1b52753d --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift @@ -0,0 +1,31 @@ +// +// MilestoneTableViewDataSource.swift +// issue-tracker +// +// Created by jinseo park on 6/18/21. +// + +import UIKit + +class MilestoneTableViewDataSource: NSObject, UITableViewDataSource { + + private var milestones = [MileStone]() + + func update(milestones: [MileStone]) { + self.milestones = milestones + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return milestones.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cellID = MileStoneTableViewCell.reuseID + let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? MileStoneTableViewCell ?? MileStoneTableViewCell() + + let milesonte = milestones[indexPath.row] + + cell.configure(title: milesonte.title, description: milesonte.description, due_date: milesonte.due_date) + return cell + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift index 82cc48b49..3d0c48bbc 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift @@ -30,7 +30,9 @@ class MilestoneViewController: UIViewController { print("마일스톤 추가해줘잉") } - private var loginInfo: LoginInfo? + private var networkManager: NetworkManagerOperations? + private var mileStoneTableDatasource: MilestoneTableViewDataSource? + private var mileStoneTableDelegate: MileStoneTableDelegate? override func viewDidLoad() { super.viewDidLoad() @@ -39,8 +41,17 @@ class MilestoneViewController: UIViewController { addNavigationButton() addTableView() - mileStoneTableView.dataSource = self - mileStoneTableView.delegate = self + mileStoneTableDatasource = MilestoneTableViewDataSource() + mileStoneTableDelegate = MileStoneTableDelegate() + mileStoneTableView.dataSource = mileStoneTableDatasource + mileStoneTableView.delegate = mileStoneTableDelegate + + setNetworkManager() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + loadData() } private func addNavigationButton() { @@ -57,24 +68,38 @@ class MilestoneViewController: UIViewController { mileStoneTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) } -} - - -extension MilestoneViewController: UITableViewDelegate { - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return view.frame.height * 0.336 + + private func setNetworkManager() { + let loginInfo = LoginInfo.shared + guard let jwt = loginInfo.jwt else { return } + let url = EndPoint.milestone.fullAddress() + let headers = [Header.authorization.key(): jwt.description] + let requestManager = RequestManager(url: url, headers: headers) + networkManager = NetworkManager(requestManager: requestManager) } -} - -extension MilestoneViewController: UITableViewDataSource { - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 3 + + func loadData() { + networkManager?.get(queryParameters: nil, completion: { [weak self] (result: Result) in + switch result { + case .success(let result): + guard let mileStone = result.data else { return } + self?.mileStoneTableDatasource?.update(milestones: mileStone) + self?.reloadTableView() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } + private func presentAlert(with errorMessage: String) { + DispatchQueue.main.async { + let alert = AlertFactory.create(body: errorMessage) + self.present(alert, animated: true, completion: nil) + } } - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cellID = MileStoneTableViewCell.reuseID - let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? MileStoneTableViewCell ?? MileStoneTableViewCell() - - return cell + private func reloadTableView() { + DispatchQueue.main.async { + self.mileStoneTableView.reloadData() + } } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift new file mode 100644 index 000000000..2db0ca783 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift @@ -0,0 +1,34 @@ +// +// Milestone.swift +// issue-tracker +// +// Created by jinseo park on 6/18/21. +// + +import Foundation + + +struct MileStoneDTO: Decodable { + let data: [MileStone]? + let message: String? + + enum CodingKeys: String, CodingKey { + case data + case message = "msg" + } +} + +struct MileStone: Decodable { + let id: Int + let title: String + let description: String + let due_date: String + + enum CodingKeys: String, CodingKey { + case id + case title + case description + case due_date + } + +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index afb1366ec..6975148f5 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -10,16 +10,16 @@ import UIKit class MileStoneTableViewCell: UITableViewCell { private let spacing: CGFloat = 16 -// -// mileStoneStackView스택을 만들고 -// 1 : sub스택 -// -1 Title 라벨 -// -2 몇 %인지 보이는 두개의 라벨 -// 2 : 마일스톤에 대한 설명 라벨 -// 3 : 데이트 라벨 -// 4 : sub스택 -// -1 열린 이슈 라벨 -// -2 닫힌 이슈 라벨 + // + // mileStoneStackView스택을 만들고 + // 1 : sub스택 + // -1 Title 라벨 + // -2 몇 %인지 보이는 두개의 라벨 + // 2 : 마일스톤에 대한 설명 라벨 + // 3 : 데이트 라벨 + // 4 : sub스택 + // -1 열린 이슈 라벨 + // -2 닫힌 이슈 라벨 private lazy var mileStoneStackView: UIStackView = { let superStackView = UIStackView() //커다란 SuperStack @@ -30,6 +30,9 @@ class MileStoneTableViewCell: UITableViewCell { return superStackView }() + //MARK: 1 : sub스택 + // -1 Title 라벨 + // -2 몇 %인지 보이는 두개의 라벨 private lazy var firstSubStackView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal @@ -38,14 +41,6 @@ class MileStoneTableViewCell: UITableViewCell { return stackView }() - private lazy var secondSubStackView: UIStackView = { - let stackView = UIStackView() - stackView.axis = .horizontal - stackView.distribution = .fillEqually - stackView.translatesAutoresizingMaskIntoConstraints = false - return stackView - }() - private lazy var titleLabel: UILabel = { let label = UILabel() label.text = "제목" @@ -61,6 +56,7 @@ class MileStoneTableViewCell: UITableViewCell { return label }() + //MARK: 2 : 마일스톤에 대한 설명 라벨 private lazy var descriptionLabel: UILabel = { let label = UILabel() label.textColor = Colors.description @@ -69,30 +65,78 @@ class MileStoneTableViewCell: UITableViewCell { return label }() + //MARK: 3 : 데이트 라벨 private lazy var dateLabel: UILabel = { let label = UILabel() - var dateText = "완료일(생략가능)" + return label + }() + + //MARK: 4 : sub스택 + // -1 열린 이슈 라벨 + // -2 닫힌 이슈 라벨 + + private lazy var openLabelTitle: UILabel = { + let label = UILabel() let attributedString = NSMutableAttributedString(string: "") let imageAttachment = NSTextAttachment() - imageAttachment.image = UIImage(systemName: "calendar") - - let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 18), NSAttributedString.Key.foregroundColor : Colors.description] - let dateString = NSMutableAttributedString(string:dateText, attributes:attrs) + imageAttachment.image = UIImage(systemName: "exclamationmark.circle") + + let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : Colors.openMileStoneTint] + let dateString = NSMutableAttributedString(string: "열린 이슈 0개", attributes:attrs) attributedString.append(NSAttributedString(attachment: imageAttachment)) attributedString.append(dateString) label.attributedText = attributedString + label.backgroundColor = Colors.openMileStoneBG return label }() - private lazy var openMileStoneLabelView: MileStoneLabelView = { - let mileStoneLabelView = MileStoneLabelView(chooseNum: 0) - return mileStoneLabelView + private lazy var closeLabelTitle: UILabel = { + let label = UILabel() + let attributedString = NSMutableAttributedString(string: "") + let imageAttachment = NSTextAttachment() + imageAttachment.image = UIImage(systemName: "archivebox") + + let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : Colors.closeMileStoneTint] + let dateString = NSMutableAttributedString(string:"닫힌 이슈 0개", attributes:attrs) + + attributedString.append(NSAttributedString(attachment: imageAttachment)) + attributedString.append(dateString) + label.attributedText = attributedString + label.backgroundColor = Colors.closeMileStoneBG + return label }() - private lazy var closedMileStoneLabelView: MileStoneLabelView = { - let mileStoneLabelView = MileStoneLabelView(chooseNum: 1) - return mileStoneLabelView + private lazy var openMileStoneView: UIView = { + let uiView = UIView() + uiView.layer.cornerRadius = 30 * 0.5 + translatesAutoresizingMaskIntoConstraints = false + // uiView.addSubview(openLabelTitle) + return uiView + }() + + private lazy var closeMileStoneView: UIView = { + let uiView = UIView() + uiView.layer.cornerRadius = 30 * 0.5 + translatesAutoresizingMaskIntoConstraints = false + // uiView.addSubview(openLabelTitle) + + // NSLayoutConstraint.activate([ + // closeLabelTitle.centerXAnchor.constraint(equalTo: centerXAnchor), + // closeLabelTitle.centerYAnchor.constraint(equalTo: centerYAnchor), + // widthAnchor.constraint(equalTo: closeLabelTitle.widthAnchor, constant: 15), + // heightAnchor.constraint(equalToConstant: 30) + // ]) + + return uiView + }() + + private lazy var secondSubStackView: UIStackView = { + let stackView = UIStackView() + stackView.axis = .horizontal + stackView.distribution = .fillEqually + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView }() static var reuseID: String { @@ -110,7 +154,6 @@ class MileStoneTableViewCell: UITableViewCell { } private func setViews() { - backgroundColor = Colors.mainGrape addMileStoneStackView() } @@ -169,17 +212,56 @@ class MileStoneTableViewCell: UITableViewCell { ]) secondSubStackView - .addArrangedSubview(openMileStoneLabelView) + .addArrangedSubview(openMileStoneView) secondSubStackView - .addArrangedSubview(closedMileStoneLabelView) + .addArrangedSubview(closeMileStoneView) + + openMileStoneView.addSubview(openLabelTitle) + closeMileStoneView.addSubview(closeLabelTitle) NSLayoutConstraint.activate([ - openMileStoneLabelView.widthAnchor.constraint(equalTo: secondSubStackView.widthAnchor,constant: 1/2), + openLabelTitle.centerXAnchor.constraint(equalTo: openMileStoneView.centerXAnchor), + openLabelTitle.centerYAnchor.constraint(equalTo: openMileStoneView.centerYAnchor), + openLabelTitle.widthAnchor.constraint(equalTo: openMileStoneView.widthAnchor, constant: 15), +// openLabelTitle.heightAnchor.constraint(equalToConstant: 30), - openMileStoneLabelView.leadingAnchor.constraint(equalTo: secondSubStackView.leadingAnchor), - closedMileStoneLabelView.leadingAnchor.constraint(equalTo: openMileStoneLabelView.leadingAnchor), - ]) - - */ + closeMileStoneView.centerXAnchor.constraint(equalTo: closeMileStoneView.centerXAnchor), + closeMileStoneView.centerYAnchor.constraint(equalTo: closeMileStoneView.centerYAnchor), + closeMileStoneView.widthAnchor.constraint(equalTo: closeMileStoneView.widthAnchor, constant: 15), +// closeMileStoneView.heightAnchor.constraint(equalToConstant: 30) + ]) + + + + */ + // + // NSLayoutConstraint.activate([ + // openMileStoneLabelView.widthAnchor.constraint(equalTo: secondSubStackView.widthAnchor,constant: 1/2), + // + // openMileStoneLabelView.leadingAnchor.constraint(equalTo: secondSubStackView.leadingAnchor), + // closedMileStoneLabelView.leadingAnchor.constraint(equalTo: openMileStoneLabelView.leadingAnchor), + // ]) + + + } + + func configure(title: String, description: String, due_date: String) { + titleLabel.text = title + descriptionLabel.text = description + dueDateConfigure(due_date: due_date) + } + + private func dueDateConfigure(due_date: String) { + let dateText = due_date != "" ? due_date :"완료일(생략가능)" + let attributedString = NSMutableAttributedString(string: "") + let imageAttachment = NSTextAttachment() + imageAttachment.image = UIImage(systemName: "calendar") + + let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 18), NSAttributedString.Key.foregroundColor : Colors.description] + let dateString = NSMutableAttributedString(string:dateText, attributes:attrs) + + attributedString.append(NSAttributedString(attachment: imageAttachment)) + attributedString.append(dateString) + dateLabel.attributedText = attributedString } } From 1088e99fc72751cacc58995ed6d8b0da589f3d21 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Fri, 18 Jun 2021 12:28:14 +0900 Subject: [PATCH 42/91] =?UTF-8?q?fix:=20[#73]=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EB=B8=94=20=EC=BB=AC=EB=9F=AC=20=EB=AF=B8?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 레이블 수정 모드 진입 시 기존 레이블 컬러를 프리뷰하지 못하는 현상 수정 --- .../Main/Common/View/LabelView.swift | 8 +++ .../LabelControlViewController.swift | 58 ++++++++++--------- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift index e41cb82e8..e6c37de57 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/LabelView.swift @@ -24,6 +24,8 @@ final class LabelView: UIView { return spacing * 2 }() + private let colorConverter = HexColorConverter() + required init?(coder: NSCoder) { super.init(coder: coder) configure() @@ -61,4 +63,10 @@ final class LabelView: UIView { labelTitle.text = title } } + + func configure(with hexColorCode: HexColorCode,_ title: String?) { + let backgroundColor = colorConverter.convertHex(hexColorCode) + let textColor = colorConverter.isColorDark(hex: hexColorCode) ? UIColor.white : UIColor.black + configure(with: backgroundColor, textColor, title) + } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift index a2421d86f..c7d49f692 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift @@ -52,9 +52,9 @@ class LabelControlViewController: UIViewController { private lazy var saveButton: ImageBarButton = { let button = ImageBarButton() button.configure(with: "", "저장") - button.isEnabled = false button.translatesAutoresizingMaskIntoConstraints = false button.addTarget(self, action: #selector(saveButtonTouched), for: .touchUpInside) + changeSaveButtonEnableStatus(baseOn: titleTextfield) return button }() @@ -135,7 +135,9 @@ class LabelControlViewController: UIViewController { private lazy var previewLabel: LabelView = { let labelView = LabelView() - labelView.configure(with: UIColor.black, UIColor.white, "레이블") + let colorText = backgroundLabel.text ?? "#000000" + let hex = HexColorCode(from: colorText) + labelView.configure(with: hex, titleTextfield.text) labelView.translatesAutoresizingMaskIntoConstraints = false return labelView }() @@ -150,8 +152,6 @@ class LabelControlViewController: UIViewController { private var loginInfo: LoginInfo? var sceneTitle: String? - - private let colorConverter: HexColorConvertable = HexColorConverter() var networkManager: NetworkManagerOperations? var dismissOperation: (() -> Void)? @@ -166,6 +166,14 @@ class LabelControlViewController: UIViewController { titleTextfield.delegate = self } + private func changeSaveButtonEnableStatus(baseOn textField: UITextField) { + guard let text = textField.text else { return } + + DispatchQueue.main.async { + self.saveButton.isEnabled = text.count > 0 + } + } + private func addTopMenu() { view.addSubview(topMenuView) @@ -228,26 +236,13 @@ class LabelControlViewController: UIViewController { self.dismissOperation = operation } - @objc private func cancelButtonTouched(_ sender: UIBarButtonItem) { - dismiss(animated: true, completion: nil) - } - - ///이 메소드를 오버라이드하여 레이블 생성 or 수정 구현 - @objc func saveButtonTouched(_ sender: UIBarButtonItem) { } - func presentAlert(with errorMessage: String) { DispatchQueue.main.async { let alert = AlertFactory.create(body: errorMessage) self.present(alert, animated: true, completion: nil) } } - - @objc private func randomColorButtonTouched(_ sender: UIButton) { - let hexColor = randomColor() - backgroundLabel.text = hexColor - changePreviewLabel(with: hexColor) - } - + private func randomColor() -> String { let colorRange = 0...255 let randomRed = Int.random(in: colorRange) @@ -260,11 +255,11 @@ class LabelControlViewController: UIViewController { return "#\(hexRed)\(hexGreen)\(hexBlue)" } - private func changePreviewLabel(with hexColorString: String) { + private func changePreviewLabel() { + let hexColorString = backgroundLabel.text ?? "#000000" + let title = titleTextfield.text ?? "레이블" let hex = HexColorCode(from: hexColorString) - let backgroundColor = colorConverter.convertHex(hex) - let titleColor = colorConverter.isColorDark(hex: hex) ? UIColor.white : UIColor.black - previewLabel.configure(with: backgroundColor, titleColor, nil) + previewLabel.configure(with: hex, title) } private func setNetworkManager() { @@ -273,13 +268,24 @@ class LabelControlViewController: UIViewController { let headers = [Header.authorization.key(): jwt.description] networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) } + + @objc private func cancelButtonTouched(_ sender: UIBarButtonItem) { + dismiss(animated: true, completion: nil) + } + + ///이 메소드를 오버라이드하여 레이블 생성 or 수정 구현 + @objc func saveButtonTouched(_ sender: UIBarButtonItem) { } + + @objc private func randomColorButtonTouched(_ sender: UIButton) { + let hexColor = randomColor() + backgroundLabel.text = hexColor + changePreviewLabel() + } } extension LabelControlViewController: UITextFieldDelegate { func textFieldDidChangeSelection(_ textField: UITextField) { - guard let text = textField.text else { return } - DispatchQueue.main.async { - self.saveButton.isEnabled = text.count > 0 - } + changeSaveButtonEnableStatus(baseOn: textField) + changePreviewLabel() } } From 70ce9eacf5764fea5db29e592f6aa7177285093c Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Fri, 18 Jun 2021 14:27:34 +0900 Subject: [PATCH 43/91] =?UTF-8?q?bug:=20[#68]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20=EC=8A=A4=ED=83=9D=EB=B7=B0=20=ED=94=84?= =?UTF-8?q?=EB=A0=88=EC=9E=84=20=EC=97=90=EB=9F=AC=20=EC=9D=B4=EC=8A=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MileStoneLabelView.swift | 41 ++++--- .../Controller/MileStoneTableDelegate.swift | 2 +- .../View/MileStoneTableViewCell.swift | 106 ++++-------------- 3 files changed, 49 insertions(+), 100 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift index ab0c2165a..47b740ece 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift @@ -9,26 +9,30 @@ import UIKit final class MileStoneLabelView: UIView { - var chooseNum: Int? - let texts = ["열린 이슈","닫힌 이슈"] - let fontColors = [UIColor.blue, UIColor.purple] - let backgroundColors = [UIColor.red, UIColor.green] - let systemImgName = ["exclamationmark.circle","archivebox"] - var issueCount = 0 + var texts: String? + var fontColors: UIColor? + var backgroundColors: UIColor? + var imgName: String? + var issueCount: Int? private lazy var labelTitle: UILabel = { let label = UILabel() + guard let imgName = self.imgName else { return UILabel() } + guard let fontColors = self.fontColors else { return UILabel() } + guard let texts = self.texts else { return UILabel() } + guard let issueCount = self.issueCount else { return UILabel() } + let attributedString = NSMutableAttributedString(string: "") let imageAttachment = NSTextAttachment() - imageAttachment.image = UIImage(systemName: systemImgName[chooseNum!]) - - let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : fontColors[chooseNum!]] - let dateString = NSMutableAttributedString(string:texts[chooseNum!]+" \(issueCount)개", attributes:attrs) + let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : fontColors] + let dateString = NSMutableAttributedString(string:"\(texts) \(issueCount)개", attributes:attrs) + imageAttachment.image = UIImage(systemName: imgName) attributedString.append(NSAttributedString(attachment: imageAttachment)) attributedString.append(dateString) label.attributedText = attributedString + label.backgroundColor = backgroundColor return label }() @@ -48,9 +52,15 @@ final class MileStoneLabelView: UIView { configure() } - required init(chooseNum: Int) { - self.chooseNum = chooseNum - super.init(frame: .zero) + required init(texts: String, fontColors: UIColor, backgroundColors: UIColor, imgName: String, issueCount: Int) { +// super.init(frame: .zero) + super.init(frame: CGRect(x: 0, y: 0, width: 113, height: 30)) + self.texts = texts + self.fontColors = fontColors + self.backgroundColors = backgroundColors + self.imgName = imgName + self.issueCount = issueCount + configure() } @@ -69,12 +79,13 @@ final class MileStoneLabelView: UIView { NSLayoutConstraint.activate([ labelTitle.centerXAnchor.constraint(equalTo: centerXAnchor), labelTitle.centerYAnchor.constraint(equalTo: centerYAnchor), - widthAnchor.constraint(equalTo: labelTitle.widthAnchor, constant: spacing), + //widthAnchor.constraint(equalTo: labelTitle.widthAnchor, constant: spacing) + widthAnchor.constraint(equalTo: widthAnchor), heightAnchor.constraint(equalToConstant: labelHeight) ]) } - func updateIssueCount(_ issueCount: Int) { + func updateIssueCount(_ issueCount: Int) { //후에 issuecount를 변경 self.issueCount = issueCount } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift index bc46708e7..4752439ca 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift @@ -8,6 +8,6 @@ import UIKit class MileStoneTableDelegate: NSObject, UITableViewDelegate { func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return tableView.frame.height * 0.336 + return tableView.frame.height * 0.233 } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index 6975148f5..0cebd917e 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -75,62 +75,6 @@ class MileStoneTableViewCell: UITableViewCell { // -1 열린 이슈 라벨 // -2 닫힌 이슈 라벨 - private lazy var openLabelTitle: UILabel = { - let label = UILabel() - let attributedString = NSMutableAttributedString(string: "") - let imageAttachment = NSTextAttachment() - imageAttachment.image = UIImage(systemName: "exclamationmark.circle") - - let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : Colors.openMileStoneTint] - let dateString = NSMutableAttributedString(string: "열린 이슈 0개", attributes:attrs) - - attributedString.append(NSAttributedString(attachment: imageAttachment)) - attributedString.append(dateString) - label.attributedText = attributedString - label.backgroundColor = Colors.openMileStoneBG - return label - }() - - private lazy var closeLabelTitle: UILabel = { - let label = UILabel() - let attributedString = NSMutableAttributedString(string: "") - let imageAttachment = NSTextAttachment() - imageAttachment.image = UIImage(systemName: "archivebox") - - let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : Colors.closeMileStoneTint] - let dateString = NSMutableAttributedString(string:"닫힌 이슈 0개", attributes:attrs) - - attributedString.append(NSAttributedString(attachment: imageAttachment)) - attributedString.append(dateString) - label.attributedText = attributedString - label.backgroundColor = Colors.closeMileStoneBG - return label - }() - - private lazy var openMileStoneView: UIView = { - let uiView = UIView() - uiView.layer.cornerRadius = 30 * 0.5 - translatesAutoresizingMaskIntoConstraints = false - // uiView.addSubview(openLabelTitle) - return uiView - }() - - private lazy var closeMileStoneView: UIView = { - let uiView = UIView() - uiView.layer.cornerRadius = 30 * 0.5 - translatesAutoresizingMaskIntoConstraints = false - // uiView.addSubview(openLabelTitle) - - // NSLayoutConstraint.activate([ - // closeLabelTitle.centerXAnchor.constraint(equalTo: centerXAnchor), - // closeLabelTitle.centerYAnchor.constraint(equalTo: centerYAnchor), - // widthAnchor.constraint(equalTo: closeLabelTitle.widthAnchor, constant: 15), - // heightAnchor.constraint(equalToConstant: 30) - // ]) - - return uiView - }() - private lazy var secondSubStackView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal @@ -139,6 +83,17 @@ class MileStoneTableViewCell: UITableViewCell { return stackView }() + private lazy var openMilestoneLabelView: MileStoneLabelView = { + let milestoneLabelView = MileStoneLabelView(texts: "열린 이슈", fontColors: Colors.openMileStoneTint, backgroundColors: Colors.openMileStoneBG, imgName: "exclamationmark.circle", issueCount: 0) + return milestoneLabelView + }() + + private lazy var closeMilestoneLabelView: MileStoneLabelView = { + let milestoneLabelView = MileStoneLabelView(texts: "닫힌 이슈", fontColors: Colors.closeMileStoneTint, backgroundColors: Colors.closeMileStoneBG, imgName: "archivebox", issueCount: 0) + return milestoneLabelView + }() + + static var reuseID: String { return String(describing: self) } @@ -203,7 +158,7 @@ class MileStoneTableViewCell: UITableViewCell { //MARK: 4 : sub스택 //-1 열린 이슈 라벨 //-2 닫힌 이슈 라벨 - /* + mileStoneStackView.addArrangedSubview(secondSubStackView) NSLayoutConstraint.activate([ @@ -212,37 +167,20 @@ class MileStoneTableViewCell: UITableViewCell { ]) secondSubStackView - .addArrangedSubview(openMileStoneView) + .addArrangedSubview(openMilestoneLabelView) secondSubStackView - .addArrangedSubview(closeMileStoneView) - - openMileStoneView.addSubview(openLabelTitle) - closeMileStoneView.addSubview(closeLabelTitle) - - NSLayoutConstraint.activate([ - openLabelTitle.centerXAnchor.constraint(equalTo: openMileStoneView.centerXAnchor), - openLabelTitle.centerYAnchor.constraint(equalTo: openMileStoneView.centerYAnchor), - openLabelTitle.widthAnchor.constraint(equalTo: openMileStoneView.widthAnchor, constant: 15), -// openLabelTitle.heightAnchor.constraint(equalToConstant: 30), - - closeMileStoneView.centerXAnchor.constraint(equalTo: closeMileStoneView.centerXAnchor), - closeMileStoneView.centerYAnchor.constraint(equalTo: closeMileStoneView.centerYAnchor), - closeMileStoneView.widthAnchor.constraint(equalTo: closeMileStoneView.widthAnchor, constant: 15), -// closeMileStoneView.heightAnchor.constraint(equalToConstant: 30) - ]) - - + .addArrangedSubview(closeMilestoneLabelView) - */ - // - // NSLayoutConstraint.activate([ - // openMileStoneLabelView.widthAnchor.constraint(equalTo: secondSubStackView.widthAnchor,constant: 1/2), - // - // openMileStoneLabelView.leadingAnchor.constraint(equalTo: secondSubStackView.leadingAnchor), - // closedMileStoneLabelView.leadingAnchor.constraint(equalTo: openMileStoneLabelView.leadingAnchor), - // ]) + /* + secondSubStackView.spacing = 16 + NSLayoutConstraint.activate([ + openMilestoneLabelView.leadingAnchor.constraint(equalTo: secondSubStackView.leadingAnchor,constant: 4), + openMilestoneLabelView.topAnchor.constraint(equalTo: secondSubStackView.topAnchor,constant: 4), + closeMilestoneLabelView.leadingAnchor.constraint(equalTo: openMilestoneLabelView.trailingAnchor,constant: 4), + closeMilestoneLabelView.topAnchor.constraint(equalTo: secondSubStackView.topAnchor,constant: 4), + ])*/ } func configure(title: String, description: String, due_date: String) { From 0d638734446fb7b19f04c301a1cc5f632e7464a0 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Fri, 18 Jun 2021 15:44:52 +0900 Subject: [PATCH 44/91] =?UTF-8?q?feat=20:[#68]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20=EB=A0=88=EC=9D=B4=EB=B8=94=EB=B7=B0?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MileStoneLabelView.swift | 36 +++++++++--------- .../View/MileStoneTableViewCell.swift | 38 ++++++++++--------- 2 files changed, 39 insertions(+), 35 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift index 47b740ece..c56212b6a 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift @@ -9,30 +9,32 @@ import UIKit final class MileStoneLabelView: UIView { - var texts: String? - var fontColors: UIColor? - var backgroundColors: UIColor? + var text: String? + var fontColor: UIColor? + var bgColor: UIColor? var imgName: String? var issueCount: Int? private lazy var labelTitle: UILabel = { let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + guard let imgName = self.imgName else { return UILabel() } - guard let fontColors = self.fontColors else { return UILabel() } - guard let texts = self.texts else { return UILabel() } + guard let fontColors = self.fontColor else { return UILabel() } + guard let texts = self.text else { return UILabel() } guard let issueCount = self.issueCount else { return UILabel() } let attributedString = NSMutableAttributedString(string: "") let imageAttachment = NSTextAttachment() let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : fontColors] - let dateString = NSMutableAttributedString(string:"\(texts) \(issueCount)개", attributes:attrs) + let issueCountString = NSMutableAttributedString(string:"\(texts) \(issueCount)개", attributes:attrs) imageAttachment.image = UIImage(systemName: imgName) attributedString.append(NSAttributedString(attachment: imageAttachment)) - attributedString.append(dateString) + attributedString.append(issueCountString) label.attributedText = attributedString - label.backgroundColor = backgroundColor + return label }() @@ -52,12 +54,13 @@ final class MileStoneLabelView: UIView { configure() } - required init(texts: String, fontColors: UIColor, backgroundColors: UIColor, imgName: String, issueCount: Int) { -// super.init(frame: .zero) - super.init(frame: CGRect(x: 0, y: 0, width: 113, height: 30)) - self.texts = texts - self.fontColors = fontColors - self.backgroundColors = backgroundColors + required init(text: String, fontColor: UIColor, bgColor: UIColor, imgName: String, issueCount: Int) { + + //init을 무엇을 줘도 상관이 없는듯. + super.init(frame: .zero) + self.text = text + self.fontColor = fontColor + self.bgColor = bgColor self.imgName = imgName self.issueCount = issueCount @@ -70,23 +73,22 @@ final class MileStoneLabelView: UIView { translatesAutoresizingMaskIntoConstraints = false addLabelTitle() + backgroundColor = bgColor } private func addLabelTitle() { addSubview(labelTitle) + //예이!!!!!!! NSLayoutConstraint.activate([ labelTitle.centerXAnchor.constraint(equalTo: centerXAnchor), labelTitle.centerYAnchor.constraint(equalTo: centerYAnchor), - //widthAnchor.constraint(equalTo: labelTitle.widthAnchor, constant: spacing) widthAnchor.constraint(equalTo: widthAnchor), heightAnchor.constraint(equalToConstant: labelHeight) ]) } - func updateIssueCount(_ issueCount: Int) { //후에 issuecount를 변경 self.issueCount = issueCount } - } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index 0cebd917e..9e3f69afc 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -75,7 +75,7 @@ class MileStoneTableViewCell: UITableViewCell { // -1 열린 이슈 라벨 // -2 닫힌 이슈 라벨 - private lazy var secondSubStackView: UIStackView = { + private lazy var milestoneLabelSubStackView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal stackView.distribution = .fillEqually @@ -84,16 +84,15 @@ class MileStoneTableViewCell: UITableViewCell { }() private lazy var openMilestoneLabelView: MileStoneLabelView = { - let milestoneLabelView = MileStoneLabelView(texts: "열린 이슈", fontColors: Colors.openMileStoneTint, backgroundColors: Colors.openMileStoneBG, imgName: "exclamationmark.circle", issueCount: 0) + let milestoneLabelView = MileStoneLabelView(text: "열린 이슈", fontColor: Colors.openMileStoneTint, bgColor: Colors.openMileStoneBG, imgName: "exclamationmark.circle", issueCount: 0) return milestoneLabelView }() private lazy var closeMilestoneLabelView: MileStoneLabelView = { - let milestoneLabelView = MileStoneLabelView(texts: "닫힌 이슈", fontColors: Colors.closeMileStoneTint, backgroundColors: Colors.closeMileStoneBG, imgName: "archivebox", issueCount: 0) + let milestoneLabelView = MileStoneLabelView(text: "닫힌 이슈", fontColor: Colors.closeMileStoneTint, bgColor: Colors.closeMileStoneBG, imgName: "archivebox", issueCount: 0) return milestoneLabelView }() - static var reuseID: String { return String(describing: self) } @@ -110,6 +109,7 @@ class MileStoneTableViewCell: UITableViewCell { private func setViews() { addMileStoneStackView() + test() } private func addMileStoneStackView() { @@ -159,30 +159,32 @@ class MileStoneTableViewCell: UITableViewCell { //-1 열린 이슈 라벨 //-2 닫힌 이슈 라벨 - mileStoneStackView.addArrangedSubview(secondSubStackView) + mileStoneStackView.addArrangedSubview(milestoneLabelSubStackView) NSLayoutConstraint.activate([ - secondSubStackView.leadingAnchor.constraint(equalTo: mileStoneStackView.leadingAnchor), - secondSubStackView.trailingAnchor.constraint(equalTo: mileStoneStackView.trailingAnchor) + milestoneLabelSubStackView.leadingAnchor.constraint(equalTo: mileStoneStackView.leadingAnchor), +// milestoneLabelSubStackView.widthAnchor.constraint(equalToConstant: mileStoneStackView.frame.width * 0.5) + milestoneLabelSubStackView.trailingAnchor.constraint(equalTo: mileStoneStackView.trailingAnchor) ]) - secondSubStackView + milestoneLabelSubStackView .addArrangedSubview(openMilestoneLabelView) - secondSubStackView + milestoneLabelSubStackView .addArrangedSubview(closeMilestoneLabelView) - /* - - secondSubStackView.spacing = 16 - + milestoneLabelSubStackView.spacing = 4 + NSLayoutConstraint.activate([ - openMilestoneLabelView.leadingAnchor.constraint(equalTo: secondSubStackView.leadingAnchor,constant: 4), - openMilestoneLabelView.topAnchor.constraint(equalTo: secondSubStackView.topAnchor,constant: 4), - closeMilestoneLabelView.leadingAnchor.constraint(equalTo: openMilestoneLabelView.trailingAnchor,constant: 4), - closeMilestoneLabelView.topAnchor.constraint(equalTo: secondSubStackView.topAnchor,constant: 4), - ])*/ +// openMilestoneLabelView.widthAnchor +// .constraint(lessThanOrEqualTo: milestoneLabelSubStackView.widthAnchor, multiplier: 0.329), +// closeMilestoneLabelView.widthAnchor +// .constraint(lessThanOrEqualTo: milestoneLabelSubStackView.widthAnchor, multiplier: 0.329) + ]) } + func test(){ + + } func configure(title: String, description: String, due_date: String) { titleLabel.text = title descriptionLabel.text = description From 8c47bc30e8d0f5b5e98e3e2df28853dc93788970 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Fri, 18 Jun 2021 16:31:15 +0900 Subject: [PATCH 45/91] =?UTF-8?q?fix:=20=E1=84=80=E1=85=B5=E1=86=BA?= =?UTF-8?q?=E1=84=92=E1=85=A5=E1=84=87=E1=85=B3=20=E1=84=85=E1=85=A9?= =?UTF-8?q?=E1=84=80=E1=85=B3=E1=84=8B=E1=85=B5=E1=86=AB=E1=84=86=E1=85=A1?= =?UTF-8?q?=E1=86=AB=20=E1=84=83=E1=85=AC=E1=84=82=E1=85=B3=E1=86=AB=20?= =?UTF-8?q?=E1=84=8B=E1=85=A9=E1=84=85=E1=85=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Login/Controller/LoginViewController.swift | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift b/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift index 5e4c0d557..351c52c42 100644 --- a/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Login/Controller/LoginViewController.swift @@ -217,10 +217,17 @@ class LoginViewController: UIViewController { private func configureLoginManager(service: LoginService) { let keyChainManager = LoginKeyChainManager(loginService: service) loginInfo.service = service - let loginManager = GithubAuthorizationManager(viewController: self, - delegate: self, - keyChainSaver: keyChainManager) - self.socialLoginManager = loginManager + + switch service { + case .github: + socialLoginManager = GithubAuthorizationManager(viewController: self, + delegate: self, + keyChainSaver: keyChainManager) + case .apple: + socialLoginManager = AppleAuthorizationManager(viewController: self, + delegate: self, + keyChainSaver: keyChainManager) + } } } From b2d473c4feed8df95dcf1863751d8e356619e9d5 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Fri, 18 Jun 2021 19:33:05 +0900 Subject: [PATCH 46/91] =?UTF-8?q?refactor:=20[#78]=20TextField=20=EA=B3=B5?= =?UTF-8?q?=EB=B0=B1=20=ED=8C=90=EB=8B=A8=20=EB=B0=A9=EB=B2=95=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 사실상 Nil인 경우가 없다고 하여 extension Method로 한번에 판별 ᅵ --- .../issue-tracker.xcodeproj/project.pbxproj | 4 ++++ .../Common/UITextFieldExtension.swift | 18 ++++++++++++++++++ .../LabelControlViewController.swift | 11 +++++------ 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Common/UITextFieldExtension.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 0c8236837..57651c6fe 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ E43912EE267C3C0E003CD344 /* CellAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912ED267C3C0E003CD344 /* CellAction.swift */; }; E43912F0267C3EED003CD344 /* LabelControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912EF267C3EED003CD344 /* LabelControlViewController.swift */; }; E43912F2267C423A003CD344 /* EditLabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F1267C423A003CD344 /* EditLabelViewController.swift */; }; + E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -100,6 +101,7 @@ E43912ED267C3C0E003CD344 /* CellAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellAction.swift; sourceTree = ""; }; E43912EF267C3EED003CD344 /* LabelControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelControlViewController.swift; sourceTree = ""; }; E43912F1267C423A003CD344 /* EditLabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditLabelViewController.swift; sourceTree = ""; }; + E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITextFieldExtension.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -195,6 +197,7 @@ FAEB30AD266F6A7800C17BE9 /* UIImageExtension.swift */, E42AD12526709C010071B436 /* UIViewControllerExtension.swift */, E426DAC82671F7760069E77D /* AlertFactory.swift */, + E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */, ); path = Common; sourceTree = ""; @@ -466,6 +469,7 @@ FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */, E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */, E42AD11E267093320071B436 /* IssueViewController.swift in Sources */, + E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */, E43912E42679C0DA003CD344 /* AddLabelViewController.swift in Sources */, E43912F2267C423A003CD344 /* EditLabelViewController.swift in Sources */, E43912DC2678A737003CD344 /* JWT.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Common/UITextFieldExtension.swift b/iOS/issue-tracker/issue-tracker/Common/UITextFieldExtension.swift new file mode 100644 index 000000000..7dca84baa --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Common/UITextFieldExtension.swift @@ -0,0 +1,18 @@ +// +// UITextFieldExtension.swift +// issue-tracker +// +// Created by Song on 2021/06/18. +// + +import UIKit + +extension UITextField { + func isEmpty() -> Bool { + if let text = self.text, text.count > 0 { + return false + } else { + return true + } + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift index c7d49f692..a1e1a5542 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift @@ -137,7 +137,8 @@ class LabelControlViewController: UIViewController { let labelView = LabelView() let colorText = backgroundLabel.text ?? "#000000" let hex = HexColorCode(from: colorText) - labelView.configure(with: hex, titleTextfield.text) + let titleText = titleTextfield.isEmpty() ? "레이블" : titleTextfield.text + labelView.configure(with: hex, titleText) labelView.translatesAutoresizingMaskIntoConstraints = false return labelView }() @@ -167,10 +168,8 @@ class LabelControlViewController: UIViewController { } private func changeSaveButtonEnableStatus(baseOn textField: UITextField) { - guard let text = textField.text else { return } - DispatchQueue.main.async { - self.saveButton.isEnabled = text.count > 0 + self.saveButton.isEnabled = !textField.isEmpty() } } @@ -257,9 +256,9 @@ class LabelControlViewController: UIViewController { private func changePreviewLabel() { let hexColorString = backgroundLabel.text ?? "#000000" - let title = titleTextfield.text ?? "레이블" let hex = HexColorCode(from: hexColorString) - previewLabel.configure(with: hex, title) + let titleText = titleTextfield.isEmpty() ? "레이블" : titleTextfield.text + previewLabel.configure(with: hex, titleText) } private func setNetworkManager() { From 9c8bd73fc4202b47f88c1ac57b911bf700cc759d Mon Sep 17 00:00:00 2001 From: Song Lee Date: Fri, 18 Jun 2021 19:55:08 +0900 Subject: [PATCH 47/91] =?UTF-8?q?refactor:=20[#78]=20TopMenuView=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 재사용성 개선 --- .../issue-tracker.xcodeproj/project.pbxproj | 4 ++ .../Main/Common/View/TopMenuView.swift | 70 +++++++++++++++++++ .../LabelControlViewController.swift | 50 ++++--------- 3 files changed, 87 insertions(+), 37 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Common/View/TopMenuView.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 57651c6fe..5eed94806 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ E43912F0267C3EED003CD344 /* LabelControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912EF267C3EED003CD344 /* LabelControlViewController.swift */; }; E43912F2267C423A003CD344 /* EditLabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F1267C423A003CD344 /* EditLabelViewController.swift */; }; E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */; }; + E43912F6267CAE01003CD344 /* TopMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F5267CAE01003CD344 /* TopMenuView.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -102,6 +103,7 @@ E43912EF267C3EED003CD344 /* LabelControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelControlViewController.swift; sourceTree = ""; }; E43912F1267C423A003CD344 /* EditLabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditLabelViewController.swift; sourceTree = ""; }; E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITextFieldExtension.swift; sourceTree = ""; }; + E43912F5267CAE01003CD344 /* TopMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopMenuView.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -290,6 +292,7 @@ children = ( E43912D326788CC3003CD344 /* ImageBarButton.swift */, E43912C626776D8F003CD344 /* LabelView.swift */, + E43912F5267CAE01003CD344 /* TopMenuView.swift */, ); path = View; sourceTree = ""; @@ -451,6 +454,7 @@ E43912C726776D8F003CD344 /* LabelView.swift in Sources */, E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */, E43912EA267A2351003CD344 /* NetworkError.swift in Sources */, + E43912F6267CAE01003CD344 /* TopMenuView.swift in Sources */, E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/TopMenuView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/TopMenuView.swift new file mode 100644 index 000000000..893b557ad --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/TopMenuView.swift @@ -0,0 +1,70 @@ +// +// TopMenuView.swift +// issue-tracker +// +// Created by Song on 2021/06/18. +// + +import UIKit + +final class TopMenuView: UIView { + + private lazy var titleLabel: UILabel = { + let titleLabel = UILabel() + titleLabel.text = menuTitle + titleLabel.font = .systemFont(ofSize: 18, weight: .bold) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + return titleLabel + }() + + private var rightButton: UIButton? + private var leftButton: UIButton? + private var menuTitle: String? + private let spacing: CGFloat = 16 + + func configure(withTitle title: String?, rightButton: UIButton?, leftButton: UIButton?) { + self.menuTitle = title + self.rightButton = rightButton + self.leftButton = leftButton + + addTitleLabel() + addRightButton() + addLeftButton() + } + + private func addTitleLabel() { + addSubview(titleLabel) + + NSLayoutConstraint.activate([ + titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor), + titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor) + ]) + } + + private func addRightButton() { + guard let rightButton = rightButton else { return } + + addSubview(rightButton) + + NSLayoutConstraint.activate([ + rightButton.centerYAnchor.constraint(equalTo: safeAreaLayoutGuide.centerYAnchor), + rightButton.widthAnchor.constraint(greaterThanOrEqualToConstant: spacing * 2), + rightButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), + rightButton.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -spacing) + ]) + } + + private func addLeftButton() { + guard let leftButton = leftButton else { return } + + addSubview(leftButton) + + NSLayoutConstraint.activate([ + leftButton.centerYAnchor.constraint(equalTo: safeAreaLayoutGuide.centerYAnchor), + leftButton.widthAnchor.constraint(greaterThanOrEqualToConstant: spacing * 2), + leftButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), + leftButton.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor, constant: spacing) + ]) + } +} + diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift index a1e1a5542..de4b11bc2 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift @@ -9,52 +9,28 @@ import UIKit class LabelControlViewController: UIViewController { - private lazy var topMenuView: UIView = { - let container = UIView() - container.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(saveButton) - NSLayoutConstraint.activate([ - saveButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), - saveButton.widthAnchor.constraint(greaterThanOrEqualToConstant: spacing * 2), - saveButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), - saveButton.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing) - ]) - - container.addSubview(cancelButton) - NSLayoutConstraint.activate([ - cancelButton.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), - cancelButton.widthAnchor.constraint(greaterThanOrEqualToConstant: spacing * 2), - cancelButton.heightAnchor.constraint(equalToConstant: spacing * 1.5), - cancelButton.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing) - ]) - - let titleLabel = UILabel() - titleLabel.text = sceneTitle - titleLabel.font = .systemFont(ofSize: 18, weight: .bold) - titleLabel.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.centerXAnchor.constraint(equalTo: container.centerXAnchor), - titleLabel.centerYAnchor.constraint(equalTo: container.centerYAnchor) - ]) - return container + private lazy var topMenuView: TopMenuView = { + let topMenuView = TopMenuView() + topMenuView.configure(withTitle: sceneTitle, rightButton: saveButton, leftButton: cancelButton) + topMenuView.translatesAutoresizingMaskIntoConstraints = false + return topMenuView }() - private lazy var cancelButton: ImageBarButton = { + private lazy var saveButton: ImageBarButton = { let button = ImageBarButton() - button.configure(with: "chevron.backward", "취소") - button.moveImageToLeft() + button.configure(with: "", "저장") button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(cancelButtonTouched), for: .touchUpInside) + button.addTarget(self, action: #selector(saveButtonTouched), for: .touchUpInside) + changeSaveButtonEnableStatus(baseOn: titleTextfield) return button }() - private lazy var saveButton: ImageBarButton = { + private lazy var cancelButton: ImageBarButton = { let button = ImageBarButton() - button.configure(with: "", "저장") + button.configure(with: "chevron.backward", "취소") + button.moveImageToLeft() button.translatesAutoresizingMaskIntoConstraints = false - button.addTarget(self, action: #selector(saveButtonTouched), for: .touchUpInside) - changeSaveButtonEnableStatus(baseOn: titleTextfield) + button.addTarget(self, action: #selector(cancelButtonTouched), for: .touchUpInside) return button }() From 76e96be79e5d6d376b88a4f279689525b1684810 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Fri, 18 Jun 2021 20:26:58 +0900 Subject: [PATCH 48/91] =?UTF-8?q?refactor:=20[#78]=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=A0=95=EB=B3=B4=20=EC=9E=85=EB=A0=A5=20stackView?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 재사용성 개선 --- .../issue-tracker.xcodeproj/project.pbxproj | 4 + .../View/MultipleLineInputStackView.swift | 91 +++++++++++++++++++ .../LabelControlViewController.swift | 69 +++----------- 3 files changed, 110 insertions(+), 54 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 5eed94806..afc5d5a66 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -48,6 +48,7 @@ E43912F2267C423A003CD344 /* EditLabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F1267C423A003CD344 /* EditLabelViewController.swift */; }; E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */; }; E43912F6267CAE01003CD344 /* TopMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F5267CAE01003CD344 /* TopMenuView.swift */; }; + E43912F8267CB3D7003CD344 /* MultipleLineInputStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F7267CB3D7003CD344 /* MultipleLineInputStackView.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; @@ -104,6 +105,7 @@ E43912F1267C423A003CD344 /* EditLabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditLabelViewController.swift; sourceTree = ""; }; E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITextFieldExtension.swift; sourceTree = ""; }; E43912F5267CAE01003CD344 /* TopMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopMenuView.swift; sourceTree = ""; }; + E43912F7267CB3D7003CD344 /* MultipleLineInputStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipleLineInputStackView.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; @@ -293,6 +295,7 @@ E43912D326788CC3003CD344 /* ImageBarButton.swift */, E43912C626776D8F003CD344 /* LabelView.swift */, E43912F5267CAE01003CD344 /* TopMenuView.swift */, + E43912F7267CB3D7003CD344 /* MultipleLineInputStackView.swift */, ); path = View; sourceTree = ""; @@ -446,6 +449,7 @@ E43912F0267C3EED003CD344 /* LabelControlViewController.swift in Sources */, E43912DE2678A76D003CD344 /* RequestKeys.swift in Sources */, E42AD102266E52FB0071B436 /* LoginViewController.swift in Sources */, + E43912F8267CB3D7003CD344 /* MultipleLineInputStackView.swift in Sources */, E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */, E43912D0267878BF003CD344 /* HexColorConvertable.swift in Sources */, FAC6D88D2671D8A100A9E5F9 /* SocialLoginManagable.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift new file mode 100644 index 000000000..f39d87119 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift @@ -0,0 +1,91 @@ +// +// ThreeLineInputStackView.swift +// issue-tracker +// +// Created by Song on 2021/06/18. +// + +import UIKit + +struct InputLineItem { + let category: String + let inputView: UIView +} + +final class MultipleLineInputStackView: UIStackView { + + private lazy var lineHeight: CGFloat = { + return frame.height / 3 + }() + + private lazy var elementSpacing: CGFloat = { + return lineHeight / 2 + }() + + private var items: [InputLineItem]? + private let borderColor = Colors.border.cgColor + private let borderWidth: CGFloat = 1 + + override init(frame: CGRect) { + super.init(frame: frame) + configure() + } + + required init(coder: NSCoder) { + super.init(coder: coder) + configure() + } + + private func configure() { + backgroundColor = UIColor.white + axis = .vertical + distribution = .fillEqually + translatesAutoresizingMaskIntoConstraints = false + } + + func configure(with items: [InputLineItem]) { + self.items = items + + items.forEach { inputLineItem in + let containerFrame = CGRect(x: 0, y: 0, width: frame.width, height: lineHeight) + let container = UIView(frame: containerFrame) + + let category = inputLineItem.category + let titleLabel = UILabel() + titleLabel.text = category + titleLabel.translatesAutoresizingMaskIntoConstraints = false + + container.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: elementSpacing), + titleLabel.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) + ]) + + let inputView = inputLineItem.inputView + inputView.translatesAutoresizingMaskIntoConstraints = false + + container.addSubview(inputView) + NSLayoutConstraint.activate([ + inputView.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: elementSpacing * 5), + inputView.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -elementSpacing), + inputView.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) + ]) + addArrangedSubview(container) + } + addDivisionLines() + } + + private func addDivisionLines() { + guard let itemCount = items?.count, itemCount >= 2 else { return } + + let size = CGSize(width: frame.width - elementSpacing, height: borderWidth) + + for i in 1...itemCount-1 { + let line = CALayer() + let origin = CGPoint(x: spacing, y: lineHeight * CGFloat(i) - borderWidth) + line.frame = CGRect(origin: origin, size: size) + line.backgroundColor = borderColor + layer.addSublayer(line) + } + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift index de4b11bc2..0f0592dc3 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift @@ -33,42 +33,17 @@ class LabelControlViewController: UIViewController { button.addTarget(self, action: #selector(cancelButtonTouched), for: .touchUpInside) return button }() - - private lazy var newLabelEditStackView: UIStackView = { + + private lazy var labelEditStackView: MultipleLineInputStackView = { let viewWidth = view.frame.width let stackViewFrame = CGRect(x: 0, y: 0, width: viewWidth, height: singleLineHeight * 3) - let stackView = UIStackView(frame: stackViewFrame) - stackView.backgroundColor = UIColor.white - stackView.axis = .vertical - stackView.distribution = .fillEqually - stackView.translatesAutoresizingMaskIntoConstraints = false - - let categories = ["제목", "설명", "배경색"] - let contentViews: [UIView] = [titleTextfield, descriptionTextfield, backgroundLabel] + let stackView = MultipleLineInputStackView(frame: stackViewFrame) - categories.enumerated().forEach { (idx, category) in - let containerFrame = CGRect(x: 0, y: 0, width: viewWidth, height: singleLineHeight) - let container = UIView(frame: containerFrame) - - let titleLabel = UILabel() - titleLabel.text = category - titleLabel.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(titleLabel) - NSLayoutConstraint.activate([ - titleLabel.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing), - titleLabel.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) - ]) + let titleInputItem = InputLineItem(category: "제목", inputView: titleTextfield) + let descriptionInputItem = InputLineItem(category: "설명", inputView: descriptionTextfield) + let backgroundColorInputItem = InputLineItem(category: "배경색", inputView: backgroundLabel) + stackView.configure(with: [titleInputItem, descriptionInputItem, backgroundColorInputItem]) - let contentView = contentViews[idx] - contentView.translatesAutoresizingMaskIntoConstraints = false - container.addSubview(contentView) - NSLayoutConstraint.activate([ - contentView.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing * 5), - contentView.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), - contentView.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) - ]) - stackView.addArrangedSubview(container) - } guard let backgroundEditView = stackView.arrangedSubviews.last else { return stackView } backgroundEditView.addSubview(randomColorButton) @@ -161,31 +136,16 @@ class LabelControlViewController: UIViewController { } private func addEditStackView() { - view.addSubview(newLabelEditStackView) + view.addSubview(labelEditStackView) NSLayoutConstraint.activate([ - newLabelEditStackView.heightAnchor.constraint(equalToConstant: singleLineHeight * 3), - newLabelEditStackView.topAnchor.constraint(equalTo: topMenuView.safeAreaLayoutGuide.bottomAnchor, constant: 40), - newLabelEditStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), - newLabelEditStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) + labelEditStackView.heightAnchor.constraint(equalToConstant: singleLineHeight * 3), + labelEditStackView.topAnchor.constraint(equalTo: topMenuView.safeAreaLayoutGuide.bottomAnchor, constant: 40), + labelEditStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + labelEditStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) ]) - addLoginStackViewDivisionLine() - } - - private func addLoginStackViewDivisionLine() { - let borderColor = Colors.border.cgColor - let borderWidth: CGFloat = 1 - let size = CGSize(width: view.frame.width - spacing, height: borderWidth) - - for i in 1...2 { - let line = CALayer() - let origin = CGPoint(x: spacing, y: singleLineHeight * CGFloat(i) - borderWidth) - line.frame = CGRect(origin: origin, size: size) - line.backgroundColor = borderColor - newLabelEditStackView.layer.addSublayer(line) - } } - + private func addLabelPreview() { let backgroundView = UIView() backgroundView.backgroundColor = UIColor.systemGray5 @@ -193,11 +153,12 @@ class LabelControlViewController: UIViewController { backgroundView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(backgroundView) backgroundView.addSubview(previewLabel) + NSLayoutConstraint.activate([ backgroundView.widthAnchor.constraint(equalToConstant: view.frame.width - spacing * 2), backgroundView.heightAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.widthAnchor, multiplier: 0.75), backgroundView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), - backgroundView.topAnchor.constraint(equalTo: newLabelEditStackView.safeAreaLayoutGuide.bottomAnchor, constant: 24), + backgroundView.topAnchor.constraint(equalTo: labelEditStackView.safeAreaLayoutGuide.bottomAnchor, constant: 24), previewLabel.centerXAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.centerXAnchor), previewLabel.centerYAnchor.constraint(equalTo: backgroundView.safeAreaLayoutGuide.centerYAnchor) ]) From 331f9229610965414c60d15bd8724d647bff29c5 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Fri, 18 Jun 2021 21:17:18 +0900 Subject: [PATCH 49/91] =?UTF-8?q?refactor:=20[#78]=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=88=98=EC=A0=95/=EC=B6=94=EA=B0=80=20=EB=B7=B0?= =?UTF-8?q?=EC=BB=A8=20=EC=82=AC=EC=9A=A9=EC=84=B1=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 8 - .../Controller/AddLabelViewController.swift | 35 ----- .../Controller/EditLabelViewController.swift | 49 ------ .../LabelControlViewController.swift | 115 +++++++------- .../Controller/LabelViewController.swift | 143 +++++++++++------- 5 files changed, 152 insertions(+), 198 deletions(-) delete mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift delete mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Controller/EditLabelViewController.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index afc5d5a66..e0b49218b 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -39,13 +39,11 @@ E43912DE2678A76D003CD344 /* RequestKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DD2678A76D003CD344 /* RequestKeys.swift */; }; E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */; }; E43912E22678AEB3003CD344 /* LabelTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */; }; - E43912E42679C0DA003CD344 /* AddLabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E32679C0DA003CD344 /* AddLabelViewController.swift */; }; E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */; }; E43912EA267A2351003CD344 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E9267A2351003CD344 /* NetworkError.swift */; }; E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912EB267B1A4E003CD344 /* LoginInfoDTO.swift */; }; E43912EE267C3C0E003CD344 /* CellAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912ED267C3C0E003CD344 /* CellAction.swift */; }; E43912F0267C3EED003CD344 /* LabelControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912EF267C3EED003CD344 /* LabelControlViewController.swift */; }; - E43912F2267C423A003CD344 /* EditLabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F1267C423A003CD344 /* EditLabelViewController.swift */; }; E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */; }; E43912F6267CAE01003CD344 /* TopMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F5267CAE01003CD344 /* TopMenuView.swift */; }; E43912F8267CB3D7003CD344 /* MultipleLineInputStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F7267CB3D7003CD344 /* MultipleLineInputStackView.swift */; }; @@ -96,13 +94,11 @@ E43912DD2678A76D003CD344 /* RequestKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestKeys.swift; sourceTree = ""; }; E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewDatasource.swift; sourceTree = ""; }; E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableDelegate.swift; sourceTree = ""; }; - E43912E32679C0DA003CD344 /* AddLabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddLabelViewController.swift; sourceTree = ""; }; E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewLabelDTO.swift; sourceTree = ""; }; E43912E9267A2351003CD344 /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; }; E43912EB267B1A4E003CD344 /* LoginInfoDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginInfoDTO.swift; sourceTree = ""; }; E43912ED267C3C0E003CD344 /* CellAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellAction.swift; sourceTree = ""; }; E43912EF267C3EED003CD344 /* LabelControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelControlViewController.swift; sourceTree = ""; }; - E43912F1267C423A003CD344 /* EditLabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditLabelViewController.swift; sourceTree = ""; }; E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITextFieldExtension.swift; sourceTree = ""; }; E43912F5267CAE01003CD344 /* TopMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopMenuView.swift; sourceTree = ""; }; E43912F7267CB3D7003CD344 /* MultipleLineInputStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipleLineInputStackView.swift; sourceTree = ""; }; @@ -315,8 +311,6 @@ E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */, E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */, E43912EF267C3EED003CD344 /* LabelControlViewController.swift */, - E43912E32679C0DA003CD344 /* AddLabelViewController.swift */, - E43912F1267C423A003CD344 /* EditLabelViewController.swift */, ); path = Controller; sourceTree = ""; @@ -478,8 +472,6 @@ E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */, E42AD11E267093320071B436 /* IssueViewController.swift in Sources */, E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */, - E43912E42679C0DA003CD344 /* AddLabelViewController.swift in Sources */, - E43912F2267C423A003CD344 /* EditLabelViewController.swift in Sources */, E43912DC2678A737003CD344 /* JWT.swift in Sources */, E43912E22678AEB3003CD344 /* LabelTableDelegate.swift in Sources */, E426DABA2670EC2D0069E77D /* AppleAuthorizationManager.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift deleted file mode 100644 index dd9a6db1e..000000000 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/AddLabelViewController.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// AddLabelViewController.swift -// issue-tracker -// -// Created by Song on 2021/06/16. -// - -import UIKit - -final class AddLabelViewController: LabelControlViewController { - override func saveButtonTouched(_ sender: UIBarButtonItem) { - super.saveButtonTouched(sender) - guard let labelTitle = titleTextfield.text, let colorCode = backgroundLabel.text else { return } - - let newLabel = NewLabelDTO(name: labelTitle, - content: descriptionTextfield.text ?? "", - colorCode: colorCode) - postNewLabel(newLabel) - } - - private func postNewLabel(_ newLabel: NewLabelDTO) { - let newLabelEndpoint = EndPoint.label.path() - networkManager?.post(endpoint: newLabelEndpoint, requestBody: newLabel, completion: { [weak self] result in - switch result { - case .success(_): - self?.dismiss(animated: true, completion: { - guard let dismissOperation = self?.dismissOperation else { return } - dismissOperation() - }) - case .failure(let error): - self?.presentAlert(with: error.description) - } - }) - } -} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/EditLabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/EditLabelViewController.swift deleted file mode 100644 index beaf84e7f..000000000 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/EditLabelViewController.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// EditLabelViewController.swift -// issue-tracker -// -// Created by Song on 2021/06/18. -// - -import UIKit - -class EditLabelViewController: LabelControlViewController { - - private var labelToEdit: Label? - - func setLabelToEdit(label: Label) { - self.labelToEdit = label - - titleTextfield.text = label.title - descriptionTextfield.text = label.body - backgroundLabel.text = label.hexColorCode - } - - override func saveButtonTouched(_ sender: UIBarButtonItem) { - super.saveButtonTouched(sender) - guard let labelTitle = titleTextfield.text, let colorCode = backgroundLabel.text else { return } - - let editedLabel = NewLabelDTO(name: labelTitle, - content: descriptionTextfield.text ?? "", - colorCode: colorCode) - putLabel(editedLabel) - } - - private func putLabel(_ editedLabel: NewLabelDTO) { - guard let labelId = labelToEdit?.id else { return } - let editLabelEndpoint = EndPoint.label.path(with: labelId) - - networkManager?.put(endpoint: editLabelEndpoint, requestBody: editedLabel, completion: { [weak self] result in - switch result { - case .success(_): - self?.dismiss(animated: true, completion: { - guard let dismissOperation = self?.dismissOperation else { return } - dismissOperation() - }) - case .failure(let error): - self?.presentAlert(with: error.description) - } - }) - } - -} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift index 0f0592dc3..dcdba493b 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelControlViewController.swift @@ -56,19 +56,19 @@ class LabelControlViewController: UIViewController { return stackView }() - lazy var titleTextfield: UITextField = { + private lazy var titleTextfield: UITextField = { let textField = UITextField() textField.placeholder = "(필수 입력)" return textField }() - lazy var descriptionTextfield: UITextField = { + private lazy var descriptionTextfield: UITextField = { let textField = UITextField() textField.placeholder = "(선택 사항)" return textField }() - lazy var backgroundLabel: UILabel = { + private lazy var backgroundLabel: UILabel = { let label = UILabel() label.text = "#000000" return label @@ -102,28 +102,23 @@ class LabelControlViewController: UIViewController { return singleLineHeight * 0.5 }() - private var loginInfo: LoginInfo? - var sceneTitle: String? - var networkManager: NetworkManagerOperations? - var dismissOperation: (() -> Void)? + private var currentLabel: Label? + private var sceneTitle: String? + private var saveOperation: ((Label) -> Void)? override func viewDidLoad() { super.viewDidLoad() + configureViews() + setTitleTextFieldSupporter() + } + + private func configureViews() { view.backgroundColor = Colors.background - addTopMenu() addEditStackView() addLabelPreview() - setNetworkManager() - titleTextfield.delegate = self - } - - private func changeSaveButtonEnableStatus(baseOn textField: UITextField) { - DispatchQueue.main.async { - self.saveButton.isEnabled = !textField.isEmpty() - } } - + private func addTopMenu() { view.addSubview(topMenuView) @@ -164,59 +159,64 @@ class LabelControlViewController: UIViewController { ]) } - func setSceneTitle(title: String) { - self.sceneTitle = title - } - - func setUpDismissOperation(_ operation: @escaping () -> Void) { - self.dismissOperation = operation + private func setTitleTextFieldSupporter() { + titleTextfield.delegate = self } - func presentAlert(with errorMessage: String) { - DispatchQueue.main.async { - let alert = AlertFactory.create(body: errorMessage) - self.present(alert, animated: true, completion: nil) - } - } - - private func randomColor() -> String { - let colorRange = 0...255 - let randomRed = Int.random(in: colorRange) - let randomGreen = Int.random(in: colorRange) - let randomBlue = Int.random(in: colorRange) + func configure(withTitle sceneTitle: String, currentLabel: Label?) { + self.sceneTitle = sceneTitle + self.currentLabel = currentLabel - let hexRed = String(randomRed, radix: 16) - let hexGreen = String(randomGreen, radix: 16) - let hexBlue = String(randomBlue, radix: 16) - return "#\(hexRed)\(hexGreen)\(hexBlue)" + setUpCurrentLabelInfo() } - private func changePreviewLabel() { - let hexColorString = backgroundLabel.text ?? "#000000" - let hex = HexColorCode(from: hexColorString) - let titleText = titleTextfield.isEmpty() ? "레이블" : titleTextfield.text - previewLabel.configure(with: hex, titleText) + private func setUpCurrentLabelInfo() { + guard let currentLabel = currentLabel else { return } + titleTextfield.text = currentLabel.title + descriptionTextfield.text = currentLabel.body + backgroundLabel.text = currentLabel.hexColorCode } - private func setNetworkManager() { - let loginInfo = LoginInfo.shared - guard let jwt = loginInfo.jwt else { return } - let headers = [Header.authorization.key(): jwt.description] - networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) + func setSaveOperation(_ operation: @escaping (Label) -> Void) { + self.saveOperation = operation } @objc private func cancelButtonTouched(_ sender: UIBarButtonItem) { dismiss(animated: true, completion: nil) } - ///이 메소드를 오버라이드하여 레이블 생성 or 수정 구현 - @objc func saveButtonTouched(_ sender: UIBarButtonItem) { } + @objc func saveButtonTouched(_ sender: UIBarButtonItem) { + guard let labelTitle = titleTextfield.text, + let colorCode = backgroundLabel.text, + let saveOperation = saveOperation else { return } + + let label = Label(id: currentLabel?.id ?? -1, + title: labelTitle, + body: descriptionTextfield.text ?? "", + hexColorCode: colorCode) + + saveOperation(label) + dismiss(animated: true, completion: nil) + } @objc private func randomColorButtonTouched(_ sender: UIButton) { let hexColor = randomColor() backgroundLabel.text = hexColor changePreviewLabel() } + + private func randomColor() -> String { + let colorRange = 0...255 + let randomRed = Int.random(in: colorRange) + let randomGreen = Int.random(in: colorRange) + let randomBlue = Int.random(in: colorRange) + + let hexRed = String(randomRed, radix: 16) + let hexGreen = String(randomGreen, radix: 16) + let hexBlue = String(randomBlue, radix: 16) + + return "#\(hexRed)\(hexGreen)\(hexBlue)" + } } extension LabelControlViewController: UITextFieldDelegate { @@ -224,4 +224,17 @@ extension LabelControlViewController: UITextFieldDelegate { changeSaveButtonEnableStatus(baseOn: textField) changePreviewLabel() } + + private func changeSaveButtonEnableStatus(baseOn textField: UITextField) { + DispatchQueue.main.async { + self.saveButton.isEnabled = !textField.isEmpty() + } + } + + private func changePreviewLabel() { + let hexColorString = backgroundLabel.text ?? "#000000" + let hex = HexColorCode(from: hexColorString) + let titleText = titleTextfield.isEmpty() ? "레이블" : titleTextfield.text + previewLabel.configure(with: hex, titleText) + } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index fe26b8814..991ef762c 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -26,6 +26,7 @@ final class LabelViewController: UIViewController { return tableView }() + private let sceneTitle = "레이블" private let colorConverter: HexColorConvertable = HexColorConverter() private var networkManager: NetworkManagerOperations? private var labelTableDatasource: LabelTableViewDatasource? @@ -33,18 +34,8 @@ final class LabelViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = UIColor.white - title = "레이블" - - addNavigationButton() - addTableView() - - labelTableDatasource = LabelTableViewDatasource() - labelTableView.dataSource = labelTableDatasource - - labelTableDelegate = LabelTableDelegate(cellActionHandler: swipeActionHandler) - labelTableView.delegate = labelTableDelegate - + configureViews() + setTableViewSupporters() setNetworkManager() } @@ -53,6 +44,14 @@ final class LabelViewController: UIViewController { loadData() } + private func configureViews() { + view.backgroundColor = UIColor.white + title = sceneTitle + + addNavigationButton() + addTableView() + } + private func addNavigationButton() { navigationItem.rightBarButtonItem = UIBarButtonItem(customView: addLabelButton) } @@ -68,43 +67,12 @@ final class LabelViewController: UIViewController { ]) } - private func swipeActionHandler(_ index: Int, _ action: CellAction) { - guard let targetLabel = labelTableDatasource?.labels[index] else { return } - - switch action { - case .delete: - deleteLabel(for: targetLabel.id) - case .edit: - presentEditLabelViewController(for: targetLabel) - default: - assert(false) - } - } - - private func deleteLabel(for id: Int) { - let deleteLabelEndpoint = EndPoint.label.path(with: id) - networkManager?.delete(endpoint: deleteLabelEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in - switch result { - case .success(_): - self?.loadData() - case .failure(let error): - self?.presentAlert(with: error.description) - } - }) - } - - private func presentEditLabelViewController(for targetLabel: Label) { - let editLabelViewController = EditLabelViewController() - editLabelViewController.setSceneTitle(title: "레이블 수정하기") - editLabelViewController.setLabelToEdit(label: targetLabel) - editLabelViewController.modalPresentationStyle = .formSheet - editLabelViewController.setUpDismissOperation { [weak self] in - self?.loadData() - } + private func setTableViewSupporters() { + labelTableDatasource = LabelTableViewDatasource() + labelTableView.dataSource = labelTableDatasource - DispatchQueue.main.async { - self.present(editLabelViewController, animated: true, completion: nil) - } + labelTableDelegate = LabelTableDelegate(cellActionHandler: swipeActionHandler) + labelTableView.delegate = labelTableDelegate } private func setNetworkManager() { @@ -114,7 +82,7 @@ final class LabelViewController: UIViewController { networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) } - func loadData() { + private func loadData() { let labelListEndpoint = EndPoint.label.path() networkManager?.get(endpoint: labelListEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in @@ -135,6 +103,30 @@ final class LabelViewController: UIViewController { } } + private func swipeActionHandler(_ index: Int, _ action: CellAction) { + guard let targetLabel = labelTableDatasource?.labels[index] else { return } + + switch action { + case .delete: + deleteLabel(for: targetLabel.id) + case .edit: + presentEditLabelViewController(for: targetLabel) + default: + assert(false) + } + } + + private func presentEditLabelViewController(for targetLabel: Label) { + let editLabelViewController = LabelControlViewController() + editLabelViewController.configure(withTitle: "레이블 수정하기", currentLabel: targetLabel) + editLabelViewController.setSaveOperation(putEditedLabel) + editLabelViewController.modalPresentationStyle = .formSheet + + DispatchQueue.main.async { + self.present(editLabelViewController, animated: true, completion: nil) + } + } + private func presentAlert(with errorMessage: String) { DispatchQueue.main.async { let alert = AlertFactory.create(body: errorMessage) @@ -143,16 +135,57 @@ final class LabelViewController: UIViewController { } @objc private func addLabelTouched(_ sender: UIButton) { - let addLabelViewController = AddLabelViewController() - addLabelViewController.setSceneTitle(title: "새로운 레이블") + let addLabelViewController = LabelControlViewController() + addLabelViewController.configure(withTitle: "새로운 레이블", currentLabel: nil) + addLabelViewController.setSaveOperation(postNewLabel) addLabelViewController.modalPresentationStyle = .formSheet - addLabelViewController.setUpDismissOperation { [weak self] in - self?.loadData() - } - + DispatchQueue.main.async { self.present(addLabelViewController, animated: true, completion: nil) } } } +//MARK: - Network Methods +extension LabelViewController { + private func deleteLabel(for id: Int) { + let deleteLabelEndpoint = EndPoint.label.path(with: id) + networkManager?.delete(endpoint: deleteLabelEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in + switch result { + case .success(_): + self?.loadData() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } + + private func postNewLabel(_ newLabel: Label) { + let newLabelEndpoint = EndPoint.label.path() + let requestBody = NewLabelDTO(name: newLabel.title, content: newLabel.body, colorCode: newLabel.hexColorCode) + + networkManager?.post(endpoint: newLabelEndpoint, requestBody: requestBody, completion: { [weak self] result in + switch result { + case .success(_): + self?.loadData() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } + + private func putEditedLabel(_ editedLabel: Label) { + let labelId = editedLabel.id + let editLabelEndpoint = EndPoint.label.path(with: labelId) + let requestBody = NewLabelDTO(name: editedLabel.title, content: editedLabel.body, colorCode: editedLabel.hexColorCode) + + networkManager?.put(endpoint: editLabelEndpoint, requestBody: requestBody, completion: { [weak self] result in + switch result { + case .success(_): + self?.loadData() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } +} From eba831c3f81927a85c5ce6dcd1367598a5396662 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Sat, 19 Jun 2021 17:50:43 +0900 Subject: [PATCH 50/91] =?UTF-8?q?feat:=20[#68]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20GET=20=ED=86=B5=EC=8B=A0=20=EB=B7=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../View/MileStoneTableViewCell.swift | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index 9e3f69afc..d0d5d0fee 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -74,7 +74,6 @@ class MileStoneTableViewCell: UITableViewCell { //MARK: 4 : sub스택 // -1 열린 이슈 라벨 // -2 닫힌 이슈 라벨 - private lazy var milestoneLabelSubStackView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal @@ -108,12 +107,10 @@ class MileStoneTableViewCell: UITableViewCell { } private func setViews() { - addMileStoneStackView() - test() + addMileStoneStackView() } private func addMileStoneStackView() { - addSubview(mileStoneStackView) NSLayoutConstraint.activate([ mileStoneStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16), @@ -125,9 +122,7 @@ class MileStoneTableViewCell: UITableViewCell { //MARK: 1 : sub스택 // -1 Title 라벨 // -2 몇 %인지 보이는 두개의 라벨 - - //titleLabel, titleLabel 자체에 너비를 비율을 맞추어놓고 설정을 해주기. - //firstSubStackView를 .fillProptionally로 바꾸어주기. + mileStoneStackView.addArrangedSubview(firstSubStackView) NSLayoutConstraint.activate([ @@ -163,7 +158,6 @@ class MileStoneTableViewCell: UITableViewCell { NSLayoutConstraint.activate([ milestoneLabelSubStackView.leadingAnchor.constraint(equalTo: mileStoneStackView.leadingAnchor), -// milestoneLabelSubStackView.widthAnchor.constraint(equalToConstant: mileStoneStackView.frame.width * 0.5) milestoneLabelSubStackView.trailingAnchor.constraint(equalTo: mileStoneStackView.trailingAnchor) ]) @@ -174,17 +168,15 @@ class MileStoneTableViewCell: UITableViewCell { milestoneLabelSubStackView.spacing = 4 - NSLayoutConstraint.activate([ + //스택fill 이슈 +// NSLayoutConstraint.activate([ // openMilestoneLabelView.widthAnchor // .constraint(lessThanOrEqualTo: milestoneLabelSubStackView.widthAnchor, multiplier: 0.329), // closeMilestoneLabelView.widthAnchor // .constraint(lessThanOrEqualTo: milestoneLabelSubStackView.widthAnchor, multiplier: 0.329) - ]) +// ]) } - func test(){ - - } func configure(title: String, description: String, due_date: String) { titleLabel.text = title descriptionLabel.text = description From a450359a21979d85766a8bf6b088962b0e184860 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Sat, 19 Jun 2021 17:56:17 +0900 Subject: [PATCH 51/91] =?UTF-8?q?merge=20:[#78]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20=EB=B7=B0=EC=97=90=20EndPoint=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=20=EB=A8=B8=EC=A7=80=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Milestone/Controller/MilestoneViewController.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift index 3d0c48bbc..8931b893c 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift @@ -72,14 +72,16 @@ class MilestoneViewController: UIViewController { private func setNetworkManager() { let loginInfo = LoginInfo.shared guard let jwt = loginInfo.jwt else { return } - let url = EndPoint.milestone.fullAddress() +// let url = EndPoint.milestone.fullAddress() let headers = [Header.authorization.key(): jwt.description] - let requestManager = RequestManager(url: url, headers: headers) - networkManager = NetworkManager(requestManager: requestManager) +// let requestManager = RequestManager(url: url, headers: headers) + networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) } func loadData() { - networkManager?.get(queryParameters: nil, completion: { [weak self] (result: Result) in + let mileStoneListEndpoint = + EndPoint.milestone.path() + networkManager?.get(endpoint: mileStoneListEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in switch result { case .success(let result): guard let mileStone = result.data else { return } From 893a6c46d6b335364359e7a5fe74b107b786a47e Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Sun, 20 Jun 2021 18:24:40 +0900 Subject: [PATCH 52/91] =?UTF-8?q?feat=20:[#68]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EB=84=A4?= =?UTF-8?q?=ED=8A=B8=EC=9B=8C=ED=81=AC=20=ED=86=B5=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 16 +- .../MileStoneControlViewController.swift | 164 ++++++++++++++++++ ...er.swift => MileStoneViewController.swift} | 57 +++++- .../MilestoneTableViewDataSource.swift | 2 +- .../Main/Milestone/Model/Milestone.swift | 4 +- .../Milestone/Model/NewMileStoneDTO.swift | 21 +++ .../TabBar/IssueTrackerTabBarCreator.swift | 2 +- 7 files changed, 254 insertions(+), 12 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift rename iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/{MilestoneViewController.swift => MileStoneViewController.swift} (60%) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Milestone/Model/NewMileStoneDTO.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index f113d7925..44ecc317e 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -24,7 +24,7 @@ E42AD1182670886F0071B436 /* IssueTrackerTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD1172670886F0071B436 /* IssueTrackerTabBarController.swift */; }; E42AD11E267093320071B436 /* IssueViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD11D267093320071B436 /* IssueViewController.swift */; }; E42AD120267093430071B436 /* LabelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD11F267093430071B436 /* LabelViewController.swift */; }; - E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD121267093590071B436 /* MilestoneViewController.swift */; }; + E42AD122267093590071B436 /* MileStoneViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD121267093590071B436 /* MileStoneViewController.swift */; }; E42AD124267093700071B436 /* MyAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD123267093700071B436 /* MyAccountViewController.swift */; }; E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E42AD12526709C010071B436 /* UIViewControllerExtension.swift */; }; E43912C726776D8F003CD344 /* LabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912C626776D8F003CD344 /* LabelView.swift */; }; @@ -51,6 +51,8 @@ E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; + FA431FF9267F36FA0010EA91 /* MileStoneControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA431FF8267F36FA0010EA91 /* MileStoneControlViewController.swift */; }; + FA431FFB267F3B680010EA91 /* NewMileStoneDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA431FFA267F3B680010EA91 /* NewMileStoneDTO.swift */; }; FA733A2E267C3D77005A40C8 /* Milestone.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A2D267C3D77005A40C8 /* Milestone.swift */; }; FA733A30267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A2F267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift */; }; FA733A32267C3EAA005A40C8 /* MileStoneTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A31267C3EAA005A40C8 /* MileStoneTableDelegate.swift */; }; @@ -84,7 +86,7 @@ E42AD1172670886F0071B436 /* IssueTrackerTabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarController.swift; sourceTree = ""; }; E42AD11D267093320071B436 /* IssueViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueViewController.swift; sourceTree = ""; }; E42AD11F267093430071B436 /* LabelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelViewController.swift; sourceTree = ""; }; - E42AD121267093590071B436 /* MilestoneViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MilestoneViewController.swift; sourceTree = ""; }; + E42AD121267093590071B436 /* MileStoneViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneViewController.swift; sourceTree = ""; }; E42AD123267093700071B436 /* MyAccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAccountViewController.swift; sourceTree = ""; }; E42AD12526709C010071B436 /* UIViewControllerExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerExtension.swift; sourceTree = ""; }; E43912C626776D8F003CD344 /* LabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelView.swift; sourceTree = ""; }; @@ -111,6 +113,8 @@ E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; + FA431FF8267F36FA0010EA91 /* MileStoneControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneControlViewController.swift; sourceTree = ""; }; + FA431FFA267F3B680010EA91 /* NewMileStoneDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewMileStoneDTO.swift; sourceTree = ""; }; FA733A2D267C3D77005A40C8 /* Milestone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Milestone.swift; sourceTree = ""; }; FA733A2F267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MilestoneTableViewDataSource.swift; sourceTree = ""; }; FA733A31267C3EAA005A40C8 /* MileStoneTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneTableDelegate.swift; sourceTree = ""; }; @@ -352,6 +356,7 @@ isa = PBXGroup; children = ( FA733A2D267C3D77005A40C8 /* Milestone.swift */, + FA431FFA267F3B680010EA91 /* NewMileStoneDTO.swift */, ); path = Model; sourceTree = ""; @@ -367,9 +372,10 @@ FAB2C36826789AE6009F879C /* Controller */ = { isa = PBXGroup; children = ( - E42AD121267093590071B436 /* MilestoneViewController.swift */, + E42AD121267093590071B436 /* MileStoneViewController.swift */, FA733A2F267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift */, FA733A31267C3EAA005A40C8 /* MileStoneTableDelegate.swift */, + FA431FF8267F36FA0010EA91 /* MileStoneControlViewController.swift */, ); path = Controller; sourceTree = ""; @@ -487,6 +493,7 @@ FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */, E426DABC2670EC5E0069E77D /* LoginInfo.swift in Sources */, E43912CE26777310003CD344 /* HexColorConverter.swift in Sources */, + FA431FFB267F3B680010EA91 /* NewMileStoneDTO.swift in Sources */, E42AD1182670886F0071B436 /* IssueTrackerTabBarController.swift in Sources */, E43912F0267C3EED003CD344 /* LabelControlViewController.swift in Sources */, E43912DE2678A76D003CD344 /* RequestKeys.swift in Sources */, @@ -500,9 +507,10 @@ E43912C726776D8F003CD344 /* LabelView.swift in Sources */, FA733A32267C3EAA005A40C8 /* MileStoneTableDelegate.swift in Sources */, E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */, + FA431FF9267F36FA0010EA91 /* MileStoneControlViewController.swift in Sources */, E43912EA267A2351003CD344 /* NetworkError.swift in Sources */, E43912F6267CAE01003CD344 /* TopMenuView.swift in Sources */, - E42AD122267093590071B436 /* MilestoneViewController.swift in Sources */, + E42AD122267093590071B436 /* MileStoneViewController.swift in Sources */, FA733A2E267C3D77005A40C8 /* Milestone.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift new file mode 100644 index 000000000..dc97a63f8 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift @@ -0,0 +1,164 @@ +// +// MileStoneControlViewController.swift +// issue-tracker +// +// Created by jinseo park on 6/20/21. +// + +import Foundation +import UIKit + +class MileStoneControlViewController: UIViewController { + + private lazy var topMenuView: TopMenuView = { + let topMenuView = TopMenuView() + topMenuView.configure(withTitle: sceneTitle, rightButton: saveButton, leftButton: cancelButton) + topMenuView.translatesAutoresizingMaskIntoConstraints = false + return topMenuView + }() + + private lazy var saveButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "", "저장") + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(saveButtonTouched), for: .touchUpInside) + changeSaveButtonEnableStatus(baseOn: titleTextfield) + return button + }() + + private lazy var cancelButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "chevron.backward", "취소") + button.moveImageToLeft() + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(cancelButtonTouched), for: .touchUpInside) + return button + }() + + private lazy var mileStoneEditStackView: MultipleLineInputStackView = { + let viewWidth = view.frame.width + let stackViewFrame = CGRect(x: 0, y: 0, width: viewWidth, height: singleLineHeight * 3) + let stackView = MultipleLineInputStackView(frame: stackViewFrame) + + let titleInputItem = InputLineItem(category: "제목", inputView: titleTextfield) + let descriptionInputItem = InputLineItem(category: "설명", inputView: descriptionTextfield) + let completeDateInputItem = InputLineItem(category: "완료일", inputView: completeDateMileStone) + stackView.configure(with: [titleInputItem, descriptionInputItem, completeDateInputItem]) + + return stackView + }() + + private lazy var titleTextfield: UITextField = { + let textField = UITextField() + textField.placeholder = "(필수 입력)" + return textField + }() + + private lazy var descriptionTextfield: UITextField = { + let textField = UITextField() + textField.placeholder = "(선택 사항)" + return textField + }() + + private lazy var completeDateMileStone: UITextField = { + let textField = UITextField() + textField.placeholder = "YYYY-MM-DD(선택사항)" + return textField + }() + + private lazy var previewLabel: LabelView = { + let labelView = LabelView() + let colorText = completeDateMileStone.text ?? "YYYY-MM-DD(선택사항)" + let hex = HexColorCode(from: colorText) + let titleText = titleTextfield.isEmpty() ? "레이블" : titleTextfield.text + labelView.configure(with: hex, titleText) + labelView.translatesAutoresizingMaskIntoConstraints = false + return labelView + }() + + private lazy var singleLineHeight: CGFloat = { + return view.frame.height * 0.05 + }() + + private lazy var spacing: CGFloat = { + return singleLineHeight * 0.5 + }() + + private var currentMileStone: MileStone? + private var sceneTitle: String? + private var saveOperation: ((MileStone) -> Void)? + + override func viewDidLoad() { + super.viewDidLoad() + configureViews() + setTitleTextFieldSupporter() + } + + private func configureViews() { + view.backgroundColor = Colors.background + addTopMenu() + addEditStackView() + } + + private func addTopMenu() { + view.addSubview(topMenuView) + + NSLayoutConstraint.activate([ + topMenuView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + topMenuView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + topMenuView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: spacing), + topMenuView.heightAnchor.constraint(equalToConstant: singleLineHeight) + ]) + } + + private func addEditStackView() { + view.addSubview(mileStoneEditStackView) + + NSLayoutConstraint.activate([ + mileStoneEditStackView.heightAnchor.constraint(equalToConstant: singleLineHeight * 3), + mileStoneEditStackView.topAnchor.constraint(equalTo: topMenuView.safeAreaLayoutGuide.bottomAnchor, constant: 40), + mileStoneEditStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + mileStoneEditStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) + ]) + } + + private func setTitleTextFieldSupporter() { + titleTextfield.delegate = self + } + + func configure(withTitle sceneTitle: String, currentMileStone: MileStone?) { + self.sceneTitle = sceneTitle + self.currentMileStone = currentMileStone + } + + func setSaveOperation(_ operation: @escaping (MileStone) -> Void) { + self.saveOperation = operation + } + + @objc private func cancelButtonTouched(_ sender: UIBarButtonItem) { + dismiss(animated: true, completion: nil) + } + + @objc func saveButtonTouched(_ sender: UIBarButtonItem) { + guard let mileStoneTitle = titleTextfield.text, + let completeDtae = completeDateMileStone.text, + let saveOperation = saveOperation else { return } + + let mileStone = MileStone(id: currentMileStone?.id ?? -1, title: mileStoneTitle, description: descriptionTextfield.text ?? "", due_date: completeDtae) + saveOperation(mileStone) + dismiss(animated: true, completion: nil) + } +} + +extension MileStoneControlViewController: UITextFieldDelegate { + func textFieldDidChangeSelection(_ textField: UITextField) { + changeSaveButtonEnableStatus(baseOn: textField) + } + + private func changeSaveButtonEnableStatus(baseOn textField: UITextField) { + DispatchQueue.main.async { + self.saveButton.isEnabled = !textField.isEmpty() + } + } + +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift similarity index 60% rename from iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift rename to iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift index 8931b893c..3e8b8f805 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift @@ -7,7 +7,7 @@ import UIKit -class MilestoneViewController: UIViewController { +class MileStoneViewController: UIViewController { private lazy var addMileStoneButton: ImageBarButton = { let button = ImageBarButton() @@ -27,7 +27,14 @@ class MilestoneViewController: UIViewController { }() @objc private func addMileStoneTouched(_ sender: UIButton) { - print("마일스톤 추가해줘잉") + let addMileStoneViewController = MileStoneControlViewController() + addMileStoneViewController.configure(withTitle: "새로운 마일스톤", currentMileStone: nil) + addMileStoneViewController.setSaveOperation(postNewMileStone) + addMileStoneViewController.modalPresentationStyle = .formSheet + + DispatchQueue.main.async { + self.present(addMileStoneViewController, animated: true, completion: nil) + } } private var networkManager: NetworkManagerOperations? @@ -72,9 +79,7 @@ class MilestoneViewController: UIViewController { private func setNetworkManager() { let loginInfo = LoginInfo.shared guard let jwt = loginInfo.jwt else { return } -// let url = EndPoint.milestone.fullAddress() let headers = [Header.authorization.key(): jwt.description] -// let requestManager = RequestManager(url: url, headers: headers) networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) } @@ -105,3 +110,47 @@ class MilestoneViewController: UIViewController { } } } + +//MARK: - Network Methods +extension MileStoneViewController { +// private func deleteMileStone(for id: Int) { +// let deleteLabelEndpoint = EndPoint.milestone.path(with: id) +// networkManager?.delete(endpoint: deleteLabelEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in +// switch result { +// case .success(_): +// self?.loadData() +// case .failure(let error): +// self?.presentAlert(with: error.description) +// } +// }) +// } + + private func postNewMileStone(_ newMileStone: MileStone) { + let newLabelEndpoint = EndPoint.milestone.path() + let requestBody = NewMileStoneDTO(title: newMileStone.title, description: newMileStone.description ?? "", due_date: newMileStone.due_date ?? "") + + networkManager?.post(endpoint: newLabelEndpoint, requestBody: requestBody, completion: { [weak self] result in + switch result { + case .success(_): + self?.loadData() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } + +// private func putEditedMileStone(_ editedLabel: MileStone) { +// let labelId = editedLabel.id +// let editLabelEndpoint = EndPoint.milestone.path(with: labelId) +// let requestBody = NewLabelDTO(name: editedLabel.title, content: editedLabel.body, colorCode: editedLabel.hexColorCode) +// +// networkManager?.put(endpoint: editLabelEndpoint, requestBody: requestBody, completion: { [weak self] result in +// switch result { +// case .success(_): +// self?.loadData() +// case .failure(let error): +// self?.presentAlert(with: error.description) +// } +// }) +// } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift index f1b52753d..9b0d25402 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift @@ -25,7 +25,7 @@ class MilestoneTableViewDataSource: NSObject, UITableViewDataSource { let milesonte = milestones[indexPath.row] - cell.configure(title: milesonte.title, description: milesonte.description, due_date: milesonte.due_date) + cell.configure(title: milesonte.title, description: milesonte.description ?? "", due_date: milesonte.due_date ?? "") return cell } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift index 2db0ca783..695a05f06 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift @@ -21,8 +21,8 @@ struct MileStoneDTO: Decodable { struct MileStone: Decodable { let id: Int let title: String - let description: String - let due_date: String + let description: String? + let due_date: String? enum CodingKeys: String, CodingKey { case id diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/NewMileStoneDTO.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/NewMileStoneDTO.swift new file mode 100644 index 000000000..31874fb2e --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/NewMileStoneDTO.swift @@ -0,0 +1,21 @@ +// +// NewMileStoneDTO.swift +// issue-tracker +// +// Created by jinseo park on 6/20/21. +// + +import Foundation + +struct NewMileStoneDTO: Encodable { + + let title: String + let description: String + let due_date: String + + enum CodingKeys: String, CodingKey { + case title + case description + case due_date + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift index 780570145..142169526 100644 --- a/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift +++ b/iOS/issue-tracker/issue-tracker/Main/TabBar/IssueTrackerTabBarCreator.swift @@ -34,7 +34,7 @@ final class IssueTrackerTabBarCreator { convenience init() { let issue = TabBarChildInfo(title: Title.issue, imageName: SystemImageName.issue, type: IssueViewController.self) let label = TabBarChildInfo(title: Title.label, imageName: SystemImageName.label, type: LabelViewController.self) - let milestone = TabBarChildInfo(title: Title.milestone, imageName: SystemImageName.milestone, type: MilestoneViewController.self) + let milestone = TabBarChildInfo(title: Title.milestone, imageName: SystemImageName.milestone, type: MileStoneViewController.self) let myAccount = TabBarChildInfo(title: Title.myAccount, imageName: SystemImageName.myAccount, type: MyAccountViewController.self) self.init(childInfos: [issue, label, milestone, myAccount]) } From 09422dfce1547c2fe9773ac83425d59cb36000c6 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Sun, 20 Jun 2021 19:42:17 +0900 Subject: [PATCH 53/91] =?UTF-8?q?feat=20:[#68]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=ED=86=B5=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/MileStoneTableDelegate.swift | 28 ++++++ .../Controller/MileStoneViewController.swift | 92 ++++++++++++------- .../MilestoneTableViewDataSource.swift | 2 +- 3 files changed, 88 insertions(+), 34 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift index 4752439ca..04ae4e7b0 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift @@ -7,7 +7,35 @@ import UIKit class MileStoneTableDelegate: NSObject, UITableViewDelegate { + + typealias CellActionHandler = (Int, CellAction) -> Void + private var cellActionHandler: CellActionHandler + + init(cellActionHandler: @escaping CellActionHandler) { + self.cellActionHandler = cellActionHandler + } + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return tableView.frame.height * 0.233 } + + func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { + let deleteAction = UIContextualAction(style: .destructive, + title: CellAction.delete.buttonTitle()) { [weak self] _, _, _ in + self?.cellActionHandler(indexPath.row, .delete) + } + deleteAction.image = UIImage(systemName: "trash") + + let editAction = UIContextualAction(style: .normal, + title: CellAction.edit.buttonTitle()) { [weak self] _, _, _ in + self?.cellActionHandler(indexPath.row, .edit) + } + editAction.image = UIImage(systemName: "pencil") + + /*넣은 UIContextualAction index의 역순으로 화면에 나타난다. + [deleteAction,editAction] 를 넣었지만 실제 화면에서 Swipe-left 시 + 편집,삭제 형태로 보여지게된다. + */ + return UISwipeActionsConfiguration(actions: [deleteAction,editAction]) + } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift index 3e8b8f805..7abc21bc4 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift @@ -47,12 +47,7 @@ class MileStoneViewController: UIViewController { title = "마일스톤" addNavigationButton() addTableView() - - mileStoneTableDatasource = MilestoneTableViewDataSource() - mileStoneTableDelegate = MileStoneTableDelegate() - mileStoneTableView.dataSource = mileStoneTableDatasource - mileStoneTableView.delegate = mileStoneTableDelegate - + setTableViewSupporters() setNetworkManager() } @@ -76,6 +71,14 @@ class MileStoneViewController: UIViewController { ]) } + private func setTableViewSupporters() { + mileStoneTableDatasource = MilestoneTableViewDataSource() + mileStoneTableView.dataSource = mileStoneTableDatasource + + mileStoneTableDelegate = MileStoneTableDelegate(cellActionHandler: swipeActionHandler) + mileStoneTableView.delegate = mileStoneTableDelegate + } + private func setNetworkManager() { let loginInfo = LoginInfo.shared guard let jwt = loginInfo.jwt else { return } @@ -109,27 +112,50 @@ class MileStoneViewController: UIViewController { self.mileStoneTableView.reloadData() } } + private func swipeActionHandler(_ index: Int, _ action: CellAction) { + guard let targetMileStone = mileStoneTableDatasource?.milestones[index] else { return } + + switch action { + case .edit: + presentEditMileStoneViewController(for: targetMileStone) + case .delete: + deleteMileStone(for: targetMileStone.id) + default: + assert(false) + } + } + + private func presentEditMileStoneViewController(for targetMileStone: MileStone) { + let editMileStoneViewController = MileStoneControlViewController() + editMileStoneViewController.configure(withTitle: "마일스톤 수정하기", currentMileStone: targetMileStone) + editMileStoneViewController.setSaveOperation(putEditedMileStone) + editMileStoneViewController.modalPresentationStyle = .formSheet + + DispatchQueue.main.async { + self.present(editMileStoneViewController, animated: true, completion: nil) + } + } } //MARK: - Network Methods extension MileStoneViewController { -// private func deleteMileStone(for id: Int) { -// let deleteLabelEndpoint = EndPoint.milestone.path(with: id) -// networkManager?.delete(endpoint: deleteLabelEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in -// switch result { -// case .success(_): -// self?.loadData() -// case .failure(let error): -// self?.presentAlert(with: error.description) -// } -// }) -// } + private func deleteMileStone(for id: Int) { + let deleteMileStoneEndpoint = EndPoint.milestone.path(with: id) + networkManager?.delete(endpoint: deleteMileStoneEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in + switch result { + case .success(_): + self?.loadData() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } private func postNewMileStone(_ newMileStone: MileStone) { - let newLabelEndpoint = EndPoint.milestone.path() + let newMileStoneEndpoint = EndPoint.milestone.path() let requestBody = NewMileStoneDTO(title: newMileStone.title, description: newMileStone.description ?? "", due_date: newMileStone.due_date ?? "") - networkManager?.post(endpoint: newLabelEndpoint, requestBody: requestBody, completion: { [weak self] result in + networkManager?.post(endpoint: newMileStoneEndpoint, requestBody: requestBody, completion: { [weak self] result in switch result { case .success(_): self?.loadData() @@ -139,18 +165,18 @@ extension MileStoneViewController { }) } -// private func putEditedMileStone(_ editedLabel: MileStone) { -// let labelId = editedLabel.id -// let editLabelEndpoint = EndPoint.milestone.path(with: labelId) -// let requestBody = NewLabelDTO(name: editedLabel.title, content: editedLabel.body, colorCode: editedLabel.hexColorCode) -// -// networkManager?.put(endpoint: editLabelEndpoint, requestBody: requestBody, completion: { [weak self] result in -// switch result { -// case .success(_): -// self?.loadData() -// case .failure(let error): -// self?.presentAlert(with: error.description) -// } -// }) -// } + private func putEditedMileStone(_ editedMileStone: MileStone) { + let mileStoneId = editedMileStone.id + let editMileStoneEndpoint = EndPoint.milestone.path(with: mileStoneId) + let requestBody = NewMileStoneDTO(title: editedMileStone.title, description: editedMileStone.description ?? "", due_date: editedMileStone.due_date ?? "") + + networkManager?.put(endpoint: editMileStoneEndpoint, requestBody: requestBody, completion: { [weak self] result in + switch result { + case .success(_): + self?.loadData() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift index 9b0d25402..2690b4758 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift @@ -9,7 +9,7 @@ import UIKit class MilestoneTableViewDataSource: NSObject, UITableViewDataSource { - private var milestones = [MileStone]() + private(set) var milestones = [MileStone]() func update(milestones: [MileStone]) { self.milestones = milestones From c9349af6d45169f0ae39e7ec1c18658cc767a9fc Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Sun, 20 Jun 2021 20:14:18 +0900 Subject: [PATCH 54/91] =?UTF-8?q?feat=20:[#68]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20=EC=88=98=EC=A0=95=20=EC=8B=9C=20=ED=95=B4?= =?UTF-8?q?=EB=8B=B9=20=EB=A7=88=EC=9D=BC=EC=8A=A4=ED=86=A4=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=ED=94=84=EB=A6=AC=EB=B7=B0=20=EB=B3=B4=EC=97=AC?= =?UTF-8?q?=EC=A3=BC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MileStoneControlViewController.swift | 16 ++++++++++++---- .../Milestone/View/MileStoneTableViewCell.swift | 10 ---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift index dc97a63f8..b26023301 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift @@ -42,7 +42,7 @@ class MileStoneControlViewController: UIViewController { let titleInputItem = InputLineItem(category: "제목", inputView: titleTextfield) let descriptionInputItem = InputLineItem(category: "설명", inputView: descriptionTextfield) - let completeDateInputItem = InputLineItem(category: "완료일", inputView: completeDateMileStone) + let completeDateInputItem = InputLineItem(category: "완료일", inputView: completeDateTextField) stackView.configure(with: [titleInputItem, descriptionInputItem, completeDateInputItem]) return stackView @@ -60,7 +60,7 @@ class MileStoneControlViewController: UIViewController { return textField }() - private lazy var completeDateMileStone: UITextField = { + private lazy var completeDateTextField: UITextField = { let textField = UITextField() textField.placeholder = "YYYY-MM-DD(선택사항)" return textField @@ -68,7 +68,7 @@ class MileStoneControlViewController: UIViewController { private lazy var previewLabel: LabelView = { let labelView = LabelView() - let colorText = completeDateMileStone.text ?? "YYYY-MM-DD(선택사항)" + let colorText = completeDateTextField.text ?? "YYYY-MM-DD(선택사항)" let hex = HexColorCode(from: colorText) let titleText = titleTextfield.isEmpty() ? "레이블" : titleTextfield.text labelView.configure(with: hex, titleText) @@ -129,6 +129,14 @@ class MileStoneControlViewController: UIViewController { func configure(withTitle sceneTitle: String, currentMileStone: MileStone?) { self.sceneTitle = sceneTitle self.currentMileStone = currentMileStone + setUpCurrentMileStoneInfo() + } + + private func setUpCurrentMileStoneInfo() { + guard let currentMileStone = currentMileStone else { return } + titleTextfield.text = currentMileStone.title + descriptionTextfield.text = currentMileStone.description + completeDateTextField.text = currentMileStone.due_date } func setSaveOperation(_ operation: @escaping (MileStone) -> Void) { @@ -141,7 +149,7 @@ class MileStoneControlViewController: UIViewController { @objc func saveButtonTouched(_ sender: UIBarButtonItem) { guard let mileStoneTitle = titleTextfield.text, - let completeDtae = completeDateMileStone.text, + let completeDtae = completeDateTextField.text, let saveOperation = saveOperation else { return } let mileStone = MileStone(id: currentMileStone?.id ?? -1, title: mileStoneTitle, description: descriptionTextfield.text ?? "", due_date: completeDtae) diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index d0d5d0fee..70a044d07 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -10,16 +10,6 @@ import UIKit class MileStoneTableViewCell: UITableViewCell { private let spacing: CGFloat = 16 - // - // mileStoneStackView스택을 만들고 - // 1 : sub스택 - // -1 Title 라벨 - // -2 몇 %인지 보이는 두개의 라벨 - // 2 : 마일스톤에 대한 설명 라벨 - // 3 : 데이트 라벨 - // 4 : sub스택 - // -1 열린 이슈 라벨 - // -2 닫힌 이슈 라벨 private lazy var mileStoneStackView: UIStackView = { let superStackView = UIStackView() //커다란 SuperStack From e64dc77d82c0205d83f2c45ebe733b907073be75 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Sun, 20 Jun 2021 23:12:03 +0900 Subject: [PATCH 55/91] =?UTF-8?q?feat=20:[#68]=20=EC=99=84=EB=A3=8C?= =?UTF-8?q?=EA=B8=B0=EA=B0=84=20=ED=8F=AC=EB=A7=B7=20=EC=B2=B4=ED=81=AC=20?= =?UTF-8?q?=EB=B0=8F=20=EC=83=89=EC=83=81=20=EB=B3=80=EA=B2=BD=ED=95=98?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 4 +++ .../issue-tracker/Common/String.swift | 27 +++++++++++++++++++ .../View/MultipleLineInputStackView.swift | 27 +++++++++++++++++-- .../MileStoneControlViewController.swift | 25 ++++++++++------- 4 files changed, 71 insertions(+), 12 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Common/String.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 44ecc317e..77155ab9b 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -53,6 +53,7 @@ E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; FA431FF9267F36FA0010EA91 /* MileStoneControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA431FF8267F36FA0010EA91 /* MileStoneControlViewController.swift */; }; FA431FFB267F3B680010EA91 /* NewMileStoneDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA431FFA267F3B680010EA91 /* NewMileStoneDTO.swift */; }; + FA431FFD267F61150010EA91 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA431FFC267F61150010EA91 /* String.swift */; }; FA733A2E267C3D77005A40C8 /* Milestone.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A2D267C3D77005A40C8 /* Milestone.swift */; }; FA733A30267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A2F267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift */; }; FA733A32267C3EAA005A40C8 /* MileStoneTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A31267C3EAA005A40C8 /* MileStoneTableDelegate.swift */; }; @@ -115,6 +116,7 @@ E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; FA431FF8267F36FA0010EA91 /* MileStoneControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneControlViewController.swift; sourceTree = ""; }; FA431FFA267F3B680010EA91 /* NewMileStoneDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewMileStoneDTO.swift; sourceTree = ""; }; + FA431FFC267F61150010EA91 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; FA733A2D267C3D77005A40C8 /* Milestone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Milestone.swift; sourceTree = ""; }; FA733A2F267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MilestoneTableViewDataSource.swift; sourceTree = ""; }; FA733A31267C3EAA005A40C8 /* MileStoneTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneTableDelegate.swift; sourceTree = ""; }; @@ -212,6 +214,7 @@ E42AD12526709C010071B436 /* UIViewControllerExtension.swift */, E426DAC82671F7760069E77D /* AlertFactory.swift */, E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */, + FA431FFC267F61150010EA91 /* String.swift */, ); path = Common; sourceTree = ""; @@ -517,6 +520,7 @@ E426DAC22671B1C60069E77D /* LoginKeyChainManager.swift in Sources */, E43912D426788CC3003CD344 /* ImageBarButton.swift in Sources */, E43912D2267878F4003CD344 /* HexColorCode.swift in Sources */, + FA431FFD267F61150010EA91 /* String.swift in Sources */, FAB2C36C2679F6CC009F879C /* MileStoneLabelView.swift in Sources */, E426DAC72671F6A00069E77D /* LoginError.swift in Sources */, E43912D626789812003CD344 /* RequestManager.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Common/String.swift b/iOS/issue-tracker/issue-tracker/Common/String.swift new file mode 100644 index 000000000..93705d598 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Common/String.swift @@ -0,0 +1,27 @@ +// +// String.swift +// issue-tracker +// +// Created by jinseo park on 6/20/21. +// + +import Foundation + +extension String { + enum ValidityType { + case date + } + enum Regex: String { + case date = "[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]" + } + func isValid(_ validityType: ValidityType)-> Bool { + let format = "SELF MATCHES %@" + var regex = "" + + switch validityType { + case .date: + regex = Regex.date.rawValue + } + return NSPredicate(format: format, regex).evaluate(with: self) + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift index f39d87119..cad705e83 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift @@ -22,6 +22,12 @@ final class MultipleLineInputStackView: UIStackView { return lineHeight / 2 }() + //마일스톤 날짜 체크를 위해 따로 생성. + private var lastItemLabel: UILabel = { + let label = UILabel() + return label + }() + private var items: [InputLineItem]? private let borderColor = Colors.border.cgColor private let borderWidth: CGFloat = 1 @@ -46,12 +52,20 @@ final class MultipleLineInputStackView: UIStackView { func configure(with items: [InputLineItem]) { self.items = items - items.forEach { inputLineItem in + items.enumerated().forEach { index, inputLineItem in let containerFrame = CGRect(x: 0, y: 0, width: frame.width, height: lineHeight) let container = UIView(frame: containerFrame) let category = inputLineItem.category - let titleLabel = UILabel() + + var titleLabel: UILabel + + if index == 2 { //마일스톤 데이트체크를 위한 라벨. 하드코딩느낌.. 라벨 배열을 만들어야 할지 헷갈림. + titleLabel = lastItemLabel + }else { + titleLabel = UILabel() + } + titleLabel.text = category titleLabel.translatesAutoresizingMaskIntoConstraints = false @@ -75,6 +89,15 @@ final class MultipleLineInputStackView: UIStackView { addDivisionLines() } + //[요구사항] 마일스톤 날짜뷰 형식에 안맞으면 해당 라벨 색상 변경 필요. + func setLabelColor(correct: Bool) { + if correct { + lastItemLabel.textColor = Colors.mainGrape + }else { + lastItemLabel.textColor = UIColor.red + } + } + private func addDivisionLines() { guard let itemCount = items?.count, itemCount >= 2 else { return } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift index b26023301..1387bc5f8 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift @@ -60,22 +60,15 @@ class MileStoneControlViewController: UIViewController { return textField }() + let validityType: String.ValidityType = .date + private lazy var completeDateTextField: UITextField = { let textField = UITextField() textField.placeholder = "YYYY-MM-DD(선택사항)" + textField.addTarget(self, action: #selector(handleTextChange), for: .editingChanged) return textField }() - private lazy var previewLabel: LabelView = { - let labelView = LabelView() - let colorText = completeDateTextField.text ?? "YYYY-MM-DD(선택사항)" - let hex = HexColorCode(from: colorText) - let titleText = titleTextfield.isEmpty() ? "레이블" : titleTextfield.text - labelView.configure(with: hex, titleText) - labelView.translatesAutoresizingMaskIntoConstraints = false - return labelView - }() - private lazy var singleLineHeight: CGFloat = { return view.frame.height * 0.05 }() @@ -94,6 +87,18 @@ class MileStoneControlViewController: UIViewController { setTitleTextFieldSupporter() } + @objc func handleTextChange() { + guard let text = completeDateTextField.text else { return } + switch validityType { + case .date: + if text.isValid(validityType) { + mileStoneEditStackView.setLabelColor(correct: true) + }else{ + mileStoneEditStackView.setLabelColor(correct: false) + } + } + } + private func configureViews() { view.backgroundColor = Colors.background addTopMenu() From d430a83206bf0ea141cf2c0813c0e9f6ac803aa1 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Mon, 21 Jun 2021 15:10:37 +0900 Subject: [PATCH 56/91] =?UTF-8?q?chore:=20[#78]=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/LabelViewController.swift | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index 991ef762c..409f7ef21 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -41,7 +41,7 @@ final class LabelViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - loadData() + loadLabels() } private func configureViews() { @@ -82,21 +82,6 @@ final class LabelViewController: UIViewController { networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) } - private func loadData() { - let labelListEndpoint = EndPoint.label.path() - networkManager?.get(endpoint: labelListEndpoint, queryParameters: nil, - completion: { [weak self] (result: Result) in - switch result { - case .success(let result): - guard let labels = result.data else { return } - self?.labelTableDatasource?.update(labels: labels) - self?.reloadTableView() - case .failure(let error): - self?.presentAlert(with: error.description) - } - }) - } - private func reloadTableView() { DispatchQueue.main.async { self.labelTableView.reloadData() @@ -148,12 +133,27 @@ final class LabelViewController: UIViewController { //MARK: - Network Methods extension LabelViewController { + private func loadLabels() { + let labelListEndpoint = EndPoint.label.path() + networkManager?.get(endpoint: labelListEndpoint, queryParameters: nil, + completion: { [weak self] (result: Result) in + switch result { + case .success(let result): + guard let labels = result.data else { return } + self?.labelTableDatasource?.update(labels: labels) + self?.reloadTableView() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } + private func deleteLabel(for id: Int) { let deleteLabelEndpoint = EndPoint.label.path(with: id) networkManager?.delete(endpoint: deleteLabelEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in switch result { case .success(_): - self?.loadData() + self?.loadLabels() case .failure(let error): self?.presentAlert(with: error.description) } @@ -167,7 +167,7 @@ extension LabelViewController { networkManager?.post(endpoint: newLabelEndpoint, requestBody: requestBody, completion: { [weak self] result in switch result { case .success(_): - self?.loadData() + self?.loadLabels() case .failure(let error): self?.presentAlert(with: error.description) } @@ -182,7 +182,7 @@ extension LabelViewController { networkManager?.put(endpoint: editLabelEndpoint, requestBody: requestBody, completion: { [weak self] result in switch result { case .success(_): - self?.loadData() + self?.loadLabels() case .failure(let error): self?.presentAlert(with: error.description) } From b1fe477415b341eb42549a4470a2209f2f494157 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Mon, 21 Jun 2021 15:12:51 +0900 Subject: [PATCH 57/91] =?UTF-8?q?chore=20:[#68]=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=A3=BC=EC=84=9D=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 10 +--- .../View/MultipleLineInputStackView.swift | 8 ++- .../MileStoneControlViewController.swift | 4 +- .../Controller/MileStoneTableDelegate.swift | 7 +-- .../Controller/MileStoneViewController.swift | 3 +- .../Model}/MileStoneLabelView.swift | 11 ---- .../View/MileStoneTableViewCell.swift | 52 +++++++------------ 7 files changed, 27 insertions(+), 68 deletions(-) rename iOS/issue-tracker/issue-tracker/Main/{Common/View/MileStoneLabelView => Milestone/Model}/MileStoneLabelView.swift (91%) diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 77155ab9b..17ae741cf 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -307,7 +307,6 @@ E43912C926776DA0003CD344 /* View */ = { isa = PBXGroup; children = ( - FAB2C36D2679FB74009F879C /* MileStoneLabelView */, E43912D326788CC3003CD344 /* ImageBarButton.swift */, E43912C626776D8F003CD344 /* LabelView.swift */, E43912F5267CAE01003CD344 /* TopMenuView.swift */, @@ -360,6 +359,7 @@ children = ( FA733A2D267C3D77005A40C8 /* Milestone.swift */, FA431FFA267F3B680010EA91 /* NewMileStoneDTO.swift */, + FAB2C36B2679F6CC009F879C /* MileStoneLabelView.swift */, ); path = Model; sourceTree = ""; @@ -383,14 +383,6 @@ path = Controller; sourceTree = ""; }; - FAB2C36D2679FB74009F879C /* MileStoneLabelView */ = { - isa = PBXGroup; - children = ( - FAB2C36B2679F6CC009F879C /* MileStoneLabelView.swift */, - ); - path = MileStoneLabelView; - sourceTree = ""; - }; FAC6D8922671E1A800A9E5F9 /* Github */ = { isa = PBXGroup; children = ( diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift index cad705e83..847dd7d7b 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift @@ -21,8 +21,7 @@ final class MultipleLineInputStackView: UIStackView { private lazy var elementSpacing: CGFloat = { return lineHeight / 2 }() - - //마일스톤 날짜 체크를 위해 따로 생성. + private var lastItemLabel: UILabel = { let label = UILabel() return label @@ -60,7 +59,7 @@ final class MultipleLineInputStackView: UIStackView { var titleLabel: UILabel - if index == 2 { //마일스톤 데이트체크를 위한 라벨. 하드코딩느낌.. 라벨 배열을 만들어야 할지 헷갈림. + if index == 2 { titleLabel = lastItemLabel }else { titleLabel = UILabel() @@ -88,8 +87,7 @@ final class MultipleLineInputStackView: UIStackView { } addDivisionLines() } - - //[요구사항] 마일스톤 날짜뷰 형식에 안맞으면 해당 라벨 색상 변경 필요. + func setLabelColor(correct: Bool) { if correct { lastItemLabel.textColor = Colors.mainGrape diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift index 1387bc5f8..25ad021d2 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift @@ -44,7 +44,7 @@ class MileStoneControlViewController: UIViewController { let descriptionInputItem = InputLineItem(category: "설명", inputView: descriptionTextfield) let completeDateInputItem = InputLineItem(category: "완료일", inputView: completeDateTextField) stackView.configure(with: [titleInputItem, descriptionInputItem, completeDateInputItem]) - + return stackView }() @@ -104,7 +104,7 @@ class MileStoneControlViewController: UIViewController { addTopMenu() addEditStackView() } - + private func addTopMenu() { view.addSubview(topMenuView) diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift index 04ae4e7b0..a7a184032 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift @@ -30,12 +30,7 @@ class MileStoneTableDelegate: NSObject, UITableViewDelegate { title: CellAction.edit.buttonTitle()) { [weak self] _, _, _ in self?.cellActionHandler(indexPath.row, .edit) } - editAction.image = UIImage(systemName: "pencil") - - /*넣은 UIContextualAction index의 역순으로 화면에 나타난다. - [deleteAction,editAction] 를 넣었지만 실제 화면에서 Swipe-left 시 - 편집,삭제 형태로 보여지게된다. - */ + editAction.image = UIImage(systemName: "pencil") return UISwipeActionsConfiguration(actions: [deleteAction,editAction]) } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift index 7abc21bc4..6d0e9a702 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift @@ -20,8 +20,7 @@ class MileStoneViewController: UIViewController { let tableView = UITableView() let cellID = MileStoneTableViewCell.reuseID tableView.register(MileStoneTableViewCell.self, forCellReuseIdentifier: cellID) - tableView.backgroundColor = Colors.background - tableView.allowsSelection = true // 테스트 + tableView.backgroundColor = Colors.background tableView.translatesAutoresizingMaskIntoConstraints = false return tableView }() diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/MileStoneLabelView.swift similarity index 91% rename from iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift rename to iOS/issue-tracker/issue-tracker/Main/Milestone/Model/MileStoneLabelView.swift index c56212b6a..e1fd606ac 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Common/View/MileStoneLabelView/MileStoneLabelView.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/MileStoneLabelView.swift @@ -55,32 +55,24 @@ final class MileStoneLabelView: UIView { } required init(text: String, fontColor: UIColor, bgColor: UIColor, imgName: String, issueCount: Int) { - - //init을 무엇을 줘도 상관이 없는듯. super.init(frame: .zero) self.text = text self.fontColor = fontColor self.bgColor = bgColor self.imgName = imgName self.issueCount = issueCount - configure() } private func configure() { - layer.cornerRadius = labelHeight * 0.5 translatesAutoresizingMaskIntoConstraints = false - addLabelTitle() backgroundColor = bgColor } private func addLabelTitle() { - addSubview(labelTitle) - - //예이!!!!!!! NSLayoutConstraint.activate([ labelTitle.centerXAnchor.constraint(equalTo: centerXAnchor), labelTitle.centerYAnchor.constraint(equalTo: centerYAnchor), @@ -88,7 +80,4 @@ final class MileStoneLabelView: UIView { heightAnchor.constraint(equalToConstant: labelHeight) ]) } - func updateIssueCount(_ issueCount: Int) { //후에 issuecount를 변경 - self.issueCount = issueCount - } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index 70a044d07..389abff10 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -10,9 +10,8 @@ import UIKit class MileStoneTableViewCell: UITableViewCell { private let spacing: CGFloat = 16 - private lazy var mileStoneStackView: UIStackView = { - let superStackView = UIStackView() //커다란 SuperStack + let superStackView = UIStackView() superStackView.axis = .vertical superStackView.distribution = .fillProportionally superStackView.translatesAutoresizingMaskIntoConstraints = false @@ -20,9 +19,6 @@ class MileStoneTableViewCell: UITableViewCell { return superStackView }() - //MARK: 1 : sub스택 - // -1 Title 라벨 - // -2 몇 %인지 보이는 두개의 라벨 private lazy var firstSubStackView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal @@ -46,7 +42,6 @@ class MileStoneTableViewCell: UITableViewCell { return label }() - //MARK: 2 : 마일스톤에 대한 설명 라벨 private lazy var descriptionLabel: UILabel = { let label = UILabel() label.textColor = Colors.description @@ -55,15 +50,11 @@ class MileStoneTableViewCell: UITableViewCell { return label }() - //MARK: 3 : 데이트 라벨 private lazy var dateLabel: UILabel = { let label = UILabel() return label }() - //MARK: 4 : sub스택 - // -1 열린 이슈 라벨 - // -2 닫힌 이슈 라벨 private lazy var milestoneLabelSubStackView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal @@ -97,7 +88,11 @@ class MileStoneTableViewCell: UITableViewCell { } private func setViews() { - addMileStoneStackView() + addMileStoneStackView() + addMileStoneFirstStackView() + addMileStoneSecondStackView() + addMileStoneThirdStackView() + addMileStoneFourthStackView() } private func addMileStoneStackView() { @@ -107,12 +102,10 @@ class MileStoneTableViewCell: UITableViewCell { mileStoneStackView.topAnchor.constraint(equalTo: topAnchor, constant: 24), mileStoneStackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -24), mileStoneStackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16) - ]) - - //MARK: 1 : sub스택 - // -1 Title 라벨 - // -2 몇 %인지 보이는 두개의 라벨 - + ]) + } + + func addMileStoneFirstStackView() { mileStoneStackView.addArrangedSubview(firstSubStackView) NSLayoutConstraint.activate([ @@ -133,17 +126,17 @@ class MileStoneTableViewCell: UITableViewCell { completenessLabel.widthAnchor.constraint(equalTo: firstSubStackView.widthAnchor, multiplier: 0.2) ]) - - //MARK: 2 : 마일스톤에 대한 설명 라벨 + } + + func addMileStoneSecondStackView() { mileStoneStackView.addArrangedSubview(descriptionLabel) - - //MARK: 3 : 완료일 스택 or Label with Img + } + + func addMileStoneThirdStackView() { mileStoneStackView.addArrangedSubview(dateLabel) - - //MARK: 4 : sub스택 - //-1 열린 이슈 라벨 - //-2 닫힌 이슈 라벨 - + } + + func addMileStoneFourthStackView() { mileStoneStackView.addArrangedSubview(milestoneLabelSubStackView) NSLayoutConstraint.activate([ @@ -158,13 +151,6 @@ class MileStoneTableViewCell: UITableViewCell { milestoneLabelSubStackView.spacing = 4 - //스택fill 이슈 -// NSLayoutConstraint.activate([ -// openMilestoneLabelView.widthAnchor -// .constraint(lessThanOrEqualTo: milestoneLabelSubStackView.widthAnchor, multiplier: 0.329), -// closeMilestoneLabelView.widthAnchor -// .constraint(lessThanOrEqualTo: milestoneLabelSubStackView.widthAnchor, multiplier: 0.329) -// ]) } func configure(title: String, description: String, due_date: String) { From a28f3d7c31895a1a40e3855017ca3e578e3426b5 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Mon, 21 Jun 2021 15:20:43 +0900 Subject: [PATCH 58/91] =?UTF-8?q?feat:=20=EB=A0=88=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80/=EC=82=AD=EC=A0=9C=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Main/Label/Controller/LabelTableDelegate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift index 0592dca94..ccb05e583 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift @@ -32,6 +32,6 @@ final class LabelTableDelegate: NSObject, UITableViewDelegate { self?.cellActionHandler(indexPath.row, .edit) } editAction.image = UIImage(systemName: "pencil") - return UISwipeActionsConfiguration(actions: [editAction, deleteAction]) + return UISwipeActionsConfiguration(actions: [deleteAction, editAction]) } } From 4578b1d50e8cf19bed0a9f34953b494b84b06890 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Mon, 21 Jun 2021 16:15:01 +0900 Subject: [PATCH 59/91] =?UTF-8?q?chore=20:[#68]=20=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EC=B9=B4=EB=A9=9C=EC=BC=80=EC=9D=B4=EC=8A=A4,=20=EC=9E=98?= =?UTF-8?q?=EB=AA=BB=EB=90=9C=20=EB=B3=80=EC=88=98=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/issue-tracker/issue-tracker/Common/String.swift | 6 ++---- .../Main/Label/Controller/LabelViewController.swift | 2 +- .../Milestone/Controller/MilestoneTableViewDataSource.swift | 4 ++-- .../issue-tracker/Main/Milestone/Model/Milestone.swift | 4 ++-- .../issue-tracker/Network/NetworkManager.swift | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Common/String.swift b/iOS/issue-tracker/issue-tracker/Common/String.swift index 93705d598..84f8d3a97 100644 --- a/iOS/issue-tracker/issue-tracker/Common/String.swift +++ b/iOS/issue-tracker/issue-tracker/Common/String.swift @@ -11,16 +11,14 @@ extension String { enum ValidityType { case date } - enum Regex: String { - case date = "[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]" - } + func isValid(_ validityType: ValidityType)-> Bool { let format = "SELF MATCHES %@" var regex = "" switch validityType { case .date: - regex = Regex.date.rawValue + regex = "[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]" } return NSPredicate(format: format, regex).evaluate(with: self) } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index 991ef762c..487e2d6f7 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -119,7 +119,7 @@ final class LabelViewController: UIViewController { private func presentEditLabelViewController(for targetLabel: Label) { let editLabelViewController = LabelControlViewController() editLabelViewController.configure(withTitle: "레이블 수정하기", currentLabel: targetLabel) - editLabelViewController.setSaveOperation(putEditedLabel) + editLabelViewController.setSaveOperation(putEditedLabel) editLabelViewController.modalPresentationStyle = .formSheet DispatchQueue.main.async { diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift index 2690b4758..9ec2d084a 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift @@ -23,9 +23,9 @@ class MilestoneTableViewDataSource: NSObject, UITableViewDataSource { let cellID = MileStoneTableViewCell.reuseID let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? MileStoneTableViewCell ?? MileStoneTableViewCell() - let milesonte = milestones[indexPath.row] + let milestone = milestones[indexPath.row] - cell.configure(title: milesonte.title, description: milesonte.description ?? "", due_date: milesonte.due_date ?? "") + cell.configure(title: milestone.title, description: milestone.description ?? "", due_date: milestone.due_date ?? "") return cell } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift index 695a05f06..fdd0483f0 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift @@ -22,13 +22,13 @@ struct MileStone: Decodable { let id: Int let title: String let description: String? - let due_date: String? + let dueDate: String? enum CodingKeys: String, CodingKey { case id case title case description - case due_date + case dueDate = "due_date" } } diff --git a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift index 34fa2a837..39a2e41e7 100644 --- a/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift +++ b/iOS/issue-tracker/issue-tracker/Network/NetworkManager.swift @@ -36,7 +36,7 @@ final class NetworkManager: NetworkManagerOperations { let error = self?.networkError(for: statusCode) ?? NetworkError.unknown completion(.failure(error)) } - } + } } func delete(endpoint: String, queryParameters: [String: Any]?, completion: @escaping (Result) -> Void) { From e5dfe328ea77b1e2ad2ac906ef332329209f24cf Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Mon, 21 Jun 2021 16:18:09 +0900 Subject: [PATCH 60/91] =?UTF-8?q?chore=20:[#68]=20=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Milestone/Controller/MileStoneControlViewController.swift | 4 ++-- .../Main/Milestone/Controller/MileStoneViewController.swift | 4 ++-- .../Milestone/Controller/MilestoneTableViewDataSource.swift | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift index 25ad021d2..8df239719 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneControlViewController.swift @@ -141,7 +141,7 @@ class MileStoneControlViewController: UIViewController { guard let currentMileStone = currentMileStone else { return } titleTextfield.text = currentMileStone.title descriptionTextfield.text = currentMileStone.description - completeDateTextField.text = currentMileStone.due_date + completeDateTextField.text = currentMileStone.dueDate } func setSaveOperation(_ operation: @escaping (MileStone) -> Void) { @@ -157,7 +157,7 @@ class MileStoneControlViewController: UIViewController { let completeDtae = completeDateTextField.text, let saveOperation = saveOperation else { return } - let mileStone = MileStone(id: currentMileStone?.id ?? -1, title: mileStoneTitle, description: descriptionTextfield.text ?? "", due_date: completeDtae) + let mileStone = MileStone(id: currentMileStone?.id ?? -1, title: mileStoneTitle, description: descriptionTextfield.text ?? "", dueDate: completeDtae) saveOperation(mileStone) dismiss(animated: true, completion: nil) } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift index 6d0e9a702..0560bef6a 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift @@ -152,7 +152,7 @@ extension MileStoneViewController { private func postNewMileStone(_ newMileStone: MileStone) { let newMileStoneEndpoint = EndPoint.milestone.path() - let requestBody = NewMileStoneDTO(title: newMileStone.title, description: newMileStone.description ?? "", due_date: newMileStone.due_date ?? "") + let requestBody = NewMileStoneDTO(title: newMileStone.title, description: newMileStone.description ?? "", due_date: newMileStone.dueDate ?? "") networkManager?.post(endpoint: newMileStoneEndpoint, requestBody: requestBody, completion: { [weak self] result in switch result { @@ -167,7 +167,7 @@ extension MileStoneViewController { private func putEditedMileStone(_ editedMileStone: MileStone) { let mileStoneId = editedMileStone.id let editMileStoneEndpoint = EndPoint.milestone.path(with: mileStoneId) - let requestBody = NewMileStoneDTO(title: editedMileStone.title, description: editedMileStone.description ?? "", due_date: editedMileStone.due_date ?? "") + let requestBody = NewMileStoneDTO(title: editedMileStone.title, description: editedMileStone.description ?? "", due_date: editedMileStone.dueDate ?? "") networkManager?.put(endpoint: editMileStoneEndpoint, requestBody: requestBody, completion: { [weak self] result in switch result { diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift index 9ec2d084a..bd3a87c1b 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift @@ -25,7 +25,7 @@ class MilestoneTableViewDataSource: NSObject, UITableViewDataSource { let milestone = milestones[indexPath.row] - cell.configure(title: milestone.title, description: milestone.description ?? "", due_date: milestone.due_date ?? "") + cell.configure(title: milestone.title, description: milestone.description ?? "", due_date: milestone.dueDate ?? "") return cell } } From 08ea6ddbf42a49cf47c0485a5a79091273871e4e Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Mon, 21 Jun 2021 16:41:26 +0900 Subject: [PATCH 61/91] =?UTF-8?q?refactor=20:[#68]=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=B8=94,=20=EB=A7=88=EC=9D=BC=EC=8A=A4=ED=86=A4=20=EA=B3=B5?= =?UTF-8?q?=ED=86=B5=20TableDelegate=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 12 ++---- .../CommonTableDelegate.swift} | 16 +++++--- .../Label/Controller/LabelTableDelegate.swift | 37 ------------------- .../Controller/LabelViewController.swift | 6 +-- .../Controller/MileStoneViewController.swift | 4 +- 5 files changed, 19 insertions(+), 56 deletions(-) rename iOS/issue-tracker/issue-tracker/Main/{Milestone/Controller/MileStoneTableDelegate.swift => Common/CommonTableDelegate.swift} (74%) delete mode 100644 iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 17ae741cf..ad6e9b675 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -38,7 +38,6 @@ E43912DC2678A737003CD344 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DB2678A737003CD344 /* JWT.swift */; }; E43912DE2678A76D003CD344 /* RequestKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DD2678A76D003CD344 /* RequestKeys.swift */; }; E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */; }; - E43912E22678AEB3003CD344 /* LabelTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */; }; E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */; }; E43912EA267A2351003CD344 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912E9267A2351003CD344 /* NetworkError.swift */; }; E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912EB267B1A4E003CD344 /* LoginInfoDTO.swift */; }; @@ -56,7 +55,6 @@ FA431FFD267F61150010EA91 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA431FFC267F61150010EA91 /* String.swift */; }; FA733A2E267C3D77005A40C8 /* Milestone.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A2D267C3D77005A40C8 /* Milestone.swift */; }; FA733A30267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A2F267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift */; }; - FA733A32267C3EAA005A40C8 /* MileStoneTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA733A31267C3EAA005A40C8 /* MileStoneTableDelegate.swift */; }; FAB2C36A26789D41009F879C /* MileStoneTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB2C36926789D40009F879C /* MileStoneTableViewCell.swift */; }; FAB2C36C2679F6CC009F879C /* MileStoneLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB2C36B2679F6CC009F879C /* MileStoneLabelView.swift */; }; FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC6D88A2671D5A100A9E5F9 /* GithubAuthorizationManager.swift */; }; @@ -65,6 +63,7 @@ FAEB30AE266F6A7800C17BE9 /* UIImageExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAEB30AD266F6A7800C17BE9 /* UIImageExtension.swift */; }; FAEB30B12670B74000C17BE9 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = FAEB30B02670B74000C17BE9 /* Alamofire */; }; FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAEB30B32670B76200C17BE9 /* NetworkManager.swift */; }; + FAFD11B1268078F80064AED4 /* CommonTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFD11B0268078F80064AED4 /* CommonTableDelegate.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -101,7 +100,6 @@ E43912DB2678A737003CD344 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = ""; }; E43912DD2678A76D003CD344 /* RequestKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestKeys.swift; sourceTree = ""; }; E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewDatasource.swift; sourceTree = ""; }; - E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableDelegate.swift; sourceTree = ""; }; E43912E7267A1FE5003CD344 /* NewLabelDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewLabelDTO.swift; sourceTree = ""; }; E43912E9267A2351003CD344 /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; }; E43912EB267B1A4E003CD344 /* LoginInfoDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginInfoDTO.swift; sourceTree = ""; }; @@ -119,7 +117,6 @@ FA431FFC267F61150010EA91 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; FA733A2D267C3D77005A40C8 /* Milestone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Milestone.swift; sourceTree = ""; }; FA733A2F267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MilestoneTableViewDataSource.swift; sourceTree = ""; }; - FA733A31267C3EAA005A40C8 /* MileStoneTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneTableDelegate.swift; sourceTree = ""; }; FAB2C36926789D40009F879C /* MileStoneTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneTableViewCell.swift; sourceTree = ""; }; FAB2C36B2679F6CC009F879C /* MileStoneLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MileStoneLabelView.swift; sourceTree = ""; }; FAC6D88A2671D5A100A9E5F9 /* GithubAuthorizationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GithubAuthorizationManager.swift; sourceTree = ""; }; @@ -127,6 +124,7 @@ FAEB30AB266F5E9700C17BE9 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = ""; }; FAEB30AD266F6A7800C17BE9 /* UIImageExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageExtension.swift; sourceTree = ""; }; FAEB30B32670B76200C17BE9 /* NetworkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkManager.swift; sourceTree = ""; }; + FAFD11B0268078F80064AED4 /* CommonTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonTableDelegate.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -300,6 +298,7 @@ children = ( E43912C926776DA0003CD344 /* View */, E43912ED267C3C0E003CD344 /* CellAction.swift */, + FAFD11B0268078F80064AED4 /* CommonTableDelegate.swift */, ); path = Common; sourceTree = ""; @@ -328,7 +327,6 @@ children = ( E42AD11F267093430071B436 /* LabelViewController.swift */, E43912DF2678AD0A003CD344 /* LabelTableViewDatasource.swift */, - E43912E12678AEB3003CD344 /* LabelTableDelegate.swift */, E43912EF267C3EED003CD344 /* LabelControlViewController.swift */, ); path = Controller; @@ -377,7 +375,6 @@ children = ( E42AD121267093590071B436 /* MileStoneViewController.swift */, FA733A2F267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift */, - FA733A31267C3EAA005A40C8 /* MileStoneTableDelegate.swift */, FA431FF8267F36FA0010EA91 /* MileStoneControlViewController.swift */, ); path = Controller; @@ -484,6 +481,7 @@ files = ( FAB2C36A26789D41009F879C /* MileStoneTableViewCell.swift in Sources */, E426DAD126730DC50069E77D /* OAuthResponseDTO.swift in Sources */, + FAFD11B1268078F80064AED4 /* CommonTableDelegate.swift in Sources */, E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */, FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */, E426DABC2670EC5E0069E77D /* LoginInfo.swift in Sources */, @@ -500,7 +498,6 @@ E42AD124267093700071B436 /* MyAccountViewController.swift in Sources */, FAEB30AC266F5E9700C17BE9 /* Colors.swift in Sources */, E43912C726776D8F003CD344 /* LabelView.swift in Sources */, - FA733A32267C3EAA005A40C8 /* MileStoneTableDelegate.swift in Sources */, E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */, FA431FF9267F36FA0010EA91 /* MileStoneControlViewController.swift in Sources */, E43912EA267A2351003CD344 /* NetworkError.swift in Sources */, @@ -529,7 +526,6 @@ E42AD11E267093320071B436 /* IssueViewController.swift in Sources */, E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */, E43912DC2678A737003CD344 /* JWT.swift in Sources */, - E43912E22678AEB3003CD344 /* LabelTableDelegate.swift in Sources */, E426DABA2670EC2D0069E77D /* AppleAuthorizationManager.swift in Sources */, FAEB30AE266F6A7800C17BE9 /* UIImageExtension.swift in Sources */, E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Common/CommonTableDelegate.swift similarity index 74% rename from iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift rename to iOS/issue-tracker/issue-tracker/Main/Common/CommonTableDelegate.swift index a7a184032..e42a87d5f 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneTableDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Common/CommonTableDelegate.swift @@ -1,22 +1,25 @@ // -// MileStoneTableDelegate.swift +// CommonTableDelegate.swift // issue-tracker // -// Created by jinseo park on 6/18/21. +// Created by jinseo park on 6/21/21. // + import UIKit -class MileStoneTableDelegate: NSObject, UITableViewDelegate { +final class CommonTableDelegate: NSObject, UITableViewDelegate { typealias CellActionHandler = (Int, CellAction) -> Void private var cellActionHandler: CellActionHandler + private var cellHeight: CGFloat - init(cellActionHandler: @escaping CellActionHandler) { + init(cellActionHandler: @escaping CellActionHandler, cellHeight: CGFloat) { self.cellActionHandler = cellActionHandler + self.cellHeight = cellHeight } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return tableView.frame.height * 0.233 + return self.cellHeight } func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { @@ -30,7 +33,8 @@ class MileStoneTableDelegate: NSObject, UITableViewDelegate { title: CellAction.edit.buttonTitle()) { [weak self] _, _, _ in self?.cellActionHandler(indexPath.row, .edit) } - editAction.image = UIImage(systemName: "pencil") + editAction.image = UIImage(systemName: "pencil") + return UISwipeActionsConfiguration(actions: [deleteAction,editAction]) } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift deleted file mode 100644 index 0592dca94..000000000 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableDelegate.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// LabelTableDelegate.swift -// issue-tracker -// -// Created by Song on 2021/06/15. -// - -import UIKit - -final class LabelTableDelegate: NSObject, UITableViewDelegate { - - typealias CellActionHandler = (Int, CellAction) -> Void - private var cellActionHandler: CellActionHandler - - init(cellActionHandler: @escaping CellActionHandler) { - self.cellActionHandler = cellActionHandler - } - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return 118 - } - - func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { - let deleteAction = UIContextualAction(style: .destructive, - title: CellAction.delete.buttonTitle()) { [weak self] _, _, _ in - self?.cellActionHandler(indexPath.row, .delete) - } - deleteAction.image = UIImage(systemName: "trash") - - let editAction = UIContextualAction(style: .normal, - title: CellAction.edit.buttonTitle()) { [weak self] _, _, _ in - self?.cellActionHandler(indexPath.row, .edit) - } - editAction.image = UIImage(systemName: "pencil") - return UISwipeActionsConfiguration(actions: [editAction, deleteAction]) - } -} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index 487e2d6f7..d79e95afb 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -30,7 +30,7 @@ final class LabelViewController: UIViewController { private let colorConverter: HexColorConvertable = HexColorConverter() private var networkManager: NetworkManagerOperations? private var labelTableDatasource: LabelTableViewDatasource? - private var labelTableDelegate: LabelTableDelegate? + private var labelTableDelegate: CommonTableDelegate? override func viewDidLoad() { super.viewDidLoad() @@ -71,7 +71,7 @@ final class LabelViewController: UIViewController { labelTableDatasource = LabelTableViewDatasource() labelTableView.dataSource = labelTableDatasource - labelTableDelegate = LabelTableDelegate(cellActionHandler: swipeActionHandler) + labelTableDelegate = CommonTableDelegate(cellActionHandler: swipeActionHandler, cellHeight: 118) labelTableView.delegate = labelTableDelegate } @@ -119,7 +119,7 @@ final class LabelViewController: UIViewController { private func presentEditLabelViewController(for targetLabel: Label) { let editLabelViewController = LabelControlViewController() editLabelViewController.configure(withTitle: "레이블 수정하기", currentLabel: targetLabel) - editLabelViewController.setSaveOperation(putEditedLabel) + editLabelViewController.setSaveOperation(putEditedLabel) editLabelViewController.modalPresentationStyle = .formSheet DispatchQueue.main.async { diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift index 0560bef6a..b966be9a7 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift @@ -38,7 +38,7 @@ class MileStoneViewController: UIViewController { private var networkManager: NetworkManagerOperations? private var mileStoneTableDatasource: MilestoneTableViewDataSource? - private var mileStoneTableDelegate: MileStoneTableDelegate? + private var mileStoneTableDelegate: CommonTableDelegate? override func viewDidLoad() { super.viewDidLoad() @@ -74,7 +74,7 @@ class MileStoneViewController: UIViewController { mileStoneTableDatasource = MilestoneTableViewDataSource() mileStoneTableView.dataSource = mileStoneTableDatasource - mileStoneTableDelegate = MileStoneTableDelegate(cellActionHandler: swipeActionHandler) + mileStoneTableDelegate = CommonTableDelegate(cellActionHandler: swipeActionHandler, cellHeight: 198) mileStoneTableView.delegate = mileStoneTableDelegate } From 6bcf4d674a65cc3f92359b10af811e824b8d5080 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Mon, 21 Jun 2021 20:53:21 +0900 Subject: [PATCH 62/91] =?UTF-8?q?feat:=20[#82]=20=EB=84=A4=EB=B9=84?= =?UTF-8?q?=EA=B2=8C=EC=9D=B4=EC=85=98=20=EB=B2=84=ED=8A=BC=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 버튼 UI 추가 - 저장 버튼 액션의 다형성 구축 (클로저 넘겨주기) --- .../issue-tracker.xcodeproj/project.pbxproj | 24 ++++++++ .../IssueControlViewController.swift | 59 +++++++++++++++++++ .../Main/Issue/IssueViewController.swift | 12 ++++ .../Main/Issue/Model/Issue.swift | 12 ++++ 4 files changed, 107 insertions(+) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index ad6e9b675..28228839b 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -47,6 +47,8 @@ E43912F6267CAE01003CD344 /* TopMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F5267CAE01003CD344 /* TopMenuView.swift */; }; E43912F8267CB3D7003CD344 /* MultipleLineInputStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F7267CB3D7003CD344 /* MultipleLineInputStackView.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; + E49695672680B0B7001AEB89 /* IssueControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695662680B0B7001AEB89 /* IssueControlViewController.swift */; }; + E49695692680B3FB001AEB89 /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695682680B3FB001AEB89 /* Issue.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -109,6 +111,8 @@ E43912F5267CAE01003CD344 /* TopMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopMenuView.swift; sourceTree = ""; }; E43912F7267CB3D7003CD344 /* MultipleLineInputStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipleLineInputStackView.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; + E49695662680B0B7001AEB89 /* IssueControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueControlViewController.swift; sourceTree = ""; }; + E49695682680B3FB001AEB89 /* Issue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Issue.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -260,6 +264,8 @@ E42AD11926708EBA0071B436 /* Issue */ = { isa = PBXGroup; children = ( + E496956B2680B40D001AEB89 /* Model */, + E496956A2680B3FE001AEB89 /* Controller */, E42AD11D267093320071B436 /* IssueViewController.swift */, ); path = Issue; @@ -344,6 +350,22 @@ path = Model; sourceTree = ""; }; + E496956A2680B3FE001AEB89 /* Controller */ = { + isa = PBXGroup; + children = ( + E49695662680B0B7001AEB89 /* IssueControlViewController.swift */, + ); + path = Controller; + sourceTree = ""; + }; + E496956B2680B40D001AEB89 /* Model */ = { + isa = PBXGroup; + children = ( + E49695682680B3FB001AEB89 /* Issue.swift */, + ); + path = Model; + sourceTree = ""; + }; FA8840422671F9B000ECCF7A /* Apple */ = { isa = PBXGroup; children = ( @@ -485,6 +507,7 @@ E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */, FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */, E426DABC2670EC5E0069E77D /* LoginInfo.swift in Sources */, + E49695672680B0B7001AEB89 /* IssueControlViewController.swift in Sources */, E43912CE26777310003CD344 /* HexColorConverter.swift in Sources */, FA431FFB267F3B680010EA91 /* NewMileStoneDTO.swift in Sources */, E42AD1182670886F0071B436 /* IssueTrackerTabBarController.swift in Sources */, @@ -523,6 +546,7 @@ E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */, FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */, E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */, + E49695692680B3FB001AEB89 /* Issue.swift in Sources */, E42AD11E267093320071B436 /* IssueViewController.swift in Sources */, E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */, E43912DC2678A737003CD344 /* JWT.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift new file mode 100644 index 000000000..9ef1143b5 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift @@ -0,0 +1,59 @@ +// +// IssueControlViewController.swift +// issue-tracker +// +// Created by Song on 2021/06/21. +// + +import UIKit + +final class IssueControlViewController: UIViewController { + + private lazy var cancelButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "chevron.backward", "취소") + button.moveImageToLeft() + button.addTarget(self, action: #selector(cancelButtonTouched), for: .touchUpInside) + return button + }() + + private lazy var saveButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "plus", "저장") + button.addTarget(self, action: #selector(saveButtonTouched), for: .touchUpInside) + return button + }() + + private var currentIssue: Issue? + private var saveOperation: ((Issue) -> Void)? + + override func viewDidLoad() { + super.viewDidLoad() + configureViews() + } + + private func configureViews() { + view.backgroundColor = .white + addNavigationButtons() + } + + private func addNavigationButtons() { + navigationItem.leftBarButtonItem = UIBarButtonItem(customView: cancelButton) + navigationItem.rightBarButtonItem = UIBarButtonItem(customView: saveButton) + } + + func setSaveOperation(_ operation: @escaping (Issue) -> Void) { + self.saveOperation = operation + } + + @objc private func cancelButtonTouched(_ sender: UIButton) { + navigationController?.popViewController(animated: true) + } + + @objc private func saveButtonTouched(_ sender: UIButton) { + guard let saveOperation = saveOperation else { return } + let tempIssue = Issue() + saveOperation(tempIssue) + } + +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift index cc3a5dc1d..73dcefb1b 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift @@ -13,6 +13,18 @@ class IssueViewController: UIViewController { super.viewDidLoad() view.backgroundColor = UIColor.red title = "이슈 선택" + //임시 전환 + presentNext() + } + + private func presentNext() { + let nextViewController = IssueControlViewController() + nextViewController.setSaveOperation(tempSaveOperation) + navigationController?.pushViewController(nextViewController, animated: false) + } + + private func tempSaveOperation(_ issue: Issue) { + print("새 issue 저장!") } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift new file mode 100644 index 000000000..bbe6d8e31 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift @@ -0,0 +1,12 @@ +// +// Issue.swift +// issue-tracker +// +// Created by Song on 2021/06/21. +// + +import Foundation + +struct Issue { + +} From a50ec6fe629c77cf5a22bf2cde2c839d730d7f5b Mon Sep 17 00:00:00 2001 From: Song Lee Date: Mon, 21 Jun 2021 21:41:12 +0900 Subject: [PATCH 63/91] =?UTF-8?q?feat:=20[#82]=20=EB=A7=88=ED=81=AC?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=EC=84=B8=EA=B7=B8=EB=A8=BC=ED=8A=B8=20?= =?UTF-8?q?=EC=BB=A8=ED=8A=B8=EB=A1=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IssueControlViewController.swift | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift index 9ef1143b5..d08eb9785 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift @@ -24,6 +24,40 @@ final class IssueControlViewController: UIViewController { return button }() + private enum Segment: Int, CaseIterable { + case markdown = 0 + case preview = 1 + + var title: String { + switch self { + case .markdown: + return "마크다운" + case .preview: + return "미리보기" + } + } + } + + private lazy var markdownSegmentedControl: UISegmentedControl = { + let segmentedControl = UISegmentedControl() + let segmentWidth = view.frame.width * 0.25 + + Segment.allCases.forEach { segment in + let segmentIndex = segment.rawValue + segmentedControl.insertSegment(withTitle: segment.title, at: segmentIndex, animated: true) + segmentedControl.setWidth(segmentWidth, forSegmentAt: segmentIndex) + } + + let heavyFontStyle = UIFont.systemFont(ofSize: 14, weight: .heavy) + let fontKey = NSAttributedString.Key.font + segmentedControl.setTitleTextAttributes([fontKey: heavyFontStyle], for: .normal) + segmentedControl.setTitleTextAttributes([fontKey: heavyFontStyle], for: .selected) + + segmentedControl.addTarget(self, action: #selector(markdownSegmentChanged), for: .valueChanged) + segmentedControl.selectedSegmentIndex = Segment.markdown.rawValue + return segmentedControl + }() + private var currentIssue: Issue? private var saveOperation: ((Issue) -> Void)? @@ -34,12 +68,13 @@ final class IssueControlViewController: UIViewController { private func configureViews() { view.backgroundColor = .white - addNavigationButtons() + addNavigationItems() } - private func addNavigationButtons() { + private func addNavigationItems() { navigationItem.leftBarButtonItem = UIBarButtonItem(customView: cancelButton) navigationItem.rightBarButtonItem = UIBarButtonItem(customView: saveButton) + navigationItem.titleView = markdownSegmentedControl } func setSaveOperation(_ operation: @escaping (Issue) -> Void) { @@ -56,4 +91,16 @@ final class IssueControlViewController: UIViewController { saveOperation(tempIssue) } + @objc private func markdownSegmentChanged(_ sender: UISegmentedControl) { + let currentIndex = sender.selectedSegmentIndex + + switch currentIndex { + case Segment.markdown.rawValue: + print("마크다운 내놔") + case Segment.preview.rawValue: + print("프리뷰 내놔") + default: + assert(false) + } + } } From c848b0f49fe7ce200b9cf49fa21aabb4e9437b9a Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 22 Jun 2021 00:01:56 +0900 Subject: [PATCH 64/91] =?UTF-8?q?feat:=20[#86]=20=EC=9D=B4=EC=8A=88=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=20=EA=B8=B0=EB=B3=B8=20=ED=94=84?= =?UTF-8?q?=EB=A0=88=EC=9E=84=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 38 +++++- .../Controller/IssueTableViewDataSource.swift | 24 ++++ .../Controller/IssueViewController.swift | 52 +++++++++ .../Main/Issue/IssueViewController.swift | 18 --- .../Main/Issue/View/IssueTableViewCell.swift | 110 ++++++++++++++++++ 5 files changed, 223 insertions(+), 19 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift delete mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index ad6e9b675..2269c4276 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -63,6 +63,9 @@ FAEB30AE266F6A7800C17BE9 /* UIImageExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAEB30AD266F6A7800C17BE9 /* UIImageExtension.swift */; }; FAEB30B12670B74000C17BE9 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = FAEB30B02670B74000C17BE9 /* Alamofire */; }; FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAEB30B32670B76200C17BE9 /* NetworkManager.swift */; }; + FAF927A92680DAFB0017F8DE /* IssueTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF927A82680DAFB0017F8DE /* IssueTableViewDelegate.swift */; }; + FAF927AB2680DB1C0017F8DE /* IssueTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF927AA2680DB1C0017F8DE /* IssueTableViewDataSource.swift */; }; + FAF927AD2680DCCA0017F8DE /* IssueTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF927AC2680DCCA0017F8DE /* IssueTableViewCell.swift */; }; FAFD11B1268078F80064AED4 /* CommonTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFD11B0268078F80064AED4 /* CommonTableDelegate.swift */; }; /* End PBXBuildFile section */ @@ -124,6 +127,9 @@ FAEB30AB266F5E9700C17BE9 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = ""; }; FAEB30AD266F6A7800C17BE9 /* UIImageExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageExtension.swift; sourceTree = ""; }; FAEB30B32670B76200C17BE9 /* NetworkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkManager.swift; sourceTree = ""; }; + FAF927A82680DAFB0017F8DE /* IssueTableViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = IssueTableViewDelegate.swift; path = ../../../../../../../../../../../Applications/IssueTableViewDelegate.swift; sourceTree = ""; }; + FAF927AA2680DB1C0017F8DE /* IssueTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTableViewDataSource.swift; sourceTree = ""; }; + FAF927AC2680DCCA0017F8DE /* IssueTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTableViewCell.swift; sourceTree = ""; }; FAFD11B0268078F80064AED4 /* CommonTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonTableDelegate.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -260,7 +266,9 @@ E42AD11926708EBA0071B436 /* Issue */ = { isa = PBXGroup; children = ( - E42AD11D267093320071B436 /* IssueViewController.swift */, + FAF927A72680D9630017F8DE /* Controller */, + FAF927A62680D95B0017F8DE /* View */, + FAF927A52680D9560017F8DE /* Model */, ); path = Issue; sourceTree = ""; @@ -403,6 +411,31 @@ path = Network; sourceTree = ""; }; + FAF927A52680D9560017F8DE /* Model */ = { + isa = PBXGroup; + children = ( + ); + path = Model; + sourceTree = ""; + }; + FAF927A62680D95B0017F8DE /* View */ = { + isa = PBXGroup; + children = ( + FAF927AC2680DCCA0017F8DE /* IssueTableViewCell.swift */, + ); + path = View; + sourceTree = ""; + }; + FAF927A72680D9630017F8DE /* Controller */ = { + isa = PBXGroup; + children = ( + E42AD11D267093320071B436 /* IssueViewController.swift */, + FAF927A82680DAFB0017F8DE /* IssueTableViewDelegate.swift */, + FAF927AA2680DB1C0017F8DE /* IssueTableViewDataSource.swift */, + ); + path = Controller; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -480,6 +513,7 @@ buildActionMask = 2147483647; files = ( FAB2C36A26789D41009F879C /* MileStoneTableViewCell.swift in Sources */, + FAF927AB2680DB1C0017F8DE /* IssueTableViewDataSource.swift in Sources */, E426DAD126730DC50069E77D /* OAuthResponseDTO.swift in Sources */, FAFD11B1268078F80064AED4 /* CommonTableDelegate.swift in Sources */, E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */, @@ -523,6 +557,7 @@ E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */, FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */, E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */, + FAF927A92680DAFB0017F8DE /* IssueTableViewDelegate.swift in Sources */, E42AD11E267093320071B436 /* IssueViewController.swift in Sources */, E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */, E43912DC2678A737003CD344 /* JWT.swift in Sources */, @@ -532,6 +567,7 @@ E42AD100266E52FB0071B436 /* SceneDelegate.swift in Sources */, E43912DA26789E16003CD344 /* Label.swift in Sources */, E426DAC92671F7760069E77D /* AlertFactory.swift in Sources */, + FAF927AD2680DCCA0017F8DE /* IssueTableViewCell.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift new file mode 100644 index 000000000..e1cfc16ec --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift @@ -0,0 +1,24 @@ +// +// IssueTableViewDataSource.swift +// issue-tracker +// +// Created by jinseo park on 6/21/21. +// + +import Foundation +import UIKit + +class IssueTableViewDataSource: NSObject, UITableViewDataSource { + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + 3 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cellID = IssueTableViewCell.reuseID + let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? IssueTableViewCell ?? IssueTableViewCell() + return cell + } + + +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift new file mode 100644 index 000000000..0a8be1f44 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift @@ -0,0 +1,52 @@ +// +// IssueViewController.swift +// issue-tracker +// +// Created by Song on 2021/06/09. +// + +import UIKit + +class IssueViewController: UIViewController { + + private var issueTableDatasource: IssueTableViewDataSource? + private var issueTableDelegate: IssueTableViewDelegate? + + private lazy var issueTableView: UITableView = { + let tableView = UITableView() + let cellID = IssueTableViewCell.reuseID + tableView.register(IssueTableViewCell.self, forCellReuseIdentifier: cellID) + tableView.backgroundColor = Colors.background + tableView.translatesAutoresizingMaskIntoConstraints = false + return tableView + }() + + override func viewDidLoad() { + super.viewDidLoad() + title = "이슈 선택" + view.backgroundColor = UIColor.white + + addTableView() + setTableViewSupporters() + } + + private func addTableView() { + view.addSubview(issueTableView) + + NSLayoutConstraint.activate([ + issueTableView.topAnchor.constraint(equalTo: view.topAnchor), + issueTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + issueTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + issueTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + + private func setTableViewSupporters() { + issueTableDatasource = IssueTableViewDataSource() + issueTableDelegate = IssueTableViewDelegate() + + issueTableView.delegate = issueTableDelegate + issueTableView.dataSource = issueTableDatasource + } + +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift deleted file mode 100644 index cc3a5dc1d..000000000 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/IssueViewController.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// IssueViewController.swift -// issue-tracker -// -// Created by Song on 2021/06/09. -// - -import UIKit - -class IssueViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - view.backgroundColor = UIColor.red - title = "이슈 선택" - } - -} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift new file mode 100644 index 000000000..fb5ef067a --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift @@ -0,0 +1,110 @@ +// +// IssueTableViewCell.swift +// issue-tracker +// +// Created by jinseo park on 6/21/21. +// + +import UIKit + +class IssueTableViewCell: UITableViewCell { + + private let spacing: CGFloat = 16 + private lazy var issueStackView: UIStackView = { + let superStackView = UIStackView() + superStackView.axis = .vertical + superStackView.distribution = .fillProportionally + superStackView.translatesAutoresizingMaskIntoConstraints = false + superStackView.spacing = 1 + return superStackView + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.text = "이슈 제목" + label.font = UIFont.boldSystemFont(ofSize: 22) + return label + }() + + private lazy var descriptionLabel: UILabel = { + let label = UILabel() + label.textColor = Colors.description + label.text = "이슈에 대한 설명(최대 두 줄까지 보여줄 수 있다)" + label.font = .systemFont(ofSize: 17) + return label + }() + + private lazy var labelsSubStackView: UIStackView = { + let stackView = UIStackView() + stackView.axis = .horizontal + stackView.distribution = .fill + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + + private lazy var mileStoneLabel: UILabel = { + let label = UILabel() + + let attributedString = NSMutableAttributedString(string: "") + let imageAttachment = NSTextAttachment() + let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : UIColor.systemGray] + let mileStoneName = NSMutableAttributedString(string:"마일스톤 이름", attributes:attrs) + + imageAttachment.image = UIImage(systemName: "signpost.right") + attributedString.append(NSAttributedString(attachment: imageAttachment)) + attributedString.append(mileStoneName) + label.attributedText = attributedString + + return label + }() + + static var reuseID: String { + return String(describing: self) + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setViews() + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setViews() + } + + private func setViews() { + + addIssueStackView() + addIssueTitleView() + addDescriptionLabel() + addMileStoneLabel() + + } + + func addIssueStackView() { + addSubview(issueStackView) + NSLayoutConstraint.activate([ + issueStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16), + issueStackView.topAnchor.constraint(equalTo: topAnchor, constant: 24), + issueStackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -24), + issueStackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16) + ]) + } + + func addIssueTitleView() { + issueStackView.addArrangedSubview(titleLabel) + } + + func addDescriptionLabel() { + issueStackView.addArrangedSubview(descriptionLabel) + } + + func addMileStoneLabel() { + issueStackView.addArrangedSubview(mileStoneLabel) + } + + func addLabelsSubStackView() { + + } + +} From 5308ee9b1be5a101b2dba0f748d5a150556dbc82 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 22 Jun 2021 00:05:06 +0900 Subject: [PATCH 65/91] =?UTF-8?q?chore:[#68]=20=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EC=B9=B4=EB=A9=9C=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Milestone/Controller/MileStoneViewController.swift | 4 ++-- .../Controller/MilestoneTableViewDataSource.swift | 2 +- .../Main/Milestone/Model/NewMileStoneDTO.swift | 4 ++-- .../Main/Milestone/View/MileStoneTableViewCell.swift | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift index b966be9a7..6fd59838c 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift @@ -152,7 +152,7 @@ extension MileStoneViewController { private func postNewMileStone(_ newMileStone: MileStone) { let newMileStoneEndpoint = EndPoint.milestone.path() - let requestBody = NewMileStoneDTO(title: newMileStone.title, description: newMileStone.description ?? "", due_date: newMileStone.dueDate ?? "") + let requestBody = NewMileStoneDTO(title: newMileStone.title, description: newMileStone.description ?? "", dueDate: newMileStone.dueDate ?? "") networkManager?.post(endpoint: newMileStoneEndpoint, requestBody: requestBody, completion: { [weak self] result in switch result { @@ -167,7 +167,7 @@ extension MileStoneViewController { private func putEditedMileStone(_ editedMileStone: MileStone) { let mileStoneId = editedMileStone.id let editMileStoneEndpoint = EndPoint.milestone.path(with: mileStoneId) - let requestBody = NewMileStoneDTO(title: editedMileStone.title, description: editedMileStone.description ?? "", due_date: editedMileStone.dueDate ?? "") + let requestBody = NewMileStoneDTO(title: editedMileStone.title, description: editedMileStone.description ?? "", dueDate: editedMileStone.dueDate ?? "") networkManager?.put(endpoint: editMileStoneEndpoint, requestBody: requestBody, completion: { [weak self] result in switch result { diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift index bd3a87c1b..9683978f4 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MilestoneTableViewDataSource.swift @@ -25,7 +25,7 @@ class MilestoneTableViewDataSource: NSObject, UITableViewDataSource { let milestone = milestones[indexPath.row] - cell.configure(title: milestone.title, description: milestone.description ?? "", due_date: milestone.dueDate ?? "") + cell.configure(title: milestone.title, description: milestone.description ?? "", dueDate: milestone.dueDate ?? "") return cell } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/NewMileStoneDTO.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/NewMileStoneDTO.swift index 31874fb2e..bd922e081 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/NewMileStoneDTO.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/NewMileStoneDTO.swift @@ -11,11 +11,11 @@ struct NewMileStoneDTO: Encodable { let title: String let description: String - let due_date: String + let dueDate: String enum CodingKeys: String, CodingKey { case title case description - case due_date + case dueDate = "due_date" } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index 389abff10..19c064497 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -153,14 +153,14 @@ class MileStoneTableViewCell: UITableViewCell { } - func configure(title: String, description: String, due_date: String) { + func configure(title: String, description: String, dueDate: String) { titleLabel.text = title descriptionLabel.text = description - dueDateConfigure(due_date: due_date) + dueDateConfigure(dueDate: dueDate) } - private func dueDateConfigure(due_date: String) { - let dateText = due_date != "" ? due_date :"완료일(생략가능)" + private func dueDateConfigure(dueDate: String) { + let dateText = dueDate != "" ? dueDate :"완료일(생략가능)" let attributedString = NSMutableAttributedString(string: "") let imageAttachment = NSTextAttachment() imageAttachment.image = UIImage(systemName: "calendar") From 5a8dcd6460cf19a54110e3c288b636a6d61397c4 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 22 Jun 2021 11:29:42 +0900 Subject: [PATCH 66/91] =?UTF-8?q?feat:=20[#82]=20=EC=A0=9C=EB=AA=A9=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20view=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IssueControlViewController.swift | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift index d08eb9785..b04ce3991 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift @@ -58,6 +58,54 @@ final class IssueControlViewController: UIViewController { return segmentedControl }() + private lazy var titleInputView: UIView = { + let container = UIView(frame: .zero) + container.translatesAutoresizingMaskIntoConstraints = false + + let titleLabel = UILabel() + titleLabel.text = "제목" + titleLabel.translatesAutoresizingMaskIntoConstraints = false + + container.addSubview(titleLabel) + + NSLayoutConstraint.activate([ + titleLabel.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing), + titleLabel.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) + ]) + + container.addSubview(titleTextField) + + NSLayoutConstraint.activate([ + titleTextField.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing * 5), + titleTextField.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), + titleTextField.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) + ]) + + let line = CALayer() + let borderWidth: CGFloat = 1 + let size = CGSize(width: view.frame.width - spacing, height: borderWidth) + let origin = CGPoint(x: spacing, y: lineHeight - borderWidth) + line.frame = CGRect(origin: origin, size: size) + line.backgroundColor = Colors.border.cgColor + container.layer.addSublayer(line) + return container + }() + + private lazy var titleTextField: UITextField = { + let textField = UITextField() + textField.placeholder = "(필수 입력)" + textField.translatesAutoresizingMaskIntoConstraints = false + return textField + }() + + private lazy var lineHeight: CGFloat = { + return view.frame.height * 0.05 + }() + + private lazy var spacing: CGFloat = { + return lineHeight * 0.5 + }() + private var currentIssue: Issue? private var saveOperation: ((Issue) -> Void)? @@ -67,8 +115,10 @@ final class IssueControlViewController: UIViewController { } private func configureViews() { + navigationController?.navigationBar.prefersLargeTitles = false view.backgroundColor = .white addNavigationItems() + addTitleInputView() } private func addNavigationItems() { @@ -77,6 +127,17 @@ final class IssueControlViewController: UIViewController { navigationItem.titleView = markdownSegmentedControl } + private func addTitleInputView() { + view.addSubview(titleInputView) + + NSLayoutConstraint.activate([ + titleInputView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: spacing * 0.3), + titleInputView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + titleInputView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + titleInputView.heightAnchor.constraint(equalToConstant: lineHeight) + ]) + } + func setSaveOperation(_ operation: @escaping (Issue) -> Void) { self.saveOperation = operation } From 99c994eb1df43d051b28f9a445208db723a30d70 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 22 Jun 2021 12:10:10 +0900 Subject: [PATCH 67/91] =?UTF-8?q?feat:=20[#82]=20=EB=82=B4=EC=9A=A9=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20textView=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IssueControlViewController.swift | 63 ++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift index b04ce3991..2cd49a8cb 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift @@ -21,6 +21,7 @@ final class IssueControlViewController: UIViewController { let button = ImageBarButton() button.configure(with: "plus", "저장") button.addTarget(self, action: #selector(saveButtonTouched), for: .touchUpInside) + changeSaveButtonEnableStatus(baseOn: titleTextField) return button }() @@ -76,7 +77,7 @@ final class IssueControlViewController: UIViewController { container.addSubview(titleTextField) NSLayoutConstraint.activate([ - titleTextField.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing * 5), + titleTextField.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: spacing * 3), titleTextField.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), titleTextField.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) ]) @@ -95,9 +96,22 @@ final class IssueControlViewController: UIViewController { let textField = UITextField() textField.placeholder = "(필수 입력)" textField.translatesAutoresizingMaskIntoConstraints = false + textField.delegate = self return textField }() + private lazy var bodyTextView: UITextView = { + let textView = UITextView() + textView.text = bodyPlaceholder + textView.font = .systemFont(ofSize: 17) + textView.textColor = .lightGray + textView.translatesAutoresizingMaskIntoConstraints = false + textView.delegate = self + return textView + }() + + private let bodyPlaceholder = "이곳에 내용을 입력하세요" + private lazy var lineHeight: CGFloat = { return view.frame.height * 0.05 }() @@ -115,10 +129,13 @@ final class IssueControlViewController: UIViewController { } private func configureViews() { - navigationController?.navigationBar.prefersLargeTitles = false view.backgroundColor = .white + navigationController?.navigationBar.prefersLargeTitles = false + navigationItem.rightBarButtonItem?.isEnabled = saveButton.isEnabled + addNavigationItems() addTitleInputView() + addBodyTextView() } private func addNavigationItems() { @@ -138,10 +155,25 @@ final class IssueControlViewController: UIViewController { ]) } + private func addBodyTextView() { + view.addSubview(bodyTextView) + + NSLayoutConstraint.activate([ + bodyTextView.topAnchor.constraint(equalTo: titleInputView.bottomAnchor, constant: spacing * 0.3), + bodyTextView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: spacing), + bodyTextView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), + bodyTextView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } + func setSaveOperation(_ operation: @escaping (Issue) -> Void) { self.saveOperation = operation } + private func changeSaveButtonEnableStatus(to status: Bool) { + saveButton.isEnabled = status + } + @objc private func cancelButtonTouched(_ sender: UIButton) { navigationController?.popViewController(animated: true) } @@ -165,3 +197,30 @@ final class IssueControlViewController: UIViewController { } } } + +extension IssueControlViewController: UITextFieldDelegate { + func textFieldDidChangeSelection(_ textField: UITextField) { + changeSaveButtonEnableStatus(baseOn: textField) + } + + private func changeSaveButtonEnableStatus(baseOn textField: UITextField) { + DispatchQueue.main.async { + self.saveButton.isEnabled = !textField.isEmpty() + } + } +} + +extension IssueControlViewController: UITextViewDelegate { + func textViewDidBeginEditing(_ textView: UITextView) { + textView.textColor = .black + textView.text = nil + } + + func textViewDidEndEditing(_ textView: UITextView) { + if textView.text.isEmpty { + textView.textColor = .lightGray + textView.text = bodyPlaceholder + changeSaveButtonEnableStatus(to: false) + } + } +} From f951ff4c3afcddcbc03df27276225849f3b15e3a Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 22 Jun 2021 17:13:53 +0900 Subject: [PATCH 68/91] =?UTF-8?q?feat:=20[#82]=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=9E=85=EB=A0=A5=EB=9E=80=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MultiLineInputStackView 활용 --- .../issue-tracker.xcodeproj/project.pbxproj | 12 ++++ .../View/MultipleLineInputStackView.swift | 5 +- .../IssueControlViewController.swift | 60 +++++++++++++++- .../Main/Issue/View/IssueInfoView.swift | 71 +++++++++++++++++++ 4 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueInfoView.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 28228839b..2935e0d97 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -49,6 +49,7 @@ E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; E49695672680B0B7001AEB89 /* IssueControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695662680B0B7001AEB89 /* IssueControlViewController.swift */; }; E49695692680B3FB001AEB89 /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695682680B3FB001AEB89 /* Issue.swift */; }; + E496956E2681905A001AEB89 /* IssueInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496956D2681905A001AEB89 /* IssueInfoView.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -113,6 +114,7 @@ E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; E49695662680B0B7001AEB89 /* IssueControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueControlViewController.swift; sourceTree = ""; }; E49695682680B3FB001AEB89 /* Issue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Issue.swift; sourceTree = ""; }; + E496956D2681905A001AEB89 /* IssueInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueInfoView.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -265,6 +267,7 @@ isa = PBXGroup; children = ( E496956B2680B40D001AEB89 /* Model */, + E496956C26819042001AEB89 /* View */, E496956A2680B3FE001AEB89 /* Controller */, E42AD11D267093320071B436 /* IssueViewController.swift */, ); @@ -366,6 +369,14 @@ path = Model; sourceTree = ""; }; + E496956C26819042001AEB89 /* View */ = { + isa = PBXGroup; + children = ( + E496956D2681905A001AEB89 /* IssueInfoView.swift */, + ); + path = View; + sourceTree = ""; + }; FA8840422671F9B000ECCF7A /* Apple */ = { isa = PBXGroup; children = ( @@ -526,6 +537,7 @@ E43912EA267A2351003CD344 /* NetworkError.swift in Sources */, E43912F6267CAE01003CD344 /* TopMenuView.swift in Sources */, E42AD122267093590071B436 /* MileStoneViewController.swift in Sources */, + E496956E2681905A001AEB89 /* IssueInfoView.swift in Sources */, FA733A2E267C3D77005A40C8 /* Milestone.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift index 847dd7d7b..667dee77b 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/MultipleLineInputStackView.swift @@ -81,7 +81,8 @@ final class MultipleLineInputStackView: UIStackView { NSLayoutConstraint.activate([ inputView.leadingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.leadingAnchor, constant: elementSpacing * 5), inputView.trailingAnchor.constraint(equalTo: container.safeAreaLayoutGuide.trailingAnchor, constant: -elementSpacing), - inputView.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor) + inputView.centerYAnchor.constraint(equalTo: container.safeAreaLayoutGuide.centerYAnchor), + inputView.topAnchor.constraint(equalTo: container.safeAreaLayoutGuide.topAnchor) ]) addArrangedSubview(container) } @@ -103,7 +104,7 @@ final class MultipleLineInputStackView: UIStackView { for i in 1...itemCount-1 { let line = CALayer() - let origin = CGPoint(x: spacing, y: lineHeight * CGFloat(i) - borderWidth) + let origin = CGPoint(x: elementSpacing, y: lineHeight * CGFloat(i) - borderWidth) line.frame = CGRect(origin: origin, size: size) line.backgroundColor = borderColor layer.addSublayer(line) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift index 2cd49a8cb..43c19d7f4 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift @@ -60,7 +60,7 @@ final class IssueControlViewController: UIViewController { }() private lazy var titleInputView: UIView = { - let container = UIView(frame: .zero) + let container = UIView() container.translatesAutoresizingMaskIntoConstraints = false let titleLabel = UILabel() @@ -110,6 +110,38 @@ final class IssueControlViewController: UIViewController { return textView }() + private lazy var additionalInfoView: MultipleLineInputStackView = { + let viewWidth = view.frame.width + let stackViewFrame = CGRect(x: 0, y: 0, width: viewWidth, height: lineHeight * 3) + let stackView = MultipleLineInputStackView(frame: stackViewFrame) + + let labelInfoItem = InputLineItem(category: "레이블", inputView: labelInfoControl) + let milestoneInfoItem = InputLineItem(category: "마일스톤", inputView: milestoneInfoControl) + let assigneeInfoItem = InputLineItem(category: "담당자", inputView: assigneeInfoControl) + stackView.configure(with: [labelInfoItem, milestoneInfoItem, assigneeInfoItem]) + + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + + private lazy var labelInfoControl: IssueInfoControl = { + let infoControl = IssueInfoControl() + infoControl.addTarget(self, action: #selector(labelInfoTouched), for: .touchUpInside) + return infoControl + }() + + private lazy var milestoneInfoControl: IssueInfoControl = { + let infoControl = IssueInfoControl() + infoControl.addTarget(self, action: #selector(milestoneInfoTouched), for: .touchUpInside) + return infoControl + }() + + private lazy var assigneeInfoControl: IssueInfoControl = { + let infoControl = IssueInfoControl() + infoControl.addTarget(self, action: #selector(assigneeInfoTouched), for: .touchUpInside) + return infoControl + }() + private let bodyPlaceholder = "이곳에 내용을 입력하세요" private lazy var lineHeight: CGFloat = { @@ -135,6 +167,7 @@ final class IssueControlViewController: UIViewController { addNavigationItems() addTitleInputView() + addAdditionalInfoView() addBodyTextView() } @@ -155,6 +188,17 @@ final class IssueControlViewController: UIViewController { ]) } + private func addAdditionalInfoView() { + view.addSubview(additionalInfoView) + + NSLayoutConstraint.activate([ + additionalInfoView.heightAnchor.constraint(equalToConstant: lineHeight * 3), + additionalInfoView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + additionalInfoView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + additionalInfoView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } + private func addBodyTextView() { view.addSubview(bodyTextView) @@ -162,7 +206,7 @@ final class IssueControlViewController: UIViewController { bodyTextView.topAnchor.constraint(equalTo: titleInputView.bottomAnchor, constant: spacing * 0.3), bodyTextView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: spacing), bodyTextView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), - bodyTextView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + bodyTextView.bottomAnchor.constraint(equalTo: additionalInfoView.topAnchor) ]) } @@ -196,6 +240,18 @@ final class IssueControlViewController: UIViewController { assert(false) } } + + @objc private func labelInfoTouched(_ sender: UIButton) { + print("레이블 내놔!") + } + + @objc private func milestoneInfoTouched(_ sender: UIButton) { + print("마일스톤 내놔!") + } + + @objc private func assigneeInfoTouched(_ sender: UIButton) { + print("담당자 내놔!") + } } extension IssueControlViewController: UITextFieldDelegate { diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueInfoView.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueInfoView.swift new file mode 100644 index 000000000..11c2517a7 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueInfoView.swift @@ -0,0 +1,71 @@ +// +// IssueInfoView.swift +// issue-tracker +// +// Created by Song on 2021/06/22. +// + +import UIKit + +final class IssueInfoControl: UIControl { + + private lazy var infoLabel: UILabel = { + let label = UILabel() + label.textColor = .lightGray + label.textAlignment = .right + label.text = "info" + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + private lazy var infoSetButton: UIButton = { + let button = UIButton() + let buttonImage = UIImage(systemName: "chevron.right") + button.tintColor = .lightGray + button.setTitle(nil, for: .normal) + button.setImage(buttonImage, for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + private let spacing: CGFloat = 15 + + override init(frame: CGRect) { + super.init(frame: frame) + configure() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + configure() + } + + private func configure() { + addInfoSetButton() + addInfoLabel() + } + + private func addInfoSetButton() { + addSubview(infoSetButton) + + NSLayoutConstraint.activate([ + infoSetButton.widthAnchor.constraint(equalToConstant: 20), + infoSetButton.trailingAnchor.constraint(equalTo: trailingAnchor), + infoSetButton.centerYAnchor.constraint(equalTo: centerYAnchor) + ]) + } + + private func addInfoLabel() { + addSubview(infoLabel) + + NSLayoutConstraint.activate([ + infoLabel.leadingAnchor.constraint(equalTo: leadingAnchor), + infoLabel.trailingAnchor.constraint(equalTo: infoSetButton.leadingAnchor, constant: -spacing), + infoLabel.centerYAnchor.constraint(equalTo: centerYAnchor) + ]) + } + + func changeInfoLabelText(to text: String) { + infoLabel.text = text + } +} From 7a2b5d63d6485d28dd60aa3dc56d7aa3ce1dd679 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 22 Jun 2021 17:18:42 +0900 Subject: [PATCH 69/91] =?UTF-8?q?feat:=20=EB=B2=84=ED=8A=BC=20disable=20?= =?UTF-8?q?=EC=8B=9C=20=EB=B2=84=ED=8A=BC=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=83=89=EC=83=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker/Main/Common/View/ImageBarButton.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift b/iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift index 2f48b6b3b..0ecba52f7 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Common/View/ImageBarButton.swift @@ -19,6 +19,12 @@ final class ImageBarButton: UIButton { configure() } + override var isEnabled: Bool { + didSet { + self.tintColor = self.isEnabled ? Colors.mainGrape : UIColor.lightGray + } + } + private func configure() { tintColor = Colors.mainGrape setTitleColor(Colors.mainGrape, for: .normal) From 10c7ff0b69a4c3026cea1b2e4027ed1fe060e7ca Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 22 Jun 2021 17:28:07 +0900 Subject: [PATCH 70/91] =?UTF-8?q?chore:=20[#82]=20SwiftyMarkdown=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 17 +++++++++++++++++ .../xcshareddata/swiftpm/Package.resolved | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 2935e0d97..669889628 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -50,6 +50,7 @@ E49695672680B0B7001AEB89 /* IssueControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695662680B0B7001AEB89 /* IssueControlViewController.swift */; }; E49695692680B3FB001AEB89 /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695682680B3FB001AEB89 /* Issue.swift */; }; E496956E2681905A001AEB89 /* IssueInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496956D2681905A001AEB89 /* IssueInfoView.swift */; }; + E49695712681D5E5001AEB89 /* SwiftyMarkdown in Frameworks */ = {isa = PBXBuildFile; productRef = E49695702681D5E5001AEB89 /* SwiftyMarkdown */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -139,6 +140,7 @@ buildActionMask = 2147483647; files = ( FAEB30B12670B74000C17BE9 /* Alamofire in Frameworks */, + E49695712681D5E5001AEB89 /* SwiftyMarkdown in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -454,6 +456,7 @@ name = "issue-tracker"; packageProductDependencies = ( FAEB30B02670B74000C17BE9 /* Alamofire */, + E49695702681D5E5001AEB89 /* SwiftyMarkdown */, ); productName = "issue-tracker"; productReference = E42AD0FA266E52FB0071B436 /* issue-tracker.app */; @@ -484,6 +487,7 @@ mainGroup = E42AD0F1266E52FB0071B436; packageReferences = ( FAEB30AF2670B74000C17BE9 /* XCRemoteSwiftPackageReference "Alamofire" */, + E496956F2681D5E5001AEB89 /* XCRemoteSwiftPackageReference "SwiftyMarkdown" */, ); productRefGroup = E42AD0FB266E52FB0071B436 /* Products */; projectDirPath = ""; @@ -773,6 +777,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + E496956F2681D5E5001AEB89 /* XCRemoteSwiftPackageReference "SwiftyMarkdown" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SimonFairbairn/SwiftyMarkdown.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.2.3; + }; + }; FAEB30AF2670B74000C17BE9 /* XCRemoteSwiftPackageReference "Alamofire" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Alamofire/Alamofire.git"; @@ -784,6 +796,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + E49695702681D5E5001AEB89 /* SwiftyMarkdown */ = { + isa = XCSwiftPackageProductDependency; + package = E496956F2681D5E5001AEB89 /* XCRemoteSwiftPackageReference "SwiftyMarkdown" */; + productName = SwiftyMarkdown; + }; FAEB30B02670B74000C17BE9 /* Alamofire */ = { isa = XCSwiftPackageProductDependency; package = FAEB30AF2670B74000C17BE9 /* XCRemoteSwiftPackageReference "Alamofire" */; diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/iOS/issue-tracker/issue-tracker.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 20e547a35..484d9ea26 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -9,6 +9,15 @@ "revision": "f96b619bcb2383b43d898402283924b80e2c4bae", "version": "5.4.3" } + }, + { + "package": "SwiftyMarkdown", + "repositoryURL": "https://github.com/SimonFairbairn/SwiftyMarkdown.git", + "state": { + "branch": null, + "revision": "5b0a1e76332a633726f9f9a00b4bbd840166bccf", + "version": "1.2.3" + } } ] }, From c132ad502dacf1157b92577142921704e983ad0a Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 22 Jun 2021 17:30:29 +0900 Subject: [PATCH 71/91] =?UTF-8?q?feat:=20[#86]=20=EC=9D=B4=EC=8A=88=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EB=B7=B0=20=ED=94=84=EB=A0=88=EC=9E=84=20?= =?UTF-8?q?=EC=A0=9C=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Main/Issue/View/IssueTableViewCell.swift | 67 +++++++++++++++++-- .../View/MileStoneTableViewCell.swift | 1 + 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift index fb5ef067a..3da9b7019 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift @@ -30,14 +30,15 @@ class IssueTableViewCell: UITableViewCell { let label = UILabel() label.textColor = Colors.description label.text = "이슈에 대한 설명(최대 두 줄까지 보여줄 수 있다)" + label.numberOfLines = 2 label.font = .systemFont(ofSize: 17) return label }() - private lazy var labelsSubStackView: UIStackView = { + private lazy var labelsStackView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal - stackView.distribution = .fill + stackView.distribution = .fillProportionally stackView.translatesAutoresizingMaskIntoConstraints = false return stackView }() @@ -54,10 +55,10 @@ class IssueTableViewCell: UITableViewCell { attributedString.append(NSAttributedString(attachment: imageAttachment)) attributedString.append(mileStoneName) label.attributedText = attributedString - + return label }() - + static var reuseID: String { return String(describing: self) } @@ -73,11 +74,12 @@ class IssueTableViewCell: UITableViewCell { } private func setViews() { - + addIssueStackView() addIssueTitleView() addDescriptionLabel() addMileStoneLabel() + addlabelsStackView() } @@ -103,8 +105,61 @@ class IssueTableViewCell: UITableViewCell { issueStackView.addArrangedSubview(mileStoneLabel) } - func addLabelsSubStackView() { + //여기서 인자 값으로 GET으로 라벨의 갯수와 라벨 배열을 가져와야 할 것같다. + func addlabelsStackView() { + + issueStackView.addArrangedSubview(labelsStackView) + + labelsStackView.spacing = 4 + NSLayoutConstraint.activate([ + labelsStackView.leadingAnchor.constraint(equalTo: issueStackView.leadingAnchor), + labelsStackView.trailingAnchor.constraint(equalTo: issueStackView.trailingAnchor) + ]) + + + let labelView1 = LabelView() + let colorText1 = "#34e6b1" + let hex1 = HexColorCode(from: colorText1) + let titleText1 = "feat" + labelView1.configure(with: hex1, titleText1) + labelView1.translatesAutoresizingMaskIntoConstraints = false + + let labelView2 = LabelView() + let colorText2 = "#1af6c5" + let hex2 = HexColorCode(from: colorText2) + let titleText2 = "하이하이하이하이" + labelView2.configure(with: hex2, titleText2) + labelView2.translatesAutoresizingMaskIntoConstraints = false + + let labelView3 = LabelView() + let colorText3 = "#3af6c5" + let hex3 = HexColorCode(from: colorText3) + let titleText3 = "iOSafafa" + labelView3.configure(with: hex3, titleText3) + labelView3.translatesAutoresizingMaskIntoConstraints = false + + let labelView4 = LabelView() + let colorText4 = "#fbfbcc" + let hex4 = HexColorCode(from: colorText4) + let titleText4 = "abdfsfwasdfsafafasdfas" + labelView4.configure(with: hex4, titleText4) + labelView4.translatesAutoresizingMaskIntoConstraints = false + + let labelView5 = LabelView() + let colorText5 = "#fbfbcc" + let hex5 = HexColorCode(from: colorText5) + let titleText5 = "abdfsfwasdfsafafasdfas" + labelView5.configure(with: hex5, titleText5) + labelView5.translatesAutoresizingMaskIntoConstraints = false + + + labelsStackView.addArrangedSubview(labelView1) + labelsStackView.addArrangedSubview(labelView2) + labelsStackView.addArrangedSubview(labelView3) +// labelsStackView.addArrangedSubview(labelView4) +// labelsStackView.addArrangedSubview(labelView5) + } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index 19c064497..2352acf0b 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -46,6 +46,7 @@ class MileStoneTableViewCell: UITableViewCell { let label = UILabel() label.textColor = Colors.description label.text = "마일스톤에 대한 설명(한 줄만 보여짐, 생략 가능)" + label.numberOfLines = 1 label.font = .systemFont(ofSize: 17) return label }() From e1bbd7db7e54d12757862e6ba1099d0be453d4b3 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 22 Jun 2021 17:56:07 +0900 Subject: [PATCH 72/91] =?UTF-8?q?feat=20:[#86]=20=EC=9D=B4=EC=8A=88DTO=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 4 + .../Main/Issue/Model/Issue.swift | 75 +++++++++++++++++++ .../Main/Issue/View/IssueTableViewCell.swift | 17 +---- .../issue-tracker/Network/EndPoint.swift | 5 +- 4 files changed, 84 insertions(+), 17 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 2269c4276..5ec5bf0c1 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -66,6 +66,7 @@ FAF927A92680DAFB0017F8DE /* IssueTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF927A82680DAFB0017F8DE /* IssueTableViewDelegate.swift */; }; FAF927AB2680DB1C0017F8DE /* IssueTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF927AA2680DB1C0017F8DE /* IssueTableViewDataSource.swift */; }; FAF927AD2680DCCA0017F8DE /* IssueTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF927AC2680DCCA0017F8DE /* IssueTableViewCell.swift */; }; + FAF927AF2681DA810017F8DE /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF927AE2681DA810017F8DE /* Issue.swift */; }; FAFD11B1268078F80064AED4 /* CommonTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFD11B0268078F80064AED4 /* CommonTableDelegate.swift */; }; /* End PBXBuildFile section */ @@ -130,6 +131,7 @@ FAF927A82680DAFB0017F8DE /* IssueTableViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = IssueTableViewDelegate.swift; path = ../../../../../../../../../../../Applications/IssueTableViewDelegate.swift; sourceTree = ""; }; FAF927AA2680DB1C0017F8DE /* IssueTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTableViewDataSource.swift; sourceTree = ""; }; FAF927AC2680DCCA0017F8DE /* IssueTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTableViewCell.swift; sourceTree = ""; }; + FAF927AE2681DA810017F8DE /* Issue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Issue.swift; sourceTree = ""; }; FAFD11B0268078F80064AED4 /* CommonTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonTableDelegate.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -414,6 +416,7 @@ FAF927A52680D9560017F8DE /* Model */ = { isa = PBXGroup; children = ( + FAF927AE2681DA810017F8DE /* Issue.swift */, ); path = Model; sourceTree = ""; @@ -553,6 +556,7 @@ E426DABE2670EC830069E77D /* SocialLoginManagerDelegate.swift in Sources */, FA733A30267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift in Sources */, E42AD0FE266E52FB0071B436 /* AppDelegate.swift in Sources */, + FAF927AF2681DA810017F8DE /* Issue.swift in Sources */, E43912EE267C3C0E003CD344 /* CellAction.swift in Sources */, E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */, FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift new file mode 100644 index 000000000..2c94fb3fd --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift @@ -0,0 +1,75 @@ +// +// Issue.swift +// issue-tracker +// +// Created by jinseo park on 6/22/21. +// + +import Foundation + + +struct IssueDTO: Decodable { + let data: [Issue]? + let message: String? + + enum CodingKeys: String, CodingKey { + case data + case message = "msg" + } +} + +class Author: Decodable { + private(set) var id: Int + private(set) var name: String + private(set) var imageUrl: String + + enum CodingKeys: String, CodingKey { + case id + case name + case imageUrl + } +} + +class Assignee: Decodable { + private(set) var id: Int + private(set) var name: String + private(set) var imageUrl: String + + enum CodingKeys: String, CodingKey { + case id + case name + case imageUrl + } +} +class Issue: Decodable { + private(set) var issueNumber: Int + private(set) var title: String + private(set) var status: Bool + private(set) var author: Author + private(set) var assignees: [Assignee] + private(set) var labels: [Label] + private(set) var milestone: MileStone + private(set) var created_date: String + + init(issueNumber: Int, title: String, status: Bool, author: Author, assignees: [Assignee], labels: [Label], milestone: MileStone, created_date: String) { + self.issueNumber = issueNumber + self.title = title + self.status = status + self.author = author + self.assignees = assignees + self.labels = labels + self.milestone = milestone + self.created_date = created_date + } + + enum CodingKeys: String, CodingKey { + case issueNumber + case title + case status + case author + case assignees + case labels + case milestone + case created_date = "createdDate" + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift index 3da9b7019..9931ddd39 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift @@ -26,15 +26,6 @@ class IssueTableViewCell: UITableViewCell { return label }() - private lazy var descriptionLabel: UILabel = { - let label = UILabel() - label.textColor = Colors.description - label.text = "이슈에 대한 설명(최대 두 줄까지 보여줄 수 있다)" - label.numberOfLines = 2 - label.font = .systemFont(ofSize: 17) - return label - }() - private lazy var labelsStackView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal @@ -77,10 +68,8 @@ class IssueTableViewCell: UITableViewCell { addIssueStackView() addIssueTitleView() - addDescriptionLabel() addMileStoneLabel() addlabelsStackView() - } func addIssueStackView() { @@ -97,19 +86,15 @@ class IssueTableViewCell: UITableViewCell { issueStackView.addArrangedSubview(titleLabel) } - func addDescriptionLabel() { - issueStackView.addArrangedSubview(descriptionLabel) - } - func addMileStoneLabel() { issueStackView.addArrangedSubview(mileStoneLabel) } //여기서 인자 값으로 GET으로 라벨의 갯수와 라벨 배열을 가져와야 할 것같다. +// func addlabelsStackView(_ labels: [Label]) func addlabelsStackView() { issueStackView.addArrangedSubview(labelsStackView) - labelsStackView.spacing = 4 NSLayoutConstraint.activate([ diff --git a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift index 549463b78..6fa755f85 100644 --- a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift +++ b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift @@ -11,6 +11,7 @@ enum EndPoint { static let baseAddress = "http://3.34.122.67/api" case OAuth + case issue case label case milestone case none @@ -19,12 +20,14 @@ enum EndPoint { switch self { case .OAuth: return "/login/ios" + case .issue: + return "/login/issues" case .label: return "/labels" case .milestone: return "/milestones" case .none: - return "" + return "" } } From 6bb621c64b48cad2d5f69ab8b956e6b26a65ea94 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 22 Jun 2021 18:40:03 +0900 Subject: [PATCH 73/91] =?UTF-8?q?feat:=20[#82]=20=EB=A7=88=ED=81=AC?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=EB=AF=B8=EB=A6=AC=EB=B3=B4=EA=B8=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - code가 제대로 나타나고 있지 않음 --- .../issue-tracker.xcodeproj/project.pbxproj | 4 ++ .../Common/MarkdownConverter.swift | 30 ++++++++++++ .../IssueControlViewController.swift | 47 +++++++++++++++---- 3 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Common/MarkdownConverter.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 669889628..5fd2b4014 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -51,6 +51,7 @@ E49695692680B3FB001AEB89 /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695682680B3FB001AEB89 /* Issue.swift */; }; E496956E2681905A001AEB89 /* IssueInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496956D2681905A001AEB89 /* IssueInfoView.swift */; }; E49695712681D5E5001AEB89 /* SwiftyMarkdown in Frameworks */ = {isa = PBXBuildFile; productRef = E49695702681D5E5001AEB89 /* SwiftyMarkdown */; }; + E49695732681DA29001AEB89 /* MarkdownConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695722681DA29001AEB89 /* MarkdownConverter.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -116,6 +117,7 @@ E49695662680B0B7001AEB89 /* IssueControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueControlViewController.swift; sourceTree = ""; }; E49695682680B3FB001AEB89 /* Issue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Issue.swift; sourceTree = ""; }; E496956D2681905A001AEB89 /* IssueInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueInfoView.swift; sourceTree = ""; }; + E49695722681DA29001AEB89 /* MarkdownConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownConverter.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -221,6 +223,7 @@ E426DAC82671F7760069E77D /* AlertFactory.swift */, E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */, FA431FFC267F61150010EA91 /* String.swift */, + E49695722681DA29001AEB89 /* MarkdownConverter.swift */, ); path = Common; sourceTree = ""; @@ -545,6 +548,7 @@ FA733A2E267C3D77005A40C8 /* Milestone.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */, + E49695732681DA29001AEB89 /* MarkdownConverter.swift in Sources */, E426DAC22671B1C60069E77D /* LoginKeyChainManager.swift in Sources */, E43912D426788CC3003CD344 /* ImageBarButton.swift in Sources */, E43912D2267878F4003CD344 /* HexColorCode.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Common/MarkdownConverter.swift b/iOS/issue-tracker/issue-tracker/Common/MarkdownConverter.swift new file mode 100644 index 000000000..9de1b0d84 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Common/MarkdownConverter.swift @@ -0,0 +1,30 @@ +// +// MarkdownConverter.swift +// issue-tracker +// +// Created by Song on 2021/06/22. +// + +import Foundation +import SwiftyMarkdown + +struct MarkdownConverter { + + private var customBullet: String? + var rawText = "" + + init(customBullet: String? = nil) { + self.customBullet = customBullet + } + + func preview(rawText: String) -> NSAttributedString { + let markdown = SwiftyMarkdown(string: rawText) + setCustomBullet(to: markdown) + return markdown.attributedString() + } + + private func setCustomBullet(to markdown: SwiftyMarkdown) { + guard let customBullet = customBullet else { return } + markdown.bullet = customBullet + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift index 43c19d7f4..c27b85a47 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift @@ -105,6 +105,7 @@ final class IssueControlViewController: UIViewController { textView.text = bodyPlaceholder textView.font = .systemFont(ofSize: 17) textView.textColor = .lightGray + textView.dataDetectorTypes = UIDataDetectorTypes.all textView.translatesAutoresizingMaskIntoConstraints = false textView.delegate = self return textView @@ -143,6 +144,7 @@ final class IssueControlViewController: UIViewController { }() private let bodyPlaceholder = "이곳에 내용을 입력하세요" + private var markdownConverter = MarkdownConverter(customBullet: "✔️") private lazy var lineHeight: CGFloat = { return view.frame.height * 0.05 @@ -181,7 +183,7 @@ final class IssueControlViewController: UIViewController { view.addSubview(titleInputView) NSLayoutConstraint.activate([ - titleInputView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: spacing * 0.3), + titleInputView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: spacing * 0.7), titleInputView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), titleInputView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), titleInputView.heightAnchor.constraint(equalToConstant: lineHeight) @@ -203,9 +205,9 @@ final class IssueControlViewController: UIViewController { view.addSubview(bodyTextView) NSLayoutConstraint.activate([ - bodyTextView.topAnchor.constraint(equalTo: titleInputView.bottomAnchor, constant: spacing * 0.3), - bodyTextView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: spacing), - bodyTextView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -spacing), + bodyTextView.topAnchor.constraint(equalTo: titleInputView.bottomAnchor, constant: spacing * 0.7), + bodyTextView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: spacing * 0.8), + bodyTextView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -spacing * 0.8), bodyTextView.bottomAnchor.constraint(equalTo: additionalInfoView.topAnchor) ]) } @@ -233,14 +235,41 @@ final class IssueControlViewController: UIViewController { switch currentIndex { case Segment.markdown.rawValue: - print("마크다운 내놔") + previewToMarkDown() case Segment.preview.rawValue: - print("프리뷰 내놔") + markdownToPreview() default: assert(false) } } + private func previewToMarkDown() { + bodyTextView.attributedText = nil + bodyTextView.text = markdownConverter.rawText + + changeTextViewEditable(to: true) + changeToplainTextView() + } + + private func markdownToPreview() { + guard let rawText = bodyTextView.text else { return } + let preview = markdownConverter.preview(rawText: rawText) + markdownConverter.rawText = rawText + bodyTextView.text = nil + bodyTextView.attributedText = preview + + changeTextViewEditable(to: false) + } + + private func changeTextViewEditable(to status: Bool) { + bodyTextView.isEditable = status + } + + private func changeToplainTextView() { + bodyTextView.font = .systemFont(ofSize: 17) + bodyTextView.textColor = .black + } + @objc private func labelInfoTouched(_ sender: UIButton) { print("레이블 내놔!") } @@ -268,8 +297,10 @@ extension IssueControlViewController: UITextFieldDelegate { extension IssueControlViewController: UITextViewDelegate { func textViewDidBeginEditing(_ textView: UITextView) { - textView.textColor = .black - textView.text = nil + if textView.textColor == .lightGray { + textView.textColor = .black + textView.text = nil + } } func textViewDidEndEditing(_ textView: UITextView) { From 8691a9ca2e44ec4763f8896564a05e27ae16989a Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 22 Jun 2021 22:56:54 +0900 Subject: [PATCH 74/91] =?UTF-8?q?feat:=20[#82]=20=EB=A7=88=ED=81=AC?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC?= =?UTF-8?q?=EB=A6=AC=20=EA=B5=90=EC=B2=B4=ED=95=98=EC=97=AC=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 24 ++++----- .../xcshareddata/swiftpm/Package.resolved | 8 +-- .../Common/MarkdownConverter.swift | 30 ----------- .../IssueControlViewController.swift | 52 +++++++++---------- 4 files changed, 40 insertions(+), 74 deletions(-) delete mode 100644 iOS/issue-tracker/issue-tracker/Common/MarkdownConverter.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 5fd2b4014..2fee4b367 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -50,8 +50,7 @@ E49695672680B0B7001AEB89 /* IssueControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695662680B0B7001AEB89 /* IssueControlViewController.swift */; }; E49695692680B3FB001AEB89 /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695682680B3FB001AEB89 /* Issue.swift */; }; E496956E2681905A001AEB89 /* IssueInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496956D2681905A001AEB89 /* IssueInfoView.swift */; }; - E49695712681D5E5001AEB89 /* SwiftyMarkdown in Frameworks */ = {isa = PBXBuildFile; productRef = E49695702681D5E5001AEB89 /* SwiftyMarkdown */; }; - E49695732681DA29001AEB89 /* MarkdownConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695722681DA29001AEB89 /* MarkdownConverter.swift */; }; + E49695762681E7B7001AEB89 /* Down in Frameworks */ = {isa = PBXBuildFile; productRef = E49695752681E7B7001AEB89 /* Down */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -117,7 +116,6 @@ E49695662680B0B7001AEB89 /* IssueControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueControlViewController.swift; sourceTree = ""; }; E49695682680B3FB001AEB89 /* Issue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Issue.swift; sourceTree = ""; }; E496956D2681905A001AEB89 /* IssueInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueInfoView.swift; sourceTree = ""; }; - E49695722681DA29001AEB89 /* MarkdownConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownConverter.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -142,7 +140,7 @@ buildActionMask = 2147483647; files = ( FAEB30B12670B74000C17BE9 /* Alamofire in Frameworks */, - E49695712681D5E5001AEB89 /* SwiftyMarkdown in Frameworks */, + E49695762681E7B7001AEB89 /* Down in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -223,7 +221,6 @@ E426DAC82671F7760069E77D /* AlertFactory.swift */, E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */, FA431FFC267F61150010EA91 /* String.swift */, - E49695722681DA29001AEB89 /* MarkdownConverter.swift */, ); path = Common; sourceTree = ""; @@ -459,7 +456,7 @@ name = "issue-tracker"; packageProductDependencies = ( FAEB30B02670B74000C17BE9 /* Alamofire */, - E49695702681D5E5001AEB89 /* SwiftyMarkdown */, + E49695752681E7B7001AEB89 /* Down */, ); productName = "issue-tracker"; productReference = E42AD0FA266E52FB0071B436 /* issue-tracker.app */; @@ -490,7 +487,7 @@ mainGroup = E42AD0F1266E52FB0071B436; packageReferences = ( FAEB30AF2670B74000C17BE9 /* XCRemoteSwiftPackageReference "Alamofire" */, - E496956F2681D5E5001AEB89 /* XCRemoteSwiftPackageReference "SwiftyMarkdown" */, + E49695742681E7B7001AEB89 /* XCRemoteSwiftPackageReference "Down" */, ); productRefGroup = E42AD0FB266E52FB0071B436 /* Products */; projectDirPath = ""; @@ -548,7 +545,6 @@ FA733A2E267C3D77005A40C8 /* Milestone.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */, - E49695732681DA29001AEB89 /* MarkdownConverter.swift in Sources */, E426DAC22671B1C60069E77D /* LoginKeyChainManager.swift in Sources */, E43912D426788CC3003CD344 /* ImageBarButton.swift in Sources */, E43912D2267878F4003CD344 /* HexColorCode.swift in Sources */, @@ -781,12 +777,12 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - E496956F2681D5E5001AEB89 /* XCRemoteSwiftPackageReference "SwiftyMarkdown" */ = { + E49695742681E7B7001AEB89 /* XCRemoteSwiftPackageReference "Down" */ = { isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/SimonFairbairn/SwiftyMarkdown.git"; + repositoryURL = "https://github.com/johnxnguyen/Down"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 1.2.3; + minimumVersion = 0.11.0; }; }; FAEB30AF2670B74000C17BE9 /* XCRemoteSwiftPackageReference "Alamofire" */ = { @@ -800,10 +796,10 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - E49695702681D5E5001AEB89 /* SwiftyMarkdown */ = { + E49695752681E7B7001AEB89 /* Down */ = { isa = XCSwiftPackageProductDependency; - package = E496956F2681D5E5001AEB89 /* XCRemoteSwiftPackageReference "SwiftyMarkdown" */; - productName = SwiftyMarkdown; + package = E49695742681E7B7001AEB89 /* XCRemoteSwiftPackageReference "Down" */; + productName = Down; }; FAEB30B02670B74000C17BE9 /* Alamofire */ = { isa = XCSwiftPackageProductDependency; diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/iOS/issue-tracker/issue-tracker.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 484d9ea26..3a1719636 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -11,12 +11,12 @@ } }, { - "package": "SwiftyMarkdown", - "repositoryURL": "https://github.com/SimonFairbairn/SwiftyMarkdown.git", + "package": "Down", + "repositoryURL": "https://github.com/johnxnguyen/Down", "state": { "branch": null, - "revision": "5b0a1e76332a633726f9f9a00b4bbd840166bccf", - "version": "1.2.3" + "revision": "f34b166be1f1db4aa8f573067e901d72f2a6be57", + "version": "0.11.0" } } ] diff --git a/iOS/issue-tracker/issue-tracker/Common/MarkdownConverter.swift b/iOS/issue-tracker/issue-tracker/Common/MarkdownConverter.swift deleted file mode 100644 index 9de1b0d84..000000000 --- a/iOS/issue-tracker/issue-tracker/Common/MarkdownConverter.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// MarkdownConverter.swift -// issue-tracker -// -// Created by Song on 2021/06/22. -// - -import Foundation -import SwiftyMarkdown - -struct MarkdownConverter { - - private var customBullet: String? - var rawText = "" - - init(customBullet: String? = nil) { - self.customBullet = customBullet - } - - func preview(rawText: String) -> NSAttributedString { - let markdown = SwiftyMarkdown(string: rawText) - setCustomBullet(to: markdown) - return markdown.attributedString() - } - - private func setCustomBullet(to markdown: SwiftyMarkdown) { - guard let customBullet = customBullet else { return } - markdown.bullet = customBullet - } -} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift index c27b85a47..39d98bfd1 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift @@ -6,6 +6,7 @@ // import UIKit +import Down final class IssueControlViewController: UIViewController { @@ -100,6 +101,14 @@ final class IssueControlViewController: UIViewController { return textField }() + private lazy var markdownStackView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [bodyTextView, markdownView]) + stackView.axis = .vertical + stackView.distribution = .fillEqually + stackView.translatesAutoresizingMaskIntoConstraints = false + return stackView + }() + private lazy var bodyTextView: UITextView = { let textView = UITextView() textView.text = bodyPlaceholder @@ -111,6 +120,13 @@ final class IssueControlViewController: UIViewController { return textView }() + private lazy var markdownView: DownView = { + let downView = try! DownView(frame: .zero, markdownString: "") + downView.pageZoom = 1.5 + downView.isHidden = true + return downView + }() + private lazy var additionalInfoView: MultipleLineInputStackView = { let viewWidth = view.frame.width let stackViewFrame = CGRect(x: 0, y: 0, width: viewWidth, height: lineHeight * 3) @@ -144,7 +160,6 @@ final class IssueControlViewController: UIViewController { }() private let bodyPlaceholder = "이곳에 내용을 입력하세요" - private var markdownConverter = MarkdownConverter(customBullet: "✔️") private lazy var lineHeight: CGFloat = { return view.frame.height * 0.05 @@ -202,13 +217,13 @@ final class IssueControlViewController: UIViewController { } private func addBodyTextView() { - view.addSubview(bodyTextView) + view.addSubview(markdownStackView) NSLayoutConstraint.activate([ - bodyTextView.topAnchor.constraint(equalTo: titleInputView.bottomAnchor, constant: spacing * 0.7), - bodyTextView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: spacing * 0.8), - bodyTextView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -spacing * 0.8), - bodyTextView.bottomAnchor.constraint(equalTo: additionalInfoView.topAnchor) + markdownStackView.topAnchor.constraint(equalTo: titleInputView.bottomAnchor, constant: spacing * 0.7), + markdownStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: spacing * 0.8), + markdownStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -spacing * 0.8), + markdownStackView.bottomAnchor.constraint(equalTo: additionalInfoView.topAnchor) ]) } @@ -244,30 +259,15 @@ final class IssueControlViewController: UIViewController { } private func previewToMarkDown() { - bodyTextView.attributedText = nil - bodyTextView.text = markdownConverter.rawText - - changeTextViewEditable(to: true) - changeToplainTextView() + markdownView.isHidden = true + bodyTextView.isHidden = false } private func markdownToPreview() { guard let rawText = bodyTextView.text else { return } - let preview = markdownConverter.preview(rawText: rawText) - markdownConverter.rawText = rawText - bodyTextView.text = nil - bodyTextView.attributedText = preview - - changeTextViewEditable(to: false) - } - - private func changeTextViewEditable(to status: Bool) { - bodyTextView.isEditable = status - } - - private func changeToplainTextView() { - bodyTextView.font = .systemFont(ofSize: 17) - bodyTextView.textColor = .black + try? markdownView.update(markdownString: rawText) + markdownView.isHidden = false + bodyTextView.isHidden = true } @objc private func labelInfoTouched(_ sender: UIButton) { From 2080826b6e46e2a6fd41bd9c9645b852860be7f3 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 22 Jun 2021 23:17:07 +0900 Subject: [PATCH 75/91] =?UTF-8?q?fix:=20[#93]=20=EC=BB=AC=EB=9F=AC=20?= =?UTF-8?q?=EC=97=90=EC=85=8B=20=EB=8C=80=EC=86=8C=EB=AC=B8=EC=9E=90=20?= =?UTF-8?q?=EB=AF=B8=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 대소문자 변경이 반영되지 않은 문제 해결 - 다른이름으로 변경 후 다시 대소문자 수정 --- .../Contents.json | 0 .../Contents.json | 0 .../Contents.json | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename iOS/issue-tracker/issue-tracker/Assets.xcassets/{closeMileStoneBG.colorset => CloseMileStoneBG.colorset}/Contents.json (100%) rename iOS/issue-tracker/issue-tracker/Assets.xcassets/{closeMileStoneTint.colorset => CloseMileStoneTint.colorset}/Contents.json (100%) rename iOS/issue-tracker/issue-tracker/Assets.xcassets/{openMileStoneTint.colorset => OpenMileStoneTint.colorset}/Contents.json (100%) diff --git a/iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneBG.colorset/Contents.json b/iOS/issue-tracker/issue-tracker/Assets.xcassets/CloseMileStoneBG.colorset/Contents.json similarity index 100% rename from iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneBG.colorset/Contents.json rename to iOS/issue-tracker/issue-tracker/Assets.xcassets/CloseMileStoneBG.colorset/Contents.json diff --git a/iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneTint.colorset/Contents.json b/iOS/issue-tracker/issue-tracker/Assets.xcassets/CloseMileStoneTint.colorset/Contents.json similarity index 100% rename from iOS/issue-tracker/issue-tracker/Assets.xcassets/closeMileStoneTint.colorset/Contents.json rename to iOS/issue-tracker/issue-tracker/Assets.xcassets/CloseMileStoneTint.colorset/Contents.json diff --git a/iOS/issue-tracker/issue-tracker/Assets.xcassets/openMileStoneTint.colorset/Contents.json b/iOS/issue-tracker/issue-tracker/Assets.xcassets/OpenMileStoneTint.colorset/Contents.json similarity index 100% rename from iOS/issue-tracker/issue-tracker/Assets.xcassets/openMileStoneTint.colorset/Contents.json rename to iOS/issue-tracker/issue-tracker/Assets.xcassets/OpenMileStoneTint.colorset/Contents.json From d527bddd8ff050a3f3764c6056ea8bc421ffe413 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Tue, 22 Jun 2021 23:54:28 +0900 Subject: [PATCH 76/91] =?UTF-8?q?fix=20:[#86]=20=EC=9D=B4=EC=8A=88DTO=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/IssueTableViewDataSource.swift | 8 ++- .../Controller/IssueViewController.swift | 51 ++++++++++++++++-- .../Main/Issue/Model/Issue.swift | 52 ++++++++++++------- .../Main/Issue/View/IssueTableViewCell.swift | 22 +++++++- .../Controller/MileStoneViewController.swift | 40 +++++++------- .../issue-tracker/Network/EndPoint.swift | 2 +- 6 files changed, 130 insertions(+), 45 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift index e1cfc16ec..c759aa971 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift @@ -10,8 +10,14 @@ import UIKit class IssueTableViewDataSource: NSObject, UITableViewDataSource { + private(set) var issues = [Issue]() + + func update(issues: [Issue]) { + self.issues = issues + } + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - 3 + return issues.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift index 0a8be1f44..1f9a5dec9 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift @@ -9,9 +9,6 @@ import UIKit class IssueViewController: UIViewController { - private var issueTableDatasource: IssueTableViewDataSource? - private var issueTableDelegate: IssueTableViewDelegate? - private lazy var issueTableView: UITableView = { let tableView = UITableView() let cellID = IssueTableViewCell.reuseID @@ -21,6 +18,10 @@ class IssueViewController: UIViewController { return tableView }() + private var networkManager: NetworkManagerOperations? + private var issueTableDatasource: IssueTableViewDataSource? + private var issueTableDelegate: IssueTableViewDelegate? + override func viewDidLoad() { super.viewDidLoad() title = "이슈 선택" @@ -28,6 +29,12 @@ class IssueViewController: UIViewController { addTableView() setTableViewSupporters() + setNetworkManager() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + loadIssues() } private func addTableView() { @@ -49,4 +56,42 @@ class IssueViewController: UIViewController { issueTableView.dataSource = issueTableDatasource } + private func setNetworkManager() { + let loginInfo = LoginInfo.shared + guard let jwt = loginInfo.jwt else { return } + let headers = [Header.authorization.key(): jwt.description] + networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) + } + + private func reloadTableView() { + DispatchQueue.main.async { + self.issueTableView.reloadData() + } + } + + private func presentAlert(with errorMessage: String) { + DispatchQueue.main.async { + let alert = AlertFactory.create(body: errorMessage) + self.present(alert, animated: true, completion: nil) + } + } } + +//MARK: - Network Methods +extension IssueViewController { + private func loadIssues() { + let issueListEndpoint = EndPoint.issue.path() + networkManager?.get(endpoint: issueListEndpoint, queryParameters: nil, + completion: { [weak self] (result: Result) in + switch result { + case .success(let result): + guard let issues = result.data else { return } + self?.issueTableDatasource?.update(issues: issues) + self?.reloadTableView() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } +} + diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift index 2c94fb3fd..b1ce47aee 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift @@ -18,7 +18,7 @@ struct IssueDTO: Decodable { } } -class Author: Decodable { +struct Author: Decodable { private(set) var id: Int private(set) var name: String private(set) var imageUrl: String @@ -30,7 +30,7 @@ class Author: Decodable { } } -class Assignee: Decodable { +struct Assignee: Decodable { private(set) var id: Int private(set) var name: String private(set) var imageUrl: String @@ -41,26 +41,38 @@ class Assignee: Decodable { case imageUrl } } -class Issue: Decodable { - private(set) var issueNumber: Int + +struct IssueLabel: Decodable { + private(set) var id: Int + private(set) var name: String + private(set) var colorCode: String + + enum CodingKeys: String, CodingKey { + case id + case name + case colorCode = "color_code" + } +} + +struct IssueMileStone: Decodable { + private(set) var id: Int private(set) var title: String - private(set) var status: Bool - private(set) var author: Author - private(set) var assignees: [Assignee] - private(set) var labels: [Label] - private(set) var milestone: MileStone - private(set) var created_date: String - init(issueNumber: Int, title: String, status: Bool, author: Author, assignees: [Assignee], labels: [Label], milestone: MileStone, created_date: String) { - self.issueNumber = issueNumber - self.title = title - self.status = status - self.author = author - self.assignees = assignees - self.labels = labels - self.milestone = milestone - self.created_date = created_date + enum CodingKeys: String, CodingKey { + case id + case title } +} + +struct Issue: Decodable { + private(set) var issueNumber: Int + private(set) var title: String? + private(set) var status: Bool + private(set) var author: Author + private(set) var assignees: [Assignee]? + private(set) var labels: [IssueLabel]? + private(set) var milestone: IssueMileStone? + private(set) var createdDate: String enum CodingKeys: String, CodingKey { case issueNumber @@ -70,6 +82,6 @@ class Issue: Decodable { case assignees case labels case milestone - case created_date = "createdDate" + case createdDate = "created_date" } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift index 9931ddd39..151d1c09d 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift @@ -37,6 +37,7 @@ class IssueTableViewCell: UITableViewCell { private lazy var mileStoneLabel: UILabel = { let label = UILabel() + //추후에 지울 것들. let attributedString = NSMutableAttributedString(string: "") let imageAttachment = NSTextAttachment() let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : UIColor.systemGray] @@ -91,7 +92,7 @@ class IssueTableViewCell: UITableViewCell { } //여기서 인자 값으로 GET으로 라벨의 갯수와 라벨 배열을 가져와야 할 것같다. -// func addlabelsStackView(_ labels: [Label]) +// func addlabelsStackView(_ labels: [Label]){ func addlabelsStackView() { issueStackView.addArrangedSubview(labelsStackView) @@ -147,4 +148,23 @@ class IssueTableViewCell: UITableViewCell { } + func configure(title: String, mileStoneName: String, labels: [Label]) { + titleLabel.text = title + mileStoneTitleConfigure(mileStoneName: mileStoneName) + } + + private func mileStoneTitleConfigure(mileStoneName: String) { + let mileStoneText = mileStoneName != "" ? mileStoneName :"마일스톤 이름" + let attributedString = NSMutableAttributedString(string: "") + let imageAttachment = NSTextAttachment() + imageAttachment.image = UIImage(systemName: "signpost.right") + + let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 13), NSAttributedString.Key.foregroundColor : Colors.description] + let dateString = NSMutableAttributedString(string:mileStoneText, attributes:attrs) + + attributedString.append(NSAttributedString(attachment: imageAttachment)) + attributedString.append(dateString) + mileStoneLabel.attributedText = attributedString + } + } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift index 6fd59838c..a2519fcf5 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift @@ -52,7 +52,7 @@ class MileStoneViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - loadData() + loadMileStones() } private func addNavigationButton() { @@ -84,21 +84,7 @@ class MileStoneViewController: UIViewController { let headers = [Header.authorization.key(): jwt.description] networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) } - - func loadData() { - let mileStoneListEndpoint = - EndPoint.milestone.path() - networkManager?.get(endpoint: mileStoneListEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in - switch result { - case .success(let result): - guard let mileStone = result.data else { return } - self?.mileStoneTableDatasource?.update(milestones: mileStone) - self?.reloadTableView() - case .failure(let error): - self?.presentAlert(with: error.description) - } - }) - } + private func presentAlert(with errorMessage: String) { DispatchQueue.main.async { let alert = AlertFactory.create(body: errorMessage) @@ -138,12 +124,28 @@ class MileStoneViewController: UIViewController { //MARK: - Network Methods extension MileStoneViewController { + + private func loadMileStones() { + let mileStoneListEndpoint = + EndPoint.milestone.path() + networkManager?.get(endpoint: mileStoneListEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in + switch result { + case .success(let result): + guard let mileStone = result.data else { return } + self?.mileStoneTableDatasource?.update(milestones: mileStone) + self?.reloadTableView() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } + private func deleteMileStone(for id: Int) { let deleteMileStoneEndpoint = EndPoint.milestone.path(with: id) networkManager?.delete(endpoint: deleteMileStoneEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in switch result { case .success(_): - self?.loadData() + self?.loadMileStones() case .failure(let error): self?.presentAlert(with: error.description) } @@ -157,7 +159,7 @@ extension MileStoneViewController { networkManager?.post(endpoint: newMileStoneEndpoint, requestBody: requestBody, completion: { [weak self] result in switch result { case .success(_): - self?.loadData() + self?.loadMileStones() case .failure(let error): self?.presentAlert(with: error.description) } @@ -172,7 +174,7 @@ extension MileStoneViewController { networkManager?.put(endpoint: editMileStoneEndpoint, requestBody: requestBody, completion: { [weak self] result in switch result { case .success(_): - self?.loadData() + self?.loadMileStones() case .failure(let error): self?.presentAlert(with: error.description) } diff --git a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift index 6fa755f85..3e434906a 100644 --- a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift +++ b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift @@ -21,7 +21,7 @@ enum EndPoint { case .OAuth: return "/login/ios" case .issue: - return "/login/issues" + return "/issues" case .label: return "/labels" case .milestone: From e2a73f24ce1a8dfea29e6bf0670ccfdce9f800e9 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 23 Jun 2021 10:53:32 +0900 Subject: [PATCH 77/91] =?UTF-8?q?refactor:=20UITableCell=20Identifier?= =?UTF-8?q?=E1=84=85=E1=85=B3=E1=86=AF=20class=20extension=E1=84=8B?= =?UTF-8?q?=E1=85=B3=E1=84=85=E1=85=A9=20=E1=84=8C=E1=85=A5=E1=86=BC?= =?UTF-8?q?=E1=84=8B=E1=85=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 8 ++++++++ .../Common/UITableCellExtension.swift | 15 +++++++++++++++ .../Main/Label/View/LabelTableViewCell.swift | 4 ---- .../Milestone/View/MileStoneTableViewCell.swift | 4 ---- 4 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Common/UITableCellExtension.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 2fee4b367..b9a2c7fa0 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -51,6 +51,8 @@ E49695692680B3FB001AEB89 /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695682680B3FB001AEB89 /* Issue.swift */; }; E496956E2681905A001AEB89 /* IssueInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496956D2681905A001AEB89 /* IssueInfoView.swift */; }; E49695762681E7B7001AEB89 /* Down in Frameworks */ = {isa = PBXBuildFile; productRef = E49695752681E7B7001AEB89 /* Down */; }; + E49695782682C4B0001AEB89 /* AdditionalInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */; }; + E496957A2682CB33001AEB89 /* UITableCellExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695792682CB33001AEB89 /* UITableCellExtension.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -116,6 +118,8 @@ E49695662680B0B7001AEB89 /* IssueControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueControlViewController.swift; sourceTree = ""; }; E49695682680B3FB001AEB89 /* Issue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Issue.swift; sourceTree = ""; }; E496956D2681905A001AEB89 /* IssueInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueInfoView.swift; sourceTree = ""; }; + E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdditionalInfoViewController.swift; sourceTree = ""; }; + E49695792682CB33001AEB89 /* UITableCellExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableCellExtension.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -221,6 +225,7 @@ E426DAC82671F7760069E77D /* AlertFactory.swift */, E43912F3267CAA8D003CD344 /* UITextFieldExtension.swift */, FA431FFC267F61150010EA91 /* String.swift */, + E49695792682CB33001AEB89 /* UITableCellExtension.swift */, ); path = Common; sourceTree = ""; @@ -359,6 +364,7 @@ isa = PBXGroup; children = ( E49695662680B0B7001AEB89 /* IssueControlViewController.swift */, + E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */, ); path = Controller; sourceTree = ""; @@ -542,6 +548,7 @@ E43912F6267CAE01003CD344 /* TopMenuView.swift in Sources */, E42AD122267093590071B436 /* MileStoneViewController.swift in Sources */, E496956E2681905A001AEB89 /* IssueInfoView.swift in Sources */, + E496957A2682CB33001AEB89 /* UITableCellExtension.swift in Sources */, FA733A2E267C3D77005A40C8 /* Milestone.swift in Sources */, E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */, E43912EC267B1A4E003CD344 /* LoginInfoDTO.swift in Sources */, @@ -557,6 +564,7 @@ E43912D826789A83003CD344 /* EndPoint.swift in Sources */, E426DABE2670EC830069E77D /* SocialLoginManagerDelegate.swift in Sources */, FA733A30267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift in Sources */, + E49695782682C4B0001AEB89 /* AdditionalInfoViewController.swift in Sources */, E42AD0FE266E52FB0071B436 /* AppDelegate.swift in Sources */, E43912EE267C3C0E003CD344 /* CellAction.swift in Sources */, E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Common/UITableCellExtension.swift b/iOS/issue-tracker/issue-tracker/Common/UITableCellExtension.swift new file mode 100644 index 000000000..12288e24c --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Common/UITableCellExtension.swift @@ -0,0 +1,15 @@ +// +// UITableCellExtension.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import UIKit + +extension UITableViewCell { + static var reuseID: String { + return String(describing: self) + } +} + diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift index bbf3bf7a1..6708d3478 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/View/LabelTableViewCell.swift @@ -26,10 +26,6 @@ final class LabelTableViewCell: UITableViewCell { private let placeholder = "No description provided" - static var reuseID: String { - return String(describing: self) - } - required init?(coder: NSCoder) { super.init(coder: coder) setViews() diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift index 389abff10..484d74e21 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/View/MileStoneTableViewCell.swift @@ -73,10 +73,6 @@ class MileStoneTableViewCell: UITableViewCell { return milestoneLabelView }() - static var reuseID: String { - return String(describing: self) - } - required init?(coder: NSCoder) { super.init(coder: coder) setViews() From 2b67688353c052791611d6eb3251867a5baa6a9f Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 23 Jun 2021 11:28:14 +0900 Subject: [PATCH 78/91] =?UTF-8?q?refactor:=20=E1=84=8C=E1=85=A6=E1=84=82?= =?UTF-8?q?=E1=85=A6=E1=84=85=E1=85=B5=E1=86=A8=E1=84=92=E1=85=A1=E1=86=AB?= =?UTF-8?q?=20=E1=84=80=E1=85=A9=E1=86=BC=E1=84=90=E1=85=A9=E1=86=BC=20DTO?= =?UTF-8?q?=20=E1=84=89=E1=85=A2=E1=86=BC=E1=84=89=E1=85=A5=E1=86=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 4 ++++ .../issue-tracker/Main/Common/CommonDTO.swift | 13 +++++++++++++ .../Main/Label/Controller/LabelViewController.swift | 2 +- .../issue-tracker/Main/Label/Model/Label.swift | 12 +----------- .../Controller/MileStoneViewController.swift | 2 +- .../Main/Milestone/Model/Milestone.swift | 12 ------------ 6 files changed, 20 insertions(+), 25 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Common/CommonDTO.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index b9a2c7fa0..af844d545 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -53,6 +53,7 @@ E49695762681E7B7001AEB89 /* Down in Frameworks */ = {isa = PBXBuildFile; productRef = E49695752681E7B7001AEB89 /* Down */; }; E49695782682C4B0001AEB89 /* AdditionalInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */; }; E496957A2682CB33001AEB89 /* UITableCellExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695792682CB33001AEB89 /* UITableCellExtension.swift */; }; + E496957C2682D2CE001AEB89 /* CommonDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496957B2682D2CE001AEB89 /* CommonDTO.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -120,6 +121,7 @@ E496956D2681905A001AEB89 /* IssueInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueInfoView.swift; sourceTree = ""; }; E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdditionalInfoViewController.swift; sourceTree = ""; }; E49695792682CB33001AEB89 /* UITableCellExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableCellExtension.swift; sourceTree = ""; }; + E496957B2682D2CE001AEB89 /* CommonDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonDTO.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -315,6 +317,7 @@ E43912C926776DA0003CD344 /* View */, E43912ED267C3C0E003CD344 /* CellAction.swift */, FAFD11B0268078F80064AED4 /* CommonTableDelegate.swift */, + E496957B2682D2CE001AEB89 /* CommonDTO.swift */, ); path = Common; sourceTree = ""; @@ -524,6 +527,7 @@ files = ( FAB2C36A26789D41009F879C /* MileStoneTableViewCell.swift in Sources */, E426DAD126730DC50069E77D /* OAuthResponseDTO.swift in Sources */, + E496957C2682D2CE001AEB89 /* CommonDTO.swift in Sources */, FAFD11B1268078F80064AED4 /* CommonTableDelegate.swift in Sources */, E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */, FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Common/CommonDTO.swift b/iOS/issue-tracker/issue-tracker/Main/Common/CommonDTO.swift new file mode 100644 index 000000000..d636cf750 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Common/CommonDTO.swift @@ -0,0 +1,13 @@ +// +// CommonDTO.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import Foundation + +struct CommonDTO: Decodable { + let data: [T]? + let error: String? +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index e3a19ca78..46e25fc99 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -136,7 +136,7 @@ extension LabelViewController { private func loadLabels() { let labelListEndpoint = EndPoint.label.path() networkManager?.get(endpoint: labelListEndpoint, queryParameters: nil, - completion: { [weak self] (result: Result) in + completion: { [weak self] (result: Result, NetworkError>) in switch result { case .success(let result): guard let labels = result.data else { return } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift index a99a381b0..ed2080e05 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift @@ -7,17 +7,7 @@ import Foundation -struct LabelDTO: Decodable { - let data: [Label]? - let message: String? - - enum CodingKeys: String, CodingKey { - case data - case message = "msg" - } -} - -class Label: Decodable { +struct Label: Decodable { private(set) var id: Int private(set) var title: String private(set) var body: String diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift index b966be9a7..7b818803d 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Controller/MileStoneViewController.swift @@ -88,7 +88,7 @@ class MileStoneViewController: UIViewController { func loadData() { let mileStoneListEndpoint = EndPoint.milestone.path() - networkManager?.get(endpoint: mileStoneListEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in + networkManager?.get(endpoint: mileStoneListEndpoint, queryParameters: nil, completion: { [weak self] (result: Result, NetworkError>) in switch result { case .success(let result): guard let mileStone = result.data else { return } diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift index fdd0483f0..8016d9f7b 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift @@ -7,17 +7,6 @@ import Foundation - -struct MileStoneDTO: Decodable { - let data: [MileStone]? - let message: String? - - enum CodingKeys: String, CodingKey { - case data - case message = "msg" - } -} - struct MileStone: Decodable { let id: Int let title: String @@ -30,5 +19,4 @@ struct MileStone: Decodable { case description case dueDate = "due_date" } - } From 6dcc4f81ea58cf641bef4ba76bc353a5d14e56f3 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Wed, 23 Jun 2021 11:56:37 +0900 Subject: [PATCH 79/91] =?UTF-8?q?feat=20:[#86]=20=EC=9D=B4=EC=8A=88=20GET,?= =?UTF-8?q?=20=ED=99=94=EB=A9=B4=20=EB=B3=B4=EC=97=AC=EC=A3=BC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/IssueTableViewDataSource.swift | 2 + .../Main/Issue/View/IssueTableViewCell.swift | 68 ++++++------------- .../Main/Milestone/Model/Milestone.swift | 1 - 3 files changed, 23 insertions(+), 48 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift index c759aa971..a0d698cfd 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift @@ -23,6 +23,8 @@ class IssueTableViewDataSource: NSObject, UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cellID = IssueTableViewCell.reuseID let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? IssueTableViewCell ?? IssueTableViewCell() + let issue = issues[indexPath.row] + cell.configure(title: issue.title ?? "", mileStoneName: issue.milestone?.title ?? "", labels: issue.labels ?? []) return cell } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift index 151d1c09d..facfa5b3e 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift @@ -70,7 +70,7 @@ class IssueTableViewCell: UITableViewCell { addIssueStackView() addIssueTitleView() addMileStoneLabel() - addlabelsStackView() +// addlabelsStackView() } func addIssueStackView() { @@ -91,9 +91,13 @@ class IssueTableViewCell: UITableViewCell { issueStackView.addArrangedSubview(mileStoneLabel) } - //여기서 인자 값으로 GET으로 라벨의 갯수와 라벨 배열을 가져와야 할 것같다. -// func addlabelsStackView(_ labels: [Label]){ - func addlabelsStackView() { + func clearLabelStackView() { + labelsStackView.subviews.forEach { $0.removeFromSuperview() } + } + + func addlabelsStackView(_ labels: [IssueLabel]) { + //Cell의 재사용으로 계속 이 함수가 불린다. 계속 라벨이 추가되는 이슈를 막기 위해서 불릴 때마다 reset하기 + issueStackView.addArrangedSubview(labelsStackView) labelsStackView.spacing = 4 @@ -103,54 +107,24 @@ class IssueTableViewCell: UITableViewCell { labelsStackView.trailingAnchor.constraint(equalTo: issueStackView.trailingAnchor) ]) - - let labelView1 = LabelView() - let colorText1 = "#34e6b1" - let hex1 = HexColorCode(from: colorText1) - let titleText1 = "feat" - labelView1.configure(with: hex1, titleText1) - labelView1.translatesAutoresizingMaskIntoConstraints = false - - let labelView2 = LabelView() - let colorText2 = "#1af6c5" - let hex2 = HexColorCode(from: colorText2) - let titleText2 = "하이하이하이하이" - labelView2.configure(with: hex2, titleText2) - labelView2.translatesAutoresizingMaskIntoConstraints = false - - let labelView3 = LabelView() - let colorText3 = "#3af6c5" - let hex3 = HexColorCode(from: colorText3) - let titleText3 = "iOSafafa" - labelView3.configure(with: hex3, titleText3) - labelView3.translatesAutoresizingMaskIntoConstraints = false - - let labelView4 = LabelView() - let colorText4 = "#fbfbcc" - let hex4 = HexColorCode(from: colorText4) - let titleText4 = "abdfsfwasdfsafafasdfas" - labelView4.configure(with: hex4, titleText4) - labelView4.translatesAutoresizingMaskIntoConstraints = false - - let labelView5 = LabelView() - let colorText5 = "#fbfbcc" - let hex5 = HexColorCode(from: colorText5) - let titleText5 = "abdfsfwasdfsafafasdfas" - labelView5.configure(with: hex5, titleText5) - labelView5.translatesAutoresizingMaskIntoConstraints = false - - - labelsStackView.addArrangedSubview(labelView1) - labelsStackView.addArrangedSubview(labelView2) - labelsStackView.addArrangedSubview(labelView3) -// labelsStackView.addArrangedSubview(labelView4) -// labelsStackView.addArrangedSubview(labelView5) + labels.forEach { label in + let labelView = LabelView() + let colorText = label.colorCode + let hex = HexColorCode(from: colorText) + let titleText = label.name + labelView.configure(with: hex, titleText) + labelView.translatesAutoresizingMaskIntoConstraints = false + labelsStackView.addArrangedSubview(labelView) + } + } - func configure(title: String, mileStoneName: String, labels: [Label]) { + func configure(title: String, mileStoneName: String, labels: [IssueLabel]) { titleLabel.text = title mileStoneTitleConfigure(mileStoneName: mileStoneName) + clearLabelStackView() + addlabelsStackView(labels) } private func mileStoneTitleConfigure(mileStoneName: String) { diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift index fdd0483f0..9f68295a9 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift @@ -7,7 +7,6 @@ import Foundation - struct MileStoneDTO: Decodable { let data: [MileStone]? let message: String? From b9b2088c17fa227f273d080315d48155debdfb14 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Wed, 23 Jun 2021 13:01:41 +0900 Subject: [PATCH 80/91] =?UTF-8?q?feat=20:[#86]=20=EC=9D=B4=EC=8A=88=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B2=84=ED=8A=BC=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AddIssueBtn.colorset/Contents.json | 38 +++++++++++++++ .../Controller/IssueViewController.swift | 47 ++++++++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 iOS/issue-tracker/issue-tracker/Assets.xcassets/AddIssueBtn.colorset/Contents.json diff --git a/iOS/issue-tracker/issue-tracker/Assets.xcassets/AddIssueBtn.colorset/Contents.json b/iOS/issue-tracker/issue-tracker/Assets.xcassets/AddIssueBtn.colorset/Contents.json new file mode 100644 index 000000000..805e83152 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Assets.xcassets/AddIssueBtn.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.478", + "red" : "0.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.478", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift index 1f9a5dec9..aeb774d38 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift @@ -18,6 +18,26 @@ class IssueViewController: UIViewController { return tableView }() + private lazy var addNewIssueButton: UIButton = { + let button = UIButton() + button.backgroundColor = Colors.mainGrape + button.addTarget(self, action: #selector(addNewIssue), for: .touchUpInside) + button.layer.masksToBounds = true + button.layer.cornerRadius = 32 + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + private lazy var plusImageView: UIImageView = { + let image = UIImage(systemName: "plus") + let resizeImg = image?.resizedImage(size: CGSize(width: 32, height: 34))?.withRenderingMode(.alwaysTemplate) + let imageView = UIImageView(image: resizeImg) + imageView.tintColor = UIColor.white + imageView.backgroundColor = Colors.mainGrape + imageView.translatesAutoresizingMaskIntoConstraints = false + return imageView + }() + private var networkManager: NetworkManagerOperations? private var issueTableDatasource: IssueTableViewDataSource? private var issueTableDelegate: IssueTableViewDelegate? @@ -28,13 +48,14 @@ class IssueViewController: UIViewController { view.backgroundColor = UIColor.white addTableView() + addButton() setTableViewSupporters() setNetworkManager() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - loadIssues() + loadIssues() } private func addTableView() { @@ -48,6 +69,25 @@ class IssueViewController: UIViewController { ]) } + private func addButton() { + view.addSubview(addNewIssueButton) + + NSLayoutConstraint.activate([ + addNewIssueButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16), + addNewIssueButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -90), + addNewIssueButton.widthAnchor.constraint(equalToConstant: 64), + addNewIssueButton.heightAnchor.constraint(equalToConstant: 64) + ]) + + + addNewIssueButton.addSubview(plusImageView) + + NSLayoutConstraint.activate([ + plusImageView.centerXAnchor.constraint(equalTo: addNewIssueButton.centerXAnchor), + plusImageView.centerYAnchor.constraint(equalTo: addNewIssueButton.centerYAnchor) + ]) + } + private func setTableViewSupporters() { issueTableDatasource = IssueTableViewDataSource() issueTableDelegate = IssueTableViewDelegate() @@ -56,6 +96,7 @@ class IssueViewController: UIViewController { issueTableView.dataSource = issueTableDatasource } + private func setNetworkManager() { let loginInfo = LoginInfo.shared guard let jwt = loginInfo.jwt else { return } @@ -75,6 +116,10 @@ class IssueViewController: UIViewController { self.present(alert, animated: true, completion: nil) } } + + @objc func addNewIssue(_ sender: UIButton) { + print("야호~") + } } //MARK: - Network Methods From 25bfd14ec2856f6c594bd255f22bc0cf04d6ee07 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Wed, 23 Jun 2021 15:00:31 +0900 Subject: [PATCH 81/91] =?UTF-8?q?feat=20:[#86]=20=EC=9D=B4=EC=8A=88=20?= =?UTF-8?q?=EC=85=80=20=EC=8A=A4=EC=99=80=EC=9D=B4=ED=94=84=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/IssueViewController.swift | 28 ++++++++++++++++++- .../Main/Issue/Model/Issue.swift | 3 +- .../Main/Issue/View/IssueTableViewCell.swift | 2 -- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift index aeb774d38..062637b8b 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift @@ -90,7 +90,7 @@ class IssueViewController: UIViewController { private func setTableViewSupporters() { issueTableDatasource = IssueTableViewDataSource() - issueTableDelegate = IssueTableViewDelegate() + issueTableDelegate = IssueTableViewDelegate(cellActionHandler: swipeActionHandler, cellHeight: 198) issueTableView.delegate = issueTableDelegate issueTableView.dataSource = issueTableDatasource @@ -110,6 +110,20 @@ class IssueViewController: UIViewController { } } + private func swipeActionHandler(_ index: Int, _ action: CellAction) { + guard let targetIssue = issueTableDatasource?.issues[index] else { return } + + switch action { + case .delete: + deleteIssue(for: targetIssue.issueNumber) + case .close: + print("close 되어랏") +// presentEditLabelViewController(for: targetLabel) + default: + assert(false) + } + } + private func presentAlert(with errorMessage: String) { DispatchQueue.main.async { let alert = AlertFactory.create(body: errorMessage) @@ -138,5 +152,17 @@ extension IssueViewController { } }) } + + private func deleteIssue(for id: Int) { + let deleteIssueEndpoint = EndPoint.issue.path(with: id) + networkManager?.delete(endpoint: deleteIssueEndpoint, queryParameters: nil, completion: { [weak self] (result: Result) in + switch result { + case .success(_): + self?.loadIssues() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) + } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift index b1ce47aee..1dba8c83b 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift @@ -71,7 +71,8 @@ struct Issue: Decodable { private(set) var author: Author private(set) var assignees: [Assignee]? private(set) var labels: [IssueLabel]? - private(set) var milestone: IssueMileStone? +// private(set) var milestone: IssueMileStone? + private(set) var milestone: MileStone? private(set) var createdDate: String enum CodingKeys: String, CodingKey { diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift index facfa5b3e..b4c13b560 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift @@ -116,8 +116,6 @@ class IssueTableViewCell: UITableViewCell { labelView.translatesAutoresizingMaskIntoConstraints = false labelsStackView.addArrangedSubview(labelView) } - - } func configure(title: String, mileStoneName: String, labels: [IssueLabel]) { From 103812f589b0e101d45863ba625ce4f21a6ad7f8 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 23 Jun 2021 15:30:01 +0900 Subject: [PATCH 82/91] =?UTF-8?q?feat:=20[#82]=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=84=A0=ED=83=9D=20=ED=99=94=EB=A9=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 레이블 선택 모달 구성 - 마일스톤, 담당자 선택 공통 인터페이스 구축 --- .../issue-tracker.xcodeproj/project.pbxproj | 28 +++ .../AdditionalInfoViewController.swift | 207 ++++++++++++++++++ .../CellSelectionTableDelegate.swift | 32 +++ .../IssueControlViewController.swift | 25 ++- .../Protocol/SimpleInfoTableDatasource.swift | 14 ++ .../Protocol/SimpleInfoTableDelegate.swift | 18 ++ .../SimpleLabelTableDatasource.swift | 46 ++++ .../Issue/View/SimpleLabelTableViewCell.swift | 52 +++++ .../Main/Label/Model/Label.swift | 19 +- 9 files changed, 430 insertions(+), 11 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/AdditionalInfoViewController.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/CellSelectionTableDelegate.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDatasource.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDelegate.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleLabelTableDatasource.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleLabelTableViewCell.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index af844d545..07034f6fd 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -54,6 +54,11 @@ E49695782682C4B0001AEB89 /* AdditionalInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */; }; E496957A2682CB33001AEB89 /* UITableCellExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695792682CB33001AEB89 /* UITableCellExtension.swift */; }; E496957C2682D2CE001AEB89 /* CommonDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496957B2682D2CE001AEB89 /* CommonDTO.swift */; }; + E496957E2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496957D2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift */; }; + E49695822682DCEC001AEB89 /* SimpleInfoTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695812682DCEC001AEB89 /* SimpleInfoTableDatasource.swift */; }; + E49695842682DDAE001AEB89 /* SimpleLabelTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695832682DDAE001AEB89 /* SimpleLabelTableDatasource.swift */; }; + E49695862682FD95001AEB89 /* SimpleInfoTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695852682FD95001AEB89 /* SimpleInfoTableDelegate.swift */; }; + E49695882682FDC9001AEB89 /* CellSelectionTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -122,6 +127,11 @@ E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdditionalInfoViewController.swift; sourceTree = ""; }; E49695792682CB33001AEB89 /* UITableCellExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableCellExtension.swift; sourceTree = ""; }; E496957B2682D2CE001AEB89 /* CommonDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonDTO.swift; sourceTree = ""; }; + E496957D2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleLabelTableViewCell.swift; sourceTree = ""; }; + E49695812682DCEC001AEB89 /* SimpleInfoTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleInfoTableDatasource.swift; sourceTree = ""; }; + E49695832682DDAE001AEB89 /* SimpleLabelTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleLabelTableDatasource.swift; sourceTree = ""; }; + E49695852682FD95001AEB89 /* SimpleInfoTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleInfoTableDelegate.swift; sourceTree = ""; }; + E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellSelectionTableDelegate.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -368,6 +378,9 @@ children = ( E49695662680B0B7001AEB89 /* IssueControlViewController.swift */, E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */, + E496958A26830B81001AEB89 /* Protocol */, + E49695832682DDAE001AEB89 /* SimpleLabelTableDatasource.swift */, + E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */, ); path = Controller; sourceTree = ""; @@ -384,10 +397,20 @@ isa = PBXGroup; children = ( E496956D2681905A001AEB89 /* IssueInfoView.swift */, + E496957D2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift */, ); path = View; sourceTree = ""; }; + E496958A26830B81001AEB89 /* Protocol */ = { + isa = PBXGroup; + children = ( + E49695812682DCEC001AEB89 /* SimpleInfoTableDatasource.swift */, + E49695852682FD95001AEB89 /* SimpleInfoTableDelegate.swift */, + ); + path = Protocol; + sourceTree = ""; + }; FA8840422671F9B000ECCF7A /* Apple */ = { isa = PBXGroup; children = ( @@ -528,6 +551,7 @@ FAB2C36A26789D41009F879C /* MileStoneTableViewCell.swift in Sources */, E426DAD126730DC50069E77D /* OAuthResponseDTO.swift in Sources */, E496957C2682D2CE001AEB89 /* CommonDTO.swift in Sources */, + E49695822682DCEC001AEB89 /* SimpleInfoTableDatasource.swift in Sources */, FAFD11B1268078F80064AED4 /* CommonTableDelegate.swift in Sources */, E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */, FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */, @@ -566,23 +590,27 @@ E426DAC42671D95D0069E77D /* LoginService.swift in Sources */, E42AD120267093430071B436 /* LabelViewController.swift in Sources */, E43912D826789A83003CD344 /* EndPoint.swift in Sources */, + E49695842682DDAE001AEB89 /* SimpleLabelTableDatasource.swift in Sources */, E426DABE2670EC830069E77D /* SocialLoginManagerDelegate.swift in Sources */, FA733A30267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift in Sources */, E49695782682C4B0001AEB89 /* AdditionalInfoViewController.swift in Sources */, E42AD0FE266E52FB0071B436 /* AppDelegate.swift in Sources */, E43912EE267C3C0E003CD344 /* CellAction.swift in Sources */, + E49695862682FD95001AEB89 /* SimpleInfoTableDelegate.swift in Sources */, E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */, FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */, E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */, E49695692680B3FB001AEB89 /* Issue.swift in Sources */, E42AD11E267093320071B436 /* IssueViewController.swift in Sources */, E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */, + E49695882682FDC9001AEB89 /* CellSelectionTableDelegate.swift in Sources */, E43912DC2678A737003CD344 /* JWT.swift in Sources */, E426DABA2670EC2D0069E77D /* AppleAuthorizationManager.swift in Sources */, FAEB30AE266F6A7800C17BE9 /* UIImageExtension.swift in Sources */, E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */, E42AD100266E52FB0071B436 /* SceneDelegate.swift in Sources */, E43912DA26789E16003CD344 /* Label.swift in Sources */, + E496957E2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift in Sources */, E426DAC92671F7760069E77D /* AlertFactory.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/AdditionalInfoViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/AdditionalInfoViewController.swift new file mode 100644 index 000000000..470f21b94 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/AdditionalInfoViewController.swift @@ -0,0 +1,207 @@ +// +// AdditionalInfoViewController.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import UIKit + +final class AdditionalInfoViewController: UIViewController { + + private lazy var topMenuView: TopMenuView = { + let topMenuView = TopMenuView() + topMenuView.configure(withTitle: sceneTitle, rightButton: saveButton, leftButton: cancelButton) + topMenuView.translatesAutoresizingMaskIntoConstraints = false + return topMenuView + }() + + private lazy var saveButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "", "저장") + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(saveButtonTouched), for: .touchUpInside) + changeSaveButtonEnableStatus() + return button + }() + + private lazy var cancelButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "chevron.backward", "취소") + button.moveImageToLeft() + button.translatesAutoresizingMaskIntoConstraints = false + button.addTarget(self, action: #selector(cancelButtonTouched), for: .touchUpInside) + return button + }() + + private lazy var infoListTable: UITableView = { + let tableView = UITableView() + let cellID = InfoCell.reuseID + tableView.register(InfoCell.self, forCellReuseIdentifier: cellID) + tableView.tintColor = Colors.mainGrape + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.dataSource = tableDatasource + return tableView + }() + + private lazy var singleLineHeight: CGFloat = { + return view.frame.height * 0.05 + }() + + private lazy var spacing: CGFloat = { + return singleLineHeight * 0.5 + }() + + private var sceneTitle: String? + private var infoCell: InfoCell? + private var tableDatasource: SimpleInfoTableDatasource? + private var tableDelegate: SimpleInfoTableDelegate? + + private var selectedInfo = [Info]() + private var saveOperation: (([Info]) -> Void)? + private var endpoint: EndPoint? + private var networkManager: NetworkManagerOperations? + + override func viewDidLoad() { + super.viewDidLoad() + configureView() + loadData() + } + + private func configureView() { + view.backgroundColor = .white + + addTopMenu() + addTableView() + } + + private func addTopMenu() { + view.addSubview(topMenuView) + + NSLayoutConstraint.activate([ + topMenuView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + topMenuView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + topMenuView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: spacing), + topMenuView.heightAnchor.constraint(equalToConstant: singleLineHeight) + ]) + } + + private func addTableView() { + view.addSubview(infoListTable) + + NSLayoutConstraint.activate([ + infoListTable.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + infoListTable.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + infoListTable.topAnchor.constraint(equalTo: topMenuView.bottomAnchor, constant: spacing), + infoListTable.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } + + func configure(withTitle sceneTitle: String, preSelectedInfos: [Info], tableDatasource: SimpleInfoTableDatasource, isMultiselectionAllowed: Bool, endpoint: EndPoint) { + self.sceneTitle = sceneTitle + self.selectedInfo = preSelectedInfos + self.tableDatasource = tableDatasource + self.endpoint = endpoint + + DispatchQueue.main.async { + self.infoListTable.allowsMultipleSelection = isMultiselectionAllowed + } + + setUpTableViewSupporter() + setUpNetworkManager() + } + + private func setUpTableViewSupporter() { + self.tableDelegate = CellSelectionTableDelegate() + tableDelegate?.setCellSelectionHandler(updateSelection) + infoListTable.delegate = tableDelegate + } + + private func updateSelection(index: Int, selectionStatus: CellSelection) { + guard let tableDatasource = tableDatasource, + let targetInfo = tableDatasource.info(for: index) as? Info else { return } + + switch selectionStatus { + case .selected: + selectedInfo.append(targetInfo) + case .deSelected: + var targetIndex: Int? + selectedInfo.enumerated().forEach { (index, info) in + if info.identifier() == targetInfo.identifier() { + targetIndex = index + } + } + guard let targetIndex = targetIndex else { return } + selectedInfo.remove(at: targetIndex) + } + changeSaveButtonEnableStatus() + } + + private func setUpNetworkManager() { + let loginInfo = LoginInfo.shared + guard let jwt = loginInfo.jwt else { return } + let headers = [Header.authorization.key(): jwt.description] + let networkManager = NetworkManager(baseAddress: EndPoint.baseAddress, headers: headers) + self.networkManager = networkManager + } + + func setSaveOperation(_ operation: @escaping ([Info]) -> Void) { + self.saveOperation = operation + } + + private func changeSaveButtonEnableStatus() { + DispatchQueue.main.async { + self.saveButton.isEnabled = !self.selectedInfo.isEmpty + } + } + + private func reloadTableView() { + DispatchQueue.main.async { + self.infoListTable.reloadData() + self.setUpCurrentLabelInfo() + } + } + + private func setUpCurrentLabelInfo() { + guard let tableDatasource = tableDatasource else { return } + let selectedIndexs = selectedInfo.compactMap{ tableDatasource.index(for: $0) } + selectedIndexs.forEach { selectedIndex in + let indexPath = IndexPath(row: selectedIndex, section: 0) + + DispatchQueue.main.async { + self.infoListTable.selectRow(at: indexPath, animated: false, scrollPosition: .top) + } + } + } + + @objc private func saveButtonTouched(_ sender: UIButton) { + guard let saveOperation = saveOperation else { return } + saveOperation(selectedInfo) + dismiss(animated: true, completion: nil) + } + + @objc private func cancelButtonTouched(_ sender: UIButton) { + dismiss(animated: true, completion: nil) + } +} + +extension AdditionalInfoViewController { + func loadData() { + guard let networkManager = networkManager, + let endpoint = endpoint, + let tableDatasource = tableDatasource else { return } + + networkManager.get(endpoint: endpoint.path(), queryParameters: nil) { [weak self] (result: Result, NetworkError>) in + switch result { + case .success(let result): + guard let infos = result.data else { return } + tableDatasource.update(with: infos) + self?.reloadTableView() + case .failure(let error): + print("\(error)") + //self?.presentAlert(with: error.description) + } + } + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/CellSelectionTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/CellSelectionTableDelegate.swift new file mode 100644 index 000000000..531c1f7cd --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/CellSelectionTableDelegate.swift @@ -0,0 +1,32 @@ +// +// CellSelectionTableDelegate.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import UIKit + +final class CellSelectionTableDelegate: NSObject, SimpleInfoTableDelegate { + + private var cellSelectionHandler: CellSelectionHandler? + + func setCellSelectionHandler(_ handler: @escaping CellSelectionHandler) { + self.cellSelectionHandler = handler + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + reportCellSelection(index: indexPath.row, + selectionStatus: CellSelection.selected) + } + + func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { + reportCellSelection(index: indexPath.row, + selectionStatus: CellSelection.deSelected) + } + + private func reportCellSelection(index: Int, selectionStatus: CellSelection) { + guard let cellSelectionHandler = cellSelectionHandler else { return } + cellSelectionHandler(index, selectionStatus) + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift index 39d98bfd1..96fcb5cac 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift @@ -170,6 +170,7 @@ final class IssueControlViewController: UIViewController { }() private var currentIssue: Issue? + private var selectedLabels: [Label]? private var saveOperation: ((Issue) -> Void)? override func viewDidLoad() { @@ -271,11 +272,31 @@ final class IssueControlViewController: UIViewController { } @objc private func labelInfoTouched(_ sender: UIButton) { - print("레이블 내놔!") + let labelInfoViewController = AdditionalInfoViewController() + let tableDatasource = SimpleLabelTableDatasource() + labelInfoViewController.configure(withTitle: "레이블 선택", + preSelectedInfos: selectedLabels ?? [], + tableDatasource: tableDatasource, + isMultiselectionAllowed: true, + endpoint: EndPoint.label) + labelInfoViewController.setSaveOperation(updateLabelSelection) + + DispatchQueue.main.async { + self.present(labelInfoViewController, animated: true, completion: nil) + } + } + + private func updateLabelSelection(labels: [Label]) { + guard let firstLabel = labels.first else { return } + self.selectedLabels = labels + let count = labels.count + let tail = count-1 > 0 ? " 외 \(count-1)개" : "" + let labelInfo = "\(firstLabel.title)" + tail + labelInfoControl.changeInfoLabelText(to: labelInfo) } @objc private func milestoneInfoTouched(_ sender: UIButton) { - print("마일스톤 내놔!") + } @objc private func assigneeInfoTouched(_ sender: UIButton) { diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDatasource.swift new file mode 100644 index 000000000..3fb73c494 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDatasource.swift @@ -0,0 +1,14 @@ +// +// SimpleInfoTableDatasource.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import UIKit + +protocol SimpleInfoTableDatasource: UITableViewDataSource { + func update(with infos: [Identifiable]) + func info(for index: Int) -> Identifiable? + func index(for info: Identifiable) -> Int? +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDelegate.swift new file mode 100644 index 000000000..384b482a5 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDelegate.swift @@ -0,0 +1,18 @@ +// +// SimpleInfoTableDelegate.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import UIKit + +enum CellSelection { + case selected + case deSelected +} + +protocol SimpleInfoTableDelegate: UITableViewDelegate { + typealias CellSelectionHandler = ((Int, CellSelection) -> Void) + func setCellSelectionHandler(_ handler: @escaping CellSelectionHandler) +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleLabelTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleLabelTableDatasource.swift new file mode 100644 index 000000000..8eca8f2bc --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleLabelTableDatasource.swift @@ -0,0 +1,46 @@ +// +// SimpleLabelTableDatasource.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import UIKit + +final class SimpleLabelTableDatasource: NSObject, SimpleInfoTableDatasource { + + private var labels = [Label]() + + func update(with infos: [Identifiable]) { + guard let labels = infos as? [Label] else { return } + self.labels = labels + } + + func info(for index: Int) -> Identifiable? { + guard labels.count > index else { return nil } + return labels[index] + } + + func index(for info: Identifiable) -> Int? { + var targetIndex: Int? + labels.enumerated().forEach { (index, label) in + if label.identifier() == info.identifier() { + targetIndex = index + } + } + return targetIndex + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return labels.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cellID = SimpleLabelTableViewCell.reuseID + let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? SimpleLabelTableViewCell ?? SimpleLabelTableViewCell() + let cellInfo = labels[indexPath.row] + let hexColorCode = HexColorCode(from: cellInfo.hexColorCode) + cell.configure(with: hexColorCode, title: cellInfo.title) + return cell + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleLabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleLabelTableViewCell.swift new file mode 100644 index 000000000..27f51475b --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleLabelTableViewCell.swift @@ -0,0 +1,52 @@ +// +// SimpleLabelTableViewCell.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import UIKit + +class SimpleLabelTableViewCell: UITableViewCell { + + private lazy var labelView = LabelView() + private let spacing: CGFloat = 15 + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + configure() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + configure() + } + + override func awakeFromNib() { + super.awakeFromNib() + configure() + } + + private func configure() { + selectionStyle = .none + addLabelView() + } + + private func addLabelView() { + addSubview(labelView) + + NSLayoutConstraint.activate([ + labelView.centerYAnchor.constraint(equalTo: centerYAnchor), + labelView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing) + ]) + } + + func configure(with hexColorCode: HexColorCode, title: String) { + labelView.configure(with: hexColorCode, title) + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + accessoryType = selected ? .checkmark : .none + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift index ed2080e05..209b48945 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift @@ -7,23 +7,24 @@ import Foundation -struct Label: Decodable { +protocol Identifiable { + func identifier() -> Int +} + +struct Label: Decodable, Identifiable { private(set) var id: Int private(set) var title: String private(set) var body: String private(set) var hexColorCode: String - - init(id: Int, title: String, body: String, hexColorCode: String) { - self.id = id - self.title = title - self.body = body - self.hexColorCode = hexColorCode - } - + enum CodingKeys: String, CodingKey { case id case title = "name" case body = "content" case hexColorCode = "color_code" } + + func identifier() -> Int { + return id + } } From 58ecdf82681d5c07b02fad1520e3e1a136bfda22 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 23 Jun 2021 15:57:58 +0900 Subject: [PATCH 83/91] =?UTF-8?q?feat:=20[#82]=20=EB=A7=88=EC=9D=BC?= =?UTF-8?q?=EC=8A=A4=ED=86=A4=20=EC=84=A0=ED=83=9D=20=ED=99=94=EB=A9=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 마일스톤 선택 모달 구성 --- .../issue-tracker.xcodeproj/project.pbxproj | 8 +++ .../IssueControlViewController.swift | 18 +++++++ .../SimpleMilestoneTableDatasource.swift | 45 ++++++++++++++++ .../View/SimpleMilestoneTableViewCell.swift | 54 +++++++++++++++++++ .../Main/Milestone/Model/Milestone.swift | 6 ++- 5 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleMilestoneTableDatasource.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleMilestoneTableViewCell.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 07034f6fd..51bb7f367 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -59,6 +59,8 @@ E49695842682DDAE001AEB89 /* SimpleLabelTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695832682DDAE001AEB89 /* SimpleLabelTableDatasource.swift */; }; E49695862682FD95001AEB89 /* SimpleInfoTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695852682FD95001AEB89 /* SimpleInfoTableDelegate.swift */; }; E49695882682FDC9001AEB89 /* CellSelectionTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */; }; + E496958C26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */; }; + E496958E26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496958D26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -132,6 +134,8 @@ E49695832682DDAE001AEB89 /* SimpleLabelTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleLabelTableDatasource.swift; sourceTree = ""; }; E49695852682FD95001AEB89 /* SimpleInfoTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleInfoTableDelegate.swift; sourceTree = ""; }; E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellSelectionTableDelegate.swift; sourceTree = ""; }; + E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleMilestoneTableViewCell.swift; sourceTree = ""; }; + E496958D26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleMilestoneTableDatasource.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -380,6 +384,7 @@ E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */, E496958A26830B81001AEB89 /* Protocol */, E49695832682DDAE001AEB89 /* SimpleLabelTableDatasource.swift */, + E496958D26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift */, E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */, ); path = Controller; @@ -398,6 +403,7 @@ children = ( E496956D2681905A001AEB89 /* IssueInfoView.swift */, E496957D2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift */, + E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */, ); path = View; sourceTree = ""; @@ -586,12 +592,14 @@ FA431FFD267F61150010EA91 /* String.swift in Sources */, FAB2C36C2679F6CC009F879C /* MileStoneLabelView.swift in Sources */, E426DAC72671F6A00069E77D /* LoginError.swift in Sources */, + E496958E26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift in Sources */, E43912D626789812003CD344 /* RequestManager.swift in Sources */, E426DAC42671D95D0069E77D /* LoginService.swift in Sources */, E42AD120267093430071B436 /* LabelViewController.swift in Sources */, E43912D826789A83003CD344 /* EndPoint.swift in Sources */, E49695842682DDAE001AEB89 /* SimpleLabelTableDatasource.swift in Sources */, E426DABE2670EC830069E77D /* SocialLoginManagerDelegate.swift in Sources */, + E496958C26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift in Sources */, FA733A30267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift in Sources */, E49695782682C4B0001AEB89 /* AdditionalInfoViewController.swift in Sources */, E42AD0FE266E52FB0071B436 /* AppDelegate.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift index 96fcb5cac..dc686a175 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift @@ -171,6 +171,7 @@ final class IssueControlViewController: UIViewController { private var currentIssue: Issue? private var selectedLabels: [Label]? + private var selectedMilestone: [MileStone]? private var saveOperation: ((Issue) -> Void)? override func viewDidLoad() { @@ -296,7 +297,24 @@ final class IssueControlViewController: UIViewController { } @objc private func milestoneInfoTouched(_ sender: UIButton) { + let milestoneViewController = AdditionalInfoViewController() + let tableDatasource = SimpleMilestoneTableDatasource() + milestoneViewController.configure(withTitle: "마일스톤 선택", + preSelectedInfos: selectedMilestone ?? [], + tableDatasource: tableDatasource, + isMultiselectionAllowed: false, + endpoint: EndPoint.milestone) + milestoneViewController.setSaveOperation(updateMilestoneSelection) + DispatchQueue.main.async { + self.present(milestoneViewController, animated: true, completion: nil) + } + } + + private func updateMilestoneSelection(milestones: [MileStone]) { + guard let firstMilestone = milestones.first else { return } + self.selectedMilestone = milestones + milestoneInfoControl.changeInfoLabelText(to: firstMilestone.title) } @objc private func assigneeInfoTouched(_ sender: UIButton) { diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleMilestoneTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleMilestoneTableDatasource.swift new file mode 100644 index 000000000..7f8f54489 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleMilestoneTableDatasource.swift @@ -0,0 +1,45 @@ +// +// SimpleMilestoneTableDatasource.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import UIKit + +final class SimpleMilestoneTableDatasource: NSObject, SimpleInfoTableDatasource { + + private var milestones = [MileStone]() + + func update(with infos: [Identifiable]) { + guard let milestones = infos as? [MileStone] else { return } + self.milestones = milestones + } + + func info(for index: Int) -> Identifiable? { + guard milestones.count > index else { return nil } + return milestones[index] + } + + func index(for info: Identifiable) -> Int? { + var targetIndex: Int? + milestones.enumerated().forEach { (index, label) in + if label.identifier() == info.identifier() { + targetIndex = index + } + } + return targetIndex + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return milestones.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cellID = SimpleMilestoneTableViewCell.reuseID + let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? SimpleMilestoneTableViewCell ?? SimpleMilestoneTableViewCell() + let cellInfo = milestones[indexPath.row] + cell.configure(with: cellInfo.title) + return cell + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleMilestoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleMilestoneTableViewCell.swift new file mode 100644 index 000000000..92e025d49 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleMilestoneTableViewCell.swift @@ -0,0 +1,54 @@ +// +// SimpleMilestoneTableViewCell.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import UIKit + +class SimpleMilestoneTableViewCell: UITableViewCell { + + private lazy var titleLabel = UILabel() + private let spacing: CGFloat = 15 + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + configure() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + configure() + } + + override func awakeFromNib() { + super.awakeFromNib() + configure() + } + + private func configure() { + selectionStyle = .none + addLabelView() + } + + private func addLabelView() { + titleLabel.translatesAutoresizingMaskIntoConstraints = false + addSubview(titleLabel) + + NSLayoutConstraint.activate([ + titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor), + titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), + titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -spacing * 2) + ]) + } + + func configure(with title: String) { + titleLabel.text = title + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + accessoryType = selected ? .checkmark : .none + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift index 8016d9f7b..624c8dc34 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Milestone/Model/Milestone.swift @@ -7,7 +7,7 @@ import Foundation -struct MileStone: Decodable { +struct MileStone: Decodable, Identifiable { let id: Int let title: String let description: String? @@ -19,4 +19,8 @@ struct MileStone: Decodable { case description case dueDate = "due_date" } + + func identifier() -> Int { + return id + } } From 05706800ecef600be5eadbe4ee3f61ba33c031e9 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 23 Jun 2021 16:15:39 +0900 Subject: [PATCH 84/91] =?UTF-8?q?refactor:=20[#82]=20=EC=93=B0=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C,?= =?UTF-8?q?=20=EB=A9=94=EC=86=8C=EB=93=9C=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/IssueControlViewController.swift | 16 ++++++++-------- .../Main/Issue/View/IssueInfoView.swift | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift index dc686a175..72c7e0583 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift @@ -281,17 +281,20 @@ final class IssueControlViewController: UIViewController { isMultiselectionAllowed: true, endpoint: EndPoint.label) labelInfoViewController.setSaveOperation(updateLabelSelection) - + present(labelInfoViewController) + } + + private func present(_ viewController: UIViewController) { DispatchQueue.main.async { - self.present(labelInfoViewController, animated: true, completion: nil) + self.present(viewController, animated: true, completion: nil) } } private func updateLabelSelection(labels: [Label]) { guard let firstLabel = labels.first else { return } self.selectedLabels = labels - let count = labels.count - let tail = count-1 > 0 ? " 외 \(count-1)개" : "" + let extraCount = labels.count - 1 + let tail = extraCount > 0 ? " 외 \(extraCount)개" : "" let labelInfo = "\(firstLabel.title)" + tail labelInfoControl.changeInfoLabelText(to: labelInfo) } @@ -305,10 +308,7 @@ final class IssueControlViewController: UIViewController { isMultiselectionAllowed: false, endpoint: EndPoint.milestone) milestoneViewController.setSaveOperation(updateMilestoneSelection) - - DispatchQueue.main.async { - self.present(milestoneViewController, animated: true, completion: nil) - } + present(milestoneViewController) } private func updateMilestoneSelection(milestones: [MileStone]) { diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueInfoView.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueInfoView.swift index 11c2517a7..e6b3c32c2 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueInfoView.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueInfoView.swift @@ -13,7 +13,6 @@ final class IssueInfoControl: UIControl { let label = UILabel() label.textColor = .lightGray label.textAlignment = .right - label.text = "info" label.translatesAutoresizingMaskIntoConstraints = false return label }() From 9ed2e6a4907f0a12c1465fb49f27da4359449c0c Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 23 Jun 2021 16:41:23 +0900 Subject: [PATCH 85/91] =?UTF-8?q?feat:=20[#82]=20=EB=8B=B4=EB=8B=B9?= =?UTF-8?q?=EC=9E=90=20=EC=84=A0=ED=83=9D=20=ED=99=94=EB=A9=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 담당자 선택 모달 구성 --- .../issue-tracker.xcodeproj/project.pbxproj | 12 +++ .../IssueControlViewController.swift | 20 ++++- .../SimpleAssigneeTableDatasource.swift | 45 +++++++++++ .../issue-tracker/Main/Issue/Model/User.swift | 18 +++++ .../View/SimpleAssigneeTableViewCell.swift | 78 +++++++++++++++++++ .../issue-tracker/Network/EndPoint.swift | 3 + 6 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleAssigneeTableDatasource.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Model/User.swift create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleAssigneeTableViewCell.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 51bb7f367..44811e3d5 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -61,6 +61,9 @@ E49695882682FDC9001AEB89 /* CellSelectionTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */; }; E496958C26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */; }; E496958E26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496958D26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift */; }; + E4969590268317C1001AEB89 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496958F268317C1001AEB89 /* User.swift */; }; + E4969592268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4969591268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift */; }; + E496959426831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959326831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -136,6 +139,9 @@ E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellSelectionTableDelegate.swift; sourceTree = ""; }; E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleMilestoneTableViewCell.swift; sourceTree = ""; }; E496958D26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleMilestoneTableDatasource.swift; sourceTree = ""; }; + E496958F268317C1001AEB89 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; + E4969591268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleAssigneeTableViewCell.swift; sourceTree = ""; }; + E496959326831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleAssigneeTableDatasource.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -385,6 +391,7 @@ E496958A26830B81001AEB89 /* Protocol */, E49695832682DDAE001AEB89 /* SimpleLabelTableDatasource.swift */, E496958D26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift */, + E496959326831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift */, E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */, ); path = Controller; @@ -394,6 +401,7 @@ isa = PBXGroup; children = ( E49695682680B3FB001AEB89 /* Issue.swift */, + E496958F268317C1001AEB89 /* User.swift */, ); path = Model; sourceTree = ""; @@ -404,6 +412,7 @@ E496956D2681905A001AEB89 /* IssueInfoView.swift */, E496957D2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift */, E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */, + E4969591268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift */, ); path = View; sourceTree = ""; @@ -593,12 +602,14 @@ FAB2C36C2679F6CC009F879C /* MileStoneLabelView.swift in Sources */, E426DAC72671F6A00069E77D /* LoginError.swift in Sources */, E496958E26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift in Sources */, + E496959426831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift in Sources */, E43912D626789812003CD344 /* RequestManager.swift in Sources */, E426DAC42671D95D0069E77D /* LoginService.swift in Sources */, E42AD120267093430071B436 /* LabelViewController.swift in Sources */, E43912D826789A83003CD344 /* EndPoint.swift in Sources */, E49695842682DDAE001AEB89 /* SimpleLabelTableDatasource.swift in Sources */, E426DABE2670EC830069E77D /* SocialLoginManagerDelegate.swift in Sources */, + E4969590268317C1001AEB89 /* User.swift in Sources */, E496958C26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift in Sources */, FA733A30267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift in Sources */, E49695782682C4B0001AEB89 /* AdditionalInfoViewController.swift in Sources */, @@ -613,6 +624,7 @@ E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */, E49695882682FDC9001AEB89 /* CellSelectionTableDelegate.swift in Sources */, E43912DC2678A737003CD344 /* JWT.swift in Sources */, + E4969592268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift in Sources */, E426DABA2670EC2D0069E77D /* AppleAuthorizationManager.swift in Sources */, FAEB30AE266F6A7800C17BE9 /* UIImageExtension.swift in Sources */, E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift index 72c7e0583..fc844d2c2 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift @@ -172,6 +172,7 @@ final class IssueControlViewController: UIViewController { private var currentIssue: Issue? private var selectedLabels: [Label]? private var selectedMilestone: [MileStone]? + private var selectedAssignees: [User]? private var saveOperation: ((Issue) -> Void)? override func viewDidLoad() { @@ -318,7 +319,24 @@ final class IssueControlViewController: UIViewController { } @objc private func assigneeInfoTouched(_ sender: UIButton) { - print("담당자 내놔!") + let assigneeViewController = AdditionalInfoViewController() + let tableDatasource = SimpleAssigneeTableDatasource() + assigneeViewController.configure(withTitle: "담당자 선택", + preSelectedInfos: selectedAssignees ?? [], + tableDatasource: tableDatasource, + isMultiselectionAllowed: true, + endpoint: EndPoint.user) + assigneeViewController.setSaveOperation(updateAssigneeSelection) + present(assigneeViewController) + } + + private func updateAssigneeSelection(assignees: [User]) { + guard let firstAssignee = assignees.first else { return } + self.selectedAssignees = assignees + let extraCount = assignees.count - 1 + let tail = extraCount > 0 ? " 외 \(extraCount)명" : "" + let assigneeInfo = "\(firstAssignee.name)" + tail + assigneeInfoControl.changeInfoLabelText(to: assigneeInfo) } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleAssigneeTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleAssigneeTableDatasource.swift new file mode 100644 index 000000000..58a276e42 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleAssigneeTableDatasource.swift @@ -0,0 +1,45 @@ +// +// SimpleAssigneeTableDatasource.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import UIKit + +final class SimpleAssigneeTableDatasource: NSObject, SimpleInfoTableDatasource { + + private var assignees = [User]() + + func update(with infos: [Identifiable]) { + guard let assignees = infos as? [User] else { return } + self.assignees = assignees + } + + func info(for index: Int) -> Identifiable? { + guard assignees.count > index else { return nil } + return assignees[index] + } + + func index(for info: Identifiable) -> Int? { + var targetIndex: Int? + assignees.enumerated().forEach { (index, assignee) in + if assignee.identifier() == info.identifier() { + targetIndex = index + } + } + return targetIndex + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return assignees.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cellID = SimpleAssigneeTableViewCell.reuseID + let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? SimpleAssigneeTableViewCell ?? SimpleAssigneeTableViewCell() + let cellInfo = assignees[indexPath.row] + cell.configure(with: cellInfo.name, imageUrl: cellInfo.imageUrl) + return cell + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/User.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/User.swift new file mode 100644 index 000000000..b09d3351c --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/User.swift @@ -0,0 +1,18 @@ +// +// User.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import Foundation + +struct User: Decodable, Identifiable { + private(set) var id: Int + private(set) var name: String + private(set) var imageUrl: String + + func identifier() -> Int { + return id + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleAssigneeTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleAssigneeTableViewCell.swift new file mode 100644 index 000000000..8fdba30f1 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleAssigneeTableViewCell.swift @@ -0,0 +1,78 @@ +// +// SimpleAssigneeTableViewCell.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import UIKit + +class SimpleAssigneeTableViewCell: UITableViewCell { + + private lazy var titleLabel = UILabel() + + private lazy var profileImageView: UIImageView = { + let imageView = UIImageView() + imageView.contentMode = .scaleAspectFit + imageView.translatesAutoresizingMaskIntoConstraints = false + return imageView + }() + + private let spacing: CGFloat = 15 + private let imageManager = ImageLoadManager() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + configure() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + configure() + } + + override func awakeFromNib() { + super.awakeFromNib() + configure() + } + + private func configure() { + selectionStyle = .none + addImageView() + addLabelView() + } + + private func addImageView() { + addSubview(profileImageView) + + NSLayoutConstraint.activate([ + profileImageView.centerYAnchor.constraint(equalTo: centerYAnchor), + profileImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: spacing), + profileImageView.heightAnchor.constraint(equalToConstant: frame.height * 0.8), + profileImageView.widthAnchor.constraint(equalToConstant: frame.height * 0.8) + ]) + } + + private func addLabelView() { + titleLabel.translatesAutoresizingMaskIntoConstraints = false + addSubview(titleLabel) + + NSLayoutConstraint.activate([ + titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor), + titleLabel.leadingAnchor.constraint(equalTo: profileImageView.trailingAnchor, constant: spacing), + titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -spacing * 2) + ]) + } + + func configure(with title: String, imageUrl: String) { + titleLabel.text = title + imageManager.load(from: imageUrl) { [weak self] cachePath in + self?.profileImageView.image = UIImage(contentsOfFile: cachePath) + } + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + accessoryType = selected ? .checkmark : .none + } +} diff --git a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift index 549463b78..21d6dafa1 100644 --- a/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift +++ b/iOS/issue-tracker/issue-tracker/Network/EndPoint.swift @@ -13,6 +13,7 @@ enum EndPoint { case OAuth case label case milestone + case user case none func path() -> String { @@ -23,6 +24,8 @@ enum EndPoint { return "/labels" case .milestone: return "/milestones" + case .user: + return "/users" case .none: return "" } From 7bc15593190e049cbd5d2827acb7f43cb3ddf4a2 Mon Sep 17 00:00:00 2001 From: JinseoPark Date: Wed, 23 Jun 2021 17:06:31 +0900 Subject: [PATCH 86/91] =?UTF-8?q?refactor=20:[#86]=20=EC=9D=B4=EC=8A=88DTO?= =?UTF-8?q?=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 4 +++ .../IssueDetailViewController.swift | 27 +++++++++++++++++++ .../Controller/IssueTableViewDataSource.swift | 2 -- .../Controller/IssueViewController.swift | 2 +- .../Main/Issue/Model/Issue.swift | 26 +----------------- .../Main/Issue/View/IssueTableViewCell.swift | 13 +++------ .../Controller/LabelTableViewDatasource.swift | 2 +- .../Controller/LabelViewController.swift | 4 +-- .../Main/Label/Model/Label.swift | 11 ++------ 9 files changed, 42 insertions(+), 49 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueDetailViewController.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 5ec5bf0c1..9b4732976 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -67,6 +67,7 @@ FAF927AB2680DB1C0017F8DE /* IssueTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF927AA2680DB1C0017F8DE /* IssueTableViewDataSource.swift */; }; FAF927AD2680DCCA0017F8DE /* IssueTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF927AC2680DCCA0017F8DE /* IssueTableViewCell.swift */; }; FAF927AF2681DA810017F8DE /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF927AE2681DA810017F8DE /* Issue.swift */; }; + FAF927B126831A570017F8DE /* IssueDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF927B026831A570017F8DE /* IssueDetailViewController.swift */; }; FAFD11B1268078F80064AED4 /* CommonTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAFD11B0268078F80064AED4 /* CommonTableDelegate.swift */; }; /* End PBXBuildFile section */ @@ -132,6 +133,7 @@ FAF927AA2680DB1C0017F8DE /* IssueTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTableViewDataSource.swift; sourceTree = ""; }; FAF927AC2680DCCA0017F8DE /* IssueTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTableViewCell.swift; sourceTree = ""; }; FAF927AE2681DA810017F8DE /* Issue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Issue.swift; sourceTree = ""; }; + FAF927B026831A570017F8DE /* IssueDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueDetailViewController.swift; sourceTree = ""; }; FAFD11B0268078F80064AED4 /* CommonTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonTableDelegate.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -435,6 +437,7 @@ E42AD11D267093320071B436 /* IssueViewController.swift */, FAF927A82680DAFB0017F8DE /* IssueTableViewDelegate.swift */, FAF927AA2680DB1C0017F8DE /* IssueTableViewDataSource.swift */, + FAF927B026831A570017F8DE /* IssueDetailViewController.swift */, ); path = Controller; sourceTree = ""; @@ -538,6 +541,7 @@ E43912E02678AD0A003CD344 /* LabelTableViewDatasource.swift in Sources */, FA431FF9267F36FA0010EA91 /* MileStoneControlViewController.swift in Sources */, E43912EA267A2351003CD344 /* NetworkError.swift in Sources */, + FAF927B126831A570017F8DE /* IssueDetailViewController.swift in Sources */, E43912F6267CAE01003CD344 /* TopMenuView.swift in Sources */, E42AD122267093590071B436 /* MileStoneViewController.swift in Sources */, FA733A2E267C3D77005A40C8 /* Milestone.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueDetailViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueDetailViewController.swift new file mode 100644 index 000000000..e737c5d12 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueDetailViewController.swift @@ -0,0 +1,27 @@ +// +// IssueDetailViewController.swift +// issue-tracker +// +// Created by jinseo park on 6/23/21. +// + +import Foundation +import UIKit + +class IssueDetailViewController: UIViewController { + + private lazy var backButton: ImageBarButton = { + let button = ImageBarButton() + button.configure(with: "chevron.backward", "목록") + button.addTarget(self, action: #selector(backToIssuesTouched), for: .touchUpInside) + return button + }() + + override func viewDidLoad() { + super.viewDidLoad() + } + + @objc func backToIssuesTouched(_ sender: UIButton) { + self.navigationController?.popViewController(animated: true) + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift index a0d698cfd..ab3ae642a 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueTableViewDataSource.swift @@ -27,6 +27,4 @@ class IssueTableViewDataSource: NSObject, UITableViewDataSource { cell.configure(title: issue.title ?? "", mileStoneName: issue.milestone?.title ?? "", labels: issue.labels ?? []) return cell } - - } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift index 062637b8b..b27e2d7f0 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueViewController.swift @@ -118,7 +118,6 @@ class IssueViewController: UIViewController { deleteIssue(for: targetIssue.issueNumber) case .close: print("close 되어랏") -// presentEditLabelViewController(for: targetLabel) default: assert(false) } @@ -146,6 +145,7 @@ extension IssueViewController { case .success(let result): guard let issues = result.data else { return } self?.issueTableDatasource?.update(issues: issues) + self?.issueTableDelegate?.update(issues: issues) self?.reloadTableView() case .failure(let error): self?.presentAlert(with: error.description) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift index 1dba8c83b..dcee5c6fa 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift @@ -7,7 +7,6 @@ import Foundation - struct IssueDTO: Decodable { let data: [Issue]? let message: String? @@ -42,36 +41,13 @@ struct Assignee: Decodable { } } -struct IssueLabel: Decodable { - private(set) var id: Int - private(set) var name: String - private(set) var colorCode: String - - enum CodingKeys: String, CodingKey { - case id - case name - case colorCode = "color_code" - } -} - -struct IssueMileStone: Decodable { - private(set) var id: Int - private(set) var title: String - - enum CodingKeys: String, CodingKey { - case id - case title - } -} - struct Issue: Decodable { private(set) var issueNumber: Int private(set) var title: String? private(set) var status: Bool private(set) var author: Author private(set) var assignees: [Assignee]? - private(set) var labels: [IssueLabel]? -// private(set) var milestone: IssueMileStone? + private(set) var labels: [Label]? private(set) var milestone: MileStone? private(set) var createdDate: String diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift index b4c13b560..4ef9336ac 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueTableViewCell.swift @@ -66,11 +66,9 @@ class IssueTableViewCell: UITableViewCell { } private func setViews() { - addIssueStackView() addIssueTitleView() addMileStoneLabel() -// addlabelsStackView() } func addIssueStackView() { @@ -95,10 +93,7 @@ class IssueTableViewCell: UITableViewCell { labelsStackView.subviews.forEach { $0.removeFromSuperview() } } - func addlabelsStackView(_ labels: [IssueLabel]) { - //Cell의 재사용으로 계속 이 함수가 불린다. 계속 라벨이 추가되는 이슈를 막기 위해서 불릴 때마다 reset하기 - - + func addlabelsStackView(_ labels: [Label]) { issueStackView.addArrangedSubview(labelsStackView) labelsStackView.spacing = 4 @@ -109,16 +104,16 @@ class IssueTableViewCell: UITableViewCell { labels.forEach { label in let labelView = LabelView() - let colorText = label.colorCode + let colorText = label.hexColorCode let hex = HexColorCode(from: colorText) - let titleText = label.name + let titleText = label.title labelView.configure(with: hex, titleText) labelView.translatesAutoresizingMaskIntoConstraints = false labelsStackView.addArrangedSubview(labelView) } } - func configure(title: String, mileStoneName: String, labels: [IssueLabel]) { + func configure(title: String, mileStoneName: String, labels: [Label]) { titleLabel.text = title mileStoneTitleConfigure(mileStoneName: mileStoneName) clearLabelStackView() diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift index 2d87fc187..7af081ffc 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelTableViewDatasource.swift @@ -27,7 +27,7 @@ final class LabelTableViewDatasource: NSObject, UITableViewDataSource { let hex = HexColorCode(from: label.hexColorCode) let backgroundColor = colorConverter.convertHex(hex) let titleColor = colorConverter.isColorDark(hex: hex) ? UIColor.white : UIColor.black - cell.configure(with: backgroundColor, titleColor, label.title, label.body) + cell.configure(with: backgroundColor, titleColor, label.title, label.body ?? "") return cell } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift index e3a19ca78..80c54afd0 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Controller/LabelViewController.swift @@ -162,7 +162,7 @@ extension LabelViewController { private func postNewLabel(_ newLabel: Label) { let newLabelEndpoint = EndPoint.label.path() - let requestBody = NewLabelDTO(name: newLabel.title, content: newLabel.body, colorCode: newLabel.hexColorCode) + let requestBody = NewLabelDTO(name: newLabel.title, content: newLabel.body ?? "", colorCode: newLabel.hexColorCode) networkManager?.post(endpoint: newLabelEndpoint, requestBody: requestBody, completion: { [weak self] result in switch result { @@ -177,7 +177,7 @@ extension LabelViewController { private func putEditedLabel(_ editedLabel: Label) { let labelId = editedLabel.id let editLabelEndpoint = EndPoint.label.path(with: labelId) - let requestBody = NewLabelDTO(name: editedLabel.title, content: editedLabel.body, colorCode: editedLabel.hexColorCode) + let requestBody = NewLabelDTO(name: editedLabel.title, content: editedLabel.body ?? "", colorCode: editedLabel.hexColorCode) networkManager?.put(endpoint: editLabelEndpoint, requestBody: requestBody, completion: { [weak self] result in switch result { diff --git a/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift b/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift index a99a381b0..ac0415425 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Label/Model/Label.swift @@ -17,19 +17,12 @@ struct LabelDTO: Decodable { } } -class Label: Decodable { +struct Label: Decodable { private(set) var id: Int private(set) var title: String - private(set) var body: String + private(set) var body: String? private(set) var hexColorCode: String - init(id: Int, title: String, body: String, hexColorCode: String) { - self.id = id - self.title = title - self.body = body - self.hexColorCode = hexColorCode - } - enum CodingKeys: String, CodingKey { case id case title = "name" From 48e29c4b333cef82fdc8a3498d442dc04a46268f Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 23 Jun 2021 17:17:51 +0900 Subject: [PATCH 87/91] =?UTF-8?q?chore:=20=EB=94=94=EB=A0=89=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 18 +++++++++--------- .../AdditionalInfoViewController.swift | 0 .../CellSelectionTableDelegate.swift | 0 .../IssueControlViewController.swift | 0 .../Protocol/SimpleInfoTableDatasource.swift | 0 .../Protocol/SimpleInfoTableDelegate.swift | 0 .../SimpleAssigneeTableDatasource.swift | 0 .../SimpleLabelTableDatasource.swift | 0 .../SimpleMilestoneTableDatasource.swift | 0 .../Main/Issue/{Model => Model2}/Issue.swift | 0 .../Main/Issue/{Model => Model2}/User.swift | 0 .../Issue/{View => View2}/IssueInfoView.swift | 0 .../SimpleAssigneeTableViewCell.swift | 0 .../SimpleLabelTableViewCell.swift | 0 .../SimpleMilestoneTableViewCell.swift | 0 15 files changed, 9 insertions(+), 9 deletions(-) rename iOS/issue-tracker/issue-tracker/Main/Issue/{Controller => Controller2}/AdditionalInfoViewController.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{Controller => Controller2}/CellSelectionTableDelegate.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{Controller => Controller2}/IssueControlViewController.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{Controller => Controller2}/Protocol/SimpleInfoTableDatasource.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{Controller => Controller2}/Protocol/SimpleInfoTableDelegate.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{Controller => Controller2}/SimpleAssigneeTableDatasource.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{Controller => Controller2}/SimpleLabelTableDatasource.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{Controller => Controller2}/SimpleMilestoneTableDatasource.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{Model => Model2}/Issue.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{Model => Model2}/User.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{View => View2}/IssueInfoView.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{View => View2}/SimpleAssigneeTableViewCell.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{View => View2}/SimpleLabelTableViewCell.swift (100%) rename iOS/issue-tracker/issue-tracker/Main/Issue/{View => View2}/SimpleMilestoneTableViewCell.swift (100%) diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 44811e3d5..fd4a9205c 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -295,9 +295,9 @@ E42AD11926708EBA0071B436 /* Issue */ = { isa = PBXGroup; children = ( - E496956B2680B40D001AEB89 /* Model */, - E496956C26819042001AEB89 /* View */, - E496956A2680B3FE001AEB89 /* Controller */, + E496956B2680B40D001AEB89 /* Model2 */, + E496956C26819042001AEB89 /* View2 */, + E496956A2680B3FE001AEB89 /* Controller2 */, E42AD11D267093320071B436 /* IssueViewController.swift */, ); path = Issue; @@ -383,7 +383,7 @@ path = Model; sourceTree = ""; }; - E496956A2680B3FE001AEB89 /* Controller */ = { + E496956A2680B3FE001AEB89 /* Controller2 */ = { isa = PBXGroup; children = ( E49695662680B0B7001AEB89 /* IssueControlViewController.swift */, @@ -394,19 +394,19 @@ E496959326831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift */, E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */, ); - path = Controller; + path = Controller2; sourceTree = ""; }; - E496956B2680B40D001AEB89 /* Model */ = { + E496956B2680B40D001AEB89 /* Model2 */ = { isa = PBXGroup; children = ( E49695682680B3FB001AEB89 /* Issue.swift */, E496958F268317C1001AEB89 /* User.swift */, ); - path = Model; + path = Model2; sourceTree = ""; }; - E496956C26819042001AEB89 /* View */ = { + E496956C26819042001AEB89 /* View2 */ = { isa = PBXGroup; children = ( E496956D2681905A001AEB89 /* IssueInfoView.swift */, @@ -414,7 +414,7 @@ E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */, E4969591268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift */, ); - path = View; + path = View2; sourceTree = ""; }; E496958A26830B81001AEB89 /* Protocol */ = { diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/AdditionalInfoViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/AdditionalInfoViewController.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/AdditionalInfoViewController.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/AdditionalInfoViewController.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/CellSelectionTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/CellSelectionTableDelegate.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/CellSelectionTableDelegate.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/CellSelectionTableDelegate.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/IssueControlViewController.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueControlViewController.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/IssueControlViewController.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/Protocol/SimpleInfoTableDatasource.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDatasource.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/Protocol/SimpleInfoTableDatasource.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/Protocol/SimpleInfoTableDelegate.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/Protocol/SimpleInfoTableDelegate.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/Protocol/SimpleInfoTableDelegate.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleAssigneeTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/SimpleAssigneeTableDatasource.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleAssigneeTableDatasource.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/SimpleAssigneeTableDatasource.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleLabelTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/SimpleLabelTableDatasource.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleLabelTableDatasource.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/SimpleLabelTableDatasource.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleMilestoneTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/SimpleMilestoneTableDatasource.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/SimpleMilestoneTableDatasource.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller2/SimpleMilestoneTableDatasource.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Model2/Issue.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Model/Issue.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Model2/Issue.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/User.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Model2/User.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Model/User.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Model2/User.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueInfoView.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View2/IssueInfoView.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueInfoView.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/View2/IssueInfoView.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleAssigneeTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View2/SimpleAssigneeTableViewCell.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleAssigneeTableViewCell.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/View2/SimpleAssigneeTableViewCell.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleLabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View2/SimpleLabelTableViewCell.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleLabelTableViewCell.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/View2/SimpleLabelTableViewCell.swift diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleMilestoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View2/SimpleMilestoneTableViewCell.swift similarity index 100% rename from iOS/issue-tracker/issue-tracker/Main/Issue/View/SimpleMilestoneTableViewCell.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/View2/SimpleMilestoneTableViewCell.swift From 21bf69466eca699469a6292350df63ff1c25d69d Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 23 Jun 2021 17:40:14 +0900 Subject: [PATCH 88/91] =?UTF-8?q?fix:=20=EB=9D=BC=EC=A7=80=ED=83=80?= =?UTF-8?q?=EC=9D=B4=ED=8B=80=20=ED=92=80=EB=A6=AC=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이슈 작성 화면 갔다가 이슈 리스트 화면으로 돌아갈 때 라지타이틀 모드 풀리는 문제 해결 --- .../IssueEditing/IssueControlViewController.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift index 352cde209..073655b03 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift @@ -239,12 +239,18 @@ final class IssueControlViewController: UIViewController { } @objc private func cancelButtonTouched(_ sender: UIButton) { - navigationController?.popViewController(animated: true) + popCurrentViewController() } @objc private func saveButtonTouched(_ sender: UIButton) { guard let saveOperation = saveOperation else { return } //saveOperation(tempIssue) + popCurrentViewController() + } + + private func popCurrentViewController() { + navigationController?.popViewController(animated: true) + navigationController?.navigationBar.prefersLargeTitles = true } @objc private func markdownSegmentChanged(_ sender: UISegmentedControl) { From aafb4e911768dbbf98269be5c7fc66208baa6cd2 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 23 Jun 2021 17:53:12 +0900 Subject: [PATCH 89/91] =?UTF-8?q?feat:=20[#82]=20=EC=83=88=20=EC=9D=B4?= =?UTF-8?q?=EC=8A=88=20=EC=B6=94=EA=B0=80=20=EB=84=A4=ED=8A=B8=EC=9B=8C?= =?UTF-8?q?=ED=81=AC=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 6 ++++- .../IssueControlViewController.swift | 14 +++++++---- .../IssueEditing/IssueViewController.swift | 12 ++++++++-- .../Main/Issue/Model/NewIssue.swift | 24 +++++++++++++++++++ 4 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Model/NewIssue.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index ce1f40520..07599177e 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -64,6 +64,7 @@ E4969592268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4969591268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift */; }; E496959426831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959326831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift */; }; E496959726832693001AEB89 /* IssueTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959626832693001AEB89 /* IssueTableViewDelegate.swift */; }; + E496959926832B5A001AEB89 /* NewIssue.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959826832B5A001AEB89 /* NewIssue.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -146,6 +147,7 @@ E4969591268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleAssigneeTableViewCell.swift; sourceTree = ""; }; E496959326831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleAssigneeTableDatasource.swift; sourceTree = ""; }; E496959626832693001AEB89 /* IssueTableViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTableViewDelegate.swift; sourceTree = ""; }; + E496959826832B5A001AEB89 /* NewIssue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewIssue.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -487,6 +489,7 @@ isa = PBXGroup; children = ( FAF927AE2681DA810017F8DE /* Issue.swift */, + E496959826832B5A001AEB89 /* NewIssue.swift */, E496958F268317C1001AEB89 /* User.swift */, ); path = Model; @@ -504,11 +507,11 @@ FAF927A72680D9630017F8DE /* Controller */ = { isa = PBXGroup; children = ( - E496956A2680B3FE001AEB89 /* IssueEditing */, E42AD11D267093320071B436 /* IssueViewController.swift */, E496959626832693001AEB89 /* IssueTableViewDelegate.swift */, FAF927AA2680DB1C0017F8DE /* IssueTableViewDataSource.swift */, FAF927B026831A570017F8DE /* IssueDetailViewController.swift */, + E496956A2680B3FE001AEB89 /* IssueEditing */, ); path = Controller; sourceTree = ""; @@ -591,6 +594,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E496959926832B5A001AEB89 /* NewIssue.swift in Sources */, FAB2C36A26789D41009F879C /* MileStoneTableViewCell.swift in Sources */, FAF927AB2680DB1C0017F8DE /* IssueTableViewDataSource.swift in Sources */, E426DAD126730DC50069E77D /* OAuthResponseDTO.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift index 073655b03..f36d076fd 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift @@ -173,7 +173,7 @@ final class IssueControlViewController: UIViewController { private var selectedLabels: [Label]? private var selectedMilestone: [MileStone]? private var selectedAssignees: [User]? - private var saveOperation: ((Issue) -> Void)? + private var saveOperation: ((NewIssue) -> Void)? override func viewDidLoad() { super.viewDidLoad() @@ -230,7 +230,7 @@ final class IssueControlViewController: UIViewController { ]) } - func setSaveOperation(_ operation: @escaping (Issue) -> Void) { + func setSaveOperation(_ operation: @escaping (NewIssue) -> Void) { self.saveOperation = operation } @@ -243,8 +243,14 @@ final class IssueControlViewController: UIViewController { } @objc private func saveButtonTouched(_ sender: UIButton) { - guard let saveOperation = saveOperation else { return } - //saveOperation(tempIssue) + guard let saveOperation = saveOperation, + let title = titleTextField.text else { return } + let newIssue = NewIssue(title: title, + comment: bodyTextView.text, + assigneeIds: selectedAssignees?.map{ $0.id }, + labelIds: selectedLabels?.map{ $0.id }, + milestoneId: selectedMilestone?.first?.id) + saveOperation(newIssue) popCurrentViewController() } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueViewController.swift index 7cfd1ef53..afc1c9c1f 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueViewController.swift @@ -167,8 +167,16 @@ extension IssueViewController { }) } - private func postIssue(_ issue: Issue) { - + private func postIssue(_ newIssue: NewIssue) { + let postIssueEndpoint = EndPoint.issue.path() + networkManager?.post(endpoint: postIssueEndpoint, requestBody: newIssue, completion: { [weak self] (result: Result) in + switch result { + case .success(_): + self?.loadIssues() + case .failure(let error): + self?.presentAlert(with: error.description) + } + }) } } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Model/NewIssue.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/NewIssue.swift new file mode 100644 index 000000000..a3fd0c7d3 --- /dev/null +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Model/NewIssue.swift @@ -0,0 +1,24 @@ +// +// NewIssue.swift +// issue-tracker +// +// Created by Song on 2021/06/23. +// + +import Foundation + +struct NewIssue: Encodable { + let title: String + let comment: String + let assigneeIds: [Int] + let labelIds: [Int] + let milestoneId: Int? + + init(title: String, comment: String?, assigneeIds: [Int]?, labelIds: [Int]?, milestoneId: Int?) { + self.title = title + self.comment = comment ?? "" + self.assigneeIds = assigneeIds ?? [] + self.labelIds = labelIds ?? [] + self.milestoneId = milestoneId + } +} From 9f9f3fe34def9de0404b094165340fc4e2340f10 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 23 Jun 2021 18:40:25 +0900 Subject: [PATCH 90/91] =?UTF-8?q?refactor:=20[#82]=20=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20datasource=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 제네릭하게 생성하여 재사용 --- .../issue-tracker.xcodeproj/project.pbxproj | 16 ++---- .../AdditionalInfoViewController.swift | 6 +-- .../CommonSimpleInfoTableDatasource.swift | 50 +++++++++++++++++++ .../IssueControlViewController.swift | 15 ++++-- .../Protocol/SimpleInfoTableDatasource.swift | 10 ++-- .../SimpleAssigneeTableDatasource.swift | 45 ----------------- .../SimpleLabelTableDatasource.swift | 46 ----------------- .../SimpleMilestoneTableDatasource.swift | 45 ----------------- .../SimpleAssigneeTableViewCell.swift | 16 +++--- .../SimpleLabelTableViewCell.swift | 9 ++-- .../SimpleMilestoneTableViewCell.swift | 8 +-- 11 files changed, 97 insertions(+), 169 deletions(-) create mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/CommonSimpleInfoTableDatasource.swift delete mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleAssigneeTableDatasource.swift delete mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleLabelTableDatasource.swift delete mode 100644 iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleMilestoneTableDatasource.swift diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 07599177e..099d76285 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -55,16 +55,14 @@ E496957C2682D2CE001AEB89 /* CommonDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496957B2682D2CE001AEB89 /* CommonDTO.swift */; }; E496957E2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496957D2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift */; }; E49695822682DCEC001AEB89 /* SimpleInfoTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695812682DCEC001AEB89 /* SimpleInfoTableDatasource.swift */; }; - E49695842682DDAE001AEB89 /* SimpleLabelTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695832682DDAE001AEB89 /* SimpleLabelTableDatasource.swift */; }; E49695862682FD95001AEB89 /* SimpleInfoTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695852682FD95001AEB89 /* SimpleInfoTableDelegate.swift */; }; E49695882682FDC9001AEB89 /* CellSelectionTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */; }; E496958C26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */; }; - E496958E26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496958D26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift */; }; E4969590268317C1001AEB89 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496958F268317C1001AEB89 /* User.swift */; }; E4969592268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4969591268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift */; }; - E496959426831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959326831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift */; }; E496959726832693001AEB89 /* IssueTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959626832693001AEB89 /* IssueTableViewDelegate.swift */; }; E496959926832B5A001AEB89 /* NewIssue.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959826832B5A001AEB89 /* NewIssue.swift */; }; + E496959B268334BC001AEB89 /* CommonSimpleInfoTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959A268334BC001AEB89 /* CommonSimpleInfoTableDatasource.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -138,16 +136,14 @@ E496957B2682D2CE001AEB89 /* CommonDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonDTO.swift; sourceTree = ""; }; E496957D2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleLabelTableViewCell.swift; sourceTree = ""; }; E49695812682DCEC001AEB89 /* SimpleInfoTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleInfoTableDatasource.swift; sourceTree = ""; }; - E49695832682DDAE001AEB89 /* SimpleLabelTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleLabelTableDatasource.swift; sourceTree = ""; }; E49695852682FD95001AEB89 /* SimpleInfoTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleInfoTableDelegate.swift; sourceTree = ""; }; E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellSelectionTableDelegate.swift; sourceTree = ""; }; E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleMilestoneTableViewCell.swift; sourceTree = ""; }; - E496958D26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleMilestoneTableDatasource.swift; sourceTree = ""; }; E496958F268317C1001AEB89 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; E4969591268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleAssigneeTableViewCell.swift; sourceTree = ""; }; - E496959326831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleAssigneeTableDatasource.swift; sourceTree = ""; }; E496959626832693001AEB89 /* IssueTableViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTableViewDelegate.swift; sourceTree = ""; }; E496959826832B5A001AEB89 /* NewIssue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewIssue.swift; sourceTree = ""; }; + E496959A268334BC001AEB89 /* CommonSimpleInfoTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonSimpleInfoTableDatasource.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -398,9 +394,7 @@ E49695662680B0B7001AEB89 /* IssueControlViewController.swift */, E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */, E496958A26830B81001AEB89 /* Protocol */, - E49695832682DDAE001AEB89 /* SimpleLabelTableDatasource.swift */, - E496958D26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift */, - E496959326831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift */, + E496959A268334BC001AEB89 /* CommonSimpleInfoTableDatasource.swift */, E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */, ); path = IssueEditing; @@ -635,13 +629,10 @@ FA431FFD267F61150010EA91 /* String.swift in Sources */, FAB2C36C2679F6CC009F879C /* MileStoneLabelView.swift in Sources */, E426DAC72671F6A00069E77D /* LoginError.swift in Sources */, - E496958E26830F28001AEB89 /* SimpleMilestoneTableDatasource.swift in Sources */, - E496959426831AE7001AEB89 /* SimpleAssigneeTableDatasource.swift in Sources */, E43912D626789812003CD344 /* RequestManager.swift in Sources */, E426DAC42671D95D0069E77D /* LoginService.swift in Sources */, E42AD120267093430071B436 /* LabelViewController.swift in Sources */, E43912D826789A83003CD344 /* EndPoint.swift in Sources */, - E49695842682DDAE001AEB89 /* SimpleLabelTableDatasource.swift in Sources */, E426DABE2670EC830069E77D /* SocialLoginManagerDelegate.swift in Sources */, E4969590268317C1001AEB89 /* User.swift in Sources */, E496958C26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift in Sources */, @@ -663,6 +654,7 @@ FAEB30AE266F6A7800C17BE9 /* UIImageExtension.swift in Sources */, E496959726832693001AEB89 /* IssueTableViewDelegate.swift in Sources */, E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */, + E496959B268334BC001AEB89 /* CommonSimpleInfoTableDatasource.swift in Sources */, E42AD100266E52FB0071B436 /* SceneDelegate.swift in Sources */, E43912DA26789E16003CD344 /* Label.swift in Sources */, E496957E2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift in Sources */, diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/AdditionalInfoViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/AdditionalInfoViewController.swift index 470f21b94..113e8242c 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/AdditionalInfoViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/AdditionalInfoViewController.swift @@ -55,7 +55,7 @@ final class AdditionalInfoViewController? private var tableDelegate: SimpleInfoTableDelegate? private var selectedInfo = [Info]() @@ -98,7 +98,7 @@ final class AdditionalInfoViewController, isMultiselectionAllowed: Bool, endpoint: EndPoint) { self.sceneTitle = sceneTitle self.selectedInfo = preSelectedInfos self.tableDatasource = tableDatasource @@ -120,7 +120,7 @@ final class AdditionalInfoViewController: NSObject, SimpleInfoTableDatasource { + + private var infos = [Info]() + private var cellUpdator: CellUpdator? + + func update(with infos: [Info]) { + self.infos = infos + } + + func info(for index: Int) -> Info? { + guard infos.count > index else { return nil } + return infos[index] + } + + func index(for targetInfo: Info) -> Int? { + var targetIndex: Int? + infos.enumerated().forEach { (index, info) in + if info.identifier() == targetInfo.identifier() { + targetIndex = index + } + } + return targetIndex + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return infos.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cellID = InfoCell.reuseID + let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? InfoCell ?? InfoCell() + guard let cellInfo = info(for: indexPath.row), + let cellUpdator = cellUpdator else { return cell } + return cellUpdator(cell, cellInfo) + } + + func setCellUpdator(_ updator: @escaping (InfoCell, Info) -> InfoCell) { + self.cellUpdator = updator + } +} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift index f36d076fd..fd87a9bc2 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift @@ -285,14 +285,17 @@ final class IssueControlViewController: UIViewController { } @objc private func labelInfoTouched(_ sender: UIButton) { + let tableDatasource = CommonSimpleInfoTableDatasource() + tableDatasource.setCellUpdator(SimpleLabelTableViewCell.update) + let labelInfoViewController = AdditionalInfoViewController() - let tableDatasource = SimpleLabelTableDatasource() labelInfoViewController.configure(withTitle: "레이블 선택", preSelectedInfos: selectedLabels ?? [], tableDatasource: tableDatasource, isMultiselectionAllowed: true, endpoint: EndPoint.label) labelInfoViewController.setSaveOperation(updateLabelSelection) + present(labelInfoViewController) } @@ -312,14 +315,17 @@ final class IssueControlViewController: UIViewController { } @objc private func milestoneInfoTouched(_ sender: UIButton) { + let tableDatasource = CommonSimpleInfoTableDatasource() + tableDatasource.setCellUpdator(SimpleMilestoneTableViewCell.update) + let milestoneViewController = AdditionalInfoViewController() - let tableDatasource = SimpleMilestoneTableDatasource() milestoneViewController.configure(withTitle: "마일스톤 선택", preSelectedInfos: selectedMilestone ?? [], tableDatasource: tableDatasource, isMultiselectionAllowed: false, endpoint: EndPoint.milestone) milestoneViewController.setSaveOperation(updateMilestoneSelection) + present(milestoneViewController) } @@ -330,14 +336,17 @@ final class IssueControlViewController: UIViewController { } @objc private func assigneeInfoTouched(_ sender: UIButton) { + let tableDatasource = CommonSimpleInfoTableDatasource() + tableDatasource.setCellUpdator(SimpleAssigneeTableViewCell.update) + let assigneeViewController = AdditionalInfoViewController() - let tableDatasource = SimpleAssigneeTableDatasource() assigneeViewController.configure(withTitle: "담당자 선택", preSelectedInfos: selectedAssignees ?? [], tableDatasource: tableDatasource, isMultiselectionAllowed: true, endpoint: EndPoint.user) assigneeViewController.setSaveOperation(updateAssigneeSelection) + present(assigneeViewController) } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/SimpleInfoTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/SimpleInfoTableDatasource.swift index 3fb73c494..9ede8dc10 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/SimpleInfoTableDatasource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/SimpleInfoTableDatasource.swift @@ -8,7 +8,11 @@ import UIKit protocol SimpleInfoTableDatasource: UITableViewDataSource { - func update(with infos: [Identifiable]) - func info(for index: Int) -> Identifiable? - func index(for info: Identifiable) -> Int? + associatedtype Info + associatedtype InfoCell + typealias CellUpdator = (InfoCell, Info) -> InfoCell + func update(with infos: [Info]) + func info(for index: Int) -> Info? + func index(for info: Info) -> Int? + func setCellUpdator(_ updator: @escaping CellUpdator) } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleAssigneeTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleAssigneeTableDatasource.swift deleted file mode 100644 index 58a276e42..000000000 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleAssigneeTableDatasource.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// SimpleAssigneeTableDatasource.swift -// issue-tracker -// -// Created by Song on 2021/06/23. -// - -import UIKit - -final class SimpleAssigneeTableDatasource: NSObject, SimpleInfoTableDatasource { - - private var assignees = [User]() - - func update(with infos: [Identifiable]) { - guard let assignees = infos as? [User] else { return } - self.assignees = assignees - } - - func info(for index: Int) -> Identifiable? { - guard assignees.count > index else { return nil } - return assignees[index] - } - - func index(for info: Identifiable) -> Int? { - var targetIndex: Int? - assignees.enumerated().forEach { (index, assignee) in - if assignee.identifier() == info.identifier() { - targetIndex = index - } - } - return targetIndex - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return assignees.count - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cellID = SimpleAssigneeTableViewCell.reuseID - let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? SimpleAssigneeTableViewCell ?? SimpleAssigneeTableViewCell() - let cellInfo = assignees[indexPath.row] - cell.configure(with: cellInfo.name, imageUrl: cellInfo.imageUrl) - return cell - } -} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleLabelTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleLabelTableDatasource.swift deleted file mode 100644 index 8eca8f2bc..000000000 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleLabelTableDatasource.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// SimpleLabelTableDatasource.swift -// issue-tracker -// -// Created by Song on 2021/06/23. -// - -import UIKit - -final class SimpleLabelTableDatasource: NSObject, SimpleInfoTableDatasource { - - private var labels = [Label]() - - func update(with infos: [Identifiable]) { - guard let labels = infos as? [Label] else { return } - self.labels = labels - } - - func info(for index: Int) -> Identifiable? { - guard labels.count > index else { return nil } - return labels[index] - } - - func index(for info: Identifiable) -> Int? { - var targetIndex: Int? - labels.enumerated().forEach { (index, label) in - if label.identifier() == info.identifier() { - targetIndex = index - } - } - return targetIndex - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return labels.count - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cellID = SimpleLabelTableViewCell.reuseID - let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? SimpleLabelTableViewCell ?? SimpleLabelTableViewCell() - let cellInfo = labels[indexPath.row] - let hexColorCode = HexColorCode(from: cellInfo.hexColorCode) - cell.configure(with: hexColorCode, title: cellInfo.title) - return cell - } -} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleMilestoneTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleMilestoneTableDatasource.swift deleted file mode 100644 index 7f8f54489..000000000 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/SimpleMilestoneTableDatasource.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// SimpleMilestoneTableDatasource.swift -// issue-tracker -// -// Created by Song on 2021/06/23. -// - -import UIKit - -final class SimpleMilestoneTableDatasource: NSObject, SimpleInfoTableDatasource { - - private var milestones = [MileStone]() - - func update(with infos: [Identifiable]) { - guard let milestones = infos as? [MileStone] else { return } - self.milestones = milestones - } - - func info(for index: Int) -> Identifiable? { - guard milestones.count > index else { return nil } - return milestones[index] - } - - func index(for info: Identifiable) -> Int? { - var targetIndex: Int? - milestones.enumerated().forEach { (index, label) in - if label.identifier() == info.identifier() { - targetIndex = index - } - } - return targetIndex - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return milestones.count - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cellID = SimpleMilestoneTableViewCell.reuseID - let cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? SimpleMilestoneTableViewCell ?? SimpleMilestoneTableViewCell() - let cellInfo = milestones[indexPath.row] - cell.configure(with: cellInfo.title) - return cell - } -} diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleAssigneeTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleAssigneeTableViewCell.swift index 8fdba30f1..16cfdada6 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleAssigneeTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleAssigneeTableViewCell.swift @@ -7,7 +7,7 @@ import UIKit -class SimpleAssigneeTableViewCell: UITableViewCell { +final class SimpleAssigneeTableViewCell: UITableViewCell { private lazy var titleLabel = UILabel() @@ -19,7 +19,7 @@ class SimpleAssigneeTableViewCell: UITableViewCell { }() private let spacing: CGFloat = 15 - private let imageManager = ImageLoadManager() + static let imageManager = ImageLoadManager() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) @@ -64,11 +64,15 @@ class SimpleAssigneeTableViewCell: UITableViewCell { ]) } - func configure(with title: String, imageUrl: String) { - titleLabel.text = title - imageManager.load(from: imageUrl) { [weak self] cachePath in - self?.profileImageView.image = UIImage(contentsOfFile: cachePath) + static func update(cell: SimpleAssigneeTableViewCell, with user: User) -> SimpleAssigneeTableViewCell { + let title = user.name + cell.titleLabel.text = title + + let imageUrl = user.imageUrl + imageManager.load(from: imageUrl) { cachePath in + cell.profileImageView.image = UIImage(contentsOfFile: cachePath) } + return cell } override func setSelected(_ selected: Bool, animated: Bool) { diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleLabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleLabelTableViewCell.swift index 27f51475b..3c83e595e 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleLabelTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleLabelTableViewCell.swift @@ -7,7 +7,7 @@ import UIKit -class SimpleLabelTableViewCell: UITableViewCell { +final class SimpleLabelTableViewCell: UITableViewCell { private lazy var labelView = LabelView() private let spacing: CGFloat = 15 @@ -41,8 +41,11 @@ class SimpleLabelTableViewCell: UITableViewCell { ]) } - func configure(with hexColorCode: HexColorCode, title: String) { - labelView.configure(with: hexColorCode, title) + static func update(cell: SimpleLabelTableViewCell, with label: Label) -> SimpleLabelTableViewCell { + let hexColorCode = HexColorCode(from: label.hexColorCode) + let title = label.title + cell.labelView.configure(with: hexColorCode, title) + return cell } override func setSelected(_ selected: Bool, animated: Bool) { diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleMilestoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleMilestoneTableViewCell.swift index 92e025d49..005672dbc 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleMilestoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleMilestoneTableViewCell.swift @@ -7,7 +7,7 @@ import UIKit -class SimpleMilestoneTableViewCell: UITableViewCell { +final class SimpleMilestoneTableViewCell: UITableViewCell { private lazy var titleLabel = UILabel() private let spacing: CGFloat = 15 @@ -43,8 +43,10 @@ class SimpleMilestoneTableViewCell: UITableViewCell { ]) } - func configure(with title: String) { - titleLabel.text = title + static func update(cell: SimpleMilestoneTableViewCell, with milestone: MileStone) -> SimpleMilestoneTableViewCell { + let title = milestone.title + cell.titleLabel.text = title + return cell } override func setSelected(_ selected: Bool, animated: Bool) { From 404fd0b971b68b565eb71b8460becd9609f8b64b Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 23 Jun 2021 18:44:23 +0900 Subject: [PATCH 91/91] =?UTF-8?q?chore:=20[#82]=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issue-tracker.xcodeproj/project.pbxproj | 56 +++++++++---------- .../AdditionalInfoViewController.swift | 6 +- .../CellSelectionTableDelegate.swift | 2 +- ....swift => CommonInfoTableDatasource.swift} | 4 +- ...er.swift => IssueEditViewController.swift} | 24 ++++---- .../IssueEditing/IssueViewController.swift | 2 +- ...ft => AdditionalInfoTableDatasource.swift} | 2 +- ...wift => AdditionalInfoTableDelegate.swift} | 2 +- ....swift => AssigneeInfoTableViewCell.swift} | 4 +- ...ell.swift => LabelInfoTableViewCell.swift} | 4 +- ...swift => MilestoneInfoTableViewCell.swift} | 4 +- 11 files changed, 55 insertions(+), 55 deletions(-) rename iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/{CommonSimpleInfoTableDatasource.swift => CommonInfoTableDatasource.swift} (88%) rename iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/{IssueControlViewController.swift => IssueEditViewController.swift} (94%) rename iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/{SimpleInfoTableDatasource.swift => AdditionalInfoTableDatasource.swift} (86%) rename iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/{SimpleInfoTableDelegate.swift => AdditionalInfoTableDelegate.swift} (84%) rename iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/{SimpleAssigneeTableViewCell.swift => AssigneeInfoTableViewCell.swift} (93%) rename iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/{SimpleLabelTableViewCell.swift => LabelInfoTableViewCell.swift} (89%) rename iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/{SimpleMilestoneTableViewCell.swift => MilestoneInfoTableViewCell.swift} (88%) diff --git a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj index 099d76285..d0ef93a9f 100644 --- a/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj +++ b/iOS/issue-tracker/issue-tracker.xcodeproj/project.pbxproj @@ -47,22 +47,22 @@ E43912F6267CAE01003CD344 /* TopMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F5267CAE01003CD344 /* TopMenuView.swift */; }; E43912F8267CB3D7003CD344 /* MultipleLineInputStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43912F7267CB3D7003CD344 /* MultipleLineInputStackView.swift */; }; E46E11242677391B005375A1 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E46E11232677391B005375A1 /* LabelTableViewCell.swift */; }; - E49695672680B0B7001AEB89 /* IssueControlViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695662680B0B7001AEB89 /* IssueControlViewController.swift */; }; + E49695672680B0B7001AEB89 /* IssueEditViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695662680B0B7001AEB89 /* IssueEditViewController.swift */; }; E496956E2681905A001AEB89 /* IssueInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496956D2681905A001AEB89 /* IssueInfoView.swift */; }; E49695762681E7B7001AEB89 /* Down in Frameworks */ = {isa = PBXBuildFile; productRef = E49695752681E7B7001AEB89 /* Down */; }; E49695782682C4B0001AEB89 /* AdditionalInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */; }; E496957A2682CB33001AEB89 /* UITableCellExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695792682CB33001AEB89 /* UITableCellExtension.swift */; }; E496957C2682D2CE001AEB89 /* CommonDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496957B2682D2CE001AEB89 /* CommonDTO.swift */; }; - E496957E2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496957D2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift */; }; - E49695822682DCEC001AEB89 /* SimpleInfoTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695812682DCEC001AEB89 /* SimpleInfoTableDatasource.swift */; }; - E49695862682FD95001AEB89 /* SimpleInfoTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695852682FD95001AEB89 /* SimpleInfoTableDelegate.swift */; }; + E496957E2682D8D1001AEB89 /* LabelInfoTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496957D2682D8D1001AEB89 /* LabelInfoTableViewCell.swift */; }; + E49695822682DCEC001AEB89 /* AdditionalInfoTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695812682DCEC001AEB89 /* AdditionalInfoTableDatasource.swift */; }; + E49695862682FD95001AEB89 /* AdditionalInfoTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695852682FD95001AEB89 /* AdditionalInfoTableDelegate.swift */; }; E49695882682FDC9001AEB89 /* CellSelectionTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */; }; - E496958C26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */; }; + E496958C26830DCE001AEB89 /* MilestoneInfoTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496958B26830DCE001AEB89 /* MilestoneInfoTableViewCell.swift */; }; E4969590268317C1001AEB89 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496958F268317C1001AEB89 /* User.swift */; }; - E4969592268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4969591268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift */; }; + E4969592268318A4001AEB89 /* AssigneeInfoTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4969591268318A4001AEB89 /* AssigneeInfoTableViewCell.swift */; }; E496959726832693001AEB89 /* IssueTableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959626832693001AEB89 /* IssueTableViewDelegate.swift */; }; E496959926832B5A001AEB89 /* NewIssue.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959826832B5A001AEB89 /* NewIssue.swift */; }; - E496959B268334BC001AEB89 /* CommonSimpleInfoTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959A268334BC001AEB89 /* CommonSimpleInfoTableDatasource.swift */; }; + E496959B268334BC001AEB89 /* CommonInfoTableDatasource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E496959A268334BC001AEB89 /* CommonInfoTableDatasource.swift */; }; E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */; }; E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */; }; E4F7E8EC26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */; }; @@ -129,21 +129,21 @@ E43912F5267CAE01003CD344 /* TopMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopMenuView.swift; sourceTree = ""; }; E43912F7267CB3D7003CD344 /* MultipleLineInputStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipleLineInputStackView.swift; sourceTree = ""; }; E46E11232677391B005375A1 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; - E49695662680B0B7001AEB89 /* IssueControlViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueControlViewController.swift; sourceTree = ""; }; + E49695662680B0B7001AEB89 /* IssueEditViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueEditViewController.swift; sourceTree = ""; }; E496956D2681905A001AEB89 /* IssueInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueInfoView.swift; sourceTree = ""; }; E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdditionalInfoViewController.swift; sourceTree = ""; }; E49695792682CB33001AEB89 /* UITableCellExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableCellExtension.swift; sourceTree = ""; }; E496957B2682D2CE001AEB89 /* CommonDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonDTO.swift; sourceTree = ""; }; - E496957D2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleLabelTableViewCell.swift; sourceTree = ""; }; - E49695812682DCEC001AEB89 /* SimpleInfoTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleInfoTableDatasource.swift; sourceTree = ""; }; - E49695852682FD95001AEB89 /* SimpleInfoTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleInfoTableDelegate.swift; sourceTree = ""; }; + E496957D2682D8D1001AEB89 /* LabelInfoTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelInfoTableViewCell.swift; sourceTree = ""; }; + E49695812682DCEC001AEB89 /* AdditionalInfoTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdditionalInfoTableDatasource.swift; sourceTree = ""; }; + E49695852682FD95001AEB89 /* AdditionalInfoTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdditionalInfoTableDelegate.swift; sourceTree = ""; }; E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellSelectionTableDelegate.swift; sourceTree = ""; }; - E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleMilestoneTableViewCell.swift; sourceTree = ""; }; + E496958B26830DCE001AEB89 /* MilestoneInfoTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MilestoneInfoTableViewCell.swift; sourceTree = ""; }; E496958F268317C1001AEB89 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; - E4969591268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleAssigneeTableViewCell.swift; sourceTree = ""; }; + E4969591268318A4001AEB89 /* AssigneeInfoTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssigneeInfoTableViewCell.swift; sourceTree = ""; }; E496959626832693001AEB89 /* IssueTableViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTableViewDelegate.swift; sourceTree = ""; }; E496959826832B5A001AEB89 /* NewIssue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewIssue.swift; sourceTree = ""; }; - E496959A268334BC001AEB89 /* CommonSimpleInfoTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonSimpleInfoTableDatasource.swift; sourceTree = ""; }; + E496959A268334BC001AEB89 /* CommonInfoTableDatasource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonInfoTableDatasource.swift; sourceTree = ""; }; E4F7E8E726732B6300CE51C2 /* TabBarChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarChildInfo.swift; sourceTree = ""; }; E4F7E8E92673394300CE51C2 /* ImageLoadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoadManager.swift; sourceTree = ""; }; E4F7E8EB26733A9700CE51C2 /* IssueTrackerTabBarCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueTrackerTabBarCreator.swift; sourceTree = ""; }; @@ -391,10 +391,10 @@ E496956A2680B3FE001AEB89 /* IssueEditing */ = { isa = PBXGroup; children = ( - E49695662680B0B7001AEB89 /* IssueControlViewController.swift */, + E49695662680B0B7001AEB89 /* IssueEditViewController.swift */, E49695772682C4B0001AEB89 /* AdditionalInfoViewController.swift */, E496958A26830B81001AEB89 /* Protocol */, - E496959A268334BC001AEB89 /* CommonSimpleInfoTableDatasource.swift */, + E496959A268334BC001AEB89 /* CommonInfoTableDatasource.swift */, E49695872682FDC9001AEB89 /* CellSelectionTableDelegate.swift */, ); path = IssueEditing; @@ -404,9 +404,9 @@ isa = PBXGroup; children = ( E496956D2681905A001AEB89 /* IssueInfoView.swift */, - E496957D2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift */, - E496958B26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift */, - E4969591268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift */, + E496957D2682D8D1001AEB89 /* LabelInfoTableViewCell.swift */, + E496958B26830DCE001AEB89 /* MilestoneInfoTableViewCell.swift */, + E4969591268318A4001AEB89 /* AssigneeInfoTableViewCell.swift */, ); path = IssueEditing; sourceTree = ""; @@ -414,8 +414,8 @@ E496958A26830B81001AEB89 /* Protocol */ = { isa = PBXGroup; children = ( - E49695812682DCEC001AEB89 /* SimpleInfoTableDatasource.swift */, - E49695852682FD95001AEB89 /* SimpleInfoTableDelegate.swift */, + E49695812682DCEC001AEB89 /* AdditionalInfoTableDatasource.swift */, + E49695852682FD95001AEB89 /* AdditionalInfoTableDelegate.swift */, ); path = Protocol; sourceTree = ""; @@ -593,12 +593,12 @@ FAF927AB2680DB1C0017F8DE /* IssueTableViewDataSource.swift in Sources */, E426DAD126730DC50069E77D /* OAuthResponseDTO.swift in Sources */, E496957C2682D2CE001AEB89 /* CommonDTO.swift in Sources */, - E49695822682DCEC001AEB89 /* SimpleInfoTableDatasource.swift in Sources */, + E49695822682DCEC001AEB89 /* AdditionalInfoTableDatasource.swift in Sources */, FAFD11B1268078F80064AED4 /* CommonTableDelegate.swift in Sources */, E43912E8267A1FE5003CD344 /* NewLabelDTO.swift in Sources */, FAEB30B42670B76200C17BE9 /* NetworkManager.swift in Sources */, E426DABC2670EC5E0069E77D /* LoginInfo.swift in Sources */, - E49695672680B0B7001AEB89 /* IssueControlViewController.swift in Sources */, + E49695672680B0B7001AEB89 /* IssueEditViewController.swift in Sources */, E43912CE26777310003CD344 /* HexColorConverter.swift in Sources */, FA431FFB267F3B680010EA91 /* NewMileStoneDTO.swift in Sources */, E42AD1182670886F0071B436 /* IssueTrackerTabBarController.swift in Sources */, @@ -635,13 +635,13 @@ E43912D826789A83003CD344 /* EndPoint.swift in Sources */, E426DABE2670EC830069E77D /* SocialLoginManagerDelegate.swift in Sources */, E4969590268317C1001AEB89 /* User.swift in Sources */, - E496958C26830DCE001AEB89 /* SimpleMilestoneTableViewCell.swift in Sources */, + E496958C26830DCE001AEB89 /* MilestoneInfoTableViewCell.swift in Sources */, FA733A30267C3E9E005A40C8 /* MilestoneTableViewDataSource.swift in Sources */, E49695782682C4B0001AEB89 /* AdditionalInfoViewController.swift in Sources */, E42AD0FE266E52FB0071B436 /* AppDelegate.swift in Sources */, FAF927AF2681DA810017F8DE /* Issue.swift in Sources */, E43912EE267C3C0E003CD344 /* CellAction.swift in Sources */, - E49695862682FD95001AEB89 /* SimpleInfoTableDelegate.swift in Sources */, + E49695862682FD95001AEB89 /* AdditionalInfoTableDelegate.swift in Sources */, E4F7E8E826732B6300CE51C2 /* TabBarChildInfo.swift in Sources */, FAC6D88B2671D5A100A9E5F9 /* GithubAuthorizationManager.swift in Sources */, E4F7E8EA2673394300CE51C2 /* ImageLoadManager.swift in Sources */, @@ -649,15 +649,15 @@ E43912F4267CAA8D003CD344 /* UITextFieldExtension.swift in Sources */, E49695882682FDC9001AEB89 /* CellSelectionTableDelegate.swift in Sources */, E43912DC2678A737003CD344 /* JWT.swift in Sources */, - E4969592268318A4001AEB89 /* SimpleAssigneeTableViewCell.swift in Sources */, + E4969592268318A4001AEB89 /* AssigneeInfoTableViewCell.swift in Sources */, E426DABA2670EC2D0069E77D /* AppleAuthorizationManager.swift in Sources */, FAEB30AE266F6A7800C17BE9 /* UIImageExtension.swift in Sources */, E496959726832693001AEB89 /* IssueTableViewDelegate.swift in Sources */, E42AD12626709C010071B436 /* UIViewControllerExtension.swift in Sources */, - E496959B268334BC001AEB89 /* CommonSimpleInfoTableDatasource.swift in Sources */, + E496959B268334BC001AEB89 /* CommonInfoTableDatasource.swift in Sources */, E42AD100266E52FB0071B436 /* SceneDelegate.swift in Sources */, E43912DA26789E16003CD344 /* Label.swift in Sources */, - E496957E2682D8D1001AEB89 /* SimpleLabelTableViewCell.swift in Sources */, + E496957E2682D8D1001AEB89 /* LabelInfoTableViewCell.swift in Sources */, E426DAC92671F7760069E77D /* AlertFactory.swift in Sources */, FAF927AD2680DCCA0017F8DE /* IssueTableViewCell.swift in Sources */, ); diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/AdditionalInfoViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/AdditionalInfoViewController.swift index 113e8242c..e5ea97caf 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/AdditionalInfoViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/AdditionalInfoViewController.swift @@ -55,8 +55,8 @@ final class AdditionalInfoViewController? - private var tableDelegate: SimpleInfoTableDelegate? + private var tableDatasource: CommonInfoTableDatasource? + private var tableDelegate: AdditionalInfoTableDelegate? private var selectedInfo = [Info]() private var saveOperation: (([Info]) -> Void)? @@ -98,7 +98,7 @@ final class AdditionalInfoViewController, isMultiselectionAllowed: Bool, endpoint: EndPoint) { + func configure(withTitle sceneTitle: String, preSelectedInfos: [Info], tableDatasource: CommonInfoTableDatasource, isMultiselectionAllowed: Bool, endpoint: EndPoint) { self.sceneTitle = sceneTitle self.selectedInfo = preSelectedInfos self.tableDatasource = tableDatasource diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/CellSelectionTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/CellSelectionTableDelegate.swift index 531c1f7cd..b1b419aa6 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/CellSelectionTableDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/CellSelectionTableDelegate.swift @@ -7,7 +7,7 @@ import UIKit -final class CellSelectionTableDelegate: NSObject, SimpleInfoTableDelegate { +final class CellSelectionTableDelegate: NSObject, AdditionalInfoTableDelegate { private var cellSelectionHandler: CellSelectionHandler? diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/CommonSimpleInfoTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/CommonInfoTableDatasource.swift similarity index 88% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/CommonSimpleInfoTableDatasource.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/CommonInfoTableDatasource.swift index a7e760e15..aa0aa243b 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/CommonSimpleInfoTableDatasource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/CommonInfoTableDatasource.swift @@ -7,8 +7,8 @@ import UIKit -final class CommonSimpleInfoTableDatasource: NSObject, SimpleInfoTableDatasource { +final class CommonInfoTableDatasource: NSObject, AdditionalInfoTableDatasource { private var infos = [Info]() private var cellUpdator: CellUpdator? diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueEditViewController.swift similarity index 94% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueEditViewController.swift index fd87a9bc2..42aecdad8 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueControlViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueEditViewController.swift @@ -8,7 +8,7 @@ import UIKit import Down -final class IssueControlViewController: UIViewController { +final class IssueEditViewController: UIViewController { private lazy var cancelButton: ImageBarButton = { let button = ImageBarButton() @@ -285,10 +285,10 @@ final class IssueControlViewController: UIViewController { } @objc private func labelInfoTouched(_ sender: UIButton) { - let tableDatasource = CommonSimpleInfoTableDatasource() - tableDatasource.setCellUpdator(SimpleLabelTableViewCell.update) + let tableDatasource = CommonInfoTableDatasource() + tableDatasource.setCellUpdator(LabelInfoTableViewCell.update) - let labelInfoViewController = AdditionalInfoViewController() + let labelInfoViewController = AdditionalInfoViewController() labelInfoViewController.configure(withTitle: "레이블 선택", preSelectedInfos: selectedLabels ?? [], tableDatasource: tableDatasource, @@ -315,10 +315,10 @@ final class IssueControlViewController: UIViewController { } @objc private func milestoneInfoTouched(_ sender: UIButton) { - let tableDatasource = CommonSimpleInfoTableDatasource() - tableDatasource.setCellUpdator(SimpleMilestoneTableViewCell.update) + let tableDatasource = CommonInfoTableDatasource() + tableDatasource.setCellUpdator(MilestoneInfoTableViewCell.update) - let milestoneViewController = AdditionalInfoViewController() + let milestoneViewController = AdditionalInfoViewController() milestoneViewController.configure(withTitle: "마일스톤 선택", preSelectedInfos: selectedMilestone ?? [], tableDatasource: tableDatasource, @@ -336,10 +336,10 @@ final class IssueControlViewController: UIViewController { } @objc private func assigneeInfoTouched(_ sender: UIButton) { - let tableDatasource = CommonSimpleInfoTableDatasource() - tableDatasource.setCellUpdator(SimpleAssigneeTableViewCell.update) + let tableDatasource = CommonInfoTableDatasource() + tableDatasource.setCellUpdator(AssigneeInfoTableViewCell.update) - let assigneeViewController = AdditionalInfoViewController() + let assigneeViewController = AdditionalInfoViewController() assigneeViewController.configure(withTitle: "담당자 선택", preSelectedInfos: selectedAssignees ?? [], tableDatasource: tableDatasource, @@ -360,7 +360,7 @@ final class IssueControlViewController: UIViewController { } } -extension IssueControlViewController: UITextFieldDelegate { +extension IssueEditViewController: UITextFieldDelegate { func textFieldDidChangeSelection(_ textField: UITextField) { changeSaveButtonEnableStatus(baseOn: textField) } @@ -372,7 +372,7 @@ extension IssueControlViewController: UITextFieldDelegate { } } -extension IssueControlViewController: UITextViewDelegate { +extension IssueEditViewController: UITextViewDelegate { func textViewDidBeginEditing(_ textView: UITextView) { if textView.textColor == .lightGray { textView.textColor = .black diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueViewController.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueViewController.swift index afc1c9c1f..9294d48cb 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueViewController.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/IssueViewController.swift @@ -131,7 +131,7 @@ final class IssueViewController: UIViewController { } @objc func addNewIssue(_ sender: UIButton) { - let nextViewController = IssueControlViewController() + let nextViewController = IssueEditViewController() nextViewController.setSaveOperation(postIssue) navigationController?.pushViewController(nextViewController, animated: false) } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/SimpleInfoTableDatasource.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/AdditionalInfoTableDatasource.swift similarity index 86% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/SimpleInfoTableDatasource.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/AdditionalInfoTableDatasource.swift index 9ede8dc10..c7446a118 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/SimpleInfoTableDatasource.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/AdditionalInfoTableDatasource.swift @@ -7,7 +7,7 @@ import UIKit -protocol SimpleInfoTableDatasource: UITableViewDataSource { +protocol AdditionalInfoTableDatasource: UITableViewDataSource { associatedtype Info associatedtype InfoCell typealias CellUpdator = (InfoCell, Info) -> InfoCell diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/SimpleInfoTableDelegate.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/AdditionalInfoTableDelegate.swift similarity index 84% rename from iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/SimpleInfoTableDelegate.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/AdditionalInfoTableDelegate.swift index 384b482a5..bc41e523a 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/SimpleInfoTableDelegate.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/Controller/IssueEditing/Protocol/AdditionalInfoTableDelegate.swift @@ -12,7 +12,7 @@ enum CellSelection { case deSelected } -protocol SimpleInfoTableDelegate: UITableViewDelegate { +protocol AdditionalInfoTableDelegate: UITableViewDelegate { typealias CellSelectionHandler = ((Int, CellSelection) -> Void) func setCellSelectionHandler(_ handler: @escaping CellSelectionHandler) } diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleAssigneeTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/AssigneeInfoTableViewCell.swift similarity index 93% rename from iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleAssigneeTableViewCell.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/AssigneeInfoTableViewCell.swift index 16cfdada6..5124c13df 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleAssigneeTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/AssigneeInfoTableViewCell.swift @@ -7,7 +7,7 @@ import UIKit -final class SimpleAssigneeTableViewCell: UITableViewCell { +final class AssigneeInfoTableViewCell: UITableViewCell { private lazy var titleLabel = UILabel() @@ -64,7 +64,7 @@ final class SimpleAssigneeTableViewCell: UITableViewCell { ]) } - static func update(cell: SimpleAssigneeTableViewCell, with user: User) -> SimpleAssigneeTableViewCell { + static func update(cell: AssigneeInfoTableViewCell, with user: User) -> AssigneeInfoTableViewCell { let title = user.name cell.titleLabel.text = title diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleLabelTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/LabelInfoTableViewCell.swift similarity index 89% rename from iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleLabelTableViewCell.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/LabelInfoTableViewCell.swift index 3c83e595e..2ac2b5031 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleLabelTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/LabelInfoTableViewCell.swift @@ -7,7 +7,7 @@ import UIKit -final class SimpleLabelTableViewCell: UITableViewCell { +final class LabelInfoTableViewCell: UITableViewCell { private lazy var labelView = LabelView() private let spacing: CGFloat = 15 @@ -41,7 +41,7 @@ final class SimpleLabelTableViewCell: UITableViewCell { ]) } - static func update(cell: SimpleLabelTableViewCell, with label: Label) -> SimpleLabelTableViewCell { + static func update(cell: LabelInfoTableViewCell, with label: Label) -> LabelInfoTableViewCell { let hexColorCode = HexColorCode(from: label.hexColorCode) let title = label.title cell.labelView.configure(with: hexColorCode, title) diff --git a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleMilestoneTableViewCell.swift b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/MilestoneInfoTableViewCell.swift similarity index 88% rename from iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleMilestoneTableViewCell.swift rename to iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/MilestoneInfoTableViewCell.swift index 005672dbc..d1ef92e2f 100644 --- a/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/SimpleMilestoneTableViewCell.swift +++ b/iOS/issue-tracker/issue-tracker/Main/Issue/View/IssueEditing/MilestoneInfoTableViewCell.swift @@ -7,7 +7,7 @@ import UIKit -final class SimpleMilestoneTableViewCell: UITableViewCell { +final class MilestoneInfoTableViewCell: UITableViewCell { private lazy var titleLabel = UILabel() private let spacing: CGFloat = 15 @@ -43,7 +43,7 @@ final class SimpleMilestoneTableViewCell: UITableViewCell { ]) } - static func update(cell: SimpleMilestoneTableViewCell, with milestone: MileStone) -> SimpleMilestoneTableViewCell { + static func update(cell: MilestoneInfoTableViewCell, with milestone: MileStone) -> MilestoneInfoTableViewCell { let title = milestone.title cell.titleLabel.text = title return cell