Skip to content

Commit d8a9beb

Browse files
fix(schemaComposition): make highlight to scroll with editor (#5719)
* style: use native monaco editor api for customized style for sync highlight * chore: run prettier * chore: add sync off style * chore: add clickable icon to editor * chore: update comment * chore: make sync icon to be a background image and un-clickable * chore: run prettier * chore: add comment * test: update classNames in test
1 parent 825ee84 commit d8a9beb

File tree

4 files changed

+57
-115
lines changed

4 files changed

+57
-115
lines changed

cypress/e2e/shared/fluxQueryBuilder.test.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,7 @@ describe('Script Builder', () => {
250250
`|> yield(name: "_editor_composition")`
251251
)
252252
cy.getByTestID('flux-editor').within(() => {
253-
cy.get('#schema-composition-sync-icon', {timeout: 3000}).should(
254-
'have.length',
255-
1
256-
)
257-
cy.get('.composition-sync').should('have.length', 2)
253+
cy.get('.composition-sync--on').should('have.length', 4) // four lines
258254
})
259255
}
260256

src/languageSupport/languages/flux/lsp/connection.ts

Lines changed: 30 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ import {reportErrorThroughHoneyBadger} from 'src/shared/utils/errors'
3030
// Utils
3131
import {event} from 'src/cloud/utils/reporting'
3232

33-
const ICON_SYNC_CLASSNAME = 'composition-sync'
34-
export const ICON_SYNC_ID = 'schema-composition-sync-icon'
35-
3633
// hardcoded in LSP
3734
const COMPOSITION_YIELD = '_editor_composition'
3835
const COMPOSITION_INIT_LINE = 1
@@ -137,24 +134,6 @@ class LspConnectionManager {
137134
})
138135
}
139136

140-
_setEditorSyncToggle() {
141-
setTimeout(() => {
142-
const clickableInvisibleDiv = document.getElementById(ICON_SYNC_ID)
143-
// add listeners
144-
clickableInvisibleDiv.removeEventListener('click', () =>
145-
this._setSessionSync(!this._session.composition.synced)
146-
) // may have existing
147-
clickableInvisibleDiv.addEventListener('click', () => {
148-
event('Toggled Flux Sync in editor', {
149-
active: `${!this._session.composition.synced}`,
150-
})
151-
this._setSessionSync(!this._session.composition.synced)
152-
})
153-
154-
this._alignInvisibleDivToEditorBlock()
155-
}, 1000)
156-
}
157-
158137
_editorChangeIsFromLsp(change) {
159138
return change.text?.includes('|> yield(name: "_editor_composition")')
160139
}
@@ -188,84 +167,49 @@ class LspConnectionManager {
188167
})
189168
}
190169

