-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #406 from pennlabs/development
Merge for 6.6.3
- Loading branch information
Showing
49 changed files
with
817 additions
and
793 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
23 changes: 23 additions & 0 deletions
23
PennMobile/Assets.xcassets/More Tab Icons/Event.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"filename" : "Event@1x.png", | ||
"idiom" : "universal", | ||
"scale" : "1x" | ||
}, | ||
{ | ||
"filename" : "Event@2x.png", | ||
"idiom" : "universal", | ||
"scale" : "2x" | ||
}, | ||
{ | ||
"filename" : "Event@3x.png", | ||
"idiom" : "universal", | ||
"scale" : "3x" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+8.64 KB
PennMobile/Assets.xcassets/More Tab Icons/Event.imageset/Event@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+11.3 KB
PennMobile/Assets.xcassets/More Tab Icons/Event.imageset/Event@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// | ||
// EventsAPI.swift | ||
// PennMobile | ||
// | ||
// Created by Samantha Su on 10/1/21. | ||
// Copyright © 2021 PennLabs. All rights reserved. | ||
// | ||
|
||
import SwiftyJSON | ||
import Foundation | ||
|
||
class EventsAPI: Requestable { | ||
static let instance = EventsAPI() | ||
|
||
let eventsUrl = "https://penntoday.upenn.edu/events-feed?_format=json" | ||
|
||
func fetchEvents(_ completion: @escaping (_ result: Result<[PennEvents], NetworkingError>) -> Void) { | ||
getRequestData(url: eventsUrl) { (data, error, statusCode) in | ||
if statusCode == nil { | ||
return completion(.failure(.noInternet)) | ||
} | ||
|
||
if statusCode != 200 { | ||
return completion(.failure(.serverError)) | ||
} | ||
|
||
guard let data = data else { return completion(.failure(.other)) } | ||
|
||
let decoder = JSONDecoder() | ||
|
||
let formatter = DateFormatter() | ||
formatter.locale = Locale(identifier: "en_US_POSIX") | ||
formatter.timeZone = TimeZone(abbreviation: "EST") | ||
formatter.dateFormat = "MM/dd/yyyy" | ||
|
||
decoder.dateDecodingStrategy = .formatted(formatter) | ||
|
||
if let events = try? decoder.decode([PennEvents].self, from: data){ | ||
self.saveToCache(events) | ||
completion(.success(events)) | ||
} else { | ||
completion(.failure(.serverError)) | ||
} | ||
} | ||
} | ||
|
||
// MARK: - Cache Methods | ||
func saveToCache(_ response: [PennEvents]) { | ||
Storage.store(response, to: .caches, as: PennEvents.directory) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// | ||
// PennEvents.swift | ||
// PennMobile | ||
// | ||
// Created by Samantha Su on 10/1/21. | ||
// Copyright © 2021 PennLabs. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
struct PennEvents: Codable { | ||
static let directory = "events.json" | ||
|
||
let id: String | ||
let title: String | ||
let body: String | ||
let image: String | ||
let location: StringOrBool | ||
let category: String | ||
let path: String | ||
let start: Date? | ||
let end: Date? | ||
let starttime: String | ||
let endtime: String | ||
let allday: String | ||
var media_image: String | ||
let shortdate: String | ||
|
||
var isAllDay: Bool { | ||
return allday == "All day" | ||
} | ||
} | ||
|
||
struct StringOrBool: Codable{ | ||
var value: String? | ||
init(from decoder: Decoder) throws { | ||
if let string = try? String(from: decoder) { | ||
value = string | ||
return | ||
} | ||
value = nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// | ||
// EventsTableViewCell.swift | ||
// PennMobile | ||
// | ||
// Created by Samantha Su on 10/1/21. | ||
// Copyright © 2021 PennLabs. All rights reserved. | ||
// | ||
|
||
import UIKit | ||
import Kingfisher | ||
import SwiftSoup | ||
|
||
class PennEventsTableViewCell: UITableViewCell { | ||
|
||
lazy var imageExistsConstraint = eventImageView.widthAnchor.constraint(equalToConstant:120) | ||
lazy var imageMissingConstraint = eventImageView.widthAnchor.constraint(equalToConstant:0) | ||
var isExpanded = false | ||
|
||
var pennEvent: PennEvents? { | ||
didSet { | ||
guard let event = pennEvent else {return} | ||
if event.media_image == "" { | ||
imageExistsConstraint.isActive = false | ||
imageMissingConstraint.isActive = true | ||
} else { | ||
let imageString = "https://penntoday.upenn.edu" + (event.media_image.slice(from: "<img src=\"", to: "\n") ?? "").trimmingCharacters(in: .whitespaces) | ||
eventImageView.kf.setImage(with: URL(string: imageString)) | ||
imageExistsConstraint.isActive = true | ||
imageMissingConstraint.isActive = false | ||
} | ||
titleLabel.text = event.shortdate + ": " + event.title | ||
if let doc: Document = try? SwiftSoup.parse(event.body), let text = try? doc.text() { | ||
bodyLabel.text = text | ||
} | ||
} | ||
} | ||
|
||
// MARK: - Views | ||
|
||
let containerView:UIView = { | ||
let view = UIView() | ||
view.translatesAutoresizingMaskIntoConstraints = false | ||
view.clipsToBounds = true // this will make sure its children do not go out of the boundary | ||
return view | ||
}() | ||
|
||
let eventImageView:UIImageView = { | ||
let img = UIImageView() | ||
img.contentMode = .scaleAspectFill // image will never be strecthed vertially or horizontally | ||
img.translatesAutoresizingMaskIntoConstraints = false // enable autolayout | ||
img.layer.cornerRadius = 7 | ||
img.clipsToBounds = true | ||
return img | ||
}() | ||
|
||
let titleLabel:UILabel = { | ||
var view = UILabel() | ||
view.backgroundColor = .clear | ||
view.numberOfLines = 0 | ||
|
||
view.textColor = UIColor(red: 0.122, green: 0.122, blue: 0.122, alpha: 1) | ||
view.font = UIFont(name: "SFProText-Regular", size: 30) | ||
view.translatesAutoresizingMaskIntoConstraints = false | ||
return view | ||
}() | ||
|
||
let bodyLabel:UILabel = { | ||
var view = UILabel() | ||
view.backgroundColor = .clear | ||
view.font = UIFont(name: "Helvetica", size: 12) | ||
view.textColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1) | ||
view.numberOfLines = 3 | ||
view.translatesAutoresizingMaskIntoConstraints = false | ||
return view | ||
}() | ||
|
||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { | ||
super.init(style: style, reuseIdentifier: reuseIdentifier) | ||
|
||
containerView.addSubview(titleLabel) | ||
containerView.addSubview(bodyLabel) | ||
self.contentView.addSubview(containerView) | ||
self.contentView.addSubview(eventImageView) | ||
|
||
containerView.leadingAnchor.constraint(equalTo:self.contentView.leadingAnchor, constant:10).isActive = true | ||
containerView.centerYAnchor.constraint(equalTo:self.contentView.centerYAnchor).isActive = true | ||
containerView.bottomAnchor.constraint(equalTo:self.contentView.bottomAnchor, constant:-10).isActive = true | ||
|
||
eventImageView.centerYAnchor.constraint(equalTo:self.contentView.centerYAnchor).isActive = true | ||
eventImageView.leadingAnchor.constraint(equalTo:containerView.trailingAnchor, constant:10).isActive = true | ||
eventImageView.trailingAnchor.constraint(equalTo:self.contentView.trailingAnchor, constant:-10).isActive = true | ||
eventImageView.heightAnchor.constraint(equalToConstant:80).isActive = true | ||
|
||
titleLabel.topAnchor.constraint(equalTo:containerView.topAnchor, constant:5).isActive = true | ||
titleLabel.trailingAnchor.constraint(equalTo:containerView.trailingAnchor, constant:-10).isActive = true | ||
titleLabel.leadingAnchor.constraint(equalTo:containerView.leadingAnchor, constant:10).isActive = true | ||
|
||
bodyLabel.topAnchor.constraint(equalTo:titleLabel.bottomAnchor, constant:0).isActive = true | ||
bodyLabel.bottomAnchor.constraint(equalTo:containerView.bottomAnchor, constant:-5).isActive = true | ||
bodyLabel.trailingAnchor.constraint(equalTo:containerView.trailingAnchor, constant:-10).isActive = true | ||
bodyLabel.leadingAnchor.constraint(equalTo:containerView.leadingAnchor, constant:10).isActive = true | ||
} | ||
|
||
required init?(coder aDecoder: NSCoder) { | ||
super.init(coder: aDecoder) | ||
} | ||
|
||
} |
Oops, something went wrong.