Aplicatie de Management Si Colaborare Intr Un Ong

Aplicatie de managment si colaborare intr-un ONG

Cuprins:

NOȚUNI INTRODUCTIVE

Prezentarea lucrării

ANALIZĂ

Analiza de proiectare

Scopul Aplicației

Studiul concurenței

Aria de acoperire a aplicației

Perspectiva structurală

Perspectiva fizică

Analiza de business

În ce constă aplicația?

Ce probleme rezolvă?

Aplicabilitatea metodologiei AGILE în cadrul proiectului

Cum se face management de proiect în ONG-uri

IMPLEMENTARE

De ce am ales arhitectura REST

Șabloane arhitecturale

Implementarea serverului folosind MVC

Implementarea clientului folosind MVVM

Limbaje de programare și frameworkuri folosite

HTML5

CSS3

Cloud Computing

Open Source

Semantic UI

Bootstrap

Javascript

Arhitectura Aplicatiei

MEAN stack web development

MongoDB

Express

AngularJS

Node.JS

PREZENTAREA APLICAȚIEI

4.1. Modele de date

4.2. Configurare client (AngularJS)

4.2.1. Directive folosite in cadrul proiectului

4.2.1.1. header-admin

4.2.1.2. ng-enter

4.2.1.3. loading

4.2.1.4. my-date-picker

4.3. Configurare server (NodeJs)

4.4. Implementare

4.4.1. Înregistrarea unui user

4.4.2. Login

4.4.3. Crearea unei organizații

4.4.4. Crearea unui proiect

4.4.5. Crearea unui task

4.4.6. Adaugarea unei activități asociatia unui proiect

4.4.7. Secțiunea de blog

4.4.8. Secțiunea de ședințe

4.4.9. Adăugarea unui membru într-o organizație

CONCLUZII

Bibliografie

1. NOȚIUNI INTRODUCTIVE

De cațiva ani buni, în industria IT, se duce o luptă cu eficientizarea proceselor de management în diferite domenii. Astfel, domeniile în care este prezentă Tehnologia Informației sunt din ce în ce mai numeroase. Unul dintre domeniile foarte puțin băgate în seama, este acela al voluntariatului. De aceea, având expertiză în acest domeniu și descoperind care sunt atât nevoile unui manager de proiect cât și nevoile unui voluntar obișnuit m-am decis să fac o aplicație care să rezolve problemele de comunicare folosind unele dintre cele mai noi tehnologii ale momentului.

Vreau să îmi pun ambiția și priceperea la încercare pentru a realiza o aplicație care să ajute project managerii dintr-un ONG. Experiența mea în cadrul unui ONG este una completă și complexă și de aceea am avut ocazia să remarc o nevoie foarte pregnantă în încercarea de a găsi cea mai eficientă metodă de project management. Chiar și eu, când am fost project manager m-am confruntat cu această problemă, nevoia de a gasi o alternativă la facebook atunci când se face project management. Întrucât Facebook este platformă de socializare nu un tool de project management, îngreunează comunicarea eficientă în cazul în care este folosit pentru a discuta sau hotarâ lucruri ce țin de un proiect. Această aplicație ar rezova și o problemă des întâlnită în echipele în continuă schimbare, și anume moștenirea cunoștințelor despre proiectele care se repetă anual.

Ideea unei aplicații de project management nu este unică. Pe piață la momentul actual sunt mai multe aplicații web care încearcă să rezolve această problemă, însă nici una nu are ca obiect/scop project managementul în cadrul unui ONG. Ce diferentiază ideea mea de alte aplicații asemănătoare este sistemul de motivare. Astfel, voi realiza o aplicație de tip task manager care va avea în componență un sistem de motivare pentru rezolvarea taskurilor.

Pe lângă asta din punctul meu de vedere ar fi interesantă și integrarea unei metodologii de project management asemanatoare cu Agile – Scrum din software development, adaptate la project managementul pentru proiectele unui ONG. Consider că integrarea cu această metodologie ar aduce un plus si din punct de vedere personal pentru fiecare user, aducându-i la cunoștință niște principii foarte sănătoase de project management, care îl pot ajuta în carieră.

Prezentarea lucrării

Ideea dezvoltarii acestei aplicații a plecat de la o provocare personală și pot spune că am reușit să dezvolt o aplicație folosind cele mai noi tehnologii ale momentului. În răndurile acestei lucrări am descris întregul proces de dezvoltare al acestei soluții.

Lucrarea se împarte în cinci capitole după cum urmează:

1. NOȚIUNI INTRODUCTIVE

Cuprinde prezentarea lucrării împreună cu o scurtă descriere a ideii.

2. ANALIZĂ

Cuprinde o prezentare o serie de analize detaliate asupra ideii abordate. Tot în acest capitol sunt prezentate succint și cele două concepte non-tehnice ce constituie tematica lucrării, acestea sunt: project management în ONG-uri și aplicabilitatea metodologiei AGILE din software development în acest proiect, acest lucru având ca scop îmbunătățirea modului în care se face project management în ONG-uri.

3. IMPLEMENTARE

Prezentarea detaliată a tehnologiilor folosite în dezvoltarea aplicației precum și arhitectura aplicației. Este prezentat în detaliu modul în care acestea conlucrează.

4. PREZENTAREA APLICAȚIEI

În cadrul acestui capitol va fi prezentată aplicația din punct de vedere funcțional și vor fi evidențiate anumite elemente care stau la baza implementării funcționalității ei.

5. CONCLUZII

În ultimul capitol al lucrării se face o ultimă analiză a lucrării și se trag concluziile legat de produsul final și sansele sale de dezvoltare.

2. ANALIZĂ

2.1 Analiza de Proiectare

1.2.1. Scopul aplicației

Scopul principal al aplicației Task Heroes este să înbunătățească colaborarea și managementul în cadrul proiectelor realizate de ONG­uri. Mai mult de atât, cu ajutorul unui sistem de ranking se menține motivarea și engagement­ul userilor pentru a se bucura de beneficiile aduse de folosirea acestei platforme în managementul unui ONG. Datorită profilurilor publice atât pentru useri cât și pentru organizații se încurajează competiția constructivă și colaborarea inter ONG­uri pentru realizarea unori proiecte comune.

Beneficiile pe care un ONG le poate avea odată cu folosirea platformei noastre sunt:

Din punct de vedere al resurselor umane:

Evidența datelor personale/ de contact ale tuturor voluntarilor într­un singur loc.

Evidența trainingurilor realizate de fiecare membru.

Evidența activității fiecărui membru.

Evidența intereselor și a aptitudinilor fiecărui membru.

Recrutarea online cu ajutorul platformei

Evidența tuturor aplicanților în perioada de recrutări

Din punct de vedere al relațiilor publice:

Profilul public al organizației poate fi folosit drept mapă de prezentare a organizației online

Se pot publica posturi în sectiunea de Blog, pentru a­și promova proiectele printre ceilalți useri ai platformei.

Din punct de vedere al unui user în general:

Profilul public este oglinda acelui user ca voluntar, legitimitatea punctajului acumulat și al aptitudinilor prezente pe profilul sau sunt garantate de faptul ca taskurile și punctajele au fost aprobate de project manageri sau adminii organizației.

Intelegerea mai buna a modului de organizare sistematic al taskurilor în cadrul unui proiect, acest lucru ajutandu­l mai tarziu și în carieră fiindui mai usor sa se adapteze unui sistem de management de tip AGILE cu iterații și evaluarea continuă a rezultatelor.

Dacă este manager de proiect are în permanență evidența taskurilor realizate.

În cazul în care proiectele se repetă anual, un project manager nou are avantajul consultării modului în care a fost realizat în trecut acel proiect precum și feedback­ul opținut pentru a nu mai repeta greșeli și în același timp pentru a aduce înbunătățiri.

Având în vedere cele spuse mai sus, se constată necesitatea elaborării unui set de roluri și privilegii pentru useri pentru asigurarea funcționarii optime a aplicatiei.

Roluri:

Admini de organizatie,

Project manageri

Useri obișnuiți.

Privilegii:

Oricine poate crea proiecte.

Doar adminii de organizatie pot adăuga membrii în organizație

Doar project managerul și adminii de organizatie pot adăuga oameni în proiect.

Oricine poate crea, edita și șterge taskuriș.

Doar project managerul și adminii de organizație pot aproba rezolvarea taskurilor.

Workflow Task

La fiecare task se poate asigna unul sau mai multe persoane, fiecare task va avea un punctaj care se va acorda celui care il rezolvă, punctajul se acordă doar dupa ce project managerul aprobă rezolvarea acelui task. Dacă sunt mai multe persoane asignate la acel task, punctajul se va împărții la numarul de persoane. În funcție de punctajul strâns fiecare user va avea o titulatură și un avatar de erou, din ce în ce mai puternic.

1.2.2. Studiul concurenței

Există deja aplicații care rezolvă mai mult sau mai puțin o parte din problemele expuse mai sus. Cei doi competitori principali sunt Trello și Wunderlist, ambele se prezintă sub formă de website și aplicație mobilă, iar Wunderlist este disponibilă și pentru Apple Watch din Aprilie 2015. Cele două soluții sunt foarte populare, însă nici una dintre acestea nu oferă un sistem de motivare și nu sunt adresate în mod special organizațiilor non-guvernamentale.

Dezavantajul acestor două soluții este faptul că, prin design-ul lor, nu permit nicio facilitate prin care să-și mențină clienții motivați. Pe lângă asta, deși sunt compatibile cu orice browser modern sau platformă mobilă. acestea nu prezintă un interes pentru organizațiile non-guvernamentale. În consecință, aceasta aplicație se poate dovedi utilă membrilor acestor asociații, prezentând sistemul acesta prin care să-o mențină motivați.

1.2.3. Aria de acoperire a aplicației

Task Heroes este o aplicatie de tip Task Mș8anager. Ce diferentiază ideea noastră de alte aplicații asemănătoare este sistemul de motivare. Astfel, Task Heroes este o aplicație de tip task manager, doar că nu este una obișnuita, ce diferentiază produsul nostru de alte produse asemănătoare este sistemul de motivare continuă și optimizarea funcționala pentru ca experiența userilor să fie una cat mai fluentă.

Ce diferențiază foarte clar aplicația noastră de alte aplicații având un obiect de activitate asemănător este optimizarea funcțională. Această aplicație are ca scop principal înbunătățirea modului în care se face project management în cadrul unui ONG. Pe această nișă nu există deocamdată o aplicație care să rezolve în mod special problemele pe care un ONG le poate avea. Principalele probleme cu care un ONG se confruntă sunt motivarea voluntarilor, managementul bazei de voluntarș2i, schimbarea continuă de nucleu și în cazul ONG-urilor studențești dinamica schimbării voluntarilor și project managerilor ceea ce face foarte grea moștenirea unui proiect.

Având în vadere că avem în plan și realizarea unor aplicații pentru mobile, acest factor diferențiază Task Heroes față de alte aplicații, mobilitatea fiind vitală în acest mediu, unde majoritatea activităților se desfășoară offline. Oricine trebuie să aibă imediat acces la resursele aplicației în orice moment, acest lucru fiind un punct definitoriu al sporirii user engagementului.

1.2.4. Perspectiva structurală

Figura 1 Arhitectura aplicațiilor folosind MongoDB, NodeJS și AngularJS

Cele 3 mari componente ale aplicației din punct de vedere sutructural sunt:

Server:

Node.js, o platformă open source creată cu scopul de a implementa aplicații Internet scalabile în limbajul JavaScript. Paradigma adoptată este cea bazată pe evenimente, operațiile de intrare/ieșire fiind asincrone (neblocante) – evented I/O.

