Skip to content

Commit 85ee3b9

Browse files
committed
refactor/qg-253: SourceItem заменён на URI
Чтобы не переизобретать велосипед для строкового представления универсальных идентификаторов ресурсов, чем SourceItem собственно и был
1 parent 4c58c0e commit 85ee3b9

File tree

19 files changed

+130
-82
lines changed

19 files changed

+130
-82
lines changed

app/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import kotlinx.kover.gradle.plugin.dsl.AggregationType
22
import kotlinx.kover.gradle.plugin.dsl.CoverageUnit
3+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
34

45
plugins {
56
alias(libs.plugins.kotlin.spring)
@@ -230,3 +231,7 @@ configurations.matching { it.name == "detekt" }.all {
230231
}
231232
}
232233
}
234+
val compileKotlin: KotlinCompile by tasks
235+
compileKotlin.compilerOptions {
236+
freeCompilerArgs.set(listOf("-Xannotation-default-target=param-property"))
237+
}

app/src/main/kotlin/pro/qyoga/app/therapist/appointments/core/edit/CreateAppointmentPageController.kt

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.PostMapping
77
import org.springframework.web.bind.annotation.RequestMapping
88
import org.springframework.web.bind.annotation.RequestParam
99
import org.springframework.web.servlet.ModelAndView
10+
import org.springframework.web.util.UriComponentsBuilder
1011
import pro.azhidkov.platform.spring.sdj.ergo.hydration.ref
1112
import pro.azhidkov.timezones.LocalizedTimeZone
1213
import pro.azhidkov.timezones.TimeZones
@@ -19,9 +20,9 @@ import pro.qyoga.app.therapist.appointments.core.edit.ops.GetAppointmentPrefillD
1920
import pro.qyoga.app.therapist.appointments.core.edit.view_model.appointmentPageModelAndView
2021
import pro.qyoga.app.therapist.appointments.core.schedule.SchedulePageController.Companion.calendarForDayWithFocus
2122
import pro.qyoga.core.appointments.core.commands.EditAppointmentRequest
22-
import pro.qyoga.core.calendar.api.SourceItem
2323
import pro.qyoga.core.users.auth.dtos.QyogaUserDetails
2424
import pro.qyoga.core.users.therapists.ref
25+
import java.net.URI
2526
import java.time.LocalDateTime
2627

