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
Add support of TODO tags #756
Conversation
About genericity, it would be great to also allow tags on all document types. From API point of view, tag system would be functionally agnostic, it's simply a unique Then, on UI side, the way it use tag name describe the functionality. I see some use cases for this genericity :
IMO, no :
|
This sounds like a good idea, and seems easier to maintain while remaining open for further use cases.
I think a TODO list is user related data, it should be only visible to logged-in users (for example if the list is a section of the user profile). It would be nice though to leave the user the choice to make it public or private or visible to all other members (or maybe just to selected other users, tagging users as friends, as friends for climbing, skiing etc., sorry this is getting off topic) |
Let's ask this point on the forum :) https://forum.camptocamp.org/t/tick-list-privee-ou-publique/253028 |
Thanks for the feedbacks! I would prefer this topic only discusses the technical aspects of the suggested feature. Using the forum would be more appropriate for debating possible evolutions and ethical issues. Tags were a key feature that we wanted to add to v6 but had to dismiss because of lack of time and budget. We planned for instance predefined tags (eg. "todo"), either personal or global (for instance for routes with restricted access, etc.). Users would also be able to create their own personal/private tags as in Gmail for instance. There are probably more info about this in the "v6" forums or specs. On the other hand I would like to keep this PR quite simple, at least for the initial version of the tool. First because I don't have much time for it and second because it could grow too big, increasing chances that the feature would not be delivered. In addition I think that the key feature (often asked for in the forum) is actually to add routes to one's todo list, other uses are more marginal I think. I have decided to use a generic name "tag" instead of "todo", in order to easily be able to extend a bit the tool. For instance.
I have the feeling that it is important that by default todo lists are private (personally I won't use the feature if any one can see my projects if I have not chosen to make them public). Making some todo items public could be done by adding |
Hi @asaunier , The question on the forum was only about what wants the users (and not guessing it). The answer is clear :
In consequence, privateness is a nice to have, just driven by the tech difficulties / our availabilities => If you want to implement it, feel free :) |
c2corg_api/views/route_tag.py
Outdated
|
||
|
||
@resource(path='/routes/tag', cors_policy=cors_policy) | ||
class RouteTagRest(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.
Suggestion : IMO, having a unique REST service, leveraging on REST model would be better :
GET /routes/tag/{route_id}
=> returns{"todo": True/False}
PUT /routes/tag/{route_id}
=> , empty body as now, set the tag on (use PUT, not POST, as it's idempotent)DELETE /routes/tag/{route_id}
=> , empty body as now, set the tag off
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.
@cbeauchesne Your suggestion makes sense but
- this code is inspired from https://github.com/c2corg/v6_api/blob/master/c2corg_api/views/user_follow.py which itself uses the same approach than other services
- I don't remember exactly but I think it is related to the way Cornice works
As a result I prefer to stick to this approach in order to keep code consistency and to avoid spending too much time using another approach whereas the existing one has proved it worked.
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.
Anotheer suggestion : tag exists on article, and are linked to a single article.
As this new object is linked to a single Route/User, rename tag to UserTag :
RouteUserTag
for modelsroutes_users_tags
for tableRouteUserTagRest
for view/routes/user_tag
for URI
I have made a few progress, adding some tests but am currently stuck because of a "405 Method Not Allowed" error when posting to the https://cornice.readthedocs.io/en/latest/exhaustive_list.html says that
|
@asaunier : I will start working on the update of the SERAC database. I'll have to create a new alembic version (also based on master HEAD) Since the project has no alembic branches, I suggest we just have two individual alembic files and do the conflict resolution just before merging the respective branches. OK for you ? |
@momomaniac No problem: I will upgrade the alembic source version if your PR is merged before mine (which is quite likely :P) |
Hey guys, what is the current status? Have you managed to overcome the 405 and move on? Not sure if I can help with this one , but maybe together we can push it forward :) What I think may be a problem here is that /routes/tag actually hits /routes/{id} of route.py, which does not define post itself -> hence 405 error to a POST request. The way around would be to change the route from /routes/tag to something like /routetags or just /tags. |
Hi @mikocot
I have made no progress on this task since my last report.
That's a good hint! I have used the users view as a reference to write the new tag view. Perhaps I have missed something.
That's worth trying. I guess |
Note about how to run the tests for this part:
|
+1 Actually, there are a lot of usages with the possibility of linking documents to users profiles. The way to make things generic would be :
Thus, as now, we actually do not need such a genericity, so first a first shoot, a simplier model would do the job. But if this model could be in that direction, it would be great :)
|
6317593
to
bf58d9f
Compare
Hi all Thanks to the suggestion of @mikocot I have succeeded in making the tests pass: I have renamed the routes to I have finally decided to generalize a little the tool in order to tag whatever document type (not only routes) even though I will only deal with routes in this PR. What is already possible now:
What I would like to do still:
As for now there is no restriction on the kind of document you may tag (could be a waypoint or an article). Could it be a problem? Edit: Travis fails (OK in my local instance though) but the failed test seems no related (is it?). |
No, it's not related, outing1 and outing4 has the same elevation, that leads to a random result for sorting feature, and t make the test randomly fails. Can you put 1499 instead of 1500 here : https://github.com/c2corg/v6_api/blob/master/c2corg_api/tests/views/test_outing.py#L1174 ? ping @momomaniac ;)
IMO, no, we will restrict the usage with the UI. And thank's a lot for this move, it will offer a lot of possibilities (even if i do not have yet a good vision what will be really useful 😄 ) Is the PR ready for review ? |
@cbeauchesne Thanks for the hint 👍 The PR is not really ready for review, I have a "codacy" issue to fix and I would like to add the possibility to filter routes on the "todo" tags. I'll work on this tonight I think. |
You're welcome! No, I'll wait for the final version, mid-work review are often a waste of time for both reviewer and worker :) |
ff94d33
to
a84c60e
Compare
Sorry, I missed the "ready for review", I'll make a review today or tomorrow. |
Hi @cbeauchesne |
```sh | ||
docker-compose exec api make -f config/docker-dev run-background-jobs | ||
docker-compose exec api make -f config/docker-dev run-syncer | ||
``` |
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.
Commands ported from https://github.com/c2corg/v6_api/wiki/Development-environment-on-Linux#run-the-application
Not 100% sure though, as I need to run them (or only run-syncer
?) to have the tags actually taken into account in ES, but on the other hand after doing so the simple search no longer works in my instance (no more results)!?
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.
First answer : run-syncer
only is not enough
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.
Side note, for this point, we need to put them in the wiki: the README must be the simplest possible help to run the dev env.
Also tested manually in the UI with PR c2corg/c2c_ui#1147 I have realized that tags are correctly transfered when merging 2 documents but there is still a problem when merging 2 users:
I wonder if the ES notifying at https://github.com/c2corg/v6_api/blob/routes-todo-list/c2corg_api/scripts/users/merge.py#L131 actually works (including in the master branch)... After restarting ES sync by hand, restarting the following command
the target user TODO list is indeed updated. FIXME: not transfered tags (because already tagged by the target user) are not removed from the ES index (thus still appear in the source user target list) |
Yep, it would far far better:
I'll have a look on this before starting the review. |
I would suggest to support a list of tags: |
Well, fail, even before starting ^^ I didn't see a test on class TestDocumentGetTaggedRoutes(BaseDocumentTagTest):
def setUp(self): # noqa
super().setUp()
self._prefix = '/routes'
def test_get_routes(self):
request_body = {
'document_id': self.route1.document_id
}
self.post_json_with_contributor(
'/tags/add', request_body, status=200, username='contributor2')
self.session.flush()
headers = self.add_authorization_header(username='contributor2')
response = self.app.get(
'{}?u={}'.format(self._prefix, self.contributor2.id),
status=200, headers=headers)
body = response.json
self.assertEqual(body['total'], 1) The body response is {
"total": 0,
"documents": []
} @asaunier , by chance, do you see something obvious I missed ? |
@cbeauchesne Nothing obvious. Your code seems to make sense. Perhaps the test doesn't work because ES does not really work in test mode? I don't know much about that. |
Hi guys I suggest that we stick to the current approach of The approach of |
Sorry, did not have a lot of time, but I really want to try. If I did not succeed in two weeks, we merge. Ok for you ? |
i'll have a look, since I am currently in hospital.
However, the internet connection is soso, and I don't have all the
dev/build tools available right now.
But I should be set up by next week to go into the detail of the PR.
And then maybe implement the UI part.
Thanks for the great work, I am so eager to try out the todo tags.
…On Fri, Jun 5, 2020 at 10:17 AM Charles de Beauchesne < ***@***.***> wrote:
Sorry, did not have a lot of time, but I really want to try. If I did not
succeed in two weeks, we merge. Ok for you ?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#756 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ANY5RCUJBUWCM5FBQVPDH7LRVCSZRANCNFSM4JNS3POQ>
.
|
'documents_tags', | ||
sa.Column('user_id', sa.Integer(), nullable=False), | ||
sa.Column('document_id', sa.Integer(), nullable=False), | ||
sa.Column('document_type', sa.String(1), nullable=False), |
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 purpose of the document_type ? It seems to me redundant with the information in guidebook.documents
the document_type does not seem to be used in this PR ? can it be removed ?
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 document type is used by the ES syncer to build its index:
- get the list of documents to update in the index:
v6_api/c2corg_api/scripts/es/sync.py
Lines 35 to 40 in b1ec975
changed_documents = \ get_changed_documents(session, last_update) + \ get_changed_users(session, last_update) + \ get_changed_documents_for_associations(session, last_update) + \ get_deleted_locale_documents(session, last_update) + \ get_tagged_documents(session, last_update) - type of the changed documents is then used at
v6_api/c2corg_api/scripts/es/sync.py
Lines 275 to 279 in b1ec975
def sync_documents(session, changed_documents, batch_size): client = elasticsearch_config['client'] batch = ElasticBatch(client, batch_size) with batch: docs_per_type = get_documents_per_type(changed_documents)
Except this the document type is as for now indeed not that relevant because all tagged documents are routes ("todo" tag). But the goal of this PR is to be extended for other kind of documents with other kind of tags.
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, thanks for your explanation.
still the data is redundant, couldn't it be handled with an sql view which queries the document type from guidebook.documents via the foreign key ? I don't feel comfortable with adding the same data once more into a second table and risk inconsistent data.
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 concern about data inconsistency makes sense indeed.
We could use views or other systems to get the type directly from the document itself but wouldn't it make things even more complicated? Perhaps we could make sure the type is correctly retrieved when creating the tags.
The current PR makes sure the document about to be tagged is actually a route, see https://github.com/c2corg/v6_api/blob/routes-todo-list/c2corg_api/views/document_tag.py#L32-L42
Please also note the document tags system is significantly inspired from the association system (dedicated table for the the actual associations + a table for the logs, as for the tags system). Associations do have document type fields duplicated in the association tables:
https://github.com/c2corg/v6_api/blob/master/c2corg_api/models/association.py#L45-L52
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 why. Yes associations also have the document type. Actually I started working on #804 and already forgot about the document types and potential inconsistency.
I checked in the db, it is really easy to retrieve the doc type directly from the table guidebook.documents (without further joins,...) so it's probably not much more complicated to retrieve the document type on the fly. Performance-wise, the foreign key is indexed, so it should be 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.
ok, I reindexed ES locally, and now also the routes?u=
entrypoint is working (I tested it manually, but I'll look also into the test written by @cbeauchesne )
Well, I've not a single second of free time, and it won't be better for one month. Sorry @asaunier, I really wanted to have some times to look at this, but it won't be reasonable to wait for so long. I release my lock on this :) @momomaniac I give you the hand! |
b1ec975
to
954c76f
Compare
a9b427e
to
5275668
Compare
In short: adds the possibility to tag routes as "TODO". The UI part would be a "TODO" button in route pages, a bit like the "Follow" button in user profiles.
I have tried to be a bit generic, in order to support other kind of tags later (eg. "done/tick", etc.).
TODO:
UI PR at c2corg/c2c_ui#1147