+

Last commit for inc/myco_objects.js: 5eb426449f564409023a31db54bedba7a948fb4c

Filter contributions by current contributor on contribution search

Benjamin Renard [2014-12-01 22:20:18]
Filter contributions by current contributor on contribution search
  1. function GroupList() {
  2.  
  3. lastChange=0;
  4.  
  5. this.loadFromLocalStorage=function() {
  6. if (jQuery.type(localStorage.groups)!='undefined') {
  7. try {
  8. var data=JSON.parse(localStorage.groups);
  9. this.lastChange=data.lastChange;
  10. for (el in data.groups) {
  11. this[el]=new Group(el,false,data.groups[el]);
  12. }
  13. }
  14. catch(e) {
  15. for (el in this) {
  16. if (this.isGroup(this[el])) {
  17. delete this[el];
  18. }
  19. }
  20. myconfirm('Erreur en chargeant les données locales. On les purges ?',
  21. function(data) {
  22. delete localStorage.groups;
  23. location.reload();
  24. }
  25. );
  26. }
  27. }
  28. }
  29.  
  30. this.export=function() {
  31. return {
  32. 'lastChange': this.lastChange,
  33. 'groups': this.each(function(idx,group) {
  34. return group.export();
  35. })
  36. };
  37. }
  38.  
  39. this.import=function(groups) {
  40. ret={};
  41. for (el in this) {
  42. if (this.isGroup(this[el])) {
  43. delete ret[el];
  44. }
  45. }
  46. this.lastChange=groups.lastChange;
  47. for (el in groups.groups) {
  48. this[el]=new Group(el,false,groups.groups[el]);
  49. }
  50. return true;
  51. }
  52.  
  53.  
  54. this.save=function() {
  55. localStorage.groups=JSON.stringify(this.export());
  56. }
  57.  
  58. this.each=function(fct) {
  59. var idx=0;
  60. var ret={};
  61. for (el in this) {
  62. if(this.isGroup(this[el])) {
  63. ret[el]=fct(idx++,this[el]);
  64. }
  65. }
  66. return ret;
  67. }
  68.  
  69. this.count=function() {
  70. len=0;
  71. this.each(function(idx,group) {
  72. len=len+1;
  73. });
  74. return len;
  75. }
  76.  
  77. this.isGroup=function(el) {
  78. return (jQuery.type(el)=='object' && jQuery.type(el.isGroup)=='function' && el.isGroup());
  79. }
  80.  
  81. this.byName=function(name) {
  82. for (el in this) {
  83. if(this.isGroup(this[el])) {
  84. if (this[el].name==name) {
  85. return this[el];
  86. }
  87. }
  88. }
  89. return false;
  90. }
  91.  
  92.  
  93. this.removeGroup=function(uuid) {
  94. if (this.isGroup(this[uuid])) {
  95. delete this[uuid];
  96. return true;
  97. }
  98. return false;
  99. }
  100.  
  101. this.balances=function(fct) {
  102. return this.each(function(idx,group) {
  103. bal=group.balance();
  104. bal.name=group.name;
  105. return bal;
  106. });
  107. }
  108.  
  109. this.newGroup=function(name,uuid) {
  110. var uuid=uuid||generate_uuid();
  111. this[uuid]=new Group(uuid,name);
  112. return uuid;
  113. }
  114.  
  115. }
  116.  
  117. function Group(uuid,name,data) {
  118. this.uuid=uuid || generate_uuid();
  119. this.name=name || false;
  120. this.contributors={};
  121. this.deletedContributors={};
  122. this.contributions={};
  123. this.deletedContributions={};
  124. this.categories={};
  125. this.deletedCategories={};
  126.  
  127. this.isGroup=function() {
  128. return true;
  129. }
  130.  
  131. this.export=function() {
  132. var contributors={};
  133. for (email in this.contributors) {
  134. contributors[email]=this.contributors[email].export();
  135. }
  136. var contributions={}
  137. for (uuid in this.contributions) {
  138. contributions[uuid]=this.contributions[uuid].export();
  139. }
  140. var categories={}
  141. for (uuid in this.categories) {
  142. categories[uuid]=this.categories[uuid].export();
  143. }
  144. return {
  145. 'uuid': this.uuid,
  146. 'name': encodeURIComponent(this.name),
  147. 'contributors': contributors,
  148. 'deletedContributors': this.deletedContributors,
  149. 'contributions': contributions,
  150. 'deletedContributions': this.deletedContributions,
  151. 'categories': categories,
  152. 'deletedCategories': this.deletedCategories
  153. };
  154. }
  155.  
  156. /*
  157.   * Contributors
  158.   */
  159. this.removeContributor=function(c) {
  160. this.deletedContributors[c.email]=c.export();
  161. time=new Date().getTime();
  162. this.deletedContributors[c.email].deletionTime=time;
  163. contributions=this.contributionsByContributorEmail(c.email);
  164. for (idx in contributions) {
  165. this.deleteContribution(contributions[idx].uuid,time);
  166. }
  167. delete this.contributors[c.email];
  168. return true;
  169. }
  170.  
  171. this.restoreContributor=function(email) {
  172. if (email in this.contributors) return;
  173. if (! email in this.deletedContributors) return;
  174. this.contributors[email]=this.importContributor(this.deletedContributors[email]);
  175. contributions=this.deletedContributionsByContributorEmail(email);
  176. for (idx in contributions) {
  177. if (contributions[idx].lastChange==this.deletedContributors[email].deletionTime) {
  178. this.restoreContribution(contributions[idx].uuid);
  179. }
  180. }
  181. delete this.deletedContributors[email];
  182. return true;
  183. }
  184.  
  185. this.getDeletedContributors=function() {
  186. var ret=[];
  187. for (email in this.deletedContributors) {
  188. ret.push(this.importContributor(this.deletedContributors[email]));
  189. }
  190. return ret;
  191. }
  192.  
  193. this.contributorByName=function(name) {
  194. for (email in this.contributors) {
  195. if (this.contributors[email].name == name) return this.contributors[email];
  196. }
  197. return undefined;
  198. }
  199.  
  200. this.contributorByEmail=function(email) {
  201. if (jQuery.type(this.contributors[email])!='undefined') {
  202. return this.contributors[email];
  203. }
  204. return undefined;
  205. }
  206.  
  207. this.addContributor=function(c) {
  208. this.contributors[c.email]=c;
  209. }
  210.  
  211. this.replaceContributor=function(email,c) {
  212. delete this.contributors[email];
  213. this.contributors[c.email]=c;
  214. }
  215.  
  216. this.importContributor=function(data) {
  217. return new Contributor(
  218. decodeURIComponent(data.name),
  219. data.email
  220. );
  221. }
  222.  
  223. /*
  224.   * Contributions
  225.   */
  226. this.contributionsByContributorEmail=function(email) {
  227. var ret=[];
  228. for (uuid in this.contributions) {
  229. if (this.contributions[uuid].contributor.email==email) {
  230. ret.push(this.contributions[uuid]);
  231. }
  232. }
  233. ret.sort(function(a,b) {
  234. if (a.date==b.date) {
  235. return 0;
  236. }
  237. else if(a.date<b.date) {
  238. return -1;
  239. }
  240. else {
  241. return 1;
  242. }
  243. });
  244. return ret;
  245. }
  246.  
  247. this.deletedContributionsByContributorEmail=function(email) {
  248. var ret=[];
  249. for (uuid in this.deletedContributions) {
  250. if (this.deletedContributions[uuid].contributor==email) {
  251. ret.push(new Contribution(
  252. this.contributorByEmail(email),
  253. this.deletedContributions[uuid].cost,
  254. decodeURIComponent(this.deletedContributions[uuid].title),
  255. this.deletedContributions[uuid].date,
  256. this.deletedContributions[uuid].category,
  257. uuid,
  258. this.deletedContributions[uuid].lastChange
  259. ));
  260. }
  261. }
  262. ret.sort(function(a,b) {
  263. if (a.lastChange==b.lastChange) {
  264. return 0;
  265. }
  266. else if(a.lastChange<b.lastChange) {
  267. return -1;
  268. }
  269. else {
  270. return 1;
  271. }
  272. });
  273. return ret;
  274. }
  275.  
  276. this.addContribution=function(c) {
  277. this.contributions[c.uuid]=c;
  278. }
  279.  
  280. this.updateContribution=function(uuid,c) {
  281. c.uuid=uuid;
  282. this.contributions[uuid]=c;
  283. }
  284.  
  285. this.deleteContribution=function(uuid,time) {
  286. this.contributions[uuid].lastChange=time || new Date().getTime();
  287. this.deletedContributions[uuid]=this.contributions[uuid].export();
  288. delete this.contributions[uuid];
  289. }
  290.  
  291. this.restoreContribution=function(uuid) {
  292. this.deletedContributions[uuid].lastChange=new Date().getTime();
  293. this.contributions[uuid]=this.importContribution(this.deletedContributions[uuid]);
  294. delete this.deletedContributions[uuid];
  295. }
  296.  
  297. this.importContribution=function(data) {
  298. return new Contribution(
  299. this.contributorByEmail(data.contributor),
  300. data.cost,
  301. decodeURIComponent(data.title),
  302. data.date,
  303. data.category,
  304. data.uuid,
  305. data.lastChange
  306. );
  307. }
  308.  
  309. this.findContributionByTitleMatches=function() {
  310. var contributions=this.contributions;
  311.  
  312. return function(q, cb) {
  313. var matches, substrRegex;
  314.  
  315. // an array that will be populated with substring matches
  316. matches = [];
  317.  
  318. // regex used to determine if a string contains the substring `q`
  319. substrRegex = new RegExp(q, 'i');
  320.  
  321. var titles=[];
  322. for (uuid in contributions) {
  323. if (substrRegex.test(contributions[uuid].title)) {
  324. var title=String(contributions[uuid].title).replace(/^\s+|\s+$/g, '');
  325. if (titles.indexOf(title.toLowerCase())!=-1) {
  326. continue;
  327. }
  328. titles.push(title.toLowerCase());
  329. matches.push({
  330. value: title,
  331. category: contributions[uuid].category
  332. });
  333. }
  334. }
  335.  
  336. cb(matches);
  337. };
  338. }
  339.  
  340. this.searchContributions=function(pattern) {
  341. var ret=[];
  342. substrRegex = new RegExp(pattern, 'i');
  343. for (uuid in this.contributions) {
  344. if (substrRegex.test(this.contributions[uuid].title) || substrRegex.test(this.contributions[uuid].cost)) {
  345. ret.push(this.contributions[uuid]);
  346. }
  347. }
  348. return ret;
  349. }
  350.  
  351. this.getContributionsByCategory=function (category) {
  352. var ret={};
  353. for (uuid in this.contributions) {
  354. if (this.contributions[uuid].category==category.uuid) {
  355. ret[uuid]=this.contributions[uuid];
  356. }
  357. }
  358. return ret;
  359. }
  360.  
  361. this.findUnusedCategories=function() {
  362. var cats={};
  363. for (uuid in this.contributions) {
  364. cid=this.contributions[uuid].category;
  365. if ($.type(cats[cid])=='undefined') {
  366. cats[cid]=1;
  367. }
  368. else {
  369. cats[cid]++;
  370. }
  371. }
  372. var ret={};
  373. for (cid in this.categories) {
  374. if ($.type(cats[cid])=='undefined') {
  375. ret[cid]=this.categories[cid];
  376. }
  377. }
  378. return ret;
  379. }
  380.  
  381. /*
  382.   * Categories
  383.   */
  384.  
  385. this.addCategory=function(c) {
  386. this.categories[c.uuid]=c;
  387. }
  388.  
  389. this.updateCategory=function(uuid,c) {
  390. c.uuid=uuid;
  391. this.categories[uuid]=c;
  392. }
  393.  
  394. this.deleteCategory=function(uuid,time) {
  395. this.categories[uuid].lastChange=time || new Date().getTime();
  396. this.deletedCategories[uuid]=this.categories[uuid].export();
  397. delete this.categories[uuid];
  398. }
  399.  
  400. this.restoreCategory=function(uuid) {
  401. this.deletedCategories[uuid].lastChange=new Date().getTime();
  402. this.categories[uuid]=this.importCategory(this.deletedCategories[uuid]);
  403. delete this.deletedCategories[uuid];
  404. }
  405.  
  406. this.getCategoryByName=function(name,approx) {
  407. if(approx) {
  408. name=String(name).replace(/^\s+|\s+$/g, '').toLowerCase();
  409. }
  410. for (uuid in this.categories) {
  411. if (approx) {
  412. if (String(this.categories[uuid].name).replace(/^\s+|\s+$/g, '').toLowerCase()==name) {
  413. return this.categories[uuid];
  414. }
  415. }
  416. else if(this.categories[uuid].name==name) {
  417. return this.categories[uuid]
  418. }
  419. }
  420. return false;
  421. }
  422.  
  423. this.importCategory=function(data) {
  424. return new Category(
  425. decodeURIComponent(data.name),
  426. data.color,
  427. data.lastChange,
  428. data.uuid
  429. );
  430. }
  431.  
  432. this.getSortedCategories=function() {
  433. uuids=[];
  434. for (uuid in this.categories) {
  435. uuids.push(uuid);
  436. }
  437. tmp_cats=this.categories;
  438. uuids.sort(function(a,b) {
  439. return tmp_cats[a]['name'].localeCompare(tmp_cats[b]['name']);
  440. });
  441. var ret={};
  442. for (idx in uuids) {
  443. ret[uuids[idx]]=this.categories[uuids[idx]];
  444. }
  445. return ret;
  446. }
  447.  
  448. this.getCategoriesStats=function() {
  449. var cats={};
  450. for (uuid in this.contributions) {
  451. if (jQuery.type(cats[this.contributions[uuid].category])=='undefined') {
  452. cats[this.contributions[uuid].category]=0;
  453. }
  454. cats[this.contributions[uuid].category]+=this.contributions[uuid].cost;
  455. }
  456. var data=[];
  457. for (cid in cats) {
  458. if (jQuery.type(this.categories[cid])!='undefined') {
  459. data.push({
  460. 'label': this.categories[cid].name,
  461. 'data': cats[cid],
  462. 'color': this.categories[cid].color
  463. });
  464. }
  465. }
  466. return data;
  467. }
  468.  
  469. /*
  470.   * Balance
  471.   */
  472. this.balance=function() {
  473. total={}
  474. min=-1;
  475. max=0;
  476. for (email in this.contributors) {
  477. var sum=0;
  478. cl=this.contributionsByContributorEmail(email);
  479. for (idx in cl) {
  480. sum+=cl[idx].cost;
  481. }
  482. if (min==-1 || min>sum) {
  483. min=sum;
  484. }
  485. if(max<sum) {
  486. max=sum;
  487. }
  488. total[email]=sum;
  489. }
  490. balance={}
  491. var sum=0;
  492. for (email in total) {
  493. balance[email]={
  494. 'name': this.contributors[email].name,
  495. 'total': total[email],
  496. 'diff': total[email]-max,
  497. }
  498. sum=sum+total[email];
  499. }
  500. return {
  501. 'balance': balance,
  502. 'sum': sum,
  503. 'min': min,
  504. 'max': max
  505. };
  506. }
  507.  
  508. /*
  509.   * Contructor
  510.   */
  511. if (jQuery.type(data)=='object') {
  512. try {
  513. this.uuid=data.uuid;
  514. this.name=data.name;
  515. if (jQuery.type(data.contributors) == 'object') {
  516. for (email in data.contributors) {
  517. this.contributors[email]=this.importContributor(data.contributors[email]);
  518. }
  519. }
  520. if (jQuery.type(data.deletedContributors) == 'object') {
  521. for (email in data.deletedContributors) {
  522. this.deletedContributors[email]=data.deletedContributors[email];
  523. }
  524. }
  525. if (jQuery.type(data.contributions) == 'object') {
  526. for (uuid in data.contributions) {
  527. this.contributions[uuid]=this.importContribution(data.contributions[uuid]);
  528. }
  529. }
  530. if (jQuery.type(data.deletedContributions) == 'object') {
  531. for (uuid in data.deletedContributions) {
  532. this.deletedContributions[uuid]=data.deletedContributions[uuid];
  533. }
  534. }
  535. if (jQuery.type(data.categories) == 'object') {
  536. for (uuid in data.categories) {
  537. this.categories[uuid]=this.importCategory(data.categories[uuid]);
  538. }
  539. }
  540. if (jQuery.type(data.deletedCategories) == 'object') {
  541. for (uuid in data.deletedCategories) {
  542. this.deletedCategories[uuid]=data.deletedCategories[uuid];
  543. }
  544. }
  545. }
  546. catch (e) {
  547. console.log(e);
  548. alert('Une erreur est survenue en chargeant le groupe '+this.name+' depuis le cache');
  549. }
  550. }
  551. }
  552.  
  553. function Contributor(name,email) {
  554. this.name=name;
  555. this.email=email;
  556. this.export=function() {
  557. return {
  558. 'name': encodeURIComponent(this.name),
  559. 'email': this.email
  560. };
  561. }
  562. }
  563.  
  564. function Category(name,color,lastChange,uuid) {
  565. this.name=name;
  566. this.color=color || '#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6);
  567. this.lastChange=lastChange || new Date().getTime();
  568. this.uuid=uuid || generate_uuid();
  569. this.export=function() {
  570. return {
  571. 'name': encodeURIComponent(this.name),
  572. 'color': this.color,
  573. 'lastChange': this.lastChange,
  574. 'uuid': this.uuid
  575. };
  576. }
  577. }
  578.  
  579. function Contribution(contributor,cost,title,date,cat,uuid,lastChange) {
  580. this.contributor=contributor;
  581. this.cost=cost;
  582. this.title=title;
  583. if (jQuery.type(date)!='date') {
  584. date=moment(date).toDate();
  585. }
  586. this.date=date;
  587. this.uuid=uuid || generate_uuid();
  588. this.category=cat;
  589. this.lastChange=lastChange || new Date().getTime();
  590. this.export=function() {
  591. return {
  592. 'contributor': this.contributor.email,
  593. 'uuid': this.uuid,
  594. 'cost': this.cost,
  595. 'title': encodeURIComponent(this.title),
  596. 'date': this.date.getTime(),
  597. 'category': this.category,
  598. 'lastChange': this.lastChange,
  599. };
  600. }
  601.  
  602. this.getTitle=function() {
  603. if (jQuery.type(this.title)=='string') {
  604. return this.title;
  605. }
  606. return '';
  607. }
  608. }
  609.  
  610. function SyncServer() {
  611. this.url=false;
  612. this.email=false;
  613. this.password=false;
  614. this.logged=false;
  615.  
  616. this.login=function(url,email,password,onsuccess,onerror) {
  617. this.url=url;
  618. this.email=email;
  619. this.password=password;
  620.  
  621. try {
  622. jQuery.getJSON(
  623. this.url+'/login',
  624. {'email':email,'password':password, 'time': new Date().getTime()},
  625. function(data, textStatus) {
  626. console.log(data);
  627. if (textStatus=='success') {
  628. if(jQuery.type(data.email) != 'undefined' && jQuery.type(data.name) != 'undefined') {
  629. console.log('Login success return');
  630. console.log(onsuccess);
  631. onsuccess(data);
  632. return true;
  633. }
  634. }
  635. onerror(data);
  636. }
  637. ).fail(onerror);
  638. }
  639. catch(e) {
  640. if(jQuery.type(onerror)=='function') {
  641. onerror();
  642. }
  643. }
  644. }
  645.  
  646. this.subscribe=function(url,email,name,password,onsuccess,onerror) {
  647. this.url=url;
  648. this.email=email;
  649. this.name=name;
  650. this.password=password;
  651.  
  652. try {
  653. jQuery.getJSON(
  654. this.url+'/subscribe',
  655. {'email':email,'name': name,'password':password, 'time': new Date().getTime()},
  656. function(data, textStatus) {
  657. console.log(data);
  658. if (textStatus=='success') {
  659. if(jQuery.type(data.email) != 'undefined' && jQuery.type(data.name) != 'undefined') {
  660. onsuccess(data);
  661. return true;
  662. }
  663. }
  664. onerror(data);
  665. return false;
  666. }
  667. ).fail(onerror);
  668. }
  669. catch(e) {
  670. if(jQuery.type(onerror)=='function') {
  671. onerror();
  672. }
  673. }
  674. }
  675.  
  676.  
  677. this.sync=function(url,email,password,groups,onsuccess,onerror) {
  678. this.url=url;
  679. this.email=email;
  680. this.password=password;
  681. try {
  682. jQuery.post(
  683. this.url+'/sync',
  684. {
  685. 'email':email,
  686. 'password':password,
  687. 'groups': JSON.stringify(groups)
  688. },
  689. function(data, textStatus) {
  690. console.log(data);
  691. if (textStatus=='success') {
  692. if(jQuery.type(data.groups)) {
  693. console.log('Sync success return');
  694. onsuccess(data);
  695. return true;
  696. }
  697. }
  698. onerror(data);
  699. },
  700. 'json'
  701. ).fail(onerror);
  702. }
  703. catch(e) {
  704. if(jQuery.type(onerror)=='function') {
  705. onerror();
  706. }
  707. }
  708. }
  709.  
  710. }