2728
@Controller
@@ -35,14 +36,9 @@ class CreateAppointmentPageController(
3536
@GetMapping
3637
fun getAppointmentPage(
3738
@RequestParam(DATE_TIME) dateTime: LocalDateTime?,
38-
@RequestParam(SOURCE_ITEM_TYPE) sourceItemType: String?,
39-
@RequestParam(SOURCE_ITEM_ID) sourceItemId: String?,
39+
@RequestParam(SOURCE_ITEM) sourceItem: URI?,
4040
@AuthenticationPrincipal therapist: QyogaUserDetails
4141
): ModelAndView {
42-
val sourceItem = when {
43-
sourceItemType != null && sourceItemId != null -> SourceItem(sourceItemType, sourceItemId)
44-
else -> null
45-
}
4642
val prefillData = getAppointmentPrefillData(therapist.ref, sourceItem, dateTime)
4743
return appointmentPageModelAndView(
4844
pageMode = EntityPageMode.CREATE,
@@ -77,17 +73,19 @@ class CreateAppointmentPageController(
7773
companion object {
7874
const val PATH = "/therapist/appointments/new"
7975
const val DATE_TIME = "dateTime"
80-
const val SOURCE_ITEM_TYPE = "sourceItemType"
81-
const val SOURCE_ITEM_ID = "sourceItemId"
76+
const val SOURCE_ITEM = "sourceItem"
8277
const val CREATE_AT_DATE_TIME_URI = "/therapist/appointments/new?$DATE_TIME={$DATE_TIME}"
8378
private const val CREATE_FROM_SOURCE_ITEM_URI =
84-
"/therapist/appointments/new?$DATE_TIME={$DATE_TIME}&$SOURCE_ITEM_TYPE={$SOURCE_ITEM_TYPE}&$SOURCE_ITEM_ID={$SOURCE_ITEM_ID}"
79+
"/therapist/appointments/new"
8580

86-
fun addFromSourceItemUri(dateTime: LocalDateTime, sourceItem: SourceItem): String =
87-
CREATE_FROM_SOURCE_ITEM_URI
88-
.replace("{$DATE_TIME}", dateTime.toString())
89-
.replace("{$SOURCE_ITEM_TYPE}", sourceItem.type)
90-
.replace("{$SOURCE_ITEM_ID}", sourceItem.id)
81+
fun addFromSourceItemUri(dateTime: LocalDateTime, sourceItem: URI): String =
82+
UriComponentsBuilder
83+
.fromPath(CREATE_FROM_SOURCE_ITEM_URI)
84+
.queryParam("dateTime", dateTime)
85+
.queryParam("sourceItem", sourceItem.toString())
86+
.encode()
87+
.build()
88+
.toUriString()
9189
}
9290

9391
}

app/src/main/kotlin/pro/qyoga/app/therapist/appointments/core/edit/forms/CreateAppointmentForm.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import pro.qyoga.core.calendar.api.CalendarItem
66
import pro.qyoga.core.calendar.api.CalendarItemId
77
import pro.qyoga.core.clients.cards.model.ClientRef
88
import pro.qyoga.core.therapy.therapeutic_tasks.model.TherapeuticTaskRef
9+
import java.net.URI
910
import java.time.Duration
1011
import java.time.LocalDateTime
1112
import java.time.ZoneId
@@ -28,7 +29,7 @@ data class CreateAppointmentForm(
2829
val payed: Boolean?,
2930
val appointmentStatus: AppointmentStatus?,
3031
val comment: String?,
31-
val externalId: String?
32+
val externalId: URI?
3233
) {
3334

3435
constructor(
@@ -37,7 +38,7 @@ data class CreateAppointmentForm(
3738
timeZone: ZoneId,
3839
timeZoneTitle: String?
3940
) : this(
40-
externalId = externalEvent?.id?.toQueryParamStr(),
41+
externalId = externalEvent?.id?.toUri(),
4142
dateTime = dateTime,
4243
timeZone = timeZone,
4344
timeZoneTitle = timeZoneTitle,

app/src/main/kotlin/pro/qyoga/app/therapist/appointments/core/edit/ops/GetAppointmentPrefillDataOp.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ package pro.qyoga.app.therapist.appointments.core.edit.ops
33
import org.springframework.stereotype.Component
44
import pro.azhidkov.timezones.TimeZones
55
import pro.qyoga.app.therapist.appointments.core.edit.forms.CreateAppointmentForm
6-
import pro.qyoga.core.calendar.api.SourceItem
76
import pro.qyoga.core.calendar.gateways.CalendarItemsResolver
87
import pro.qyoga.core.users.auth.model.UserRef
98
import pro.qyoga.core.users.settings.UserSettingsRepo
109
import pro.qyoga.core.users.therapists.TherapistRef
10+
import java.net.URI
1111
import java.time.LocalDateTime
1212

1313

@@ -16,16 +16,16 @@ class GetAppointmentPrefillDataOp(
1616
private val calendarItemsResolver: CalendarItemsResolver,
1717
private val userSettingsRepo: UserSettingsRepo,
1818
private val timeZones: TimeZones,
19-
) : (TherapistRef, SourceItem?, LocalDateTime?) -> CreateAppointmentForm {
19+
) : (TherapistRef, URI?, LocalDateTime?) -> CreateAppointmentForm {
2020

2121
override fun invoke(
2222
therapistRef: TherapistRef,
23-
sourceItem: SourceItem?,
23+
sourceItem: URI?,
2424
dateTime: LocalDateTime?
2525
): CreateAppointmentForm {
2626
val currentUserTimeZone = userSettingsRepo.getUserTimeZone(UserRef(therapistRef))
2727

28-
val sourceEvent = calendarItemsResolver.findCalendarItem(therapistRef, sourceItem!!)
28+
val sourceEvent = sourceItem?.let { calendarItemsResolver.findCalendarItem(therapistRef, it) }
2929

3030
val timeZoneTitle = timeZones.findById(currentUserTimeZone)?.displayName
3131

app/src/main/kotlin/pro/qyoga/app/therapist/appointments/core/schedule/CalendarPageModel.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import pro.qyoga.core.appointments.core.model.AppointmentStatus
1717
import pro.qyoga.core.appointments.core.views.LocalizedAppointmentSummary
1818
import pro.qyoga.core.calendar.api.CalendarItem
1919
import pro.qyoga.core.calendar.api.CalendarItemId
20-
import pro.qyoga.core.calendar.api.SourceItem
2120
import pro.qyoga.l10n.russianDayOfMonthLongFormat
2221
import pro.qyoga.l10n.russianTimeFormat
2322
import pro.qyoga.l10n.systemLocale
@@ -267,7 +266,7 @@ private fun CalendarItem<*, LocalDateTime>.editUri() =
267266
is UUID -> EditAppointmentPageController.editUri(id as UUID)
268267
is CalendarItemId -> CreateAppointmentPageController.addFromSourceItemUri(
269268
dateTime,
270-
SourceItem(id as CalendarItemId)
269+
(id as CalendarItemId).toUri()
271270
)
272271
else -> error("Unsupported type: $id")
273272
}

app/src/main/kotlin/pro/qyoga/core/calendar/api/CalendarItem.kt

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,61 @@
11
package pro.qyoga.core.calendar.api
22

3+
import org.springframework.util.MultiValueMap
4+
import org.springframework.web.util.UriComponentsBuilder
5+
import org.springframework.web.util.UriTemplate
6+
import java.net.URI
37
import java.time.Duration
48
import java.time.temporal.Temporal
59

10+
data class CalendarItemUri(
11+
val type: String,
12+
val params: Map<String, String?>
13+
) {
14+
15+
companion object {
16+
17+
private const val SCHEMA = "qyoga"
18+
private const val HOST = "calendars"
19+
private const val PATH = "{type}/events"
20+
const val TEMPLATE = "$SCHEMA://$HOST/$PATH"
21+
22+
private val pathTemplate = UriTemplate("/$PATH")
23+
24+
fun parseOrNull(uri: URI): CalendarItemUri? {
25+
if (uri.scheme != SCHEMA) {
26+
return null
27+
}
28+
if (uri.host != HOST) {
29+
return null
30+
}
31+
32+
val comps = UriComponentsBuilder.fromUri(uri).build()
33+
if (!pathTemplate.matches(comps.path)) {
34+
return null
35+
}
36+
37+
val type = comps.pathSegments.getOrNull(0)
38+
?: return null
39+
40+
val params: Map<String, String?> = comps.queryParams.toSingleValueMap()
41+
42+
return CalendarItemUri(type, params)
43+
}
44+
45+
}
46+
47+
}
48+
649
interface CalendarItemId {
750

851
val type: CalendarType
952

10-
fun toQueryParamStr(): String
53+
fun toUri(): URI = UriComponentsBuilder.fromUriString(CalendarItemUri.TEMPLATE)
54+
.queryParams(MultiValueMap.fromSingleValue(toMap()))
55+
.buildAndExpand(type.name)
56+
.toUri()
57+
58+
fun toMap(): Map<String, String?>
1159

1260
}
1361

app/src/main/kotlin/pro/qyoga/core/calendar/api/CalendarsService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ interface CalendarsService<ID> {
2222

2323
fun findById(therapistRef: TherapistRef, eventId: ID): CalendarItem<ID, ZonedDateTime>?
2424

25-
fun parseStringId(sourceItem: SourceItem): ID
25+
fun createItemId(itemId: Map<String, String?>): ID
2626

2727
}

app/src/main/kotlin/pro/qyoga/core/calendar/api/SourceItem.kt

Lines changed: 0 additions & 10 deletions
This file was deleted.

app/src/main/kotlin/pro/qyoga/core/calendar/gateways/CalendarItemsResolver.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ package pro.qyoga.core.calendar.gateways
33
import org.springframework.stereotype.Service
44
import pro.qyoga.core.calendar.api.CalendarItem
55
import pro.qyoga.core.calendar.api.CalendarItemId
6+
import pro.qyoga.core.calendar.api.CalendarItemUri
67
import pro.qyoga.core.calendar.api.CalendarsService
7-
import pro.qyoga.core.calendar.api.SourceItem
88
import pro.qyoga.core.users.therapists.TherapistRef
9+
import java.net.URI
910
import java.time.ZonedDateTime
1011

1112
@Service
@@ -17,11 +18,14 @@ class CalendarItemsResolver(
1718

1819
fun findCalendarItem(
1920
therapistRef: TherapistRef,
20-
sourceItem: SourceItem
21+
sourceItem: URI
2122
): CalendarItem<CalendarItemId, ZonedDateTime>? {
23+
val calendarItemUri = CalendarItemUri.parseOrNull(sourceItem)
24+
?: throw IllegalArgumentException("Invalid calendar item URI: $sourceItem")
25+
2226
@Suppress("UNCHECKED_CAST")
23-
val service = services[sourceItem.type] as CalendarsService<CalendarItemId>
24-
val id = service.parseStringId(sourceItem)
27+
val service = services[calendarItemUri.type] as CalendarsService<CalendarItemId>
28+
val id = service.createItemId(calendarItemUri.params)
2529
return service.findById(therapistRef, id)
2630
}
2731

app/src/main/kotlin/pro/qyoga/i9ns/calendars/google/GoogleCalendarItem.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ data class GoogleCalendarItemId(
1616

1717
override val type: CalendarType = GoogleCalendar.Type
1818

19-
override fun toQueryParamStr(): String =
20-
"$calendarId,$itemId"
19+
override fun toMap(): Map<String, String> = mapOf(
20+
"cid" to calendarId,
21+
"eid" to itemId
22+
)
2123

2224
}
2325

0 commit comments

Comments
 (0)