Un program în Node.js rulează într-un singur proces.

Astfel, Node.js încurajează realizarea de aplicații Web în care interacțiunea cu utilizatorul are loc în timp-real.

Client:

AngularJS este o librărie javascript realizată de Google și multi alți contribuitori din lume în jurul ideei de simplificare a muncii dezvoltatorului web. Astfel, paradigma Model-View-Controller(MVC) a fost introdus și în dezvoltarea web client side. În plus cu ajutorul acestui framework se poate realiza data binding direct în HTML fiind un layer intermediar între Backend și Frontend.

Baza de date:

MongoDB este o bază de date NoSQL open-source orientată pe documente. Acestă bază de date beneficiază de suport din partea compamobilitatea fiind vitală în acest mediu, unde majoritatea activităților se desfășoară offline. Oricine trebuie să aibă imediat acces la resursele aplicației în orice moment, acest lucru fiind un punct definitoriu al sporirii user engagementului.

1.2.4. Perspectiva structurală

Figura 1 Arhitectura aplicațiilor folosind MongoDB, NodeJS și AngularJS

Cele 3 mari componente ale aplicației din punct de vedere sutructural sunt:

Server:

Node.js, o platformă open source creată cu scopul de a implementa aplicații Internet scalabile în limbajul JavaScript. Paradigma adoptată este cea bazată pe evenimente, operațiile de intrare/ieșire fiind asincrone (neblocante) – evented I/O.

Un program în Node.js rulează într-un singur proces.

Astfel, Node.js încurajează realizarea de aplicații Web în care interacțiunea cu utilizatorul are loc în timp-real.

Client:

AngularJS este o librărie javascript realizată de Google și multi alți contribuitori din lume în jurul ideei de simplificare a muncii dezvoltatorului web. Astfel, paradigma Model-View-Controller(MVC) a fost introdus și în dezvoltarea web client side. În plus cu ajutorul acestui framework se poate realiza data binding direct în HTML fiind un layer intermediar între Backend și Frontend.

Baza de date:

MongoDB este o bază de date NoSQL open-source orientată pe documente. Acestă bază de date beneficiază de suport din partea companiei 10gen. MongoDB face parte din familia de sistemelor de baze de date NoSQL. Diferența principală constă în faptul că stocarea datelor nu se face folosind tabele precum într-o bază de date relațională, MongoDB stochează datele sub formă de documente JSON cu scheme dinamice.

1.2.5. Perspectiva fizică

Din punct de vedere fizic, atat aplicatia NodeJS cât și baza de date sunt proiectate pentru a funcționa în cloud ca un serviciu.

Cloud computing, este un concept modern în domeniul computerelor și informaticii, reprezentând un ansamblu distribuit de servicii de calcul, aplicații, acces la informații și stocare de date, fără ca utilizatorul să aibă nevoie să cunoască amplasarea și configurația fizică a sistemelor care furnizează aceste servicii.

Avantaje:

Sincronizarea datelor utilizatorului care folosește mai multe dispozitive legate la cloud (de ex. un smartphone, o tabletă, un notebook, dar și un PC) este simplificată

Documentele online din cloud se pot prelucra cu ajutorul unor aplicații web

Viteză de calcul și capacitate de stocare sporite, dar fără investiții în propria configurație

Datele nu pot fi furate, purtătorul de date nu se poate defecta etc.

2.2. Analiza de business

2.2.1. În ce constă aplicația?

Task Heroes este o aplicație web gratuită de management în cadrul unei organizații, ce folosește metoda de dezvoltare Agile, ce constă în dezvoltare incrementală.

Ceea ce diferențiază această idee de orice alt tip de aplicații asemănătoare, precum Trello, Todoist, Goole Keep, Any.do, Flow, este sistemul de motivare a utilizatorilor. Cele trei tipuri de roluri, Admin, Project Manager și Member, vor putea strânge un număr de puncte pe baza activităților pe care aceștia le-au finalizat. În funcție de punctele cumulate, utilizatorii vor ave drept reward un avatar de ‘erou’ și o ‘titulatură’, ambele fiind upgradabile.

Scopul principal al aplicatiei Task Heroes este sa înbunătățească colaborarea și managementul în cadrul proiectelor realizate de ONG-uri. Mai mult de atat, cu ajutorul unui sistem de ranking se mentine motivarea si engagement-ul userilor pentru a se bucura de beneficiile aduse de folosirea acestei platforme in managementul unui ONG. Datorita profilurilor publice atat pentru useri cat si pentru organizatii se incurajeaza competitia constructiva si colaborarea inter ONG-uri pentru realizarea unori proiecte comune.

2.2.2. Ce probleme rezolvă?

Task Heroes se adresează instițiilor non-guvernamentale, însă ar putea fi folosită, de asemenea, pentru managementul oricărui tip de organizație sau proiect personal. Problemele pe care aceasta le rezolvă sunt: motivarea voluntarilor, managementul bazei de date, schimbarea continuă a flow-ului si managementului. Aceasta aplicatie creaza un mediu propice colaborarii in cadrul proiectelor, prin organizarea tuturor informatiilor intr-un mod user-friendly si motivant pentru viitorii sau actualii membrii ai unei organizatii.

2.3 Aplicabilitatea metodologiei AGILE în cadrul proiectului

Metodele de dezvoltare Agile, este o metodologie adaptivă si se adresează persoanelor care urmăresc atingerea satisfacției clientului prin realizarea unor proiecte care să fie pe deplin funcționale de-a lungul întregului proces de fabricație.

Această metodă necesită patru tipuri de ședințe:

Ședințele zilnice: echipa se reunește în fiecare zi și petrece circa 15 minute, în general în picioare, pentru a răspunde la următoarele trei întrebări: ce am făcut ieri? Ce voi face azi? Cu ce obstacole mă confrunt azi?

Ședințele de planificare: întreaga echipă se adună pentru a decide care sunt funcționalitățile care vor alcătui următorul sprint, și pentru a actualiza lista generală.

Ședințele de revizuire a activității: în timpul acestei ședințe, fiecare membru prezintă ceea ce a făcut pe durata sprintului. Se organizează o demonstrație a noilor funcționalități și o prezentare a arhitecturii. Aceasta este o ședință informală, de două ore, la care participă toată echipa.

Ședințele retrospective: la finalul fiecărui sprint, echipa analizează aspectele care au funcționat bine, precum și pe cele care au funcționat mai puțin bine. În timpul acestei ședințe de 15–30 de minute în care fiecare membru vorbește în nume propriu, se organizează un vot de încredere pentru a decide ce îmbunătățiri trebuie adese.

Figura 2 Bordurile de proiect inspirate de metodologia Agile

1. Bordurile de proiect sunt concepute astfel încât prin folosirea lor proiectul să se realizeze incremental având 4 stadii prin care trece un task:

Backlog – lista transparentă cu taskurile care trebuiesc implementate pe parcursul proiectului

Waiting – lista cu taskuri care au fost selectate ca fiind prioritare de către project manager și care trebuiesc imediat rezolvate, așteptând voluntari.

Doing – lista cu taskurile în desfășurare pentru ca oricine să poată vedea ce se realizează în fiecare moment, astfel realizându-se o comunicare eficientă.

Done – în această lista sunt doua tipuri de taskuri, taskurile finalizate și validate de project manager ca fiind rezolvate și taskurile care așteaptă acceptul project managerului.

2. “Clientul” proiectului unui ONG este beneficiarul/publicul țintă. Acesta poate fi mereu la curent cu ce se întamplă în cadrul dezvoltării unui proiect urmărind proiectul pe profilul public al organizatiei. Cei care pot urmării un proiect sunt selectați de către project manager.

3. Cei care urmăresc proiectul și sunt acceptați de project manager pot trimite feedback în orice moment, acesta fiind vizibil întregii echipe de proiect. În urmă acestui feedback echipa de proiect decide dacă trebuie să mai adauge și alte taskuri în Backlog.

4. Ședințele se pot ține cu ajutorul platformei, echipa de proiect fiind mereu la curent cu cele discutate în cadrul fiecărei ședințe și cu stadiul actual al proiectului.

5. Pe panoul de control al fiecărui user sunt prezente taskurile impartite pe categorii de date, astfel un user va știi mereu ce trebuie să facă în ziua respectivă sau în ziua următoare.

2.4. Cum se face management de proiect în ONG-uri

PROIECTUL reprezintă un set de activități desfășurate într-o perioadă de timp determinată, planificate și controlate și care au drept scop producerea unei schimbări în bine a situației beneficiarilor organizației.

Caracteristicile proiectelor

Iată mai jos câteva elemente caracteristice pentru proiecte:

timp limitat: începutul și sfârșitul proiectului sunt bine delimitate;

echipă de proiect ad hoc: echipa de proiect se constituie în momentul apariției ideii de proiect sau în momentul obținerii finanțării; în multe cazuri aduce împreună persoane care nu au mai colaborat anterior, dar a căror pregătire și experiență și pregătire într-un anumit domeniu le recomandă pentru participarea în cadrul proiectului. Exista cazuri în care echipa de proiect poate fi alcătuită din persoane provenind din instituții, organizații diferite și chiar din țări diferite. O echipă de proiect poate lucra chiar și în condițiile în care membrii săi se întâlnesc numai periodic, ținând legătura prin e-mail, telefonic etc. pe parcursul derulării proiectului.

obiective precise, clar formulate;

rezultate concrete, măsurabile, unice (proiectul livrează un produs sau un serviciu nou, unic, irepetabil);

plan riguros (stabilit inainte de implementarea efectiva a proiectului);

activități interdependente, intercondiționate

resurse limitate: resurse financiare (buget stabilit dinainte), resurse umane, echipamente, dotări, sedii, materii prime și materiale, informație, prestigiu;

schimbare: derularea proiectului produce în mod obligatoriu o schimbare față de starea inițială – de la începutul proiectului;

risc: acțiunile și procesele specifice sunt caracterizate întotdeauna de un grad de risc; managementul riscului prezintă importanță deosebită; riscurile trebuie identificate chiar din faza de proiectare / scriere, pentru fiecare, în funcție de impactul pe care, în condițiile în care ar apărea, l-ar avea asupra derulării proiectului, trebuind să fie găsită o soluție, astfel încât rezultatul final să nu fie afectat

metodologie specifică;

strategie de dezvoltare.

Managementul de proiect

Managementul proiectelor este un proces dinamic, desfășurat în mod științific, prin care resursele necesare sunt utilizate și organizate într-o asemenea manieră încât să conducă la îndeplinirea obiectivele proiectului. În managementul proiectelor o parte din personalul pentru implementarea proiectelor poate fi angajat temporar, în calitate de consultanți, lipsind astfel permanența rolurilor. Personalul implicat în proiect poate avea diferite roluri de îndeplinit la momente diferite.

Planificarea în cadrul elementelor prestabilite, ca bugetul, durata de realizare, planul de bază,

care sunt precizate la momentul structurării proiectului prezintă o importanță fundamentală.

Managementul proiectelor se caracterizează prin trăsături proprii, care asigură succesul proiectelor. Una dintre trăsături este aceea de a fi un proces complex deoarece implică, pe lângă cunoștințe economice și tehnice de specialitate, din domeniul specific fiecărui proiect, o gamă largă de cunoștințe și aptitudini organizatorice, astfel încât să coordoneze în paralel organizarea optimă a timpului, conducerea echipei, precum și administrarea celorlalte resurse.

Pentru asigurarea succesului proiectelor, o condiție esențială constă în concentrarea permanentă a managementului proiectelor asupra îndeplinirii obiectivelor propuse, și deci, a schimbării într-un mod organizat a situației existente în vederea realizării situației dorite.

