feat(series-banner): 시리즈 배너를 언어별로 등록하고 노출한다
This commit is contained in:
@@ -56,7 +56,9 @@ class AdminContentSeriesBannerController(
|
||||
val banners = bannerService.getActiveBanners(pageable)
|
||||
val response = SeriesBannerListPageResponse(
|
||||
totalCount = banners.totalElements,
|
||||
content = banners.content.map { SeriesBannerResponse.from(it, imageHost) }
|
||||
content = banners.content.map {
|
||||
SeriesBannerResponse.from(it, imageHost, appendLanguageToSeriesTitle = true)
|
||||
}
|
||||
)
|
||||
ApiResponse.ok(response)
|
||||
}
|
||||
@@ -82,7 +84,7 @@ class AdminContentSeriesBannerController(
|
||||
val objectMapper = ObjectMapper()
|
||||
val request = objectMapper.readValue(requestString, SeriesBannerRegisterRequest::class.java)
|
||||
|
||||
val banner = bannerService.registerBanner(seriesId = request.seriesId, imagePath = "")
|
||||
val banner = bannerService.registerBanner(seriesId = request.seriesId, imagePath = "", lang = request.lang)
|
||||
val imagePath = saveImage(banner.id!!, image)
|
||||
val updatedBanner = bannerService.updateBanner(banner.id!!, imagePath)
|
||||
val response = SeriesBannerResponse.from(updatedBanner, imageHost)
|
||||
|
||||
@@ -2,10 +2,12 @@ package kr.co.vividnext.sodalive.admin.content.series.banner.dto
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import kr.co.vividnext.sodalive.content.series.main.banner.SeriesBanner
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
|
||||
// 시리즈 배너 등록 요청 DTO
|
||||
data class SeriesBannerRegisterRequest(
|
||||
@JsonProperty("seriesId") val seriesId: Long
|
||||
@JsonProperty("seriesId") val seriesId: Long,
|
||||
@JsonProperty("lang") val lang: Lang? = null
|
||||
)
|
||||
|
||||
// 시리즈 배너 수정 요청 DTO
|
||||
@@ -22,14 +24,30 @@ data class SeriesBannerResponse(
|
||||
val seriesTitle: String
|
||||
) {
|
||||
companion object {
|
||||
fun from(banner: SeriesBanner, imageHost: String): SeriesBannerResponse {
|
||||
fun from(
|
||||
banner: SeriesBanner,
|
||||
imageHost: String,
|
||||
appendLanguageToSeriesTitle: Boolean = false
|
||||
): SeriesBannerResponse {
|
||||
return SeriesBannerResponse(
|
||||
id = banner.id!!,
|
||||
imagePath = "$imageHost/${banner.imagePath}",
|
||||
seriesId = banner.series.id!!,
|
||||
seriesTitle = banner.series.title
|
||||
seriesTitle = if (appendLanguageToSeriesTitle) {
|
||||
"${banner.series.title} (${getLanguageLabel(banner.lang)})"
|
||||
} else {
|
||||
banner.series.title
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun getLanguageLabel(lang: Lang): String {
|
||||
return when (lang) {
|
||||
Lang.KO -> "한국어"
|
||||
Lang.EN -> "영어"
|
||||
Lang.JA -> "일본어"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.content.series.ContentSeriesService
|
||||
import kr.co.vividnext.sodalive.content.series.main.banner.ContentSeriesBannerService
|
||||
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
@@ -21,6 +22,7 @@ import org.springframework.web.bind.annotation.RestController
|
||||
class SeriesMainController(
|
||||
private val contentSeriesService: ContentSeriesService,
|
||||
private val bannerService: ContentSeriesBannerService,
|
||||
private val langContext: LangContext,
|
||||
private val memberContentPreferenceService: MemberContentPreferenceService,
|
||||
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
@@ -33,7 +35,7 @@ class SeriesMainController(
|
||||
if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
|
||||
val preference = resolvePreference(member)
|
||||
|
||||
val banners = bannerService.getActiveBanners(PageRequest.of(0, 10))
|
||||
val banners = bannerService.getDisplayBanners(PageRequest.of(0, 10), langContext.lang)
|
||||
.content
|
||||
.map {
|
||||
SeriesBannerResponse.from(it, imageHost)
|
||||
|
||||
@@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.content.series.main.banner
|
||||
|
||||
import kr.co.vividnext.sodalive.admin.content.series.AdminContentSeriesRepository
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import org.springframework.data.domain.Page
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.stereotype.Service
|
||||
@@ -16,22 +17,28 @@ class ContentSeriesBannerService(
|
||||
return bannerRepository.findByIsActiveTrueOrderBySortOrderAsc(pageable)
|
||||
}
|
||||
|
||||
fun getDisplayBanners(pageable: Pageable, lang: Lang): Page<SeriesBanner> {
|
||||
return bannerRepository.findByIsActiveTrueAndLangOrderBySortOrderAsc(lang, pageable)
|
||||
}
|
||||
|
||||
fun getBannerById(bannerId: Long): SeriesBanner {
|
||||
return bannerRepository.findById(bannerId)
|
||||
.orElseThrow { SodaException(messageKey = "series.banner.error.not_found") }
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun registerBanner(seriesId: Long, imagePath: String): SeriesBanner {
|
||||
fun registerBanner(seriesId: Long, imagePath: String, lang: Lang? = null): SeriesBanner {
|
||||
val series = seriesRepository.findByIdAndActiveTrue(seriesId)
|
||||
?: throw SodaException(messageKey = "series.banner.error.series_not_found")
|
||||
|
||||
val finalSortOrder = (bannerRepository.findMaxSortOrder() ?: 0) + 1
|
||||
val finalLang = lang ?: Lang.KO
|
||||
|
||||
val banner = SeriesBanner(
|
||||
imagePath = imagePath,
|
||||
series = series,
|
||||
sortOrder = finalSortOrder
|
||||
sortOrder = finalSortOrder,
|
||||
lang = finalLang
|
||||
)
|
||||
return bannerRepository.save(banner)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@ package kr.co.vividnext.sodalive.content.series.main.banner
|
||||
|
||||
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||
import kr.co.vividnext.sodalive.creator.admin.content.series.Series
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import javax.persistence.Column
|
||||
import javax.persistence.Entity
|
||||
import javax.persistence.EnumType
|
||||
import javax.persistence.Enumerated
|
||||
import javax.persistence.FetchType
|
||||
import javax.persistence.JoinColumn
|
||||
import javax.persistence.ManyToOne
|
||||
@@ -25,6 +29,10 @@ class SeriesBanner(
|
||||
// 정렬 순서 (낮을수록 먼저 표시)
|
||||
var sortOrder: Int = 0,
|
||||
|
||||
@Column(nullable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
var lang: Lang = Lang.KO,
|
||||
|
||||
// 활성화 여부 (소프트 삭제용)
|
||||
var isActive: Boolean = true
|
||||
) : BaseEntity()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package kr.co.vividnext.sodalive.content.series.main.banner
|
||||
|
||||
import kr.co.vividnext.sodalive.i18n.Lang
|
||||
import org.springframework.data.domain.Page
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
@@ -10,6 +11,8 @@ import org.springframework.stereotype.Repository
|
||||
interface SeriesBannerRepository : JpaRepository<SeriesBanner, Long> {
|
||||
fun findByIsActiveTrueOrderBySortOrderAsc(pageable: Pageable): Page<SeriesBanner>
|
||||
|
||||
fun findByIsActiveTrueAndLangOrderBySortOrderAsc(lang: Lang, pageable: Pageable): Page<SeriesBanner>
|
||||
|
||||
@Query("SELECT MAX(b.sortOrder) FROM SeriesBanner b WHERE b.isActive = true")
|
||||
fun findMaxSortOrder(): Int?
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user