Browse Source

personnal notes on materails on modalCard is ok

bach 3 years ago
parent
commit
1f9b5a0053
25 changed files with 545 additions and 7 deletions
  1. 22 0
      config/sync/core.base_field_override.node.note.promote.yml
  2. 97 0
      config/sync/core.entity_form_display.node.note.default.yml
  3. 51 0
      config/sync/core.entity_view_display.node.note.default.yml
  4. 39 0
      config/sync/core.entity_view_display.node.note.teaser.yml
  5. 19 0
      config/sync/field.field.node.note.field_contenu.yml
  6. 28 0
      config/sync/field.field.node.note.field_target.yml
  7. 23 0
      config/sync/field.storage.node.field_contenu.yml
  8. 23 0
      config/sync/field.storage.node.field_target.yml
  9. 11 0
      config/sync/language.content_settings.node.note.yml
  10. 17 0
      config/sync/node.type.note.yml
  11. 3 2
      config/sync/rest.resource.entity.node.yml
  12. 2 0
      config/sync/user.role.adherent.yml
  13. 2 0
      config/sync/user.role.admin.yml
  14. 2 0
      config/sync/user.role.admin_showroom.yml
  15. 2 0
      config/sync/user.role.alpha_testeur.yml
  16. 2 0
      config/sync/user.role.translator.yml
  17. 3 3
      package-lock.json
  18. 1 0
      package.json
  19. 7 0
      web/modules/custom/materio_graphql/graphql/materio_extension.base.graphqls
  20. 54 0
      web/modules/custom/materio_graphql/src/Plugin/GraphQL/SchemaExtension/MaterioSchemaExtension.php
  21. 17 1
      web/themes/custom/materiotheme/assets/dist/main.css
  22. 20 0
      web/themes/custom/materiotheme/assets/dist/main.js
  23. 23 0
      web/themes/custom/materiotheme/assets/styles/main.scss
  24. 5 0
      web/themes/custom/materiotheme/vuejs/api/gql/materiaumodal.fragment.gql
  25. 72 1
      web/themes/custom/materiotheme/vuejs/components/Content/ModalCard.vue

+ 22 - 0
config/sync/core.base_field_override.node.note.promote.yml

@@ -0,0 +1,22 @@
+uuid: e28b50f6-2871-47d2-af11-db34c50092a3
+langcode: fr
+status: true
+dependencies:
+  config:
+    - node.type.note
+id: node.note.promote
+field_name: promote
+entity_type: node
+bundle: note
+label: 'Promu en page d''accueil'
+description: ''
+required: false
+translatable: true
+default_value:
+  -
+    value: 0
+default_value_callback: ''
+settings:
+  on_label: Activé
+  off_label: Désactivé
+field_type: boolean

+ 97 - 0
config/sync/core.entity_form_display.node.note.default.yml

@@ -0,0 +1,97 @@
+uuid: d8aa1b2a-cefe-4787-906a-66d1b4942b81
+langcode: fr
+status: true
+dependencies:
+  config:
+    - field.field.node.note.field_contenu
+    - field.field.node.note.field_target
+    - node.type.note
+  module:
+    - path
+id: node.note.default
+targetEntityType: node
+bundle: note
+mode: default
+content:
+  created:
+    type: datetime_timestamp
+    weight: 10
+    region: content
+    settings: {  }
+    third_party_settings: {  }
+  field_contenu:
+    weight: 121
+    settings:
+      rows: 5
+      placeholder: ''
+    third_party_settings: {  }
+    type: string_textarea
+    region: content
+  field_target:
+    weight: 122
+    settings:
+      match_operator: CONTAINS
+      match_limit: 10
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+    type: entity_reference_autocomplete
+    region: content
+  langcode:
+    type: language_select
+    weight: 2
+    region: content
+    settings:
+      include_locked: true
+    third_party_settings: {  }
+  path:
+    type: path
+    weight: 30
+    region: content
+    settings: {  }
+    third_party_settings: {  }
+  promote:
+    type: boolean_checkbox
+    settings:
+      display_label: true
+    weight: 15
+    region: content
+    third_party_settings: {  }
+  status:
+    type: boolean_checkbox
+    settings:
+      display_label: true
+    weight: 120
+    region: content
+    third_party_settings: {  }
+  sticky:
+    type: boolean_checkbox
+    settings:
+      display_label: true
+    weight: 16
+    region: content
+    third_party_settings: {  }
+  title:
+    type: string_textfield
+    weight: -5
+    region: content
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+  uid:
+    type: entity_reference_autocomplete
+    weight: 5
+    settings:
+      match_operator: CONTAINS
+      size: 60
+      placeholder: ''
+      match_limit: 10
+    region: content
+    third_party_settings: {  }
+  url_redirects:
+    weight: 50
+    settings: {  }
+    third_party_settings: {  }
+    region: content
+hidden: {  }

