Skip to content

Commit

Permalink
feat: quick start guide (#1917)
Browse files Browse the repository at this point in the history
  • Loading branch information
stepan662 authored Dec 13, 2023
1 parent fa9d124 commit f640383
Show file tree
Hide file tree
Showing 135 changed files with 3,025 additions and 955 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.tolgee.api.v2.controllers

import io.tolgee.hateoas.quickStart.QuickStartModel
import io.tolgee.hateoas.quickStart.QuickStartModelAssembler
import io.tolgee.security.authentication.AuthenticationFacade
import io.tolgee.service.QuickStartService
import org.springframework.data.crossstore.ChangeSetPersister.NotFoundException
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/v2/quick-start")
class QuickStartController(
private val quickStartService: QuickStartService,
private val quickStartModelAssembler: QuickStartModelAssembler,
private val authenticationFacade: AuthenticationFacade
) {
@PutMapping("/steps/{step}/complete")
fun completeGuideStep(@PathVariable("step") step: String): QuickStartModel {
val entity = quickStartService.completeStep(authenticationFacade.authenticatedUser, step)
?: throw NotFoundException()
return quickStartModelAssembler.toModel(entity)
}

@PutMapping("/set-finished/{finished}")
fun setFinishedState(
@PathVariable finished: Boolean
): QuickStartModel {
val entity = quickStartService.setFinishState(authenticationFacade.authenticatedUser, finished)
return quickStartModelAssembler.toModel(entity)
}

@PutMapping("/set-open/{open}")
fun setOpenState(
@PathVariable open: Boolean
): QuickStartModel {
val entity = quickStartService.setOpenState(authenticationFacade.authenticatedUser, open)
return quickStartModelAssembler.toModel(entity)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,7 @@ import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.ResponseStatus
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
import javax.validation.Valid

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import io.tolgee.hateoas.organization.PrivateOrganizationModel
import io.tolgee.hateoas.organization.PrivateOrganizationModelAssembler
import io.tolgee.model.views.OrganizationView
import io.tolgee.security.authentication.AuthenticationFacade
import io.tolgee.service.QuickStartService
import io.tolgee.service.organization.OrganizationRoleService
import io.tolgee.service.security.UserPreferencesService
import org.springframework.stereotype.Component
Expand All @@ -15,7 +16,8 @@ class PreferredOrganizationFacade(
private val organizationRoleService: OrganizationRoleService,
private val userPreferencesService: UserPreferencesService,
private val privateOrganizationModelAssembler: PrivateOrganizationModelAssembler,
private val enabledFeaturesProvider: EnabledFeaturesProvider
private val enabledFeaturesProvider: EnabledFeaturesProvider,
private val quickStartService: QuickStartService
) {

fun getPreferred(): PrivateOrganizationModel? {
Expand All @@ -25,7 +27,9 @@ class PreferredOrganizationFacade(
val roleType = organizationRoleService.findType(preferredOrganization.id)
val view = OrganizationView.of(preferredOrganization, roleType)
return this.privateOrganizationModelAssembler.toModel(
view to enabledFeaturesProvider.get(view.organization.id)
view,
enabledFeaturesProvider.get(view.organization.id),
quickStartService.find(authenticationFacade.authenticatedUser.id, view.organization.id)
)
}
return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ class InitialDataModel(
var preferredOrganization: PrivateOrganizationModel? = null,
var languageTag: String? = null,
val eeSubscription: EeSubscriptionModel? = null,
var announcement: AnnouncementDto? = null
var announcement: AnnouncementDto? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.tolgee.hateoas.organization

import io.swagger.v3.oas.annotations.media.Schema
import io.tolgee.constants.Feature
import io.tolgee.hateoas.quickStart.QuickStartModel
import org.springframework.hateoas.RepresentationModel
import org.springframework.hateoas.server.core.Relation

Expand All @@ -11,5 +12,8 @@ open class PrivateOrganizationModel(
organizationModel: OrganizationModel,

@get:Schema(example = "Features organization has enabled")
val enabledFeatures: Array<Feature>
val enabledFeatures: Array<Feature>,

@get:Schema(example = "Quick start data for current user")
val quickStart: QuickStartModel?
) : IOrganizationModel by organizationModel, RepresentationModel<PrivateOrganizationModel>()
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
package io.tolgee.hateoas.organization

import io.tolgee.api.v2.controllers.organization.OrganizationController
import io.tolgee.constants.Feature
import io.tolgee.hateoas.quickStart.QuickStartModelAssembler
import io.tolgee.model.QuickStart
import io.tolgee.model.views.OrganizationView
import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport
import org.springframework.stereotype.Component

@Component
class PrivateOrganizationModelAssembler(
private val organizationModelAssembler: OrganizationModelAssembler
) : RepresentationModelAssemblerSupport<Pair<OrganizationView, Array<Feature>>, PrivateOrganizationModel>(
OrganizationController::class.java, PrivateOrganizationModel::class.java
private val organizationModelAssembler: OrganizationModelAssembler,
private val quickStartModelAssembler: QuickStartModelAssembler
) {
override fun toModel(data: Pair<OrganizationView, Array<Feature>>): PrivateOrganizationModel {
val (view, features) = data
fun toModel(
organization: OrganizationView,
features: Array<Feature>,
quickStart: QuickStart?
): PrivateOrganizationModel {
return PrivateOrganizationModel(
organizationModel = organizationModelAssembler.toModel(view),
enabledFeatures = features
organizationModel = organizationModelAssembler.toModel(organization),
enabledFeatures = features,
quickStart = quickStart?.let { quickStartModelAssembler.toModel(it) }
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.tolgee.hateoas.quickStart

import org.springframework.hateoas.RepresentationModel

data class QuickStartModel(
val finished: Boolean,
val completedSteps: MutableList<String>,
val open: Boolean
) : RepresentationModel<QuickStartModel>()
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.tolgee.hateoas.quickStart

import io.tolgee.model.QuickStart
import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport
import org.springframework.stereotype.Component

@Component
class QuickStartModelAssembler() : RepresentationModelAssemblerSupport<QuickStart, QuickStartModel>(
QuickStart::class.java, QuickStartModel::class.java
) {
override fun toModel(entity: QuickStart): QuickStartModel {
return QuickStartModel(
finished = entity.finished,
completedSteps = entity.completedSteps,
open = entity.open
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ data class PrivateUserAccountModel(
var accountType: UserAccount.AccountType,
var globalServerRole: UserAccount.Role,
val deletable: Boolean,
val needsSuperJwtToken: Boolean
val needsSuperJwtToken: Boolean,
) : RepresentationModel<PrivateUserAccountModel>()
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.springframework.stereotype.Component
@Component
class PrivateUserAccountModelAssembler(
private val avatarService: AvatarService,
private val mfaService: MfaService
private val mfaService: MfaService,
) : RepresentationModelAssemblerSupport<UserAccount, PrivateUserAccountModel>(
V2UserController::class.java, PrivateUserAccountModel::class.java
) {
Expand All @@ -27,7 +27,7 @@ class PrivateUserAccountModelAssembler(
accountType = entity.accountType ?: UserAccount.AccountType.LOCAL,
globalServerRole = entity.role ?: UserAccount.Role.USER,
deletable = entity.isDeletable,
needsSuperJwtToken = entity.needsSuperJwt
needsSuperJwtToken = entity.needsSuperJwt,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package io.tolgee.controllers

import io.tolgee.component.demoProject.DemoProjectData
import io.tolgee.dtos.request.auth.SignUpDto
import io.tolgee.fixtures.andIsOk
import io.tolgee.fixtures.waitForNotThrowing
import io.tolgee.testing.AbstractControllerTest
import io.tolgee.testing.assert
import io.tolgee.testing.assertions.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc

@AutoConfigureMockMvc
class DemoProjectTest :
AbstractControllerTest() {

@Test
fun `creates demo project`() {
val demoOrganization = "Oh my organization"
val dto = SignUpDto(
name = "Pavel Novak",
password = "aaaaaaaaa",
email = "aaaa@aaaa.com",
organizationName = demoOrganization
)
performPost("/api/public/sign_up", dto).andIsOk
val project = executeInNewTransaction {
val organization = organizationRepository.findAllByName(demoOrganization).single()
val project = organization.projects.single()
assertThat(project.name).isEqualTo("Demo project")
val keyCount = DemoProjectData.translations["en"]!!.size
project.keys.assert.hasSize(keyCount)
val key = project.keys.find { it.name == "add-item-add-button" }!!
key.keyScreenshotReferences.assert.hasSize(1)
val screenshot = key.keyScreenshotReferences.single().screenshot
screenshot.keyScreenshotReferences.assert.hasSize(keyCount)
key.translations.assert.hasSize(3)
project
}

waitForNotThrowing {
executeInNewTransaction {
val stats = languageStatsService.getLanguageStats(project.id)
stats.forEach {
it.reviewedWords.assert.isGreaterThan(0)
}
}
}
}
}
Loading

0 comments on commit f640383

Please sign in to comment.