can patch node from editablecontent fields

This commit is contained in:
Bachir Soussi Chiadmi 2024-03-18 18:57:07 +01:00
parent 4dc5644898
commit 8c90f54b3c
7 changed files with 216 additions and 28 deletions

View File

@ -23,6 +23,7 @@ fragment ConcernementFields on Concernement {
} }
created created
changed changed
can_update
lieu { lieu {
name name
} }

View File

@ -1026,3 +1026,40 @@ body{
} }
} }
*[contenteditable="true"] {
background: #eee;
border: #eee 2px solid;
border-radius: 5px;
$p:0.3em;
padding:$p;
margin:0 0 0 -$p;
box-sizing: border-box;
transition: all 0.2s ease-in-out;
&:focus{
outline: none;
border: #01ffe2 2px solid;
}
}
button.edit-btn,
button.save-btn{
background-color: #444;
color: #fff;
border: none;
border-radius: 6px;
$size: 25px;
width: $size; height:$size;
display: inline;
>svg{
width:100%;
height:100%;
}
transition: all 0.2s ease-in-out;
&:hover{
cursor:pointer;
opacity: 0.7;
}
}

View File

@ -1985,7 +1985,7 @@ export default {
}.bind(this); }.bind(this);
this.paper_main_object.onMouseMove = function(event){ this.paper_main_object.onMouseMove = function(event){
console.log(`onmousemove ${this.id}`, this.cartouch_is_opened); // console.log(`onmousemove ${this.id}`, this.cartouch_is_opened);
// prevent hover map item mouse event if cartouch is opened // prevent hover map item mouse event if cartouch is opened
if (this.cartouch_is_opened && this.map_mode !== "superposition") return; if (this.cartouch_is_opened && this.map_mode !== "superposition") return;
@ -2068,7 +2068,7 @@ export default {
} }
let result = paper_group_tohit ? paper_group_tohit.hitTest(event.point) : null; let result = paper_group_tohit ? paper_group_tohit.hitTest(event.point) : null;
console.log('move result', result); // console.log('move result', result);
if (result && result.item.item_id && (result.item.name != "label_click_zone" || this.detailsZoomValue > 2)) { if (result && result.item.item_id && (result.item.name != "label_click_zone" || this.detailsZoomValue > 2)) {
console.log('move has result', result); console.log('move has result', result);
let new_hover_elmt = { let new_hover_elmt = {

View File

@ -21,6 +21,8 @@ import SvgIcon from '@jamescoyle/vue-icon';
import { mdiChevronRight } from '@mdi/js'; import { mdiChevronRight } from '@mdi/js';
import { mdiChevronDown } from '@mdi/js'; import { mdiChevronDown } from '@mdi/js';
import ContentEditable from '@components/misc/ContentEditable.vue';
export default { export default {
props: ['cid', 'eid'], props: ['cid', 'eid'],
data(){ data(){
@ -206,13 +208,20 @@ export default {
} else { } else {
this.headerreduced = false; this.headerreduced = false;
} }
},
onContentEditableFocusOut(e){
console.log('onContentEditableFocusOut', e);
let new_field_content = e.target.innerText;
console.log('onContentEditableFocusOut', new_field_content);
console.log('onContentEditableFocusOut this.concernement.title', this.concernement.title);
} }
}, },
components: { components: {
CartoucheLayout, CartoucheLayout,
Entite, Entite,
VueSlider, VueSlider,
SvgIcon SvgIcon,
ContentEditable
} }
} }
@ -233,13 +242,36 @@ export default {
<template v-if="!entite"> <template v-if="!entite">
<section v-if="concernement.description" class="description"> <section v-if="concernement.description" class="description">
<label v-if="ct_concernement">{{ ct_concernement.field_description.description }}</label> <label v-if="ct_concernement">{{ ct_concernement.field_description.description }}</label>
<p v-html="concernement.description"/>
<!-- <p>{{ concernement.description }}</p> --> <ContentEditable
tag="p"
:value="concernement.description"
:html="true"
:class="{ ellipsed: headerreduced }"
:contenteditable="concernement.can_update"
:data="{
entitytype: 'node',
bundle: 'concernement',
nid: this.concernement.id,
field: 'field_description'
}" />
</section> </section>
<section v-if="concernement.caillou" class="caillou"> <section v-if="concernement.caillou" class="caillou">
<label v-if="ct_concernement">{{ ct_concernement.field_caillou.description }}</label> <label v-if="ct_concernement">{{ ct_concernement.field_caillou.description }}</label>
<!-- <p v-html="concernement.caillou"/> -->
<p>{{ concernement.caillou }}</p> <ContentEditable
tag="p"
:value="concernement.caillou"
:class="{ ellipsed: headerreduced }"
:contenteditable="concernement.can_update"
:data="{
entitytype: 'node',
bundle: 'concernement',
nid: this.concernement.id,
field: 'field_caillou'
}" />
</section> </section>
</template> </template>

View File

@ -6,6 +6,8 @@ import { ConcernementsStore } from '@stores/concernements'
import SvgIcon from '@jamescoyle/vue-icon'; import SvgIcon from '@jamescoyle/vue-icon';
import { mdiHeadphones } from '@mdi/js'; import { mdiHeadphones } from '@mdi/js';
import ContentEditable from '@components/misc/ContentEditable.vue';
export default { export default {
props: ['cid'], props: ['cid'],
emits: ['main_scrolled'], emits: ['main_scrolled'],
@ -19,6 +21,7 @@ export default {
created () { created () {
console.log('Cartouch layout created', this.cid); console.log('Cartouch layout created', this.cid);
this.concernement = this.concernementsByID[this.cid]; this.concernement = this.concernementsByID[this.cid];
console.log('can_update', this.concernement.can_update);
}, },
mounted () { mounted () {
// console.log('cartouche layout mounted', this); // console.log('cartouche layout mounted', this);
@ -44,16 +47,18 @@ export default {
console.log(`TerrainDeVie watch cid o:${o}, n:${n}`); console.log(`TerrainDeVie watch cid o:${o}, n:${n}`);
if (n) { if (n) {
this.concernement = this.concernementsByID[n]; this.concernement = this.concernementsByID[n];
console.log('can_update', this.concernement.can_update);
} }
}, },
deep: true deep: true
} }
}, },
methods: { methods: {
...mapActions(ConcernementsStore,['setMapMode']) ...mapActions(ConcernementsStore,['setMapMode']),
}, },
components: { components: {
SvgIcon SvgIcon,
ContentEditable
} }
} }
</script> </script>
@ -62,7 +67,20 @@ export default {
<header ref="cartouche_header"> <header ref="cartouche_header">
<div class="concernement-cartouche-icons"> <div class="concernement-cartouche-icons">
<label :class="{ hidden: headerreduced }">{{ ct_concernement.title.description }}</label> <label :class="{ hidden: headerreduced }">{{ ct_concernement.title.description }}</label>
<h2 :class="{ ellipsed: headerreduced }">{{ concernement.title }}</h2>
<ContentEditable
tag="h2"
:value="concernement.title"
:class="{ ellipsed: headerreduced }"
:contenteditable="concernement.can_update"
:data="{
entitytype: 'node',
bundle: 'concernement',
nid: this.concernement.id,
field: 'title'
}" />
<!-- <nav class="icons"> <!-- <nav class="icons">
<ul> <ul>
<li v-if="concernement.has_recit" > <li v-if="concernement.has_recit" >