+ 51 - 0
config/sync/core.entity_view_display.node.note.default.yml

@@ -0,0 +1,51 @@
+uuid: 8fc0b216-f68b-405d-b408-82375647473b
+langcode: fr
+status: true
+dependencies:
+  config:
+    - field.field.node.note.field_contenu
+    - field.field.node.note.field_target
+    - node.type.note
+  module:
+    - user
+id: node.note.default
+targetEntityType: node
+bundle: note
+mode: default
+content:
+  field_contenu:
+    weight: 101
+    label: above
+    settings: {  }
+    third_party_settings: {  }
+    type: basic_string
+    region: content
+  field_target:
+    weight: 102
+    label: above
+    settings:
+      link: true
+    third_party_settings: {  }
+    type: entity_reference_label
+    region: content
+  flag_flag_list_template_1:
+    weight: 10
+    settings: {  }
+    third_party_settings: {  }
+    region: content
+  links:
+    weight: 100
+    settings: {  }
+    third_party_settings: {  }
+    region: content
+  title:
+    label: hidden
+    type: string
+    weight: -5
+    region: content
+    settings:
+      link_to_entity: false
+    third_party_settings: {  }
+hidden:
+  langcode: true
+  search_api_excerpt: true

+ 39 - 0
config/sync/core.entity_view_display.node.note.teaser.yml

@@ -0,0 +1,39 @@
+uuid: 40a73cb6-fc72-4cd6-89fe-80f373a3bec6
+langcode: fr
+status: true
+dependencies:
+  config:
+    - core.entity_view_mode.node.teaser
+    - field.field.node.note.field_contenu
+    - field.field.node.note.field_target
+    - node.type.note
+  module:
+    - user
+id: node.note.teaser
+targetEntityType: node
+bundle: note
+mode: teaser
+content:
+  flag_flag_list_template_1:
+    weight: 10
+    settings: {  }
+    third_party_settings: {  }
+    region: content
+  links:
+    weight: 100
+    settings: {  }
+    third_party_settings: {  }
+    region: content
+  title:
+    label: hidden
+    type: string
+    weight: -5
+    region: content
+    settings:
+      link_to_entity: false
+    third_party_settings: {  }
+hidden:
+  field_contenu: true
+  field_target: true
+  langcode: true
+  search_api_excerpt: true

+ 19 - 0
config/sync/field.field.node.note.field_contenu.yml

@@ -0,0 +1,19 @@
+uuid: 73730111-28a7-41c5-a371-62830262c700
+langcode: fr
+status: true
+dependencies:
+  config:
+    - field.storage.node.field_contenu
+    - node.type.note
+id: node.note.field_contenu
+field_name: field_contenu
+entity_type: node
+bundle: note
+label: contenu
+description: ''
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings: {  }
+field_type: string_long

+ 28 - 0
config/sync/field.field.node.note.field_target.yml