Activitatea de management de proiect se desfășoară pe toată durata ciclului de viață al proiectului, și privește controlul acestuia în întregime.

Managementul proiectelor este deosebit de complex, deoarece reprezintă sinteza a cel puțin cinci elemente:

de a pregăti și lansa proiectul;

de a conduce proiectul în sine;

de a organiza dezvoltarea și implementarea proiectului;

de a asigura coerența acțiunilor;

de conducere a monitorizării și evaluării.

Astfel,

managementul proiectului reprezintă procesul de organizare și supraveghere a proiectului pentru a asigura realizarea acestuia conform planificării, în limitele bugetului și conform specificațiilor stabilite.

Planificarea activităților

Procesul de planificare a activităților presupune parcurgerea următorilor pași:

1. Pentru fiecare obiectiv al proiectului, decideți strategia optimă și activitățile pe care le implică.

2. Lista tuturor activităților proiectului. Elaborați o singură listă pentru toate activitățile planificate.

3. Împărțiți activitățile în sub-activități și sarcini realizabile. Împărțiți activitățile mai întâi în sub-activități și apoi în sarcini. Principala considerație este obținerea unui nivel corect de detalii. Cea mai frecventă greșeală este împărțirea activității în prea multe detalii. Cei care planifică trebuie să împartă activitățile doar până la un nivel la care au destule informații pentru a deduce resursele necesare.

4. Pentru fiecare activitate, estimați durata și resursele necesare. Pentru aceasta e bine să utilizați o foaie separată pentru fiecare activitate.

5. Clarificați secvența și dependența. Acum ordonați activitățile în succesiunea lor logică. Unele activități pot avea loc în paralel. Legați activitățile unele de altele pentru a le determina secvența și dependența. Activitatea depinde de începerea sau încheierea altei activități? De exemplu, construirea unei case constă într-un număr de acțiuni separate dar interrelaționate: mai întâi se sapă și se face fundația, apoi se ridică zidurile, etc. Sunt și activități ce se pot face în paralel: aprovizionarea cu materiale și ridicarea fundației.

6. E momentul să evaluați dependența activităților de resurse. Unele activități care, teoretic, pot avea loc concomitent, în realitate nu vor putea deoarece necesită aceeași resursă (umană sau materială). Acestea vor trebui reordonate în succesiune.

7. Stabiliți termene pentru fiecare sarcină. Fiecare sarcină trebuie să aibă o dată de începere, o durată și o dată de încheiere. Apoi agenda trebuie urmată cât mai îndeaproape.

8. Alcătuiti agenda activităților principale. După ce ați specificat termenele sarcinilor individuale, următorul pas este să planificați termenele pentru întreaga activitate principală.

9. Utilizați repere (milestones). Reperele sunt evenimente cheie care oferă o măsură a progresului proiectului și obiective către care să se îndrepte echipa proiectului.

10. Având aceste date stabilește drumul critic: succesiunea de activități între care nu există pauze datorate dependenței unei activități de realizarea concomitentă a altora. În acest caz, orice întârziere în realizarea unei activități va duce la întârzierea terminării proiectului. El reprezintă drumul cel mai lung (ca durată) din întregul proiect.

Data de finalizare a proiectului pe drumul critic trebuie apoi comparată cu termenul limită pentru proiect. Dacă se termină înainte, e bine. Dacă nu, trebuie luată în considerare posibilitatea de reducere a timpului de realizare a unor activități prin utilizarea mai multor resurse, renegocierea termenului limită sau oportunitatea realizării proiectului respectiv.

11. Definiți expertiza în cadrul echipei. Nivelul și tipul expertizei necesare trebuie hotărâte separat pentru fiecare sarcină.

12. Alocați sarcini în cadrul echipei. Distribuiți responsabilități în consultare cu membrii echipei. Fiecare sarcină este atribuită unui individ care și-o asumă ca un scop pe termen scurt.

IMPLEMENTARE

Proiectarea web ca disciplină științifică este influențată de dezvoltarea aplicațiilor web. Orientarea actuală în domeniul dezvoltării aplicațiilor web este deseori caracterizată printr-o abordare ad-hoc și o lipsă a metodelor de dezvoltare. Datorită complexității și ritmului proliferării aplicațiilor web, această abordare are un impact negativ asupra calității. Aplicațiile web reprezintă un nou domeniu de aplicații cu propriile sale provocări asupra dezvoltării software-ului.

Este necesară construirea unui ciclu de viață a aplicațiilor web, prezentarea conceptelor, tehnicilor, metodelor și utilitarelor pentru dezvoltarea sistematică a aplicațiilor web.

3.1. De ce am ales arhitectura REST

Representational State Transfer (REST) este o arhitectură software compusa din instructiuni și bune practici pentru crearea unor servicii web scalabile. REST este un set coordonat de constrângeri aplicate la proiectarea de componente într-un sistem hypermedia distribuit, care poate duce la o arhitectură mai performanta și usor de întreținut.

REST a fost acceptat pe scară largă in Web development ca o alternativă mai simplă pentru SOAP sau WSDL. Sistemele RESTful de obicei, dar nu întotdeauna, comunica peste Hypertext Transfer Protocol cu aceleași verbele HTTP (GET, POST, PUT, DELETE, etc.), utilizate de browsere web pentru a prelua pagini web și trimite date la serverele de la distanță.

Constrângeri arhitecturale

Constrângerile formale REST sunt:

Client–server

O interfață uniformă separă clienții de servere. Această separare înseamnă că, de exemplu, clienții nu se preocupă de stocarea datelor, acest proces desfășurandu-se în interiorul serverului iar serverele nu sunt preocupate de starea interfaței cu utilizator sau starii utilizatorului, astfel încât serverele poate fi mai simple și mai scalabil. Servere și clienții pot fi de asemenea înlocuite și dezvoltate independent, atâta timp cât interfața dintre ele nu este modificată.

Stateless

Fiecare cerere de la orice client conține toate informațiile necesare pentru a deservi cererea, iar starea sesiunii este ținută în client. Statutul sesiunii poate fi transferat de server către un alt serviciu, cum ar fi o bază de date pentru a menține o stare persistentă pe o perioadă și să permită autentificarea. Clientul începe trimiterea cererilor atunci când este gata să facă tranziția la o nouă stare.

Cachable

In WWW, clienții pot cache-ui raspunsuri. Pentru a prevenii refolosirea datelor în răspunsurile viitoarelor cereri acestea trebuie implicit sau explicit să se autodefineasca ca fiind cachable, sau nu. Buna gestionare a caching parțial sau eliminarea completă în cazul unor interacțiuni particulare dintre client-server, poate duce la îmbunătățirea scalabilității și performanței.

Layered system

Un client nu poate spune de obicei daca este conectat la end server sau la un server intermediar. Serverele intermediare pot înbunătății scalabilitatea sistemului prin permiterea balansării încărcării producând un sistem de caching comun. Acestea pot constitui de altfel și o parte a unei politici de securitate mai vaste.

Code on demand (opțional)

Serverele pot extinde temporar sau personaliza funcționalitatea unui client prin transferul de cod executabil. Exemplele pot include componente compilate, cum ar fi applet-uri Java și scripturi client-side, cum ar fi JavaScript. "Code on demand" este singura constrângere opțională a arhitecturii REST.

În momentul de față se evidențiază trei tipuri de arhitecturi pentru serviciile web: arhitectura REST, arhitectura RPC și un hibrid între REST și RPC.

În serviciile web care se bazează pe arhitectura REST, informațiile despre metoda apelată sunt date de metoda HTTP folosită, iar argumentele metodei sunt date de URI-ul folosit. Combinația este puternică, astfel din prima linie a unei cereri HTTP făcută unui serviciu web în manieră REST (”GET /reports/open-bugs HTTP/1.1”) ar trebui să înțelegem ce dorește clientul să facă. Restul cererii sunt doar detalii. Dacă metoda HTTP nu corespunde cu metoda pe care o apelează clientul, atunci serviciul web nu este RESTful. La fel dacă argumentele nu sunt date de URI.

Codul de pe client este redus deoarece browserul poate fi folosit pentru a accesa orice resursă. De asemenea, un serviciu web RESTful depinde mai puțin de formate proprietare și de frameworkuri de mesagerie deasupra HTTP.

3.2. Șabloane Arhitecturale

Un model arhitectural este o soluție generală, reutilizabilă pentru o problemă care de obicei apare în arhitectura software într-un context dat. Modelele arhitecturale sunt asemanatoare cu modele de design de software, dar au un domeniu de aplicabilitate mai mare. Modelele arhitecturale abordeaza diverse probleme în inginerie software, cum ar fi limitările performanțelor hardware. Unele modele arhitecturale au fost implementate in frameworkuri software. Cele mai importante șabloane arhitecturale ale momentului sunt MVC si MVVM.

Implementarea serverului folosind MVC

MVC, sau Model-View-Controller este un șablon arhitectural folosit în industria de software development (inclusiv web development). Această modalitate de lucru reușește cu succes izolarea părții logice de interfața proiectului, rezultând în aplicații extrem de ușor de modificat. În organizarea MVC, modelul reprezintă informația (datele) de care are nevoie aplicația, viewerul corespunde cu elementele de interfață iar controller-ul reprezintă sistemul comunicativ și decizional ce procesează datele informaționale, făcând legătura între model și view.

Figura 3 Modelul Arhitectural MVC

MVC este un concept foarte raspândit în programarea Web. Scopul MVC este de a ține separate logica business-ului și interfața utilizator, astfel încât cei care intrețin aplicația să schimbe mult mai ușor o parte, fără a afecta alte părți. În MVC, modelul conține informațiile (datele) și regulile business; view conține elemente din interfața utilizator (texte, input-uri ale formularelor etc); controller-ul genstionează comunicația dintre model și view.

Modelul

Modelul trebuie să aibă acces la un obiect db întors de MongoCLient. Modelul nostru ar trebui să aibă, de asemenea, o metodă pentru extinderea acestuia, pentru cazurile în care dorim să creem alte tipuri de modele.

View

View-ul va face posibilă randarea informațiilor în browser. În esență, view-ul este o clasa care trimite răspuns brownserului. Express oferă o modalitate de a face acest lucru cu ajutorul urmatoarei comenzi:

res.render('index', { title: 'Express' });

Controller

app.get ('/', routes.index);

In exemplul de mai sus, ce urmeaza dupa ‘/’, este de fapt controlerul. E doar o funcție middleware care acceptă request, response și next.

exports.index = function (cer, res, următoare) {

res.render ("index", {title: "Express"});

};

Mai sus, este modul în care ar trebui să arate controler, în contextul Express.

Implementarea clientului folosind MVVM

Figura 4 Modelul arhitectural MVVM aplicat in AngularJS

View-ul comunică doar cu ViewModel-ul, în timp ce ViewModel-ul este privit ca un punct intermediar între View și Model. De asemenea, Modelul este singurul care interacționează cu baza de date. Acest model are sens în practică doar dacă se folosește în combinație cu o bază de date. O diagramă a acestui design pattern poate fi observată și in figura de mai jos.

Alte două funcționalități care fac ca acesta să fie atât de des folosit sunt data template-urile și resursele de sistem. Template-urile aplică View-uri asupra obiectelor unui ViewModel.

Figura 5 Modelul Arhitectural MVVM

De mai mulți ani, AngularJS a fost mai aproape de MVC (sau, mai degrabă una dintre variantele sale client-side), dar în timp multumita multor refactorizari și îmbunătățiri, este acum mai aproape de MVVM – obiectul $scope ca domeniu de aplicabilitate ar putea fi considerat ca un ViewModel care este introdus printr-o funcție pe care o numim o controller.

