Hola! Aquest és el nostre lloc de coneixement compartit i obert a tothom
Coopdevs és una cooperativa oberta que té com objectiu millorar la societat a través de la tecnologia, els nostres valors s’emmarquen dins del cooperativisme obert el que significa que ens centrem a aportar valor no sols a clients o projectes en què participem sinó a un ecosistema de procomuns digitals molt més ampli.
Pots trobar el codi que desenvolupem a:
Coopdevs s’organitza de manera horitzontal i pren les decisions de manera assembleària.
Pots consultar les persones que actualment formem part de l’equip de Coopdevs a https://coopdevs.coop/qui-som
Per més informació sobre el cooperativisme llegir Ser soci d’una cooperativa
Ens organitzem per comissions de treball, equips de treball amb objectius i activitats concrets aprovats per l’assemblea.
Juntament amb grups de treball o projectes destacats amb una durada més acotada, pots consultar els assumptes/comissions que repassem a cada reunió review mensual
Fes una ullada a la entrada del blog La importància de trobar-nos
Vam fer uns estatuts bastant estàndards al 2018 en la fundació de la cooperativa, és un marc legal juntament amb la Llei de cooperatives de Catalunya
El reglament de regim intern (RRI) és un document viu on nom especificant com ens organitzem i els acords als que hem arribat assembleariament, per això fem diverses versions de RRI aprovats.
Carpeta on tenim les diverses versions del nostre RRI
A Coopdevs, totes les treballadores tenim el mateix sou.
El salari és quelcom que totes necessitem per viure però no creiem que hagi de representar una recompensa variable segons el valor que cada treballadora aporta a la empresa, representaria una tasca impossible i injusta valorar diferències d’aportació de valor entre les treballadores a una organització com la nostra on totes participem de manera igualitària en la seva governança.
Coopdevs treballa sols per projectes de l’Economia Social i Solidària, en un sentit ampli això pot incloure projectes per entitats com associacions, fundacions, cooperatives o bé per l’administració pública. Sigui quina sigui la forma jurídica dels nostres clients per nosaltres és molt important que el seus valors s’emmarquin en els principis de l’ESS i que a ells també els encaixin els nostres principis relatius a la tecnologia:
A continuació deixem un index amb les pàgines més destacades del handbook, pero afegim noves pàgines amb certa freqüència, per trobar més contiguts fes servir el cercador
Support:
Traduccions:
Documentació Mòduls:
select
case when "isFolder"=True then '#'||repeat('#',depth)||' '||repeat(' ',(depth-1)*2)||title
else '* ['||title||'](/'||path||')'
end as text
from "pageTree"
where "localeCode"='ca'
order by SPLIT_PART(path,'/',1)
,case when SPLIT_PART(path,'/',2) is null or depth<2 then 'aaaaaaaaaaaaaa'
when not "isFolder" and depth=2 then 'aaaaaaaaaaaaab'
else path end
,case when SPLIT_PART(path,'/',3) is null or depth<3 then 'aaaaaaaaaaaaaa'
when not "isFolder" and depth=3 then 'aaaaaaaaaaaaab'
else path end
,case when SPLIT_PART(path,'/',4) is null or depth<4 then 'aaaaaaaaaaaaaa'
when not "isFolder" and depth=4 then 'aaaaaaaaaaaaab'
else path end
Una pràctica recomenada és fer servir pàgines per a les carpetes virtuals, amb l’objectiu de que no es trenquin els breadcrumbs.
Podem generar un index dinàmic amb els següent passos:
HTML Raw code
con aquest contingut a la ruta de la carpeta virtual. Possa-li el mateix nom que té la carpeta.<h1><span id="section_name"></span> pages</h1>
<hr/>
<div id="pageTree">Loading pages...</div>
<br/>
<br/>
<br/>
<br/>
<br/>
<i id="loadingMessage">If you are reading this, it probably should have loaded by now...</i>
<hr/>
Scripts
, fica el següent text:<script>
function getCurrentPagePath() {
const urlPath = window.location.pathname;
// Removes localization ('en', 'ca'...)
const localePattern = /^\/[a-z]{2}\//; // Adjust if necessary
let path = urlPath.replace(localePattern, '');
document.getElementById('section_name').innerHTML = path;
return path;
}
async function fetchAllPages() {
const graphqlEndpoint = "/graphql";
const query = `
query GetAllPages {
pages{
list(limit: 1000, orderBy: PATH, orderByDirection: ASC) {
id
path
locale
title
createdAt
updatedAt
}
}
}
`;
try {
const response = await fetch(graphqlEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ query })
});
if (!response.ok) {
throw new Error(`Network error: ${response.statusText}`);
}
const jsonResponse = await response.json();
return jsonResponse.data.pages.list;
} catch (error) {
console.error('Fetching all pages failed:', error);
return []; // Return an empty array on failure
}
}
function generateTree(pages) {
const root = { children: [] };
const currentPagePath = getCurrentPagePath();
pages.forEach(page => {
if (page.path.startsWith(currentPagePath) && page.path !== currentPagePath) {
const relativePath = page.path.substring(currentPagePath.length);
console.log(relativePath);
const parts = relativePath.split('/').filter(Boolean);
let current = root;
parts.forEach((part, index) => {
let child = current.children.find(child => child.name === part);
if (!child) {
child = { name: part, children: [], page: null };
current.children.push(child);
}
current = child;
});
current.page = page;
}
});
return root;
}
function buildHtmlFromTree(node) {
let html = '';
node.children.forEach(child => {
if (child.children.length === 0) {
if (child.page) {
const pageLink = `<a href="/ca/${child.page.path}">${child.page.title}</a>`;
html += `<li>${pageLink}</li>`;
} else {
html += `<h2>${child.name}</h2>`;
}
} else {
const pageLink = child.page ? `<a href="/ca/${child.page.path}">${child.page.title}</a>` : child.name;
html += `<section><h2>${pageLink}</h2>${buildHtmlFromTree(child)}</section>`;
}
});
if (node.children.length > 0) {
html = `<ul>${html}</ul>`;
}
return html;
}
function removeElement(id) {
var elem = document.getElementById(id);
return elem.parentNode.removeChild(elem);
}
async function displayPageTree() {
try {
const pages = await fetchAllPages();
currentPath = getCurrentPagePath();
const descendantPages = pages.filter(page => {
const startsWithCurrentPath = page.path.startsWith(currentPath);
const isNotCurrentPath = page.path !== currentPath;
return startsWithCurrentPath && isNotCurrentPath;
});
if (descendantPages.length === 0) {
document.getElementById('loadingMessage').innerHTML = '<p>No descendant pages found.</p>';
return;
}
const treeRoot = generateTree(descendantPages);
if (treeRoot.children.length === 0) {
document.getElementById('loadingMessage').innerHTML = '<p>The tree could not be built.</p>';
return;
}
const treeHtml = buildHtmlFromTree(treeRoot);
document.getElementById('pageTree').innerHTML = treeHtml;
removeElement('loadingMessage');
} catch (error) {
console.error('Error displaying page tree:', error);
document.getElementById('loadingMessage').innerHTML = '<p>Failed to load the page tree. Please try again later.</p>';
}
}
window.boot.register('page-ready', () => {
displayPageTree();
});
</script>