View File

@ -0,0 +1,95 @@
<script>
import REST from '@api/rest-axios'
// import JSONAPI from '@api/json-axios'
// import qs from 'querystring-es3'
// import { print } from 'graphql/language/printer'
// import gql from 'graphql-tag'
// import GQL from '@api/graphql-axios'
import { mapActions, mapState } from 'pinia'
import { UserStore } from '@stores/user'
export default {
props: {
tag: String,
value: String,
contenteditable : {
type : [Boolean, String],
default : true,
},
html : {
type : [Boolean, String],
default : false,
},
data: Object
},
// emits: ['returned'],
data(){
return {
}
},
computed: {
...mapState(UserStore,['csrf_token']),
},
created () {
console.log('ContentEditable created');
},
mounted () {
},
methods: {
onContentEditableFocusOut(e){
console.log('onContentEditableFocusOut', e);
// console.log('onContentEditableFocusOut data', this.data);
let new_field_content = this.html ? e.target.innerHTML : e.target.innerText;
// console.log('onContentEditableFocusOut', new_field_content);
this.save(new_field_content)
},
save(content){
console.log('save csrf_token', this.csrf_token);
const params = {
type: this.data.bundle,
nid: [{"value":this.data.nid}],
[this.data.field]: {value: content}
};
const configs = {
headers: {
'X-CSRF-Token': this.csrf_token,
// Authorization: `Bearer ${this.csrf_token}`,
// 'customheader': "bobobo"
}
};
console.log('REST', REST);
REST.patch(`/node/${this.data.nid}?_format=json`, params, configs)
.then(({ data }) => {
console.log('user REST post node data', data)
// TODO if success update the data in pinia
})
.catch(error => {
console.warn('Issue with post node', error)
Promise.reject(error)
})
}
},
}
</script>
<template>
<component
v-if="!html"
:is="tag"
:contenteditable="contenteditable"
@focusout="onContentEditableFocusOut"
>{{ value }}</component>
<component
v-else
:is="tag"
v-html="value"
:contenteditable="contenteditable"
@focusout="onContentEditableFocusOut"
/>
</template>

View File

@ -39,26 +39,31 @@ export const UserStore = defineStore({
this.isloggedin = true //data.attributes.status this.isloggedin = true //data.attributes.status
console.log('user store checkuser isloggedin', this.isloggedin); console.log('user store checkuser isloggedin', this.isloggedin);
this.userGetRoles() this.getUser(); // necessery to get the csrf-token
.then(({ data : { data : { user } } }) => {
console.log('graphql user loaded', user) // this.userGetRoles()
this.roles = user.roles // .then(({ data : { data : { user } } }) => {
this.checkIsAdmin() // console.log('graphql user loaded', user)
}) // this.roles = user.roles
.catch(error => { // this.checkIsAdmin()
console.warn('Issue with graphql user loading', error) // })
Promise.reject(error) // .catch(error => {
}) // console.warn('Issue with graphql user loading', error)
// Promise.reject(error)
// })
}) })
} }
}) })
},
getSessionToken(){
}, },
userLogin (credentials) { userLogin (credentials) {
console.log('user store userLogin', credentials); console.log('user store userLogin', credentials);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.getToken(credentials) this.postCredentials(credentials)
.then((response) => { .then((response) => {
console.log('userLogin getToken response', response) console.log('userLogin postCredentials response', response)
if (response.status === 200) { if (response.status === 200) {
this.uid = response.data.current_user.uid this.uid = response.data.current_user.uid
@ -71,24 +76,24 @@ export const UserStore = defineStore({
console.log('User Loggedin') console.log('User Loggedin')
// todo reload concernements // todo reload concernements
// concrnmtStore().reloadConcernements(); // INFO would be good but to much complicated for now, just reload the page // concrnmtStore().reloadConcernements(); // INFO would be good but to much complicated for now, just reload the page
window.location.reload(); // window.location.reload();
resolve() resolve()
}) })
} else { } else {
this.loginMessage = response.data.message this.loginMessage = response.data.message
console.warn('Issue with getToken', response) console.warn('Issue with postCredentials', response)
console.log('user loggein failed', this.loginMessage) console.log('user loggein failed', this.loginMessage)
Promise.reject(new Error('user loggin failed')) Promise.reject(new Error('user loggin failed'))
} }
}) })
.catch(error => { .catch(error => {
console.warn('Issue with Dispatch getToken', error) console.warn('Issue with Dispatch postCredentials', error)
Promise.reject(error) Promise.reject(error)
}) })
}) })
}, },
getToken (credentials) { postCredentials (credentials) {
console.log('userStore getToken', credentials) console.log('userStore postCredentials', credentials)
return REST.post('/user/login?_format=json', return REST.post('/user/login?_format=json',
credentials, credentials,
{ {