AngularJS oferă un model MVVM extrem de flexibil. Conceptul de databinding foarte bine implementat, capabil să manipuleze obiecte JSON furnizate de diferite servicii WEB. View-urile sunt extrem de ușor de creat, singura inovație la acest capitol fiind existența unor directive. Existența mecanismului de rootare face posibilă crearea aplicațiilor “Single Page Application“. Conceptul de DependencyObject asigură creearea unor componente decuplate, ușor de intreținut, schimbat. De asemenea testarea este mult ușurată datorită acestui concept. Ca orice arhitectură modernă un mare accent se pune pe posibilitatea de testare automată, capitol la care AngularJS aș putea spune că excelează.

Personal consider că era HTML este în plină expansiune, orice plugin sau ActiveX trebuie să dispară, locul lor fiind luat de componente Javascript. Cu siguranță pe viitor tot mai multe “aplicații native” vor fi înlocuite de standarde “OPEN”, drept urmare HTML5 împreună cu javascript trebuie tratat cu cea mai mare atenție. Aplicațiile “viitorului” cu siguranta se vor baza pe aceste standarde.

3.3. Limbaje de programare și frameworkuri folosite

3.3.1. HTML5

HTML5 este un limbaj pentru structurarea și prezentarea conținutului pentru World Wide Web, o tehnologie nucleu pentru Internet propusă inițial pentru browserul Opera.

În special, HTML5 aduce multe noi caracteristici sintactice. Acestea cuprind elemente ca <video>, <audio>, <header> și <canvas> elemente HTML, precum și integrarea conținutului SVG care a înlocuiește utilizarea tag-ului generic <object>. Aceste noutăți sunt proiectate pentru a facilita includerea și manipularea în web a conținuturilor multimedia și grafice fără a fi nevoie să se recurgă la proprietățile de plugin și API. Alte noi elemente ca <section>, <article>, <header>, și <nav>sunt proiectate să îmbunătățească conținutul semantic al documentelor. Noi atribute au fost introduse în același scop, în același timp unele elemente și atribute au fost îndepărtate. Unele elemente ca <a>, <cite> și <menu> au fost schimbate, redefinite și standardizate. API-urile și DOM-urile (document object model) sunt certitudini și sunt părți fundamentale în specificațiile HTML5. HTML5, de asemenea, definește in câteva detalii prelucrările necesare pentru documentele invalide, astfel încât sintaxa erorilor va fi tratată uniform de toate browserele cunoscute.

3.3.2. CSS3

CSS (Cascading Style Sheets) este un standard pentru formatarea elementelor unui document HTML. Stilurile se pot atașa elementelor HTML prin intermediul unor fișiere externe sau în cadrul documentului, prin elementul <style> și/sau atributul style. CSS se poate utiliza și pentru formatarea elementelor XHTML, XML și SVGL.

CSS3 reprezintă un upgrade ce aduce câteva atribute noi și ajută la dezvoltarea noilor concepte in webdesign.

Unele dintre cele mai importante segmente (module) noi adăugate acestui standard pentru formatarea elementelor HTML aduc un plus considerabil in dezvoltarea activități webdesign.

Mai jos sunt prezente in listă cele mai importante modulele adăugate in CSS3:

Selectors

Box Model

Backgrounds and Borders

Image Values and Replaced Content

Text Effects

2D/3D Transformations

Animations

Multiple Column Layout

User Interface

Deși au apărut unele deficiente de compatibilitate intre browsere, majoritatea proprietăților CSS3 au fost implementate cu succes in variantele browserelor noi.

3.3.3. Cloud computing

Cloud computing, literal „computerizare în nori”, este un concept modern în domeniul computerelor șiinformaticii, reprezentând un ansamblu distribuit de servicii de calcul, aplicații, acces la informații și stocare de date, fără ca utilizatorul să aibă nevoie să cunoască amplasarea și configurația fizică a sistemelor care furnizează aceste servicii. Pentru cloud computing încă nu există un nume românesc încetățenit.

Expresia cloud computing derivă dintr-o reprezentare grafică simbolică a Internetului des întâlnită în formă de nor („the cloud”), folosită atunci când detaliile tehnice ale Internetului pot fi ignorate, ca în imaginea din dreapta. Conceptul și termenul englez au apărut în practică prin anii 2006-2007.

Cloud computing folosește noi metode de oferire și consumare a serviciilor IT în Internet, servicii care de obicei pot fi dimensionate dinamic și care includ resurse virtualizate. Este de fapt doar o posibilitate secundară, urmare a ușurinței cu care se pot acum accesa toate serverele și centrele de calcul interconectate prin intermediul Internetului.

Furnizorii tipici de cloud computing pun la dispoziție, de exemplu, aplicații comerciale standard; utilizatorul are acces la acestea doar prin intermediul unui browser local, deoarece atât aplicația cât și datele proprii ale utilizatorului sunt găzduite în cloud, pe serverul furnizorului de servicii. În aceste condiții asigurarea confidențialității și drepturilor de acces la date în contextul Internetului atotprezent joacă un rol primordial.

3.3.4. Open source

Termenul „cu sursă deschisă” (en: open source) descrie practica de a produce sau dezvolta anumite produse finite, permițând accesul utilizatorilor să acționeze liber asupra procesului de producție sau dezvoltare. Unii specialiști definesc „sursa deschisă” ca un concept filozofic; alții consideră că este o metodologie pragmatică.

Fiind foarte frecvent utilizat în dezvoltarea de programe software, mulți specialiști în elaborarea de programe au impresia că "open source" este o noțiune specifică acestei activități. În realitate, "open source" se poate aplica în orice domeniu în care se produce sau dezvoltă un produs. Există exemple de asemenea aplicații și în tehnologie, medicină, învățământ, cultură și altele.

3.3.5. Semantic UI

Semantic UI se bazează pe convingerea că blocul de construcție conceptuală a siteurilor nu sunt tag-urile HTML individuale, ci elemente de interfață individuale. Elemente de interfață sunt componente cum ar fi butoane, dropdowns, și modals, elemente care structureza și contextualizeaza conținutul web. Aranjate împreună într-o pagină creaza flux vizual pe care noi il percepem ca pe un site web.

Acest lucru poate fi considerat ca similar cu o camera plina de scriitori, argumentând despre "Care este cel mai bun limbaj pentru a compune un roman?". Știm cu toții că orice roman mare, deși scris într-o limbă care a fost convenabilă sau familiara pentru autor, va fi tradus în cele din urmă in multe alte limbi, într-un mod care păstrează încă calitatea cea mai importantă, sensul său.

UI Semantic tratează cuvinte și clase ca si concepte interschimbabile. Clasele folosesc sintaxa de limbi naturale, cum ar fi substantiv/relatie.

Platforma oficiala: http://semantic-ui.com/

3.3.6. Bootstrap

Bootstreap este cel mai popular framework de CSS. Este un proiect open-source, foarte dinamic, drept urmare poate fi integrat fără probleme și în aplicații comerciale. Folosit de majoritatea dezvoltatorilor web, acest framework este foarte util deoarece ușurează mult munca pe care trebuie să o depună un programator sau designer în crearea unei interfețe grafice cât mai placută și în același timp utilă și ușor de folosit. De asemenea salvează foarte mult timp pe care un dezvoltator îl pierde în mod normal cu realizarea acestor proceduri.

Acest framework are integrate multe stiluri predefinite cum ar fi: aspectele unor tabele, panouri sau butoane pe care le poți folosi foarte ușor ca atare sau poți porni de la ele și le poți modifica după bunul plac. Concluzionând, acest lucru înseamnă că această unealtă ajută să nu pleci cu un proiect de la ci să ai o bază cu anumite utilități foarte ușor integrabile în orice aplicație.

Pentru a folosi Bootstrap este necesar să ne procurăm arhiva acestui framework pe care îl găsim chiar pe site-ul dezvoltatorilor săi. Această arhivă ne va furniza trei foldere ce conțin fișiere pentru stilizarea paginilor și pictograme pe care le putem folosi în paginile noastre. De asemenea, acest tool te ajută încă de la conceperea aplicației, atât la organizarea elementelor din pagină, a textului, tabelelor și altele precum și la stilizarea lor.

Majoritatea site-urilor, mai ales cele concepute la nivel înalt, folosesc acest framework, el fiind în pas cu ceea ce înseamnă noutate în materie de dezvoltare Web.

Pentru mai multe exemple și modele de site-uri concepute cu ajutorul Bootstrap, platforma deschisă tuturor utilizatorilor este: http://getbootstrap.com.

3.3.7. Javascript

JavaScript (JS) este un limbaj de programare orientat obiect bazat pe conceptul prototipurilor. Este folosit mai ales pentru introducerea unor funcționalități în paginile web, codul Javascript din aceste pagini fiind rulat de către browser. Limbajul este binecunoscut pentru folosirea sa în construirea siturilor web, dar este folosit și pentru acesul la obiecte încastrate (embedded objects) în alte aplicații. A fost dezvoltat inițial de către Brendan Eich de la Netscape Communications Corporation sub numele de Mocha, apoi LiveScript, și denumit în final JavaScript.

Motorul V8 JavaScript este un motor de activarea JavaScript – open source dezvoltat de Google pentru browserul web Google Chrome. Acesta a fost utilizat în multe alte proiecte open-source cum ar fi Node.JS. Prima versiune a motorului V8 a fost lansat în același timp cu prima versiune a Chrome, 2 septembrie, 2008.

Arhitectura Aplicatiei

Figura 6 Tehnologiile folosite în cadrul proiectului

În schema de mai sus sunt prezentate tehnologiile cu care am dezvoltat acest proiect precum și modul în care acestea conlucrează. Avem o bază de date non-relațională care este interogată de aplicația de Node cu ajutorul modulului mongoose. Clienții fac request-uri prin HTTP, serverul procesează și raspunde cu datele cerute.

Toată aplicația folosește arhitectura REST, inclusiv clienții de mobile care comunică cu aplicația din cloud tot RESTfull prin HTTP.

Aplicatia Node din cloud raspunde cu date în format JSON, urmând ca datele să fie parsate și intepretate de clienți.

3.4.1. MEAN stack web development

Figura 7 Identitate vizuală MEAN STACK

Tehnologiile web evolueaza cu viteza cu care evoluează și internetul, este foarte greu să găsești combinația perfectă de soluții pentru aplicațiile web daca ești web developer. Pornind de la framework-urile din front-end până la cele din back-end sau mediile de stocare a datelor, este foarte greu să ajungem la o îmbinare perfectă a tehnologiilor în cazul proiectelor noastre web.

Dacă sunteți în căutarea eficientizarii fluxul de lucru al dezvoltarii aplicatiilor web, din ce în ce mai popularul MEAN stack (un acronim referitor la combinația dintre MongoDB, Express.JS, Angular.JS si Node.JS) este o alegere excelentă. Iată ce este:

În primul rând, îți permite să scrii codul în intregime în JavaScript, de la client la server. Acest lucru în sine face ca MEAN să fie un mediu full-stack foarte bun pentru dezvoltatorii care și-au investit timp în învățarea limbajului JavaScript pentru client-side.

În al doilea rând, aceasta suportă design patterns cum ar fi MVC sau MVVM pentru a înbunătății arhitactura aplicației dumneavoastră. Și desigur componentele MEAN sunt toate proiecte open-source, ceea ce înseamnă că tot pachetul este liber de utilizat, actualizat în mod regular și foarte flexibil atât în utilizarea cât și în personalizarea nevoilor oricarui proiect.

