-
-
Notifications
You must be signed in to change notification settings - Fork 315
feat: plans migration #3216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dkrizan
wants to merge
47
commits into
main
Choose a base branch
from
danielkrizan/plan-migration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
feat: plans migration #3216
Changes from all commits
Commits
Show all changes
47 commits
Select commit
Hold shift + click to select a range
65e2d7c
chore: create plan migration endpoint
dkrizan 9896c97
feat: cloud plans migration controller + UI
dkrizan f284b1d
feat: self-hosted migrations controller and UI
dkrizan da30671
chore: test plan migration
dkrizan ee801e3
draft: migration history
dkrizan a9b8463
chore: option to delete selfhosted plan migration, handle customer up…
dkrizan 9575259
chore: real stripe test to schedule update and preview update
dkrizan 3c39fc9
feat: self-hosted plans - migrated subscriptions list
dkrizan b202ade
feat: send plan change notice when migrated
dkrizan e18d21b
chore: migration history refactored
dkrizan fe88513
chore: migrator cache fix
dkrizan 1ae426e
chore: e2e tests - administration plan migrations
dkrizan c800dfc
chore: test fix
dkrizan 493e964
chore: migration form refactored
dkrizan e2294cd
feat: allow upgrade free plans too
dkrizan f8cdafa
chore: release schedule on subscription update
dkrizan 13c9bcf
chore: check-translations fix
dkrizan 0924298
feat: migration email content updated
dkrizan e0bee28
chore: CR fixes
dkrizan 977bfb6
chore: plan migration form refactored
dkrizan cdee642
chore: plan migration edit form refactored
dkrizan 11c3f6b
chore: CR refactors
dkrizan 3033146
chore: internal properties controller refactor
dkrizan 5fc5548
chore: migration history refactored (renamed to migration record)
dkrizan 31010ad
chore: type
dkrizan c444b7c
fix: PlanMigration chip code improvements
dkrizan dd0bf89
chore: coderabbit fixes
dkrizan 482ecd8
chore: billingSchema updated
dkrizan 1dbbff2
chore: coderabbitai fixes
dkrizan 2d238c1
chore: refactor plan migration create form
dkrizan 8b6994e
chore: coderabbit improvements
dkrizan bf4be43
chore: coderabbit improvements 2
dkrizan 218216e
chore: coderabbit improvements 2
dkrizan 80fe8c4
chore: error message for missing plan migration
dkrizan 19321f5
chore: schemas updated
dkrizan 4fc1b59
chore: schemas updated
dkrizan 6129329
chore: coderabbit
dkrizan 623e127
feat: plan migration email changed
dkrizan c7e53b2
feat: custom email in Plan migration form
dkrizan 3ea67a4
feat: custom email in Plan migration form
dkrizan 7407ad0
chore: ktlint
dkrizan b57796a
feat: alert of plan upgrade on Subscriptions page
dkrizan b7dd81f
feat: collapsible Email content editor in Plan migration detail.
dkrizan 04a9ed5
feat: to be transferred subscription list
dkrizan 0351e8d
feat: tooltips for cloud plan subscriptions on Cloud plans page
dkrizan d5388b1
chore: tsc & eslint fix
dkrizan 4ad47cf
feat: tooltips for cloud plan subscriptions on Self hosted EE plans page
dkrizan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or 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 hidden or 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
31 changes: 31 additions & 0 deletions
31
...nd/data/src/main/kotlin/io/tolgee/component/email/customTemplate/EmailTemplateRenderer.kt
This file contains hidden or 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,31 @@ | ||
| package io.tolgee.component.email.customTemplate | ||
|
|
||
| import io.tolgee.component.email.customTemplate.placeholder.EmailPlaceholdersExtractor | ||
| import org.springframework.stereotype.Component | ||
| import java.text.MessageFormat | ||
| import java.util.Locale | ||
| import kotlin.reflect.KClass | ||
|
|
||
| @Component | ||
| class EmailTemplateRenderer( | ||
| private val placeholderExtractor: EmailPlaceholdersExtractor, | ||
| ) { | ||
| fun render( | ||
| template: String, | ||
| variables: EmailTemplateVariables, | ||
| ): String { | ||
| @Suppress("UNCHECKED_CAST") | ||
| val entries = | ||
| placeholderExtractor.getEntries( | ||
| variables::class as KClass<EmailTemplateVariables>, | ||
| ) | ||
|
|
||
| val parameters = | ||
| entries | ||
| .map { entry -> | ||
| entry.accessor(variables) ?: "" | ||
| }.toTypedArray() | ||
|
|
||
| return MessageFormat(template, Locale.ENGLISH).format(parameters) | ||
| } | ||
| } |
6 changes: 6 additions & 0 deletions
6
...d/data/src/main/kotlin/io/tolgee/component/email/customTemplate/EmailTemplateVariables.kt
This file contains hidden or 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,6 @@ | ||
| package io.tolgee.component.email.customTemplate | ||
|
|
||
| /** | ||
| * Marker interface for classes that describe email template variables via [io.tolgee.component.email.customTemplate.placeholder.EmailPlaceholder] annotations. | ||
| */ | ||
| interface EmailTemplateVariables |
10 changes: 10 additions & 0 deletions
10
.../src/main/kotlin/io/tolgee/component/email/customTemplate/placeholder/EmailPlaceholder.kt
This file contains hidden or 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,10 @@ | ||
| package io.tolgee.component.email.customTemplate.placeholder | ||
|
|
||
| @Target(AnnotationTarget.PROPERTY) | ||
| @Retention(AnnotationRetention.RUNTIME) | ||
| annotation class EmailPlaceholder( | ||
| val position: Int, | ||
| val placeholder: String, | ||
| val description: String, | ||
| val exampleValue: String, | ||
| ) |
15 changes: 15 additions & 0 deletions
15
...kotlin/io/tolgee/component/email/customTemplate/placeholder/EmailPlaceholderDefinition.kt
This file contains hidden or 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,15 @@ | ||
| package io.tolgee.component.email.customTemplate.placeholder | ||
|
|
||
| import io.tolgee.component.email.customTemplate.EmailTemplateVariables | ||
|
|
||
| data class EmailPlaceholderDefinition( | ||
| val position: Int, | ||
| val placeholder: String, | ||
| val description: String, | ||
| val exampleValue: String, | ||
| ) | ||
|
|
||
| data class EmailPlaceholderEntry<T : EmailTemplateVariables>( | ||
| val definition: EmailPlaceholderDefinition, | ||
| val accessor: (T) -> String?, | ||
| ) |
51 changes: 51 additions & 0 deletions
51
...kotlin/io/tolgee/component/email/customTemplate/placeholder/EmailPlaceholdersExtractor.kt
This file contains hidden or 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 @@ | ||
| package io.tolgee.component.email.customTemplate.placeholder | ||
|
|
||
| import io.tolgee.component.email.customTemplate.EmailTemplateVariables | ||
| import org.springframework.stereotype.Component | ||
| import java.util.concurrent.ConcurrentHashMap | ||
| import kotlin.collections.set | ||
| import kotlin.reflect.KClass | ||
| import kotlin.reflect.full.findAnnotation | ||
| import kotlin.reflect.full.memberProperties | ||
|
|
||
| @Component | ||
| class EmailPlaceholdersExtractor { | ||
| private val cache = | ||
| ConcurrentHashMap<KClass<*>, List<EmailPlaceholderEntry<*>>>() | ||
|
|
||
| fun <T : EmailTemplateVariables> getEntries(kClass: KClass<T>): List<EmailPlaceholderEntry<T>> { | ||
| val existing = cache[kClass] | ||
| if (existing != null) { | ||
| @Suppress("UNCHECKED_CAST") | ||
| return existing as List<EmailPlaceholderEntry<T>> | ||
| } | ||
|
|
||
| val extracted = extract(kClass) | ||
| cache[kClass] = extracted | ||
| return extracted | ||
| } | ||
|
|
||
| fun <T : EmailTemplateVariables> getDefinitions(kClass: KClass<T>): List<EmailPlaceholderDefinition> { | ||
| return getEntries(kClass).map { it.definition } | ||
| } | ||
|
|
||
| private fun <T : EmailTemplateVariables> extract(kClass: KClass<T>): List<EmailPlaceholderEntry<T>> { | ||
| return kClass.memberProperties | ||
| .mapNotNull { property -> | ||
| val annotation = property.findAnnotation<EmailPlaceholder>() ?: return@mapNotNull null | ||
|
|
||
| EmailPlaceholderEntry( | ||
| definition = | ||
| EmailPlaceholderDefinition( | ||
| position = annotation.position, | ||
| placeholder = annotation.placeholder, | ||
| description = annotation.description, | ||
| exampleValue = annotation.exampleValue, | ||
| ), | ||
| accessor = { instance: T -> | ||
| property.get(instance)?.toString() | ||
| }, | ||
| ) | ||
| }.sortedBy { it.definition.position } | ||
| } | ||
| } |
This file contains hidden or 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
7 changes: 7 additions & 0 deletions
7
backend/data/src/main/kotlin/io/tolgee/dtos/misc/EmailPlaceholderModel.kt
This file contains hidden or 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,7 @@ | ||
| package io.tolgee.dtos.misc | ||
|
|
||
| data class EmailPlaceholderModel( | ||
| val placeholder: String, | ||
| val description: String, | ||
| val exampleValue: String, | ||
| ) |
6 changes: 6 additions & 0 deletions
6
backend/data/src/main/kotlin/io/tolgee/dtos/misc/EmailTemplateModel.kt
This file contains hidden or 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,6 @@ | ||
| package io.tolgee.dtos.misc | ||
|
|
||
| data class EmailTemplateModel( | ||
| val body: String, | ||
| val placeholders: List<EmailPlaceholderModel>, | ||
| ) |
This file contains hidden or 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
31 changes: 4 additions & 27 deletions
31
backend/development/src/main/kotlin/io/tolgee/controllers/internal/PropertiesController.kt
This file contains hidden or 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 |
|---|---|---|
| @@ -1,47 +1,24 @@ | ||
| package io.tolgee.controllers.internal | ||
|
|
||
| import io.tolgee.configuration.tolgee.E2eRuntimeMutable | ||
| import io.tolgee.configuration.tolgee.TolgeeProperties | ||
| import io.tolgee.dtos.request.SetPropertyDto | ||
| import io.tolgee.exceptions.BadRequestException | ||
| import io.tolgee.exceptions.NotFoundException | ||
| import io.tolgee.facade.InternalPropertiesSetterFacade | ||
| import jakarta.validation.Valid | ||
| import org.springframework.transaction.annotation.Transactional | ||
| import org.springframework.web.bind.annotation.PutMapping | ||
| import org.springframework.web.bind.annotation.RequestBody | ||
| import kotlin.reflect.KMutableProperty1 | ||
| import kotlin.reflect.KProperty1 | ||
| import kotlin.reflect.full.declaredMemberProperties | ||
| import kotlin.reflect.full.hasAnnotation | ||
|
|
||
| @InternalController(["internal/properties"]) | ||
| class PropertiesController( | ||
| val tolgeeProperties: TolgeeProperties, | ||
| private val tolgeeProperties: TolgeeProperties, | ||
| private val internalPropertiesSetterFacade: InternalPropertiesSetterFacade, | ||
| ) { | ||
| @PutMapping(value = ["/set"]) | ||
| @Transactional | ||
| fun setProperty( | ||
| @RequestBody @Valid | ||
| setPropertyDto: SetPropertyDto, | ||
| ) { | ||
| val name = setPropertyDto.name | ||
| var instance: Any = tolgeeProperties | ||
| name.split(".").let { namePath -> | ||
| namePath.forEachIndexed { idx, property -> | ||
| val isLast = idx == namePath.size - 1 | ||
| val props = instance::class.declaredMemberProperties | ||
| val prop = props.find { it.name == property } ?: throw NotFoundException() | ||
| if (isLast) { | ||
| (prop as? KMutableProperty1<Any, Any?>)?.let { | ||
| if (!it.hasAnnotation<E2eRuntimeMutable>()) { | ||
| io.tolgee.constants.Message.PROPERTY_NOT_MUTABLE | ||
| } | ||
| it.set(instance, setPropertyDto.value) | ||
| return | ||
| } ?: throw BadRequestException(io.tolgee.constants.Message.PROPERTY_NOT_MUTABLE) | ||
| } | ||
| instance = (prop as KProperty1<Any, Any?>).get(instance)!! | ||
| } | ||
| } | ||
| internalPropertiesSetterFacade.setProperty(tolgeeProperties, setPropertyDto) | ||
| } | ||
| } |
42 changes: 42 additions & 0 deletions
42
backend/development/src/main/kotlin/io/tolgee/facade/InternalPropertiesSetterFacade.kt
This file contains hidden or 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,42 @@ | ||
| package io.tolgee.facade | ||
|
|
||
| import io.tolgee.configuration.tolgee.E2eRuntimeMutable | ||
| import io.tolgee.dtos.request.SetPropertyDto | ||
| import io.tolgee.exceptions.BadRequestException | ||
| import io.tolgee.exceptions.NotFoundException | ||
| import org.springframework.stereotype.Component | ||
| import kotlin.reflect.KMutableProperty1 | ||
| import kotlin.reflect.KProperty1 | ||
| import kotlin.reflect.full.declaredMemberProperties | ||
| import kotlin.reflect.full.hasAnnotation | ||
|
|
||
| @Component | ||
| class InternalPropertiesSetterFacade { | ||
| fun setProperty( | ||
| root: Any, | ||
| setPropertyDto: SetPropertyDto, | ||
| onSet: (() -> Unit)? = null, | ||
| ) { | ||
| val name = setPropertyDto.name | ||
| var instance: Any = root | ||
| name.split(".").let { namePath -> | ||
| namePath.forEachIndexed { idx, property -> | ||
| val isLast = idx == namePath.size - 1 | ||
| val props = instance::class.declaredMemberProperties | ||
| val prop = props.find { it.name == property } ?: throw NotFoundException() | ||
| if (isLast) { | ||
| (prop as? KMutableProperty1<Any, Any?>)?.let { | ||
| if (!it.hasAnnotation<E2eRuntimeMutable>()) { | ||
| io.tolgee.constants.Message.PROPERTY_NOT_MUTABLE | ||
| } | ||
| it.set(instance, setPropertyDto.value) | ||
| onSet?.invoke() | ||
| return | ||
| } ?: throw BadRequestException(io.tolgee.constants.Message.PROPERTY_NOT_MUTABLE) | ||
| } | ||
| instance = (prop as KProperty1<Any, Any?>).get(instance) | ||
| ?: throw NotFoundException() | ||
| } | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or 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 hidden or 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
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.