diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/SdkSelection.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/SdkSelection.kt deleted file mode 100644 index 9601b111ea..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/SdkSelection.kt +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Component for SDK selection - */ - -@file:Suppress("FILE_NAME_MATCH_CLASS", "WildcardImport", "FILE_WILDCARD_IMPORTS") - -package com.saveourtool.save.frontend.common.components.basic - -import com.saveourtool.save.domain.* -import com.saveourtool.save.frontend.common.utils.selectorBuilder -import com.saveourtool.save.frontend.common.utils.useStateFromProps - -import react.* -import react.dom.html.ReactHTML.div -import react.dom.html.ReactHTML.label -import web.cssom.ClassName -import web.html.HTMLSelectElement - -/** - * Component for sdk selection - */ -val sdkSelection: FC = FC { props -> - val (sdkName, setSdkName) = useStateFromProps(props.selectedSdk.getPrettyName()) - val (sdkVersion, setSdkVersion) = useStateFromProps(props.selectedSdk.version) - - if (props.title.isNotBlank()) { - label { - className = - ClassName("control-label col-auto justify-content-between font-weight-bold text-gray-800 mb-1 pl-0") - +props.title - } - } - div { - className = ClassName("card align-items-left mb-3 pt-0 pb-0") - div { - className = ClassName("card-body align-items-left pb-1 pt-3") - div { - className = ClassName("row no-gutters align-items-left") - selection( - "SDK", - sdkName, - sdks, - isDisabled = props.isDisabled, - ) { element -> - val newSdkName = element.value - val newSdkVersion = newSdkName.getSdkVersions().first() - setSdkName(newSdkName) - setSdkVersion(newSdkVersion) - props.onSdkChange("$newSdkName:$newSdkVersion".toSdk()) - } - } - div { - className = ClassName("row no-gutters align-items-left") - className = ClassName("d-inline") - selection( - "Version", - sdkVersion, - sdkName.getSdkVersions(), - isDisabled = props.isDisabled, - ) { element -> - val newSdkVersion = element.value - setSdkVersion(newSdkVersion) - props.onSdkChange("$sdkName:$newSdkVersion".toSdk()) - } - } - } - } -} - -/** - * Props for SdkSelection component - */ -external interface SdkProps : PropsWithChildren { - /** - * Title for sdk selector - */ - var title: String - - /** - * The selected SDK - */ - var selectedSdk: Sdk - - /** - * Callback invoked when SDK is changed - */ - var onSdkChange: (Sdk) -> Unit - - /** - * Flag to disable sdk selection - */ - var isDisabled: Boolean -} - -private fun ChildrenBuilder.selection( - labelValue: String, - value: String, - options: List, - isDisabled: Boolean, - onChangeFun: (HTMLSelectElement) -> Unit, -) = div { - className = ClassName("input-group mb-3") - div { - className = ClassName("input-group-prepend") - label { - className = ClassName("input-group-text") - +labelValue - } - } - selectorBuilder(value, options, "custom-select", isDisabled) { onChangeFun(it.target) } -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/fileuploader/ProgressBarComponent.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/fileuploader/ProgressBarComponent.kt deleted file mode 100644 index 340f5d52f0..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/fileuploader/ProgressBarComponent.kt +++ /dev/null @@ -1,51 +0,0 @@ -/** - * File containing progress bar functional component - */ - -@file:Suppress("FILE_NAME_MATCH_CLASS") - -package com.saveourtool.save.frontend.common.components.basic.fileuploader - -import com.saveourtool.save.utils.toKilobytes -import react.FC -import react.Props - -/** - * Progress Bar [FC] - */ -@Suppress("MAGIC_NUMBER") -val progressBarComponent: FC = FC { props -> - defaultProgressBarComponent { - currentProgress = if (props.total == props.current && props.total == 0L) { - -1 - } else { - (100 * props.current / props.total).toInt() - } - currentProgressMessage = if (props.current == props.total && props.total != 0L) { - "Successfully uploaded ${props.total.toKilobytes()} KB." - } else { - "${props.current.toKilobytes()} / ${props.total.toKilobytes()} KB" - } - reset = props.flushCounters - } -} - -/** - * [Props] for [progressBarComponent] - */ -external interface ProgressBarComponentProps : Props { - /** - * Amount of entity that is already marked as done (uploaded, downloaded, fixed, etc.) - */ - var current: Long - - /** - * Total amount of entity - */ - var total: Long - - /** - * Callback invoked to flush [current] and [total] - */ - var flushCounters: () -> Unit -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/fileuploader/SimpleFileUploader.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/fileuploader/SimpleFileUploader.kt deleted file mode 100644 index 5de924a081..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/fileuploader/SimpleFileUploader.kt +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Component for uploading files (FileDtos) - */ - -@file:Suppress("FILE_NAME_MATCH_CLASS") - -package com.saveourtool.save.frontend.common.components.basic.fileuploader - -import com.saveourtool.save.entities.FileDto -import com.saveourtool.save.frontend.common.externals.fontawesome.* -import com.saveourtool.save.frontend.common.externals.fontawesome.faTimes -import com.saveourtool.save.frontend.common.utils.* - -import react.* -import react.dom.html.ReactHTML.div -import react.dom.html.ReactHTML.li -import react.dom.html.ReactHTML.ul -import web.cssom.ClassName - -@Suppress( - "TOO_LONG_FUNCTION", - "TYPE_ALIAS", - "LongMethod", - "ComplexMethod", -) -val simpleFileUploader: FC = FC { props -> - useTooltip() - val (selectedFiles, setSelectedFiles) = useState>(emptyList()) - val (availableFiles, setAvailableFiles) = useState>(emptyList()) - - useEffect(selectedFiles) { props.fileDtosSetter { selectedFiles } } - - @Suppress("TOO_MANY_LINES_IN_LAMBDA") - (useRequest { - props.getUrlForSelectedFilesFetch?.let { - val response = get( - it(), - jsonHeaders, - loadingHandler = ::noopLoadingHandler, - responseHandler = ::noopResponseHandler, - ) - if (response.ok) { - setSelectedFiles(response.decodeFromJsonString>()) - } - } - }) - - useRequest(arrayOf(selectedFiles)) { - props.getUrlForAvailableFilesFetch?.invoke()?.let { url -> - val response = get( - url, - jsonHeaders, - loadingHandler = ::noopLoadingHandler, - responseHandler = ::noopResponseHandler, - ) - if (response.ok) { - val presentNames = selectedFiles.map { it.name } - response.decodeFromJsonString>() - .let { fileDtos -> fileDtos.filter { fileDto -> fileDto.name !in presentNames }.distinctBy { it.name } } - .let(setAvailableFiles::invoke) - } - } - } - div { - ul { - className = ClassName("list-group") - - // ===== SELECTOR ===== - li { - className = ClassName("list-group-item d-flex justify-content-between align-items-center") - selectorBuilder( - "Select a file from existing", - availableFiles.map { it.name }.plus("Select a file from existing"), - classes = "form-control custom-select", - isDisabled = props.isDisabled, - ) { event -> - val availableFile = availableFiles.first { it.name == event.target.value } - setSelectedFiles { it.plus(availableFile) } - setAvailableFiles { it.minus(availableFile) } - } - } - - // ===== SELECTED FILES ===== - selectedFiles.map { file -> - li { - className = ClassName("list-group-item") - buttonBuilder(faTimes, null, isDisabled = props.isDisabled) { - setSelectedFiles { it.minus(file) } - setAvailableFiles { files -> files.plus(file) } - } - +file.name - } - } - } - } -} - -typealias FileDtosSetter = StateSetter> - -/** - * Props for simpleFileUploader - */ -external interface SimpleFileUploaderProps : Props { - /** - * Callback to get url to get available files - */ - var getUrlForAvailableFilesFetch: (() -> String)? - - /** - * Callback to get url to get files that are already selected - */ - var getUrlForSelectedFilesFetch: (() -> String)? - - /** - * Callback to update list of selected file ids - */ - var fileDtosSetter: FileDtosSetter - - /** - * Flag that defines if the uploader is disabled - */ - var isDisabled: Boolean -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/table/filters/TestExecutionFilter.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/table/filters/TestExecutionFilter.kt deleted file mode 100644 index ab6dfe8a29..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/components/basic/table/filters/TestExecutionFilter.kt +++ /dev/null @@ -1,170 +0,0 @@ -@file:Suppress("FILE_NAME_MATCH_CLASS") - -package com.saveourtool.save.frontend.common.components.basic.table.filters - -import com.saveourtool.save.domain.TestResultStatus -import com.saveourtool.save.filters.TestExecutionFilter -import com.saveourtool.save.frontend.common.externals.fontawesome.faFilter -import com.saveourtool.save.frontend.common.externals.fontawesome.faSearch -import com.saveourtool.save.frontend.common.externals.fontawesome.faTrashAlt -import com.saveourtool.save.frontend.common.externals.fontawesome.fontAwesomeIcon -import react.FC -import react.Props -import react.dom.html.ReactHTML.button -import react.dom.html.ReactHTML.div -import react.dom.html.ReactHTML.input -import react.dom.html.ReactHTML.option -import react.dom.html.ReactHTML.select -import react.useEffect -import react.useState -import web.cssom.ClassName -import web.html.ButtonType -import web.html.InputType - -const val ANY = "ANY" - -/** - * A row of filter selectors for table with `TestExecutionDto`s. Currently, filters are "status" and "test suite". - * - * @return a function component - */ -@Suppress("LongMethod", "TOO_LONG_FUNCTION") -val testExecutionFiltersRow: FC = FC { props -> - // Store local copy of filters in order to perform searching only by the search button, and not by any change in the filter fields - val (filters, setFilters) = useState(props.filters) - useEffect(props.filters) { - if (filters !== props.filters) { - setFilters(props.filters) - } - } - div { - className = ClassName("container-fluid") - div { - className = ClassName("row d-flex justify-content-between") - div { - className = ClassName("col-0 pr-1 align-self-center") - fontAwesomeIcon(icon = faFilter) - } - div { - className = ClassName("row") - div { - className = ClassName("col-auto align-self-center") - +"Status: " - } - div { - className = ClassName("col-auto") - select { - className = ClassName("form-control custom-select") - val elements = TestResultStatus.values().map { it.name }.toMutableList() - elements.add(0, ANY) - value = filters.status?.name ?: ANY - elements.forEach { element -> - option { - if (element == props.filters.status?.name) { - selected = true - } - +element - } - } - onChange = { - if (it.target.value == ANY) { - setFilters(filters.copy(status = null)) - } else { - setFilters(filters.copy(status = TestResultStatus.valueOf(it.target.value))) - } - } - } - } - } - div { - className = ClassName("row") - div { - className = ClassName("col-auto align-self-center") - +"File name: " - } - div { - className = ClassName("col-auto") - input { - type = InputType.text - className = ClassName("form-control") - value = filters.fileName ?: "" - required = false - onChange = { - setFilters(filters.copy(fileName = it.target.value)) - } - } - } - } - div { - className = ClassName("row") - div { - className = ClassName("col-auto align-self-center") - +"Test suite: " - } - div { - className = ClassName("col-auto") - input { - type = InputType.text - className = ClassName("form-control") - value = filters.testSuite ?: "" - required = false - onChange = { - setFilters(filters.copy(testSuite = it.target.value)) - } - } - } - } - div { - className = ClassName("row") - div { - className = ClassName("col-auto align-self-center") - +"Tags: " - } - div { - className = ClassName("col-auto") - input { - type = InputType.text - className = ClassName("form-control") - value = filters.tag ?: "" - required = false - onChange = { - setFilters(filters.copy(tag = it.target.value)) - } - } - } - } - button { - type = ButtonType.button - className = ClassName("btn btn-outline-primary") - fontAwesomeIcon(icon = faSearch, classes = "trash-alt") - onClick = { - props.onChangeFilters(filters) - } - } - button { - type = ButtonType.button - className = ClassName("btn btn-outline-primary") - fontAwesomeIcon(icon = faTrashAlt, classes = "trash-alt") - onClick = { - setFilters(TestExecutionFilter.empty) - props.onChangeFilters(TestExecutionFilter.empty) - } - } - } - } -} - -/** - * [Props] for filters value - */ -external interface FiltersRowProps : Props { - /** - * All filters in one class property [filters] - */ - var filters: TestExecutionFilter - - /** - * lambda to change [filters] - */ - var onChangeFilters: (TestExecutionFilter) -> Unit -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/calendar/ReactCalendar.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/calendar/ReactCalendar.kt deleted file mode 100644 index b51c9af150..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/calendar/ReactCalendar.kt +++ /dev/null @@ -1,87 +0,0 @@ -@file:Suppress("HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE") -@file:JsModule("react-calendar") -@file:JsNonModule - -package com.saveourtool.save.frontend.common.externals.calendar - -import org.w3c.dom.events.Event -import react.Component -import react.PropsWithChildren -import react.ReactElement -import react.State -import kotlin.js.Date - -/** - * External declaration of [ReactCalendarProps] react component - */ -@JsName("Calendar") -external class ReactCalendar : Component { - override fun render(): ReactElement? -} - -/** - * Props of [ReactCalendarProps] - */ -external interface ReactCalendarProps : PropsWithChildren { - /** - * The beginning of a period that shall be displayed. - * If you wish to use React-Calendar in an uncontrolled way, use [defaultActiveStartDate] instead. - */ - var activeStartDate: Date - - /** - * Class name(s) that will be added along with "react-calendar" to the main React-Calendar
element. - */ - var className: String - - /** - * The beginning of a period that shall be displayed by default. - * If you wish to use React-Calendar in a controlled way, use [activeStartDate] instead. - */ - var defaultActiveStartDate: Date - - /** - * Calendar value that shall be selected initially. - * Can be either one value or an array of two values. - * If you wish to use React-Calendar in a controlled way, use [value] instead. - */ - var defaultValue: Array - - /** - * Function called when the user clicks an item (day on month view, month on year view and so on) - * on the most detailed view available. - */ - var onChange: (Date, Event) -> Unit - - /** - * Function called when the user clicks a day. - */ - var onClickDay: (Int, Event) -> Unit - - /** - * Calendar value. Can be either one value or an array of two values. - * If you wish to use React-Calendar in an uncontrolled way, use [defaultValue] instead. - */ - var value: Array - - /** - * Whether days from previous or next month shall be rendered - * if the month doesn't start on the first day of the week - * or doesn't end on the last day of the week, respectively. - */ - var showNeighboringMonth: Boolean - - /** - * Locale that should be used by the calendar. - * Can be any IETF language tag. - */ - var locale: String - - /** - * Type of calendar that should be used. Can be "ISO 8601", "US", "Arabic", or "Hebrew". - * Setting to "US" or "Hebrew" will change the first day of the week to Sunday. - * Setting to "Arabic" will change the first day of the week to Saturday. - * Setting to "Arabic" or "Hebrew" will make weekends appear on Friday to Saturday. - */ - var calendarType: String -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/calendar/ReactCalendarBuilder.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/calendar/ReactCalendarBuilder.kt deleted file mode 100644 index d39421eaa1..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/calendar/ReactCalendarBuilder.kt +++ /dev/null @@ -1,25 +0,0 @@ -@file:Suppress("HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE") - -package com.saveourtool.save.frontend.common.externals.calendar - -import org.w3c.dom.events.Event -import react.ChildrenBuilder -import react.react -import kotlin.js.Date - -/** - * @param onChange - * @param handler - */ -fun ChildrenBuilder.calendar( - onChange: (Date, Event) -> Unit, - handler: ChildrenBuilder.(ReactCalendarProps) -> Unit = {}, -) { - kotlinext.js.require("react-calendar/dist/Calendar.css") - ReactCalendar::class.react { - this.onChange = onChange - this.showNeighboringMonth = false - this.locale = "en-EN" - handler(this) - } -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/chart/PieChart.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/chart/PieChart.kt deleted file mode 100644 index a6476f788e..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/chart/PieChart.kt +++ /dev/null @@ -1,16 +0,0 @@ -@file:JsModule("react-minimal-pie-chart") -@file:JsNonModule - -package com.saveourtool.save.frontend.common.externals.chart - -import react.Component -import react.ReactElement -import react.State - -/** - * External declaration of [PieChart] react component - */ -@JsName("PieChart") -external class PieChart : Component { - override fun render(): ReactElement? -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/chart/PieChartBuilder.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/chart/PieChartBuilder.kt deleted file mode 100644 index 0c16bcd4ac..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/chart/PieChartBuilder.kt +++ /dev/null @@ -1,51 +0,0 @@ -/** - * kotlin-react builders for PieChart components - */ - -@file:Suppress("FILE_NAME_MATCH_CLASS") - -package com.saveourtool.save.frontend.common.externals.chart - -import react.ChildrenBuilder -import react.react -import kotlin.random.Random - -/** - * @property hex - */ -enum class PieChartColors(val hex: String) { - GREEN("#89E894"), - GREY("#CCCCC4"), - RED("#FF8989"), - ; -} - -/** - * @param data dataset for pie chart - * @param handler handler to set up a component - * @return ReactElement - */ -@Suppress("MAGIC_NUMBER") -fun ChildrenBuilder.pieChart( - data: Array, - handler: ChildrenBuilder.(PieChartProps) -> Unit = {}, -) = PieChart::class.react { - this.data = data - animate = false - segmentsShift = 0 - viewBoxSize = intArrayOf(100, 100) - radius = 50 - handler(this) -} - -/** - * @return string of random hex color - */ -fun randomColor(): String { - var stringColor = "#" - val charPool = "0123456789ABCDEF".split("") - while (stringColor.length <= 6) { - stringColor += charPool[Random.nextInt(16)] - } - return stringColor -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/chart/PieChartProps.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/chart/PieChartProps.kt deleted file mode 100644 index 43207e8d2c..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/chart/PieChartProps.kt +++ /dev/null @@ -1,66 +0,0 @@ -@file:Suppress("HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE") - -package com.saveourtool.save.frontend.common.externals.chart - -import react.PropsWithChildren -import web.events.Event - -/** - * Props of [PieChart] - */ -external interface PieChartProps : PropsWithChildren { - /** - * Dataset for pie chart - */ - var data: Array - - /** - * Animate segments on component mount - */ - var animate: Boolean - - /** - * Translates segments radially. If number set, provide shift value relative to viewBoxSize space - */ - var segmentsShift: Int - - /** - * width and height of SVG viewBox attribute - */ - var viewBoxSize: IntArray - - /** - * Radius of the pie (relative to viewBoxSize space) - */ - var radius: Int - - /** - * onClick event handler for each segment - */ - var onClick: (Event, Int) -> Unit - - /** - * onMouseOut event handler for each segment - */ - var onMouseOut: (Event, Int) -> Unit - - /** - * onMouseOver event handler for each segment - */ - var onMouseOver: (Event, Int) -> Unit -} - -/** - * Source data. Each entry represents a chart segment - * - * @property title segment name - * @property value value of segment - * @property color color of segment - * @property key custom value to be used as segments element keys - */ -data class DataPieChart( - val title: String? = null, - val value: Int, - var color: String, - val key: String? = null, -) diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/CpgUtils.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/CpgUtils.kt deleted file mode 100644 index 8defd7734e..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/CpgUtils.kt +++ /dev/null @@ -1,131 +0,0 @@ -/** - * Utils for CpgGraph and Sigma in general - */ - -package com.saveourtool.save.frontend.common.externals.graph - -import com.saveourtool.save.demo.cpg.CpgEdge -import com.saveourtool.save.demo.cpg.CpgGraph -import com.saveourtool.save.demo.cpg.CpgNode -import com.saveourtool.save.demo.cpg.cytoscape.CytoscapeEdge -import com.saveourtool.save.demo.cpg.cytoscape.CytoscapeGraph -import com.saveourtool.save.demo.cpg.cytoscape.CytoscapeNode - -import js.core.jso - -import kotlin.random.Random -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json - -private val cpgJsonSerializer = Json { encodeDefaults = true } - -/** - * @return serialized graph that can be used with useLoadGraph hook - */ -fun CpgGraph.toGraphologyJson() = let { graph -> - @Suppress("UnusedPrivateProperty", "UNUSED_VARIABLE") - val str = cpgJsonSerializer.encodeToString(graph) - js("JSON.parse(str);") -} - -/** - * Paint [CpgNode] with color - * - * @param color color to paint the [CpgNode] to - * @return [CpgNode] painted with [color] - */ -fun CpgNode.paint(color: String) = copy( - attributes = attributes.copy(color = color) -) - -/** - * Paint [CpgEdge] with color - * - * @param color color to paint the [CpgEdge] to - * @return [CpgEdge] painted with [color] - */ -fun CpgEdge.paint(color: String) = copy( - attributes = attributes.copy(color = color) -) - -/** - * Paint all the [CpgNode]s of [CpgGraph] with [color]. - * - * @param color color to paint the [CpgGraph.nodes] to, if null - each [CpgNode] is painted into random color - * @return [CpgGraph] with all [CpgGraph.nodes] painted with [color] (or randomly) - */ -fun CpgGraph.paintNodes( - color: String? = null -) = nodes.map { node -> - node.paint(color ?: getRandomHexColor()) -} - .let { coloredNodes -> - copy(nodes = coloredNodes) - } - -/** - * Paint all the [CpgEdge]s of [CpgGraph] with [color]. - * - * @param color color to paint the [CpgGraph.edges] to, if null - each [CpgEdge] is painted into random color - * @return [CpgGraph] with all [CpgGraph.edges] painted with [color] (or randomly) - */ -fun CpgGraph.paintEdges( - color: String? = null -) = edges.map { edge -> - edge.paint(color ?: getRandomHexColor()) -} - .let { coloredEdges -> - copy(edges = coloredEdges) - } - -/** - * @return [CytoscapeEdge] from [CpgEdge] - */ -fun CpgEdge.asCytoscapeEdge() = CytoscapeEdge( - CytoscapeEdge.Data(key, source, target, attributes.label), - false -) - -/** - * @return [CytoscapeNode] from [CpgNode] - */ -fun CpgNode.asCytoscapeNode() = CytoscapeNode( - CytoscapeNode.Data(key, label = attributes.label) -) - -/** - * @return [CytoscapeGraph] from [CpgGraph] - */ -fun CpgGraph.asCytoscapeGraph() = CytoscapeGraph( - nodes.map { it.asCytoscapeNode() }, - edges.map { it.asCytoscapeEdge() }, - CytoscapeGraph.Attributes(name = attributes.name) -) - -/** - * @param edgeType type of the edge that should be displayed - * @param isRenderEdgeLabels flag that defines if edge labels should be displayed or not - * @return settings of sigmaContainer - */ -fun getSigmaContainerSettings( - edgeType: String = "arrow", - isRenderEdgeLabels: Boolean = true, -): dynamic = jso { - renderEdgeLabels = isRenderEdgeLabels - defaultEdgeType = edgeType -} - -/** - * Get random hex color - * - * @param isPastel flag to generate only pastel colors - true by default - * @return randomized color in format "#RRGGBB" - */ -@Suppress("MAGIC_NUMBER") -fun getRandomHexColor(isPastel: Boolean = true) = buildString { - append("#") - val from = if (isPastel) 127 else 0 - append(Random.nextInt(from, 255).toString(16)) - append(Random.nextInt(from, 255).toString(16)) - append(Random.nextInt(from, 255).toString(16)) -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/cytoscape/CytoscapeWrapper.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/cytoscape/CytoscapeWrapper.kt deleted file mode 100644 index 0c8eb0f412..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/cytoscape/CytoscapeWrapper.kt +++ /dev/null @@ -1,87 +0,0 @@ -@file:Suppress("FILE_NAME_MATCH_CLASS", "HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE") - -package com.saveourtool.save.frontend.common.externals.graph.cytoscape - -import com.saveourtool.save.demo.cpg.cytoscape.CytoscapeGraph -import com.saveourtool.save.demo.cpg.cytoscape.CytoscapeLayout - -import react.* -import web.cssom.* -import web.html.HTMLDivElement - -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json - -/** - * @param graph data in [CytoscapeGraph] format - * @param layout [CytoscapeLayout] that should be applied to graph - * @param divRef reference to div where a graph should be rendered in - * @param selectionType type of node selection - * @return cytoscape graph as dynamic - */ -@Suppress( - "UNUSED_VARIABLE", - "TOO_LONG_FUNCTION", - "UNUSED_PARAMETER", - "LongMethod" -) -fun cytoscape( - graph: CytoscapeGraph, - layout: CytoscapeLayout, - divRef: MutableRefObject, - selectionType: String = "single", -): dynamic { - val cytoscapeGraphJsonString = Json.encodeToString(graph) - val cytoscapeGraphJsonStringJs = js("JSON.parse(cytoscapeGraphJsonString);") - // language=json - val graphStyle = js(""" - [ - { - "selector": "node", - "style": { - "background-color": "#666", - "label": "data(label)", - "height": 20, - "width": 20, - "font-size": 7 - } - }, - { - "selector": "edge", - "style": { - "width": 2, - "height": 2, - "line-color": "#ccc", - "target-arrow-color": "#ccc", - "target-arrow-shape": "triangle", - "curve-style": "bezier", - "label": "data(label)", - "font-size": 5, - "arrow-scale": 0.5 - } - } - ] - """) - val layoutName = layout.layoutName - val graphLayout = js(""" - { - "name": layoutName, - "padding": 5 - } - """) - @Suppress("UNUSED_ANONYMOUS_PARAMETER") - val options = divRef.current?.let { containerRefCurrent -> - js(""" - { - "container" : containerRefCurrent, - "elements" : cytoscapeGraphJsonStringJs, - "layout" : graphLayout, - "style" : graphStyle, - "selectionType": selectionType - } - """) - } - - val cytoscapeJs: dynamic = kotlinext.js.require("cytoscape") - return cytoscapeJs(options) -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/ReactSigma.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/ReactSigma.kt deleted file mode 100644 index a451c44572..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/ReactSigma.kt +++ /dev/null @@ -1,68 +0,0 @@ -@file:Suppress("FILE_NAME_MATCH_CLASS", "HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE") -@file:JsModule("@react-sigma/core") -@file:JsNonModule - -package com.saveourtool.save.frontend.common.externals.graph.sigma - -import react.* - -/** - * External declaration of [sigmaContainer] react [FC] - */ -@JsName("SigmaContainer") -external val sigmaContainer: FC - -/** - * [PropsWithChildren] for [sigmaContainer] - */ -external interface SigmaContainerProps : PropsWithChildren { - /** - * HTML classes that should be applied to [sigmaContainer] - */ - var className: String? - - /** - * CSS styles that should be applied to [sigmaContainer] - */ - var style: dynamic - - /** - * Component settings - */ - var settings: dynamic - - /** - * Graphology graph - */ - var graph: dynamic -} - -/** - * @return graph setter - */ -@JsName("useLoadGraph") -external fun useLoadGraph(): (graph: dynamic) -> Unit - -/** - * Hook to configure the graph - * - * @return callback that receives json with graph settings - */ -@JsName("useSetSettings") -external fun useSetSettings(): (dynamic) -> Unit - -/** - * Hook to configure event handlers - * - * @return callback that receives the json with event handlers - */ -@JsName("useRegisterEvents") -external fun useRegisterEvents(): (dynamic) -> Unit - -/** - * Hook to get Sigma object, required to get current graph for example - * - * @return sigma object - */ -@JsName("useSigma") -external fun useSigma(): dynamic diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutCircular.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutCircular.kt deleted file mode 100644 index 7619cdaa96..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutCircular.kt +++ /dev/null @@ -1,15 +0,0 @@ -@file:Suppress("FILE_NAME_MATCH_CLASS", "HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE") -@file:JsModule("@react-sigma/layout-circular") -@file:JsNonModule - -package com.saveourtool.save.frontend.common.externals.graph.sigma.layouts - -import react.* - -/** - * @param settings - * @return [LayoutInstance] with positions and assign functions - */ -@JsName("useLayoutCircular") -@JsExport -external fun useLayoutCircular(settings: dynamic = definedExternally): LayoutInstance diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutForceAtlas2.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutForceAtlas2.kt deleted file mode 100644 index 5af60187a2..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutForceAtlas2.kt +++ /dev/null @@ -1,14 +0,0 @@ -@file:Suppress("FILE_NAME_MATCH_CLASS", "HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE") -@file:JsModule("@react-sigma/layout-forceatlas2") -@file:JsNonModule - -package com.saveourtool.save.frontend.common.externals.graph.sigma.layouts - -import react.* - -/** - * @param settings - * @return [LayoutInstance] with positions and assign functions - */ -@JsName("useLayoutForceAtlas2") -external fun useLayoutForceAtlas2(settings: dynamic = definedExternally): LayoutInstance diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutInstance.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutInstance.kt deleted file mode 100644 index f87de18769..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutInstance.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.saveourtool.save.frontend.common.externals.graph.sigma.layouts - -/** - * Wrapper for useLayoutRandom returning value to allow unpacking a pair (has [component1] and [component2]) - */ -@JsExport -external interface LayoutInstance diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutRandom.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutRandom.kt deleted file mode 100644 index 4b229fb7ca..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/graph/sigma/layouts/LayoutRandom.kt +++ /dev/null @@ -1,15 +0,0 @@ -@file:Suppress("FILE_NAME_MATCH_CLASS", "HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE") -@file:JsModule("@react-sigma/layout-random") -@file:JsNonModule - -package com.saveourtool.save.frontend.common.externals.graph.sigma.layouts - -import react.* - -/** - * @param settings - * @return [LayoutInstance] with positions and assign functions - */ -@JsName("useLayoutRandom") -@JsExport -external fun useLayoutRandom(settings: dynamic = definedExternally): LayoutInstance diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/reactace/AceBuilder.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/reactace/AceBuilder.kt deleted file mode 100644 index 831691ce7d..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/reactace/AceBuilder.kt +++ /dev/null @@ -1,156 +0,0 @@ -@file:Suppress("HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE") - -package com.saveourtool.save.frontend.common.externals.reactace - -import com.saveourtool.save.frontend.common.utils.parsePositionString -import com.saveourtool.save.utils.DEBOUNCE_PERIOD_FOR_EDITORS -import com.saveourtool.save.utils.Languages - -import io.github.petertrr.diffutils.diff -import js.core.jso -import react.ChildrenBuilder -import react.dom.html.ReactHTML.div -import web.cssom.ClassName - -typealias AceMarkers = Array - -/** - * @param text displayed text - * @param selectedMode highlight mode - * @param selectedTheme displayed theme - * @param aceMarkers array of [AceMarker]s that defines which lines should be marked as unsaved - * @param disabled should this editor be readonly - * @param onChangeFun callback invoked on input - */ -@Suppress("TOO_MANY_PARAMETERS", "LongParameterList") -fun ChildrenBuilder.aceBuilder( - text: String, - selectedMode: Languages, - selectedTheme: AceThemes = AceThemes.CHROME, - aceMarkers: Array = emptyArray(), - disabled: Boolean = false, - onChangeFun: (String) -> Unit, -) { - selectedTheme.require() - kotlinext.js.require("ace-builds/src-min-noconflict/mode-${selectedMode.modeName}") - - div { - className = ClassName("d-flex justify-content-center flex-fill") - reactAce { - fontSize = "16px" - className = "flex-fill" - mode = selectedMode.modeName - theme = selectedTheme.themeName - width = "auto" - debounceChangePeriod = DEBOUNCE_PERIOD_FOR_EDITORS - value = text - showPrintMargin = false - readOnly = disabled - onChange = { value, _ -> onChangeFun(value) } - markers = aceMarkers - } - } -} - -/** - * Get array of [AceMarker]s for modified lines of a [String]. - * - * @param oldString old version of string - * @param newString new version of string - * @return Array of [AceMarker]s corresponding to modified lines. - */ -fun getAceMarkers(oldString: String, newString: String) = diff( - oldString.split("\n"), - newString.split("\n"), -) - .deltas - .map { - it.target.position to it.target.last() - } - .map { (from, to) -> - aceMarkerBuilder(from, to) - } - .toTypedArray() - -/** - * Get [AceMarker] - * - * @param beginLineIndex index of the first line to be marked - * @param endLineIndex index of the last line to be marked - * @param markerType type of marker - * @param classes - * @return [AceMarker] - */ -fun aceMarkerBuilder( - beginLineIndex: Int, - endLineIndex: Int = beginLineIndex, - markerType: String = "fullLine", - classes: String = "unsaved-marker", -): AceMarker = aceMarkerBuilder( - beginLineIndex, - 0, - endLineIndex, - 1, - classes, - markerType -) - -/** - * Get [AceMarker] from [positionString] - string in format: - * - * (:-) - * - * @param positionString string that contains beginning and ending positions of requested [AceMarker] - * @param classes - * @return [AceMarker] - */ -@Suppress("DestructuringDeclarationWithTooManyEntries") -fun aceMarkerBuilder( - positionString: String, - classes: String = "unsaved-marker", -): AceMarker? = positionString.parsePositionString() - ?.let { positionList -> - val (startRow, startCol, endRow, endCol) = positionList - aceMarkerBuilder( - startRow, - startCol, - endRow, - endCol, - classes, - "background", - ) - } - -/** - * Get [AceMarkers] by [CpgNodeAdditionalParams.location] - string in format - * - * `(:-:)` - * - * @param positionString string that contains start and end positions - * @return [AceMarker] - */ -fun getAceMarkers( - positionString: String? -): AceMarkers = positionString?.let { - aceMarkerBuilder(positionString)?.let { - arrayOf(it) - } ?: emptyArray() -} ?: emptyArray() - -@Suppress("TOO_MANY_PARAMETERS", "LongParameterList") -private fun aceMarkerBuilder( - beginLineIndex: Int, - beginCharacterIndex: Int, - endLineIndex: Int, - endCharacterIndex: Int, - classes: String, - markerType: String -): AceMarker = jso { - startRow = beginLineIndex - endRow = endLineIndex - startCol = beginCharacterIndex - endCol = endCharacterIndex - className = classes - type = markerType - inFront = false -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/reactace/AceThemes.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/reactace/AceThemes.kt deleted file mode 100644 index 7b2d90db6b..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/reactace/AceThemes.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.saveourtool.save.frontend.common.externals.reactace - -/** - * Themes for AceEditor - * - * @property themeName substring of file with required theme - */ -enum class AceThemes(val themeName: String) { - /** - * Light theme - */ - CHROME("chrome"), - - /** - * Another light theme, but worse - */ - GITHUB("github"), - - /** - * Nice dark theme - */ - MONOKAI("monokai"), - ; - - /** - * Method that includes required theme - */ - fun require() = kotlinext.js.require("ace-builds/src-min-noconflict/theme-$themeName") - companion object { - /** - * Theme that is recommended to be used everywhere - */ - val preferredTheme = CHROME - } -} diff --git a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/reactace/ReactAce.kt b/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/reactace/ReactAce.kt deleted file mode 100644 index 9b11c4e6d1..0000000000 --- a/save-frontend-common/src/main/kotlin/com/saveourtool/save/frontend/common/externals/reactace/ReactAce.kt +++ /dev/null @@ -1,82 +0,0 @@ -@file:Suppress("FILE_NAME_MATCH_CLASS", "HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE") -@file:JsModule("react-ace") -@file:JsNonModule - -package com.saveourtool.save.frontend.common.externals.reactace - -import react.* - -/** - * External declaration of [reactAce] react [FC] - */ -@JsName("default") -external val reactAce: FC - -/** - * [Props] for [reactAce] - */ -@Suppress("COMMENTED_OUT_CODE") -@JsName("IAceEditorProps") -external interface AceEditorProps : Props { - var name: String - var style: CSSProperties - var mode: String - var theme: String - var height: String - var width: String - var className: String - var fontSize: String - var showGutter: Boolean - var showPrintMargin: Boolean - var highlightActiveLine: Boolean - var focus: Boolean - var cursorStart: Int - var wrapEnabled: Boolean - var readOnly: Boolean - var minLines: Int - var maxLines: Int - var navigateToFileEnd: Boolean - var debounceChangePeriod: Int? - var enableBasicAutocompletion: Boolean - var enableLiveAutocompletion: Boolean - var tabSize: Int - var value: String - var placeholder: String? - var defaultValue: String - var enableSnippets: Boolean - var setOptions: dynamic - var markers: AceMarkers - - @Suppress("TYPE_ALIAS") - var onChange: (value: String, event: dynamic) -> Unit - // var onSelectionChange: (value: String, event: Event) -> Unit - // onCursorChange?: (value: any, event?: any) => void; - // onInput?: (event?: any) => void; - // onLoad?: (editor: Ace.Editor) => void; - // onValidate?: (annotations: Ace.Annotation[]) => void; - // onBeforeLoad?: (ace: typeof AceBuilds) => void; - // onSelection?: (selectedText: string, event?: any) => void; - // onCopy?: (value: string) => void; - // onPaste?: (value: string) => void; - // onFocus?: (event: any, editor?: Ace.Editor) => void; - // onBlur?: (event: any, editor?: Ace.Editor) => void; - // onScroll?: (editor: IEditorProps) => void; - // editorProps?: IEditorProps; - // keyboardHandler?: string; - // commands?: ICommand[]; - // annotations?: Ace.Annotation[]; -} - -/** - * Line markers for [reactAce] - */ -@JsName("IMarker") -external interface AceMarker { - var startRow: Int - var startCol: Int - var endRow: Int - var endCol: Int - var className: String - var type: dynamic - var inFront: Boolean -}