Figura 8 Arhitectura MEAN

3.4.1.1 MongoDB

MongoDB este un sistem de gestionare a bazelor de date NoSQL care folosește documente de tip JSON pentru a stoca date, acest lucru facându-l foarte prietenos cu dezvoltatorii care au ales sa foloseasca Javascript atât pe client cât și pe server. În mare, poți folosi MongoDB în același mod în care ai folosi MySQL, deci este foarte familiar și accesibil de folosit. De asemenea este și scalabil pentru proiectele de anvergura, aceasta particularitate fiindui caracteristică oricărui sistem NoSQL.

3.4.1.2. Express

ExpressJS este un framework pentru aplicații web sau mobile ce funcționeaza pe server care se bazează pe un mediu de dezvoltare de tip NodeJS, pentru a oferi un mediu solid pentru componentele fundamentale ce pun în aplicare funcțiile de backend ale aplicațiilor web scrise în Javascript.

3.4.1.3. AngularJS

Figura 9 Schema conceptuala pentru AngularJS

AngularJS este un alt framework de JavaScript. A devenit preferatul multor dezvoltatori la foarte scurt timp de la lansare.

HTML este foarte bun pentru declararea documentelor statice, dar se clatina atunci când încercăm să-l folosim pentru declara vizualizări dinamice din aplicații web. AngularJS permite să extindeți vocabularul HTML pentru aplicația dumneavoastră. Mediul rezultat este extrem de expresiv, ușor de citit, și rapid de dezvoltat.

Data-binding este un mod automat de actualizare a view-ului ori de câte ori se schimbă modelul, precum și actualizarea modelului ori de câte ori se schimbă view-ul. Acest lucru este minunat, deoarece eliminal manipularea DOM din lista de lucruri pentru care trebuie să vă faceți griji.

3.4.1.4. Node.JS

Node.js este o platformă construită pe motorul de JavaScript V8 folosit și în Google Chrome. Acesta ne permite crearea de aplicații rapide, ușor de dezvoltat și întreținut.

Node.js foloseste motorul Google V8 JavaScript pentru a executa cod, precum și un procent mare dintre modulele de bază sunt scrise în JavaScript. Node.js conține o bibliotecă incorporata pentru a permite aplicațiilor să acționeze ca un server web fără software-uri precum Apache Server HTTP sau IIS.

Node.js funcționează pe un singur thread, permițându-i să susțină zeci de mii de conexiuni concurente, fără a suporta costurile de thread context-switching. Proiectarea unei aplicatii prin impartirea unui singur thread a tuturor cererilor înseamnă că poate fi folosit pentru a construi aplicații extrem de concurente. Scopul de proiectare a unei cereri Node.js este că orice funcție care desfășoară I / O trebuie să utilizeze un apel invers.

De ce am ales NodeJS?

1. JavaScript

Dacă vrei să scrii aplicații pt. web, inevitabil trebuie să înveți JavaScript și programarea pe evenimente. Datorită V8-ului JavaScript-ul pe server este foarte bine optimizat!

Engine-ul V8 implementează ECMAScript (ECMA-262, 5th edition) (în prezent) este cel rapid VM pt. JavaScript (folosit și în Google Chrome).

2. Comunitatea

Proiectul are jur de 2 ani și jumătate și are 3000+ de module scrise. Nu toate sunt excelente, dar sunt open-source și poți să faci cam orice ai avea nevoie, chiar dacă vrei să-ți aprinzi lumina din cameră.

3. Modulele / librăriile și NPM (Node.js Package Manager)

Un lucru foarte important pe care comunitatea a reușit să-l facă, este să creeze standarde. Cât de importante sunt standardele? Limbajul este un standard, scrisul este un standard; nu am fi evoluat niciodată dacă nu reușeam să ne conformăm unor seturi de reguli acceptate în comunitate.

Cum acționează Serverul atunci când este cerută o pagină ?

Clientul ( Browserul ) trimite o cerere de tip GET, POST, DELETE, PUT prin care solicită un anumit fișier / pagină de pe serverul nostru.

GET ( Listează pagină, exemplu: http://localhost/info.php?pagina=2 )

POST ( Este folosit la formulare de login, search etc. )

PUT ( Este folosit atunci când vrem să introducem ceva în baza de date, de obicei programatorii folosesc POST în loc de PUT, deoarece este mult mai ușor de implementat )

DELETE ( Când vrem să ștergem ceva din baza de date )

MIME-Type-ul ( Tipul fișierului cerut HTML / PHP / JSON / JPEG etc. ) este interpretat de către server și caută dacă o rută cu acel nume există.

Dacă ruta nu există:

Atunci se caută un fișier cu acel nume în directorul ”Public” (Asemănător cu htdocs de pe serverul HTTP Apache) și trimite fișierul.

Dacă fișierul nu există este afișată o pagină de eroare (cod 404).

Dacă ruta există:

Serverul execută tot codul ( Javascript în cazul nostru ) și îl transformă în HTML pe care browserul nostru îl poate interpreta foarte ușor.

Ce se întâmplă cu Browserul cândp rimesc date de la serverul HTTP?

Browserele moderne sunt capabile să interpreteze 3 MIME-Type-uri:

HTML – Cu ajutorul unui DOM parser (care corectează codul HTML scris greșit și îi acordă sens).

CSS – Leagă fiecare select unui element din DOM. ( Folosește un motor de 2D, cele mai des întâlnite sunt Webkit și Gecko )

JavaScript – Fiecare instrucțiune este executată. ( Multe browsere au acum suport pentru HTML5 și se poate folosi JavaScript pentru 3D / 2D )

Dacă MIME-Type-ul nu este recunoscut de Browser atunci fișierul este descărcat.

4. PREZENTAREA APLICAȚIEI

4.1 Modele de date:

Deoarece folosesc o bază de date non-relațională, schema conceptuală a bazei de date nu poate fi expusă într-o diagramă de tip “Schemă – Relație” (ca o schemă de date în SQL). MongoDB folosește scheme de date care compun un obiect iar rezultatul unei interogări depinde exclusiv de cum sunt construite aceste obiecte. Spre deosebire de o baza de date relatională, rezultatul unei interogări poate diferi în functie de ce conține obiectul selectat.

Diferența dintre cele două sisteme de gestionare a bazelor de date din punct de vedere al schemei conceptuale este ilustrată în imaginea de mai jos.

Figura 10 Diferența dintre SQL și NoSQL din punct de vedere al schemei conceptuale

Pentru a construi un model de date omogen pentru aplicație m-am folosit de mongoose, un modul special creat pentru manipularea datelor în MongoDB. Acest modul functionează ca un layer suplimentar, de legatură între aplicația de NodeJs și MongoDB având implementate și alte funcționalități folositoare cum ar fi validarea datelor și multe instrumente pentru manipularea acestora.

Schemele folosite în aplicație sunt următoarele:

var OrganizationSchema = new Schema({

organization_name: String,

organization_type: String,

organization_website:String,

organization_facebook_page:String,

organization_desc:String,

organization_country_id: Number,

organization_profile_picture:{type:Number,default:0},// 0-No picture 1-Has picture

organization_members_id:[{type:Schema.ObjectId, ref:'user'}],

organization_admin_id:[{type:Schema.ObjectId, ref:'user'}],

organization_projects:[{type:Schema.ObjectId, ref:'project'}]

});

mongoose.model('organization',OrganizationSchema);

var UserSchema = new Schema({

email: {type: String, unique: true},

hashed_password: String,

first_name: String,

last_name: String,

points: {type:Number , default:0},

user_since: {type:Date, default: Date.now},

telephone:Number,

facebook:String,

twitter:String,

google_plus:String,

orgs:[{type:Schema.ObjectId, ref:'organization'}]

});

mongoose.model('user',UserSchema);

var JoinNotificationScheema = new Schema({

org_id:{type:Schema.ObjectId, ref:'organization'},

user_id:{type:Schema.ObjectId, ref:'user'},

status: {type:Number , default:0} //0 Waiting, 1 Accept

});

mongoose.model('joinNotification',JoinNotificationScheema);

var ProjectSchema = new Schema({

project_name:String,

project_description:String,

project_manager:[{type:Schema.ObjectId,ref:'user'}],

start_date:{type:Date, default: Date.now},

end_date:Date,

org:{type:Schema.ObjectId,ref:'organization'},

activities:{type:Schema.ObjectId,ref:'activity'},

project_members:[{type:Schema.ObjectId,ref:'user'}]

});

mongoose.model('project',ProjectSchema);

var ActivitySchema = new Schema({

activity_name:String,

project_id:{type:Schema.ObjectId,ref:'project'},

color:String

});

mongoose.model('activity',ActivitySchema);

var TaskSchema = new Schema({

task_name:String,

task_desc:String,

i_volunteer:[{type:Schema.ObjectId,ref:'user'}],

activity:[{type:Schema.ObjectId,ref:'activity'}],

added_on:{type:Date, default: Date.now},

deadline:Date,

points:{type:Number, default: 0},

org_id:{type:Schema.ObjectId,ref:'organization'},

project_id:{type:Schema.ObjectId,ref:'project'},

done_on_date:Date,

subtasks:[{type:Schema.ObjectId,ref:'SubTask'}],

status:{type:Number, default: 1} //1.Waiting review 2.Done

});

mongoose.model('task',TaskSchema);

var SubTask = new Schema({

subtask_name: String,

status:{type:Number, default: 1}, //1.Undone 2.Done

task_id:{type:Schema.ObjectId,ref:'task'},

added_by:{type:Schema.ObjectId,ref:'user'},

done_by:{type:Schema.ObjectId,ref:'user'}

});

mongoose.model('SubTask',SubTask);

var TaskCategoryesSchema = new Schema({

project_id:{type:Schema.ObjectId,ref:'project'},

backlog:[{type:Schema.ObjectId,ref:'task'}],

waiting:[{type:Schema.ObjectId,ref:'task'}],

doing:[{type:Schema.ObjectId,ref:'task'}],

done:[{type:Schema.ObjectId,ref:'task'}]

});

mongoose.model('taskCat',TaskCategoryesSchema);

var PostSchema = new Schema({

post_title: String,

org:{type:Schema.ObjectId,ref:'organization'},

active:{type:Boolean, default:0},//0 Draft 1 Published

p_date: Date,

p_body: String,

author: {type:Schema.ObjectId,ref:'user'},

related_project:{type:Schema.ObjectId,ref:'project'},

date_modifyed:Date,

modifyed_by:{type:Schema.ObjectId,ref:'user'}

});

mongoose.model('post',PostSchema);

var MeetingsSchema = new Schema({

project:{type:Schema.ObjectId,ref:'project'},

org:{type:Schema.ObjectId,ref:'organization'},

date:Date,

status:Boolean,

hosts:[{type:Schema.ObjectId,ref:'user'}],

invited:[{type:Schema.ObjectId,ref:'user'}],

confirmed:[{type:Schema.ObjectId,ref:'user'}],

topics:[{type:Schema.ObjectId,ref:'topic'}],

decisions:[{type:Schema.ObjectId,ref:'decision'}]

});

mongoose.model('meeting',MeetingsSchema);

var TopicScheema = new Schema({

topic: String

});

mongoose.model('topic',TopicScheema);

var DecisionScheema = new Schema({

decision: String

});

mongoose.model('decision',DecisionScheema);

4.2. Configurare client (AngularJS)

Configurarea clientului în AngularJS se reduce la crearea unui modul, introducerea listei de dependințe care pot fi alte module sau directive scrise în Angular. Dacă alegem să folosim $routeProvider pentru routare trebuie să introducem fiecare rută împreună cu adresa locala a fisierului html în care sa află template-ul și numele controllerului pe care îl folosește acea pagină. Dacă ruta nu există, se face redirect la o pagina de 404 not found.

4.2.1. Directive folosite in cadrul proiectului

4.2.1.1. header-admin

Directiva care încarcă template-ul headerului pentru partea de admin.

app.directive('headerAdmin', function () {

return {

templateUrl: 'static/views/shared/headerAdmin.html',

}

});

Pentru a folosi aceasta directivă în html trebuie să avem:

<div header-admin></div>

4.2.1.2 ng-enter

Pe parcursul dezvoltării acestei aplicații am avut nevoia ca uneori să apelez funcții în AngularJS folosind apăsarea tastei “enter”. Directiva care mă ajută să fac acest lucru este următoarea:

app.directive('ngEnter', function() {

return function(scope, element, attrs) {

element.bind("keydown keypress", function(event) {

if(event.which === 13) {

scope.$apply(function(){

scope.$eval(attrs.ngEnter, {'event': event});

});

event.preventDefault();

}

});

};

});

Pentru folosirea acestei directive în codul html trebuie să avem:

<input type=”text” ng-enter=”nume_functie()” />

În acest caz nume funcție se află în $scope iar implementarea acesteia se poate face în controlerul asociat paginii html. Triggerul care declanșează aplicarea funcției este apasarea tastei “enter”.

4.2.1.3 loading

Directiva care afișeză în interfață un loading până un request selectat de dezvoltator se finalizează. Aceastei directive îi este asociat și un controller.

app.directive('loading',function(){

return{

templateUrl: 'static/views/DialogTemplates/loading.html',

controller: function($scope){

$scope.$whenReady(function() {

$scope.loading=true;

});

}

}

});

Pentru folosirea acestei directive în codul html trebuie să avem:

<div loading></div>

Dezactivarea loadingului se face prin aplăsarea functiei $scope.$onReady(); în callback-ul unui request. În acest fel loading-ul dispare exact atunci când se primește răspunsul.

4.2.1.4. my-date-picker

În unele cazuri a fost nevoie să folosesc librării externe de exemplu pentru amplasarea unui date picker. Pentru a folosi librării externe care au ca dependinte librării precum JQuery trebuie să creem o directivă specială. În interiorul acesteia se inițializează librăria în modul în care se indică inițializarea acesteia în documentația oficială.

app.directive('myDatePicker',function(){

return{

link: function(scope,elem,attr){

elem.datepicker({

todayBtn: "linked",

autoclose: true,

todayHighlight: true,

toggleActive: true

});

}

}

});

Pentru folosirea acestei directive în codul html trebuie să avem:

<div my-date-picker></div>

4.3. Configurare server (NodeJS)

Configurarea serverului este compusă din două părți. JSON-ul de configurare în care sunt listate atât depedințele cât și date relevante despre proiect numit package.json . Acesta este folosit atunci când se face migrarea aplicației pe alte medii, unde serverul de node descarcă toate dependițele și configurează aplicația pe baza acestui fisier.

{

"name": "Licenta–Task-Heroes-nodejs-",

"version": "0.0.1",

"description": "Organization Manager App",

"main": "app.js",

"directories": {

"doc": "docs"

},

"dependencies": {

"body-parser": "^1.10.0",

"connect-mongo": "^0.4.1",

"cookie-parser": "^1.3.3",

"ejs": "^1.0.0",

"express": "^4.10.6",

"express-session": "^1.9.3",

"fs-extra": "*",

"helmet": "^0.5.3",

"moment": "^2.9.0",

"mongodb": "^1.4.23",

"mongoose": "^3.8.20",

"mongoose-deep-populate": "^1.0.0",

"textangular": "^1.3.9"

},

"devDependencies": {},

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1"

},

"repository": {

"type": "git",

"url": "https://github.com/niculiviu/Licenta–Task-Heroes-nodejs-.git"

},

"engines": {

"node": "0.12.x"

},

"author": "Liviu Nicu Alexandru",

"license": "ISC",

"bugs": {

"url": "https://github.com/niculiviu/Licenta–Task-Heroes-nodejs-/issues"

},

"homepage": "https://github.com/niculiviu/Licenta–Task-Heroes-nodejs-"

}

