Compare commits

...

43 Commits

Author SHA1 Message Date
1667fd0403 partially debuged proximites 2025-06-03 17:02:37 +02:00
f6292d8ad1 better cartouch css 2025-06-03 16:20:53 +02:00
f35493ea90 better cartouch css 2025-06-03 16:08:37 +02:00
bab0204ed7 commented B Latour video on doleancer 2025-06-03 13:01:28 +02:00
a9e6fe2567 fixed recording entity when switching or closing entity 2025-06-03 13:01:02 +02:00
cc943c5776 fixed concernement field recording 2025-06-03 12:38:26 +02:00
b9f9551efa drag if not editable bug fix 2025-06-02 15:21:53 +02:00
b9b04f1634 fixed entities label bug on detail zoom 2025-06-02 10:54:04 +02:00
3e25f8c678 added commit hash as release name in sentry vitejs config 2025-05-05 10:54:26 +02:00
77640c9d16 bugfix concernementmapitem this.constraint 2025-05-05 10:43:45 +02:00
2837705a38 bugfix graphql-axios 2025-05-05 10:19:50 +02:00
01d3278a6a sentry vite plugin sourcemap fixed release.name, removed test error 2025-03-21 23:16:55 +01:00
2d9f83cfef added sentry test throw error 2025-03-21 23:00:44 +01:00
0e92cbb060 @sentry/vite-plugin & sourcemap bugfix 2025-03-21 22:45:52 +01:00
5d27c489a1 @sentry/vite-plugin & sourcemap bugfix 2025-03-21 22:44:12 +01:00
629dd738f5 added @sentry/vite-plugin & sourcemap 2025-03-21 22:40:20 +01:00
78480e4958 removed sentry captur message test 2025-03-20 22:26:53 +01:00
18a90fec0a sentry captur message test 2025-03-20 22:25:15 +01:00
c63740fe1c integrated sentry/glitchtip 2025-03-20 20:45:44 +01:00
424c251f26 cercle politique admin front fine tunning 2025-03-13 14:11:29 +01:00
86074b4bb0 cercle politique admin front fine tunning 2025-03-13 12:02:21 +01:00
076a0b4c67 cercle politique admin front completed 2025-03-12 16:22:22 +01:00
64d174dcfc cercle po: adresse de la decision ok 2025-02-26 19:17:01 +01:00
77ca3a85cf cercle po: mise en œuvre de la decision ok 2025-02-26 19:06:18 +01:00
a33104e402 cercle po: active steo is visualy focused 2025-02-26 16:48:30 +01:00
55b213af64 cercle po: decision ok 2025-02-26 12:39:48 +01:00
4afa5fbfa0 cercle po: adresse doleance & reception et traitement OK 2025-02-26 12:24:23 +01:00
b3c6f3bb9c admin front doleance groupes d'intérets done 2025-02-13 12:43:05 +01:00
d324c0436e admin front doleance improved dateEditable with optional range 2025-02-13 11:50:29 +01:00
e0651f9ac9 admin front doleance add new groupe interet 2025-02-12 17:13:50 +01:00
86bd454791 admin front doleance DateEditable 2025-02-12 15:21:31 +01:00
a87d7ac5ff admin front l'enquete 2025-02-12 13:44:56 +01:00
85f4100fe9 admin front create new doleance 2025-02-10 16:22:12 +01:00
1da22af863 doleance le problème is editable 2025-02-10 12:09:42 +01:00
0b92ab8e9f restored prev bug fix 2024-12-04 13:00:04 +01:00
7db1608051 bug fix 2024-12-04 11:31:18 +01:00
45a1e25e66 bug fix 2024-10-10 10:31:12 +02:00
d6b3bdf2aa admin front: entite active boolean 2024-10-04 15:46:36 +02:00
984ec07084 fileeditable filename with accent bug fix 2024-10-03 23:02:35 +02:00
6fb04ede84 linkeditable save bug fix 2024-10-03 22:30:39 +02:00
0fae2dee66 bug fix: revisions mismatch 2024-10-03 22:18:45 +02:00
f44d52bc2c bug fix: open boussole from search failed when mapitem_id different from cid 2024-10-03 22:18:11 +02:00
b988b43a66 commented some consolelog 2024-10-03 21:21:31 +02:00
23 changed files with 3170 additions and 526 deletions

2
.gitignore vendored
View File

@ -14,6 +14,8 @@ dist-ssr
coverage
*.local
.env
/cypress/videos/
/cypress/screenshots/

1005
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,13 @@
"@material-design-icons/svg": "^0.14.2",
"@mdi/font": "^7.1.96",
"@mdi/js": "^7.2.96",
"@sentry/browser": "^9.7.0",
"@sentry/integrations": "^7.114.0",
"@sentry/vue": "^9.7.0",
"@tweenjs/tween.js": "^21.0.0",
"@vojtechlanka/vue-simple-suggest": "^2.0.6",
"@vuepic/vue-datepicker": "^11.0.1",
"dotenv": "^16.4.7",
"fabric": "^6.0.0-beta7",
"granim": "^2.0.0",
"lodash": "^4.17.21",
@ -34,6 +39,7 @@
"devDependencies": {
"@rollup/plugin-graphql": "^2.0.0",
"@rushstack/eslint-patch": "^1.1.4",
"@sentry/vite-plugin": "^3.2.2",
"@types/medium-editor": "^5.0.8",
"@vitejs/plugin-vue": "^4.4.0",
"@vue/eslint-config-prettier": "^8.0.0",

View File

@ -21,8 +21,11 @@ export default {
}
},
created () {
this.loadContentTypeDefinition();
this.loadContentTypeDefinition()
this.loadConcernements()
// setTimeout(()=>{
// throw new Error("sentry test error");
// })
},
mounted () {
console.log('APP onMounted')

View File

@ -30,6 +30,7 @@ fragment ConcernementFields on Concernement {
entites {
id
revision_id
active
menacemaintien
actuelfuture
entite {
@ -50,6 +51,9 @@ fragment ConcernementFields on Concernement {
revision_id
changed
entites {
id
revision_id
active
menacemaintien
prise
actuelfuture
@ -99,6 +103,8 @@ fragment ConcernementFields on Concernement {
leprobleme
lenquete
groupesinterets {
id
revision_id
date {
end
start
@ -111,10 +117,12 @@ fragment ConcernementFields on Concernement {
date_adresse {
start
}
entite_addresse_doleance
comment_ennonce_doleance
aqui_addresse_doleance
entite_adresse_doleance
comment_enonce_doleance
a_qui_adresse_doleance
reception_traitement {
id
revision_id
date {
end
start
@ -129,8 +137,10 @@ fragment ConcernementFields on Concernement {
start
}
entites_decisionnaires
decision_formule
decision_formulee
mise_en_oeuvre_decision {
id
revision_id
date {
end
start
@ -147,6 +157,8 @@ fragment ConcernementFields on Concernement {
aqui_adresse_decision
comment_formule_decision
receptions_et_applications {
id
revision_id
date {
end
start

View File

@ -21,8 +21,8 @@ MGQ.interceptors.response.use(
return Promise.resolve(response)
},
error => {
const { status } = error.response
console.warn('error in graphql-axios', status)
// const { status } = error.response
// console.warn('error in graphql-axios', status)
// if (status === 403) {
// window.location = '/'
// }

View File

@ -224,7 +224,7 @@ div.loading{
box-sizing: border-box;
width:$cartouch_width_full;
height: 100%;
padding: 2rem 2rem 1rem;
padding: 1rem 1rem 1rem;
overflow-y: auto;
overflow-x: hidden;
//
@ -263,7 +263,7 @@ div.loading{
// layout
>header{
flex: 0 0 auto;
padding: 0 0 1em 0;
// padding: 0 0 1em 0;
}
>main{
flex: 1 1 auto;
@ -305,7 +305,7 @@ div.loading{
// display: flex;
// flex-direction: column;
// justify-content: flex-end;
padding-bottom: 0.5em;
// padding-bottom: 0.5em;
label, h3{
// height: 70px;
box-sizing: border-box;
@ -325,22 +325,30 @@ div.loading{
font-weight: bold;
}
}
// span.menacemaintient{
// display: block;
// font-weight: 100;
// font-size: 0.882em;
// padding: 1em 0;
// }
section.entite-params{
padding:0.5em 0;
display: flex;
flex-direction: row;
gap:0.5em;
align-items: center;
>section.editable{
// margin: 0.3em;
flex: 1 0 auto;
}
}
}
div.concernement-cartouche-icons{
margin-bottom: 1em;
h2{
font-weight: 400;
font-weight: 500;
font-size: 1.512em;
// &.faded{
// font-weight: 100;
// }
padding-bottom: 0.5em;
margin-top: 0;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
@ -379,13 +387,23 @@ div.loading{
transition: max-height 0.5s ease-in-out,padding 0.5s ease-in-out;
max-height: 100px;
overflow: hidden;
&.hidden{
max-height: 0;
padding-bottom: 0;
// &.hidden{
// max-height: 0;
// padding-bottom: 0;
// }
}
}
&.entity-opened{
>header{
div.concernement-cartouche-icons{
label{
max-height: 0;
padding-bottom: 0;
}
}
}
}
>main{
overflow-y: auto;
padding-top: $gradpad;
@ -607,55 +625,23 @@ div.loading{
margin: 0 0 0.5em 0;
}
}
>section{
margin:1em 0 0;
}
label{
margin:0;
margin:1em 0 0;
padding:0 0 0.5em 0;
}
p{
p:not(.editable):not(.html-editable){
margin:0;
padding:0 0 0.5em 0;
}
ul{
// padding:0 0 0 1em;
}
// .v-select{
// input.vs__search{
// display: none;
// }
// div.vs__dropdown-toggle{
// border-radius: 0;
// border: none;
// }
// div.vs__selected-options{
// padding: 0;
// span.vs__selected{
// padding: 0;
// margin: 0;
// font-weight: 400;
// font-size: 1.323em;
// color:inherit;
// line-height: 1.15;
// }
// }
// ul.vs__dropdown-menu{
// border-radius: 0;
// border: none;
// li.vs__dropdown-option{
// white-space:normal;
// padding:1em 1em 0 1em;
// &:last-of-type{
// padding:1em;
// }
// color: #aaa;
// transition: color 0.2s ease-in-out;
// &.vs__dropdown-option--highlight{
// color:#000;
// background-color: #fff;
// }
// }
// }
// }
.leprobleme-date{
margin: 0.5em 0;
}
}
}
@ -721,7 +707,7 @@ div.loading{
font-weight: 400;
font-size: 1.1em;
}
section>div, p{
section>div:not(.btn), p{
// font-size: 1em;
// font-weight: 300;
// line-height: 1.40;
@ -731,7 +717,7 @@ div.loading{
span.date{
@include font_questions();
display: block;
padding: 0 0 1em 0;
padding: 0 0 0.3em 0;
}
ul, li{
padding:0; margin:0;
@ -1090,7 +1076,8 @@ div.loading{
}
}
*[contenteditable="true"] {
*[contenteditable="true"],
div.dp__main{
background: #eee;
border: #eee 2px solid;
border-radius: 5px;
@ -1099,6 +1086,8 @@ div.loading{
margin:0 0 0 -$p;
box-sizing: border-box;
transition: all 0.2s ease-in-out;
box-shadow: 2px 2px 4px #bbb;
width: calc(100% - 4px);
&:focus{
outline: none;
border: #01ffe2 2px solid;
@ -1328,4 +1317,21 @@ div.add-besoin-btn{
div.add-ressource-btn{
@include add-btn();
}
div.add-cerclepo-btn,
div.add-groupinteret-btn,
div.add-adressedoleance-btn,
div.add-receptiontraitement-btn,
div.add-decision-btn,
div.add-miseenoeuvre-btn,
div.add-adressedecision-btn,
div.add-receptionapplicationdecision-btn{
@include add-btn();
margin: 0 0 1em;
height: 60px;
line-height: 50px;
>svg{
width:30px; height:30px;
}
}

View File

@ -31,6 +31,7 @@ export default {
concernement: null,
active_revision: null,
entities: null,
activeEntites: null,
superposedEntiteID: null,
// superposedEntitesIDsList: [],
canvas: null,
@ -86,7 +87,8 @@ export default {
'detailsZoomValue',
'reloadConcernements',
'reloadConcernementEntites',
'concernements_loading_nb']),
'concernements_loading_nb',
'concernement_is_updating_nid']),
...mapState(CommonStore,['hover_elmt',
'map_item_ray',
'cartouch_width',
@ -95,7 +97,7 @@ export default {
...mapState(UserStore,['csrf_token']),
},
created () {
console.log('ConcernementMapItem created', this.mapitem);
// console.log('ConcernementMapItem created', this.mapitem);
// this.id = this.superposition_id ? `${this.cid}___${this.superposition_id}` : this.cid;
// console.log(`this.mapitem.id`, this.mapitem.id);
this.resetConcernement();
@ -116,9 +118,9 @@ export default {
//
this.parseEntityPointsValues();
let activeEntites = this.getActiveEntites(this.entites);
// this.getSalientPoints()
this.sailentEntites = this.concernement.sailentEntites = this.getJarvisEnvelopeConvexeEntites(this.entites)
this.sailentEntites = this.concernement.sailentEntites = this.getJarvisEnvelopeConvexeEntites(activeEntites)
// define init position of the item
this.pos = this.getRandomPos();
@ -268,7 +270,7 @@ export default {
},
concernement: {
handler (n, o){
console.log(`ConcernementMapItem ${this.id} watch concernement o, n`, this.concernement.parsedEntites, o, n);
// console.log(`ConcernementMapItem ${this.id} watch concernement o, n`, this.concernement.parsedEntites, o, n);
// check for active_revision changes
// do not trigger on first variable filling (if o is null)
// check for new concernement object
@ -297,7 +299,7 @@ export default {
},
'concernement.besoins': {
handler (n, o){
console.log(`ConcernementMapItem ${this.id} watch concernement.besoins o, n`, o, n);
// console.log(`ConcernementMapItem ${this.id} watch concernement.besoins o, n`, o, n);
if (this.is_open && this.map_mode === "puissancedagir") {
// this.resetPaperBesoinReponsePos();
this.setPaperPuissanceagirBesoins(true); // true for update=true
@ -307,7 +309,7 @@ export default {
},
'concernement.besoins.length': {
handler (n, o){
console.log(`ConcernementMapItem ${this.id} watch concernement.besoins.length o, n`, o, n);
// console.log(`ConcernementMapItem ${this.id} watch concernement.besoins.length o, n`, o, n);
if (this.is_open && this.map_mode === "puissancedagir" && o != null && n !== o) {
this.resetPaperContents();
}
@ -367,7 +369,7 @@ export default {
},
'concernement.entites': {
handler (n, o) {
console.log(`ConcernementMapItem ${this.id} watch concernement.entites o, n`, o, n);
// console.log(`ConcernementMapItem ${this.id} watch concernement.entites o, n`, o, n);
// do not trigger on first fill of the property (if o is null)
if (o) {
this.resetPaperEntitesAndContours();
@ -376,6 +378,32 @@ export default {
},
deep: true
},
'concernement.doleances': {
handler (n, o) {
console.log(`${this.id} watch concernement.doleances o, n`, o, n);
if (this.is_open && this.map_mode === "doleancer") {
this.setPaperDoleances(true); // true for update=true
this.focusOpenedDoleanceStep();
}
},
deep: true
},
'concernement.doleances.length': {
handler (n, o){
console.log(`${this.id} watch concernement.doleances.length o, n`, o, n);
if (this.is_open && this.map_mode === "doleancer" && o != null && n !== o) {
this.resetPaperContents();
}
},
deep: true
},
'concernement.opened_doleance': {
handler (n, o) {
console.log(`${this.id} watch concernement.opened_doleance o, n`, o, n);
this.focusOpenedDoleanceStep();
},
deep: true
},
wait: {
handler (n, o){
// when we are reloading entites par exemple
@ -400,7 +428,7 @@ export default {
'setDetailsZoomValue',
]),
resetConcernement(){
console.log(`resetConcernement() ${this.mapitem.id}`);
// console.log(`resetConcernement() ${this.mapitem.id}`);
this.id = this.mapitem.id;
this.concernement = this.concernementsByID[this.mapitem.cid];// this.mapitem.concernement;
this.cid = this.concernement.id;
@ -409,10 +437,17 @@ export default {
// console.log(`ConcernementsMapItem ${this.id} created`);
// this.entites = this.concernement.entites
this.entites = this.concernement.revisions_byid[this.concernement.revision_id].entites;
// TODO sometimes active revision is not on revisions_by_id ... why ?
let revisions_ids = Object.keys(this.concernement.revisions_byid);
if (revisions_ids.indexOf(this.concernement.revision_id) !== -1) {
this.entites = this.concernement.revisions_byid[this.concernement.revision_id].entites;
} else {
this.entites = this.concernement.revisions_byid[revisions_ids.pop()].entites;
}
},
parseEntityPointsValues (){
console.log(`parseEntityPointsValues`);
// console.log(`parseEntityPointsValues`);
// converts data (menace/maintien, actuel/future, prise) into atcual position x,y
for (let r = 0; r < this.concernement.revisions.length; r++) { // loop through all revisions
for (let i = 0; i < this.concernement.revisions[r].entites.length; i++) { // loop through all entite for each revision
@ -458,6 +493,17 @@ export default {
this.concernement.parsedEntites = true;
},
getActiveEntites(entites){
// console.log('getActiveEntites', entites);
let activeEntites = [];
for (let i = 0; i < entites.length; i++) {
if (entites[i].active) {
activeEntites.push(entites[i])
}
}
return activeEntites;
},
getSalientPoints_OLD() {
// debugger
// console.log(this.entites);
@ -493,6 +539,12 @@ export default {
// console.log(`this.salientPoints ${this.concernement.id}`, this.salientPoints);
},
getJarvisEnvelopeConvexeEntites(entites){
// console.log(`getJarvisEnvelopeConvexeEntites cid:${this.cid}`, entites);
if (entites.length === 0) {
console.error('getJarvisEnvelopeConvexeEntites entites must not be empty')
return;
}
let sailentEntites = [];
// https://www.geeksforgeeks.org/convex-hull-using-jarvis-algorithm-or-wrapping/
// find the most left point
@ -523,19 +575,21 @@ export default {
// clockwise than q, then update q.
q = (p + 1) % entites.length;
for (let i = 0; i < entites.length; i++) {
let p_x = (entites[p].display.ray) * Math.cos(entites[p].display.alpha * (Math.PI/180));
let p_y = (entites[p].display.ray) * Math.sin(entites[p].display.alpha * (Math.PI/180));
let i_x = (entites[i].display.ray) * Math.cos(entites[i].display.alpha * (Math.PI/180));
let i_y = (entites[i].display.ray) * Math.sin(entites[i].display.alpha * (Math.PI/180));
let q_x = (entites[q].display.ray) * Math.cos(entites[q].display.alpha * (Math.PI/180));
let q_y = (entites[q].display.ray) * Math.sin(entites[q].display.alpha * (Math.PI/180));
let val = (i_y - p_y) * (q_x - i_x) - (i_x - p_x) * (q_y - i_y);
// If i is more clockwise than current q, then update q
if (val > 0){
q = i;
}
// if (entite.active) {
let p_x = (entites[p].display.ray) * Math.cos(entites[p].display.alpha * (Math.PI/180));
let p_y = (entites[p].display.ray) * Math.sin(entites[p].display.alpha * (Math.PI/180));
let i_x = (entites[i].display.ray) * Math.cos(entites[i].display.alpha * (Math.PI/180));
let i_y = (entites[i].display.ray) * Math.sin(entites[i].display.alpha * (Math.PI/180));
let q_x = (entites[q].display.ray) * Math.cos(entites[q].display.alpha * (Math.PI/180));
let q_y = (entites[q].display.ray) * Math.sin(entites[q].display.alpha * (Math.PI/180));
let val = (i_y - p_y) * (q_x - i_x) - (i_x - p_x) * (q_y - i_y);
// If i is more clockwise than current q, then update q
if (val > 0){
q = i;
}
// }
}
// Now q is the most clockwise with
@ -810,7 +864,8 @@ export default {
});
// rebuild the contours with the new ray
this.parseEntityPointsValues()
this.sailentEntites = this.concernement.sailentEntites = this.getJarvisEnvelopeConvexeEntites(this.entites)
let activeEntites = this.getActiveEntites(this.entites);
this.sailentEntites = this.concernement.sailentEntites = this.getJarvisEnvelopeConvexeEntites(activeEntites)
// redraw the contours
this.paper_main_object.addChild(this.setPaperContour());
@ -887,9 +942,12 @@ export default {
this.paper_main_object.addChild(this.setPaperAgissantes());
break;
case 'doleancer':
this.addNewPaperSymbolInstance('doleance_bg');
this.paper_main_object.addChild(this.setPaperDoleances());
if (this.concernement.doleances.length) {
this.addNewPaperSymbolInstance('doleance_bg');
this.paper_main_object.addChild(this.setPaperDoleances());
}
break;
}
this.paperContentsIsSet = true;
}
@ -909,8 +967,9 @@ export default {
console.log(`entite len : ${this.concernement.revisions_byid[this.active_revision].entites.length}`);
this.parseEntityPointsValues()
this.sailentEntites = this.getJarvisEnvelopeConvexeEntites(this.concernement.revisions_byid[this.active_revision].entites);
let activeEntites = this.getActiveEntites(this.concernement.revisions_byid[this.active_revision].entites);
this.sailentEntites = this.getJarvisEnvelopeConvexeEntites(activeEntites);
// remove contours if already exists
if (this.paper_main_object.children && this.paper_main_object.children.contours) {
@ -960,7 +1019,7 @@ export default {
}
},
getPaddedRoundedSegments(points, scale){
console.log(`setPaperContour ${this.concernement.id}, points`, points);
// console.log(`setPaperContour ${this.concernement.id}, points`, points);
let getSegmentProps = (b,a,c) => {
const ac = { x: c.x - a.x, y: c.y - a.y } // get ac vecteur
const lac = Math.sqrt(Math.pow(ac.x, 2) + Math.pow(ac.y, 2)); // get ac longueur ac
@ -1077,6 +1136,8 @@ export default {
},
setPaperEntites(){
console.log(`setPaperEntites ${this.cid}`);
let g = new paper.Group({
pivot: new paper.Point(this.pos),
name: 'entites'
@ -1087,29 +1148,38 @@ export default {
opacity: 0
});
g.addChild(g_label);
// when we are re-setting the entitie (e.g. arfter one entity moved) also check the detail zoom and apply correct dim
g_label.opacity = -2 + this.detailsZoomValue;
g_label.sendToBack();
// for (let i = 0; i < this.entites.length; i++) {
for (let i = 0; i < this.concernement.revisions_byid[this.active_revision].entites.length; i++) {
let entite = this.concernement.revisions_byid[this.active_revision].entites[i];
console.log('entite', entite);
if (!entite.active && !this.concernement.can_update) {
continue;
}
// item type
let item_type = entite.entite ? entite.entite.agissante ? 'entite_action' : 'entite' : 'entite_hidden';
let item_type = entite.entite ? entite.entite.agissante ? 'entite_action' : entite.active ? 'entite' : 'entite_inactive' : 'entite_hidden';
// use paper symbol
let symbol_name = item_type;
switch (item_type) {
case 'entite':
if(parseInt(this.opened_entite_id) === entite.entite.id){
if(entite.entite && parseInt(this.opened_entite_id) === entite.entite.id){
switch (item_type) {
case 'entite':
symbol_name = 'entite_hover';
}
break;
case 'entite_action':
if(parseInt(this.opened_entite_id) === entite.entite.id){
break;
case 'inactive_entite':
symbol_name = 'entite_inactive_hover';
break;
case 'entite_action':
symbol_name = 'entite_action_hover';
}
break;
}
break;
}
}
// console.log(`item_type: ${item_type}, symbol_name: ${symbol_name}`);
console.log(`item_type: ${item_type}, symbol_name: ${symbol_name}`);
let instance = new paper.SymbolItem(this.paper_symbol_definitions[symbol_name]);
instance.name = 'entite';
@ -1122,7 +1192,8 @@ export default {
instance.is_symbol_instance = true;
g.addChild(instance);
// instance.bringToFront();
console.log('instance', instance);
if (entite.entite && entite.entite.title) {
let pad = 2;
let label_pos = new paper.Point({
@ -1168,12 +1239,15 @@ export default {
label.addChild(label_bg);
label_txt.insertAbove(label_bg);
label_click_zone.insertAbove(label_txt);
label.scale(this.scale);
// label.sendToBack();
g_label.addChild(label);
instance.label_item = label;
}
}
console.log(`g`, g);
return g;
},
setPaperEntitesSuperposees(){
@ -1391,8 +1465,13 @@ export default {
}); // end of loop on proximite for each main entite
// WARNING allEntiteRefConcernementContourEntites does contains entities just display infos so WHY getActiveEntities() it CAN'T work
// let activeEntites = this.getActiveEntites(allEntiteRefConcernementContourEntites);
// console.log('activeEntites', activeEntites);
// general contour arround proximité
// console.log('allEntiteRefConcernementContourEntites', allEntiteRefConcernementContourEntites);
// let genContoursEntite = this.getJarvisEnvelopeConvexeEntites(activeEntites);
let genContoursEntite = this.getJarvisEnvelopeConvexeEntites(allEntiteRefConcernementContourEntites);
// console.log('genContoursEntite', genContoursEntite);
let points = [];
@ -1617,23 +1696,60 @@ export default {
// }
// }
// },
setPaperDoleances(){
let g = new paper.Group({
pivot: new paper.Point({x:0,y:0}),
name: `doleances`
});
setPaperDoleances(update){
console.log(`setPaperDoleances cid:${this.concernement.id}, update: ${update}`);
let g;
if (update) {
g = this.paper_main_object.children['doleances'];
console.log('REUSING doleances group', g);
} else{
g = new paper.Group({
pivot: new paper.Point({x:0,y:0}),
name: `doleances`
});
}
if (!g) {
console.warn('no doleances group created nor found')
return;
}
console.log('doleances main group: ', g);
this.concernement.doleances.forEach((d) => {
g.addChild(this.setPaperDoleanceSteps(d))
console.log('each doleance, d:', d);
let doleance_group;
console.log('is update: ', update);
if (update) {
doleance_group = g.children[`doleance_${d.id}`];
console.log('doleance_group', doleance_group);
if (doleance_group) {
this.setPaperDoleanceSteps(d, doleance_group);
}else{
g.addChild(this.setPaperDoleanceSteps(d));
}
}else{
g.addChild(this.setPaperDoleanceSteps(d));
}
});
return g;
},
setPaperDoleanceSteps(doleance){
let g = new paper.Group({
pivot: new paper.Point({x:0,y:0}),
name: `doleance_${doleance.id}`,
doleance_id: doleance.id,
visible: false
});
setPaperDoleanceSteps(doleance, groupToUpdate){
console.log(`setPaperDoleanceSteps doleance`, doleance);
console.log(`setPaperDoleanceSteps groupToUpdate`, groupToUpdate);
let g;
if (groupToUpdate) {
g = groupToUpdate;
g.removeChildren();
} else {
g = new paper.Group({
pivot: new paper.Point({x:0,y:0}),
name: `doleance_${doleance.id}`,
doleance_id: doleance.id,
visible: false
});
}
// let doleance = this.concernement.doleances[0];
let all_fields = [
[
@ -1649,9 +1765,9 @@ export default {
}
],
[
'entite_addresse_doleance',
'comment_ennonce_doleance',
'aqui_addresse_doleance',
'entite_adresse_doleance',
'comment_enonce_doleance',
'a_qui_adresse_doleance',
{
fieldname: 'reception_traitement',
fields: [
@ -1870,7 +1986,7 @@ export default {
// adresse de la doleance
if (doleance.entite_addresse_doleance || doleance.aqui_addresse_doleance || doleance.comment_ennonce_doleance) {
if (doleance.entite_adresse_doleance || doleance.a_qui_adresse_doleance || doleance.comment_enonce_doleance) {
g.addChild(new paper.Path.Circle({
center: [this.pos.x - r, this.pos.y],
radius: 3 * this.scale,
@ -2109,8 +2225,9 @@ export default {
} else if(!this.doleance_transition) {
this.concernement.doleances.forEach((d) => {
this.paper_main_object.children.doleances.children[`doleance_${d.id}`].visible = d.id === this.concernement.opened_doleance.id;
})
})
}
}
} else {
// this.paper_main_object.children.doleance_icon.visible = false;
@ -2125,29 +2242,75 @@ export default {
group.children.forEach((item) => {
if (this.opened_entite_id && item.item_id === parseInt(this.opened_entite_id) && item.item_type !== 'entite_hidden') {
// switch symbole definition to hover
item.definition = item.item_type === 'entite' ? this.paper_symbol_definitions.entite_hover : this.paper_symbol_definitions.entite_action_hover;
item.definition = item.item_type === 'entite' ? this.paper_symbol_definitions.entite_hover
: item.item_type === 'entite_inactive' ? this.paper_symbol_definitions.entite_inactive_hover
: this.paper_symbol_definitions.entite_action_hover;
} else {
// switch back symbole definition to normal
if ((!this.hover_elmt || item.item_id !== this.hover_elmt.id) && item.item_type !== 'entite_hidden') {
item.definition = item.item_type === 'entite' ? this.paper_symbol_definitions.entite : this.paper_symbol_definitions.entite_action;
item.definition = item.item_type === 'entite' ? this.paper_symbol_definitions.entite
: item.item_type === 'entite_inactive' ? this.paper_symbol_definitions.entite_inactive
: this.paper_symbol_definitions.entite_action;
}
}
})
}
let labels_group = this.paper_main_object.children['entites'].children['entites_labels'];
if (labels_group) {
labels_group.children.forEach((item) => {
if (this.opened_entite_id && item.item_id === parseInt(this.opened_entite_id) && item.item_type !== 'entite_hidden') {
item.bringToFront();
item.children[0].strokeColor = "#01ffe2";
}else{
// item.children[0].strokeColor = "#fff";
}
})
if (this.paper_main_object.children && this.paper_main_object.children['entites']) {
let labels_group = this.paper_main_object.children['entites'].children['entites_labels'];
if (labels_group) {
labels_group.children.forEach((item) => {
if (this.opened_entite_id && item.item_id === parseInt(this.opened_entite_id) && item.item_type !== 'entite_hidden') {
item.bringToFront();
item.children[0].strokeColor = "#01ffe2";
}else{
// item.children[0].strokeColor = "#fff";
}
})
}
}
}
},
focusOpenedDoleanceStep(){
console.log('focusOpenedDoleanceStep', this.concernement.opened_doleance);
if (this.concernement.has_doleance) {
if (this.map_mode === "doleancer") {
if (this.is_open) {
// focus on opened doleance step
if (this.concernement.opened_doleance.field) {
let paper_doleance = this.paper_main_object.children.doleances.children[`doleance_${this.concernement.opened_doleance.id}`];
// console.log('paper_doleance', paper_doleance);
paper_doleance.children.forEach((step) =>{
// console.log('step.item_type', step.item_type);
let active = false;
if (step.field === this.concernement.opened_doleance.field) {
if(typeof this.concernement.opened_doleance.field_index != 'undefined'){
// we have an index, let find if we have the right step here
if (this.concernement.opened_doleance.field_index === step.field_index) {
active = true;
}
}else{
// we do not have a field index, so it is a single step, so it is active no matter the index
active = true
}
}
if (active) {
// step.data.prevStrokeColor is for hover_elmt watch in MapConcernements.vue
step.data.prevStrokeColor = step.strokeColor = "#01ffe2";
step.bringToFront();
} else {
step.data.prevStrokeColor = step.strokeColor = "#fff";
}
});
}
}
}
}
},
initDoleanceTransition(from, to){
if (!this.doleance_transition) {
@ -2466,21 +2629,29 @@ export default {
if (group_to_hit) {
let result = group_to_hit.hitTest(event.point);
console.log('click result', result);
if (result) {
if (result && result.item.item_id && (result.item.name != "label_click_zone" || this.detailsZoomValue > 2)) {
switch (this.map_mode) {
case "terraindevie":
case "superposition":
case "action":
// we have clicked on an entite
this.$router.push({
name: 'concernement',
params: {cid: this.cid, eid: result.item.item_id},
query: {
mapitemid: this.id,
// superposition_id: this.mapitem.superposition_ids[0]
},
hash: `#${this.map_mode}`,
});
// unfocus any active element to trigger recording if needed
document.activeElement.blur();
// setInterval to let time for editable fields to focus out and record changes
let interval = setInterval(() => {
if (!this.concernement_is_updating_nid) {
clearInterval(interval);
this.$router.push({
name: 'concernement',
params: {cid: this.cid, eid: result.item.item_id},
query: {
mapitemid: this.id,
// superposition_id: this.mapitem.superposition_ids[0]
},
hash: `#${this.map_mode}`,
});
}
}, 1)
break;
case "proximite":
switch (result.item.item_type) {
@ -2511,11 +2682,20 @@ export default {
} else {
// otherwise we close the entite and come back to the concernement
this.$router.push({
name: 'concernement',
hash: `#${this.map_mode}`,
params: {id: this.cid, mapitemid: this.id}
});
// unfocus any active element to trigger recording if needed
document.activeElement.blur();
// setInterval to let time for editable fields to focus out and record changes
let interval = setInterval(() => {
if (!this.concernement_is_updating_nid) {
clearInterval(interval);
this.$router.push({
name: 'concernement',
hash: `#${this.map_mode}`,
params: {id: this.cid, mapitemid: this.id}
});
}
}, 1)
// reset the mousehover
this.resetHoverElmt();
@ -2535,10 +2715,10 @@ export default {
}.bind(this);
/*
* works i correlation with updateDetailsZoomScale()
* works in correlation with updateDetailsZoomScale()
*/
this.paper_main_object.onMouseDrag = async function(event){
if (this.is_open && this.map_mode === 'terraindevie' && this.concernement.can_update) {
if (this.is_open && this.map_mode === 'terraindevie') { // && this.concernement.can_update
// console.log('paper concernement onMouseDrag', event, this);
event.stopPropagation();
event.preventDefault();
@ -2597,7 +2777,7 @@ export default {
this.recordNewEntitePos(pid, af, mm, p)
.then((parag) => {
// then reload value
// redrawing entites is handle by watch concernement.entites
// redrawing entites is handled by watch concernement.entites
this.reloadConcernementEntites(this.concernement.id)
.then(() => {
this.wait = false;
@ -2870,7 +3050,9 @@ export default {
x: (this.canvas.width - this.cartouch_width) / 2,
y: this.canvas.height / 2
};
this.constraint.pointA = this.pos;
if (this.constraint) {
this.constraint.pointA = this.pos;
}
console.log('resetMapItemPosition', this.cartouch_width, this.pos);
Matter.Body.setPosition(this.body, this.pos);
},

View File

@ -52,12 +52,13 @@ export default {
},
methods: {
parseInfos(){
// console.log('mapPopup infos', this.infos);
console.log('mapPopup infos', this.infos);
switch (this.infos.type) {
case 'concernement':
this.concernement = this.concernementsByID[this.infos.cid];
break;
case 'entite':
case 'entite_inactive':
case 'entite_proximite':
case 'entite_superpose':
case 'entite_action':
@ -156,7 +157,7 @@ export default {
</div>
</section>
<section v-if="infos.type === 'entite' || infos.type === 'entite_action' || infos.type === 'superposition' || infos.type === 'entite_superpose' || infos.type === 'entite_proximite'" class="entite-map-popup">
<section v-if="infos.type === 'entite' || infos.type === 'entite_inactive' || infos.type === 'entite_action' || infos.type === 'superposition' || infos.type === 'entite_superpose' || infos.type === 'entite_proximite'" class="entite-map-popup">
<template
v-for="(entite, index) of entites"
:key="index"

View File

@ -61,6 +61,7 @@ export default {
'concernements',
'concernementsByID',
'opened_concernement',
'concernement_is_updating_nid',
'opened_entite_id',
'opened_recit',
'allSuperpositions',
@ -122,11 +123,17 @@ export default {
this.paper.view.onClick = function(event) {
// console.log("view onClick", this, event.target);
if(event.target._id === "paper-view-0") {
this.resetConcernementOpened();
this.$router.push({
name: 'home',
hash: `#${this.map_mode}`
});
// // unfocus any active element to trigger recording if needed
// document.activeElement.blur();
// // setTimeout to let time for editable fields to focus out and record changes
// setTimeout(() => {
// this.resetConcernementOpened();
// this.$router.push({
// name: 'home',
// hash: `#${this.map_mode}`
// });
// }, 1);
this.closeConcernement();
}
}.bind(this);
@ -405,8 +412,10 @@ export default {
// this.addPaperSymbolDefinition('doleance_icon', this.setPaperDoleanceICONSymbol());
if (!update) {
this.addPaperSymbolDefinition('entite', this.setPaperEntiteSymbol());
this.addPaperSymbolDefinition('entite_hidden', this.setPaperHiddenEntiteSymbol());
this.addPaperSymbolDefinition('entite_hover', this.setPaperEntiteHoverSymbol());
this.addPaperSymbolDefinition('entite_inactive', this.setPaperInactiveEntiteSymbol());
this.addPaperSymbolDefinition('entite_inactive_hover', this.setPaperInactiveEntiteHoverSymbol());
this.addPaperSymbolDefinition('entite_hidden', this.setPaperHiddenEntiteSymbol());
this.addPaperSymbolDefinition('entite_action_icon', this.setPaperEntiteActionIconSymbol());
this.addPaperSymbolDefinition('entite_action', this.setPaperEntiteActionSymbol());
this.addPaperSymbolDefinition('entite_action_hover', this.setPaperEntiteActionHoverSymbol());
@ -1089,6 +1098,16 @@ export default {
strokeWidth:2
})
},
setPaperEntiteHoverSymbol(){
return new paper.Path.Circle({
pivot: new paper.Point({x:0,y:0}),
center: [0,0],
radius: 0.5,
fillColor: '#01ffe2',
strokeColor: 'rgba(255,255,255,0.05)',
strokeWidth:2
})
},
setPaperHiddenEntiteSymbol(){
return new paper.Path.Circle({
pivot: new paper.Point({x:0,y:0}),
@ -1099,16 +1118,74 @@ export default {
strokeWidth:2
})
},
setPaperEntiteHoverSymbol(){
setPaperInactiveEntiteSymbol(){
return new paper.Path.Circle({
pivot: new paper.Point({x:0,y:0}),
center: [0,0],
radius: 0.5,
fillColor: '#01ffe2',
strokeColor: 'rgba(255,255,255,0.05)',
radius: 0.5, //0.3
fillColor: '#F00',
strokeColor: 'rgba(255,0,0,0.05)',
strokeWidth:2
})
},
setPaperInactiveEntiteHoverSymbol(){
// let svgIcon = paper.project.importSVG(iconAction);
// svgIcon.strokeColor = '#01ffe2';
// svgIcon.strokeWidth = 0.25;
// svgIcon.scale(0.15);
// svgIcon.fillColor = null;
// svgIcon.position = {x:0, y:0};
// let circle = new paper.Path.Circle({
// radius: 3,
// fillColor: 'rgba(255,255,255,0.05)'
// })
// return new paper.Group({
// children: [circle, svgIcon],
// name: 'action_icon'
// });
let children = [];
let ray = 0.7; //this.map_item_ray;
// let pos = {x:0, y:0};
// let strokewidth = 0.4;
// children.push(new paper.Path.Line({
// from: [- ray, ray],
// to: [ray, - ray],
// strokeColor: '#01ffe2',
// strokeWidth: strokewidth
// }));
// children.push(new paper.Path.Line({
// from: [ray, ray],
// to: [- ray, - ray],
// strokeColor: '#01ffe2',
// strokeWidth: strokewidth
// }));
children.push(new paper.Path.Circle({
radius: ray/2,
fillColor: '#F00'
}))
children.push(new paper.Path.Circle({
radius: ray * 1.2,
strokeColor: '#01ffe2',
strokeWidth: 0.2,
fillColor: 'rgba(0,0,0,0)'
}))
children.push(new paper.Path.Circle({
radius: ray,
fillColor: 'rgba(255,255,255,0.01)'
}))
return new paper.Group({
children: children,
name: 'action_icon'
});
},
setPaperEntiteActionIconSymbol(){
// let svgIcon = paper.project.importSVG(iconAction);
// svgIcon.strokeWidth = 0.8;
@ -1473,6 +1550,26 @@ export default {
});
wall_rects.addChildren(children);
}
},
closeConcernement(){
// unfocus any active element to trigger recording if needed
document.activeElement.blur();
// setTimeout to let time for editable fields to focus out and record changes
this.waitForUpdatingEnded();
},
waitForUpdatingEnded(){
setTimeout(() => {
if (!this.concernement_is_updating_nid) {
this.resetConcernementOpened();
this.$router.push({
name: 'home',
hash: `#${this.map_mode}`
});
} else {
this.waitForUpdatingEnded();
}
}, 1);
}
},
beforeUpdate () {
@ -1544,8 +1641,9 @@ export default {
<li>
<a
title="cercle politique" href="#doleancer" @click="setMapMode('doleancer')"
:class="{ disabled: opened_concernement && !opened_concernement.has_doleance, active: map_mode === 'doleancer'}"
:class="{ active: map_mode === 'doleancer'}"
>
<!-- disabled: opened_concernement && !opened_concernement.has_doleance, -->
<span class="icon doleancer"/> <span class="label"> cercle politique</span>
</a>
</li>

View File

@ -29,7 +29,7 @@ export default {
// let hue = Math.floor(Math.random()*360)
for (let j = 0; j < num_colors; j++) {
let pos = (1/num_colors*j + 1/num_colors/3 + Math.random()*1/num_colors/3)*100;
console.log('gradient pos', pos);
// console.log('gradient pos', pos);
colors.push({
color: this.getRandBGColor(),
@ -43,7 +43,7 @@ export default {
// })
gradients.push(colors)
}
console.log('gradients', gradients);
// console.log('gradients', gradients);
let cssgrad = '';
gradients.forEach((gradient, index) => {
@ -55,7 +55,7 @@ export default {
cssgrad += index < gradients.length-1 ? '),' : ')';
});
// cssgrad += ';';
console.log('cssgrad', cssgrad);
// console.log('cssgrad', cssgrad);
gradientBackground.style.background = cssgrad;
},
getRandBGColor (hue) {

File diff suppressed because it is too large Load Diff

View File

@ -211,8 +211,10 @@ export default {
...mapActions(ConcernementsStore, ['setActiveRevision',
'setDetailsZoomValue',
'loadConcernements',
'setConcernementIsUpdating',
'reloadConcernements',
'reloadConcernementEntites',
'reloadConcernementField',
'reloadProximites'
]),
...mapActions(UserStore, ['getUserEntitees']),
@ -233,6 +235,14 @@ export default {
.then(({data: { data: { entite }}}) => {
console.log('load entite loaded', entite)
this.entite = entite;
// record the paragraphe field id from concernement wher the entity is referenced
this.concernement.entites.forEach(parag_entite => {
if (parag_entite.entite && parag_entite.entite.id === this.entite.id) {
this.parag_entite = parag_entite;
}
});
// this.setProxSuggestions()
this.checkForUserProxmite();
})
@ -250,6 +260,22 @@ export default {
this.headerreduced = false;
}
},
// triggered when focus out and gql patch xhr triggered
onFieldIsUpdating(cid){
this.setConcernementIsUpdating(cid);
},
// triggered when gql patch done
onFieldUpdated(cid){
this.setConcernementIsUpdating(null);
this.reloadConcernementEntites(cid);
},
concernementFieldIsUpdating(field){
this.setConcernementIsUpdating(this.cid);
},
concernementFieldUpdated(field){
this.setConcernementIsUpdating(null);
this.reloadConcernementField(this.cid, field);
},
onContentEditableFocusOut(e){
console.log('onContentEditableFocusOut', e);
let new_field_content = e.target.innerText;
@ -300,7 +326,7 @@ export default {
resolve(data)
})
.catch(error => {
console.warn(`Issue with post new paragraph source`, error)
console.warn(`Issue with post new node cercle_politique`, error)
reject(error)
})
})
@ -505,7 +531,7 @@ export default {
</script>
<template>
<CartoucheLayout ref="cartouche_layout" :cid="cid" @main_scrolled="onMainScrolled">
<CartoucheLayout ref="cartouche_layout" :cid="cid" :eid="eid" @main_scrolled="onMainScrolled">
<template v-slot:header>
<div class="entite">
<!-- TODO update entite with revisions -->
@ -523,7 +549,8 @@ export default {
id: this.entite.id,
field: {field_name: 'title', value:'value'}
}"
v-on:updated="reloadConcernementEntites(cid)"/>
v-on:updating="onFieldIsUpdating(cid)"
v-on:updated="onFieldUpdated(cid)"/>
<!-- proximité -->
<section
@ -567,34 +594,44 @@ export default {
</div>
</section>
<!-- agissante -->
<CheckboxEditable
v-if="entite && entite.can_update"
:checked="entite.agissante"
label="Entité action"
:data="{
entitytype: 'node',
bundle: 'entite',
nid: this.entite.id,
field: 'field_entite_agissante'
}" />
<section class="entite-params" v-if="entite && entite.can_update">
<!-- active -->
<CheckboxEditable
:checked="this.parag_entite.active"
label="Active"
:data="{
entitytype: 'paragraph',
bundle: 'entite_concernement',
id: this.parag_entite.id,
field: 'field_active'}"
v-on:updated="reloadConcernementEntites(cid)"/>
<SelectEditable
v-if="entite && entite.can_update"
label="Confidentialité"
:value="entite.confidentialite"
:options="{
'confidentialite_prive': 'privé',
'confidentialite_interne': 'interne',
'confidentialite_public': 'public'
}"
:data="{
entitytype: 'node',
bundle: 'entite',
nid: this.entite.id,
field: 'field_confidentialite'
}" />
<!-- agissante -->
<CheckboxEditable
:checked="entite.agissante"
label="Entité action"
:data="{
entitytype: 'node',
bundle: 'entite',
id: this.entite.id,
field: 'field_entite_agissante'}"
v-on:updated="reloadConcernementEntites(cid)"/>
<!-- confidentialité -->
<SelectEditable
label="Confidentialité"
:value="entite.confidentialite"
:options="{
'confidentialite_prive': 'privé',
'confidentialite_interne': 'interne',
'confidentialite_public': 'public'}"
:data="{
entitytype: 'node',
bundle: 'entite',
nid: this.entite.id,
field: 'field_confidentialite'}"
v-on:updated="reloadConcernementEntites(cid)"/>
</section>
</div>
@ -617,7 +654,9 @@ export default {
bundle: 'concernement',
id: this.concernement.id,
field: {field_name: 'field_description', value:'value'}
}" />
}"
v-on:updating="concernementFieldIsUpdating('description')"
v-on:updated="concernementFieldUpdated('description')"/>
</section>
<section v-if="concernement.caillou || concernement.can_update" class="caillou">
@ -633,7 +672,9 @@ export default {
bundle: 'concernement',
id: this.concernement.id,
field: {field_name: 'field_caillou', value:'value'}
}" />
}"
v-on:updating="concernementFieldIsUpdating('caillou')"
v-on:updated="concernementFieldUpdated('caillou')"/>
</section>
<template v-if="concernement.can_update">
@ -648,7 +689,15 @@ export default {
</template>
<!-- entite -->
<Entite v-if="entite" :concernement="concernement" :entite="entite" :eid="eid" v-on:reloadEntite="loadEntite"/>
<Entite
v-if="entite"
:concernement="concernement"
:entite="entite"
:eid="eid"
v-on:reloadEntite="loadEntite"/>
<!-- v-on:updating="onFieldIsUpdating(cid)"
v-on:updated="onFieldUpdated(cid)" -->
</template>
<template v-slot:footer>

View File

@ -38,17 +38,24 @@ export default {
},
save(checked){
// console.log('save csrf_token', this.csrf_token);
const params = {
let params = {
type: this.data.bundle,
nid: [{"value":this.data.nid}],
// nid: [{"value":this.data.nid}],
[this.data.field]: {value: checked}
};
if (this.data.entitytype === 'node') {
params.nid = [{"value":this.data.id}];
} else {
params.id = [{"value":this.data.id}];
}
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
REST.patch(`/node/${this.data.nid}?_format=json`, params, configs)
let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
.then(({ data }) => {
console.log('user REST post node data', data)
console.log(`checkboxEditable REST patch ${this.data.entitytype} data`, data)
// TODO if success update the data in pinia
// this.reloadConcernements();
this.$emit('updated');

View File

@ -29,7 +29,7 @@ export default {
default : 'Ajouter du texte'
}
},
emits: ['updated'],
emits: ['updating', 'updated'],
data(){
return {
editor: null,
@ -74,6 +74,7 @@ export default {
}
},
save(content){
this.$emit('updating');
// console.log('save csrf_token', this.csrf_token);
const params = {
type: this.data.bundle,

View File

@ -0,0 +1,152 @@
<script>
import REST from '@api/rest-axios'
import { mapActions, mapState } from 'pinia'
import { ConcernementsStore } from '@stores/concernements'
import { UserStore } from '@stores/user'
import VueDatePicker from '@vuepic/vue-datepicker';
import '@vuepic/vue-datepicker/dist/main.css';
export default {
props: {
tag: String,
value: String,
end_value : {
type : String,
default : null
},
contenteditable : {
type : [Boolean, String],
default : true
},
mode : {
type : String,
default : null
},
data: Object,
placeholder : {
type : String,
default : 'Choisir une date'
}
},
emits: ['updated'],
data(){
return {
date: null
}
},
computed: {
...mapState(UserStore,['csrf_token']),
attrs() {
// console.log(`this.mode: ${this.mode}`);
let a = {};
if (this.mode && this.mode === 'range') {
a.range = true;
}
return a;
}
},
created () {
console.log('DateEditable created');
this.initDateValues();
},
// updated() {
// console.log('DateEditable updated');
// this.initDateValues();
// },
mounted () {
},
beforeUnmount() {
},
watch: {
value (n, o) {
console.log(`dateEditable watch value n, o`, n, o);
if(n !== o){
this.initDateValues();
}
},
},
methods: {
...mapActions(ConcernementsStore, ['reloadConcernements']),
initDateValues(){
if (this.value) {
if (this.mode && this.mode === 'range') {
this.date = [this.value, this.end_value]
}else{
this.date = this.value;
}
} else {
this.date = null;
}
},
onDateSelected(modeldata){
console.log('onDateSelected, modeldata', modeldata);
this.save();
},
save(){
console.log('save csrf_token', this.csrf_token);
console.log('save this.data', this.data);
console.log('save this.date', this.date);
let params = {
type: this.data.bundle,
};
if (this.data.entitytype === 'node') {
params.nid = [{"value":this.data.id}];
} else {
params.id = [{"value":this.data.id}];
}
if (this.mode && this.mode === "range") {
params[this.data.field.field_name] = [{
value: this.date[0],
end_value: this.date[1]
}]
} else {
params[this.data.field.field_name] = [{
value: this.date
}]
}
const configs = {
headers: {'X-CSRF-Token': this.csrf_token}
};
// url is not the same between nodes and others entities
let url_base = `/${this.data.entitytype === 'node' ? '' : 'entity/'}${this.data.entitytype}`;
// call the api
REST.patch(`${url_base}/${this.data.id}?_format=json`, params, configs)
.then(({ data }) => {
console.log('user REST post node data', data)
this.$emit('updated');
})
.catch(error => {
console.warn(`Issue with patch ${this.data.entitytype} ${this.data.bundle}`, error)
Promise.reject(error)
})
}
},
components: {
VueDatePicker
}
}
</script>
<template>
<VueDatePicker
v-if="contenteditable"
v-model="date"
model-type="yyyy-MM-dd"
format="dd-MM-yyyy"
:enable-time-picker="false"
:clearable="false"
@update:model-value="onDateSelected"
:placeholder="placeholder"
v-bind="attrs"/>
<span v-else class="date">{{ value }}</span>
</template>

View File

@ -51,11 +51,14 @@ export default {
this.saveNewFile(file);
},
saveNewFile(file){
const filename = file.name.normalize('NFD').replace(/[\u0300-\u036f]/g, "").replace(/[^a-zA-Z0-9_\-\.]/g, "_"); // Normalisation Unicode et suppression des accents
console.log('filename', filename);
const configs = {
headers: {
'X-CSRF-Token': this.csrf_token,
'Content-Type': 'application/octet-stream',
'Content-Disposition': `file; filename="${file.name}"`,
'Content-Disposition': `file; filename="${filename}"`,
},
};

View File

@ -71,12 +71,16 @@ export default {
const $li = this.$refs.links_list.children[i];
if ($li.querySelector('input.url').value) {
let title = $li.querySelector('input.title').value;
let url = $li.querySelector('input.url').value;
let url = $li.querySelector('input.url').value;
console.log(`title ${title}, url ${url}`);
list.push({
title: title,
uri: url
});
tobesaved = (typeof this.links[i] === 'undefined' || title !== this.links[i].title || url !== this.links[i].url);
console.log(`title ${title} | this.links[i].title ${this.links[i].title}`);
if (!tobesaved) {
tobesaved = (typeof this.links[i] === 'undefined' || title !== this.links[i].title || url !== this.links[i].url);
}
}
}
if (!tobesaved) {

View File

@ -9,13 +9,14 @@ import { mdiHeadphones } from '@mdi/js';
import ContentEditable from '@components/editable/ContentEditable.vue';
export default {
props: ['cid'],
props: ['cid','eid'],
emits: ['main_scrolled'],
data(){
return {
headphones_path: mdiHeadphones,
mainscrolled: false,
headerreduced: false,
entite: false
}
},
created () {
@ -25,18 +26,18 @@ export default {
},
mounted () {
// console.log('cartouche layout mounted', this);
this.$refs.cartouche_main.addEventListener('scroll', (event) => {
// console.log('main is scrolling', event);
let $main = event.target;
let scrolled = $main.scrollTop > 0;
this.$emit('main_scrolled', scrolled);
// TODO how to make this failsafe limit responsive ?
if(scrolled && $main.scrollHeight > 900){
this.headerreduced = true;
} else {
this.headerreduced = false;
}
})
// this.$refs.cartouche_main.addEventListener('scroll', (event) => {
// console.log('main is scrolling', event);
// let $main = event.target;
// let scrolled = $main.scrollTop > 0;
// this.$emit('main_scrolled', scrolled);
// // TODO how to make this failsafe limit responsive ?
// if(scrolled && $main.scrollHeight > 900){
// this.headerreduced = true;
// } else {
// this.headerreduced = false;
// }
// })
},
computed: {
...mapState(ConcernementsStore,['concernementsByID', 'opened_concernement', 'ct_concernement']),
@ -51,10 +52,29 @@ export default {
}
},
deep: true
},
eid: {
handler (n, o) {
console.log(`TerrainDeVie watch eid o:${o}, n:${n}`);
if (n) {
this.entite = true;
}else{
this.entite = false;
}
},
deep: true
}
},
methods: {
...mapActions(ConcernementsStore,['setMapMode']),
...mapActions(ConcernementsStore,['setMapMode',"setConcernementIsUpdating","reloadConcernementField"]),
// triggered when focus out and gql patch xhr triggered
concernementFieldIsUpdating(field){
this.setConcernementIsUpdating(this.cid);
},
concernementFieldUpdated(field){
this.setConcernementIsUpdating(null);
this.reloadConcernementField(this.cid, field);
}
},
components: {
SvgIcon,
@ -66,19 +86,21 @@ export default {
<template>
<header ref="cartouche_header">
<div class="concernement-cartouche-icons">
<label :class="{ hidden: headerreduced }">{{ ct_concernement.title.description }}</label>
<label class="concernement-label">{{ ct_concernement.title.description }}</label>
<!-- :class="{ hidden: headerreduced }" -->
<ContentEditable
tag="h2"
:value="concernement.title"
:class="{ ellipsed: headerreduced }"
:contenteditable="concernement.can_update"
:class="{ ellipsed: entite }"
:contenteditable="(concernement.can_update && !entite)"
:data="{
entitytype: 'node',
bundle: 'concernement',
id: this.concernement.id,
field: {field_name: 'title', value:'value'}
}" />
}"
v-on:updating="concernementFieldIsUpdating('title')"
v-on:updated="concernementFieldUpdated('title')"/>
<!-- <nav class="icons">

View File

@ -1,3 +1,4 @@
// import Vue from "vue"
import { createApp } from 'vue'
import { createPinia } from 'pinia'
@ -14,10 +15,36 @@ import './assets/main.scss'
import VuePlyr from 'vue-plyr'
import 'vue-plyr/dist/vue-plyr.css'
// import * as Sentry from "@sentry/browser";
// import * as Integrations from "@sentry/integrations";
// Sentry.init({
// dsn: "https://d1780f9da2fc4dd28c9c17cb344a088f@frontlog.figli.io/2",
// integrations: [new Integrations.Vue()],
// });
import * as Sentry from "@sentry/vue";
import { createSentryPiniaPlugin } from "@sentry/vue";
const app = createApp(App)
Sentry.init({
app,
dsn: "https://d1780f9da2fc4dd28c9c17cb344a088f@frontlog.figli.io/2",
integrations: [
Sentry.browserTracingIntegration({ router }),
],
tracesSampleRate: 0.01,
normalizeDepth: 10, // Or however deep you want your state context to be.
environment: "prod",
// release : '1'
release: __SENTRY_RELEASE__
});
const pinia = createPinia()
pinia.use( ({store}) => { store.router = router } )
pinia.use(createSentryPiniaPlugin());
app.use(pinia)
app.use(router)
// app.use(VueCollapsiblePanel)
@ -25,3 +52,5 @@ app.use(VuePlyr, {
plyr: {}
})
app.mount('#app')
// Sentry.captureMessage("sentry vue is working", "info");

View File

@ -50,6 +50,7 @@ export const ConcernementsStore = defineStore({
concernements_are_loading: false,
concernement_active_revision: null,
detailsZoomValue: 1,
concernement_is_updating_nid: null
}),
getters: {
@ -74,7 +75,7 @@ export const ConcernementsStore = defineStore({
// console.log('ast', ast);
GQL.post('', { query: print(ast) })
.then(({ data : { data : { allconcernements } } }) => {
console.log('loadconcernements loaded', allconcernements)
console.log('|||||||||||| loadconcernements loaded ||||||||||||||||||', allconcernements)
this.concernements = [];
this.parseConcernements(allconcernements, true)
this.concernements_loaded = true;
@ -108,73 +109,80 @@ export const ConcernementsStore = defineStore({
if (!concernement.entites_byid[entite.entite.id]) {
concernement.entites_byid[entite.entite.id] = entite;
}
// record entite agissante
if (entite.entite.agissante) {
if (!concernement.entitesagissantes_byid[entite.entite.id]) {
concernement.entitesagissantes_byid[entite.entite.id] = entite;
}
concernement.has_agissantes = true;
}
// record a flat list of all entités of all concernement for map-popup
if (!this.allEntitesById[entite.entite.id]) {
this.allEntitesById[entite.entite.id] = entite;
this.allEntitesById[entite.entite.id].cid = concernement.id;
}
// PROXIMITES
if (entite.entite.proximite.length) {
// console.log("proximite", entite.entite.proximite);
concernement.has_proximites = true;
}
// SUPERPOSITIONS
if (entite.entite.superposition.length) {
// create properties for later
if (init) {
concernement.superpositions = {};
concernement.superposition_constraints_id = {};
concernement.all_superposed_concernements_id = [];
concernement.superposed_mapitem_id_by_mapitem_id = {};
// Do not integrate the entite if not active
if(entite.active){
// record entite agissante
if (entite.entite.agissante) {
if (!concernement.entitesagissantes_byid[entite.entite.id]) {
concernement.entitesagissantes_byid[entite.entite.id] = entite;
}
concernement.has_agissantes = true;
}
entite.entite.superposition.forEach(entite_superpose => {
// console.log(`superposition eid:${entite.entite.id}, teid:${entite_superpose.id}`);
let already_recorded = false;
// loop through all already recorded superposition to complete the array instead of create duplicates
// TODO check if target cid and eid are accessible before recording the superposition
// check if half of the superpositions is already recorded, if yes complete it (add the missing concernement id)
for(let superposition of temp_allSuperpositions) {
for(let superposition_item of superposition) {
if (superposition_item.eid === entite.entite.id && !superposition_item.cid) {
// console.log(`already_recorded, eid:${entite.entite.id}, teid:${entite_superpose.id}`, entite.entite.title);
already_recorded = true;
superposition_item.cid = concernement.id;
// PROXIMITES
if (entite.entite.proximite.length) {
// console.log("proximite", entite.entite.proximite);
concernement.has_proximites = true;
}
// SUPERPOSITIONS
if (entite.entite.superposition.length) {
// create properties for later
if (init) {
concernement.superpositions = {};
concernement.superposition_constraints_id = {};
concernement.all_superposed_concernements_id = [];
concernement.superposed_mapitem_id_by_mapitem_id = {};
}
entite.entite.superposition.forEach(entite_superpose => {
// console.log(`superposition eid:${entite.entite.id}, teid:${entite_superpose.id}`);
let already_recorded = false;
// loop through all already recorded superposition to complete the array instead of create duplicates
// TODO check if target cid and eid are accessible before recording the superposition
// check if half of the superpositions is already recorded, if yes complete it (add the missing concernement id)
for(let superposition of temp_allSuperpositions) {
for(let superposition_item of superposition) {
if (superposition_item.eid === entite.entite.id && !superposition_item.cid) {
// console.log(`already_recorded, eid:${entite.entite.id}, teid:${entite_superpose.id}`, entite.entite.title);
already_recorded = true;
superposition_item.cid = concernement.id;
break;
}
}
if (already_recorded) {
break;
}
}
if (already_recorded) {
break;
// if not already recorded, add it to the array. It is incomplete has it's missing one concernement id wich will be filled in next loops
if (!already_recorded) {
// console.log(`NOT already_recorded, eid:${entite.entite.id}, teid:${entite_superpose.id}`, entite.entite.title);
let s = [
{
cid: concernement.id,
eid: entite.entite.id
},
{
cid: null,
eid: entite_superpose.id
}
];
// concernement.superpositions.push(s);
temp_allSuperpositions.push(s);
}
}
// if not already recorded, add it to the array. It is incomplete has it's missing one concernement id wich will be filled in next loops
if (!already_recorded) {
// console.log(`NOT already_recorded, eid:${entite.entite.id}, teid:${entite_superpose.id}`, entite.entite.title);
let s = [
{
cid: concernement.id,
eid: entite.entite.id
},
{
cid: null,
eid: entite_superpose.id
}
];
// concernement.superpositions.push(s);
temp_allSuperpositions.push(s);
}
})
})
}
}
}
}); // end of concernement.entites loop
@ -302,6 +310,9 @@ export const ConcernementsStore = defineStore({
// console.log(`end of parsing concernements`);
},
setConcernementIsUpdating(nid){
this.concernement_is_updating_nid = nid;
},
reloadConcernements () {
console.log('reloadConcernements');
return new Promise((resolve, reject) => {
@ -317,7 +328,7 @@ export const ConcernementsStore = defineStore({
},
reloadConcernementEntites(nid){
let tmp_conc = this.concernementsByID[nid];
console.log(`reloadConcernementEntites len: ${tmp_conc.entites.length} revision: ${tmp_conc.revision_id} nid: ${nid}`);
console.log(`reloadConcernementEntites len: ${tmp_conc.entites.length} revision: ${tmp_conc.revision_id} nid: ${nid} ${Math.random()*10000}`);
return new Promise((resolve, reject) => {
const ast = gql`{
concernement(id:${nid}) {
@ -325,8 +336,10 @@ export const ConcernementsStore = defineStore({
entites {
id
revision_id
active
menacemaintien
actuelfuture
prise
entite {
title
id
@ -346,6 +359,9 @@ export const ConcernementsStore = defineStore({
revision_id
changed
entites {
id
revision_id
active
menacemaintien
prise
actuelfuture
@ -377,15 +393,17 @@ export const ConcernementsStore = defineStore({
// records and/or merge into general object and on conernement entitites_byid
tmp_conc.entites.forEach(entite => {
entite.cid = tmp_conc.id;
if (this.allEntitesById[entite.entite.id]) {
_assign(this.allEntitesById[entite.entite.id], entite);
}else{
this.allEntitesById[entite.entite.id] = entite;
}
if (tmp_conc.entites_byid[entite.entite.id]) {
_assign(tmp_conc.entites_byid[entite.entite.id], entite);
}else{
tmp_conc.entites_byid[entite.entite.id] = entite;
if(entite.entite){
if (this.allEntitesById[entite.entite.id]) {
_assign(this.allEntitesById[entite.entite.id], entite);
}else{
this.allEntitesById[entite.entite.id] = entite;
}
if (tmp_conc.entites_byid[entite.entite.id]) {
_assign(tmp_conc.entites_byid[entite.entite.id], entite);
}else{
tmp_conc.entites_byid[entite.entite.id] = entite;
}
}
});
// add and/or merge revisions
@ -415,9 +433,36 @@ export const ConcernementsStore = defineStore({
})
})
},
reloadConcernementField(nid, field){
console.log('reloadConcernementField', nid, field);
// let tmp_conc = this.concernementsByID[nid];
return new Promise((resolve, reject) => {
const ast = gql`{
concernement(id:${nid}) {
id
${field}
}
}
`
GQL.post('', { query: print(ast) })
.then(({ data : { data : { concernement } } }) => {
console.log(`reloadConcernementField loaded ${field}`, concernement)
let tmp_conc = this.concernementsByID[concernement.id];
// merge old concernement besoins with new once
_merge(tmp_conc, concernement);
resolve(concernement);
})
.catch(error => {
console.warn('Issue with reloadConcernementField', error)
reject(error);
Promise.reject(error)
})
});
},
reloadConcernementBesoins(nid){
let tmp_conc = this.concernementsByID[nid];
console.log(`reloadConcernementEntites len: ${tmp_conc.entites.length} revision: ${tmp_conc.revision_id} nid: ${nid}`);
// console.log(`reloadConcernementBesoins len: ${tmp_conc.entites.length} revision: ${tmp_conc.revision_id} nid: ${nid}`);
return new Promise((resolve, reject) => {
const ast = gql`{
concernement(id:${nid}) {
@ -532,6 +577,127 @@ export const ConcernementsStore = defineStore({
})
});
},
reloadConcernementCerclePol(nid){
// let tmp_conc = this.concernementsByID[nid];
console.log(`reloadConcernementCerclePol nid: ${nid} ${Math.random()*10000}`);
return new Promise((resolve, reject) => {
const ast = gql`{
concernement(id:${nid}) {
id
doleances {
id
author
bundle
path
title
uuid
#1
date_leprobleme {
start
}
leprobleme
lenquete
groupesinterets {
id
revision_id
date {
end
start
}
groupe_interets
accorder_interets
formuler
}
#2
date_adresse {
start
}
entite_adresse_doleance
comment_enonce_doleance
a_qui_adresse_doleance
reception_traitement {
id
revision_id
date {
end
start
}
entite_adressee
doleance_formulee
traite_doleance
entite_recoit_doleance
}
#3
date_decision {
start
}
entites_decisionnaires
decision_formulee
mise_en_oeuvre_decision {
id
revision_id
date {
end
start
}
entite_adresse_decision
formule_decision
entite_metenoeuvre_decisio
}
#4
date_application {
start
}
entite_adresse_application
aqui_adresse_decision
comment_formule_decision
receptions_et_applications {
id
revision_id
date {
end
start
}
applique_decision
formule_decision_applic
entite_recoit_decision
}
probleme_initial_resolu
oui_nouvelle_situation
non_adresse_doleance
}
}
}
`
// console.log('ast', ast);
GQL.post('', { query: print(ast) })
.then(({ data : { data : { concernement } } }) => {
console.log(`reloadConcernementCerclePol loaded len: ${concernement.doleances.length} revision: ${concernement.revision_id}`, concernement)
let tmp_conc = this.concernementsByID[concernement.id];
// merge old concernement entites with new once
_assign(tmp_conc.doleances, concernement.doleances);
// redefine opened doleance if needed
tmp_conc.has_doleance = tmp_conc.doleances.length ? true : false;
if (tmp_conc.has_doleance) {
// console.log('concernement has doleance', tmp_conc.doleances);
if (!tmp_conc.opened_doleance) {
tmp_conc.opened_doleance = {
id: tmp_conc.doleances[0].id
};
}
}
// resolve
resolve(concernement);
})
.catch(error => {
console.warn('Issue with reloadConcernementCerclePol', error)
reject(error);
Promise.reject(error)
})
});
},
loadContentTypeDefinition () {
const body = {
query: `
@ -644,7 +810,7 @@ export const ConcernementsStore = defineStore({
openCloseConcernements (cid, mi_id) {
console.log(`openCloseConcernements cid: ${cid}, mi_id: ${mi_id}`);
var state;
let mapitem_id = mi_id ? mi_id : this.concernementsByID[cid].mapitems_ids[0];
let mapitem_id = mi_id ? mi_id : cid ? this.concernementsByID[cid].mapitems_ids[this.concernementsByID[cid].mapitems_ids.length -1] : null;
this.opened_concernement = null;
this.opened_recit = null;
this.concernements.forEach((c, i) => {
@ -692,7 +858,7 @@ export const ConcernementsStore = defineStore({
// })
},
setOpenedDoleance(cid, did){
console.log(`setOpenedDoleance(${cid}, ${did})`, cid, did);
console.log(`setOpenedDoleance cid:${cid}, did:${did})`, cid, did);
this.concernementsByID[cid].opened_doleance = {id: did};
// console.log('this.opened_concernement.opened_doleance', this.opened_concernement.opened_doleance);
},

View File

@ -40,7 +40,8 @@ export default {
...mapState(ConcernementsStore,['map_mode',
'opened_concernement',
'concernements_loaded',
'allSuperpositions_clustered']),
'allSuperpositions_clustered',
'concernement_is_updating_nid']),
...mapState(CommonStore,['cartouch_width']),
//
main_cid_eid () {
@ -203,7 +204,20 @@ export default {
},
closeConcernement(){
this.resetConcernementOpened();
// unfocus any active element to trigger recording if needed
document.activeElement.blur();
// setTimeout to let time for editable fields to focus out and record changes
this.waitForUpdatingEnded();
},
waitForUpdatingEnded(){
setTimeout(() => {
if (!this.concernement_is_updating_nid) {
this.resetConcernementOpened();
} else {
this.waitForUpdatingEnded();
}
}, 1);
}
},
components: {
@ -216,7 +230,7 @@ export default {
</script>
<template>
<section v-if="opened_concernement" class="concernement">
<section v-if="opened_concernement" class="concernement" :class="{ 'entity-opened': main_cid_eid.eid }">
<TerrainDeVie v-if="map_mode === 'terraindevie' || map_mode === 'action' || map_mode === 'superposition' || map_mode === 'proximite'" :cid="main_cid_eid.cid" :eid="main_cid_eid.eid"/>
<PuissanceAgir v-if="map_mode === 'puissancedagir'" :cid="cid"/>
<Doleancer v-if="map_mode === 'doleancer'" :cid="cid"/>

View File

@ -5,6 +5,21 @@ import vue from '@vitejs/plugin-vue'
import graphql from '@rollup/plugin-graphql';
import { viteRequire } from 'vite-require'
import svgLoader from 'vite-svg-loader'
import { sentryVitePlugin } from "@sentry/vite-plugin";
import { execSync } from 'child_process'
require('dotenv').config();
// Get short Git commit hash
function getGitCommitHash() {
try {
return execSync('git rev-parse --short HEAD').toString().trim()
} catch (e) {
console.warn('Could not retrieve Git commit hash')
return 'unknown'
}
}
const release = `ouatterrir@${getGitCommitHash()}`
// https://vitejs.dev/config/
export default defineConfig({
@ -14,7 +29,18 @@ export default defineConfig({
whitespace: 'preserve'
}
}
}), graphql(), viteRequire(), svgLoader({defaultImport: 'raw'})],
}), graphql(), viteRequire(), svgLoader({defaultImport: 'raw'}),
sentryVitePlugin({
org: "figures-libres",
project: "atlas-atterrissage.com",
authToken: process.env.AUTH_TOKEN,
release: {
// name: "ouatterrir",
name: release
},
url: "https://frontlog.figli.io",
})
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
@ -36,6 +62,7 @@ export default defineConfig({
},
},
build: {
sourcemap: true,
rollupOptions: {
// https://rollupjs.org/configuration-options/
},
@ -44,4 +71,7 @@ export default defineConfig({
esbuild: {
drop: ['console', 'debugger'],
},
define: {
__SENTRY_RELEASE__: JSON.stringify(release),
}
})