Hypertopic / Porphyry

Corpus analyses confrontation
https://hypertopic.org/porphyry
GNU Affero General Public License v3.0
21 stars 165 forks source link

Add a resource to an item (as a file) #142

Closed benel closed 2 years ago

benel commented 6 years ago

Description

What is the valuable outcome that cannot be achieved with current features?

For which stakeholder (people, role, project, domain) is it important?

Which user action should be enabled (or restricted)? For who?

Additional details (solutions you think about, or workarounds you tried)

Deliverables status

Phase 1

Phase 2

Phase 3

Calinou commented 5 years ago

@GhislainLefevre Have you started implementing the front-end for this feature? This would allow me to work more easily on the interaction with the CouchDB API to store attachments.

Calinou commented 5 years ago

Due to the lack of response (and the tight schedule of this project), I started implementing this feature with the front-end on @GhislainLefevre's fork: https://github.com/GhislainLefevre/Porphyry/tree/add-resource-crud

JoyCJay commented 5 years ago

add_ressource add_ressource1

benel commented 4 years ago

It can be emulated by posting a comment with an image attachment (see feature #47). However this is not a real Hypertopic resource.

Damien71 commented 4 years ago

Studying abroad : Having access to files to present additional information could be interesting to allow the student to get a better idea of the UE for example.

benel commented 4 years ago

@Damien71 OK... Any examples of those "additional information" resources? Other question: What would be the benefit compared to #208 in which the resource is remote?

Damien71 commented 4 years ago

@benel For example, a resource could be an example of a test. Compared to ticket #208, this will allow us to give access to resources not available on the internet.

hebertquentin commented 4 years ago

(Archeologie grecque)

Il est toujours utile de pouvoir ajouter une ressource à un item. Des PDF, des photos supplémentaires...

ghost commented 4 years ago

Pour Collectives' stories, nous pensons que le contenu d'un conteur d'expérience sera varié, plus qu'une simple description. C'est pourquoi nous voulons laisser la possibilité à l'utilisateur d'attacher des photos supplémentaires, un court extrait vidéo, etc...

ValentinLouerat commented 4 years ago

Projet : Approche par compétence de la formation Utile pour fournir des ressources liées aux UE/compétences

Gaetanherry commented 4 years ago

Pour Collectives' stories, nous proposons ces scénarios : Fonctionnalité: Add a resource to an item (as a file) #142: Soit l'utilisateur "Alice" connecté Je veux ajouter une ressource à l'article

Scénario: Ajouter un fichier Quand je choisis d'ajouter une ressource Et je sélectionne un fichier "tableau_revenus.xls" Et je valide Alors le fichier "tableau_revenus.xls" a été ajouté à l'article

Scénario: Ajouter une photo(.png, .jpg) Quand je choisis d'ajouter une ressource Et je sélectionne un fichier "plante_jour5.jpg" Et je valide Alors la photo "plante_jour5.jpg" a été ajoutée à l'article

Scénario: Ajouter plusieurs fichiers Quand je choisis d'ajouter une ressource Et je sélectionne un fichier "tuto_jardinage.docx" et un fichier "loi_agriculture.pdf" Et je valide Alors les fichiers "tuto_jardinage.docx" et "loi_agriculture.pdf" ont été ajoutés à l'article

benel commented 4 years ago

@Ocynox je ne sais pas si vous vous souvenez, mais dans le scénario on ne doit pas encore avoir les éléments d'interface (c'est grâce à cela qu'on peut le faire indépendemment des maquettes). Ce qui est important ce sont les données : Quel fichier ? Quelle photo ? Ajouté à quel cas ? Le but des scénarios c'est de raconter une histoire de nous faire rêver...

wikolas21 commented 4 years ago

Pour Collectives' stories Fonctionnalité: Add a resource to an item (as a file) #142: Maquette : -Adobe XD : https://xd.adobe.com/view/79a2b831-0e69-4f75-5fd3-23a7ad3a2441-0f93/?fullscreen&hints=off

benel commented 4 years ago

@wikolas21 Les deux types d'interfaces classiques pour le télédépôt (upload) sont par sélection dans le système de fichier et par glisser-déposer. Je n'ai pas compris lequel vous aviez choisi. Si vous avez des raisons de choisir l'un plutôt que l'autre, pensez à le mentionner.

Sur vos maquettes pensez bien à instancier les données (plutôt que fichier1.png). C'est cela qui rend vos maquettes vivantes... Quel fichier aurait besoin de déposer votre réparateur de bicyclette ? La photo de son atelier ? Une vidéo d'entretien ? Un schéma de bicyclette ? etc. Les choix techniques peuvent en être changés (ex : si c'est une vidéo il faudra peut-être le stocker sur un site tiers, ou autoriser les uploads de grande taille, prévoir plus d'espace de stockage). Soyez le plus concret possible.

Gaetanherry commented 4 years ago

@Ocynox je ne sais pas si vous vous souvenez, mais dans le scénario on ne doit pas encore avoir les éléments d'interface (c'est grâce à cela qu'on peut le faire indépendemment des maquettes). Ce qui est important ce sont les données : Quel fichier ? Quelle photo ? Ajouté à quel cas ? Le but des scénarios c'est de raconter une histoire de nous faire rêver...

J'ai modifié, c'est mieux?

benel commented 4 years ago

@Ocynox Même remarque que pour @wikolas21. Il faut que les parties prenantes puissent se projeter dans cet usage (voir les exemples que je donnais à @wikolas21).

wikolas21 commented 4 years ago

@benel J'ai modifié la maquette afin de la rendre plus réaliste, pourriez vous tester le lien Adobe XD ?

@wikolas21 Les deux types d'interfaces classiques pour le télédépôt (upload) sont par sélection dans le système de fichier et par glisser-déposer. Je n'ai pas compris lequel vous aviez choisi. Si vous avez des raisons de choisir l'un plutôt que l'autre, pensez à le mentionner.

Sur vos maquettes pensez bien à instancier les données (plutôt que fichier1.png). C'est cela qui rend vos maquettes vivantes... Quel fichier aurait besoin de déposer votre réparateur de bicyclette ? La photo de son atelier ? Une vidéo d'entretien ? Un schéma de bicyclette ? etc. Les choix techniques peuvent en être changés (ex : si c'est une vidéo il faudra peut-être le stocker sur un site tiers, ou autoriser les uploads de grande taille, prévoir plus d'espace de stockage). Soyez le plus concret possible.

benel commented 4 years ago

J'ai modifié la maquette afin de la rendre plus réaliste, pourriez vous tester le lien Adobe XD ?

Oui c'est beaucoup mieux.

Gaetanherry commented 4 years ago

@benel Nous sommes en train de réfléchir à la stratégie d'implémentation; si on veut rendre des documents type word pas très gros uploadables et downloadables couchdb suffira?

Gaetanherry commented 4 years ago

Stratégie d'implémentation pour Collectives' stories : -Fichier à modifier : Item.jsx, dans le render ajouter un bouton d'upload dont la fonction ressemblera à _getAttributeCreationForm qui appelle _submitAttribute et _setAttribute. Il faudra alors ajouter des attributs correspondant à la ressource. Fonctionnalités à développer : -Ouvrir une fenêtre d'upload et récupérer le fichier s'il a une taille correcte -Stocker le fichier dans la db -Permettre de télécharger un fichier depuis le lien de l'attribut -Afficher une image si l'extension du fichier depuis le lien de l'attribut est une image

benel commented 4 years ago

@benel Nous sommes en train de réfléchir à la stratégie d'implémentation; si on veut rendre des documents type word pas très gros uploadables et downloadables couchdb suffira?

Vous voulez dire en tant que pièces jointes d'objets CouchDB. Oui, oui, quelques Mo, ça le fait (il faudra juste peut-être évaluer la volumétrie pour l'ensemble de votre projet pour que les administrateurs systèmes n'aient pas de mauvaises surprises).

Par contre les formats de Word, pour des fichiers partagés ce n'est vraiment pas idéal !

benel commented 4 years ago

@Ocynox Je ne sais pas si vous avez trouvé la documentation de la gestion des pièces jointes dans CouchDB, elle est ici :

https://docs.couchdb.org/en/2.3.1/api/document/common.html#attachments

benel commented 4 years ago

Afin de résoudre notre ticket 142, mais également pour mieux pouvoir manier Hypertopic, nous voulons utiliser le PUT afin d'attacher un fichier dans la db. Jusque maintenant je vois que l'on crée un objet hypertopic et on utilise la fonction getView pour obtenir des ressources venant de la db, ou setAttributes pour ajouter des attributs. Y-a-t'il donc une doc des fonctions utilisables de l'objet Hypertopic ou quelque chose que je n'ai pas trouvé qui explique comment avoir l'équivalent pour la procédure PUT, ou comment créer sa propre fonction hypertopic?

@Ocynox Pour faire vos requêtes vers l'API Hypertopic vous pouvez :

A priori, dans votre cas, puisqu'il s'agit d'une nouvelle opération hypertopique, vous ne pourrez pas directement utiliser la troisième solution (par contre, une fois que ça marchera, votre code pourra être intégré à la blibliothèque !).

Peut-être que votre question concerne le fait que c'est post qui est disponible alors que vous avez besoin d'un PUT. Faites le test dans le RESTClient, mais normalement, tout ce que vous pouvez faire dans CouchDB avec l'un peut l'être avec l'autre (moyennant une adaptation de l'URI).

Si la documentation de la bibliothèque n'est pas claire, n'hésitez pas à regarder le code : à part getViewdont l'implémentation est un peu compliquée (mais dont vous n'avez pas du tout besoin), les autres méthodes (get, post, item, setAttributes) sont assez simples...

J'espère que je réponds à votre question... Sinon, dites le moi...

Gaetanherry commented 4 years ago

Afin de résoudre notre ticket 142, mais également pour mieux pouvoir manier Hypertopic, nous voulons utiliser le PUT afin d'attacher un fichier dans la db. Jusque maintenant je vois que l'on crée un objet hypertopic et on utilise la fonction getView pour obtenir des ressources venant de la db, ou setAttributes pour ajouter des attributs. Y-a-t'il donc une doc des fonctions utilisables de l'objet Hypertopic ou quelque chose que je n'ai pas trouvé qui explique comment avoir l'équivalent pour la procédure PUT, ou comment créer sa propre fonction hypertopic?

@Ocynox Pour faire vos requêtes vers l'API Hypertopic vous pouvez :

* soit les faire directement avec la méthode `fetch` de JavaScript (et donc en gérant vous-mêmes toutes les entêtes, etc.),

* soit les faire avec la bibliothèque Hypertopic/lib-node

  * avec un [premier niveau d'abstraction](https://github.com/Hypertopic/lib-node#update-objects-with-generic-methods) : avec des méthodes `get`, `post`, `delete` toutes faites et un système de chaînage de promesses avec le `then` de JavaScript,
  * avec un [second niveau d'abstraction](https://github.com/Hypertopic/lib-node#update-or-create-hypertopic-objects-experimental) qui permet de partir d'un objet d'un certain type (récupéré du serveur ou nouveau si introuvable), de faire des opérations liées au type, avec un chaînage simplifié (chaque opération attendant la fin de l'opération précédente).

A priori, dans votre cas, puisqu'il s'agit d'une nouvelle opération hypertopique, vous ne pourrez pas directement utiliser la troisième solution (par contre, une fois que ça marchera, votre code pourra être intégré à la blibliothèque !).

Peut-être que votre question concerne le fait que c'est post qui est disponible alors que vous avez besoin d'un PUT. Faites le test dans le RESTClient, mais normalement, tout ce que vous pouvez faire dans CouchDB avec l'un peut l'être avec l'autre (moyennant une adaptation de l'URI).

Si la documentation de la bibliothèque n'est pas claire, n'hésitez pas à regarder le code : à part getViewdont l'implémentation est un peu compliquée (mais dont vous n'avez pas du tout besoin), les autres méthodes (get, post, item, setAttributes) sont assez simples...

J'espère que je réponds à votre question... Sinon, dites le moi...

J'ai fait plusieurs tests et j'ai regardé docs et code, mais j'obtiens une Unauthorized error quand j'essaie de faire un new Hypertopic(...).post(), même quand je me réfère à l'exemple avec alice/whiterabbit. Qu'est ce qui ne va pas? N'a t'on pas les droits de post sur cette db?

benel commented 4 years ago

J'ai fait plusieurs tests et j'ai regardé docs et code, mais j'obtiens une Unauthorized error quand j'essaie de faire un new Hypertopic(...).post(), même quand je me réfère à l'exemple avec alice/whiterabbit. Qu'est ce qui ne va pas? N'a t'on pas les droits de post sur cette db?

Vous êtes bien sur le serveur de test (argos2.test.hypertopic.org) ?

benel commented 4 years ago

Il y a possiblement deux modes d'authentification :

On a été contraints de désactiver la première au semestre d'automne. Donc il faut le faire avec la seconde méthode.

Il faut donc créer une session tout d'abord :

Capture d’écran 2020-06-02 à 12 37 39

Vous pouvez ensuite faire une requête de modification :

Capture d’écran 2020-06-02 à 12 38 29

Si vous êtes en LO10 (ou si quelqu'un de votre équipe y est), c'est exactement ce que l'on a fait la dernière fois pour l'application "CuiCui".

Gaetanherry commented 4 years ago

D'accord, je pense qu'on n'est simplement pas sur argos test c'est pour ça qu'on reçoit une erreur quand on essaie de post

EDIT : dans config.yml il y a pourtant bien

user: vitraux services

yuchen0527 commented 4 years ago

image Oui...J'ai aussi reçu cette erreur

benel commented 4 years ago

image

@yuchen0527 Je ne comprends pas ce que vous essayez de faire. L'URI /_utils/argos ne correspond à rien que je connaisse dans CouchDB.

Gaetanherry commented 4 years ago

return new Hypertopic((await conf).services).auth('alice', 'whiterabbit') .post({_id:'007', item_name:'Bond', item_corpus:'TEST'}) .then((x) => console.log(JSON.stringify(x, null, 2))) .catch((x) => console.error(x.message));

Quand je fais ceci, avec Hypertopic et conf importés, c'est là que j'obtiens une erreur unauthorized. Sur RESTClient cela a l'air de marcher pourtant

benel commented 4 years ago

return new Hypertopic((await conf).services).auth('alice', 'whiterabbit') .post({_id:'007', item_name:'Bond', item_corpus:'TEST'}) .then((x) => console.log(JSON.stringify(x, null, 2))) .catch((x) => console.error(x.message));

Supprimez la partie auth. C'est de l'authentification HTTP Basic, ça ne marchera pas. Vous devez utiliser une authentification par session. Êtes-vous dans Porphyry ou dans un code JavaScript à part ?

Gaetanherry commented 4 years ago

return new Hypertopic((await conf).services).auth('alice', 'whiterabbit') .post({_id:'007', item_name:'Bond', item_corpus:'TEST'}) .then((x) => console.log(JSON.stringify(x, null, 2))) .catch((x) => console.error(x.message));

Supprimez la partie auth. C'est de l'authentification HTTP Basic, ça ne marchera pas. Vous devez utiliser une authentification par session. Êtes-vous dans Porphyry ou dans un code JavaScript à part ?

Je suis dans Porphyry dans Item.jsx

benel commented 4 years ago

Je suis dans Porphyry dans Item.jsx

Dans Porphyry, une session peut être créée dans l'interface.

Gaetanherry commented 4 years ago

D'accord merci je comprends mieux ! Ca marche enfin. Nous avons une autre erreur, quand on veut accéder à un item, il semble que notre programme aie modifié la db et maintenant certains items ne sont plus bons. Est-il possible de reset la db de test avec la version d'origine? Merci.

benel commented 4 years ago

Nous avons une autre erreur, quand on veut accéder à un item, il semble que notre programme aie modifié la db et maintenant certains items ne sont plus bons. Est-il possible de reset la db de test avec la version d'origine?

Je n'ai pas de manière simple et immédiate de le faire. Pouvez-vous m'indiquer précisément où vous voyez un problème dans les données ?

Yann-Qiu commented 4 years ago

TypeError: props.value.startsWith is not a function, c'est sur que il y a des choses mauvaise dans le database...

yuchen0527 commented 4 years ago

image

benel commented 4 years ago

TypeError: props.value.startsWith is not a function, c'est sur que il y a des choses mauvaise dans le database...

Ma question portait plutôt sur l'item que vous avez modifié ? Est-ce que vous vous souvenez de son nom ?

Yann-Qiu commented 4 years ago

PSM 002, SJ 001 SM 001 n SM 008 g, snz 006

Gaetanherry commented 4 years ago

On a modifié plusieurs items, en ajoutant des attributes qui parfois n'avaient pas de contenu ou de nom, du coup la méthode startsWith ne marche plus

benel commented 4 years ago

Ah j'en ai trouvé un :

  "ressource": [
    {}
  ]

C'est parce que vous avez mis un objet dans ce qui était censé être une chaîne de caractère. Je vais essayer de les supprimer un par un.

À l'avenir :

benel commented 4 years ago

Si vous avez besoin d'items préexistants, utilisez un des très nombreux SMV 129 (ils ont été créés par des tests et seront supprimés à la première occasion).

benel commented 4 years ago

Est-ce que vous avez besoin d'aide pour comprendre la doc des attachments de CouchDB ?

benel commented 4 years ago

Notez bien que la clef _attachments fait partie de la spécification. Vous ne pouvez pas la remplacer par "key" ou "resource".

Gaetanherry commented 4 years ago

Ce que je n'avais pas compris avec la doc des attachments, c'est où est-ce que le fichier est transmis en lui-même, car du coup nous on fait : .setAttributes({ file: file.name, _attachments: {follows:"true", content_type : file.type, length: file.size, value: file.name} }) mais je ne comprends pas comment à partir de ça le fichier file en lui même peut être stocké dans la db et récupéré

benel commented 4 years ago

Voilà a priori j'ai nettoyé tous les items "vitraux" 'utilisés dans les tests).