Aplicația propriuzisă este serverul de Express care este configurat cu ajutorul dependințelor. Configurarea serverului Express constă printre altele și în listarea resurselor statice, conectarea la baza de date și comanda de rander a paginilor statice in functie de rută. În cazul aplicației mele, root-ul adica ‘/’ randează aplicația de AngularJS care se ocupă mai departe de rutare, fiind single page apliction și având propriul sistem de routare pe client.

Conectarea la baza de date MongoDB se realizează cu ajutorul modului mongoose astfel:

var conn = mongoose.connect('mongodb://liviu:[anonimizat]:27017/nev2yjoH');

Pornirea serverului local se face astfel:

var server = http.createServer(app).listen( process.env.PORT || 5000, function () {

console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);

});

Tot fisierul de configurare se găseste în app.js și are următoarea formă:

/**

* main app – EXPRESS SERVER

*/

var express = require('express');

var bodyParser = require('body-parser');

var http = require('http');

var helmet = require('helmet');

var fs = require('fs-extra');

var moment=require('moment');

var busboy = require('connect-busboy');

var cookieParser = require('cookie-parser');

var expressSession = require('express-session');

var mongoStore = require('connect-mongo')({session: expressSession});

var mongoose = require('mongoose');

require('./node/models/user.js');

require('./node/models/organization.js');

var app = express();

app.use(busboy());

app.engine('.html',require('ejs').__express);

app.set('views',__dirname+'/');

app.set('view engine','html');

app.use('/lib', express.static(__dirname +'/lib'));

app.use('/node-modules', express.static(__dirname +'/node-modules'));

app.use('/lib/css', express.static('./lib/css/'));

app.use('/static/', express.static('./static/'));

app.use('/img/', express.static('./img/'));

app.use('/template/', express.static('./template/'));

var conn = mongoose.connect('mongodb://liviu:[anonimizat]:27017/nev2yjoH');

app.use(helmet.noSniff());

app.use(bodyParser.urlencoded({extended: true}));

app.use(bodyParser.json());

app.use(cookieParser());

app.use(expressSession({

secret: 'SECRET',

cookie: {maxAge: 60*60*1000},

store: new mongoStore({

db:mongoose.connection.db,

collection: 'session'

}),

resave: true,

saveUninitialized: true

}));

require('./node/routes.js')(app);

app.get('*', function(req, res){

res.render('index.html');

});

var server = http.createServer(app).listen( process.env.PORT || 5000, function () {

console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);

});

4.4. Implementare:

În capitolul acesta o să arat modul în care conlucreaza toate tehnologiile prezentate mai sus.

4.4.1 Înregistrarea unui user

Figura 11 Formularul de înregistrare

Register.html

<h3>Register</h3>

<div class="ui form">

<p>Personal Informations</p>

<div class="ui two column grid">

<div class="column">

<div class="ui fluid icon input">

<input type="text" placeholder="First Name" ng-model="NewOrg.First">

</div>

</div>

<div class="column">

<div class="ui fluid icon input">

<input type="text" placeholder="Last Name" ng-model="NewOrg.Last">

</div>

</div>

</div>

<div class="ui fluid icon input" style="margin-top:10px;">

<input type="text" placeholder="E-mail" ng-model="NewOrg.Email">

</div>

<p>Password</p>

<div class="ui fluid icon input" style="margin-top:10px;">

<input type="text" placeholder="Password" ng-model="NewOrg.Pass1">

</div>

<div class="ui fluid icon input" style="margin-top:10px;">

<input type="text" placeholder="Password Again" ng-model="NewOrg.Pass2">

</div>

<hr>

<div class="ui primary button" ng-click="newOrganization(NewOrg)">

Register

</div>

<div class="ui button" ng-click="closeThisDialog('Some value')">

Cancel

</div>

</div>

Dupa cum observați, fiecarui input îi este asociat un model iar la apasarea butonului register se apelează functia newOrganization din LoginController și se trimite ca parametru obiectul format din toate modelele.

LoginController.js

'use strict';

app.controller('loginCtrl', ['$scope', 'loginService', '$rootScope','ngDialog','$location',

function ($scope, loginService, $rootScope, ngDialog,$location) {

$scope.newOrganization = function(data){

loginService.registerNewOrganization(data)

.success(function(response){

})

.error(function(err){

console.log(err);

});

}

}]);

Apelarea funcției newOrganization din loginController duce la apelarea unui alte funcții dintr-un serviciu, loginService, care întoarce răspunsul unui request HTTP, tratând răspunsul și în cazul în care acesta s-a încheiat cu succes cât și dacă s-a produs o eroare.

LoginService.js

'use strict';

app.factory('loginService', function ($http, $location,$rootScope) {

var myFunctions =

{

……………

registerNewOrganization: function(user){

return $http.post('/register/user',user);

},

…………..

}

return myFunctions;

});

Cu ajutorul funcției registerNewOrganization se realizează un request folosind metoda POST la link-ul “/register/user” și se trimite în corpul requestului datele pe care le-am completat în formul de html și care au fost transmise cu ajutorul controllerului.

Urmează partea de server:

routes.js

var crypto = require('crypto');

var express=require('express');

module.exports=function(app){

var user=require('./controllers/userNodeController.js');

app.post('/register/user', user.register);

}

Acest fișier conține toate rutele definite de noi pe care le folosim pentru a face requesturi către server. Fiecărui link îi este asociată o funcție dintr-un controller, în cazul nostru atunci când se face un requrest la ‘/register/user’ se apelează funcția register din userNodeController.js

userNodeController.js > register

var crypto = require('crypto');

var mongoose =require('mongoose'); // se initializeza modului mongoose

//se asociaza variabilei user obiectul de tip model(‘user’) definit mai sus

var user=mongoose.model('user');

function hashPW(pwd){

return crypto.createHash('sha256').update(pwd).digest('base64').toString();

}

//functie folosita pentru encriptarea parolelor in base64

exports.register = function(req, res){

var newUser= new user(); //Se creaza un nou obeict de tip user

newUser.set('email',req.body.Email);

newUser.set('hashed_password',hashPW(req.body.Pass1)); //encriptare

newUser.set('first_name',req.body.First);

newUser.set('last_name', req.body.Last);

//se seteaza continutul noului obiect folosind datele din corpul requestului

newUser.save(function(err){ //se salveaza modificarile

if(err){

console.log(err); //daca se intampina o eroare se afiseaza in consola

}

else{

//daca salvarea s-a efectuat cu succes se trimite in raspuns ‘user Inserted successfuly’’

res.status(200).json({success:'User Inserted successfuly!'});

}

});

}

4.4.2 Login

Figura 12 Pagina de login

login.html

<div class="column">

<div class="ui form segment">

<div class="field">

<label>Username</label>

<div class="ui left icon input">

<input type="text" placeholder="Username" ng-model="user.username">

<i class="user icon"></i>

</div>

</div>

<div class="field">

<label>Password</label>

<div class="ui left icon input">

<input type="password" placeholder="Password" ng-model="user.pass">

<i class="lock icon"></i>

</div>

</div>

<div class="ui blue submit button" ng-click="login(user)">Login</div>

</div>

</div>

Aceasta este o parte din codul html al paginii de login, partea cu formularul în care un user își poate introduce userul și parola pentru a se loga. Ce este de remarcat la aceast cod sunt cele două modele pe care le creeaza amplicatia de angular precum și funcția pe care o apelăm la click. Atât modele cât și funcția sunt acum în $scope.

