diff --git a/package-lock.json b/package-lock.json index 906d9d5..4179bd8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@mdi/font": "^7.1.96", "@mdi/js": "^7.2.96", "@tweenjs/tween.js": "^21.0.0", + "@vojtechlanka/vue-simple-suggest": "^2.0.6", "fabric": "^6.0.0-beta7", "granim": "^2.0.0", "lodash": "^4.17.21", @@ -806,6 +807,17 @@ "vue": "^3.2.25" } }, + "node_modules/@vojtechlanka/vue-simple-suggest": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vojtechlanka/vue-simple-suggest/-/vue-simple-suggest-2.0.6.tgz", + "integrity": "sha512-cptxgqpt7jmtcvADc1Ro/9ZYvKffIxCXBqjVTC5GaksH3LLKc/jODESPkpH1xQ4dYb8d4w1sy97TGKeipDc9rw==", + "dependencies": { + "vue": "3.x" + }, + "peerDependencies": { + "vue": "3.x" + } + }, "node_modules/@vue/compiler-core": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz", @@ -1321,6 +1333,20 @@ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "optional": true }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/core-js": { "version": "3.33.0", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.33.0.tgz", @@ -1687,6 +1713,20 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, "node_modules/es-module-lexer": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", @@ -2297,6 +2337,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/granim": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/granim/-/granim-2.0.0.tgz", @@ -2416,6 +2464,20 @@ "node": ">= 4" } }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/immutable": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", @@ -2574,6 +2636,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -2691,6 +2761,67 @@ "json-buffer": "3.0.1" } }, + "node_modules/less": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/less/-/less-3.13.1.tgz", + "integrity": "sha512-SwA1aQXGUvp+P5XdZslUOhhLnClSLIjWvJhmd+Vgib5BFIr9lMNlQwmwUNOjXThF/A0x+MCYYPeWEfeWiLRnTw==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "copy-anything": "^2.0.1", + "tslib": "^1.10.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "native-request": "^1.0.5", + "source-map": "~0.6.0" + } + }, + "node_modules/less/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/less/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/less/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2831,6 +2962,20 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -2963,6 +3108,14 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/native-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/native-request/-/native-request-1.1.0.tgz", + "integrity": "sha512-uZ5rQaeRn15XmpgE0xoPL8YWqcX90VtCFglYwAgkvKM5e8fog+vePLAhHxuuv/gRkrQxIeh5U3q9sMNUrENqWw==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -3266,6 +3419,17 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/pinia": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.6.tgz", @@ -3418,6 +3582,14 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", diff --git a/package.json b/package.json index 8524312..867a646 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@mdi/font": "^7.1.96", "@mdi/js": "^7.2.96", "@tweenjs/tween.js": "^21.0.0", + "@vojtechlanka/vue-simple-suggest": "^2.0.6", "fabric": "^6.0.0-beta7", "granim": "^2.0.0", "lodash": "^4.17.21", diff --git a/src/assets/main.scss b/src/assets/main.scss index fe1ce2f..23a0af5 100644 --- a/src/assets/main.scss +++ b/src/assets/main.scss @@ -1231,6 +1231,19 @@ ul.editable-files{ } +section.editable-proximites{ + margin-top: 1em; + label{ + padding: 0!important; + } + div.wrapper.editable{ + margin:0; padding:0.5em !important; + &>div.vue-simple-suggest{ + display: block!important; + } + } +} + .delete-btn{ text-align: center; background-color: #eee; diff --git a/src/components/contents/TerrainDeVie.vue b/src/components/contents/TerrainDeVie.vue index 63593c1..80c5f79 100644 --- a/src/components/contents/TerrainDeVie.vue +++ b/src/components/contents/TerrainDeVie.vue @@ -29,6 +29,9 @@ import ContentEditable from '@components/editable/ContentEditable.vue'; import CheckboxEditable from '@components/editable/CheckboxEditable.vue'; import SelectEditable from '@components/editable/SelectEditable.vue'; +// import vueAutocomplete from "@venegrad/vue3-autocomplete" +import VueSimpleSuggest from '@vojtechlanka/vue-simple-suggest'; + export default { props: ['cid', 'eid'], data(){ @@ -44,7 +47,10 @@ export default { chevrondown_path: mdiChevronDown, headerreduced: false, mdiStickerPlusOutline_path: mdiStickerPlusOutline, - reloading_concernements: false + reloading_concernements: false, + prox_default_values: [], + prox_new_value: {}, + prox_suggestions: [] } }, computed: { @@ -54,9 +60,13 @@ export default { 'ct_concernement', 'ct_entite', 'detailsZoomValue', + 'allEntitesById' // 'concernements_are_loading' ]), - ...mapState(UserStore,['name','csrf_token']), + ...mapState(UserStore,['name', + 'csrf_token', + 'isloggedin', + 'user_entites']), created(){ let d = new Date(this.concernement.created); console.log('d', d); @@ -184,6 +194,15 @@ export default { } }, deep: true + }, + user_entites: { + handler (n, o) { + console.log('TerrainDeVie watch user_entites'); + if (n) { + this.checkForUserProxmite(); + } + }, + deep: true } }, methods: { @@ -191,8 +210,9 @@ export default { 'setDetailsZoomValue', 'loadConcernements', 'reloadConcernements', - 'reloadConcernementEntites']), - // 'loadConcernementsRevisions' + 'reloadConcernementEntites', + 'reloadProximites' + ]), onClickInfos(){ this.infos_opened = !this.infos_opened; }, @@ -208,7 +228,9 @@ export default { GQL.post('', { query: print(ast) }) .then(({data: { data: { entite }}}) => { console.log('load entite loaded', entite) - this.entite = entite + this.entite = entite; + // this.setProxSuggestions() + this.checkForUserProxmite(); }) .catch(error => { console.warn('Issue with load entite', error) @@ -341,16 +363,124 @@ export default { REST.patch(`/node/${this.cid}?_format=json`, params_node, configs) .then(({ data }) => { - console.log('REST patch entite new field_sources', data) + console.log('REST patch entite new field_entite', data) resolve(data) }) .catch(error => { - console.warn(`Issue with patch node entite field_sources`, error) + console.warn(`Issue with patch node entite field_entite`, error) reject(error) }) // resolve('test') }) - } + }, + // setProxSuggestions(){ + // this.prox_suggestions = []; + // // check that entite is well referenced in a loaded concernement + // this.user_entites.forEach((entite) => { + // if (this.allEntitesById[entite.id]) { + // // check if not already proximited + // let tobesuggested = true; + // this.prox_default_values.forEach((default_entite) => { + // if (default_entite.id === entite.id) { + // tobesuggested = false; + // } + // }) + // if (tobesuggested) { + // this.prox_suggestions.push(entite) + // } + // } + // }) + // console.log('this.prox_suggestions', this.prox_suggestions); + // // this.checkForUserProxmite(); + // }, + checkForUserProxmite(){ + if (this.entite && this.isloggedin && !this.entite.can_update ) { + console.log('checkForUserProxmite', this.entite); + // this.prox_suggestions.forEach((user_entite) => { + this.prox_default_values = []; + this.prox_suggestions = []; + this.user_entites.forEach((user_entite) => { + console.log('user_entite', user_entite); + console.log('entite', this.allEntitesById[user_entite.id]); + if (this.allEntitesById[user_entite.id]) { + let tobesuggested = true + this.allEntitesById[user_entite.id].entite.proximite.forEach((prox_field_entite) => { + if(prox_field_entite.id === this.entite.id) { + this.prox_default_values.push(user_entite); + tobesuggested = false + } + }) + if (tobesuggested) { + this.prox_suggestions.push(user_entite) + } + } + }) + console.log('this.prox_default_values', this.prox_default_values); + } + }, + onProximiteSelected(src_entite){ + console.log('onProximiteSelected', src_entite); + if (src_entite) { + this.proxvaluetitle = src_entite.title; + // get all the field_proximite values, we don't want to ersae everything + let proximites = []; + this.allEntitesById[src_entite.id].entite.proximite.forEach((target_entite) =>{ + proximites.push({ + target_id: target_entite.id, + }) + }) + // add the new field value + proximites.push({ + target_id: this.entite.id, + }) + console.log('proximites', proximites); + + this.recordProximites(src_entite.id, proximites); + } + }, + deleteProximite(src_entite){ + console.log('deleteProximite', src_entite); + if (src_entite) { + // get all the field_proximite values, excpet the one we want to delete + let proximites = []; + this.allEntitesById[src_entite.id].entite.proximite.forEach((target_entite) =>{ + if(target_entite.id !== this.entite.id){ + proximites.push({ + target_id: target_entite.id, + }) + } + }) + this.recordProximites(src_entite.id, proximites); + } + }, + recordProximites(src_id, proximites){ + console.log(`recordProximites proximites`, proximites); + + const params_node = { + type: 'entite', + nid: [{value: src_id}], + 'field_proximite': proximites + }; + + const configs = { + headers: {'X-CSRF-Token': this.csrf_token} + }; + + REST.patch(`/node/${src_id}?_format=json`, params_node, configs) + .then(({ data }) => { + console.log('REST patch entite new field_proximite', data) + this.reloadProximites(src_id) + .then(() => { + // TODO clear the autocomplete field + this.prox_new_value = null; + }) + }) + .catch(error => { + console.warn(`Issue with patch node entite field_proximite`, error) + // reject(error) + }) + }, + }, components: { @@ -360,7 +490,8 @@ export default { SvgIcon, ContentEditable, CheckboxEditable, - SelectEditable + SelectEditable, + VueSimpleSuggest } } @@ -386,6 +517,41 @@ export default { field: {field_name: 'title', value:'value'} }" /> + +
+ +
+ + +
+
+ + + + diff --git a/src/stores/concernements.js b/src/stores/concernements.js index 77ec501..86979b0 100644 --- a/src/stores/concernements.js +++ b/src/stores/concernements.js @@ -1,4 +1,7 @@ import { defineStore } from 'pinia' + +import { UserStore } from '@/stores/user'; + // import REST from '@api/rest-axios' // import JSONAPI from '@api/json-axios' import { print } from 'graphql/language/printer' @@ -15,6 +18,7 @@ import ConcernementFields from '@api/gql/concernement.fragment.gql' import _assign from 'lodash/assign'; + export const ConcernementsStore = defineStore({ id: 'concernements', state: () => ({ @@ -398,6 +402,47 @@ export const ConcernementsStore = defineStore({ }) }) }, + reloadProximites (entite_id) { + console.log(`reloadProximites src_id:${entite_id}`); + console.log('this.allEntitesById[entite_id]', this.allEntitesById[entite_id]); + return new Promise((resolve, reject) => { + let old_entite = this.allEntitesById[entite_id]; + const ast = gql`{ + entite(id:${entite_id}) { + title + id + proximite { + id + title + } + + } + } + ` + GQL.post('', { query: print(ast) }) + .then(({ data : { data : { entite } } }) => { + console.log(`reloadProximites loaded`, entite); + let concernement = this.concernementsByID[old_entite.cid]; + console.log('concernement', concernement); + concernement.entites_byid[entite.id].entite.proximite = entite.proximite; + let user = UserStore(); + console.log('user', user); + user.getUserEntitees() + .then(() => { // { data : { data : { userentites } } } + console.log('reloadProximites graphql userentites loaded') + // this.user_entites = userentites; + resolve(); + }) + .catch(error => { + console.warn('Issue with graphql userentites loading', error) + Promise.reject(error) + }) + }) + .catch(error => { + console.warn('Issue with reloadProximites', error); + }) + }); + }, loadContentTypeDefinition () { const body = { query: ` diff --git a/src/stores/user.js b/src/stores/user.js index dacd93d..025e857 100644 --- a/src/stores/user.js +++ b/src/stores/user.js @@ -21,7 +21,8 @@ export const UserStore = defineStore({ name: null, roles: [], isAdmin: false, - logginMessage: null + logginMessage: null, + user_entites: null, }), getters: { @@ -41,16 +42,7 @@ export const UserStore = defineStore({ this.getUser(); // necessery to get the csrf-token - // this.userGetRoles() - // .then(({ data : { data : { user } } }) => { - // console.log('graphql user loaded', user) - // this.roles = user.roles - // this.checkIsAdmin() - // }) - // .catch(error => { - // console.warn('Issue with graphql user loading', error) - // Promise.reject(error) - // }) + }) } }) @@ -134,7 +126,18 @@ export const UserStore = defineStore({ console.log('graphql user loaded', user) this.roles = user.roles this.checkIsAdmin() - resolve() + + this.getUserEntitees() + .then(() => { //{ data : { data : { userentites } } } + console.log('then from get user, graphql userentites loaded') + // this.user_entites = userentites; + resolve() + }) + .catch(error => { + console.warn('Issue with graphql userentites loading', error) + Promise.reject(error) + }) + }) .catch(error => { console.warn('Issue with graphql user loading', error) @@ -174,6 +177,31 @@ export const UserStore = defineStore({ } } }, + getUserEntitees () { + console.log('getUserEntitees'); + + + return new Promise((resolve, reject) => { + const body = { + query: ` + query UserEntites($uid: Int!){ + userentites(uid: $uid) { + id + title + } + }`, + variables: { uid: parseInt(this.uid) } + } + + GQL.post('', body) + .then(({ data : { data : { userentites } } }) => { + console.log('then from getUserEntitees, graphql userentites loaded', userentites) + this.user_entites = userentites; + resolve(); + }); + + }); + }, userLogout () { const credentials = qs.stringify({ token: this.csrf_token