From f621a29953c65207804f0ced5a9286e4a92cad81 Mon Sep 17 00:00:00 2001 From: Pasq G Date: Sun, 22 Dec 2024 20:17:42 +0100 Subject: [PATCH 01/14] Poble X --- imports/roles.js | 11 +- imports/ui/App.jsx | 21 +- .../PanellSeccions/PanellSeccions.jsx | 8 +- imports/ui/Login.tsx | 14 +- imports/ui/Poble.jsx | 144 ++++++++++++ imports/ui/Pobles.jsx | 43 +++- imports/ui/Usuaris.jsx | 211 ++++++++++++++++-- package-lock.json | 52 +++++ package.json | 1 + server/main.js | 44 +++- 10 files changed, 507 insertions(+), 42 deletions(-) create mode 100644 imports/ui/Poble.jsx diff --git a/imports/roles.js b/imports/roles.js index 07eb4be..d24b4a2 100644 --- a/imports/roles.js +++ b/imports/roles.js @@ -13,4 +13,13 @@ export const ROLS_DE_POBLE = { }; // as const; // export type TeamRolesKeys = keyof typeof TEAM_ROLES; -// export type TeamRolesValues = (typeof TEAM_ROLES)[TeamRolesKeys]; \ No newline at end of file +// export type TeamRolesValues = (typeof TEAM_ROLES)[TeamRolesKeys]; + + + +///////////////////////////////////////////////////////////////////////////////////////////////////// + +// De menor a major privilegi: +// +// Usuari < Voluntari de Poble < Encarregat de Tasques < Monitor de Poble < Administrador Global + diff --git a/imports/ui/App.jsx b/imports/ui/App.jsx index 9418765..227d054 100644 --- a/imports/ui/App.jsx +++ b/imports/ui/App.jsx @@ -5,6 +5,7 @@ import { Login } from './Login'; import { useSubscribe, useTracker, useFind } from 'meteor/react-meteor-data/suspense'; import { Pobles } from './Pobles'; +import { Poble } from './Poble'; import { Necessitats } from './Necessitats'; import { Tipus } from './Tipus'; import { BarraNav } from './BarraNav/BarraNav'; @@ -22,6 +23,8 @@ export const App = () => { const [esAdministrador, setEsAdministrador] = useState(false); + // const [pobleSeleccionat, setPobleSeleccionat] = useState(null); + // const u = useTracker("user", async () => await Meteor.userAsync()); @@ -33,18 +36,24 @@ export const App = () => { }, [user]); // const userId = await Meteor.userAsync(); - return + return {Meteor.userId() && } Carregant...}>{user ? : } } /> - } /> - } /> - } /> - } /> - } /> + } /> + } /> + } /> + } /> + } /> + } /> }; diff --git a/imports/ui/BarraNav/PanellSeccions/PanellSeccions.jsx b/imports/ui/BarraNav/PanellSeccions/PanellSeccions.jsx index 2a73670..ead6caf 100644 --- a/imports/ui/BarraNav/PanellSeccions/PanellSeccions.jsx +++ b/imports/ui/BarraNav/PanellSeccions/PanellSeccions.jsx @@ -16,22 +16,22 @@ export const BotóSecció = ({titol, linkto}) => { export const SeccióPobles = () => ; export const SeccióNecessitats = () => ; export const SeccióTipus = () => ; export const SeccióUsuaris = () => ; export const PanellSeccions = ({children}) => { diff --git a/imports/ui/Login.tsx b/imports/ui/Login.tsx index 82de457..d4e8c2c 100644 --- a/imports/ui/Login.tsx +++ b/imports/ui/Login.tsx @@ -2,7 +2,8 @@ import React, { useState } from 'react'; import { Accounts } from 'meteor/accounts-base'; import { useNavigate } from 'react-router-dom'; import { Meteor } from 'meteor/meteor'; - +import { Roles } from 'meteor/roles'; +import { ROLS_GLOBALS } from '../roles'; export const Login = () => { const [isLogin, setIsLogin] = useState( { initialState: true } ); @@ -25,7 +26,7 @@ export const Login = () => { }); }; - const handleRegistration = (e) => { + const handleRegistration = async (e) => { e.preventDefault(); // console.dir(e); const username = e.target.elements.username.value; @@ -38,11 +39,16 @@ export const Login = () => { return null; } - Accounts.createUserAsync({ + const userId = await Accounts.createUserAsync({ username, email, password - }).then(() => navigate('/')) + }); + console.log("userId deL NOU USUARI: ", userId); + userId && await Roles.addUsersToRolesAsync(userId, [ROLS_GLOBALS.USUARI]); + navigate('/'); + + return userId; }; diff --git a/imports/ui/Poble.jsx b/imports/ui/Poble.jsx new file mode 100644 index 0000000..57ff162 --- /dev/null +++ b/imports/ui/Poble.jsx @@ -0,0 +1,144 @@ +import React, { Suspense, useEffect, useState, useRef, lazy } from 'react'; +import { Meteor } from 'meteor/meteor'; +import { PoblesCollection } from '/imports/api/pobles.js'; +import { useSubscribe, useTracker, useFind } from 'meteor/react-meteor-data/suspense'; + +import { Roles } from 'meteor/roles'; +// import { useUserId } from 'meteor/react-meteor-accounts'; +import { BarraNav } from "./BarraNav/BarraNav"; +import { useParams } from "react-router-dom"; + + + + +export const Poble = () => { + + let { ambitPoble } = useParams(); + + // const [pobleSeleccionat, setPobleSeleccionat] = useState(null); + // const [creantPoble, setCreantPoble] = useState(false); + useSubscribe('pobles'); + // const pobles = useTracker("pobles", () => PoblesCollection.find().fetchAsync()); + const pobles = useFind(PoblesCollection, [{}, {sort: {nomPoble: 1}}]); + + const [esEditor, setEsEditor] = useState(false); + const userId = Meteor.userId(); + let pob; + + console.log("ambitPoble: ", ambitPoble); + console.log("pobles: ", pobles); + pob = pobles.find(p => p.ambitAssociat === ambitPoble); + console.log("pob: ", pob); + + // console.log("isAdmin: ", isAdmin) ; + + // (async () => { + useEffect(() => { + (async () => { + const comprovaAdmin = await Roles.userIsInRoleAsync(userId, ["admin"]); + setEsEditor(comprovaAdmin); + + })(); + }, []); + // })(); + + + + // const QuadreInfo_Poble = () => { + + // const refInAmbitAssignat = useRef(); + + // return
+ + // {pobleSeleccionat &&

{pobleSeleccionat._id}

} + + //
{ + // try { + // Meteor.callAsync('editaOAfigPoble', + // { + // ...pobleSeleccionat || [], + // nomPoble: d.get('nomPoble'), + // cp: d.get('cp') || "", + // comarca: d.get('comarca') || "", + // ambitAssociat: d.get('ambit-associat') + // }).then(() => setPobleSeleccionat(null)) + // .catch(err => console.error(err)); + // } catch (err) { + // alert(err); + // console.error(err); + // } + // }} + // > + // + // refInAmbitAssignat.current.value = ev.target.value.replace(/ +/g, '-').toLowerCase()} + // />
+ //
+ //
+ + // { esEditor && <> + //

+ // Àmbit associat: + + // + // {/* // nomPoble.replace(/ +/g, '-').toLowerCase()}/> */} + //

+ // } + + // + // + //
+ //
; + // }; + + return Carregant...} > + +

{pob?.nomPoble}

+ + {/* { esEditor && (pobleSeleccionat || creantPoble) && } + +
    { + pobles + .sort((a,b) => a.nomPoble?.toLowerCase() > b.nomPoble?.toLowerCase()) + .map(pob =>
  • + {pob.nomPoble}{esEditor && }
  • ) + }
+ {esEditor && } */} +
; +}; \ No newline at end of file diff --git a/imports/ui/Pobles.jsx b/imports/ui/Pobles.jsx index 3eb370c..460eea5 100644 --- a/imports/ui/Pobles.jsx +++ b/imports/ui/Pobles.jsx @@ -6,6 +6,7 @@ import { useSubscribe, useTracker, useFind } from 'meteor/react-meteor-data/susp import { Roles } from 'meteor/roles'; // import { useUserId } from 'meteor/react-meteor-accounts'; import { BarraNav } from "./BarraNav/BarraNav"; +import { Link } from 'react-router-dom'; @@ -13,6 +14,7 @@ import { BarraNav } from "./BarraNav/BarraNav"; export const Pobles = () => { const [pobleSeleccionat, setPobleSeleccionat] = useState(null); + const [creantPoble, setCreantPoble] = useState(false); useSubscribe('pobles'); // const pobles = useTracker("pobles", () => PoblesCollection.find().fetchAsync()); const pobles = useFind(PoblesCollection, [{}, {sort: {nomPoble: 1}}]); @@ -31,8 +33,12 @@ export const Pobles = () => { }, []); // })(); + + const QuadreInfo_Poble = () => { + const refInAmbitAssignat = useRef(); + return
{ }}> {pobleSeleccionat &&

{pobleSeleccionat._id}

} -