@@ -0,0 +1,28 @@
+uuid: 46868b76-ac8f-4498-989a-912388005be1
+langcode: fr
+status: true
+dependencies:
+  config:
+    - field.storage.node.field_target
+    - node.type.materiau
+    - node.type.note
+id: node.note.field_target
+field_name: field_target
+entity_type: node
+bundle: note
+label: target
+description: ''
+required: true
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings:
+  handler: 'default:node'
+  handler_settings:
+    target_bundles:
+      materiau: materiau
+    sort:
+      field: _none
+    auto_create: false
+    auto_create_bundle: ''
+field_type: entity_reference

+ 23 - 0
config/sync/field.storage.node.field_contenu.yml

@@ -0,0 +1,23 @@
+uuid: 9aad2aad-1346-48ef-b6d1-84c58d7cd8ad
+langcode: fr
+status: true
+dependencies:
+  module:
+    - field_permissions
+    - node
+third_party_settings:
+  field_permissions:
+    permission_type: private
+id: node.field_contenu
+field_name: field_contenu
+entity_type: node
+type: string_long
+settings:
+  case_sensitive: false
+module: core
+locked: false
+cardinality: 1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false

+ 23 - 0
config/sync/field.storage.node.field_target.yml

@@ -0,0 +1,23 @@
+uuid: 039ae1b2-6588-4ab6-b890-28a055c1fe2a
+langcode: fr
+status: true
+dependencies:
+  module:
+    - field_permissions
+    - node
+third_party_settings:
+  field_permissions:
+    permission_type: private
+id: node.field_target
+field_name: field_target
+entity_type: node
+type: entity_reference
+settings:
+  target_type: node
+module: core
+locked: false
+cardinality: 1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false

+ 11 - 0
config/sync/language.content_settings.node.note.yml

@@ -0,0 +1,11 @@
+uuid: fa779e69-d676-4418-a8b7-09306dd2680d
+langcode: fr
+status: true
+dependencies:
+  config:
+    - node.type.note
+id: node.note
+target_entity_type_id: node
+target_bundle: note
+default_langcode: zxx
+language_alterable: false

+ 17 - 0
config/sync/node.type.note.yml

@@ -0,0 +1,17 @@
+uuid: e2cbfd49-99af-4302-90ca-4ca8f7900efd
+langcode: fr
+status: true
+dependencies:
+  module:
+    - menu_ui
+third_party_settings:
+  menu_ui:
+    available_menus: {  }
+    parent: ''
+name: Note
+type: note
+description: ''
+help: ''
+new_revision: false
+preview_mode: 1
+display_submitted: false

+ 3 - 2
config/sync/rest.resource.entity.node.yml

@@ -1,6 +1,6 @@
 uuid: 268f10a8-04a2-4b09-a229-35fd0bf2061e
 langcode: en
-status: false
+status: true
 dependencies:
   module:
     - node
@@ -11,7 +11,8 @@ plugin_id: 'entity:node'
 granularity: resource
 configuration:
   methods:
-    - GET
+    - POST
+    - PATCH
   formats:
     - json
   authentication:

+ 2 - 0
config/sync/user.role.adherent.yml

@@ -10,8 +10,10 @@ permissions:
   - 'access materio search'
   - 'add flag lists'
   - 'create member profile'
+  - 'create note content'
   - 'create workflow workflow_transition'
   - 'edit own flag lists'
+  - 'edit own note content'
   - 'flag dossier other items'
   - 'unflag dossier other items'
   - 'update own commerce_license'

+ 2 - 0
config/sync/user.role.admin.yml

@@ -45,6 +45,7 @@ permissions:
   - 'create materiau content'
   - 'create materio_order_type commerce_order'
   - 'create migration workflow_transition'
+  - 'create note content'
   - 'create page content'
   - 'create simplenews_issue content'
   - 'create terms in assisted_research'
@@ -85,6 +86,7 @@ permissions:
   - 'edit field_showroom'
   - 'edit own enregistrement content'
   - 'edit own flag lists'
+  - 'edit own note content'
   - 'edit terms in assisted_research'
   - 'edit terms in collectionneurs'
   - 'edit terms in company'