LoginController.js

$scope.login=function(user){

loginService.login(user)

.success(function(response){

console.log(response);

$location.path('/admin');

//redirect catre pagina de admin daca raspunsul este afirmativ

})

.error(function(response){

if(response){

if(response.msg='user not found'){

$scope.emailNotInDatabase=false;

$scope.emailOrPassIncorect=true;

}else if(response.msg='user or pass'){

$scope.emailNotInDatabase=true;

$scope.emailOrPassIncorect=false;

}

}

});

}

Modul în care funcționează funcția de login este destul de simplu, se trimit datele din model, adică sunt transmise cu ajutorul parametrului user către serviciul de login care face requst prin HTTP la server pentru a verifica daca userul și parola se potrivesc. În caz afirmativ se intră în funcția success() și se face redirect la pagina de admin, în caz negativ, dacă userul și parola nu sunt corecte se intră în funcția error() și se afișează mesaje lămuritoare în interfață. Cele două tipuri de erori pot fi:

Emailul nu este în baza noastră de date.

Emailul există în baza de date dar parola nu este corectă.

LoginService.js

app.factory('loginService', function ($http, $location,$rootScope) {

var myFunctions =

{

….

login: function (user) {

return $http.post('/login/user',user);

},

…..

}

return myFunctions;

});

Serviciul transmite mai departe requestul către server și transmite în corpul requestului datele userului pentru validare.

Controllerul de login din node.js

var crypto = require('crypto');

var mongoose =require('mongoose');

var user=mongoose.model('user');

function hashPW(pwd){

return crypto.createHash('sha256').update(pwd).digest('base64').toString();

}

exports.login = function(req,res){

user.findOne({email:req.body.username}).

exec(function(err,user){

console.log(err);

if(!user){

res.status(404).json({msg: 'user not found'});

}else

if(user.hashed_password === hashPW(req.body.pass.toString())){

req.session.regenerate(function(){

req.session.user=user.id;

req.session.username=user.email;

req.session.firstName=user.first_name;

req.session.lastName=user.last_name;

res.json(user);

});

}else{

res.status(404).json({msg:'user or pass'});

}

});

}

În acest controller se primesc datele de la client sub forma unul json în corpul reqestului. Prin urmare serverul primește în obiectul req.body un json de forma

{

username: ‘[anonimizat]’,

pass:’liviupass’

}

Mai departe se caută dacă username-ul se află în baza de date, în caz negativ se transmite un mesaj de eroare în raspuns și requestul se termină, în caz afirmativ se verifică dacă username-ului respectiv îi este asociată parola introdusă de user. Parola este encodata în baza de date pentru a spori securitatea aplicație. În acest caz, pentru a verifica dacă parola intrudisă de user este aceeași cu parola din baza de date trebuie sa encodam și parola introdusă de user, iar acest lucru se realizează prin apelarea functiei hashPW: hashPW(req.body.pass.toString()). Dacă parola introdusă se potrivește cu cea din baza de date se introduc datele userului găsit în obiectul session și se trimit în raspuns aceleași informații, în caz negativ se trasmite în răspuns mesajul ‘user or pass’ și se afișează în interfață un mesaj concludent.

4.4.3 Crearea unei organizații

Figura 13 Formular de crearea a unei organizații

new_organization.html

<h3>New Organization</h3>

<div class="ui form">

<div class="ui fluid icon input" style="margin-top:10px;">

<input type="text" placeholder="Organization Name" ng-model="NewOrg.Name">

</div>

<div class="ui fluid icon input" style="margin-top:10px;">

<textarea rows="3" type="text" placeholder="Description" ng-model="NewOrg.Desc"></textarea>

</div>

<div class="ui fluid icon input" style="margin-top:10px;">

<select ng-model="NewOrg.Type" semantic-dropdown class="form-control">

<option>–SELECT TYPE–</option>

<option>Youth</option>

<option>School</option>

<option>Religious</option>

</select>

</div>

<hr>

<div class="ui primary button" ng-click="newOrganization(NewOrg,loggedUser)">

Add

</div>

<div class="ui button" ng-click="closeThisDialog('Some value')">

Cancel

</div>

</div>

adminController.js

Deschiderea modalului:

$scope.open_new_organization=function(){

ngDialog.open({

template: 'static/views/DialogTemplates/new_organization.html',

scope:$scope

});

}

Funcția care apelează serviciul pentru crearea unei noi organizații:

$scope.newOrganization=function(newOrg,user){

console.log(newOrg);

console.log(user);

var obj={org: newOrg,user:user}

var newOrgModel= {

organization_name: newOrg.Name

}

adminService.newOrg(obj)

.success(function(response){

//console.log(response);

console.log($scope.allOrganizations);

$rootScope.allOrganizations.orgs.push(response);

ngDialog.close();

})

.error(function(response){});

}

adminService.js

'use strict';

app.factory('adminService', function ($http, $location,$rootScope) {

var myFunctions =

{

newOrg: function (obj) {

return $http.post('/new/org',obj);

}

….

}

return myFunctions;

});

NodeJS Controller

exports.newOrg=function(req,res){

var newOrg=new organization();

newOrg.set('organization_name',req.body.org.Name);

newOrg.set('organization_type',req.body.org.Type);

newOrg.set('organization_desc',req.body.org.Desc);

newOrg.save(function(err,docsInserted){

if(err){

console.log(err);

}

else{

res.status(200).json(docsInserted);

docsInserted.organization_admin_id.push(req.body.user._id);

docsInserted.organization_members_id.push(req.body.user._id);

docsInserted.save(function(err,doc){

if(err){

console.log(err);

}else{

console.log(doc);

}

});

user.findOne({_id:req.body.user._id}).exec(function(err,doc){

doc.orgs.push(docsInserted._id);

doc.save(function(err,doc){

if(err){

console.log(err);

}else{

console.log(doc);

}

});

});

}

});

}

4.4.4 Crearea unui proiect

NodeJS Controller

exports.insertProject = function(req,res){

var newProject = new project();

newProject.set('project_name',req.body.project.Name);

newProject.set('project_description',req.body.project.Desc);

newProject.set('end_date',req.body.project.End_date);

newProject.set('project_manager',req.body.user._id);

newProject.set('org',req.body.org._id);

newProject.save(function(err,project){

if(err){

res.status(404).json({msg: err});

}

else{

res.status(200).json(project);

var newtaskCat = new taskCat();

newtaskCat.set('project_id',project._id);

newtaskCat.save(function(err,doc){

if(err){console.log(err)}

else{console.log(doc)}

});

var newActOrder = new activityOrder();

newActOrder.set('project_id',project._id)

newActOrder.save();

organization.update(

{_id:req.body.org._id},

{$push:

{

organization_projects:project._id

}

},

{upsert: true},

function(err,doc){

if(err){

console.log(err);

}

else{

console.log("organization_members_id updated");

console.log(doc)

}});

organization.findOne({_id:req.body.org._id}).exec(function(err,doc){

console.log(doc);

})

}

});

}

4.4.5 Crearea unui task

NodeJS Controller

Un user poate adauga un task din oricare lista, de accea acestea sunt serviciile pentru adaugarea unui task in fiecare dintre liste:

exports.addDoing = function(req,res){

var newTask = new task();

console.log(req.body);

newTask.set('task_name',req.body.task);

newTask.set('project_id',req.body.project_id);

newTask.set('org_id',req.body.org);

newTask.save(function(err,task){

if(err){console.log(err)}

else{

taskCat.update(

{project_id:req.body.project_id},

{$push:

{

doing:task._id

}

},

{upsert: true},

function(err,doc){

if(err){

console.log("err");

}

else{

console.log("success adding task Doing");

}

});

taskCat.findOne({project_id:req.body.project_id})

.populate('doing')

.exec(function(err,doc){

if(err){console.log(err)}

else{

res.status(200).json(doc);

}

});

}

});

}

exports.addWaiting = function(req,res){

var newTask = new task();

newTask.set('task_name',req.body.task);

newTask.set('project_id',req.body.project_id);

newTask.set('org_id',req.body.org);

newTask.save(function(err,task){

if(err){console.log(err)}

else{

taskCat.update(

{project_id:req.body.project_id},

{$push:

{

waiting:task._id

}

},

{upsert: true},

function(err,doc){

if(err){

console.log("err");

}

else{

console.log("success adding task waiting");

}

});

taskCat.findOne({project_id:req.body.project_id})

.populate('waiting')

.exec(function(err,doc){

if(err){console.log(err)}

else{

res.status(200).json(doc);

}

});

}

});

}

exports.addBacklog = function(req,res){

var newTask = new task();

newTask.set('task_name',req.body.task);

newTask.set('project_id',req.body.project_id);

newTask.set('org_id',req.body.org);

newTask.save(function(err,task){

if(err){console.log(err)}

else{

taskCat.update(

{project_id:req.body.project_id},

{$push:

{

backlog:task._id

}

},

{upsert: true},

function(err,doc){

if(err){

console.log("err");

}

else{

console.log("success adding task backlog");

}

});

taskCat.findOne({project_id:req.body.project_id})

.populate('backlog')

.exec(function(err,doc){

if(err){console.log(err)}

else{

res.status(200).json(doc);

}

});

}

});

}

4.4.6 Adăugarea unei activități asociate unui proiect

Activitățile sunt un lucru foarte important. Este modul în care se împart taskurile în cadrul unei ședințe. Aceste activități uneori sunt chiar echipele de proiect. Având o evidență clară a taskurilor fiecărei echipe de proiect duce la o mai bună comunicare și colaborare între voluntari.

Aceste activități se pot adăuga drept tag-uri pentru taskuri. Un task poate fi realizabil în una sau mai multe activități.

În rândurile următoare sunt prezentate serviciile web ce stau la baza acestei functionalități.

exports.addList = function(req,res){

var newActivity= new activity();

var color=getRandomColor();

newActivity.set('activity_name',req.body.ListName);

newActivity.set('project_id',req.body.ProjectID);

newActivity.set('color',color);

newActivity.save(function(err){

if(err){

res.status(404).json(err);

}else{

res.status(200).json({color:color});

}

});

}

In acest controller se apeleaza functia getRandomColor(), descrisa mai jos:

function getRandomColor() {

var letters = '0123456789ABCDEF'.split('');

var color = '#';

for (var i = 0; i < 6; i++ ) {

color += letters[Math.floor(Math.random() * 16)];

}

return color;

}

4.4.7 Secțiunea de blog

În această secțiune a site-ului oricare organizație își poate crea propriul blog, care va reprezenta chiar propria lor colecție de proiecte. Această pagină publică poate fi folosita drept mapă de proiecte. Caracteristica publică a acestei pagini o face folositoare pentru a o trimite eventualilor parteneri sau sponsori în vederea strângerii de fonduri.

Un alt avantaj al acestei secțiuni este acela de PR. Orice user al platformei poate vedea evenimentele altor ONG-uri.

În rândurile următoare sunt prezentate serviciile web ce stau la baza acestei functionalități.

Salvarea unui draft

exports.saveAsDraft = function(req,res){

console.log(req.body);

var newPost= new post();

newPost.set('post_title',req.body.title);

newPost.set('related_project',req.body.related);

newPost.set('author',req.body.author);

newPost.set('p_body',req.body.body);

newPost.set('p_date',req.body.date);

newPost.set('org',req.body.org);

newPost.save(function(err){

if(err){

console.log(err);

res.status(500).json({err: err});

}else{

res.status(200).json({success: 1});

console.log("Post Added!");

}

});

}

Publicarea unui articol

exports.publish = function(req,res){

console.log(req.body);

var newPost= new post();

newPost.set('post_title',req.body.title);

newPost.set('related_project',req.body.related);

newPost.set('author',req.body.author);

newPost.set('p_body',req.body.body);

newPost.set('p_date',req.body.date);

newPost.set('org',req.body.org);

newPost.set('active',1);

newPost.save(function(err){

if(err){

console.log(err);

res.status(500).json({err: err});

}else{

res.status(200).json({success: 1});

console.log("Post Added!");

}

});

}

Returnarea tuturor posturilor asociate unei organizații

exports.getAllPosts = function(req,res){

post.find({org: req.body._id}).deepPopulate(['author','related_project']).exec(

function(err,posts){

if(err){

res.status(500).json({msg: msg});

}else{

res.status(200).json(posts);

}

}

)

}

Returnarea informațiilor asociate unui post

exports.getSinglePost=function(req,res){

post.findOne({_id:req.body.PostID}).deepPopulate(['author','related_project']).exec(

function(err,post){

if(err){

res.status(500).json({msg: msg});

}else{

res.status(200).json(post);

}

}

)

}

Revenirea la stadiul de draft al unui post publicat

exports.updateToDraft=function(req,res){

post.findOne({_id:req.body.post_id})

.exec(function(err,post){

if(err){

console.log(err);

}else{

post.active=0;

post.p_body=req.body.body;

post.post_title=req.body.title;

post.related_project=req.body.related;

post.date_modifyed=new Date();

post.modifyed_by=req.body.author;

post.save(function(err){

if(err){

console.log(err);

}else{

console.log("Update to draft success!");

res.status(200).json({success:"post updated!"})

}

})

}

});

}

4.4.8 Secțiunea de ședințe

Un lucru foarte important este menținerea unei evidențe asupra celor discutate în cadrul ședintelor de proiect. Ședintele, din punctul meu de vedere sunt foarte importante, pentru că doar în cadrul ședințelor se poat lua decizii în mod democratic și sunt cel mai bun mod de a păstra pe toată lumea conectată.

Viziunea mea asupra acestei secțiuni este următoarea:

Ședințele se pot crea doar dacă sunt asociate unui proiect.

Ședințele se pot crea doar daca se specifică și data în care va avea loc ședința

La ședință se pot invita membrii, având opțiunea de a-i învita pe toți sau de a selecta din ei

Pagina de ședințe este împărțită în 3 zone: Decizii, Topicuri de discutie și Activități

În orice moment ai în vedere activitățile și orice modificare adusă activităților se va reflecta și în pagina de proiect.

Ședințele sunt listate și în pagina de proiect.

Adăugarea unei noi ședințe

exports.newMeeting = function(req,res){

var NewMeeting = new meeting();

NewMeeting.set('project',req.body.pro);

NewMeeting.set('date',req.body.date);

NewMeeting.set('org',req.body.org);

NewMeeting.save(function(err,doc){

if(err){

res.status(500).json({msg:err});

}else{

res.status(200).json(doc);

}

});

}

Returnarea tuturor ședințelor asociate unei organizații

exports.getOrgMeetings = function(req,res){

meeting.find({org:req.body.OrgID}).deepPopulate(['project','org']).exec(

function(err,doc){

if(err){

res.status(500).json({msg:err});

}else{

res.status(200).json(doc);

}

}

)

}

Returnarea informațiilor asociate unei ședinte

exports.getSingleMeeting = function(req,res){

meeting.findOne({_id:req.body.MeetingID})

.deepPopulate(['project','org','hosts','invited','confirmed','topics','decisions'])

.exec(function(err,doc){

if(err){

res.status(500).json({msg:err});

}else{

res.status(200).json(doc);

}

})

}

Adăugarea unui topic

exports.addTopic = function(req,res){

var newTopic=new topic();

newTopic.set('topic',req.body.topic);

newTopic.save(

function(err,doc){

if(err){

console.log(err);

}else{

console.log("New Topic");

console.log(doc);

meeting.update(

{_id:req.body.meeting},

{$push:

{

topics:doc._id

}

},

{upsert: true},

function(err,doc){

if(err){

console.log("err");

}

else{

console.log("Topic Added");

res.status(200).json(doc);

}

});

}

}

)

}

Adăugarea unei decizii

exports.addDecision=function(req,res){

var newDecision=new decision();

newDecision.set('decision',req.body.decision);

newDecision.save(

function(err,doc){

if(err){

console.log(err);

}else{

console.log("New Decision");

console.log(doc);

meeting.update(

{_id:req.body.meeting},

{$push:

{

decisions:doc._id

}

},

{upsert: true},

function(err,doc){

if(err){

console.log("err");

}

else{

console.log("Decision Added");

res.status(200).json(doc);

}

});

}

}

)

}

4.4.9 Adăugarea unui membru într-o organizație

Se poate adăuga prin două metode, fie direct, cu ajutorul adminului de organizație care poate adăuga orice membru care are cont pe platformă, fie userul aderând la o organizație de pe platformă. În acest caz este nevoie de acceptul administratorului de organizație pentru ca acesta să intre în organizație.

Adăugarea unui membru în organizație cu ajutorul adminului de organizație

exports.AddMemberToOrganization = function(req,res){

//console.log(req.body);

user.update(

{_id:req.body.user},

{$push:

{

orgs:req.body.org

}

},

{upsert: true},

function(err,doc){

if(err){

console.log(err);

}

else{

console.log("Orgs Added");

}

});

organization.update(

{_id:req.body.org},

{$push:

{

organization_members_id:req.body.user

}

},

{upsert: true},

function(err,doc){

if(err){

console.log(err);

}

else{

console.log("organization_members_id updated");

}

});

organization.findOne({_id:req.body.org})

.populate(['organization_members_id','organization_admin_id'])

.exec(function(err,org){

if(err){

console.log(err);

}else{

res.status(200).json(org);

}

});

}

Trimiterea unei cereri de aderare

exports.joinOrg = function(req,res){

var newJoin = new joinNotification();

newJoin.set('org_id',req.body.org);

newJoin.set('user_id',req.body.user);

newJoin.save(function(err,not){

if(err){

res.status(404).json({msg:err});

}else{

res.status(200).json(not);

}

});

}

Respingerea unei cereri de aderare la o organizație

exports.declineJoin = function(req,res){

joinNotification.findOne({_id:req.body.id}).remove().exec(function(err){

if(err){ console.log(err)}else{res.status(200).json({msg:'erased'})}

});

}

Acceptarea unei cereri de aderare la o organizație

exports.acceptJoin = function(req,res){

joinNotification.findOne({_id:req.body._id},function(err,doc){

doc.status=1;

doc.save(function(err,doc){

if(err){

res.status(404).json({msg:err});

}else{

res.status(200).json(doc);

}

});

});

user.update(

{_id:req.body.user_id._id},

{$push:

{

orgs:req.body.org_id

}

},

{upsert: true},

function(err,doc){

if(err){

console.log("err");

}

else{

console.log("Orgs Added");

}

});

organization.update(

{_id:req.body.org_id},

{$push:

{

organization_members_id:req.body.user_id._id

}

},

{upsert: true},

function(err,doc){

if(err){

console.log("err");

}

else{

console.log("organization_members_id updated");

}

});

}

5. CONCULUZII

Dezvoltarea acestei aplicații a plecat de la o provocare personală. La început mi-am propus să învaț ceva total nou. Pot spune că am reușit să dezvolt o aplicație folosind cele mai noi tehnologii ale momentului. Odată cu indeplinirea acestei provocări, spun cu tărie că de acum nimic nu mi se mai pare greu de realizat.

Aplicația web va putea fi folosită pe: http://taskheroes.net

Pe parcursul dezvoltării acestei versiuni a aplicației mi-am dat seama că acest proiect poate ajunge și mai departe de atât. Planurile de viitor sunt marețe, pentru că împreuna cu echipa mea vom realiza și aplicații de mobile, pentru mai multă portabilitate. De aceea cred cu tărie în viitorul acestei aplicații și sper ca aceasta să facă o diferență și să ajute voluntarii din întreaga lume. Pot spune că acesta poate fi punctul de plecare pentru un start-up. Spun asta privind și determinarea colegilor din echipa Task Heroes!

Alte îmbunătățiri pe care le putem aduce aplicației sunt implementarea unora dintre funcționalități folosind web-sockets, abilitatea de a colabora la proiecte mai multe organizații și abilitatea de a adăuga observatori externi la proiecte (cei care pot avea rol de parteneri sau sponsori ai acelor proiecte în realitate).

Un alt lucru care ar aduce unicitate aplicației noastre ar fi realizarea grafica a unor “eroi”.

Arhitectura aplicației este concepută special pentru a îmbina cat mai ușor toate tehnologiile necesare dezoltării ideii de la care am plecat cât și a planurilor noastre de viitor. Singurul impediment este cel financiar, pentru că serviciile cloud sunt destul de costisitoare.

Personal cred cu tarie ca acest proiect va reuși, și că vom aduce un aport pozitiv managementului de proiect în ONG-uri sub numele de Task Heroes.

Bibliografie

[1] Andrei Avădanei – Introducere in Design Patterns

http://www.worldit.info/articole/introducere-in-design-patterns-mvc-partea-i/

[2] Brad Dayley – Node.js, MongoDB, and AngularJS Web Development, Developer's Library

[3] Cristi Pascan – Javascript MVVM (Model View ViewModel )

http://cristi.phonefinder.ro/2012/10/30/javascript-mvvm-model-view-viewmodel/

[4] Eugen Tudorancea – Node.js Introducere – Thread-uri vs Evenimente

http://www.iamntz.com/2436/frontend-developer/node-js-introducere-partea-intai/

[5] Fundamentele managementului de proiect – suport de curs, FDSC, 2005

[6] Managementul Proiectului – Curs , Facultatea de Comunicare si Relații Publice "DavidOgilvy"

[7] O.Nicolaescu – Management, l. Verboncu, Editura Economică, 1996

[8] Articole de pe Wikipedia: http://ro.wikipedia.org/wiki

[9] AngularJS & NodeJS: http://www.openhub.ro/angular-js-node-js/

[10] Vasile Alaiba – Servicii web bazate pe arhitectura REST http://profs.info.uaic.ro/~alaiba/mw/index.php?title=Servicii_web_bazate_pe_arhitectura_REST

Bibliografie

[1] Andrei Avădanei – Introducere in Design Patterns

http://www.worldit.info/articole/introducere-in-design-patterns-mvc-partea-i/

[2] Brad Dayley – Node.js, MongoDB, and AngularJS Web Development, Developer's Library

[3] Cristi Pascan – Javascript MVVM (Model View ViewModel )

http://cristi.phonefinder.ro/2012/10/30/javascript-mvvm-model-view-viewmodel/

[4] Eugen Tudorancea – Node.js Introducere – Thread-uri vs Evenimente

http://www.iamntz.com/2436/frontend-developer/node-js-introducere-partea-intai/

[5] Fundamentele managementului de proiect – suport de curs, FDSC, 2005

[6] Managementul Proiectului – Curs , Facultatea de Comunicare si Relații Publice "DavidOgilvy"

[7] O.Nicolaescu – Management, l. Verboncu, Editura Economică, 1996

[8] Articole de pe Wikipedia: http://ro.wikipedia.org/wiki

[9] AngularJS & NodeJS: http://www.openhub.ro/angular-js-node-js/

[10] Vasile Alaiba – Servicii web bazate pe arhitectura REST http://profs.info.uaic.ro/~alaiba/mw/index.php?title=Servicii_web_bazate_pe_arhitectura_REST

Similar Posts