-
Notifications
You must be signed in to change notification settings - Fork 0
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
GSLUX-707 activate style edition for drawings #161
Conversation
GitHub Pages links: * Luxembourg-geoportail: https://geoportail-luxembourg.github.io/luxembourg-geoportail/GSLUX-707_drawStyle/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the nice feature @mki-c2c ! Code looks mostly good to me. I left some comments and ideas regarding the testing inline. Don't forget to rebase, as the circle edition has evolved. Shouldn't have an impact here though, if I see right.
Testing it, it works really well. The only thing I noticed that didn't work is the eyedropper stick (not sure if that's what you call it) to choose a color from somewhere else. But it is the same on prod.
Also noticed that you don't have to validate style changes when switching between features. They are preserved, which might be a little strange. But prod also behaves the same here. So averything is isofunctional :-)
cy.window() | ||
.its('featureHash') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should be able to wrap this into a cypress function in the commands.ts
utilities, where an import of FeatureHash
should be possible. Not totally sure, but this would avoid the window workaround.
Then again, there is the question if it makes sense to import logic in the tests that we want to test? An alternative would be to test against the encoded URL values instead of the decodes ones (maybe with the decoded ones in comments). Certainly much less readable, but it would test for potential regressions in FeatureHash
.
Or maybe we could manage to test the style properties directly on the openlayers features without using the URL. By getting the map from the window and then the drawLayer => source => feature => style!? Not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have loved to import the functions in cypress, but it did not work since the package luxembourg does not exist and must be built first. The window trick seems to be common in tips I found online and we already used it for olMap here: https://github.com/Geoportail-Luxembourg/luxembourg-geoportail/blob/main/cypress/support/commands.ts#L51
I found the e2e test via the URL to be very powerful, the encoding in the URL is a good representation of the app's state
function onSizeChange(newSize: string | number) { | ||
feature.featureStyle.size = parseFloat(newSize as string) | ||
feature.changed() | ||
} | ||
|
||
function onAngleChange(newAngle: string | number) { | ||
feature.featureStyle.angle = (parseFloat(newAngle as string) * Math.PI) / 180 | ||
feature.changed() | ||
} | ||
|
||
function onWidthChange(newWidth: string | number) { | ||
feature.featureStyle.stroke = parseFloat(newWidth as string) | ||
feature.changed() | ||
} | ||
|
||
function onTransparencyChange(newTransparency: string | number) { | ||
feature.featureStyle.opacity = | ||
(100 - parseFloat(newTransparency as string)) / 100 | ||
feature.changed() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the input param always be number
here, as we use a number
input in the html template? This could make the casting and converting unnecessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using v-model.number
to enforce events as number in the common rangefinder component
data-cy="featStyleColor" | ||
/> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<template v-slot:size> | ||
<template v-slot:size="slotProps"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for my understanding, where does the slotProps
come from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it' so that I can pass the max parameter for the template configuration
cf <slot name="size" :maxsize="900"></slot>
src/components/draw/feature-item.vue
Outdated
// should preform deep copy, nut then the updqte of the OL object on the canvas would not work ?? | ||
const localFeature = props.feature |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this still an open question?
5d2f860
to
398802a
Compare
still öissing: line style and point symbol
- different style options - validate => URL - cancel => restore style
ba81f8f
to
9a92015
Compare
…cies between CI and local tests
.trigger('input') | ||
cy.get('*[data-cy="featStyleLineWidth"]').type('{selectAll}5.5') | ||
cy.get('*[data-cy="featStyleTransparency"]').type('{selectAll}22') | ||
cy.get('button[data-cy="featureEditValidate"]').click() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you wrap all this in a describe statement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll have to check potential reorganisation
}) | ||
}) | ||
|
||
describe('When checking featureStyle in OL DrawnFeature object', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually e2e is meant to mimic user behavior in the browser, so put this statement "When checking featureStyle in OL DrawnFeature object" in a describe for an e2e tests is awkward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was the result of some discussion, in theory e2e would be only capable of checking rendered pixels, but this seems a bit too picky. Both checking th URL and checking the OL features' attributes seem a good compromise for meaningful tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was talking about the text description, not the test itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah ;-)
that's easier then.
package.json
Outdated
@@ -15,8 +15,8 @@ | |||
"test:unit": "vitest --environment jsdom --root .", | |||
"test:unit:ci": "vitest run --environment jsdom --coverage", | |||
"test:e2e": "INSTRUMENT_COVERAGE=true start-server-and-test preview :4173 'cypress open --e2e'", | |||
"test:e2e:ci": "INSTRUMENT_COVERAGE=true start-server-and-test 'VITE_USE_PROXYURL=false vite dev --port 4173' :4173 'cypress run --browser chrome --e2e'", | |||
"test:e2e:dev": "INSTRUMENT_COVERAGE=true start-server-and-test 'vite dev --port 4173' :4173 'cypress open --browser chrome --e2e'", | |||
"test:e2e:ci": "INSTRUMENT_COVERAGE=true start-server-and-test 'VITE_USE_PROXYURL=false vite dev --port 4173' :4173 'cypress run --browser chromium --e2e'", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this change???
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok seen together: I didn't know you couldn't run the e2e tests because your are using chromium. But apparently you have found a solution. Thx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, it was not intended to be merged without notice. I wanted the change to go into CI first, with its share of surprises.
Now, cypress is configured to use the first browser among chrome and chromium it will encounter. That should be pretty robust
<img | ||
class="symbol-style" | ||
v-if="!!feature.featureStyle.symbolId" | ||
:src="`${SYMBOL_ICONS_URL}/symbol/${feature.featureStyle.symbolId}`" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why "symbol/
" is not included in the SYMBOL_ICONS_URL
const?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because symbol.url provided by the backend includes symbol/
https://github.com/Geoportail-Luxembourg/luxembourg-geoportail/blob/GSLUX-707_drawStyle/src/components/draw/feature-edit-symbol-list.vue#L55
|
||
function onSizeChange(newSize: number) { | ||
feature.featureStyle.size = newSize | ||
feature.changed() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure the component should be aware of the openlayers feature implementation, it would have been great to refactor and move all this in a service or maybe add new methods to our extended Feature class that already exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, could be cleaner to wrap all this into the DrawnFeature
...
Cross, | ||
Triangle, | ||
} as const | ||
const currentSymbolTab: Ref<tabs> = ref(tabs.configurables) | ||
const featureColor = 'red' // feature.olFeature.get('color') // TODO: to plug when feature ok | ||
// const featureColor = feature.featureStyle.color |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clean comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
} | ||
|
||
function onChangeSymbol(id: number) { | ||
alert('onChangeSymbol TODO' + id) // TODO: | ||
backNavigation() | ||
feature.featureStyle.symbolId = `${id}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor: do this in a class/service, maybe extend the existing one. Same for all the functions above that is changing the feature style.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's really tricky, if we put a setter on the symbolId, it will not be able to trigger the redraw of its parent, otherwise we have to clone the whole featureStyle.
Actually this listener is the place in the code where access to both symbolId and changed() is possible.
Refactoring is possible, but not sure if these penalties will be worthwhile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try to write a POC to see if it's not too complex
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I converted modifying the featureStyle attributes to cloning the featureStyle object.
I am not quite happy with this change since it slowed down the app quite a lot.
Could you please test if the app is sluggiish for you too ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The app still works fine for me, I don't see any latency. Thx for the refactor, I was thinking about a function that sets any given property of the style instead of setting the entire style, but you did it this way and it works fine 👌🏽.
let prevLabel = feature.label | ||
let prevDescription = feature.description | ||
// keep deep copy of previous style to be able to revert style on cancel | ||
const prevStyle: DrawnFeatureStyle = { ...feature.featureStyle } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the logic in keeping the style or the description + label in this specific component? You handle the change in the parent component, it is very hard to find where operations and setters are made.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in case you cancel the editions, label and description are restored. This is not related to the PR, but it was a functional difference with prod
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I understand the functionality, my question was: why storing previous values here in this specific feature-sub-content.vue
? what is the link with "sub-content"? You could just emit the cancel event, and the parent handles the previous values itself.
Plus I see the label is updated in the treeview but not on the map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the adaptions @mki-c2c and for the double-checking in the tests (URL+feature)!
@@ -22,7 +22,7 @@ describe('Background selector', () => { | |||
const layers = (<AUTWindowOlMap>window).olMap | |||
.getLayers() | |||
.getArray() | |||
.filter((l: any) => l.get('cyLayerType') !== 'featureLayer') | |||
.filter((l: any) => !/feature(Edit)?Layer/.exec(l.get('cyLayerType'))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little pity, we can't target the bgLayers directly during filtering, but I guess that's how it is.
@@ -35,7 +35,10 @@ describe('Draw "Circle"', () => { | |||
) | |||
cy.dragVertexOnMap(200, 200, 300, 300) | |||
cy.get('*[data-cy="featItemLength"]').should('contain.text', '693.17 km') | |||
cy.get('*[data-cy="featItemArea"]').should('contain.text', '38235.40 km²') | |||
// test of 2 possible measurements due to precision issues between local tests and CI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can get rid or adapt this comment now :-) (I see you adapted it below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
}) | ||
}) | ||
|
||
// describe('Test style edition of Point feature', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you forget to uncomment or delete this describe
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops
|
||
function onSizeChange(newSize: number) { | ||
feature.featureStyle.size = newSize | ||
feature.changed() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, could be cleaner to wrap all this into the DrawnFeature
...
currentEditCompKey.value = undefined | ||
} | ||
|
||
function onClickValidate() { | ||
const currentComponent = | ||
editComponents[currentEditCompKey.value as keyof typeof editComponents] | ||
|
||
prevLabel = feature.label | ||
prevDescription = feature.description | ||
Object.assign(prevStyle, feature.featureStyle) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Object assign?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, I'll put prevStyle = {...feature.featureStyle}
for homogeneity
Somehow I find
Object.assign(prevStyle, feature.featureStyle)
more concise in this case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, I just saw, this writing makes the linter catch a const modification, I see a whole new advantage int the spread syntax.
cool!
cypress.config.ts
Outdated
@@ -13,6 +13,14 @@ export default defineConfig({ | |||
|
|||
// It's IMPORTANT to return the config object | |||
// with any changed environment variables | |||
// console.log(JSON.stringify(config.browsers)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove unnecessary comments (console.log)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hard to debug
// cy.visit('/') | ||
// describe('Draw "Point"', () => { | ||
// cy.get('button[data-cy="drawButton"]').click() | ||
// cy.get('button[data-cy="drawPointButton"]').click() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we going to keep all these comments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
forgot to delete
.filter((l: any) => l.get('cyLayerType') !== 'featureLayer') | ||
.filter( | ||
(l: any) => | ||
// regex match |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes we know this is a regex, what is the purpose of this comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it helps reading, since nothing tells, this is a regex, I did not know this obscure syntax represents a regex
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please clean your code:
- remove unnecessary comments,
- use "===" as much as possible (unless it is a choice on purpose),
- prefer using {..., something, ... something else } instead of Object.assign() (unless it is on purpose, in some cases I agree Object.assign will be more usefull),
- and refacto all functions that sets the feature style.
One other UI difference: when modifying a line style in prod, feature is not selected (line width is not thicker) whereas in your PR, the line is thicker and updating the stroke width preview on the map when modifying is not the definite one. |
One other thing: When adding a symbol and setting a size to a point, after zooming out, the symbol keeps the same size. Ok to keep it as is (same behavior in prod). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok thx a lot for the rework, I don't see any latency, maybe someone else should test it? ping @tkohr
There are some minor things regarding the UI, it could be great to fix them before merging.
No latencies on my side neither :-) |
- sync line direction with feature value - refactor line styles into mini-component - sync button state with line style - fix unselect behavior when clicking on map away from features
- move setRadius from composable useEdit to service to prevent creation of multiple listeners (useEdit, must remain singleton) - fix selection, deselection of features between edit modes
225c586
to
eae429f
Compare
fixed the UI issues and some more (related to selection deselection) |
No user configured icons so far (awaiting myMaps)
JIRA issue
https://jira.camptocamp.com/browse/GSLUX-707
Description
first review to validate the testing approach (for point and polygon):
edit style => check correct URL
Screenshots
(only if the final render is different)