From ff94d2b4c1c8bb5f59fa8366b725c72fa87fd39d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cihat=20Gu=CC=88ndu=CC=88z?= Date: Mon, 1 Jul 2024 23:47:40 +0200 Subject: [PATCH 1/2] Add start of week as new option in app setting model --- Sources/DataTransferObjects/DTOs/DTOv2.swift | 11 ++++++++++- .../EncodingDecodingTests.swift | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Sources/DataTransferObjects/DTOs/DTOv2.swift b/Sources/DataTransferObjects/DTOs/DTOv2.swift index 14637f8..1469df0 100644 --- a/Sources/DataTransferObjects/DTOs/DTOv2.swift +++ b/Sources/DataTransferObjects/DTOs/DTOv2.swift @@ -205,6 +205,11 @@ public enum DTOv2 { case website } + public enum StartOfWeek: String, Codable, Hashable { + case sunday + case monday + } + /// If true, the app should display demo content instead of public var showExampleData: Bool? @@ -219,10 +224,14 @@ public enum DTOv2 { /// How should the overview page for this application be layouted? public var displayMode: DisplayMode? - public init(displayMode: DisplayMode? = nil, colorScheme: String? = nil, showExampleData: Bool? = nil) { + /// The start of week when filtering using weekly filters like 'This Week'. + public var startOfWeek: StartOfWeek? + + public init(displayMode: DisplayMode? = nil, colorScheme: String? = nil, showExampleData: Bool? = nil, startOfWeek: StartOfWeek? = nil) { self.displayMode = displayMode ?? .app self.colorScheme = colorScheme self.showExampleData = showExampleData ?? false + self.startOfWeek = startOfWeek ?? .sunday } } diff --git a/Tests/DataTransferObjectsTests/EncodingDecodingTests.swift b/Tests/DataTransferObjectsTests/EncodingDecodingTests.swift index b3f04ea..9c3cbf6 100644 --- a/Tests/DataTransferObjectsTests/EncodingDecodingTests.swift +++ b/Tests/DataTransferObjectsTests/EncodingDecodingTests.swift @@ -10,7 +10,8 @@ final class EncodingDecodingTests: XCTestCase { let expectedOutput = """ { "displayMode": "app", - "showExampleData": false + "showExampleData": false, + "startOfWeek": "sunday" } """ .filter { !$0.isWhitespace } From bb4185eb34361fadb34dfe7138e845b00716a206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cihat=20Gu=CC=88ndu=CC=88z?= Date: Tue, 2 Jul 2024 00:22:34 +0200 Subject: [PATCH 2/2] Add start of week options to relative time interval --- .../Query/CustomQuery+CompileDown.swift | 4 ++-- .../Query/RelativeTimeInterval.swift | 13 +++++++----- .../RelativeDateTests.swift | 10 +++++----- .../CompileDownTests.swift | 20 +++++++++---------- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/Sources/DataTransferObjects/Query/CustomQuery+CompileDown.swift b/Sources/DataTransferObjects/Query/CustomQuery+CompileDown.swift index 3056f62..253fcab 100644 --- a/Sources/DataTransferObjects/Query/CustomQuery+CompileDown.swift +++ b/Sources/DataTransferObjects/Query/CustomQuery+CompileDown.swift @@ -51,7 +51,7 @@ public extension CustomQuery { /// @warn Both precompile AND compileToRunnableQuery need to be run before a query can safely be handed to Druid! /// /// @see precompile - func compileToRunnableQuery() throws -> CustomQuery { + func compileToRunnableQuery(startWeekOnMonday: Bool) throws -> CustomQuery { guard compilationStatus == .precompiled else { throw QueryGenerationError.compilationStatusError } @@ -61,7 +61,7 @@ public extension CustomQuery { // Compile relative Time intervals if let relativeIntervals = query.relativeIntervals { - query.intervals = relativeIntervals.map { QueryTimeInterval.from(relativeTimeInterval: $0) } + query.intervals = relativeIntervals.map { QueryTimeInterval.from(relativeTimeInterval: $0, startWeekOnMonday: startWeekOnMonday) } } guard query.intervals != nil, !query.intervals!.isEmpty else { diff --git a/Sources/DataTransferObjects/Query/RelativeTimeInterval.swift b/Sources/DataTransferObjects/Query/RelativeTimeInterval.swift index 0a6403a..1742f64 100644 --- a/Sources/DataTransferObjects/Query/RelativeTimeInterval.swift +++ b/Sources/DataTransferObjects/Query/RelativeTimeInterval.swift @@ -66,11 +66,14 @@ public struct RelativeDate: Codable, Hashable, Equatable { } public extension Date { - static func from(relativeDate: RelativeDate) -> Date { + static func from(relativeDate: RelativeDate, startWeekOnMonday: Bool) -> Date { var date = Date() + var calendar = date.calendar + calendar.firstWeekday = startWeekOnMonday ? 2 : 1 // 1 is Sunday, 2 is Monday + let calendarComponent = relativeDate.component.calendarComponent - date = date.calendar.date(byAdding: calendarComponent, value: relativeDate.offset, to: date) ?? date + date = calendar.date(byAdding: calendarComponent, value: relativeDate.offset, to: date) ?? date switch relativeDate.position { case .beginning: @@ -84,10 +87,10 @@ public extension Date { } public extension QueryTimeInterval { - static func from(relativeTimeInterval: RelativeTimeInterval) -> QueryTimeInterval { + static func from(relativeTimeInterval: RelativeTimeInterval, startWeekOnMonday: Bool) -> QueryTimeInterval { QueryTimeInterval( - beginningDate: Date.from(relativeDate: relativeTimeInterval.beginningDate), - endDate: Date.from(relativeDate: relativeTimeInterval.endDate) + beginningDate: Date.from(relativeDate: relativeTimeInterval.beginningDate, startWeekOnMonday: startWeekOnMonday), + endDate: Date.from(relativeDate: relativeTimeInterval.endDate, startWeekOnMonday: startWeekOnMonday) ) } } diff --git a/Tests/DataTransferObjectsTests/RelativeDateTests.swift b/Tests/DataTransferObjectsTests/RelativeDateTests.swift index c1318d9..66f5b97 100644 --- a/Tests/DataTransferObjectsTests/RelativeDateTests.swift +++ b/Tests/DataTransferObjectsTests/RelativeDateTests.swift @@ -134,26 +134,26 @@ final class RelativeDateTests: XCTestCase { let beginningOfLastMonthRelative = RelativeDate(.beginning, of: .month, adding: -1) let beginningOfLastMonthAbsolute = Date().calendar.date(byAdding: .month, value: -1, to: Date())!.beginning(of: .month) - XCTAssertEqual(beginningOfLastMonthAbsolute, Date.from(relativeDate: beginningOfLastMonthRelative)) + XCTAssertEqual(beginningOfLastMonthAbsolute, Date.from(relativeDate: beginningOfLastMonthRelative, startWeekOnMonday: false)) let endOfThisMonthRelative = RelativeDate(.end, of: .month, adding: 0) let endOfThisMonthAbsolute = Date().end(of: .month) - XCTAssertEqual(endOfThisMonthAbsolute, Date.from(relativeDate: endOfThisMonthRelative)) + XCTAssertEqual(endOfThisMonthAbsolute, Date.from(relativeDate: endOfThisMonthRelative, startWeekOnMonday: false)) let beginningOfNextWeekRelative = RelativeDate(.beginning, of: .week, adding: 1) let beginningOfNextWeekAbsolute = Date().calendar.date(byAdding: .weekOfYear, value: 1, to: Date())!.beginning(of: .weekOfYear)! - XCTAssertEqual(beginningOfNextWeekAbsolute, Date.from(relativeDate: beginningOfNextWeekRelative)) + XCTAssertEqual(beginningOfNextWeekAbsolute, Date.from(relativeDate: beginningOfNextWeekRelative, startWeekOnMonday: false)) let endOfTodayRelative = RelativeDate(.end, of: .day, adding: 0) let endOfTodayAbsolute = Date().end(of: .day) - XCTAssertEqual(endOfTodayAbsolute, Date.from(relativeDate: endOfTodayRelative)) + XCTAssertEqual(endOfTodayAbsolute, Date.from(relativeDate: endOfTodayRelative, startWeekOnMonday: false)) let in30HoursRelative = RelativeDate(.beginning, of: .hour, adding: 30) let in30HoursAbsolute = Date().startOfHour.adding(.hour, value: 30).startOfHour - XCTAssertEqual(in30HoursAbsolute, Date.from(relativeDate: in30HoursRelative)) + XCTAssertEqual(in30HoursAbsolute, Date.from(relativeDate: in30HoursRelative, startWeekOnMonday: false)) } } diff --git a/Tests/QueryGenerationTests/CompileDownTests.swift b/Tests/QueryGenerationTests/CompileDownTests.swift index 639976b..064b10b 100644 --- a/Tests/QueryGenerationTests/CompileDownTests.swift +++ b/Tests/QueryGenerationTests/CompileDownTests.swift @@ -123,13 +123,13 @@ final class CompileDownTests: XCTestCase { func testCompilationFailsIfNoPrecompilation() throws { let query = CustomQuery(queryType: .timeseries, relativeIntervals: relativeIntervals, granularity: .all) - XCTAssertThrowsError(try query.compileToRunnableQuery()) + XCTAssertThrowsError(try query.compileToRunnableQuery(startWeekOnMonday: false)) } func testIntervalsAreCreated() throws { let query = CustomQuery(queryType: .timeseries, relativeIntervals: relativeIntervals, granularity: .all) let precompiledQuery = try query.precompile(organizationAppIDs: [appID1, appID2], isSuperOrg: false) - let compiledQuery = try precompiledQuery.compileToRunnableQuery() + let compiledQuery = try precompiledQuery.compileToRunnableQuery(startWeekOnMonday: false) XCTAssertNotNil(compiledQuery.intervals) XCTAssertFalse(compiledQuery.intervals!.isEmpty) @@ -138,7 +138,7 @@ final class CompileDownTests: XCTestCase { func testCompilationStatusIsSetCorrectly() throws { let query = CustomQuery(queryType: .timeseries, relativeIntervals: relativeIntervals, granularity: .all) let precompiledQuery = try query.precompile(organizationAppIDs: [appID1, appID2], isSuperOrg: false) - let compiledQuery = try precompiledQuery.compileToRunnableQuery() + let compiledQuery = try precompiledQuery.compileToRunnableQuery(startWeekOnMonday: false) XCTAssertEqual(precompiledQuery.compilationStatus, .precompiled) XCTAssertEqual(compiledQuery.compilationStatus, .compiled) @@ -146,7 +146,7 @@ final class CompileDownTests: XCTestCase { func testThrowsIfCompilationStatusNotSetCorrectly() throws { let query = CustomQuery(queryType: .timeseries, relativeIntervals: relativeIntervals, granularity: .all) - XCTAssertThrowsError(try query.compileToRunnableQuery()) + XCTAssertThrowsError(try query.compileToRunnableQuery(startWeekOnMonday: false)) } func testRestrictions() throws { @@ -167,7 +167,7 @@ final class CompileDownTests: XCTestCase { let query = CustomQuery(queryType: .timeseries, restrictions: restrictions, intervals: intervals, granularity: .all) let precompiledQuery = try query.precompile(organizationAppIDs: [appID1, appID2], isSuperOrg: false) - let compiledQuery = try precompiledQuery.compileToRunnableQuery() + let compiledQuery = try precompiledQuery.compileToRunnableQuery(startWeekOnMonday: false) XCTAssertEqual(compiledQuery.restrictions, [ .init(beginningDate: Date(iso8601String: "2023-03-01T00:00:00.000Z")!, endDate: Date(iso8601String: "2023-04-02T00:00:00.000Z")!), @@ -182,7 +182,7 @@ final class CompileDownTests: XCTestCase { let query = CustomQuery(queryType: .timeseries, sampleFactor: 1, intervals: intervals, granularity: .day) let precompiledQuery = try query.precompile(organizationAppIDs: [appID1, appID2], isSuperOrg: false) - let compiledQuery = try precompiledQuery.compileToRunnableQuery() + let compiledQuery = try precompiledQuery.compileToRunnableQuery(startWeekOnMonday: false) XCTAssertEqual(compiledQuery.dataSource?.name, "telemetry-signals") } @@ -193,7 +193,7 @@ final class CompileDownTests: XCTestCase { let query = CustomQuery(queryType: .timeseries, sampleFactor: 10, intervals: intervals, granularity: .day) let precompiledQuery = try query.precompile(organizationAppIDs: [appID1, appID2], isSuperOrg: false) - let compiledQuery = try precompiledQuery.compileToRunnableQuery() + let compiledQuery = try precompiledQuery.compileToRunnableQuery(startWeekOnMonday: false) XCTAssertEqual(compiledQuery.dataSource?.name, "telemetry-signals-sample10") } @@ -204,7 +204,7 @@ final class CompileDownTests: XCTestCase { let query = CustomQuery(queryType: .timeseries, sampleFactor: 100, intervals: intervals, granularity: .day) let precompiledQuery = try query.precompile(organizationAppIDs: [appID1, appID2], isSuperOrg: false) - let compiledQuery = try precompiledQuery.compileToRunnableQuery() + let compiledQuery = try precompiledQuery.compileToRunnableQuery(startWeekOnMonday: false) XCTAssertEqual(compiledQuery.dataSource?.name, "telemetry-signals-sample100") } @@ -215,7 +215,7 @@ final class CompileDownTests: XCTestCase { let query = CustomQuery(queryType: .timeseries, sampleFactor: 1000, intervals: intervals, granularity: .day) let precompiledQuery = try query.precompile(organizationAppIDs: [appID1, appID2], isSuperOrg: false) - let compiledQuery = try precompiledQuery.compileToRunnableQuery() + let compiledQuery = try precompiledQuery.compileToRunnableQuery(startWeekOnMonday: false) XCTAssertEqual(compiledQuery.dataSource?.name, "telemetry-signals-sample1000") } @@ -226,7 +226,7 @@ final class CompileDownTests: XCTestCase { let query = CustomQuery(queryType: .timeseries, sampleFactor: 42, intervals: intervals, granularity: .day) let precompiledQuery = try query.precompile(organizationAppIDs: [appID1, appID2], isSuperOrg: false) - let compiledQuery = try precompiledQuery.compileToRunnableQuery() + let compiledQuery = try precompiledQuery.compileToRunnableQuery(startWeekOnMonday: false) XCTAssertEqual(compiledQuery.dataSource?.name, "telemetry-signals") } }