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

Gantt and Calendar view of tasks #533

Open
chavu opened this issue Jun 17, 2024 · 7 comments
Open

Gantt and Calendar view of tasks #533

chavu opened this issue Jun 17, 2024 · 7 comments

Comments

@chavu
Copy link

chavu commented Jun 17, 2024

I'm working on project task management tool. I'm currently displaying the tasks in tabulator table. I now want to add Gantt and Calendar views. Does Kvision have any component that can do this? If not, how can I use extrernal JS libraries like these two below:

Google Charts (https://developers.google.com/chart/interactive/docs/gallery/ganttchart)
https://dlhsoft.com/GanttChartHyperLibrary/

@rjaros
Copy link
Owner

rjaros commented Jun 17, 2024

I haven't done that, but you can try using scatter chart with chart.js module. See this SO example: https://stackoverflow.com/questions/41259441/how-to-draw-gantt-chart-using-chart-js-or-other-libraries

@chavu
Copy link
Author

chavu commented Jun 17, 2024

Thanks. I will try it out and give feedback

@chavu
Copy link
Author

chavu commented Jun 18, 2024

Instead of using the Chart module, I desided to try integrating this full-fledged react scheduler component https://github.com/Bitnoise/react-scheduler
The scduler is no display and see the following error message:
"TypeError: e.reduce is not a function or its return value is not iterable"
Below are my code .

Data clasess define in CommonMain module


import io.kvision.types.LocalDateTime
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable


@Serializable
data class ScheduleData(
    val id: String,
    val label: ScheduleRowLabel,
    val data: List<ScheduleResourceItem>? = null
)

@Serializable
data class ScheduleRowLabel(
    val icon: String? = null,
    val title: String,
    val subTitle: String? = null,
)

@Serializable
data class ScheduleResourceItem(
    val id: String, //unique resource id
    val title: String, //resource title that will be displayed on resource tile
    val subTitle: String? = null, //resource subtitle that will be displayed on resource tile
    val description: String? = null, //resource description that will be displayed on resource tile
    @Contextual val startDate: LocalDateTime, //date for calculating start position for resource
    @Contextual val endDate: LocalDateTime, //date for calculating end position for resource
    @Contextual  val occupancy: Number = 30, //number of seconds resource takes up for given row that will be visible on resource tooltip when hovered
    val bgColor: String, //tile color
)

data class ScheduleConfig(
    val zoom: Number = 1, // 0 - weeks, 1 - Days
    val filterButtonState: Number,
    val maxRecordsPerPage: Number,
    val lang: String = "en",
    val includeTakenHoursOnWeekendsInDayView: Boolean
)

View to display the scheduler


import com.digitres.pmis.models.scheduling.ScheduleConfig
import com.digitres.pmis.models.scheduling.ScheduleData
import com.digitres.pmis.models.scheduling.ScheduleResourceItem
import io.kvision.core.Container
import io.kvision.react.react
import react.ComponentClass
import react.PropsWithChildren
import react.PropsWithRef

external interface ReactSchedulerProps : PropsWithRef<dynamic>, PropsWithChildren {
    var data: List<ScheduleData>
    var isLoading: Boolean
    var onRangeChange: (String) -> Unit
    var onTileClick: (String) -> Unit
    var onItemClick: (ScheduleResourceItem) -> Unit
    var onFilterData: () -> Unit
    var onClearData: () -> Unit
    var config: ScheduleConfig
}

val Scheduler: ComponentClass<ReactSchedulerProps> = io.kvision.require("@bitnoi.se/react-scheduler").Scheduler

fun Container.scheduleView() {
    react {
        Scheduler {
            data = SampleSchedule.data
            isLoading = false
            config = ScheduleConfig(
                zoom = 1,
                filterButtonState = 0,
                maxRecordsPerPage = 10,
                lang = "en",
                includeTakenHoursOnWeekendsInDayView = true
            )
        }
    }
}

Sample Data to display


import com.digitres.pmis.models.scheduling.ScheduleData
import com.digitres.pmis.models.scheduling.ScheduleResourceItem
import com.digitres.pmis.models.scheduling.ScheduleRowLabel
import kotlin.js.Date

object SampleSchedule {
    val data = listOf(
        ScheduleData(
            id = "1",
            label = ScheduleRowLabel(
                icon = null,
                title = "Facility 1",
                subTitle = null
            ),
            data = listOf(
                ScheduleResourceItem(
                    id = "1.1",
                    title = "Team 1",
                    subTitle = null,
                    description = null,
                    startDate = Date("2024-09-02T08:00"),
                    endDate = Date("2024-09-11T08:00"),
                    occupancy = 20,
                    bgColor = "rgb(254,165,177)"
                )
            )
        ),
        ScheduleData(
                id = "2",
        label = ScheduleRowLabel(
            icon = null,
            title = "Facility 2",
            subTitle = null
        ),
        data = listOf(
            ScheduleResourceItem(
                id = "2.1",
                title = "Team 2",
                subTitle = null,
                description = null,
                startDate = Date("2024-09-13T08:00"),
                endDate = Date("2024-09-20T08:00"),
                occupancy = 20,
                bgColor = "rgb(254,165,177)"
            )
        )
    )
    )
}

build.gradle dependencies addedd

        val jsMain by getting {
            resources.srcDir(webDir)
            dependencies {
                implementation(npm("react-is", "18.3.1"))
                implementation(npm("@babel/core", "7.24.7"))
                implementation(npm("@babel/plugin-syntax-jsx", "7.24.7"))
                implementation(npm("@bitnoi.se/react-scheduler", "0.2.0"))
                 implementation("io.kvision:kvision-react:$kvisionVersion")
                ...
            }
            kotlin.srcDir("build/generated-src/frontend")
        }

Error Stack

index.umd.cjs:114 Uncaught TypeError: e.reduce is not a function or its return value is not iterable
    at Bo (index.umd.cjs:114:4169)
    at eval (index.umd.cjs:114:4591)
    at mountMemo (react-dom.development.js:17225:19)
    at Object.useMemo (react-dom.development.js:17670:16)
    at Object.useMemo (react.development.js:1651:21)
    at Ro (index.umd.cjs:114:4579)
    at as (index.umd.cjs:138:544)
    at renderWithHooks (react-dom.development.js:16305:18)
    at mountIndeterminateComponent (react-dom.development.js:20069:13)
    at beginWork (react-dom.development.js:21582:16)

@rjaros
Copy link
Owner

rjaros commented Jun 18, 2024

I'm almost sure you can't use Kotlin types (lists or data classes), even serializable, as a data model for React components. So it's very unlikely List<ScheduleData> will work. In my opinion you need to use Array<dynamic> or other external types.

@chavu
Copy link
Author

chavu commented Jun 18, 2024

Thanks. Using Arrary worked. I then converted the Kotlin List as below.

data =  JSON.parse(Json.encodeToString(SampleSchedule.data))

I am now able to display the scheduler. However it is displaying fullscreen and yet it's supposed to be within the content area under the header. I am also not sure if its style I added to App.kt is being utilised.

class App : Application() {
    init {
        require("./css/custom.css")
        require("@bitnoi.se/react-scheduler/dist/style.css")
    }
...
}

@rjaros
Copy link
Owner

rjaros commented Jun 19, 2024

Have you checked this: Bitnoise/react-scheduler#60 ?

@chavu
Copy link
Author

chavu commented Jun 19, 2024

Thanks, wrapping the scheduler in div and setting Relative position worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants