From ae8c405e277649e0c659207585a6788c5a239096 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Wed, 3 Apr 2019 18:01:47 -0400 Subject: [PATCH 01/18] Test app to load resources with dummy data --- .../resourcecard/model/ResourceCardItem.kt | 27 ++++++- .../widgets/resourcecard/view/ResourceCard.kt | 13 ++- .../resourcestestapp/app/ResourceCardApp.kt | 39 +++++++++ .../styles/ProgressBannerStyles.kt | 18 +++++ .../styles/ResourceListStyles.kt | 34 ++++++++ .../resourcestestapp/view/ProgressBanner.kt | 44 +++++++++++ .../view/ResourceListFragment.kt | 36 +++++++++ .../resourcestestapp/view/ResourcesView.kt | 20 +++++ .../viewmodel/ResourceCardViewModel.kt | 24 ++++++ .../viewmodel/ResourcesViewModel.kt | 79 +++++++++++++++++++ src/main/resources/Messages_en.properties | 1 + 11 files changed, 328 insertions(+), 7 deletions(-) create mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/app/ResourceCardApp.kt create mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ProgressBannerStyles.kt create mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ResourceListStyles.kt create mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ProgressBanner.kt create mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt create mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt create mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourceCardViewModel.kt create mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourcesViewModel.kt diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt index 537a0b40..edb1f6c3 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt @@ -1,5 +1,26 @@ package org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model -data class ResourceCardItem( - val title: String -) +import javafx.beans.property.DoubleProperty +import javafx.beans.property.SimpleDoubleProperty +import org.wycliffeassociates.otter.common.data.workbook.AssociatedAudio +import org.wycliffeassociates.otter.common.data.workbook.Resource + +data class ResourceCardItem(val resource: Resource, val onSelect: () -> Unit) { + // Want resource to be a val so we can navigate to the takes page with the resource + val title: String = resource.title.text + val titleProgressProperty: DoubleProperty = resource.titleAudio.progressProperty() + val bodyProgressProperty: DoubleProperty? = resource.bodyAudio?.progressProperty() + val hasBodyAudio: Boolean = resource.bodyAudio != null + + private fun AssociatedAudio.progressProperty(): DoubleProperty { + val progressProperty = SimpleDoubleProperty(0.0) + this.selected.subscribe { + progressProperty.set( if (it.value != null) 1.0 else 0.0) + } + return progressProperty + } + + fun isCompleted(): Boolean { + return resource.isCompleted() + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt index eda026b3..a826cb99 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt @@ -15,7 +15,8 @@ import org.wycliffeassociates.otter.jvm.statusindicator.control.statusindicator import tornadofx.* import tornadofx.FX.Companion.messages -class ResourceCard(private val resource: ResourceCardItem) : HBox() { + +class ResourceCard(private val item: ResourceCardItem) : HBox() { val isCurrentResourceProperty = SimpleBooleanProperty(false) var primaryColorProperty = SimpleObjectProperty(Color.ORANGE) @@ -33,17 +34,18 @@ class ResourceCard(private val resource: ResourceCardItem) : HBox() { add( statusindicator { initForResourceCard() - progress = 1.0 + progressProperty.bind(item.titleProgressProperty) } ) add( statusindicator { initForResourceCard() - progress = 0.0 + item.bodyProgressProperty?.let { progressProperty.bind(it) } + isVisible = item.hasBodyAudio } ) } - text(resource.title) + text(item.title) maxWidth = 150.0 } @@ -59,6 +61,9 @@ class ResourceCard(private val resource: ResourceCardItem) : HBox() { graphic = MaterialIconView(MaterialIcon.APPS, "25px") maxWidth = 500.0 text = messages["viewRecordings"] + action { + item.onSelect() + } } ) } diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/app/ResourceCardApp.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/app/ResourceCardApp.kt new file mode 100644 index 00000000..78cf28f3 --- /dev/null +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/app/ResourceCardApp.kt @@ -0,0 +1,39 @@ +package org.wycliffeassociates.otter.jvm.resourcestestapp.app + +import io.reactivex.Observable +import javafx.beans.value.ObservableValue +import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceCardItem +import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceGroupCardItem +import org.wycliffeassociates.otter.jvm.resourcestestapp.view.ResourcesView +import tornadofx.* + +class ResourceCardApp : App(ResourcesView::class) { + + companion object { + // Temporary functions to create dummy data +// fun createResourceGroups(): List { +// val groups: MutableList = mutableListOf() +// for (i in 0..175) { +// groups.add(ResourceGroupCardItem("Verse $i Resources", createListOfResources(i, (i % 5) + 1))) +// } +// return groups +// } +// +// private fun createListOfResources(verseNum: Int, n: Int): Observable { +// val obs = Observable.fromPublisher { pub -> +// for (i in 1..n) { +// pub.onNext(resourceCardItem(verseNum, i)) +// } +// } +// return obs +// } +// +// private fun resourceCardItem(verseNum: Int, resourceNum: Int): ResourceCardItem { +// return ResourceCardItem("Verse $verseNum, Title $resourceNum") +// } + } +} + +fun main(args: Array) { + launch(args) +} diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ProgressBannerStyles.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ProgressBannerStyles.kt new file mode 100644 index 00000000..aade9bac --- /dev/null +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ProgressBannerStyles.kt @@ -0,0 +1,18 @@ +package org.wycliffeassociates.otter.jvm.resourcestestapp.styles + +import org.wycliffeassociates.otter.jvm.app.theme.AppTheme +import tornadofx.* + +class ProgressBannerStyles : Stylesheet() { + + companion object { + val progressBanner by cssclass() + } + + init { + progressBanner { + padding = box(10.px, 100.px, 20.px, 70.px) + backgroundColor += AppTheme.colors.white + } + } +} diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ResourceListStyles.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ResourceListStyles.kt new file mode 100644 index 00000000..1f1009e1 --- /dev/null +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ResourceListStyles.kt @@ -0,0 +1,34 @@ +package org.wycliffeassociates.otter.jvm.resourcestestapp.styles + +import javafx.scene.paint.Color +import tornadofx.* + +typealias LinearU = Dimension + +class ResourceListStyles : Stylesheet() { + + companion object { + val resourceGroupList by cssclass() + } + + init { + resourceGroupList { + borderColor += box(Color.TRANSPARENT) // Necessary for border under status bar banner to stay visible + padding = box(0.px, 0.px, 0.px, 80.px) // Left "margin" + scrollBar { + +margin(0.px, 0.px, 0.px, 80.px) // Margin between scrollbar and right side of cards + } + + listCell { + // Add space between the cards (top margin) + // But need to make the "margin" at least as large as the dropshadow offsets + +margin(30.px, 4.px, 0.px, 0.px) + } + } + } + + private fun margin(top: LinearU, right: LinearU, bottom: LinearU, left: LinearU) = mixin { + padding = box(top, right, bottom, left) + backgroundInsets += box(top, right, bottom, left) + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ProgressBanner.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ProgressBanner.kt new file mode 100644 index 00000000..e0ab2ff5 --- /dev/null +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ProgressBanner.kt @@ -0,0 +1,44 @@ +package org.wycliffeassociates.otter.jvm.resourcestestapp.view + +import com.jfoenix.controls.JFXCheckBox +import javafx.scene.layout.Priority +import javafx.scene.layout.VBox +import javafx.scene.paint.Color +import org.wycliffeassociates.otter.jvm.resourcestestapp.styles.ProgressBannerStyles +import tornadofx.* + +class ProgressBanner : VBox() { + init { + importStylesheet() + + addClass(ProgressBannerStyles.progressBanner) + spacing = 10.0 + hbox { + label("Translation Notes") { +// graphic = AppStyles.tNGraphic() + } + region { + hgrow = Priority.ALWAYS + } + add( + JFXCheckBox("Hide Completed").apply { + isDisableVisualFocus = true + } + ) + } + // TODO: Status bar + region { + hgrow = Priority.ALWAYS + style { + backgroundColor += Color.ORANGE + prefHeight = 8.px + } + } + } +} + +fun progressbanner(init: ProgressBanner.() -> Unit = {}): ProgressBanner { + val pb = ProgressBanner() + pb.init() + return pb +} \ No newline at end of file diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt new file mode 100644 index 00000000..06ff1471 --- /dev/null +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt @@ -0,0 +1,36 @@ +package org.wycliffeassociates.otter.jvm.resourcestestapp.view + +import javafx.scene.layout.Priority +import org.wycliffeassociates.otter.jvm.app.ui.mainscreen.view.MainScreenStyles +import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.view.resourcegroupcard +import org.wycliffeassociates.otter.jvm.resourcestestapp.styles.ResourceListStyles +import org.wycliffeassociates.otter.jvm.resourcestestapp.viewmodel.ResourcesViewModel +import tornadofx.* + +class ResourceListFragment : Fragment() { + + val viewModel: ResourcesViewModel by inject() + + init { + importStylesheet() + importStylesheet() + } + + override val root = vbox { + + addClass(MainScreenStyles.main) + + add(progressbanner{}) + + listview(viewModel.resourceGroups) { + vgrow = Priority.ALWAYS // This needs to be here + cellFormat { + graphic = cache(it.title) { + resourcegroupcard(it) + } + } + isFocusTraversable = false + addClass(ResourceListStyles.resourceGroupList) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt new file mode 100644 index 00000000..e353bc7e --- /dev/null +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt @@ -0,0 +1,20 @@ +package org.wycliffeassociates.otter.jvm.resourcestestapp.view + +import tornadofx.View +import tornadofx.Workspace +import tornadofx.removeFromParent +import tornadofx.vbox + +class ResourcesView : View() { + + override val root = vbox {} + + var activeFragment: Workspace = Workspace() + + init { + activeFragment.header.removeFromParent() + + activeFragment.dock() + add(activeFragment) + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourceCardViewModel.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourceCardViewModel.kt new file mode 100644 index 00000000..9597634e --- /dev/null +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourceCardViewModel.kt @@ -0,0 +1,24 @@ +package org.wycliffeassociates.otter.jvm.resourcestestapp.viewmodel + +import javafx.beans.property.SimpleBooleanProperty +import org.wycliffeassociates.otter.common.data.workbook.Resource + +class ResourceCardViewModel(private val resource: Resource) { + + val titleTakeSelected = SimpleBooleanProperty(false) + val bodyTakeSelected = SimpleBooleanProperty(false) + + init { + resource.titleAudio.selected.subscribe { + titleTakeSelected.set(it != null) + } + + resource.bodyAudio?.selected?.subscribe { + bodyTakeSelected.set(it != null) + } + } + + fun navigateToTakesPage() { + // TODO + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourcesViewModel.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourcesViewModel.kt new file mode 100644 index 00000000..d5217a15 --- /dev/null +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourcesViewModel.kt @@ -0,0 +1,79 @@ +package org.wycliffeassociates.otter.jvm.resourcestestapp.viewmodel + +import com.github.thomasnield.rxkotlinfx.observeOnFx +import javafx.collections.FXCollections +import javafx.collections.ObservableList +import org.wycliffeassociates.otter.common.data.workbook.* +import org.wycliffeassociates.otter.jvm.app.ui.inject.Injector +import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceCardItem +import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceGroupCardItem +import tornadofx.ViewModel + +class ResourcesViewModel : ViewModel() { + + // All of this is just to get what we will already have + private val injector: Injector by inject() + private val collectionRepository = injector.collectionRepo + private val workbookRepository = injector.workbookRepository + var workbook: Workbook + + var chapter: Chapter + var resourceSlug = "tn" + var resourceGroups: ObservableList = FXCollections.observableArrayList() + +// private fun resourceCardGroupItem(element: BookElement, slug: String): ResourceGroupCardItem { +// +// // Find the correct resource group +// val resourceGroup = element.resources.first { +// it.info.slug == slug +// } +// return ResourceGroupCardItem( +// element.title, +// resourceGroup.resources.map { +// ResourceCardItem(it) { +// navigateToTakesPage(it) +// } +// } +// ) +// } + + private fun resourceCardGroupItem(element: BookElement, slug: String): ResourceGroupCardItem? { + + // Find the correct resource group + val resourceGroup = element.resources.firstOrNull { + it.info.slug == slug + } + return resourceGroup?.let { rg -> + ResourceGroupCardItem( + element.title, + rg.resources.map { + ResourceCardItem(it) { + navigateToTakesPage(it) + } + } + ) + } + } + + private fun navigateToTakesPage(resource: Resource) { + // TODO use navigator + println(resource.title) + } + + init { + // All of this is just to get what we will already have + val targetProject = collectionRepository.getRootProjects().blockingGet().first() + val sourceProject = collectionRepository.getSource(targetProject).blockingGet() + workbook = workbookRepository.get(sourceProject, targetProject) + chapter = workbook.target.chapters.blockingFirst() +// chapter = workbook.source.chapters.blockingFirst() + + chapter.chunks.map { + resourceCardGroupItem(it, resourceSlug) + }.startWith { + resourceCardGroupItem(chapter, resourceSlug) + }.subscribe { + resourceGroups.add(it) + } + } +} \ No newline at end of file diff --git a/src/main/resources/Messages_en.properties b/src/main/resources/Messages_en.properties index bb214511..34f06930 100644 --- a/src/main/resources/Messages_en.properties +++ b/src/main/resources/Messages_en.properties @@ -11,6 +11,7 @@ load = Load open = Open record = RECORD viewTakes =VIEW TAKES +viewRecordings = VIEW RECORDINGS edit = EDIT chapter = Chapter verse=Verse From 8ecb54750794f4e7b055a9823c37f20e34d95364 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Thu, 16 May 2019 21:06:56 -0400 Subject: [PATCH 02/18] Loading resources from the workbook --- .../resourcecard/view/ResourceGroupCard.kt | 14 +++-- .../repositories/ResourceRepository.kt | 58 +++++++++++++++---- .../viewmodel/ResourcesViewModel.kt | 37 ++++-------- 3 files changed, 68 insertions(+), 41 deletions(-) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt index c67f233b..7de6f24b 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt @@ -1,5 +1,6 @@ package org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.view +import javafx.application.Platform import javafx.scene.layout.VBox import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceGroupCardItem import tornadofx.* @@ -10,10 +11,15 @@ class ResourceGroupCard(group: ResourceGroupCardItem) : VBox() { addClass(ResourceGroupCardStyles.resourceGroupCard) label(group.title) - group.resources.subscribe { - add( - resourcecard(it) - ) + + group.resources.buffer(10).subscribe { items -> + Platform.runLater { + items.forEach { + add( + resourcecard(it) + ) + } + } } } } diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt index a347ce7e..b73ab589 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt @@ -7,6 +7,8 @@ import io.reactivex.rxkotlin.toObservable import io.reactivex.schedulers.Schedulers import jooq.Tables.* import org.jooq.Condition +import org.jooq.SelectConditionStep +import org.jooq.Record import org.jooq.DSLContext import org.wycliffeassociates.otter.common.collections.multimap.MultiMap import org.wycliffeassociates.otter.common.data.model.Collection @@ -14,6 +16,7 @@ import org.wycliffeassociates.otter.common.data.model.Content import org.wycliffeassociates.otter.common.data.workbook.ResourceInfo import org.wycliffeassociates.otter.common.persistence.repositories.IResourceRepository import org.wycliffeassociates.otter.jvm.persistence.database.AppDatabase +import org.wycliffeassociates.otter.jvm.persistence.database.daos.ContentEntityTable import org.wycliffeassociates.otter.jvm.persistence.database.daos.RecordMappers import org.wycliffeassociates.otter.jvm.persistence.entities.CollectionEntity import org.wycliffeassociates.otter.jvm.persistence.entities.ContentEntity @@ -70,9 +73,8 @@ class ResourceRepository(private val database: AppDatabase) : IResourceRepositor return database.dsl .selectDistinct(DUBLIN_CORE_ENTITY.asterisk()) .from(RESOURCE_LINK) - .join(CONTENT_ENTITY).on(CONTENT_ENTITY.ID.eq(RESOURCE_LINK.CONTENT_FK)) .join(DUBLIN_CORE_ENTITY).on(DUBLIN_CORE_ENTITY.ID.eq(RESOURCE_LINK.DUBLIN_CORE_FK)) - .where(CONTENT_ENTITY.COLLECTION_FK.eq(collection.id)) + .where(RESOURCE_LINK.COLLECTION_FK.eq(collection.id)) .fetch(RecordMappers.Companion::mapToResourceMetadataEntity) .map(this::buildResourceInfo) } @@ -87,7 +89,14 @@ class ResourceRepository(private val database: AppDatabase) : IResourceRepositor .map(this::buildResourceInfo) } - override fun getResources(collection: Collection, resourceInfo: ResourceInfo): Observable { + /** + * Returns all resources for which the resource content's COLLECTION_FK field references this collection. + * This will return resources about the chapter as well as all resources about the chapter's chunks. + */ + override fun getResourcesForCollectionAndChildren( + collection: Collection, + resourceInfo: ResourceInfo + ): Observable { return getResources({ table -> table.COLLECTION_FK.eq(collection.id) }, resourceInfo) } @@ -95,6 +104,26 @@ class ResourceRepository(private val database: AppDatabase) : IResourceRepositor return getResources({ table -> table.ID.eq(content.id) }, resourceInfo) } + /** + * Returns collection-specific resources + */ + override fun getResources(collection: Collection, resourceInfo: ResourceInfo): Observable { + val metadata = mapToResourceMetadataEntity[resourceInfo] + ?: return Observable.empty() + + val help = CONTENT_ENTITY.`as`("help") + + val selectStatement = database.dsl + .selectDistinct(help.asterisk()) + .from(RESOURCE_LINK) + .join(COLLECTION_ENTITY).on(COLLECTION_ENTITY.ID.eq(RESOURCE_LINK.COLLECTION_FK)) + .join(help).on(RESOURCE_LINK.RESOURCE_CONTENT_FK.eq(help.ID)) + .where(RESOURCE_LINK.DUBLIN_CORE_FK.eq(metadata.id)) + .and(COLLECTION_ENTITY.ID.eq(collection.id)) + + return getResources(help, selectStatement) + } + private fun getResources( condition: (jooq.tables.ContentEntity) -> Condition, resourceInfo: ResourceInfo @@ -105,14 +134,23 @@ class ResourceRepository(private val database: AppDatabase) : IResourceRepositor val main = CONTENT_ENTITY.`as`("main") val help = CONTENT_ENTITY.`as`("help") + val selectStatement = database.dsl + .selectDistinct(help.asterisk()) + .from(RESOURCE_LINK) + .join(main).on(main.ID.eq(RESOURCE_LINK.CONTENT_FK)) + .join(help).on(help.ID.eq(RESOURCE_LINK.RESOURCE_CONTENT_FK)) + .where(RESOURCE_LINK.DUBLIN_CORE_FK.eq(metadata.id)) + .and(condition(main)) + + return getResources(help, selectStatement) + } + + private fun getResources( + help: ContentEntityTable, + selectStatement: SelectConditionStep + ): Observable { val contentStreamObservable = Observable.fromCallable { - database.dsl - .selectDistinct(help.asterisk()) - .from(RESOURCE_LINK) - .join(main).on(main.ID.eq(RESOURCE_LINK.CONTENT_FK)) - .join(help).on(help.ID.eq(RESOURCE_LINK.RESOURCE_CONTENT_FK)) - .where(RESOURCE_LINK.DUBLIN_CORE_FK.eq(metadata.id)) - .and(condition(main)) + selectStatement .orderBy(help.START, help.SORT) .fetchStream() .map { RecordMappers.mapToContentEntity(it, help) } diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourcesViewModel.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourcesViewModel.kt index d5217a15..5c891aa0 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourcesViewModel.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourcesViewModel.kt @@ -1,6 +1,6 @@ package org.wycliffeassociates.otter.jvm.resourcestestapp.viewmodel -import com.github.thomasnield.rxkotlinfx.observeOnFx +import javafx.application.Platform import javafx.collections.FXCollections import javafx.collections.ObservableList import org.wycliffeassociates.otter.common.data.workbook.* @@ -21,25 +21,8 @@ class ResourcesViewModel : ViewModel() { var resourceSlug = "tn" var resourceGroups: ObservableList = FXCollections.observableArrayList() -// private fun resourceCardGroupItem(element: BookElement, slug: String): ResourceGroupCardItem { -// -// // Find the correct resource group -// val resourceGroup = element.resources.first { -// it.info.slug == slug -// } -// return ResourceGroupCardItem( -// element.title, -// resourceGroup.resources.map { -// ResourceCardItem(it) { -// navigateToTakesPage(it) -// } -// } -// ) -// } + private fun resourceGroupCardItem(element: BookElement, slug: String): ResourceGroupCardItem? { - private fun resourceCardGroupItem(element: BookElement, slug: String): ResourceGroupCardItem? { - - // Find the correct resource group val resourceGroup = element.resources.firstOrNull { it.info.slug == slug } @@ -61,19 +44,19 @@ class ResourcesViewModel : ViewModel() { } init { - // All of this is just to get what we will already have val targetProject = collectionRepository.getRootProjects().blockingGet().first() val sourceProject = collectionRepository.getSource(targetProject).blockingGet() workbook = workbookRepository.get(sourceProject, targetProject) - chapter = workbook.target.chapters.blockingFirst() -// chapter = workbook.source.chapters.blockingFirst() + chapter = workbook.source.chapters.blockingFirst() chapter.chunks.map { - resourceCardGroupItem(it, resourceSlug) - }.startWith { - resourceCardGroupItem(chapter, resourceSlug) - }.subscribe { - resourceGroups.add(it) + resourceGroupCardItem(it, resourceSlug) + }.startWith( + resourceGroupCardItem(chapter, resourceSlug) + ).buffer(2).subscribe { // Buffering by 2 prevents the list UI from jumping while groups are loading + Platform.runLater { + resourceGroups.addAll(it) + } } } } \ No newline at end of file From 4244e27408f3835c98168ee24ea6686eddd7c6d5 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Fri, 17 May 2019 11:33:30 -0400 Subject: [PATCH 03/18] Using WorkbookHeader --- .../jvm/resourcestestapp/view/ResourceListFragment.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt index 06ff1471..9f94977e 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt @@ -3,6 +3,7 @@ package org.wycliffeassociates.otter.jvm.resourcestestapp.view import javafx.scene.layout.Priority import org.wycliffeassociates.otter.jvm.app.ui.mainscreen.view.MainScreenStyles import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.view.resourcegroupcard +import org.wycliffeassociates.otter.jvm.app.widgets.workbookheader.workbookheader import org.wycliffeassociates.otter.jvm.resourcestestapp.styles.ResourceListStyles import org.wycliffeassociates.otter.jvm.resourcestestapp.viewmodel.ResourcesViewModel import tornadofx.* @@ -20,7 +21,12 @@ class ResourceListFragment : Fragment() { addClass(MainScreenStyles.main) - add(progressbanner{}) + add( + workbookheader { + labelText = viewModel.chapter.title + " Resources" + filterText = "Hide Completed" + } + ) listview(viewModel.resourceGroups) { vgrow = Priority.ALWAYS // This needs to be here From 7c205dc73a9fea03b10d5021b4ed46a45c2d5925 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Fri, 17 May 2019 13:53:18 -0400 Subject: [PATCH 04/18] Rendering resource title text content --- build.gradle | 3 +++ .../widgets/resourcecard/model/ResourceCardItem.kt | 14 +++++++++++++- .../app/widgets/resourcecard/view/ResourceCard.kt | 2 -- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index ec35ae6b..d9a6127c 100644 --- a/build.gradle +++ b/build.gradle @@ -129,6 +129,9 @@ dependencies { implementation 'org.wycliffeassociates:8woc2018-common' implementation 'org.wycliffeassociates:kotlin-resource-container' implementation 'com.github.WycliffeAssociates:jdenticon-kotlin:-SNAPSHOT' + + //Atlassian commonmark (for rendering markdown) + implementation 'com.atlassian.commonmark:commonmark:0.12.1' } //tell gradle what to put in the jar diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt index edb1f6c3..cf26ec47 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt @@ -4,10 +4,12 @@ import javafx.beans.property.DoubleProperty import javafx.beans.property.SimpleDoubleProperty import org.wycliffeassociates.otter.common.data.workbook.AssociatedAudio import org.wycliffeassociates.otter.common.data.workbook.Resource +import org.commonmark.parser.Parser +import org.commonmark.renderer.text.TextContentRenderer data class ResourceCardItem(val resource: Resource, val onSelect: () -> Unit) { // Want resource to be a val so we can navigate to the takes page with the resource - val title: String = resource.title.text + val title: String = getTitleTextContent() val titleProgressProperty: DoubleProperty = resource.titleAudio.progressProperty() val bodyProgressProperty: DoubleProperty? = resource.bodyAudio?.progressProperty() val hasBodyAudio: Boolean = resource.bodyAudio != null @@ -20,6 +22,16 @@ data class ResourceCardItem(val resource: Resource, val onSelect: () -> Unit) { return progressProperty } + companion object { + val parser: Parser = Parser.builder().build() + val renderer: TextContentRenderer = TextContentRenderer.builder().build() + } + + private fun getTitleTextContent(): String { + val document = parser.parse(resource.title.text) + return renderer.render(document) + } + fun isCompleted(): Boolean { return resource.isCompleted() } diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt index a826cb99..af07086c 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt @@ -15,7 +15,6 @@ import org.wycliffeassociates.otter.jvm.statusindicator.control.statusindicator import tornadofx.* import tornadofx.FX.Companion.messages - class ResourceCard(private val item: ResourceCardItem) : HBox() { val isCurrentResourceProperty = SimpleBooleanProperty(false) @@ -75,7 +74,6 @@ class ResourceCard(private val item: ResourceCardItem) : HBox() { trackFill = Color.LIGHTGRAY indicatorRadius = 3.0 } - } fun resourcecard(resource: ResourceCardItem, init: ResourceCard.() -> Unit = {}): ResourceCard { From 7eb8b8788ea22ec65e571977dcf16b2710d21cd1 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Fri, 17 May 2019 14:07:50 -0400 Subject: [PATCH 05/18] Created standalone ResourceListView --- .../styles/ResourceListStyles.kt | 2 +- .../resourcecard/view/ResourceListView.kt | 21 +++++++++++++++++++ .../view/ResourceListFragment.kt | 19 +++++------------ 3 files changed, 27 insertions(+), 15 deletions(-) rename src/main/kotlin/org/wycliffeassociates/otter/jvm/{resourcestestapp => app/widgets/resourcecard}/styles/ResourceListStyles.kt (93%) create mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceListView.kt diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ResourceListStyles.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/styles/ResourceListStyles.kt similarity index 93% rename from src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ResourceListStyles.kt rename to src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/styles/ResourceListStyles.kt index 1f1009e1..5f1a941c 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ResourceListStyles.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/styles/ResourceListStyles.kt @@ -1,4 +1,4 @@ -package org.wycliffeassociates.otter.jvm.resourcestestapp.styles +package org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.styles import javafx.scene.paint.Color import tornadofx.* diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceListView.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceListView.kt new file mode 100644 index 00000000..66563e1e --- /dev/null +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceListView.kt @@ -0,0 +1,21 @@ +package org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.view + +import javafx.collections.ObservableList +import javafx.scene.control.ListView +import javafx.scene.layout.Priority +import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceGroupCardItem +import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.styles.ResourceListStyles +import tornadofx.* + +class ResourceListView(items: ObservableList): ListView(items) { + init { + vgrow = Priority.ALWAYS // This needs to be here + cellFormat { + graphic = cache(it.title) { + resourcegroupcard(it) + } + } + isFocusTraversable = false + addClass(ResourceListStyles.resourceGroupList) + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt index 9f94977e..5747f7fe 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt @@ -1,10 +1,9 @@ package org.wycliffeassociates.otter.jvm.resourcestestapp.view -import javafx.scene.layout.Priority import org.wycliffeassociates.otter.jvm.app.ui.mainscreen.view.MainScreenStyles -import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.view.resourcegroupcard import org.wycliffeassociates.otter.jvm.app.widgets.workbookheader.workbookheader -import org.wycliffeassociates.otter.jvm.resourcestestapp.styles.ResourceListStyles +import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.styles.ResourceListStyles +import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.view.ResourceListView import org.wycliffeassociates.otter.jvm.resourcestestapp.viewmodel.ResourcesViewModel import tornadofx.* @@ -27,16 +26,8 @@ class ResourceListFragment : Fragment() { filterText = "Hide Completed" } ) - - listview(viewModel.resourceGroups) { - vgrow = Priority.ALWAYS // This needs to be here - cellFormat { - graphic = cache(it.title) { - resourcegroupcard(it) - } - } - isFocusTraversable = false - addClass(ResourceListStyles.resourceGroupList) - } + add( + ResourceListView(viewModel.resourceGroups) + ) } } \ No newline at end of file From d786c37aa7955481e9ca1769d052b2d098f22212 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Mon, 20 May 2019 10:08:22 -0400 Subject: [PATCH 06/18] Move files out of testapp folder --- .../resources}/view/ResourceListFragment.kt | 4 +- .../viewmodel/ResourcesViewModel.kt | 55 +++++++++---------- .../styles/ProgressBannerStyles.kt | 18 ------ .../resourcestestapp/view/ProgressBanner.kt | 44 --------------- .../resourcestestapp/view/ResourcesView.kt | 22 +++++++- .../viewmodel/ResourceCardViewModel.kt | 24 -------- 6 files changed, 48 insertions(+), 119 deletions(-) rename src/main/kotlin/org/wycliffeassociates/otter/jvm/{resourcestestapp => app/ui/resources}/view/ResourceListFragment.kt (87%) rename src/main/kotlin/org/wycliffeassociates/otter/jvm/{resourcestestapp => app/ui/resources}/viewmodel/ResourcesViewModel.kt (64%) delete mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ProgressBannerStyles.kt delete mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ProgressBanner.kt delete mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourceCardViewModel.kt diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/view/ResourceListFragment.kt similarity index 87% rename from src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt rename to src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/view/ResourceListFragment.kt index 5747f7fe..047ccc41 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourceListFragment.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/view/ResourceListFragment.kt @@ -1,10 +1,10 @@ -package org.wycliffeassociates.otter.jvm.resourcestestapp.view +package org.wycliffeassociates.otter.jvm.app.ui.resources.view import org.wycliffeassociates.otter.jvm.app.ui.mainscreen.view.MainScreenStyles import org.wycliffeassociates.otter.jvm.app.widgets.workbookheader.workbookheader import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.styles.ResourceListStyles import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.view.ResourceListView -import org.wycliffeassociates.otter.jvm.resourcestestapp.viewmodel.ResourcesViewModel +import org.wycliffeassociates.otter.jvm.app.ui.resources.viewmodel.ResourcesViewModel import tornadofx.* class ResourceListFragment : Fragment() { diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourcesViewModel.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt similarity index 64% rename from src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourcesViewModel.kt rename to src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt index 5c891aa0..e59cb216 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourcesViewModel.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt @@ -1,28 +1,43 @@ -package org.wycliffeassociates.otter.jvm.resourcestestapp.viewmodel +package org.wycliffeassociates.otter.jvm.app.ui.resources.viewmodel import javafx.application.Platform +import javafx.beans.property.SimpleObjectProperty +import javafx.beans.property.SimpleStringProperty import javafx.collections.FXCollections import javafx.collections.ObservableList import org.wycliffeassociates.otter.common.data.workbook.* -import org.wycliffeassociates.otter.jvm.app.ui.inject.Injector import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceCardItem import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceGroupCardItem -import tornadofx.ViewModel +import tornadofx.* class ResourcesViewModel : ViewModel() { + val activeWorkbookProperty = SimpleObjectProperty() + val workbook: Workbook + get() = activeWorkbookProperty.value - // All of this is just to get what we will already have - private val injector: Injector by inject() - private val collectionRepository = injector.collectionRepo - private val workbookRepository = injector.workbookRepository - var workbook: Workbook + val activeChapterProperty = SimpleObjectProperty() + val chapter: Chapter + get() = activeChapterProperty.value + + val activeResourceSlugProperty = SimpleStringProperty() + val resourceSlug: String + get() = activeResourceSlugProperty.value - var chapter: Chapter - var resourceSlug = "tn" var resourceGroups: ObservableList = FXCollections.observableArrayList() - private fun resourceGroupCardItem(element: BookElement, slug: String): ResourceGroupCardItem? { + fun loadResourceGroups() { + chapter.chunks.map { + resourceGroupCardItem(it, resourceSlug) + }.startWith( + resourceGroupCardItem(chapter, resourceSlug) + ).buffer(2).subscribe { // Buffering by 2 prevents the list UI from jumping while groups are loading + Platform.runLater { + resourceGroups.addAll(it) + } + } + } + private fun resourceGroupCardItem(element: BookElement, slug: String): ResourceGroupCardItem? { val resourceGroup = element.resources.firstOrNull { it.info.slug == slug } @@ -40,23 +55,5 @@ class ResourcesViewModel : ViewModel() { private fun navigateToTakesPage(resource: Resource) { // TODO use navigator - println(resource.title) - } - - init { - val targetProject = collectionRepository.getRootProjects().blockingGet().first() - val sourceProject = collectionRepository.getSource(targetProject).blockingGet() - workbook = workbookRepository.get(sourceProject, targetProject) - chapter = workbook.source.chapters.blockingFirst() - - chapter.chunks.map { - resourceGroupCardItem(it, resourceSlug) - }.startWith( - resourceGroupCardItem(chapter, resourceSlug) - ).buffer(2).subscribe { // Buffering by 2 prevents the list UI from jumping while groups are loading - Platform.runLater { - resourceGroups.addAll(it) - } - } } } \ No newline at end of file diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ProgressBannerStyles.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ProgressBannerStyles.kt deleted file mode 100644 index aade9bac..00000000 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/styles/ProgressBannerStyles.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.wycliffeassociates.otter.jvm.resourcestestapp.styles - -import org.wycliffeassociates.otter.jvm.app.theme.AppTheme -import tornadofx.* - -class ProgressBannerStyles : Stylesheet() { - - companion object { - val progressBanner by cssclass() - } - - init { - progressBanner { - padding = box(10.px, 100.px, 20.px, 70.px) - backgroundColor += AppTheme.colors.white - } - } -} diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ProgressBanner.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ProgressBanner.kt deleted file mode 100644 index e0ab2ff5..00000000 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ProgressBanner.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.wycliffeassociates.otter.jvm.resourcestestapp.view - -import com.jfoenix.controls.JFXCheckBox -import javafx.scene.layout.Priority -import javafx.scene.layout.VBox -import javafx.scene.paint.Color -import org.wycliffeassociates.otter.jvm.resourcestestapp.styles.ProgressBannerStyles -import tornadofx.* - -class ProgressBanner : VBox() { - init { - importStylesheet() - - addClass(ProgressBannerStyles.progressBanner) - spacing = 10.0 - hbox { - label("Translation Notes") { -// graphic = AppStyles.tNGraphic() - } - region { - hgrow = Priority.ALWAYS - } - add( - JFXCheckBox("Hide Completed").apply { - isDisableVisualFocus = true - } - ) - } - // TODO: Status bar - region { - hgrow = Priority.ALWAYS - style { - backgroundColor += Color.ORANGE - prefHeight = 8.px - } - } - } -} - -fun progressbanner(init: ProgressBanner.() -> Unit = {}): ProgressBanner { - val pb = ProgressBanner() - pb.init() - return pb -} \ No newline at end of file diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt index e353bc7e..2da7dd91 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt @@ -1,20 +1,38 @@ package org.wycliffeassociates.otter.jvm.resourcestestapp.view +import org.wycliffeassociates.otter.jvm.app.ui.inject.Injector +import org.wycliffeassociates.otter.jvm.app.ui.resources.view.ResourceListFragment +import org.wycliffeassociates.otter.jvm.app.ui.resources.viewmodel.ResourcesViewModel import tornadofx.View import tornadofx.Workspace import tornadofx.removeFromParent import tornadofx.vbox class ResourcesView : View() { + val viewModel: ResourcesViewModel by inject() + private val injector: Injector by inject() + private val collectionRepository = injector.collectionRepo + private val workbookRepository = injector.workbookRepository override val root = vbox {} var activeFragment: Workspace = Workspace() init { - activeFragment.header.removeFromParent() + setupViewModel() + activeFragment.header.removeFromParent() activeFragment.dock() add(activeFragment) } -} \ No newline at end of file + + private fun setupViewModel() { + val targetProject = collectionRepository.getRootProjects().blockingGet().first() + val sourceProject = collectionRepository.getSource(targetProject).blockingGet() + val workbook = workbookRepository.get(sourceProject, targetProject) + viewModel.activeWorkbookProperty.set(workbook) + viewModel.activeChapterProperty.set(workbook.source.chapters.blockingFirst()) + viewModel.activeResourceSlugProperty.set("tn") + viewModel.loadResourceGroups() + } +} diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourceCardViewModel.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourceCardViewModel.kt deleted file mode 100644 index 9597634e..00000000 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/viewmodel/ResourceCardViewModel.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.wycliffeassociates.otter.jvm.resourcestestapp.viewmodel - -import javafx.beans.property.SimpleBooleanProperty -import org.wycliffeassociates.otter.common.data.workbook.Resource - -class ResourceCardViewModel(private val resource: Resource) { - - val titleTakeSelected = SimpleBooleanProperty(false) - val bodyTakeSelected = SimpleBooleanProperty(false) - - init { - resource.titleAudio.selected.subscribe { - titleTakeSelected.set(it != null) - } - - resource.bodyAudio?.selected?.subscribe { - bodyTakeSelected.set(it != null) - } - } - - fun navigateToTakesPage() { - // TODO - } -} \ No newline at end of file From 15eacbd69cbe548f993b8cff9bbabe651b8debec Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Mon, 20 May 2019 10:13:00 -0400 Subject: [PATCH 07/18] Removed entry point files to be added in new branch --- .../resourcestestapp/app/ResourceCardApp.kt | 39 ------------------- .../resourcestestapp/view/ResourcesView.kt | 38 ------------------ 2 files changed, 77 deletions(-) delete mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/app/ResourceCardApp.kt delete mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/app/ResourceCardApp.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/app/ResourceCardApp.kt deleted file mode 100644 index 78cf28f3..00000000 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/app/ResourceCardApp.kt +++ /dev/null @@ -1,39 +0,0 @@ -package org.wycliffeassociates.otter.jvm.resourcestestapp.app - -import io.reactivex.Observable -import javafx.beans.value.ObservableValue -import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceCardItem -import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceGroupCardItem -import org.wycliffeassociates.otter.jvm.resourcestestapp.view.ResourcesView -import tornadofx.* - -class ResourceCardApp : App(ResourcesView::class) { - - companion object { - // Temporary functions to create dummy data -// fun createResourceGroups(): List { -// val groups: MutableList = mutableListOf() -// for (i in 0..175) { -// groups.add(ResourceGroupCardItem("Verse $i Resources", createListOfResources(i, (i % 5) + 1))) -// } -// return groups -// } -// -// private fun createListOfResources(verseNum: Int, n: Int): Observable { -// val obs = Observable.fromPublisher { pub -> -// for (i in 1..n) { -// pub.onNext(resourceCardItem(verseNum, i)) -// } -// } -// return obs -// } -// -// private fun resourceCardItem(verseNum: Int, resourceNum: Int): ResourceCardItem { -// return ResourceCardItem("Verse $verseNum, Title $resourceNum") -// } - } -} - -fun main(args: Array) { - launch(args) -} diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt deleted file mode 100644 index 2da7dd91..00000000 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/resourcestestapp/view/ResourcesView.kt +++ /dev/null @@ -1,38 +0,0 @@ -package org.wycliffeassociates.otter.jvm.resourcestestapp.view - -import org.wycliffeassociates.otter.jvm.app.ui.inject.Injector -import org.wycliffeassociates.otter.jvm.app.ui.resources.view.ResourceListFragment -import org.wycliffeassociates.otter.jvm.app.ui.resources.viewmodel.ResourcesViewModel -import tornadofx.View -import tornadofx.Workspace -import tornadofx.removeFromParent -import tornadofx.vbox - -class ResourcesView : View() { - val viewModel: ResourcesViewModel by inject() - private val injector: Injector by inject() - private val collectionRepository = injector.collectionRepo - private val workbookRepository = injector.workbookRepository - - override val root = vbox {} - - var activeFragment: Workspace = Workspace() - - init { - setupViewModel() - - activeFragment.header.removeFromParent() - activeFragment.dock() - add(activeFragment) - } - - private fun setupViewModel() { - val targetProject = collectionRepository.getRootProjects().blockingGet().first() - val sourceProject = collectionRepository.getSource(targetProject).blockingGet() - val workbook = workbookRepository.get(sourceProject, targetProject) - viewModel.activeWorkbookProperty.set(workbook) - viewModel.activeChapterProperty.set(workbook.source.chapters.blockingFirst()) - viewModel.activeResourceSlugProperty.set("tn") - viewModel.loadResourceGroups() - } -} From bd153c9286f4a70a5ca75d25de7205105efea6cf Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Mon, 20 May 2019 10:45:00 -0400 Subject: [PATCH 08/18] Remove dead code --- .../jvm/app/widgets/resourcecard/model/ResourceCardItem.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt index cf26ec47..f19e3196 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt @@ -31,8 +31,4 @@ data class ResourceCardItem(val resource: Resource, val onSelect: () -> Unit) { val document = parser.parse(resource.title.text) return renderer.render(document) } - - fun isCompleted(): Boolean { - return resource.isCompleted() - } } \ No newline at end of file From 1859e298b28d71d3c618b51facf9fd198c15535e Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Mon, 20 May 2019 11:48:20 -0400 Subject: [PATCH 09/18] Minor formatting fixes --- .../otter/jvm/app/ui/resources/view/ResourceListFragment.kt | 2 -- .../jvm/app/widgets/resourcecard/model/ResourceCardItem.kt | 1 - .../otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt | 1 - .../app/widgets/resourcecard/view/ResourceGroupCardStyles.kt | 1 - 4 files changed, 5 deletions(-) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/view/ResourceListFragment.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/view/ResourceListFragment.kt index 047ccc41..e009299a 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/view/ResourceListFragment.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/view/ResourceListFragment.kt @@ -8,14 +8,12 @@ import org.wycliffeassociates.otter.jvm.app.ui.resources.viewmodel.ResourcesView import tornadofx.* class ResourceListFragment : Fragment() { - val viewModel: ResourcesViewModel by inject() init { importStylesheet() importStylesheet() } - override val root = vbox { addClass(MainScreenStyles.main) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt index f19e3196..939e2a92 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt @@ -8,7 +8,6 @@ import org.commonmark.parser.Parser import org.commonmark.renderer.text.TextContentRenderer data class ResourceCardItem(val resource: Resource, val onSelect: () -> Unit) { - // Want resource to be a val so we can navigate to the takes page with the resource val title: String = getTitleTextContent() val titleProgressProperty: DoubleProperty = resource.titleAudio.progressProperty() val bodyProgressProperty: DoubleProperty? = resource.bodyAudio?.progressProperty() diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt index af07086c..e41cb492 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceCard.kt @@ -16,7 +16,6 @@ import tornadofx.* import tornadofx.FX.Companion.messages class ResourceCard(private val item: ResourceCardItem) : HBox() { - val isCurrentResourceProperty = SimpleBooleanProperty(false) var primaryColorProperty = SimpleObjectProperty(Color.ORANGE) var primaryColor: Color by primaryColorProperty diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCardStyles.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCardStyles.kt index 843f4be7..4c061be4 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCardStyles.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCardStyles.kt @@ -6,7 +6,6 @@ import javafx.scene.text.FontWeight import tornadofx.* class ResourceGroupCardStyles : Stylesheet() { - companion object { val resourceGroupCard by cssclass() } From 40137eb392ad8d0919e4cc240de48a6d09b8bb13 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Mon, 20 May 2019 15:03:05 -0400 Subject: [PATCH 10/18] Refactored resource group card item constructor --- .../resources/viewmodel/ResourcesViewModel.kt | 23 +++---------- .../model/ResourceGroupCardItem.kt | 34 ++++++++++++++++++- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt index e59cb216..d43471fc 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt @@ -8,6 +8,7 @@ import javafx.collections.ObservableList import org.wycliffeassociates.otter.common.data.workbook.* import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceCardItem import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceGroupCardItem +import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.resourceGroupCardItem import tornadofx.* class ResourcesViewModel : ViewModel() { @@ -26,10 +27,10 @@ class ResourcesViewModel : ViewModel() { var resourceGroups: ObservableList = FXCollections.observableArrayList() fun loadResourceGroups() { - chapter.chunks.map { - resourceGroupCardItem(it, resourceSlug) + chapter.chunks.map { chunk -> + resourceGroupCardItem(chunk, resourceSlug) { navigateToTakesPage(it) } }.startWith( - resourceGroupCardItem(chapter, resourceSlug) + resourceGroupCardItem(chapter, resourceSlug) { navigateToTakesPage(it) } ).buffer(2).subscribe { // Buffering by 2 prevents the list UI from jumping while groups are loading Platform.runLater { resourceGroups.addAll(it) @@ -37,22 +38,6 @@ class ResourcesViewModel : ViewModel() { } } - private fun resourceGroupCardItem(element: BookElement, slug: String): ResourceGroupCardItem? { - val resourceGroup = element.resources.firstOrNull { - it.info.slug == slug - } - return resourceGroup?.let { rg -> - ResourceGroupCardItem( - element.title, - rg.resources.map { - ResourceCardItem(it) { - navigateToTakesPage(it) - } - } - ) - } - } - private fun navigateToTakesPage(resource: Resource) { // TODO use navigator } diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt index bbea70ab..0c9a4b2a 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt @@ -1,8 +1,40 @@ package org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model import io.reactivex.Observable +import org.wycliffeassociates.otter.common.data.workbook.* data class ResourceGroupCardItem( val title: String, val resources: Observable -) \ No newline at end of file +) + +fun resourceGroupCardItem(element: BookElement, slug: String, onSelect: (Resource) -> Unit): ResourceGroupCardItem? { + return findResourceGroup(element, slug)?.let { rg -> + ResourceGroupCardItem( + getGroupTitle(element), + getResourceCardItems(rg, onSelect) + ) + } +} + +private fun findResourceGroup(element: BookElement, slug: String): ResourceGroup? { + return element.resources.firstOrNull { + it.info.slug == slug + } +} + +private fun getGroupTitle(element: BookElement): String { + return when (element) { + is Chapter -> "Chapter " + element.title + is Chunk -> "Chunk " + element.title + else -> element.title + } +} + +private fun getResourceCardItems(rg: ResourceGroup, onSelect: (Resource) -> Unit): Observable { + return rg.resources.map { + ResourceCardItem(it) { + onSelect(it) + } + } +} \ No newline at end of file From 38e7f3d793c510cc7a5aee0273b8fb87c1adc5f1 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Tue, 21 May 2019 15:40:33 -0400 Subject: [PATCH 11/18] PR Comments: Internalization & constants --- .../otter/jvm/app/ui/resources/view/ResourceListFragment.kt | 4 ++-- .../app/widgets/resourcecard/model/ResourceGroupCardItem.kt | 6 ++++-- .../jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt | 3 ++- src/main/resources/Messages_en.properties | 3 +++ 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/view/ResourceListFragment.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/view/ResourceListFragment.kt index e009299a..0ceb7b9c 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/view/ResourceListFragment.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/view/ResourceListFragment.kt @@ -20,8 +20,8 @@ class ResourceListFragment : Fragment() { add( workbookheader { - labelText = viewModel.chapter.title + " Resources" - filterText = "Hide Completed" + labelText = "${viewModel.chapter.title} ${messages["resources"]}" + filterText = messages["hideCompleted"] } ) add( diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt index 0c9a4b2a..669e3868 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt @@ -2,6 +2,8 @@ package org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model import io.reactivex.Observable import org.wycliffeassociates.otter.common.data.workbook.* +import tornadofx.* +import tornadofx.FX.Companion.messages data class ResourceGroupCardItem( val title: String, @@ -25,8 +27,8 @@ private fun findResourceGroup(element: BookElement, slug: String): ResourceGroup private fun getGroupTitle(element: BookElement): String { return when (element) { - is Chapter -> "Chapter " + element.title - is Chunk -> "Chunk " + element.title + is Chapter -> "${messages["chapter"]} ${element.title}" + is Chunk -> "${messages["chunk"]} ${element.title}" else -> element.title } } diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt index 7de6f24b..fede5f95 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt @@ -6,13 +6,14 @@ import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceG import tornadofx.* class ResourceGroupCard(group: ResourceGroupCardItem) : VBox() { + private val RENDER_BATCH_SIZE = 10 init { importStylesheet() addClass(ResourceGroupCardStyles.resourceGroupCard) label(group.title) - group.resources.buffer(10).subscribe { items -> + group.resources.buffer(RENDER_BATCH_SIZE).subscribe { items -> Platform.runLater { items.forEach { add( diff --git a/src/main/resources/Messages_en.properties b/src/main/resources/Messages_en.properties index 34f06930..43ae0469 100644 --- a/src/main/resources/Messages_en.properties +++ b/src/main/resources/Messages_en.properties @@ -14,6 +14,7 @@ viewTakes =VIEW TAKES viewRecordings = VIEW RECORDINGS edit = EDIT chapter = Chapter +chunk = Chunk verse=Verse take=Take select = Select @@ -74,3 +75,5 @@ selectBook = Select a Book home = Home profile = Profile settings = Settings +resources = Resources +hideCompleted = Hide Completed From c0e87f1b986345ed9463e79e4c204dacd9fed024 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Tue, 21 May 2019 15:46:54 -0400 Subject: [PATCH 12/18] PR Comment: Kill progressProperty subscription --- .../resources/viewmodel/ResourcesViewModel.kt | 7 ++---- .../resourcecard/model/ResourceCardItem.kt | 9 +++++++- .../model/ResourceGroupCardItem.kt | 8 ++++++- .../model/ResourceGroupCardItemList.kt | 22 +++++++++++++++++++ 4 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItemList.kt diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt index d43471fc..51b81a0c 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt @@ -3,11 +3,8 @@ package org.wycliffeassociates.otter.jvm.app.ui.resources.viewmodel import javafx.application.Platform import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleStringProperty -import javafx.collections.FXCollections -import javafx.collections.ObservableList import org.wycliffeassociates.otter.common.data.workbook.* -import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceCardItem -import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceGroupCardItem +import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceGroupCardItemList import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.resourceGroupCardItem import tornadofx.* @@ -24,7 +21,7 @@ class ResourcesViewModel : ViewModel() { val resourceSlug: String get() = activeResourceSlugProperty.value - var resourceGroups: ObservableList = FXCollections.observableArrayList() + var resourceGroups: ResourceGroupCardItemList = ResourceGroupCardItemList(mutableListOf()) fun loadResourceGroups() { chapter.chunks.map { chunk -> diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt index 939e2a92..65a05716 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt @@ -1,5 +1,6 @@ package org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model +import io.reactivex.disposables.CompositeDisposable import javafx.beans.property.DoubleProperty import javafx.beans.property.SimpleDoubleProperty import org.wycliffeassociates.otter.common.data.workbook.AssociatedAudio @@ -9,15 +10,21 @@ import org.commonmark.renderer.text.TextContentRenderer data class ResourceCardItem(val resource: Resource, val onSelect: () -> Unit) { val title: String = getTitleTextContent() + private val disposables = CompositeDisposable() val titleProgressProperty: DoubleProperty = resource.titleAudio.progressProperty() val bodyProgressProperty: DoubleProperty? = resource.bodyAudio?.progressProperty() val hasBodyAudio: Boolean = resource.bodyAudio != null + fun clearDisposables() { + disposables.clear() + } + private fun AssociatedAudio.progressProperty(): DoubleProperty { val progressProperty = SimpleDoubleProperty(0.0) - this.selected.subscribe { + val sub = this.selected.subscribe { progressProperty.set( if (it.value != null) 1.0 else 0.0) } + disposables.add(sub) return progressProperty } diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt index 669e3868..016f3dd3 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItem.kt @@ -8,7 +8,13 @@ import tornadofx.FX.Companion.messages data class ResourceGroupCardItem( val title: String, val resources: Observable -) +) { + fun onRemove() { + resources.forEach { + it.clearDisposables() + } + } +} fun resourceGroupCardItem(element: BookElement, slug: String, onSelect: (Resource) -> Unit): ResourceGroupCardItem? { return findResourceGroup(element, slug)?.let { rg -> diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItemList.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItemList.kt new file mode 100644 index 00000000..e624788d --- /dev/null +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceGroupCardItemList.kt @@ -0,0 +1,22 @@ +package org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model + +import com.sun.javafx.collections.ObservableListWrapper +import javafx.collections.ListChangeListener + +class ResourceGroupCardItemList(list: List) : + ObservableListWrapper(list) { + + init { + addListener( + ListChangeListener { + while(it.next()) { + if (it.wasRemoved()) { + it.removed.forEach { item -> + item.onRemove() + } + } + } + } + ) + } +} \ No newline at end of file From 18427cfd32d6f572f6e61e49d144191749e704f6 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Tue, 21 May 2019 15:49:07 -0400 Subject: [PATCH 13/18] PR Comment: Rename title rendering function --- .../jvm/app/widgets/resourcecard/model/ResourceCardItem.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt index 65a05716..2150d909 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt @@ -9,7 +9,7 @@ import org.commonmark.parser.Parser import org.commonmark.renderer.text.TextContentRenderer data class ResourceCardItem(val resource: Resource, val onSelect: () -> Unit) { - val title: String = getTitleTextContent() + val title: String = renderTitleAsPlainText() private val disposables = CompositeDisposable() val titleProgressProperty: DoubleProperty = resource.titleAudio.progressProperty() val bodyProgressProperty: DoubleProperty? = resource.bodyAudio?.progressProperty() @@ -33,7 +33,7 @@ data class ResourceCardItem(val resource: Resource, val onSelect: () -> Unit) { val renderer: TextContentRenderer = TextContentRenderer.builder().build() } - private fun getTitleTextContent(): String { + private fun renderTitleAsPlainText(): String { val document = parser.parse(resource.title.text) return renderer.render(document) } From 0da196ff38df2be799145b255a113a05a4c95a7b Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Tue, 21 May 2019 15:51:18 -0400 Subject: [PATCH 14/18] PR Comment: remove unecessary getResources function --- .../repositories/ResourceRepository.kt | 40 +++++-------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt index b73ab589..45ffdc95 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt @@ -89,58 +89,40 @@ class ResourceRepository(private val database: AppDatabase) : IResourceRepositor .map(this::buildResourceInfo) } - /** - * Returns all resources for which the resource content's COLLECTION_FK field references this collection. - * This will return resources about the chapter as well as all resources about the chapter's chunks. - */ - override fun getResourcesForCollectionAndChildren( - collection: Collection, - resourceInfo: ResourceInfo - ): Observable { - return getResources({ table -> table.COLLECTION_FK.eq(collection.id) }, resourceInfo) - } - override fun getResources(content: Content, resourceInfo: ResourceInfo): Observable { - return getResources({ table -> table.ID.eq(content.id) }, resourceInfo) - } - - /** - * Returns collection-specific resources - */ - override fun getResources(collection: Collection, resourceInfo: ResourceInfo): Observable { val metadata = mapToResourceMetadataEntity[resourceInfo] ?: return Observable.empty() + val main = CONTENT_ENTITY.`as`("main") val help = CONTENT_ENTITY.`as`("help") val selectStatement = database.dsl .selectDistinct(help.asterisk()) .from(RESOURCE_LINK) - .join(COLLECTION_ENTITY).on(COLLECTION_ENTITY.ID.eq(RESOURCE_LINK.COLLECTION_FK)) - .join(help).on(RESOURCE_LINK.RESOURCE_CONTENT_FK.eq(help.ID)) + .join(main).on(main.ID.eq(RESOURCE_LINK.CONTENT_FK)) + .join(help).on(help.ID.eq(RESOURCE_LINK.RESOURCE_CONTENT_FK)) .where(RESOURCE_LINK.DUBLIN_CORE_FK.eq(metadata.id)) - .and(COLLECTION_ENTITY.ID.eq(collection.id)) + .and(main.ID.eq(content.id)) return getResources(help, selectStatement) } - private fun getResources( - condition: (jooq.tables.ContentEntity) -> Condition, - resourceInfo: ResourceInfo - ): Observable { + /** + * Returns collection-specific resources (does not return resources about the collection's children.) + */ + override fun getResources(collection: Collection, resourceInfo: ResourceInfo): Observable { val metadata = mapToResourceMetadataEntity[resourceInfo] ?: return Observable.empty() - val main = CONTENT_ENTITY.`as`("main") val help = CONTENT_ENTITY.`as`("help") val selectStatement = database.dsl .selectDistinct(help.asterisk()) .from(RESOURCE_LINK) - .join(main).on(main.ID.eq(RESOURCE_LINK.CONTENT_FK)) - .join(help).on(help.ID.eq(RESOURCE_LINK.RESOURCE_CONTENT_FK)) + .join(COLLECTION_ENTITY).on(COLLECTION_ENTITY.ID.eq(RESOURCE_LINK.COLLECTION_FK)) + .join(help).on(RESOURCE_LINK.RESOURCE_CONTENT_FK.eq(help.ID)) .where(RESOURCE_LINK.DUBLIN_CORE_FK.eq(metadata.id)) - .and(condition(main)) + .and(COLLECTION_ENTITY.ID.eq(collection.id)) return getResources(help, selectStatement) } From 67175450987dc14ea6c158a2477ac5167185c785 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Tue, 21 May 2019 15:52:18 -0400 Subject: [PATCH 15/18] PR Comment: Null-safe resource group loading --- .../resources/viewmodel/ResourcesViewModel.kt | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt index 51b81a0c..71186730 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt @@ -1,5 +1,6 @@ package org.wycliffeassociates.otter.jvm.app.ui.resources.viewmodel +import io.reactivex.Observable import javafx.application.Platform import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleStringProperty @@ -23,16 +24,20 @@ class ResourcesViewModel : ViewModel() { var resourceGroups: ResourceGroupCardItemList = ResourceGroupCardItemList(mutableListOf()) + fun Observable.mapNotNull(f: (T) -> R?): Observable = + concatMapIterable { listOfNotNull(f(it)) } + fun loadResourceGroups() { - chapter.chunks.map { chunk -> - resourceGroupCardItem(chunk, resourceSlug) { navigateToTakesPage(it) } - }.startWith( - resourceGroupCardItem(chapter, resourceSlug) { navigateToTakesPage(it) } - ).buffer(2).subscribe { // Buffering by 2 prevents the list UI from jumping while groups are loading - Platform.runLater { - resourceGroups.addAll(it) + chapter + .children + .startWith(chapter) + .mapNotNull { resourceGroupCardItem(it, resourceSlug, onSelect = this::navigateToTakesPage) } + .buffer(2) // Buffering by 2 prevents the list UI from jumping while groups are loading + .subscribe { + Platform.runLater { + resourceGroups.addAll(it) + } } - } } private fun navigateToTakesPage(resource: Resource) { From 7b74f9b9285023d74f8094470566325f5b9efadc Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Wed, 22 May 2019 10:14:15 -0400 Subject: [PATCH 16/18] PR Comment: constant val --- .../jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt | 2 +- .../jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt | 4 +++- .../otter/jvm/persistence/repositories/ResourceRepository.kt | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt index 71186730..77a6bc03 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt @@ -22,7 +22,7 @@ class ResourcesViewModel : ViewModel() { val resourceSlug: String get() = activeResourceSlugProperty.value - var resourceGroups: ResourceGroupCardItemList = ResourceGroupCardItemList(mutableListOf()) + val resourceGroups: ResourceGroupCardItemList = ResourceGroupCardItemList(mutableListOf()) fun Observable.mapNotNull(f: (T) -> R?): Observable = concatMapIterable { listOfNotNull(f(it)) } diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt index fede5f95..1eed3edf 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceGroupCard.kt @@ -6,7 +6,9 @@ import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceG import tornadofx.* class ResourceGroupCard(group: ResourceGroupCardItem) : VBox() { - private val RENDER_BATCH_SIZE = 10 + companion object { + const val RENDER_BATCH_SIZE = 10 + } init { importStylesheet() diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt index 45ffdc95..78217a71 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/persistence/repositories/ResourceRepository.kt @@ -6,7 +6,6 @@ import io.reactivex.Single import io.reactivex.rxkotlin.toObservable import io.reactivex.schedulers.Schedulers import jooq.Tables.* -import org.jooq.Condition import org.jooq.SelectConditionStep import org.jooq.Record import org.jooq.DSLContext From a1d91b967c14bbac9c2b92182b629c8200bbda10 Mon Sep 17 00:00:00 2001 From: Kevin Joslyn Date: Thu, 23 May 2019 09:48:32 -0400 Subject: [PATCH 17/18] PR Comment: finalize ResourceCardItem --- .../jvm/app/widgets/resourcecard/model/ResourceCardItem.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt index 2150d909..92e1786e 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/model/ResourceCardItem.kt @@ -15,6 +15,11 @@ data class ResourceCardItem(val resource: Resource, val onSelect: () -> Unit) { val bodyProgressProperty: DoubleProperty? = resource.bodyAudio?.progressProperty() val hasBodyAudio: Boolean = resource.bodyAudio != null + @Suppress("ProtectedInFinal", "Unused") + protected fun finalize() { + clearDisposables() + } + fun clearDisposables() { disposables.clear() } From 6732dddc11367a8b3eca2bc76a02ed092f976671 Mon Sep 17 00:00:00 2001 From: KJoslyn Date: Fri, 31 May 2019 09:39:48 -0400 Subject: [PATCH 18/18] Move mapNotNull to RxUtils, minor code clean --- .../jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt | 5 +---- .../jvm/app/widgets/resourcecard/view/ResourceListView.kt | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt index 77a6bc03..ce53dd41 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/ui/resources/viewmodel/ResourcesViewModel.kt @@ -1,10 +1,10 @@ package org.wycliffeassociates.otter.jvm.app.ui.resources.viewmodel -import io.reactivex.Observable import javafx.application.Platform import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleStringProperty import org.wycliffeassociates.otter.common.data.workbook.* +import org.wycliffeassociates.otter.common.utils.mapNotNull import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.ResourceGroupCardItemList import org.wycliffeassociates.otter.jvm.app.widgets.resourcecard.model.resourceGroupCardItem import tornadofx.* @@ -24,9 +24,6 @@ class ResourcesViewModel : ViewModel() { val resourceGroups: ResourceGroupCardItemList = ResourceGroupCardItemList(mutableListOf()) - fun Observable.mapNotNull(f: (T) -> R?): Observable = - concatMapIterable { listOfNotNull(f(it)) } - fun loadResourceGroups() { chapter .children diff --git a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceListView.kt b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceListView.kt index 66563e1e..b7fc6f99 100644 --- a/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceListView.kt +++ b/src/main/kotlin/org/wycliffeassociates/otter/jvm/app/widgets/resourcecard/view/ResourceListView.kt @@ -9,12 +9,12 @@ import tornadofx.* class ResourceListView(items: ObservableList): ListView(items) { init { - vgrow = Priority.ALWAYS // This needs to be here cellFormat { graphic = cache(it.title) { resourcegroupcard(it) } } + vgrow = Priority.ALWAYS isFocusTraversable = false addClass(ResourceListStyles.resourceGroupList) }