Skip to content

Commit 49009d5

Browse files
committed
✨ Select events by service
1 parent a850c4b commit 49009d5

File tree

4 files changed

+93
-2
lines changed

4 files changed

+93
-2
lines changed

Sources/Cli/Options.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,18 @@ struct EventOptions: ParsableArguments {
8585
valueName: "t"
8686
)) var selectTags: [String] = []
8787

88+
@Option(help: ArgumentHelp(
89+
"Ignore events which services contain the service <s> " +
90+
"A comma separated list of services",
91+
valueName: "s"
92+
)) var ignoreServices: [String] = []
93+
94+
@Option(help: ArgumentHelp(
95+
"Select events which services contain the service <s> " +
96+
"A comma separated list of services",
97+
valueName: "s"
98+
)) var selectServices: [String] = []
99+
88100
@Option(help: ArgumentHelp(
89101
"Minimum (inclusive) number <n> of attendees",
90102
valueName: "n"

Sources/Filters/EventFilter.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,42 @@ enum EventFilter {
179179
}
180180
}
181181

182+
class IgnoreServices: EventFilterI {
183+
let services: [String]
184+
185+
init(services: [String]) {
186+
self.services = services
187+
}
188+
189+
func accept(_ event: Event) -> Bool {
190+
let intersection = Set(services).intersection(Set(event.services.keys))
191+
let hasMatchingService = !intersection.isEmpty
192+
return !hasMatchingService
193+
}
194+
195+
var description: String {
196+
return "EventFilter.IgnoreServices(\(services))"
197+
}
198+
}
199+
200+
class SelectServices: EventFilterI {
201+
let services: [String]
202+
203+
init(services: [String]) {
204+
self.services = services
205+
}
206+
207+
func accept(_ event: Event) -> Bool {
208+
let intersection = Set(services).intersection(Set(event.services.keys))
209+
let hasMatchingService = !intersection.isEmpty
210+
return hasMatchingService
211+
}
212+
213+
var description: String {
214+
return "EventFilter.SelectServices(\(services))"
215+
}
216+
}
217+
182218
class Combined: EventFilterI {
183219
let filters: [EventFilterI]
184220

@@ -195,6 +231,9 @@ enum EventFilter {
195231
}
196232
}
197233

234+
// ignoring cyclomatic_complexity, since they are
235+
// required checks and just add filters
236+
// swiftlint:disable:next cyclomatic_complexity
198237
static func build(
199238
opts: EventOptions
200239
) -> (EventFilterI) {
@@ -229,6 +268,14 @@ enum EventFilter {
229268
add(EventFilter.SelectTags(tags: opts.selectTags))
230269
}
231270

271+
if !opts.ignoreServices.isEmpty {
272+
add(EventFilter.IgnoreServices(services: opts.ignoreServices))
273+
}
274+
275+
if !opts.selectServices.isEmpty {
276+
add(EventFilter.SelectServices(services: opts.selectServices))
277+
}
278+
232279
if opts.minNumAttendees ?? -1 >= 0 {
233280
add(EventFilter.MinNumAttendees(count: opts.minNumAttendees!))
234281
}

Sources/Model/Event.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ struct Event: Codable, ReverseCodable, Equatable {
8787
attendees: [String] = [],
8888
now: Date = Date(),
8989
startDate: Date = Date(),
90-
endDate: Date = Date()
90+
endDate: Date = Date(),
91+
services: [String: String] = [:]
9192
) -> Event {
9293
let cal = PlanCalendar.Unknown
9394
let title = Title(text: title)
@@ -99,7 +100,6 @@ struct Event: Codable, ReverseCodable, Equatable {
99100
)
100101
let location = ""
101102
let meeting = Meeting(organizer: "", attendees: attendees)
102-
let services: [String: String] = [:]
103103

104104
return Event(
105105
id: id,

Tests/EventFilterTest.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,38 @@ import Testing
4343
#expect(actual == expected)
4444
}
4545

46+
@Test func testIgnoreServicesNoServices() {
47+
let event = Event.generate()
48+
let expected = true
49+
let actual = EventFilter.IgnoreServices(services: []).accept(event)
50+
51+
#expect(actual == expected)
52+
}
53+
54+
@Test func testIgnoreServiceMatchingService() {
55+
let event = Event.generate(services: ["zoom": "example"])
56+
let expected = false
57+
let actual = EventFilter.IgnoreServices(services: ["zoom"]).accept(event)
58+
59+
#expect(actual == expected)
60+
}
61+
62+
@Test func testIgnoreServiceNotMatchingServices() {
63+
let event = Event.generate(services: ["zoom": "example"])
64+
let expected = true
65+
let actual = EventFilter.IgnoreServices(services: ["teams"]).accept(event)
66+
67+
#expect(actual == expected)
68+
}
69+
70+
@Test func testSelectServicesMatchingServices() {
71+
let event = Event.generate(services: ["zoom": "example"])
72+
let expected = true
73+
let actual = EventFilter.SelectServices(services: ["zoom"]).accept(event)
74+
75+
#expect(actual == expected)
76+
}
77+
4678
@Test func testIgnoreAnAllDayEvent() {
4779
let event = Event.generate(allDay: true)
4880
let expected = false

0 commit comments

Comments
 (0)