Pobles

{ @@ -53,6 +58,7 @@ export const Pobles = () => { nomPoble: d.get('nomPoble'), cp: d.get('cp') || "", comarca: d.get('comarca') || "", + ambitAssociat: d.get('ambit-associat') }).then(() => setPobleSeleccionat(null)) .catch(err => console.error(err)); } catch (err) { @@ -61,9 +67,25 @@ export const Pobles = () => { } }} > -
+ + refInAmbitAssignat.current.value = ev.target.value.replace(/ +/g, '-').toLowerCase()} + />


+ + { esEditor && <> +

+ Àmbit associat: + + + {/* // nomPoble.replace(/ +/g, '-').toLowerCase()}/> */} +

+ } +
; }; - + return Carregant...} > + +

Pobles

- { esEditor && } + { esEditor && (pobleSeleccionat || creantPoble) && }
    { backgroundColor: `${'lightgreen' || 'lightcoral'}` }} > - {pob.nomPoble}{esEditor && }) + + {pob.nomPoble}{esEditor && } + + ) + }
+ {esEditor && }
; }; \ No newline at end of file diff --git a/imports/ui/Usuaris.jsx b/imports/ui/Usuaris.jsx index 59eca25..6d81b31 100644 --- a/imports/ui/Usuaris.jsx +++ b/imports/ui/Usuaris.jsx @@ -7,12 +7,153 @@ import { Roles } from 'meteor/roles'; // import { useUserId } from 'meteor/react-meteor-accounts'; import { BarraNav } from "./BarraNav/BarraNav"; +const isClickInsideRectangle = (e, element) => { + const r = element?.getBoundingClientRect(); + return ( + e.clientX > r.left && + e.clientX < r.right && + e.clientY > r.top && + e.clientY < r.bottom + ); +}; +const AssignadorDeRols = ({pobles, ambitGeneral, esEditor, rols, usrSeleccionat}) => { + const [creantRol, setCreantRol] = useState(false); + const [ambitsUSel, setAmbitsUSel] = useState([]); + + useEffect(() => { + (async () => { + const ambits = await Roles.getScopesForUserAsync(usrSeleccionat?._id); + setAmbitsUSel(ambits); + })(); + }, []); + + return
+

Rols

+ +

Àmbits

+
General:
+
    { + rols?.map(uRol =>
  • + {uRol} + {esEditor && } +
  • ) + }
+ + {/*
    */} + { + ambitsUSel?.map(async aus => { + + const uRol = await Roles.getRolesForUserAsync(usrSeleccionat._id, {scope: aus, onlyScoped: true}); + return <> +
    {aus}:
    + { + {uRol} + {esEditor && } + + }
    + ; + }) + } + {/*
*/} + + {esEditor && creantRol &&
+
{ + Meteor.callAsync('assignaRol', usrSeleccionat._id, d.get('selRol'), d.get('selAmbit')); + }}> + + Àmbit:
+ + Rol:

+ + + +
+
} + + {esEditor && usrSeleccionat && } +
; +}; export const Usuaris = () => { - + const refQuadreSeleccionat = useRef(); const [usrSeleccionat, setUsrSeleccionat] = useState(null); + useSubscribe('pobles'); const pobles = useTracker("pobles", () => PoblesCollection.find().fetchAsync()); @@ -21,8 +162,15 @@ export const Usuaris = () => { const usuaris = useTracker("usuaris", () => { Meteor.subscribe('usuaris'); - return Meteor.users.find().fetch().filter(u => u._id !== Meteor.userId()); + return Meteor.users.find().fetch()//.filter(u => u._id !== Meteor.userId()); }); + + const rols = useTracker("rols", async () => { + return await Roles.getRolesForUserAsync(usrSeleccionat?._id); + }); + + console.log("rols: ", rols); + // console.log("isAdmin: ", isAdmin) ; console.log("usuaris: ", usuaris); // (async () => { @@ -35,15 +183,34 @@ export const Usuaris = () => { }, []); // })(); + const QuadreInfo_Usuari = () => { + + // const [rols, setRols] = useState([]); + + const [ambitGeneral, setAmbitGeneral] = useState(false); + + + let allScopes; + + // useEffect( async () => { + // allScopes = await Roles.getScopesForUserAsync(usrSeleccionat?._id); + // // Roles.getRolesForUser(usrSeleccionat?._id).map(uRol =>
  • {uRol}
  • ); + + // // setRols(rols); + // }); + + return
    + display: `inline-block`, + border: `1px solid #6666`, + padding: `.5rem`, + borderRadius: `.3em`, + backgroundColor: `lightcyan` + }} + ref={refQuadreSeleccionat} + > {usrSeleccionat &&

    {usrSeleccionat._id}

    } @@ -66,23 +233,30 @@ export const Usuaris = () => { >

    -
    - + + + + + { esEditor && } +
    ; }; - return Carregant...} > + return
    { + !isClickInsideRectangle(ev, refQuadreSeleccionat.current) && setUsrSeleccionat(null); + }}>Carregant...} > +

    Usuaris

    - { esEditor && } + { esEditor && usrSeleccionat && }
      { backgroundColor: `${'lightgreen' || 'lightcoral'}` }} > - {usr.username}{esEditor && }) + {usr.username}{esEditor && }) }
    -
    ; + + {esEditor && !usrSeleccionat && } + +
    ; }; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 1d952f7..6f5f927 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "meteor-node-stubs": "^1.2.5", "react": "19", "react-dom": "19", + "react-router": "^7.0.2", "react-router-dom": "^6.28.0", "react-select": "^5.8.3", "styled-components": "^6.1.13" @@ -356,6 +357,12 @@ "node": ">=14.0.0" } }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "license": "MIT" + }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -432,6 +439,15 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "license": "MIT" }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -1977,6 +1993,30 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, + "node_modules/react-router": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.0.2.tgz", + "integrity": "sha512-m5AcPfTRUcjwmhBzOJGEl6Y7+Crqyju0+TgTQxoS4SO+BkWbhOrcfZNq6wSWdl2BBbJbsAoBUb8ZacOFT+/JlA==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, "node_modules/react-router-dom": { "version": "6.28.0", "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.0.tgz", @@ -2131,6 +2171,12 @@ "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", "license": "MIT" }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", @@ -2207,6 +2253,12 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "license": "0BSD" }, + "node_modules/turbo-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", + "license": "ISC" + }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", diff --git a/package.json b/package.json index 279ce12..6804200 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "meteor-node-stubs": "^1.2.5", "react": "19", "react-dom": "19", + "react-router": "^7.0.2", "react-router-dom": "^6.28.0", "react-select": "^5.8.3", "styled-components": "^6.1.13" diff --git a/server/main.js b/server/main.js index 1d38f67..c154f0f 100644 --- a/server/main.js +++ b/server/main.js @@ -213,15 +213,19 @@ Meteor.startup(async () => { await Roles.createRoleAsync(ROLS_DE_POBLE.ENCARREGAT, { unlessExists: true }); await Roles.createRoleAsync(ROLS_DE_POBLE.VOLUNTARI, { unlessExists: true }); - await Roles.addRolesToParentAsync([ROLS_DE_POBLE.VOLUNTARI, ROLS_DE_POBLE.ENCARREGAT], ROLS_DE_POBLE.MONITOR); - await Roles.addRolesToParentAsync([ROLS_DE_POBLE.VOLUNTARI, ROLS_DE_POBLE.ENCARREGAT, ROLS_DE_POBLE.MONITOR, ROLS_GLOBALS.USUARI], ROLS_GLOBALS.ADMINISTRADOR); + // await Roles.addRolesToParentAsync([ROLS_DE_POBLE.VOLUNTARI, ROLS_DE_POBLE.ENCARREGAT], ROLS_DE_POBLE.MONITOR); + // await Roles.addRolesToParentAsync([ROLS_DE_POBLE.VOLUNTARI, ROLS_DE_POBLE.ENCARREGAT, ROLS_DE_POBLE.MONITOR, ROLS_GLOBALS.USUARI], ROLS_GLOBALS.ADMINISTRADOR); } catch (err) { console.error(err.message); } // Publish user's own roles -Meteor.publish(null, function () { +Meteor.publish(null, async function () { + if (await Roles.userIsInRoleAsync(Meteor.userId(), "admin")) { + return Meteor.roleAssignment.find(); + } + if (this.userId) { return Meteor.roleAssignment.find({ "user._id": this.userId }); } @@ -232,14 +236,30 @@ Meteor.publish(null, function () { // Meteor.publish("scopeRoles", function (scope) { // if (this.userId) { // return Meteor.roleAssignment.find({ scope: scope }); -// } +// }2024-12-19 21:40:26 // this.ready(); // }); +Accounts.onCreateUser(async (options, user) => { + await Roles.addUsersToRolesAsync(user._id, ROLS_GLOBALS.USUARI); + return user; +}); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Meteor.methods({ +Meteor.methods({ + 'assignaRol': async function (userId, rols, ambits) { + const esAdmin = await Roles.userIsInRoleAsync(Meteor.userId(), "admin"); + esAdmin && await Roles.addUsersToRolesAsync(userId, rols, ambits); + console.log(`Rol "${rols}" assignat a l'usuari "${userId}" delimitat amb l'àmbit "${ambits}"`); + }, + + 'retiraRols': async function (rols, userId, ambits) { + const esAdmin = await Roles.userIsInRoleAsync(Meteor.userId(), "admin"); + esAdmin && await Roles.removeUsersFromRolesAsync(userId, rols, ambits); + + console.log(`Retirats els rols "${rols}" de l'usuari "${userId}"`); + }, 'editaOAfigPoble': async function (poble) { const esAdmin = await Roles.userIsInRoleAsync(Meteor.userId(), "admin"); @@ -305,6 +325,20 @@ Meteor.publish(null, function () { } }, + 'eliminaUsuari': async function (usuariId) { + const esAdmin = await Roles.userIsInRoleAsync(Meteor.userId(), "admin"); + try { + console.log(`ELIMINACIÓ D'USUARI sol·licitada per a ${usuariId}. Comprovant si ${Meteor.userId()} és Admin: `, esAdmin); + if (esAdmin && usuariId) { + return await Meteor.users.removeAsync(usuariId); + } else { + throw new Error("El nom de l'usuari no és vàlid"); + } + } catch (e) { + console.error(e); + } + }, + 'afigTipus': async function (tipus) { const esAdmin = await Roles.userIsInRoleAsync(Meteor.userId(), "admin"); try { From e129eb41075a42f89ee29cdf70ff1590be2ddb54 Mon Sep 17 00:00:00 2001 From: Pasq G Date: Wed, 25 Dec 2024 15:24:14 +0100 Subject: [PATCH 02/14] =?UTF-8?q?Avan=C3=A7os=20amb=20els=20formularis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- imports/ui/Necessitats.jsx | 44 +++++++++++++++++++------- imports/ui/Poble.jsx | 63 +++++++++++++++++++++++++++++++++++--- imports/ui/Pobles.jsx | 9 +++++- server/main.js | 17 +++++++--- 4 files changed, 112 insertions(+), 21 deletions(-) diff --git a/imports/ui/Necessitats.jsx b/imports/ui/Necessitats.jsx index ad5b45f..deae70f 100644 --- a/imports/ui/Necessitats.jsx +++ b/imports/ui/Necessitats.jsx @@ -59,11 +59,20 @@ export const Necessitats = () => { action={d => { if (d.get('selTipus')) try { + const tipusSeleccionat = tipus.find(t => t._id === d.get('selTipus')) || ""; + const pobleSeleccionat = pobles.find(p => p._id === d.get('selPoble')) || ""; Meteor.callAsync('afigNecessitat', { ...necessitatSeleccionada || [], - titol: d.get('titol'), - tipus: d.get('selTipus') || "", - poble: d.get('selPoble') + titol: d.get('taTitol'), + tipus: tipusSeleccionat, + poble: pobleSeleccionat, + descrip: d.get('taDescripcio'), + contacte: { + nom: d.get('inContacte'), + tel: d.get('inTelefon'), + email: d.get('inEMail'), + adr: d.get('inAdreça') + } }) .then(() => setNecessitatSeleccionada(null)) .catch(err => console.error(err)) @@ -76,7 +85,7 @@ export const Necessitats = () => { >
    - +

    @@ -91,6 +100,7 @@ export const Necessitats = () => { formatCreateLabel={(inputValue) => "Crear nou tipus..."} defaultOptions={tipus.map((v,i) => ({value: v._id, label: v.titol})).sort((a,b) => a.label.toLowerCase() > b.label.toLowerCase()) } onCreateOption={(inputValue) => Meteor.callAsync('afigTipus', {titol: inputValue})} + defaultValue={ necessitatSeleccionada ? { value: necessitatSeleccionada.tipus._id, label: necessitatSeleccionada.tipus.titol} : ""} // loadOptions={tipus.map((v,i) => ({value: v, label: v.titol}))} /> @@ -106,7 +116,9 @@ export const Necessitats = () => { - ({value: v._id, label: v.nomPoble})) } /> + ({value: v._id, label: v.nomPoble})) } + defaultValue={ necessitatSeleccionada ? { value: necessitatSeleccionada.poble._id, label: necessitatSeleccionada.poble.nomPoble} : ""} + /> {/*
    +

    @@ -125,10 +139,18 @@ export const Necessitats = () => { border: `1px solid #6666` }}> Contacte -
    -
    -
    -
    +
    +
    +
    +

    @@ -173,7 +195,7 @@ export const Necessitats = () => { backgroundColor: `${'lightgreen' || 'lightcoral'}` }} > - {nec.titol}{esEditor && }) + {nec.titol} {esEditor && }) }
    ; }; \ No newline at end of file diff --git a/imports/ui/Poble.jsx b/imports/ui/Poble.jsx index 57ff162..4877e68 100644 --- a/imports/ui/Poble.jsx +++ b/imports/ui/Poble.jsx @@ -18,6 +18,7 @@ export const Poble = () => { // const [pobleSeleccionat, setPobleSeleccionat] = useState(null); // const [creantPoble, setCreantPoble] = useState(false); useSubscribe('pobles'); + useSubscribe('usuaris'); // const pobles = useTracker("pobles", () => PoblesCollection.find().fetchAsync()); const pobles = useFind(PoblesCollection, [{}, {sort: {nomPoble: 1}}]); @@ -77,10 +78,10 @@ export const Poble = () => { // }} // > // - // refInAmbitAssignat.current.value = ev.target.value.replace(/ +/g, '-').toLowerCase()} // />
    //
    @@ -111,6 +112,60 @@ export const Poble = () => {

    {pob?.nomPoble}

    +

    Monitores:

    +
      + { + (async () => { + const monitors = await Roles.getUsersInRoleAsync("monitor_de_poble", pob?.ambitAssociat); + console.log("monitors: ", monitors); + return monitors?.map( (u) =>
    • {u.username}
    • ); + })() + } +
    + +

    Encarregades de tasques:

    +
      + { + (async () => { + const encarregats = await Roles.getUsersInRoleAsync("encarregat_de_tasques", pob?.ambitAssociat); + console.log("encarregats: ", encarregats); + return encarregats?.map( (u) =>
    • {u.username}
    • ); + })() + } +
    + +

    Voluntàries de poble:

    +
      + { + (async () => { + const voluntaris = await Roles.getUsersInRoleAsync("voluntari_de_poble", pob?.ambitAssociat); + console.log("voluntaris: ", voluntaris); + return voluntaris?.map( (u) =>
    • {u.username}
    • ); + })() + } +
    + {/* { esEditor && (pobleSeleccionat || creantPoble) && }
      { }} > - {pob.nomPoble}{esEditor && } + {pob.nomPoble}{esEditor && } ) diff --git a/server/main.js b/server/main.js index c154f0f..e522993 100644 --- a/server/main.js +++ b/server/main.js @@ -194,13 +194,20 @@ Meteor.startup(async () => { Meteor.publish('usuaris', async function (uid) { - const esAdmin = await Roles.userIsInRoleAsync(Meteor.userId(), "admin"); - const userRoles = await Roles.getRolesForUserAsync(Meteor.userId()); + const esAdmin = await Roles.userIsInRoleAsync(this.userId, "admin", null); + const userRoles = await Roles.getRolesForUserAsync(this.userId); console.log("userRoles: ", userRoles); - if (uid) { - return Meteor.users.find({_id: uid},{fields: {username: 1, avatarId: 1, avatarLink: 1}}); + console.log("esAdmin: ", esAdmin); + + if (esAdmin) { + return Meteor.users.find({}); } + + if (uid) { + return Meteor.users.find({_id: uid}, {fields: {username: 1, avatarId: 1, avatarLink: 1}}); + } + return Meteor.users.find({},{fields: {username: 1, avatarId: 1, avatarLink: 1}}); }); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -222,7 +229,7 @@ Meteor.startup(async () => { // Publish user's own roles Meteor.publish(null, async function () { - if (await Roles.userIsInRoleAsync(Meteor.userId(), "admin")) { + if (await Roles.userIsInRoleAsync(this.userId, "admin")) { return Meteor.roleAssignment.find(); } From 9a64c013eacd5d6e56bcc8619cc21d71503e0f02 Mon Sep 17 00:00:00 2001 From: Pasq G Date: Wed, 25 Dec 2024 16:15:28 +0100 Subject: [PATCH 03/14] =?UTF-8?q?Avan=C3=A7os=20en=20Pobles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- imports/ui/Pobles.jsx | 120 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 97 insertions(+), 23 deletions(-) diff --git a/imports/ui/Pobles.jsx b/imports/ui/Pobles.jsx index 8b7498b..00b0e2f 100644 --- a/imports/ui/Pobles.jsx +++ b/imports/ui/Pobles.jsx @@ -113,30 +113,104 @@ export const Pobles = () => { }}>{ pobles .sort((a,b) => a.nomPoble?.toLowerCase() > b.nomPoble?.toLowerCase()) - .map(pob =>
    • - - {pob.nomPoble}{esEditor && } - -
    • ) - + .map(pob => +
    • + { +
      + 1 + 2 + 3 +
      + } + + { +
      + 0 + {/* 2 + 3 */} +
      + } + + + {pob.nomPoble} {esEditor && } + +
    • + ) }
    + {esEditor && }) + } + {/* { esEditor && (pobleSeleccionat || creantPoble) && }
      { }, []); // })(); + const BotoPobleAmbIndicadors = ({pob}) => { + useSubscribe('necessitats', pob.ambitAssociat); + const necessitats = useFind(NecessitatsCollection, [{"poble.ambitAssociat": pob.ambitAssociat}]); + const [monitors, setMonitors] = useState(false); + + + useEffect(() => { + (async () => { + const mon = await Roles.getUsersInRoleAsync('monitor_de_poble', pob.ambitAssociat); + setMonitors(mon.map(m => m).length); + })(); + }, [pob]); + + + // console.log("mon: ", monitors); + + return
    • + {// Indicadors de Responsables +
      + { + monitors + ? {monitors} + : false + } + 2 + 3 +
      + } + + {// Indicadors de Necessitats +
      + { + necessitats.length + ? + {necessitats.length } + : false + } +
      + } + + {// Botó de creació de nou poble + + {pob.nomPoble} {esEditor && } + + } +
    • ; + } const QuadreInfo_Poble = () => { @@ -68,10 +179,10 @@ export const Pobles = () => { }} > - refInAmbitAssignat.current.value = ev.target.value.replace(/ +/g, '-').toLowerCase()} />

      @@ -97,6 +208,10 @@ export const Pobles = () => { ; }; + + // const Indicador = ({valor, ambit, }) => { + + // }; return Carregant...} > @@ -113,102 +228,9 @@ export const Pobles = () => { }}>{ pobles .sort((a,b) => a.nomPoble?.toLowerCase() > b.nomPoble?.toLowerCase()) - .map(pob => -
    • - { -
      - 1 - 2 - 3 -
      - } - - { -
      - 0 - {/* 2 - 3 */} -
      - } - - - {pob.nomPoble} {esEditor && } - -
    • - ) + .map(pob => { + return + }) }
    {esEditor && } - ; + ; }; \ No newline at end of file From f4d51a73cf7e6931d7c5f10cd3a76e1ec005a497 Mon Sep 17 00:00:00 2001 From: Pasq G Date: Fri, 3 Jan 2025 17:35:14 +0100 Subject: [PATCH 07/14] =?UTF-8?q?Camps=20de=20pobles=20reactius=20al=20can?= =?UTF-8?q?viar=20la=20selecci=C3=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/main.jsx | 6 +- imports/ui/Pobles.jsx | 395 +++++++++++++++++++++--------------------- 2 files changed, 204 insertions(+), 197 deletions(-) diff --git a/client/main.jsx b/client/main.jsx index d2e380f..a9f7af3 100644 --- a/client/main.jsx +++ b/client/main.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {StrictMode} from 'react'; import { createRoot } from 'react-dom/client'; import { Meteor } from 'meteor/meteor'; import { App } from '/imports/ui/App'; @@ -6,5 +6,7 @@ import { App } from '/imports/ui/App'; Meteor.startup(() => { const container = document.getElementById('react-target'); const root = createRoot(container); - root.render(); + root.render( + + ); }); diff --git a/imports/ui/Pobles.jsx b/imports/ui/Pobles.jsx index e6acc93..bacdebb 100644 --- a/imports/ui/Pobles.jsx +++ b/imports/ui/Pobles.jsx @@ -10,7 +10,203 @@ import { Link } from 'react-router-dom'; import { NecessitatsCollection } from '../api/necessitats'; +const QuadreInfo_Poble = ({esEditor, pobleSeleccionat, setPobleSeleccionat}) => { + + const refInAmbitAssignat = useRef(); + return
    + + {pobleSeleccionat &&

    {pobleSeleccionat._id}

    } + +
    { + try { + Meteor.callAsync('editaOAfigPoble', + { + ...pobleSeleccionat || [], + nomPoble: d.get('nomPoble'), + cp: d.get('cp') || "", + comarca: d.get('comarca') || "", + ambitAssociat: d.get('ambit-associat') + }).then(() => setPobleSeleccionat(null)) + .catch(err => console.error(err)); + } catch (err) { + alert(err); + console.error(err); + } + }} + > + + refInAmbitAssignat.current.value = ev.target.value.replace(/ +/g, '-').toLowerCase()} + />
    +
    +
    + + { esEditor && <> +

    + Àmbit associat: + + + {/* // nomPoble.replace(/ +/g, '-').toLowerCase()}/> */} +

    + } + + + +
    +
    ; +}; + +const BotoPobleAmbIndicadors = ({pob, pobleSeleccionat, setPobleSeleccionat, esEditor}) => { + // let pob = pobleSeleccionat; + useSubscribe('necessitats', pob.ambitAssociat); + const necessitats = useFind(NecessitatsCollection, [{"poble.ambitAssociat": pob.ambitAssociat}]); + const [monitors, setMonitors] = useState(false); + const [encarregats, setEncarregats] = useState(false); + const [voluntaris, setVoluntaris] = useState(false); + + // let mon, mons, enc, encs, vol, vols; + + (async () => { + const mons = await Roles.getUsersInRoleAsync("monitor_de_poble", pob?.ambitAssociat); + // console.log("monitors: ", monitors); + setMonitors(mons?.fetch().length || false); + + const encs = await Roles.getUsersInRoleAsync("encarregat_de_tasques", pob?.ambitAssociat); + // console.log("monitors: ", monitors); + setEncarregats(encs?.fetch().length || false); + + const vols = await Roles.getUsersInRoleAsync("voluntari_de_poble", pob?.ambitAssociat); + // console.log("monitors: ", monitors); + setVoluntaris(vols?.fetch().length || false); + })(); + + return
  • + {// Indicadors de Responsables +
    + { + monitors + ? {monitors} + : false + } + { encarregats + ? {encarregats} + : false + } + { voluntaris + ? {voluntaris} + : false + } +
    + } + + {// Indicadors de Necessitats +
    + { + necessitats.length + ? + {necessitats.length } + : false + } +
    + } + + {// Botó de creació de nou poble + + {pob.nomPoble} {esEditor && } + + } +
  • ; +} export const Pobles = () => { @@ -36,201 +232,10 @@ export const Pobles = () => { }, []); // })(); - const BotoPobleAmbIndicadors = ({pob}) => { - useSubscribe('necessitats', pob.ambitAssociat); - const necessitats = useFind(NecessitatsCollection, [{"poble.ambitAssociat": pob.ambitAssociat}]); - const [monitors, setMonitors] = useState(false); - const [encarregats, setEncarregats] = useState(false); - const [voluntaris, setVoluntaris] = useState(false); - - // let mon, mons, enc, encs, vol, vols; - - (async () => { - const mons = await Roles.getUsersInRoleAsync("monitor_de_poble", pob?.ambitAssociat); - // console.log("monitors: ", monitors); - setMonitors(mons?.fetch().length || false); - - const encs = await Roles.getUsersInRoleAsync("encarregat_de_tasques", pob?.ambitAssociat); - // console.log("monitors: ", monitors); - setEncarregats(encs?.fetch().length || false); - - const vols = await Roles.getUsersInRoleAsync("voluntari_de_poble", pob?.ambitAssociat); - // console.log("monitors: ", monitors); - setVoluntaris(vols?.fetch().length || false); - })(); - - return
  • - {// Indicadors de Responsables -
    - { - monitors - ? {monitors} - : false - } - { encarregats - ? {encarregats} - : false - } - { voluntaris - ? {voluntaris} - : false - } -
    - } - - {// Indicadors de Necessitats -
    - { - necessitats.length - ? - {necessitats.length } - : false - } -
    - } - - {// Botó de creació de nou poble - - {pob.nomPoble} {esEditor && } - - } -
  • ; - } - const QuadreInfo_Poble = () => { - - const refInAmbitAssignat = useRef(); - - return
    - - {pobleSeleccionat &&

    {pobleSeleccionat._id}

    } - -
    { - try { - Meteor.callAsync('editaOAfigPoble', - { - ...pobleSeleccionat || [], - nomPoble: d.get('nomPoble'), - cp: d.get('cp') || "", - comarca: d.get('comarca') || "", - ambitAssociat: d.get('ambit-associat') - }).then(() => setPobleSeleccionat(null)) - .catch(err => console.error(err)); - } catch (err) { - alert(err); - console.error(err); - } - }} - > - - refInAmbitAssignat.current.value = ev.target.value.replace(/ +/g, '-').toLowerCase()} - />
    -
    -
    - - { esEditor && <> -

    - Àmbit associat: - - - {/* // nomPoble.replace(/ +/g, '-').toLowerCase()}/> */} -

    - } - - - -
    -
    ; - }; + + // const Indicador = ({valor, ambit, }) => { @@ -240,7 +245,7 @@ export const Pobles = () => {

    Pobles

    - { esEditor && (pobleSeleccionat || creantPoble) && } + { esEditor && (pobleSeleccionat || creantPoble) && }
      { pobles .sort((a,b) => a.nomPoble?.toLowerCase() > b.nomPoble?.toLowerCase()) .map(pob => { - return + return }) }
    From d18970948a91a5d92b097c1b180909543250c064 Mon Sep 17 00:00:00 2001 From: Kal Date: Tue, 7 Jan 2025 15:05:58 +0100 Subject: [PATCH 08/14] =?UTF-8?q?Avan=C3=A7os=20en=20taula=20d'usuaris?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- imports/ui/Usuaris.jsx | 420 +++++++++++++++++++++-------------------- 1 file changed, 219 insertions(+), 201 deletions(-) diff --git a/imports/ui/Usuaris.jsx b/imports/ui/Usuaris.jsx index 3491b99..8873b5a 100644 --- a/imports/ui/Usuaris.jsx +++ b/imports/ui/Usuaris.jsx @@ -5,155 +5,206 @@ import { useSubscribe, useTracker, useFind } from 'meteor/react-meteor-data/susp import { Roles } from 'meteor/roles'; // import { useUserId } from 'meteor/react-meteor-accounts'; -import { BarraNav } from "./BarraNav/BarraNav"; -const isClickInsideRectangle = (e, element) => { - const r = element?.getBoundingClientRect(); - return ( - e.clientX > r.left && - e.clientX < r.right && - e.clientY > r.top && - e.clientY < r.bottom - ); +// import { Meteor } from 'meteor/meteor'; +// import React, {useState, useEffect, Suspense} from 'react'; +// import { useTracker, useFind } from 'meteor/react-meteor-data/suspense'; + +// import { FilesCol } from '/imports/api/files.js'; +import { useNavigate, Link } from 'react-router-dom'; + +// import { Roles } from 'meteor/roles'; +// import { useUserContext } from '/imports/api/contexts/AppContext'; +// import { groupBy } from 'lodash'; + +//import Radium from 'radium'; + + +// const IndicadorMissatges = ({notif}) => { +// return +// {notif && } +// +// ; +// }; + +const U = ({u, esAdministrador}) => { + + // const [esAdministrador, setEsAdministrador] = useState(false); + +// const u = useTracker("user", async () => await Meteor.userAsync()); +// const userId = Meteor.userId(); + + + // useEffect(() => { + // (async () => { + // const comprovaAdmin = await Roles.userIsInRoleAsync(userId, ["admin"]); + // setEsAdministrador(comprovaAdmin); + // })(); + // }, [Meteor.userId()]); + + // const u = useUserContext(); + + + // console.log("UUU: ", u); + + const navigate = useNavigate(); + // const files = useTracker(() => { + // const filesHandle = Meteor.subscribe('files.avatar'); + // // const docsReadyYet = filesHandle.ready(); + // const files = FilesCol?.find({"meta.userId": Meteor.userId()}, {sort: {name: 1}}).fetch(); // Meteor.userId() ?? "nop" + + // return files; + // }); + +// const uname = useTracker(() => Meteor.user({ fields: { 'username': 1 } })?.username ); + +// const [mostraMenu, setMostraMenu] = useState(false); + + //const avatarLink = u.avatarLink; + + // alert("avLnk: ", u.profile.avatarLink); + + return +
    { + // setMostraMenu(true); + // }} + + // title="Logout" + + onClick={ev => { + ev.stopPropagation(); + ev.preventDefault(); + + // console.log("u: ", u); + + navigate(`/${u.username}`); + + }} + > + { (u && esAdministrador) &&
    ADMIN
    } + + + {u?.username} + + { + ev.preventDefault(); + ev.stopPropagation(); + + alert("Click en missatges"); + }} + > + {/* */} + +
    + { + // mostraMenu && + //
    { + // // setMostraMenu(false); + // // }} + // > + // {/* */} + //
    { + // //setEditaPerfil(true); + // ev.stopPropagation(); + // ev.preventDefault(); + + // navigate(`/c/config`); + + // }} + // >Configuración
    + // {/* */} + + //
    { + // Meteor.logout(err => { + // err && alert(`Problema: ${err}`); + // }); + // navigate(`/`); + // }} + // >Cierra la sesión
    + //
    + } +

    +
    ; }; -const AssignadorDeRols = ({pobles, ambitGeneral, esEditor, rols, usrSeleccionat}) => { - const [creantRol, setCreantRol] = useState(false); - const [ambitsUSel, setAmbitsUSel] = useState([]); - - useEffect(() => { - (async () => { - const ambits = await Roles.getScopesForUserAsync(usrSeleccionat?._id); - setAmbitsUSel(ambits); - })(); - }, []); - - return
    -

    Rols

    - -

    Àmbits

    -
    General:
    -
      { - rols?.map(uRol =>
    • - {uRol} - {esEditor && } -
    • ) - }
    - - {/*
      */} - { - ambitsUSel?.map(async aus => { - - const uRol = await Roles.getRolesForUserAsync(usrSeleccionat._id, {scope: aus, onlyScoped: true}); - return <> -
      {aus}:
      - { - {uRol} - {esEditor && } - - }
      - ; - }) - } - {/*
    */} - - {esEditor && creantRol &&
    -
    { - Meteor.callAsync('assignaRol', usrSeleccionat._id, d.get('selRol'), d.get('selAmbit')); - }}> - - Àmbit:
    - - Rol:

    - - - -
    -
    } - - {esEditor && usrSeleccionat && } -
    ; -}; export const Usuaris = () => { - const refQuadreSeleccionat = useRef(); + const [usrSeleccionat, setUsrSeleccionat] = useState(null); - useSubscribe('pobles'); const pobles = useTracker("pobles", () => PoblesCollection.find().fetchAsync()); @@ -162,17 +213,10 @@ export const Usuaris = () => { const usuaris = useTracker("usuaris", () => { Meteor.subscribe('usuaris'); - return Meteor.users.find().fetch()//.filter(u => u._id !== Meteor.userId()); + return Meteor.users.find().fetch();//.filter(u => u._id !== Meteor.userId()); }); - - const rols = useTracker("rols", async () => { - return await Roles.getRolesForUserAsync(usrSeleccionat?._id); - }); - - // console.log("rols: ", rols); - // console.log("isAdmin: ", isAdmin) ; - // console.log("usuaris: ", usuaris); + console.log("usuaris: ", usuaris); // (async () => { useEffect(() => { (async () => { @@ -183,34 +227,15 @@ export const Usuaris = () => { }, []); // })(); - const QuadreInfo_Usuari = () => { - - // const [rols, setRols] = useState([]); - - const [ambitGeneral, setAmbitGeneral] = useState(false); - - - let allScopes; - - // useEffect( async () => { - // allScopes = await Roles.getScopesForUserAsync(usrSeleccionat?._id); - // // Roles.getRolesForUser(usrSeleccionat?._id).map(uRol =>
  • {uRol}
  • ); - - // // setRols(rols); - // }); - - return
    + display: `inline-block`, + border: `1px solid #6666`, + padding: `.5rem`, + borderRadius: `.3em`, + backgroundColor: `lightcyan` + }}> {usrSeleccionat &&

    {usrSeleccionat._id}

    } @@ -233,55 +258,48 @@ export const Usuaris = () => { >

    - - - +
    + - - { esEditor && } -
    ; }; - return
    { - !isClickInsideRectangle(ev, refQuadreSeleccionat.current) && setUsrSeleccionat(null); - }}>Carregant...} > - + return Carregant...} >

    Usuaris

    - { esEditor && usrSeleccionat && } + { esEditor && }
      { usuaris .sort((a,b) => a.username?.toLowerCase() > b.username?.toLowerCase()) .map(usr =>
    • - {usr.username}{esEditor && }
    • ) + {/* {usr.username}{esEditor && } */} + + ) }
    - - {esEditor && !usrSeleccionat && } - -
    ; + ; }; \ No newline at end of file From c8790f1005b481107e86bda1e922127a3f0ed290 Mon Sep 17 00:00:00 2001 From: Pasq G Date: Sat, 4 Jan 2025 23:08:42 +0100 Subject: [PATCH 09/14] Rols visibles a Usuaris --- imports/ui/Usuaris.jsx | 92 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/imports/ui/Usuaris.jsx b/imports/ui/Usuaris.jsx index 8873b5a..afadf0c 100644 --- a/imports/ui/Usuaris.jsx +++ b/imports/ui/Usuaris.jsx @@ -38,6 +38,30 @@ import { useNavigate, Link } from 'react-router-dom'; const U = ({u, esAdministrador}) => { + const [adm, setAdm] = useState(false); + const [mon, setMon] = useState(false); + const [enc, setEnc] = useState(false); + const [vol, setVol] = useState(false); + + (async () => { + const esAdmin = await Roles.userIsInRoleAsync(u._id, ["admin"]); + setAdm(esAdmin); + const esMonit = await Roles.userIsInRoleAsync(u._id, ["monitor_de_poble"], {anyScope: true}); + setMon(esMonit); + const esEncar = await Roles.userIsInRoleAsync(u._id, ["encarregat_de_tasques"], {anyScope: true}); + setEnc(esEncar); + const esVolun = await Roles.userIsInRoleAsync(u._id, ["voluntari_de_poble"], {anyScope: true}); + setVol(esVolun); + // setEsAdministrador(comprovaAdmin); + })(); + + + // console.log("adm: ", adm); + // console.log("mon: ", mon); + // console.log("enc: ", enc); + // console.log("vol: ", vol); + + // const [esAdministrador, setEsAdministrador] = useState(false); // const u = useTracker("user", async () => await Meteor.userAsync()); @@ -109,11 +133,30 @@ const U = ({u, esAdministrador}) => { }} > - { (u && esAdministrador) &&
    ADMIN
    } +
    + { (u && adm) &&
    ADMIN
    } + { (u && mon) &&
    mon
    } + { (u && enc) &&
    enc
    } + { (u && vol) &&
    vol
    } +
    { }, []); // })(); + // const [monitors, setMonitors] = useState(false); + // const [encarregats, setEncarregats] = useState(false); + // const [voluntaris, setVoluntaris] = useState(false); + // const [administradors, setAdministradors] = useState(false); + + // let mon, mons, enc, encs, vol, vols; + // let + // administradors, + // monitors, + // encarregats, + // voluntaris + // ; + + + // (async () => { + // const admins = await Roles.getUsersInRoleAsync("administrador"); + // // console.log("admins: ", admins); + // administradors = await admins?.fetchAsync(); + // console.log("administradors: ", administradors); + + // const mons = await Roles.getUsersInRoleAsync("monitor_de_poble"); + // // console.log("mons: ", mons); + // monitors = await mons?.fetchAsync(); + // console.log("monitors: ", monitors); + + // const encs = await Roles.getUsersInRoleAsync("encarregat_de_tasques"); + // // console.log("encs: ", encs); + // encarregats = await encs?.fetchAsync(); + // console.log("encarregats: ", encarregats); + + // const vols = await Roles.getUsersInRoleAsync("voluntari_de_poble"); + // // console.log("vols: ", vols); + // voluntaris = await vols?.fetchAsync(); + // console.log("voluntaris: ", voluntaris); + // })(); + + const QuadreInfo_Usuari = () => { return
    { }} > {/* {usr.username}{esEditor && } */} - + ) } ; From d6e1329d798c865fc355a3d60b9e65109213f507 Mon Sep 17 00:00:00 2001 From: Pasq G Date: Tue, 7 Jan 2025 12:08:38 +0100 Subject: [PATCH 10/14] codis_0 --- imports/ui/Codis.jsx | 250 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 imports/ui/Codis.jsx diff --git a/imports/ui/Codis.jsx b/imports/ui/Codis.jsx new file mode 100644 index 0000000..b22ce5f --- /dev/null +++ b/imports/ui/Codis.jsx @@ -0,0 +1,250 @@ +import React, { Suspense, useEffect, useState, useRef, lazy } from 'react'; +import { Meteor } from 'meteor/meteor';; +import { NecessitatsCollection } from '/imports/api/necessitats.js'; +import { PoblesCollection } from '../api/pobles'; +import { TipusCollection } from '../api/tipus'; +import { useSubscribe, useTracker, useFind } from 'meteor/react-meteor-data/suspense'; +import { Roles } from 'meteor/roles'; +// import { useUserId } from 'meteor/react-meteor-accounts'; +import Select from 'react-select'; + +import CreatableSelect from 'react-select/creatable'; +import AsyncCreatableSelect from 'react-select/async-creatable'; +import { BarraNav } from "./BarraNav/BarraNav"; + + + + +export const Codis = () => { + + // const [permes, setPermes] = useState(false); + const [esEditor, setEsEditor] = useState(false); + const userId = Meteor.userId(); + + useEffect(() => { + (async () => { + const comprovaAdmin = await Roles.userIsInRoleAsync(userId, ["admin"]); + setEsEditor(comprovaAdmin); + })(); + }, []); + + // console.log("isAdmin: ", isAdmin) ; + + let ambitSeleccionat = null; + + useSubscribe('necessitats'); + const necessitats = useTracker("necessitats", () => NecessitatsCollection.find().fetchAsync()); + + useSubscribe('pobles'); + const pobles = useTracker("pobles", () => PoblesCollection.find().fetchAsync()); + const ambits = pobles?.map(p => p?.ambitAssociat); + + // console.log("ambits: ", ambits); + + // useSubscribe('tipus'); + // const ambits = useTracker("ambits", () => Collection.find().fetchAsync()); + + // console.log("tipus: ", tipus); + // console.log("necessitats: ", necessitats); + + // console.log("tipusSeleccionat: ", tipusSeleccionat); + + + // const filterAmbit = (inputValue) => { + // return ambits.filter((i) => + // i.toLowerCase().includes(inputValue.toLowerCase()) + // ); + // }; + + const SelectorDeRol = ({ambitSeleccionat}) => { + return <> + + "Crear nou tipus..."} + // filterOption={filterAmbit} + options={ + [... + ambits + .map((v,i) => ({ + value: v, + label: v + })) + .sort((a,b) => a.label.toLowerCase() > b.label.toLowerCase()), + { + value: "GENERAL", + label: "GENERAL" + } + ] + } + // onCreateOption={(inputValue) => Meteor.callAsync('afigT', {titol: inputValue})} + isSearchable + // loadOptions={tipus.map((v,i) => ({value: v, label: v.titol}))} + onChange={ev => { + ambitSeleccionat = ev.value; + console.log("ambitSeleccionat: ", ambitSeleccionat); + + }} + /> + + {/* */} + +
    + + + +
    + + + + +

    + + + + ({value: v._id, label: v.nomPoble})) } /> + {/* */} + +
    + + + + {ambitSeleccionat && esEditor && } + +
    ; + }; + + + return Carregant...} > + + + +

    + + {/* ({value: v, label: v.titol})) } + loadOptions={tipus.map((v,i) => ({value: v, label: v.titol}))} + /> */} + + {/* */} + + +
      { + ambits + .sort((a,b) => a.toLowerCase() > b.toLowerCase()) + .map(amb =>
    • + {amb}{esEditor && } +
    • ) + }
    +
    ; +}; \ No newline at end of file From 945cfa46e32b747d725c512880e534f50c22549c Mon Sep 17 00:00:00 2001 From: Pasq G Date: Tue, 7 Jan 2025 21:58:03 +0100 Subject: [PATCH 11/14] codis_1 --- imports/ui/BarraNav/BarraNav.jsx | 5 +++++ imports/ui/BarraNav/PanellSeccions/PanellSeccions.jsx | 10 ++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/imports/ui/BarraNav/BarraNav.jsx b/imports/ui/BarraNav/BarraNav.jsx index 6e7dc86..a071deb 100644 --- a/imports/ui/BarraNav/BarraNav.jsx +++ b/imports/ui/BarraNav/BarraNav.jsx @@ -19,6 +19,10 @@ const SeccióUsuaris = lazy(async () => { const module = await import('/imports/ui/BarraNav/PanellSeccions/PanellSeccions.jsx'); return ({ default: module.SeccióUsuaris }); }); +const SeccióCodis = lazy(async () => { + const module = await import('/imports/ui/BarraNav/PanellSeccions/PanellSeccions.jsx'); + return ({ default: module.SeccióCodis }); +}); const BarraNav = ({esAdministrador, setEsAdministrador}) => { const userId = Meteor.userId(); @@ -38,6 +42,7 @@ const BarraNav = ({esAdministrador, setEsAdministrador}) => { + ; }; diff --git a/imports/ui/BarraNav/PanellSeccions/PanellSeccions.jsx b/imports/ui/BarraNav/PanellSeccions/PanellSeccions.jsx index ead6caf..8092e6a 100644 --- a/imports/ui/BarraNav/PanellSeccions/PanellSeccions.jsx +++ b/imports/ui/BarraNav/PanellSeccions/PanellSeccions.jsx @@ -34,15 +34,21 @@ export const SeccióUsuaris = () => ; +export const SeccióCodis = () => ; + export const PanellSeccions = ({children}) => { return <>
    {children}

    ; }; - From 182c1025acc727134fd45ba7efbed4dee3cd9591 Mon Sep 17 00:00:00 2001 From: Pasq G Date: Wed, 8 Jan 2025 00:55:39 +0100 Subject: [PATCH 12/14] Unmessing. Abans de provar les solucions de kapa ai --- imports/ui/Usuaris.jsx | 269 ++++++++++++++++++++++++++++++++--------- 1 file changed, 215 insertions(+), 54 deletions(-) diff --git a/imports/ui/Usuaris.jsx b/imports/ui/Usuaris.jsx index afadf0c..0dece71 100644 --- a/imports/ui/Usuaris.jsx +++ b/imports/ui/Usuaris.jsx @@ -36,7 +36,7 @@ import { useNavigate, Link } from 'react-router-dom'; //
    ; // }; -const U = ({u, esAdministrador}) => { +const U = ({u, esAdministrador, setUsrSeleccionat}) => { const [adm, setAdm] = useState(false); const [mon, setMon] = useState(false); @@ -99,6 +99,7 @@ const U = ({u, esAdministrador}) => { return
    { ev.preventDefault(); ev.stopPropagation(); - alert("Click en missatges"); + // alert("Click en missatges"); }} > + {} {/* */}
    @@ -245,6 +247,193 @@ const U = ({u, esAdministrador}) => { }; + +const AssignadorDeRols = ({pobles, ambitGeneral, esEditor, rols, usrSeleccionat, ambitsUSel}) => { + const [creantRol, setCreantRol] = useState(false); + // const [ambitsUSel, setAmbitsUSel] = useState([]); + // let ambitsUSel; + // let ambitsUSel = []; + // useEffect(() => { + // (async () => { + // const ambits = await Roles.getScopesForUserAsync(usrSeleccionat?._id); + // // console.log("ambitsUSel: ", ambitsUSel); + // // ambitsUSel = ambits; + // // setAmbitsUSel(ambits); + // ambitsUSel = ambits; + // // console.log("ambitsUSel: ", ambitsUSel); + // })(); + // }, []); + + return
    +

    Rols

    + +

    Àmbits

    +
    General:
    +
      { + rols?.map(uRol =>
    • + {uRol} + {esEditor && } +
    • ) + }
    + + {/*
      */} + { + ambitsUSel.map(async aus => { + + console.log("usrSeleccionat: ", usrSeleccionat); + console.log("ambitsUSel: ", ambitsUSel); + const uRol = await Roles.getRolesForUserAsync(usrSeleccionat._id, {scope: aus, onlyScoped: true}); + return <> +
      {aus}:
      + { + {uRol} + {esEditor && } + + }
      + ; + }) + } + {/*
    */} + + {esEditor && creantRol &&
    +
    { + Meteor.callAsync('assignaRol', usrSeleccionat._id, d.get('selRol'), d.get('selAmbit')); + }}> + + Àmbit:
    + + Rol:

    + + + +
    +
    } + + {esEditor && usrSeleccionat && } +
    ; +}; + +const QuadreInfo_Usuari = ({usrSeleccionat, esEditor, pobles, rols, ambitsUSel}) => { + + return
    + + {usrSeleccionat &&

    {usrSeleccionat._id}

    } + +
    { + try { + Meteor.callAsync('editaOAfigPoble', + { + ...usrSeleccionat || [], + nomPoble: d.get('nomPoble'), + cp: d.get('cp') || "", + comarca: d.get('comarca') || "", + }).then(() => setUsrSeleccionat(null)) + .catch(err => console.error(err)); + } catch (err) { + alert(err); + console.error(err); + } + }} + > +
    +
    +
    + + +
    + + { esEditor && } +
    ; +}; + + export const Usuaris = () => { const [usrSeleccionat, setUsrSeleccionat] = useState(null); @@ -260,14 +449,28 @@ export const Usuaris = () => { }); // console.log("isAdmin: ", isAdmin) ; console.log("usuaris: ", usuaris); + + // const [ambitsUSel, setAmbitsUSel] = useState([]); // (async () => { - useEffect(() => { - (async () => { - const comprovaAdmin = await Roles.userIsInRoleAsync(userId, ["admin"]); - setEsEditor(comprovaAdmin); - })(); - - }, []); + + let ambitsUSel = []; + + useEffect(() => { + (async () => { + const comprovaAdmin = await Roles.userIsInRoleAsync(userId, ["admin"]); + setEsEditor(comprovaAdmin); + + const ambits = await Roles.getScopesForUserAsync(usrSeleccionat?._id); + setAmbitsUSel(ambits); + // console.log("ambitsUSel: ", ambitsUSel); + })(); + + }, []); + + + const rols = useTracker("rols", async () => { + return await Roles.getRolesForUserAsync(usrSeleccionat?._id); + }); // })(); // const [monitors, setMonitors] = useState(false); @@ -307,54 +510,12 @@ export const Usuaris = () => { // })(); - const QuadreInfo_Usuari = () => { - - return
    - - {usrSeleccionat &&

    {usrSeleccionat._id}

    } - -
    { - try { - Meteor.callAsync('editaOAfigPoble', - { - ...usrSeleccionat || [], - nomPoble: d.get('nomPoble'), - cp: d.get('cp') || "", - comarca: d.get('comarca') || "", - }).then(() => setUsrSeleccionat(null)) - .catch(err => console.error(err)); - } catch (err) { - alert(err); - console.error(err); - } - }} - > -
    -
    -
    - - -
    -
    ; - }; + return Carregant...} >

    Usuaris

    - { esEditor && } + { esEditor && }
      { }} > {/* {usr.username}{esEditor && } */} - + ) }
    ; From 6efa6956d7ea7145a8281354edc5b32a70f77bd0 Mon Sep 17 00:00:00 2001 From: Pasq G Date: Wed, 8 Jan 2025 01:32:40 +0100 Subject: [PATCH 13/14] =?UTF-8?q?Resolt=20problema=20amb=20versi=C3=B3=20s?= =?UTF-8?q?=C3=ADncrona?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- imports/ui/Usuaris.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/imports/ui/Usuaris.jsx b/imports/ui/Usuaris.jsx index 0dece71..0e7929f 100644 --- a/imports/ui/Usuaris.jsx +++ b/imports/ui/Usuaris.jsx @@ -212,7 +212,7 @@ const U = ({u, esAdministrador, setUsrSeleccionat}) => { // zIndex: `200` // }} // // onMouseLeave={ev => { - // // setMostraMenu(false); + // // setMostraMenu(false);p // // }} // > // {/* */} @@ -453,20 +453,21 @@ export const Usuaris = () => { // const [ambitsUSel, setAmbitsUSel] = useState([]); // (async () => { - let ambitsUSel = []; + // let ambitsUSel = []; useEffect(() => { (async () => { const comprovaAdmin = await Roles.userIsInRoleAsync(userId, ["admin"]); setEsEditor(comprovaAdmin); - const ambits = await Roles.getScopesForUserAsync(usrSeleccionat?._id); - setAmbitsUSel(ambits); // console.log("ambitsUSel: ", ambitsUSel); })(); }, []); + const ambitsUSel = Roles.getScopesForUser(usrSeleccionat?._id); + // setAmbitsUSel(ambits); + const rols = useTracker("rols", async () => { return await Roles.getRolesForUserAsync(usrSeleccionat?._id); From 8c679009528c90ad51fccfb880ccb3bf6200af8b Mon Sep 17 00:00:00 2001 From: Pasq G Date: Wed, 8 Jan 2025 03:05:30 +0100 Subject: [PATCH 14/14] =?UTF-8?q?Assignaci=C3=B3=20de=20rol=20admin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- imports/ui/BarraNav/BarraNav.jsx | 2 +- imports/ui/Usuaris.jsx | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/imports/ui/BarraNav/BarraNav.jsx b/imports/ui/BarraNav/BarraNav.jsx index a071deb..ed46184 100644 --- a/imports/ui/BarraNav/BarraNav.jsx +++ b/imports/ui/BarraNav/BarraNav.jsx @@ -42,7 +42,7 @@ const BarraNav = ({esAdministrador, setEsAdministrador}) => { - + { esAdministrador && } ; }; diff --git a/imports/ui/Usuaris.jsx b/imports/ui/Usuaris.jsx index 0e7929f..a1f0955 100644 --- a/imports/ui/Usuaris.jsx +++ b/imports/ui/Usuaris.jsx @@ -248,8 +248,9 @@ const U = ({u, esAdministrador, setUsrSeleccionat}) => { -const AssignadorDeRols = ({pobles, ambitGeneral, esEditor, rols, usrSeleccionat, ambitsUSel}) => { +const AssignadorDeRols = ({pobles, esEditor, rols, usrSeleccionat, ambitsUSel}) => { const [creantRol, setCreantRol] = useState(false); + const [ambitGeneral, setAmbitGeneral] = useState(false); // const [ambitsUSel, setAmbitsUSel] = useState([]); // let ambitsUSel; // let ambitsUSel = []; @@ -342,16 +343,20 @@ const AssignadorDeRols = ({pobles, ambitGeneral, esEditor, rols, usrSeleccionat, backgroundColor: `#fffa` }}>
    { - Meteor.callAsync('assignaRol', usrSeleccionat._id, d.get('selRol'), d.get('selAmbit')); + if (ambitGeneral) { + Meteor.callAsync('assignaRol', usrSeleccionat._id, d.get('selRol')); + } else { + Meteor.callAsync('assignaRol', usrSeleccionat._id, d.get('selRol'), d.get('selAmbit')); + } }}> Àmbit:
    Rol: