Skip to content

Commit

Permalink
feat(mail): implement the send mail view
Browse files Browse the repository at this point in the history
  • Loading branch information
Rok93 authored Oct 4, 2021
1 parent 027980d commit 1c075b7
Show file tree
Hide file tree
Showing 15 changed files with 424 additions and 19 deletions.
5 changes: 4 additions & 1 deletion src/main/kotlin/apply/application/EvaluationDtos.kt
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,11 @@ data class EvaluationTargetData(
)

data class MailTargetResponse(
val name: String,
val email: String
)
) {
constructor(applicantResponse: ApplicantResponse) : this(applicantResponse.name, applicantResponse.email)
}

data class EvaluationItemScoreData(
@field:NotNull
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/apply/application/MailTargetService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class MailTargetService(
fun findMailTargets(evaluationId: Long, evaluationStatus: EvaluationStatus? = null): List<MailTargetResponse> {
val applicantIds = findEvaluationTargets(evaluationId, evaluationStatus).map { it.applicantId }
return applicantRepository.findAllById(applicantIds)
.map { MailTargetResponse(it.email) }
.map { MailTargetResponse(it.name, it.email) }
}

private fun findEvaluationTargets(evaluationId: Long, evaluationStatus: EvaluationStatus?): List<EvaluationTarget> {
Expand Down
14 changes: 14 additions & 0 deletions src/main/kotlin/apply/application/mail/MailData.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package apply.application.mail

import javax.validation.constraints.NotEmpty

data class MailData(
@field:NotEmpty
var subject: String = "",

@field:NotEmpty
var body: String = "",

@field:NotEmpty
var recipients: List<String> = emptyList()
)
4 changes: 3 additions & 1 deletion src/main/kotlin/apply/ui/admin/BaseLayout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package apply.ui.admin

import apply.ui.admin.cheater.CheatersView
import apply.ui.admin.evaluation.EvaluationsView
import apply.ui.admin.mail.MailFormView
import apply.ui.admin.mission.MissionSelectionsView
import apply.ui.admin.recruitment.RecruitmentsView
import apply.ui.admin.selections.SelectionsView
Expand All @@ -27,7 +28,8 @@ class BaseLayout : AppLayout() {
"평가 관리" to EvaluationsView::class.java,
"과제 관리" to MissionSelectionsView::class.java,
"선발 과정" to SelectionsView::class.java,
"부정 행위자" to CheatersView::class.java
"부정 행위자" to CheatersView::class.java,
"메일 발송" to MailFormView::class.java
)

init {
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/apply/ui/admin/cheater/CheaterForm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import com.vaadin.flow.component.select.Select
import com.vaadin.flow.component.textfield.TextArea
import support.views.BindingFormLayout
import support.views.createItemSelect
import support.views.createSearchBar
import support.views.createSearchBox

class CheaterForm() : BindingFormLayout<CheaterData>(CheaterData::class) {
private val applicants: Select<ApplicantResponse> = createItemSelect<ApplicantResponse>().apply {
Expand All @@ -26,7 +26,7 @@ class CheaterForm() : BindingFormLayout<CheaterData>(CheaterData::class) {
}

private fun createApplicantSearchBar(listener: (String) -> List<ApplicantResponse>): Component {
val searchBar = createSearchBar("회원 검색") {
val searchBar = createSearchBox("회원 검색") {
applicants.setItems(listener(it))
}
return HorizontalLayout(searchBar, applicants).apply {
Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/apply/ui/admin/cheater/CheatersView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout
import com.vaadin.flow.data.renderer.ComponentRenderer
import com.vaadin.flow.data.renderer.Renderer
import com.vaadin.flow.router.Route
import support.views.NO_NAME
import support.views.addSortableColumn
import support.views.addSortableDateTimeColumn
import support.views.createDeleteButtonWithDialog
Expand Down Expand Up @@ -50,7 +51,7 @@ class CheatersView(

private fun createCheaterGrid(): Grid<CheaterResponse> {
return Grid<CheaterResponse>(10).apply {
addSortableColumn("이름") { it.name ?: "(이름 없음)" }
addSortableColumn("이름") { it.name ?: NO_NAME }
addSortableColumn("이메일") { it.email }
addSortableDateTimeColumn("등록일", CheaterResponse::createdDateTime)
addSortableColumn("설명") { it.description }
Expand Down
102 changes: 102 additions & 0 deletions src/main/kotlin/apply/ui/admin/mail/GroupMailTargetDialog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package apply.ui.admin.mail

import apply.application.EvaluationService
import apply.application.MailTargetResponse
import apply.application.MailTargetService
import apply.application.RecruitmentResponse
import apply.application.RecruitmentService
import apply.domain.evaluation.Evaluation
import apply.domain.evaluationtarget.EvaluationStatus
import com.vaadin.flow.component.Component
import com.vaadin.flow.component.button.Button
import com.vaadin.flow.component.dialog.Dialog
import com.vaadin.flow.component.grid.Grid
import com.vaadin.flow.component.html.H2
import com.vaadin.flow.component.orderedlayout.FlexComponent
import com.vaadin.flow.component.orderedlayout.HorizontalLayout
import com.vaadin.flow.component.select.Select
import com.vaadin.flow.data.provider.ListDataProvider
import support.views.addSortableColumn
import support.views.createContrastButton
import support.views.createItemSelect
import support.views.createPrimaryButton
import support.views.toText

class GroupMailTargetDialog(
private val recruitmentService: RecruitmentService,
private val evaluationService: EvaluationService,
private val mailTargetService: MailTargetService,
private val accept: (Collection<MailTargetResponse>) -> Unit
) : Dialog() {
private val mailTargetsGrid: Grid<MailTargetResponse> = createMailTargetsGrid()

init {
add(H2("그룹 불러오기"), createSearchFilter(), mailTargetsGrid, createButtons())
width = "900px"
height = "70%"
open()
}

private fun createMailTargetsGrid(): Grid<MailTargetResponse> {
return Grid<MailTargetResponse>(10).apply {
addSortableColumn("이름", MailTargetResponse::name)
addSortableColumn("이메일", MailTargetResponse::email)
}
}

private fun createSearchFilter(): HorizontalLayout {
val evaluationItem = createItemSelect<Evaluation>("평가")
return HorizontalLayout(
createRecruitmentItem(evaluationItem), evaluationItem, createEvaluationStatusItem(evaluationItem),
).apply {
element.style.set("margin-bottom", "10px")
}
}

private fun createRecruitmentItem(evaluationItem: Select<Evaluation>): Select<RecruitmentResponse> {
return createItemSelect<RecruitmentResponse>("모집").apply {
setItems(*recruitmentService.findAll().toTypedArray())
setItemLabelGenerator { it.title }
addValueChangeListener {
evaluationItem.apply {
setItems(*evaluationService.findAllByRecruitmentId(it.value.id).toTypedArray())
setItemLabelGenerator { it.title }
}
}
}
}

private fun createEvaluationStatusItem(
evaluationItem: Select<Evaluation>
): Select<EvaluationStatus> {
return createItemSelect<EvaluationStatus>("평가 상태").apply {
setItems(*EvaluationStatus.values())
setItemLabelGenerator { it.toText() }
addValueChangeListener {
mailTargetsGrid.setItems(mailTargetService.findMailTargets(evaluationItem.value.id, it.value))
}
}
}

private fun createButtons(): Component {
return HorizontalLayout(createAddButton(), createCancelButton()).apply {
setSizeFull()
justifyContentMode = FlexComponent.JustifyContentMode.CENTER
element.style.set("margin-top", "10px")
}
}

private fun createAddButton(): Button {
return createPrimaryButton("추가") {
val dataProvider = mailTargetsGrid.dataProvider as ListDataProvider
accept(dataProvider.items)
close()
}
}

private fun createCancelButton(): Button {
return createContrastButton("취소") {
close()
}
}
}
73 changes: 73 additions & 0 deletions src/main/kotlin/apply/ui/admin/mail/IndividualMailTargetDialog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package apply.ui.admin.mail

import apply.application.ApplicantResponse
import apply.application.ApplicantService
import apply.application.MailTargetResponse
import com.vaadin.flow.component.Component
import com.vaadin.flow.component.button.Button
import com.vaadin.flow.component.dialog.Dialog
import com.vaadin.flow.component.grid.Grid
import com.vaadin.flow.component.html.H2
import com.vaadin.flow.component.orderedlayout.FlexComponent
import com.vaadin.flow.component.orderedlayout.HorizontalLayout
import com.vaadin.flow.data.renderer.ComponentRenderer
import com.vaadin.flow.data.renderer.Renderer
import support.views.addSortableColumn
import support.views.createContrastButton
import support.views.createPrimarySmallButton
import support.views.createSearchBox

class IndividualMailTargetDialog(
private val applicantService: ApplicantService,
private val accept: (MailTargetResponse) -> Unit
) : Dialog() {
private val mailTargetsGrid: Grid<ApplicantResponse> = createMailTargetsGrid()

init {
add(H2("개별 불러오기"), createSearchFilter(), mailTargetsGrid, createButtons())
width = "900px"
height = "70%"
open()
}

private fun createSearchFilter(): Component {
return HorizontalLayout(
createSearchBox { mailTargetsGrid.setItems(applicantService.findAllByKeyword(it)) }
).apply {
element.style.set("margin-top", "10px")
element.style.set("margin-bottom", "10px")
}
}

private fun createMailTargetsGrid(): Grid<ApplicantResponse> {
return Grid<ApplicantResponse>(10).apply {
addSortableColumn("이름", ApplicantResponse::name)
addSortableColumn("이메일", ApplicantResponse::email)
addColumn(createAddButton()).apply { isAutoWidth = true }
}
}

private fun createAddButton(): Renderer<ApplicantResponse> {
return ComponentRenderer<Component, ApplicantResponse> { applicantResponse ->
createPrimarySmallButton("추가") {
accept(MailTargetResponse(applicantResponse))
}.apply {
isDisableOnClick = true
}
}
}

private fun createButtons(): Component {
return HorizontalLayout(createCancelButton()).apply {
setSizeFull()
justifyContentMode = FlexComponent.JustifyContentMode.CENTER
element.style.set("margin-top", "10px")
}
}

private fun createCancelButton(): Button {
return createContrastButton("취소") {
close()
}
}
}
Loading

0 comments on commit 1c075b7

Please sign in to comment.