+ 2 - 0
config/sync/user.role.admin_showroom.yml

@@ -9,7 +9,9 @@ is_admin: null
 permissions:
   - 'access materio search'
   - 'add flag lists'
+  - 'create note content'
   - 'edit own flag lists'
+  - 'edit own note content'
   - 'flag dossier other items'
   - 'unflag dossier other items'
   - 'use jsonrpc services'

+ 2 - 0
config/sync/user.role.alpha_testeur.yml

@@ -10,7 +10,9 @@ permissions:
   - 'access materio search'
   - 'add flag lists'
   - 'create member profile'
+  - 'create note content'
   - 'edit own flag lists'
+  - 'edit own note content'
   - 'flag dossier other items'
   - 'unflag dossier other items'
   - 'update own member profile'

+ 2 - 0
config/sync/user.role.translator.yml

@@ -9,7 +9,9 @@ is_admin: null
 permissions:
   - 'access materio search'
   - 'add flag lists'
+  - 'create note content'
   - 'edit own flag lists'
+  - 'edit own note content'
   - 'flag dossier other items'
   - 'unflag dossier other items'
   - 'view own flag lists'

+ 3 - 3
package-lock.json

@@ -8390,9 +8390,9 @@
       }
     },
     "lodash": {
-      "version": "4.17.11",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
-      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
+      "version": "4.17.20",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
       "dev": true
     },
     "lodash._reinterpolate": {

+ 1 - 0
package.json

@@ -56,6 +56,7 @@
     "eslint-webpack-plugin": "^2.4.0",
     "graphql": "^15.4.0",
     "graphql-tag": "^2.11.0",
+    "lodash": "^4.17.20",
     "mini-css-extract-plugin": "^1.3.1",
     "node-sass": "^5.0.0",
     "querystring-es3": "^0.2.1",

+ 7 - 0
web/modules/custom/materio_graphql/graphql/materio_extension.base.graphqls

@@ -27,6 +27,13 @@ type Materiau implements NodeInterface {
   # index: Int
   reference: String
   samples: [Sample]
+  note: Note
+}
+
+type Note implements NodeInterface {
+  id: Int!
+  contenu: String
+  target: Int
 }
 
 type Article implements NodeInterface {

+ 54 - 0
web/modules/custom/materio_graphql/src/Plugin/GraphQL/SchemaExtension/MaterioSchemaExtension.php

@@ -31,6 +31,8 @@ class MaterioSchemaExtension extends SdlSchemaExtensionPluginBase {
 
     $this->addMateriau($registry, $builder);
 
+    $this->addNote($registry, $builder);
+
     $this->addSearchResult($registry, $builder);
 
     $this->addSample($registry, $builder);
@@ -271,6 +273,58 @@ class MaterioSchemaExtension extends SdlSchemaExtensionPluginBase {
         ->map('value', $builder->fromParent())
         ->map('path', $builder->fromValue('field_samples'))
       );
+
+    $registry->addFieldResolver('Materiau', 'note',
+      $builder->compose(
+        $builder->callback(function($parent, $args){
+          // get the current user id
+          $user = \Drupal::currentUser()->id();
+          // get the current material id
+          $target = $parent->id();
+          // query the note for these user AND material (if any)
+          // if null, UI will create it with rest api
+          $entity_storage = \Drupal::entityTypeManager()->getStorage('node');
+          $query = $entity_storage->getQuery()
+            ->condition('type', 'note')
+            ->condition('uid', $user)
+            ->condition('field_target', $target)
+            ->accessCheck(TRUE);
+          $results = $query->execute();
+          // $test="test";
+          return array_shift($results);
+        }),
+        $builder->produce('entity_load')
+          ->map('type', $builder->fromValue('node'))
+          ->map('bundle', $builder->fromValue('note'))
+          ->map('id', $builder->fromParent())
+      )
+    );
+  }
+
+  //  _  _     _
+  // | \| |___| |_ ___
+  // | .` / _ \  _/ -_)
+  // |_|\_\___/\__\___|
+  protected function addNote(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
+
+    $registry->addFieldResolver('Note', 'id',
+      $builder->produce('entity_id')
+        ->map('entity', $builder->fromParent())
+      );
+
+    $registry->addFieldResolver('Note', 'contenu',
+        $builder->produce('property_path')
+        ->map('type', $builder->fromValue('entity:node'))
+        ->map('value', $builder->fromParent())
+        ->map('path', $builder->fromValue('field_contenu.value'))
+    );
+
+    $registry->addFieldResolver('Note', 'target',
+      $builder->produce('property_path')
+        ->map('type', $builder->fromValue('entity:node'))
+        ->map('value', $builder->fromParent())
+        ->map('path', $builder->fromValue('field_target.target_id'))
+      );
   }
 
   //  ___                  _    ___             _ _

+ 17 - 1
web/themes/custom/materiotheme/assets/dist/main.css

@@ -1943,7 +1943,8 @@ article.card {
         max-height: 0;
         max-width: 0;
         overflow: hidden;
-        transition: all 0.2s ease-in-out; }
+        transition: all 0.2s ease-in-out;
+        transition-delay: 0.1s; }
       article.card nav.tools > *:hover .tool-content {
         transition: all 0.3s ease-in-out;
         opacity: 1;
@@ -2048,6 +2049,21 @@ article.card {
         padding-right: 0.5em; }
         article.card.modal-card section.col-right section.tool.samples div.tool-content ul li span.showroom {
           font-weight: 500; }
+    article.card.modal-card section.col-right section.tool.note:hover div.tool-content {
+      max-height: 370px; }
+    article.card.modal-card section.col-right section.tool.note div.tool-content textarea,
+    article.card.modal-card section.col-right section.tool.note div.tool-content textarea:focus,
+    article.card.modal-card section.col-right section.tool.note div.tool-content textarea:focus-visible,
+    article.card.modal-card section.col-right section.tool.note div.tool-content textarea:active {
+      resize: none;
+      width: 99%;
+      height: 350px;
+      margin: 0;
+      padding: 0.3em;
+      border: 1px solid #ccc;
+      border-radius: 3px;
+      outline: none;
+      box-sizing: border-box; }
     article.card.modal-card section.col-right section.industriels {
       display: flex;
       flex-flow: row; }

File diff suppressed because it is too large
+ 20 - 0
web/themes/custom/materiotheme/assets/dist/main.js


+ 23 - 0
web/themes/custom/materiotheme/assets/styles/main.scss

@@ -1076,6 +1076,7 @@ article.card{
         max-height: 0; max-width:0;
         overflow: hidden;
         transition: all 0.2s ease-in-out;
+        transition-delay: 0.1s;
       }
       &:hover{
         .tool-content{
@@ -1249,6 +1250,28 @@ article.card{
           }
         }
       }
+      section.tool.note{
+        &:hover div.tool-content{
+          max-height: 370px;
+        }
+        div.tool-content{
+          textarea,
+          textarea:focus,
+          textarea:focus-visible,
+          textarea:active{
+            resize:none;
+            width:99%;
+            height:350px;
+            margin:0;
+            padding:0.3em;
+            border:1px solid #ccc;
+            border-radius: 3px;
+            outline: none;
+            box-sizing: border-box;
+
+          }
+        }
+      }
       // section.tool.industriels{
       //   div.tool-content{
       //     display: flex;

+ 5 - 0
web/themes/custom/materiotheme/vuejs/api/gql/materiaumodal.fragment.gql

@@ -2,6 +2,11 @@ fragment MateriauFields on Materiau {
   title
 	short_description
   reference
+  note{
+    id
+    contenu
+    target
+  }
   attachments{
     file{
       filename

+ 72 - 1
web/themes/custom/materiotheme/vuejs/components/Content/ModalCard.vue

@@ -50,6 +50,12 @@
             </ul>
           </div>
         </section>
+        <section class="tool note">
+          <span class="btn mdi mdi-square-edit-outline"/>
+          <div class="tool-content">
+            <textarea spellcheck="false" v-model="note" name="note"/>
+          </div>
+        </section>
         <section class="tool print">
           <a :href="material.path+'/printable/print'" target="_blank">
             <span class="btn mdi mdi-printer"/>
@@ -198,6 +204,7 @@ import LinkedMaterialCard from 'vuejs/components/Content/LinkedMaterialCard'
 
 import cardMixins from 'vuejs/components/cardMixins'
 
+import { REST } from 'vuejs/api/rest-axios'
 import { MGQ } from 'vuejs/api/graphql-axios'
 import { print } from 'graphql/language/printer'
 import gql from 'graphql-tag'
@@ -205,6 +212,8 @@ import materiauFields from 'vuejs/api/gql/materiaumodal.fragment.gql'
 
 const prettyBytes = require('pretty-bytes')
 
+const _debounce = require('lodash/debounce')
+
 export default {
   name: "ModalCard",
   props: ['item'],
@@ -218,11 +227,14 @@ export default {
       loading: false,
       blanksrc:`${drupalSettings.path.themePath}/assets/img/blank.gif`,
       loadingFlag: false,
-      lightbox_index: null
+      lightbox_index: null,
+      note: "",
+      note_nid: null
     }
   },
   computed: {
     ...mapState({
+      csrf_token: state => state.User.csrf_token,
       flagcolls: state => state.User.flagcolls,
       showrooms: state => state.Showrooms.showrooms_by_tid
     })
@@ -230,6 +242,14 @@ export default {
   created () {
     console.log('modale item', this.item)
     this.loadMaterial()
+    this.debouncedSaveNote = _debounce(this.saveNote, 500)
+  },
+  watch: {
+    // whenever question changes, this function will run
+    note: function (n, o) {
+      console.log("note watcher: note", n)
+      this.debouncedSaveNote()
+    }
   },
   methods: {
     ...mapActions({
@@ -251,6 +271,10 @@ export default {
           console.log('loadMaterial material loaded', materiau )
           this.material = materiau
           this.loading = false
+          if(materiau.note && materiau.note.id){
+            this.note_id = materiau.note.id
+            this.note = materiau.note.contenu
+          }
           // delay the lazyload to let the card the time to update dom
           // maybe not the best method
           setTimeout(function () {
@@ -298,6 +322,53 @@ export default {
     },
     shortUrl(url){
       return url.replace(/^http:\/\//, '').replace(/^www\./, '')
+    },
+    saveNote(){
+      console.log("saveNote", this.note);
+      if(this.note_nid){
+        this.updateNote()
+      }else{
+        this.createNote()
+      }
+    },
+    updateNote(){
+      let params = {
+        type: [{target_id:'note'}],
+        field_contenu: this.note
+      }
+      let config = {
+        headers:{
+          "X-CSRF-Token": this.csrf_token
+        }
+      }
+      REST.patch(`/node/${this.note_nid}?_format=json`, params, config)
+        .then(({ data }) => {
+          console.log('updateNote REST data', data)
+        })
+        .catch(error => {
+          console.warn('Issue with updateNote', error)
+        })
+    },
+    createNote(){
+      let params = {
+        type: [{target_id:'note'}],
+        title: [{value:`note`}],
+        field_contenu: this.note,
+        field_target: this.item.id
+      }
+      let config = {
+        headers:{
+          "X-CSRF-Token": this.csrf_token
+        }
+      }
+      REST.post('/node?_format=json', params, config)
+        .then(({ data }) => {
+          console.log('createNote REST data', data)
+          this.note_nid = data.nid[0].value
+        })
+        .catch(error => {
+          console.warn('Issue with createNote', error)
+        })
     }
   }
 }

Some files were not shown because too many files changed in this diff