Skip to content

Commit

Permalink
Add daily reports and force view update
Browse files Browse the repository at this point in the history
  • Loading branch information
dz0ny committed Dec 29, 2021
1 parent 32d9643 commit bb61c4d
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 35 deletions.
8 changes: 8 additions & 0 deletions Work Hours/Extensions/Date.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ extension Date {
YearMonthFormatter.timeZone = TimeZone(secondsFromGMT: 0)
return YearMonthFormatter
}()

static let HourMinutesFormatter: DateFormatter = {
let YearMonthFormatter = DateFormatter()
YearMonthFormatter.locale = Locale(identifier: "en_US_POSIX")
YearMonthFormatter.dateFormat = "HH:mm"
YearMonthFormatter.timeZone = TimeZone(secondsFromGMT: 0)
return YearMonthFormatter
}()
}

extension TimeInterval {
Expand Down
56 changes: 35 additions & 21 deletions Work Hours/ReportsGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,23 @@ struct Report {

static func fromData(_ data: [String: Int]) -> [Report] {
var reports = [Report]()
for (ts, duration) in data {
for (timestamp, duration) in data {
// skip if less than a minute
if duration < 60 {
continue
}
reports.append(Report(timestamp: ts, amount: TimeInterval.hoursAndMinutes(duration)))
reports.append(Report(timestamp: timestamp, amount: TimeInterval.hoursAndMinutes(duration)))
}
return reports
return reports.sorted(by: { $0.timestamp < $1.timestamp })
}
}

struct Event {
let startTimestamp: Date
let endTimestamp: Date

var elapsedSeconds: Int {
Int(endTimestamp.timeIntervalSince(startTimestamp))
}
}

Expand Down Expand Up @@ -88,21 +97,38 @@ enum Events {
return nil
}

static func generateReport(formatter: DateFormatter) -> [Report]? {
static func generateReport(events: [Event], formatter: DateFormatter) -> [Report]? {
os_log("Start, generateReport")
var data: [String: Int] = [:]
for event in events {
let key = formatter.string(from: event.startTimestamp)
os_log("Elapsed %s, %s > %d", event.startTimestamp.debugDescription, event.endTimestamp.debugDescription, event.elapsedSeconds)
if let val = data[key] {
data[key] = event.elapsedSeconds + val
} else {
data[key] = event.elapsedSeconds
}
}
return Report.fromData(data)
}

static func getEvents() -> [Event]? {
os_log("Start, getEvents")

var events = [Event]()

guard let logFile = logFile else {
return nil
}
if FileManager.default.fileExists(atPath: logFile.path) {
guard let csvFile: CSV = try? CSV(url: logFile) else {
guard let CSVFile: CSV = try? CSV(url: logFile) else {
return nil
}
var startTimestamp: Date?
var endTimestamp: Date?
var prevEvent: String?

for line in csvFile.enumeratedRows {
for line in CSVFile.enumeratedRows {
// XOR for event filtering, when there is data corruption
if prevEvent == nil {
prevEvent = line[0]
Expand Down Expand Up @@ -130,26 +156,14 @@ enum Events {
return nil
}

// corrupted data
// Got both actions
if startTimestamp != nil, endTimestamp != nil {
// same day, TODO: remove once we are ok with current state of parsing
// if formatter.string(from: startTimestamp!) == formatter.string(from: endTimestamp!) {
let elapsed = Int(endTimestamp!.timeIntervalSince(startTimestamp!))
let key = formatter.string(from: startTimestamp!)
os_log("Elapsed %s, %s > %d", startTimestamp!.debugDescription, endTimestamp!.debugDescription, elapsed)
if let val = data[key] {
data[key] = elapsed + val
} else {
data[key] = elapsed
}
events.append(Event(startTimestamp: startTimestamp!, endTimestamp: endTimestamp!))
startTimestamp = nil
endTimestamp = nil
// }else {
// return nil
// }
}
}
return Report.fromData(data)
return events
}
return nil
}
Expand Down
45 changes: 32 additions & 13 deletions Work Hours/StatusBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,20 @@ class StatusBarController: NSObject, NSMenuDelegate {

func fromReports(_ reports: [Report]) -> NSMenu {
let submenu = NSMenu()
for report in reports {
for report in reports.sorted(by: { $0.timestamp > $1.timestamp }) {
submenu.addItem(addSubmenu(withTitle: "\(report.timestamp) worked \(report.amount)", action: #selector(copyToPasteboard)))
}
return submenu
}

func fromReportsToday(_ reports: [Report]) -> NSMenu {
let submenu = NSMenu()
for report in reports.sorted(by: { $0.timestamp > $1.timestamp }) {
submenu.addItem(addSubmenu(withTitle: "Started \(report.timestamp) worked \(report.amount)", action: #selector(copyToPasteboard)))
}
return submenu
}

@objc func copyToPasteboard() {}

override
Expand Down Expand Up @@ -76,10 +84,13 @@ class StatusBarController: NSObject, NSMenuDelegate {
addApplicationItems()
}

func menuDidClose(_: NSMenu) {}
func menuDidClose(_: NSMenu) {
timerModel.update()
}

func menuWillOpen(_: NSMenu) {
updateMenu()
timerModel.update()
}

@objc func toggle() {
Expand Down Expand Up @@ -107,20 +118,28 @@ class StatusBarController: NSObject, NSMenuDelegate {
}

statusItemMenu.addItem(NSMenuItem.separator())
if let events = Events.getEvents(), events.count > 0 {
let todayItem = NSMenuItem(title: "Today", action: nil, keyEquivalent: "")
if let todayReports = Events.generateReport(events: events.filter {
Calendar.current.isDateInToday($0.startTimestamp) && Calendar.current.isDateInToday($0.endTimestamp)
}, formatter: Date.HourMinutesFormatter) {
todayItem.submenu = fromReportsToday(todayReports)
}
statusItemMenu.addItem(todayItem)

let dailyItem = NSMenuItem(title: "Daily Reports", action: nil, keyEquivalent: "")
if let dailyReports = Events.generateReport(formatter: Date.YearMonthDayFormatter) {
dailyItem.submenu = fromReports(dailyReports.sorted(by: { $0.timestamp < $1.timestamp }).suffix(7))
}
statusItemMenu.addItem(dailyItem)
let dailyItem = NSMenuItem(title: "Daily Reports", action: nil, keyEquivalent: "")
if let dailyReports = Events.generateReport(events: events, formatter: Date.YearMonthDayFormatter) {
dailyItem.submenu = fromReports(dailyReports.suffix(7))
}
statusItemMenu.addItem(dailyItem)

let monthlyItem = NSMenuItem(title: "Monthly Reports", action: nil, keyEquivalent: "")
if let monthlyReports = Events.generateReport(formatter: Date.YearMonthFormatter) {
monthlyItem.submenu = fromReports(monthlyReports.sorted(by: { $0.timestamp < $1.timestamp }))
let monthlyItem = NSMenuItem(title: "Monthly Reports", action: nil, keyEquivalent: "")
if let monthlyReports = Events.generateReport(events: events, formatter: Date.YearMonthFormatter) {
monthlyItem.submenu = fromReports(monthlyReports.suffix(12))
}
statusItemMenu.addItem(monthlyItem)
statusItemMenu.addItem(NSMenuItem.separator())
}
statusItemMenu.addItem(monthlyItem)

statusItemMenu.addItem(NSMenuItem.separator())

let preferencesItem = NSMenuItem(title: "Preferences", action: #selector(AppDelegate.showPrefs), keyEquivalent: ",")
preferencesItem.target = NSApp.delegate
Expand Down
2 changes: 1 addition & 1 deletion Work Hours/TimerModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class TimerModel: ObservableObject {
}

func update() {
if isRunning, startTime != nil {
if startTime != nil {
let diff = Date() - startTime
display = diff.hoursAndMinutes()
}
Expand Down

0 comments on commit bb61c4d

Please sign in to comment.