Skip to content
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

Support multiple resource selection in Project Wizard #1180

Merged
merged 11 commits into from
Aug 16, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,17 @@ class CreateProject @Inject constructor(
fun createAllBooks(
sourceLanguage: Language,
targetLanguage: Language,
projectMode: ProjectMode
projectMode: ProjectMode,
resourceId: String? = null
): Completable {
val isVerseByVerse = projectMode != ProjectMode.TRANSLATION
return collectionRepo.getRootSources()
.flattenAsObservable {
it
}
.filter {
it.resourceContainer?.language == sourceLanguage
.filter { collection ->
collection.resourceContainer?.language == sourceLanguage &&
(resourceId?.let { collection.resourceContainer?.identifier == resourceId } ?: true)
}
.firstOrError()
.flatMap { rootCollection ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,32 +64,36 @@ class NewTranslationCard2(
}
vbox {
addClass("translation-card__body")
label {
addClass("translation-card__language")
textProperty().bind(
sourceLanguageProperty.stringBinding { source ->
togglePseudoClass("unset", source == null)
source?.name ?: "???"
}
)
graphic = FontIcon(Material.HEARING)
}
label {
addClass("translation-card__divider")
sourceLanguageProperty.onChangeAndDoNow { source ->
togglePseudoClass("unset", source == null)
vbox {
label(messages["sourceLanguage"]) {
addClass("h5", "translation-card__subtitle")
}
label {
addClass("translation-card__language")
textProperty().bind(
sourceLanguageProperty.stringBinding { source ->
togglePseudoClass("unset", source == null)
source?.name ?: "???"
}
)
graphic = FontIcon(Material.HEARING)
}
graphic = FontIcon(MaterialDesign.MDI_CHEVRON_DOUBLE_DOWN)
}
label {
addClass("translation-card__language")
textProperty().bind(
targetLanguageProperty.stringBinding { target ->
togglePseudoClass("unset", target == null)
target?.name ?: "???"
}
)
graphic = FontIcon(MaterialDesign.MDI_VOICE)
separator()
vbox {
label(messages["targetLanguage"]) {
addClass("h5", "translation-card__subtitle")
}
label {
addClass("translation-card__language")
textProperty().bind(
targetLanguageProperty.stringBinding { target ->
togglePseudoClass("unset", target == null)
target?.name ?: "???"
}
)
graphic = FontIcon(MaterialDesign.MDI_VOICE)
}
}
}
button(messages["cancel"]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ class TranslationCard2(
private val sourceLanguage: Language,
private val targetLanguage: Language,
private val mode: ProjectMode,
private val resourceSlug: String,
selectedProjectGroupProperty: ObservableValue<ProjectGroupKey>
) : ButtonBase() {

val cardTitleProperty = SimpleStringProperty(
MessageFormat.format(messages["translationMode"], messages[mode.titleKey])
MessageFormat.format(messages["projectModeTitle"], resourceSlug.uppercase(), messages[mode.titleKey])
)
val sourceLanguageProperty = SimpleObjectProperty(sourceLanguage)
val targetLanguageProperty = SimpleObjectProperty(targetLanguage)
Expand Down Expand Up @@ -87,7 +88,7 @@ class TranslationCard2(
}
}

private fun getKey() = ProjectGroupKey(sourceLanguage.slug, targetLanguage.slug, mode)
private fun getKey() = ProjectGroupKey(sourceLanguage.slug, targetLanguage.slug, resourceSlug, mode)
}

class TranslationCardSkin2(card: TranslationCard2) : SkinBase<TranslationCard2>(card) {
Expand Down Expand Up @@ -159,17 +160,24 @@ class ActiveTranslationCardSkin(card: TranslationCard2) : SkinBase<TranslationCa
}
vbox {
addClass("translation-card__body")
label(sourceLanguageProperty) {
addClass("translation-card__language")
graphic = FontIcon(Material.HEARING)
}
label {
addClass("translation-card__divider")
graphic = FontIcon(MaterialDesign.MDI_CHEVRON_DOUBLE_DOWN)
vbox {
label(messages["sourceLanguage"]) {
addClass("h5", "translation-card__subtitle")
}
label(sourceLanguageProperty) {
addClass("translation-card__language")
graphic = FontIcon(Material.HEARING)
}
}
label(targetLanguageProperty) {
addClass("translation-card__language")
graphic = FontIcon(MaterialDesign.MDI_VOICE)
separator()
vbox {
label(messages["targetLanguage"]) {
addClass("h5", "translation-card__subtitle")
}
label(targetLanguageProperty) {
addClass("translation-card__language")
graphic = FontIcon(MaterialDesign.MDI_VOICE)
}
}
}
}
Expand All @@ -186,6 +194,7 @@ fun EventTarget.translationCard(
sourceLanguage: Language,
targetLanguage: Language,
mode: ProjectMode,
resourceSlug: String,
selectedCardProperty: ObjectProperty<ProjectGroupKey> = SimpleObjectProperty(),
op: TranslationCard2.() -> Unit = {}
) = TranslationCard2(sourceLanguage, targetLanguage, mode, selectedCardProperty).attachTo(this, op)
) = TranslationCard2(sourceLanguage, targetLanguage, mode, resourceSlug, selectedCardProperty).attachTo(this, op)
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ package org.wycliffeassociates.otter.jvm.controls.event
import org.wycliffeassociates.otter.common.data.primitives.Language
import org.wycliffeassociates.otter.common.data.workbook.WorkbookDescriptor
import org.wycliffeassociates.otter.common.domain.resourcecontainer.ImportResult
import org.wycliffeassociates.otter.jvm.controls.model.ResourceVersion
import tornadofx.FXEvent
import java.io.File

class LanguageSelectedEvent(val item: Language) : FXEvent()
class ResourceVersionSelectedEvent(val resourceVersion: ResourceVersion): FXEvent()

class ProjectImportFinishEvent(
val result: ImportResult,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ class ProjectGroupCardModel(
val sourceLanguage: Language,
val targetLanguage: Language,
val mode: ProjectMode,
val resourceSlug: String,
val modifiedTs: LocalDateTime?,
val books: ObservableList<WorkbookDescriptorWrapper>
) {
val booksModel = books.map { it.workbookDescriptor }
fun getKey() = ProjectGroupKey(sourceLanguage.slug, targetLanguage.slug, mode)
fun getKey() = ProjectGroupKey(sourceLanguage.slug, targetLanguage.slug, resourceSlug, mode)
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ package org.wycliffeassociates.otter.jvm.controls.model

import org.wycliffeassociates.otter.common.data.primitives.ProjectMode

data class ProjectGroupKey(val sourceLanguage: String, val targetLanguage: String, val mode: ProjectMode)
data class ProjectGroupKey(val sourceLanguage: String, val targetLanguage: String, val resourceSlug: String, val mode: ProjectMode)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Copyright (C) 2020-2024 Wycliffe Associates
*
* This file is part of Orature.
*
* Orature is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Orature is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Orature. If not, see <https://www.gnu.org/licenses/>.
*/
package org.wycliffeassociates.otter.jvm.controls.model

data class ResourceVersion(val slug: String, val name: String)
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ data class WorkbookDescriptorWrapper(
val lastModified = workbookDescriptor.targetCollection.modifiedTs
val sourceLanguage = workbookDescriptor.sourceLanguage
val targetLanguage = workbookDescriptor.targetLanguage
val sourceMetadataSlug = workbookDescriptor.sourceCollection.resourceContainer!!.identifier
val anthology = workbookDescriptor.anthology

val progressProperty = SimpleDoubleProperty(0.0)
Expand Down
9 changes: 7 additions & 2 deletions jvm/controls/src/main/resources/css/translation-card-2.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/
.translation-card {
-fx-padding: 12px 16px;
-fx-spacing: 8px;
-fx-spacing: 12px;
-fx-background-radius: 16px;
-fx-background-color: -wa-foreground;
-fx-background-color: transparent;
Expand Down Expand Up @@ -56,6 +56,7 @@

.translation-card__header .translation-card__header__text {
-fx-text-fill: -wa-regular-text;
-fx-font-weight: bold;
}

.translation-card__header .ikonli-font-icon,
Expand All @@ -65,10 +66,14 @@
}

.translation-card__body {
-fx-spacing: 3;
-fx-spacing: 12px;
-fx-alignment: center-left;
}

.translation-card__subtitle {
-fx-font-size: 1em;
}

.translation-card__language {
-fx-graphic-text-gap: 0.6em;
-fx-text-fill: -wa-regular-text;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Copyright (C) 2020-2024 Wycliffe Associates
*
* This file is part of Orature.
*
* Orature is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Orature is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Orature. If not, see <https://www.gnu.org/licenses/>.
*/
package org.wycliffeassociates.otter.jvm.workbookapp.ui.components.tableview

import javafx.scene.control.TableRow
import org.wycliffeassociates.otter.jvm.controls.event.ResourceVersionSelectedEvent
import org.wycliffeassociates.otter.jvm.controls.model.ResourceVersion
import tornadofx.*

class ResourceVersionTableRow : TableRow<ResourceVersion>() {
override fun updateItem(item: ResourceVersion?, empty: Boolean) {
super.updateItem(item, empty)

if (item == null || empty) {
isMouseTransparent = true
return
}

isMouseTransparent = isDisable
isFocusTraversable = false

setOnMouseClicked {
if (it.clickCount == 1) { // avoid double fire()
FX.eventbus.fire(ResourceVersionSelectedEvent(item))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* Copyright (C) 2020-2024 Wycliffe Associates
*
* This file is part of Orature.
*
* Orature is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Orature is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Orature. If not, see <https://www.gnu.org/licenses/>.
*/
package org.wycliffeassociates.otter.jvm.workbookapp.ui.components.tableview

import javafx.collections.ObservableList
import javafx.event.EventTarget
import javafx.scene.control.TableView
import javafx.scene.input.KeyCode
import javafx.scene.input.KeyEvent
import javafx.scene.layout.Priority
import javafx.scene.layout.Region
import org.wycliffeassociates.otter.jvm.controls.event.ResourceVersionSelectedEvent
import org.wycliffeassociates.otter.jvm.controls.model.ResourceVersion
import tornadofx.*
import tornadofx.FX.Companion.messages

class ResourceVersionTableView(
resources: ObservableList<ResourceVersion>
): TableView<ResourceVersion>(resources) {
init {
addClass("wa-table-view")
vgrow = Priority.ALWAYS
columnResizePolicy = CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN
placeholder = Region() // shows nothing when table is empty

column(messages["resource_name"], String::class) {
addClass("table-view__column-header-row")
setCellValueFactory { it.value.name.toProperty() }
cellFormat {
graphic = label(item) {
addClass("h4", "h4--80")
tooltip(item)
}
}
}
column(messages["code"], String::class).apply {
addClass("table-view__column-header-row")
setCellValueFactory { it.value.slug.toProperty() }
cellFormat {
graphic = label(item) { addClass("normal-text") }
}
}

setRowFactory { ResourceVersionTableRow() }

/* accessibility */
focusedProperty().onChange {
if (it && selectionModel.selectedIndex < 0) {
selectionModel.select(0)
focusModel.focus(0)
}
}
addEventFilter(KeyEvent.KEY_PRESSED) { keyEvent ->
if (keyEvent.code == KeyCode.SPACE || keyEvent.code == KeyCode.ENTER) {
selectedItem?.let {
FX.eventbus.fire(ResourceVersionSelectedEvent(it))
}
}
}
}
}

fun EventTarget.resourceVersionTableView(
values: ObservableList<ResourceVersion>,
op: ResourceVersionTableView.() -> Unit = {}
) = ResourceVersionTableView(values).attachTo(this, op)
Loading
Loading