diff --git a/designer/client/src/actions/nk/process.ts b/designer/client/src/actions/nk/process.ts index 8509e9b5f4f..9887f05b646 100644 --- a/designer/client/src/actions/nk/process.ts +++ b/designer/client/src/actions/nk/process.ts @@ -60,23 +60,23 @@ export function displayTestCapabilities(processName: ProcessName, scenarioGraph: ); } -export function fetchStickyNotesForScenario(scenarioName: string, scenarioVersionId: number): ThunkAction { - return (dispatch) => { - HttpService.getStickyNotes(scenarioName, scenarioVersionId).then((stickyNotes) => { +const refreshStickyNotes = (dispatch, scenarioName: string, scenarioVersionId: number) => { + return HttpService.getStickyNotes(scenarioName, scenarioVersionId).then((stickyNotes) => { + flushSync(() => { dispatch({ type: "STICKY_NOTES_UPDATED", stickyNotes: stickyNotes.data }); + dispatch(layoutChanged()); }); - }; + }); +}; + +export function fetchStickyNotesForScenario(scenarioName: string, scenarioVersionId: number): ThunkAction { + return (dispatch) => refreshStickyNotes(dispatch, scenarioName, scenarioVersionId); } export function stickyNoteUpdated(scenarioName: string, scenarioVersionId: number, stickyNote: StickyNote): ThunkAction { return (dispatch) => { HttpService.updateStickyNote(scenarioName, scenarioVersionId, stickyNote).then((_) => { - HttpService.getStickyNotes(scenarioName, scenarioVersionId).then((stickyNotes) => { - flushSync(() => { - dispatch({ type: "STICKY_NOTES_UPDATED", stickyNotes: stickyNotes.data }); - dispatch(layoutChanged()); - }); - }); + refreshStickyNotes(dispatch, scenarioName, scenarioVersionId); }); }; } @@ -94,12 +94,7 @@ export function stickyNoteDeleted(scenarioName: string, stickyNoteId: number): T export function stickyNoteAdded(scenarioName: string, scenarioVersionId: number, position: Position, dimensions: Dimensions): ThunkAction { return (dispatch) => { HttpService.addStickyNote(scenarioName, scenarioVersionId, position, dimensions).then((_) => { - HttpService.getStickyNotes(scenarioName, scenarioVersionId).then((stickyNotes) => { - flushSync(() => { - dispatch({ type: "STICKY_NOTES_UPDATED", stickyNotes: stickyNotes.data }); - dispatch(layoutChanged()); - }); - }); + refreshStickyNotes(dispatch, scenarioName, scenarioVersionId); }); }; } diff --git a/designer/client/src/components/StickyNotePreview.tsx b/designer/client/src/components/StickyNotePreview.tsx index 0184d65318e..af37f0fd504 100644 --- a/designer/client/src/components/StickyNotePreview.tsx +++ b/designer/client/src/components/StickyNotePreview.tsx @@ -6,12 +6,12 @@ import { alpha, useTheme } from "@mui/material"; import { getBorderColor, getStickyNoteBackgroundColor } from "../containers/theme/helpers"; import { STICKY_NOTE_CONSTRAINTS, STICKY_NOTE_DEFAULT_COLOR } from "./graph/EspNode/stickyNote"; +const PREVIEW_SCALE = 0.9; +const ACTIVE_ROTATION = 2; +const INACTIVE_SCALE = 1.5; + export function StickyNotePreview({ isActive, isOver }: { isActive?: boolean; isOver?: boolean }): JSX.Element { const theme = useTheme(); - - const PREVIEW_SCALE = 0.9; - const ACTIVE_ROTATION = 2; - const INACTIVE_SCALE = 1.5; const scale = isOver ? 1 : PREVIEW_SCALE; const rotation = isActive ? (isOver ? -ACTIVE_ROTATION : ACTIVE_ROTATION) : 0; const finalScale = isActive ? 1 : INACTIVE_SCALE; diff --git a/designer/client/src/components/graph/EspNode/stickyNote.ts b/designer/client/src/components/graph/EspNode/stickyNote.ts index 2c939415b5f..41c8d2d988e 100644 --- a/designer/client/src/components/graph/EspNode/stickyNote.ts +++ b/designer/client/src/components/graph/EspNode/stickyNote.ts @@ -19,7 +19,7 @@ export const STICKY_NOTE_CONSTRAINTS = { export const BORDER_RADIUS = 3; export const CONTENT_PADDING = 5; export const ICON_SIZE = 20; -export const STICKY_NOTE_DEFAULT_COLOR = "#13130d"; +export const STICKY_NOTE_DEFAULT_COLOR = "#eae672"; export const MARKDOWN_EDITOR_NAME = "markdown-editor"; const border: dia.MarkupNodeJSON = { diff --git a/designer/client/src/components/graph/EspNode/stickyNoteElements.ts b/designer/client/src/components/graph/EspNode/stickyNoteElements.ts index ec3c2e97c84..146b910261e 100644 --- a/designer/client/src/components/graph/EspNode/stickyNoteElements.ts +++ b/designer/client/src/components/graph/EspNode/stickyNoteElements.ts @@ -36,7 +36,7 @@ export function makeStickyNoteElement( color: theme.palette.getContrastText(getStickyNoteBackgroundColor(theme, stickyNote.color).main), }, icon: { - xlinkHref: stickyNoteIcon, + xlinkHref: stickyNoteIcon(), opacity: 1, color: theme.palette.getContrastText(getStickyNoteBackgroundColor(theme, stickyNote.color).main), }, diff --git a/designer/client/src/components/graph/Graph.tsx b/designer/client/src/components/graph/Graph.tsx index 248728eaf51..bae19bd6c60 100644 --- a/designer/client/src/components/graph/Graph.tsx +++ b/designer/client/src/components/graph/Graph.tsx @@ -12,7 +12,7 @@ import { EventTrackingSelector, EventTrackingType, TrackEventParams } from "../. import { isTouchEvent, LONG_PRESS_TIME } from "../../helpers/detectDevice"; import { batchGroupBy } from "../../reducers/graph/batchGroupBy"; import { UserSettings } from "../../reducers/userSettings"; -import { Edge, LayoutData, NodeId, NodeType, ProcessDefinitionData, ScenarioGraph } from "../../types"; +import { Edge, NodeId, NodeType, ProcessDefinitionData, ScenarioGraph } from "../../types"; import { ComponentDragPreview } from "../ComponentDragPreview"; import { Scenario } from "../Process/types"; import { createUniqueArrowMarker } from "./arrowMarker"; @@ -531,7 +531,7 @@ export class Graph extends React.Component { if (this.props.isFragment === true) return; const canAddStickyNote = this.props.capabilities.editFrontend; if (canAddStickyNote) { - const dimensions = { width: STICKY_NOTE_CONSTRAINTS.DEFAULT_WIDTH, height: STICKY_NOTE_CONSTRAINTS.MIN_HEIGHT }; + const dimensions = { width: STICKY_NOTE_CONSTRAINTS.DEFAULT_WIDTH, height: STICKY_NOTE_CONSTRAINTS.DEFAULT_HEIGHT }; this.props.stickyNoteAdded(scenarioName, scenarioVersionId, position, dimensions); } } diff --git a/designer/client/src/components/graph/StickyNoteElement.ts b/designer/client/src/components/graph/StickyNoteElement.ts index b3c70ecfdbb..9dcdcbad2dd 100644 --- a/designer/client/src/components/graph/StickyNoteElement.ts +++ b/designer/client/src/components/graph/StickyNoteElement.ts @@ -3,13 +3,13 @@ import { Events } from "./types"; import { MARKDOWN_EDITOR_NAME } from "./EspNode/stickyNote"; import MarkupNodeJSON = dia.MarkupNodeJSON; -interface StickyNoteDefaults { +export interface StickyNoteDefaults { position?: { x: number; y: number }; size?: { width: number; height: number }; attrs?: Record; } -interface StickyNoteProtoProps { +export interface StickyNoteProtoProps { markup: (dia.MarkupNodeJSON | MarkupNodeJSON)[]; [key: string]: unknown; } @@ -19,7 +19,6 @@ export const StickyNoteElement = (defaults?: StickyNoteDefaults, protoProps?: St export const StickyNoteElementView = dia.ElementView.extend({ events: { - "change textarea": "onChange", "click textarea": "stopPropagation", "keydown textarea": "selectAll", "focusout textarea": "onChange", diff --git a/designer/client/src/components/toolbars/creator/ComponentIcon.tsx b/designer/client/src/components/toolbars/creator/ComponentIcon.tsx index 1d8569690dd..bd3c350151a 100644 --- a/designer/client/src/components/toolbars/creator/ComponentIcon.tsx +++ b/designer/client/src/components/toolbars/creator/ComponentIcon.tsx @@ -24,7 +24,9 @@ const preloadBeImage = memoize((src: string): string | null => { }); export const stickyNoteIconSrc = `/assets/components/${StickyNoteType}.svg`; -export const stickyNoteIcon: string | null = preloadBeImage(stickyNoteIconSrc); +export function stickyNoteIcon(): string | null { + return preloadBeImage(stickyNoteIconSrc); +} export function getComponentIconSrc(node: NodeType, { components }: ProcessDefinitionData): string | null { // missing type means that node is the fake properties component diff --git a/designer/server/src/main/scala/pl/touk/nussknacker/ui/api/StickyNotesApiHttpService.scala b/designer/server/src/main/scala/pl/touk/nussknacker/ui/api/StickyNotesApiHttpService.scala index a4c5e5c3eb6..0c29c5257c3 100644 --- a/designer/server/src/main/scala/pl/touk/nussknacker/ui/api/StickyNotesApiHttpService.scala +++ b/designer/server/src/main/scala/pl/touk/nussknacker/ui/api/StickyNotesApiHttpService.scala @@ -138,9 +138,8 @@ class StickyNotesApiHttpService( .right( dbioActionRunner .run( - stickyNotesRepository.findStickyNotes(scenarioId, versionId) + stickyNotesRepository.countStickyNotes(scenarioId, versionId) ) - .map(_.length) ) private def deleteStickyNote(noteId: StickyNoteId)( diff --git a/designer/server/src/main/scala/pl/touk/nussknacker/ui/process/repository/stickynotes/DbStickyNotesRepository.scala b/designer/server/src/main/scala/pl/touk/nussknacker/ui/process/repository/stickynotes/DbStickyNotesRepository.scala index 9469f10c0c4..8acf546cf28 100644 --- a/designer/server/src/main/scala/pl/touk/nussknacker/ui/process/repository/stickynotes/DbStickyNotesRepository.scala +++ b/designer/server/src/main/scala/pl/touk/nussknacker/ui/process/repository/stickynotes/DbStickyNotesRepository.scala @@ -47,6 +47,22 @@ class DbStickyNotesRepository private (override protected val dbRef: DbRef, over ) } + override def countStickyNotes(scenarioId: ProcessId, scenarioVersionId: VersionId): DB[Int] = { + run( + stickyNotesTable + .filter(event => event.scenarioId === scenarioId && event.scenarioVersionId <= scenarioVersionId) + .groupBy(_.noteCorrelationId) + .map { case (noteCorrelationId, notes) => (noteCorrelationId, notes.map(_.eventDate).max) } + .join(stickyNotesTable) + .on { case ((noteCorrelationId, eventDate), event) => + event.noteCorrelationId === noteCorrelationId && event.eventDate === eventDate + } + .map { case ((_, _), event) => event } + .result + .map(events => events.count(_.eventType != StickyNoteEvent.StickyNoteDeleted)) + ) + } + override def findStickyNoteById( noteId: StickyNoteId )(implicit user: LoggedUser): DB[Option[StickyNoteEventEntityData]] = { diff --git a/designer/server/src/main/scala/pl/touk/nussknacker/ui/process/repository/stickynotes/StickyNotesRepository.scala b/designer/server/src/main/scala/pl/touk/nussknacker/ui/process/repository/stickynotes/StickyNotesRepository.scala index a9c5800163d..6f762c7ad49 100644 --- a/designer/server/src/main/scala/pl/touk/nussknacker/ui/process/repository/stickynotes/StickyNotesRepository.scala +++ b/designer/server/src/main/scala/pl/touk/nussknacker/ui/process/repository/stickynotes/StickyNotesRepository.scala @@ -23,6 +23,11 @@ trait StickyNotesRepository { scenarioVersionId: VersionId ): DB[Seq[StickyNote]] + def countStickyNotes( + scenarioId: ProcessId, + scenarioVersionId: VersionId + ): DB[Int] + def addStickyNote( content: String, layoutData: LayoutData,