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

display warning in new note form after too many anonymous notes #5468

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

etiennejourdier
Copy link

Motivation

In the French community, we've had a problem for over a year with someone creating a huge number of anonymous notes, which hampers the processing of other relevant notes in the same area. See this discussion on the French community forum.

I thought it would be a good idea to count the number of anonymous notes created in the same browser and to display a warning when this number becomes too high, to encourage visitors to become users and contributors.

Description

This PR creates a new warning in the UI of the new note form if an anonymous visitor has already created too many anonymous notes (threshold set at 20 for now)
image

Changes:

  • in template views/note/new.html.erb
    • add a new div element displaying the warning (hidden at first)
  • in locales/en.yml
    • add text and links for the warning, with ‘(N)’ being replaced by the number of anonymous notes
  • in new_note.js
    • when an anonymous note is created: add +1 to the counter in localStorage
    • when the form is displayed: check the counter in localStorage. If more that 20 notes have already been created: display the warning, and replace (N) in the text warning with the number of anonymous notes already created.

Possible additional change (not included yet)
After an even larger number of anonymous notes (50?), I thought we could hide the textarea, and trigger its display by clicking on a button sure you want to post an anonymous note again?, which would force the visitor to perform an additional action. This is not included in this PR yet, but tell me if you want me to add it.

How has this been tested?

The code has been tested on my personal computer using rails built-in webserver. I verified that the new note form is still working fine both when logged in and in anonymous mode.

However, as described in issue #5467 I was not able to make all the tests requested in CONTRIBUTING.md.

As this is my very first PR, I'm not sure I've done everything right, so I welcome any relevant comments!

create a counter of anonymous notes in localStorage, then, if an anonymous visitor has already created too many notes, display a warning in the new note form to encourage him to contribute by himself
@tomhughes
Copy link
Member

If they're valid notes I don't really see the problem? Are these genuine notes or is this some sort of spam attack?

if (typeof OSM.user === "undefined" && anonymousNotesCount >= 20) {
var counterWarning = content.find("#new-note-counter-warning");
if (typeof counterWarning.html() !== "undefined") {
counterWarning.html(counterWarning.html().replace("(N)", anonymousNotesCount));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not how translatable numerals work. The number could also affect other parts of the sentence in various languages ("24 заметки", "25 заметок").

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I understood how pluralization works with i18n, but it is server-side ... If the value of the counter is in the browser (whether in a cookie or in localStorage), it has to be inserted by jquery, so after the translation, and it's too late to manage the different plurals, right ? Is there another option to manage plurals with jquery ? Or is it why you propose the counter to be server-side ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is i18n library in javascript too but it's better to avoid it if possible. You'd have to declare strings in a different section of en.yml, then all of those strings are sent over to the client.

Example of javascript i18n with count:

return I18n.t("javascripts.map.locate." + options.unit + "Popup", { count: options.distance });

@AntonKhorev
Copy link
Collaborator

I'd store the counter in a cookie, set an expiration date for that cookie to something like a week and replace the existing "You are not logged in" alert with this more motivating one with a note counter server-side.

@@ -162,6 +172,9 @@ OSM.NewNote = function (map) {
newNoteMarker.dragging.disable();

createNote(location, text, (feature) => {
if (typeof OSM.user === "undefined") {
localStorage.setItem("anonymousNotesCount", anonymousNotesCount + 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we keep localstorage (see @AntonKhorev comment):
localStorage.setItem can throw an exception.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the nullish coalescence operator ?? you propose below sufficient to handle the case of an exception? Or does it only work for null and undefined?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?? replaces null and undefined values only.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I will add a try ... catch

@@ -152,6 +152,16 @@ OSM.NewNote = function (map) {
.on("input", updateControls)
.focus();

var anonymousNotesCount = Number(localStorage.getItem("anonymousNotesCount"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var anonymousNotesCount = Number(localStorage.getItem("anonymousNotesCount"));
var anonymousNotesCount = Number(localStorage.getItem("anonymousNotesCount") ?? 0);

after #5421 is merged

@gendy54
Copy link

gendy54 commented Jan 5, 2025

If they're valid notes I don't really see the problem? Are these genuine notes or is this some sort of spam attack?

This contributor's notes are potentially problematic and pollute the other notes.
image

@cquest
Copy link

cquest commented Jan 5, 2025

If they're valid notes I don't really see the problem? Are these genuine notes or is this some sort of spam attack?

A large part of them are not valid or useless.

This PR should not be seen as a way to solve a one guy problem, but a global issue with anonymous notes. The lack of communication channel makes a lot of them difficult to deal with, so at least when someone is creating a lot of notes, we should push to create that communication channel, and it also a way to avoid spam.

@etiennejourdier
Copy link
Author

etiennejourdier commented Jan 5, 2025

I'd store the counter in a cookie, set an expiration date

I am not a specialist of cookies VS localStorage, the only advantage of cookies is the possibility to set an expiration date ?

replace the existing "You are not logged in" alert with this more motivating one

good idea!

with a note counter server-side.

I'm not sure I understood this part. I imagined this would require storing an ‘anonymous visitor ID’ in the cookie and creating a table on the server to associate this ID with the notes created by the visitor? but maybe I've misunderstood?

@AntonKhorev
Copy link
Collaborator

I am not a specialist of cookies VS localStorage, the only advantage of cookies is the possibility to set an expiration date ?

The browser sends cookies to the server. It doesn't send localStorage. If the server knows the counter value, it can display another message based on that value, that's what I mean by:

replace the existing "You are not logged in" alert with this more motivating one with a note counter server-side.

@AntonKhorev
Copy link
Collaborator

AntonKhorev commented Jan 6, 2025

I imagined this would require storing an ‘anonymous visitor ID’ in the cookie

This thing already exists as session id in _osm_session cookie. And that's another option. Instead of managing the counter and its expiration date in javascript, you can make a request at some special endpoint after a note is successfully created here


That request will increase the counter stored in session if necessary. After that app/views/notes/new.html.erb or its controller can check the counter value and display the message based on that.

All of this depends on how soon our sessions expire. The example in #5468 (comment) shows a 10-minute burst of activity, so the session doesn't have to live for very long.

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

Successfully merging this pull request may close these issues.

6 participants