ContentEditable.vue 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <script>
  2. import REST from '@api/rest-axios'
  3. import { mapActions, mapState } from 'pinia'
  4. import { ConcernementsStore } from '@stores/concernements'
  5. import { UserStore } from '@stores/user'
  6. import MediumEditor from 'medium-editor-x'
  7. import 'medium-editor-x/dist/css/medium-editor.css'
  8. import 'medium-editor-x/dist/css/themes/beagle.css'
  9. export default {
  10. props: {
  11. tag: String,
  12. value: String,
  13. contenteditable : {
  14. type : [Boolean, String],
  15. default : true,
  16. },
  17. html : {
  18. type : [Boolean, String],
  19. default : false,
  20. },
  21. data: Object
  22. },
  23. emits: ['updated'],
  24. data(){
  25. return {
  26. editor: null,
  27. spellcheck: false
  28. }
  29. },
  30. computed: {
  31. ...mapState(UserStore,['csrf_token']),
  32. },
  33. created () {
  34. console.log('ContentEditable created');
  35. },
  36. mounted () {
  37. this.editor = new MediumEditor(this.$refs.html_editable, {
  38. toolbar: {
  39. allowMultiParagraphSelection: false,
  40. buttons: ['anchor'],
  41. }
  42. });
  43. },
  44. beforeUnmount() {
  45. },
  46. methods: {
  47. ...mapActions(ConcernementsStore, ['reloadConcernements']),
  48. onContentEditableFocusOut(e){
  49. console.log('onContentEditableFocusOut', e);
  50. // console.log('onContentEditableFocusOut data', this.data);
  51. let new_field_content = this.html ? e.target.innerHTML : e.target.innerText;
  52. // console.log('onContentEditableFocusOut', new_field_content);
  53. this.save(new_field_content)
  54. },
  55. save(content){
  56. // console.log('save csrf_token', this.csrf_token);
  57. const params = {
  58. type: this.data.bundle,
  59. [this.data.field.field_name]: [{[this.data.field.value]: content}]
  60. };
  61. if (this.data.entitytype === 'node') {
  62. params.nid = [{"value":this.data.id}];
  63. } else {
  64. params.id = [{"value":this.data.id}];
  65. }
  66. // we need additional values for image alt for example
  67. // console.log('additional_values', this.data.field.additional_values);
  68. if (this.data.field.additional_values) {
  69. for (const key in this.data.field.additional_values) {
  70. if (Object.hasOwnProperty.call(this.data.field.additional_values, key)) {
  71. params[this.data.field.field_name][0][key] = this.data.field.additional_values[key]
  72. }
  73. }
  74. }
  75. const configs = {
  76. headers: {'X-CSRF-Token': this.csrf_token}
  77. };
  78. let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
  79. REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
  80. .then(({ data }) => {
  81. console.log('user REST post node data', data)
  82. // TODO if success update the data in pinia
  83. // this.reloadConcernements();
  84. this.$emit('updated');
  85. })
  86. .catch(error => {
  87. console.warn(`Issue with patch node ${this.data.bundle}`, error)
  88. Promise.reject(error)
  89. })
  90. }
  91. },
  92. components: {
  93. }
  94. }
  95. </script>
  96. <template>
  97. <component
  98. v-if="!html"
  99. :is="tag"
  100. :contenteditable="contenteditable"
  101. :spellcheck="speelcheck"
  102. @focusout="onContentEditableFocusOut"
  103. >{{ value }}</component>
  104. <component
  105. v-else
  106. :is="tag"
  107. class="html-editable"
  108. ref="html_editable"
  109. v-html="value"
  110. :contenteditable="contenteditable"
  111. :spellcheck="speelcheck"
  112. @focusout="onContentEditableFocusOut"
  113. />
  114. </template>