191-
_alignInvisibleDivToEditorBlock() {
192-
// elements in monaco-editor. positioned by editor.
193-
const syncIcons = document.getElementsByClassName(ICON_SYNC_CLASSNAME)
194-
195-
// UI elements we control
196-
const clickableInvisibleDiv = document.getElementById(ICON_SYNC_ID)
197-
if (!syncIcons.length || !clickableInvisibleDiv) {
198-
return
170+
_compositionSyncStyle(startLine: number, endLine: number, synced: boolean) {
171+
const classNamePrefix = synced
172+
? 'composition-sync--on'
173+
: 'composition-sync--off'
174+
175+
// Customize the full width of Monaco editor margin using API `marginClassName`
176+
// https://github.com/microsoft/monaco-editor/blob/35eb0ef/website/typedoc/monaco.d.ts#L1533
177+
const startLineStyle = {
178+
range: new MonacoTypes.Range(startLine, 1, startLine, 1),
179+
options: {
180+
marginClassName: `${classNamePrefix}--first`,
181+
},
199182
}
200-
201-
const [upperIcon] = syncIcons
202-
let [, lowerIcon] = syncIcons
203-
if (!lowerIcon) {
204-
lowerIcon = upperIcon
183+
const middleLinesStyle = {
184+
range: new MonacoTypes.Range(startLine, 1, endLine, 1),
185+
options: {
186+
marginClassName: classNamePrefix,
187+
},
205188
}
206-
const compositionBlock = this._getCompositionBlockLines()
207-
if (!compositionBlock) {
208-
return
189+
const endLineStyle = {
190+
range: new MonacoTypes.Range(endLine, 1, endLine, 1),
191+
options: {
192+
marginClassName: `${classNamePrefix}--last`,
193+
},
209194
}
210-
const {startLine, endLine} = compositionBlock
211-
212-
// move div to match monaco-editor coordinates
213-
clickableInvisibleDiv.style.top = ((upperIcon as any).offsetTop || 0) + 'px'
214-
const height =
215-
((lowerIcon as any).offsetHeight || 0) * (endLine - startLine + 1) +
216-
((upperIcon as any).offsetTop || 0)
217-
clickableInvisibleDiv.style.height = height + 'px'
218-
// width size is always the same, defined in classname "sync-bar"
195+
return [startLineStyle, middleLinesStyle, endLineStyle]
219196
}
220197

221198
_setEditorBlockStyle(schema: SchemaSelection = this._session) {
222199
const compositionBlock = this._getCompositionBlockLines()
223200

224-
const startLineStyle = [
225-
{
226-
range: new MonacoTypes.Range(
227-
compositionBlock?.startLine,
228-
1,
229-
compositionBlock?.startLine,
230-
1
231-
),
232-
options: {
233-
linesDecorationsClassName: ICON_SYNC_CLASSNAME,
234-
},
235-
},
236-
]
237-
const endLineStyle = [
238-
{
239-
range: new MonacoTypes.Range(
240-
compositionBlock?.endLine,
241-
1,
242-
compositionBlock?.endLine,
243-
1
244-
),
245-
options: {
246-
linesDecorationsClassName: ICON_SYNC_CLASSNAME,
247-
},
248-
},
249-
]
250-
251201
const removeAllStyles = !compositionBlock || schema.composition.diverged
252202

203+
const compositionSyncStyle = this._compositionSyncStyle(
204+
compositionBlock?.startLine,
205+
compositionBlock?.endLine,
206+
schema.composition.synced
207+
)
208+
253209
this._compositionStyle = this._editor.deltaDecorations(
254210
this._compositionStyle,
255-
removeAllStyles ? [] : startLineStyle.concat(endLineStyle)
211+
removeAllStyles ? [] : compositionSyncStyle
256212
)
257-
258-
this._alignInvisibleDivToEditorBlock()
259-
const clickableInvisibleDiv = document.getElementById(ICON_SYNC_ID)
260-
clickableInvisibleDiv.className = schema.composition.synced
261-
? 'sync-bar sync-bar--on'
262-
: 'sync-bar sync-bar--off'
263-
264-
if (removeAllStyles) {
265-
clickableInvisibleDiv.style.display = 'none'
266-
} else {
267-
clickableInvisibleDiv.style.display = 'block'
268-
}
269213
}
270214

271215
// XXX: wiedld (25 Aug 2022) - handling the absence of a middleware listener
@@ -409,7 +353,6 @@ class LspConnectionManager {
409353

410354
_initCompositionHandlers() {
411355
// handlers to trigger end composition
412-
this._setEditorSyncToggle()
413356
this._setEditorIrreversibleExit()
414357

415358
// XXX: wiedld (25 Aug 2022) - eventually, this should be from the LSP response.

src/shared/components/FluxMonacoEditor.scss

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,29 +48,40 @@
4848
position: relative;
4949
overflow: hidden;
5050

51-
.sync-bar {
52-
position: absolute;
53-
width: 48px;
51+
.composition-sync--on {
52+
background: #00a3ff26; // blue with 15% opacity
5453
}
5554

56-
.sync-bar--on {
57-
background: #00a3ff26; // blue with 15% opacity
55+
.composition-sync--on--first {
5856
border-top: 1px solid $c-pool;
59-
border-bottom: 1px solid $c-pool;
57+
// composition sync icon
58+
background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4.82511 4.0427L7.10622 1.6971L5.67243 0.302734L0.0902793 6.0427H16V4.0427H4.82511ZM11.1749 11.9571H0V9.95714H15.9097L10.3275 15.6971L8.89376 14.3027L11.1749 11.9571Z' fill='%2300a3ff'/%3E%3C/svg%3E%0A");
59+
background-repeat: no-repeat;
60+
background-size: 11px 11px;
61+
background-position: $cf-space-3xs $cf-space-3xs;
62+
}
6063

61-
.sync-icon {
62-
color: $c-pool;
63-
}
64+
.composition-sync--on--last {
65+
border-bottom: 1px solid $c-pool;
6466
}
6567

66-
.sync-bar--off {
68+
.composition-sync--off {
6769
opacity: 50%;
6870
background-color: $cf-grey-35;
71+
}
72+
73+
.composition-sync--off--first {
74+
opacity: 50%;
6975
border-top: 1px solid $cf-white;
70-
border-bottom: 1px solid $cf-white;
76+
// composition sync icon
77+
background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4.82511 4.0427L7.10622 1.6971L5.67243 0.302734L0.0902793 6.0427H16V4.0427H4.82511ZM11.1749 11.9571H0V9.95714H15.9097L10.3275 15.6971L8.89376 14.3027L11.1749 11.9571Z' fill='white'/%3E%3C/svg%3E%0A");
78+
background-repeat: no-repeat;
79+
background-size: 11px 11px;
80+
background-position: $cf-space-3xs $cf-space-3xs;
81+
}
7182

72-
.sync-icon {
73-
color: $cf-white;
74-
}
83+
.composition-sync--off--last {
84+
opacity: 50%;
85+
border-bottom: 1px solid $cf-white;
7586
}
7687
}

src/shared/components/FluxMonacoEditor.tsx

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import classnames from 'classnames'
77
// Components
88
import MonacoEditor from 'react-monaco-editor'
99
import ErrorBoundary from 'src/shared/components/ErrorBoundary'
10-
import {Icon, IconFont} from '@influxdata/clockface'
1110

1211
// LSP
1312
import FLUXLANGID from 'src/languageSupport/languages/flux/monaco.flux.syntax'
@@ -18,9 +17,7 @@ import {
1817
submit,
1918
} from 'src/languageSupport/languages/flux/monaco.flux.hotkeys'
2019
import {registerAutogrow} from 'src/languageSupport/monaco.autogrow'
21-
import ConnectionManager, {
22-
ICON_SYNC_ID,
23-
} from 'src/languageSupport/languages/flux/lsp/connection'
20+
import ConnectionManager from 'src/languageSupport/languages/flux/lsp/connection'
2421

2522
// Contexts and State
2623
import {EditorContext} from 'src/shared/contexts/editor'
@@ -159,11 +156,6 @@ const FluxEditorMonaco: FC<Props> = ({
159156
}}
160157
editorDidMount={editorDidMount}
161158
/>
162-
{useSchemaComposition && (
163-
<div id={ICON_SYNC_ID} className="sync-bar">
164-
<Icon glyph={IconFont.Sync} className="sync-icon" />
165-
</div>
166-
)}
167159
</div>
168160
</ErrorBoundary>
169161
),

0 commit comments

Comments
 (0)