Je vous recommande très fortement de faire d'abord des tests de l'API _attachments avec le RESTClient pour vérifier que vous avez bien compris comment ça marche.

benel commented 4 years ago

J'ai l'impression que vous ne regardez pas les bonnes requêtes dans la doc...

benel commented 4 years ago

Apparemment, on peut l'envoyer :

{
  "_id":"multiple_attachments",
  "_attachments":
  {
    "foo.txt":
    {
      "content_type":"text\/plain",
      "data": "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
    },

   "bar.txt":
    {
      "content_type":"text\/plain",
      "data": "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
    }
  }
}
--abc123
Content-Type: application/json

{
    "body": "This is a body.",
    "_attachments": {
        "foo.txt": {
            "follows": true,
            "content_type": "text/plain",
            "length": 21
        },
        "bar.txt": {
            "follows": true,
            "content_type": "text/plain",
            "length": 20
        }
    }
}

--abc123

this is 21 chars long
--abc123

this is 20 chars lon
--abc123--
Gaetanherry commented 4 years ago

Merci. faire nos tests sur RESTClient a un rapport avec "attention à faire vos tests sur vos propres objets et non sur ceux qui sont nécessaires aux tests." que vous disiez plus tot? Car j'ai mal compris cette phrase. Au passage, je m'excuse avec mon équipe de ne pas avoir des compétences suffisantes pour s'en sortir tout seuls avec ce genre de problèmes

benel commented 4 years ago

Au passage, je m'excuse avec mon équipe de ne pas avoir des compétences suffisantes pour s'en sortir tout seuls avec ce genre de problèmes

Pas de problème pour ça. La compréhension d'une API donnée est le genre de choses que l'on ne peut pas savoir faire avant de l'avoir fait.

La fonctionnalité que vous avez choisie est un peu plus technique que les autres et nécessite de passer plus de temps à réfléchir à votre stratégie d'implémentation. Je suis là pour vous y aider.