From 4b1542db7fba8c789810eb3328b4e3537c837b28 Mon Sep 17 00:00:00 2001 From: red Date: Sat, 21 Sep 2024 18:59:26 +0800 Subject: [PATCH 1/9] added spp_dashboard_base module --- spp_dashboard_base/__init__.py | 0 spp_dashboard_base/__manifest__.py | 30 ++++++++ spp_dashboard_base/pyproject.toml | 3 + .../static/description/icon.png | Bin 0 -> 12567 bytes .../static/src/card_board/card_board.js | 17 +++++ .../static/src/card_board/card_board.xml | 26 +++++++ spp_dashboard_base/static/src/chart/chart.js | 71 ++++++++++++++++++ spp_dashboard_base/static/src/chart/chart.xml | 18 +++++ .../static/src/dashboard/dashboard.js | 28 +++++++ .../static/src/dashboard/dashboard.xml | 14 ++++ 10 files changed, 207 insertions(+) create mode 100644 spp_dashboard_base/__init__.py create mode 100644 spp_dashboard_base/__manifest__.py create mode 100644 spp_dashboard_base/pyproject.toml create mode 100644 spp_dashboard_base/static/description/icon.png create mode 100644 spp_dashboard_base/static/src/card_board/card_board.js create mode 100644 spp_dashboard_base/static/src/card_board/card_board.xml create mode 100644 spp_dashboard_base/static/src/chart/chart.js create mode 100644 spp_dashboard_base/static/src/chart/chart.xml create mode 100644 spp_dashboard_base/static/src/dashboard/dashboard.js create mode 100644 spp_dashboard_base/static/src/dashboard/dashboard.xml diff --git a/spp_dashboard_base/__init__.py b/spp_dashboard_base/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/spp_dashboard_base/__manifest__.py b/spp_dashboard_base/__manifest__.py new file mode 100644 index 000000000..282f6ee54 --- /dev/null +++ b/spp_dashboard_base/__manifest__.py @@ -0,0 +1,30 @@ +# Part of OpenSPP. See LICENSE file for full copyright and licensing details. + + +{ + "name": "OpenSPP Dashboard: Base", + "category": "OpenSPP", + "version": "17.0.1.0.0", + "sequence": 1, + "author": "OpenSPP.org", + "website": "https://github.com/OpenSPP/openspp-modules", + "license": "LGPL-3", + "development_status": "Beta", + "maintainers": ["reichie020212"], + "depends": [ + "base", + ], + "data": [], + "assets": { + "web.assets_backend": [ + "spp_dashboard_base/static/src/dashboard/**/*", + "spp_dashboard_base/static/src/chart/**/*", + "spp_dashboard_base/static/src/card_board/**/*", + ], + }, + "demo": [], + "images": [], + "application": False, + "installable": True, + "auto_install": False, +} diff --git a/spp_dashboard_base/pyproject.toml b/spp_dashboard_base/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/spp_dashboard_base/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/spp_dashboard_base/static/description/icon.png b/spp_dashboard_base/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..35f8fec263588314689c920efc4b6728b407daaa GIT binary patch literal 12567 zcmW+-b66#B8$Q|AW^J`;v$sxev+XuxvyH7bZ?9d&I=lQSGq%(qxksmE0ENqsa=TIC*`@5*; zlZ@L_`{Xb|K5+g!T~BvDVye!4*Q3X9c!~4i!s6O*km%@}$Iack7k;fEj2m%dbS@g+ z&=(0&=8uP-x0Zo=3!)It?=-Zk9Pq4;w^+LagDlrZJ6O15xaY^oL=bSz;<)GDlr$uL6X)^k3|pxhu2( z;_tdO%DJ4jTUyBdzT$xUzXTq*Mdd^n8tz8T7ZRRi57vC$Zv>MUEP4wpRL0 zY~SS+buafxe|G8TvkS=E4my#ndzs#k96VRZL_BmH9%~Hc|NA6bAm*Nire4mUl&2d2 z>UMGd#-BiDQI%(923rv?=0>kWjD+9ZAv9Jzf77qJHcRST^@=%Qt!u=j@^4d?Tkss- zU5`VFrEG7c!5cXm5>)>2;wujVpiHWM;V%zYEnn zt{>bHYhNrG_lst7{4I$IN{efQ=;!t!5EFQ`Y%Rl%rR3!~XGQpFSPX`5eeZe3Oj>yf zxL0S$JbqB}QK?@2EY#`BMLLb136|1Gf%s9awql4-YM|Oz z>a>59{l&87VSl#6y^V1grlEyNVMwf!6ruszAaUXjgMt_7Ws?(?LzT{+J&=(RqR0k6t)rkqb z=6ZE9`|NcR`%Z387?`YBCLvYoFh5*2e*z)+Y2sXfHRfeB2>NOCfrtBI3$_cqgB3momFOvQ*KE z&q^#v$pl`u%p5!>y-+V1J!r?bi=NnVeq<{Qe^)ZV6TDYFiJlpC3)TJ{}7kC1|(f(x%6%=_QO(vTj(KKhu0ic)h0 zTB(3@c)p;iR=v4tHV}}(Qz;K{gCgT3o|$yG*xZW+6+it`di?T;NCb;9p!IKl0@y<{&@8*(dG zJ7=~SeleZo{^PgBKKA7wX^xmLUTavWkKEz)<$QUrg&XUJ%p78hIa%mCH&;;we@08D zT%eN(cMsjihvEYZz~rDSYHjU>tTx-b^6CU~h+9usoWn@ji1CoojaRBR4-_2F?n2~? z4$HICsd3{I-T-M72lkVR!+4dwNqA7l(3}Yy#$N3~z`h*uk#De!Zt6lyx>cx*r0S{a zNwuM|l|25s=i1704&l(k8N*k$q3Ijf!FFGTCoHmMqT2UW{*!}XrnoRoaaL!GmA?^M z{9InDo!g66sdpfdQpkv8pJ!K_smq}UD+gb=G_u2OyXoUgNmv{RLZ_A;W3^D5o67Dd z@aT?=EoQhUmWeW~*D|+l$07|tDXsq<+W;I(4ICRdi&A?)GrzkAPB?>ucfTOQ#JD-# z7u%{5g}WLVp2_!@03h(SLY&)DOa%$lNoFB<06hlQZ24v5krn`=qj9d zxwR^Mf*f90DFeCveGlO+RzGX?z|-N@ym<28E-@LF`q zCtG1cf$zcH9SOD$MM8+Ht~WkxfZ21;TkxvXkWS?JOtD{3|L`L#dwk31`#||~ef$!w z{o9j%TuulmsLR;u9nEx3%0doO3gvn)y3}mqqu`ATUkj7vCW*f+H!C(w)8oIZp@r-% z*LxrN@dQ5KG{xo=%^2pXoqt^y4p!4vFpWv4__1`JHHsE94Hw<_{$sNAP*SPJs`l4Z z3|z?G?+Y!08V0EqD^h$9^=r$dQz?31f8>gV?0zyj#^X9K&tWupNNCXpFO3LrBU4y9 z8BPteLvEfu2SXy>+MzpPW0_@4k{vUGbBv$(~9jjo)Nd zM)mt2Z8o&0KVspRzwk^?J5edrBQUIJ-A>ih}QyxSEOpH;2tinG>d-JI|C(+gT;kGC9c9uN5$=MfXm9(Wk> zX$SmbTL2lPVPpbyw~m|0%PS?8aDl#QkaOG$zL&8KFCV%c1-3ArCWmG9VjTL z$!JRotdQ?yMHl(T%FKdg62;t-{$S%qrjg;)5i~L&f8eDZ30X%X33+t*D%31SXi2s- zNn+HXRj}?g*kaAQQz`P=3I|-MvKr;ugL4Dik5Ptm;vl*aWDm+3maw!@)ni!aD6G-j zl)+DOS3JU(F*08DlYhgDph+kQ&>}tAw5TUi;+76nb9w*Po?DMGv0Jp;(fV^3D?&2nd5cj$n$$I!33DJBhkwuf zn(kRuq98aA1IEiy_lCedU?7Dtxq}){mJI`KBG|Q4(}gAx;`Q)lp;I=K?Xr2ShJ*kk zrkkhB5>lDVTDuh4kFbODtb~7q-}Y~yLttDHF+8Z=x(4pN_1`Y5grUi%4n`C_J>GgQsRoi9^EW@lXv^Zz;ELGC&4y+{K8YRW}ZFS9mSRU2hmLErl znloh1nLX2Ey$BPR2XcPDE^PN+l-`^qs!JhBfLk0Cz@*r_EnaKEyE&$KcidbMYC!cI z`{QC=DDhOb6L8ReD|11TFfs%{W~TSSq)Y<|Aw*e^sYg7?hk-(T%%q(gm~@VB=x76_ z<{ER>I=ONDb9B{8;_h&P|l!vJGEn+K|biD#LQOzdT z{?eho+7+fwmFKjvFsQlFTe#T@AB4>SP4sS1JjAh@$2tZ}y>utu(y2D@>^u;v?^x6D z18!{{r3MWPz=C&@0c)ZDdGrYyixJ8&y1L|urPW_Bl0w=rI!uSLHn?Nd%k^EBfAY?V zIEOkTN*hEAL-dL0-D#+clL#6+_-g4pj5@VKP-vtl1C}8C^*Hd8Hz z%d$o5Poa`)H_^u>Z+cpom)pTvd!jL=eN6noK{bhR9U}8&RXNGdBH^z7Dud`DJ9eUp zur6n6rC)8p2}aE4_ia&=)r^d)94S3`E;nT1&qfm~$f(kDDT6$7LP?d|I89lsuaRmn zA+k0Iq;S)Zj>OvSZFE&<-D^cqvCyAj`G-P3D7`kP?LF`#|9?+?`}i4cYNR@z%b7 zH}Ny%Vot0;)l^aL&ym=YA8g1?XDHHzdrSFs0(IpZbzyCEK<%>u-CY}nut46`GL2VG z7Db}?HwJ*Tbh0hFjF27Su`^-NI@B3BY=%_Ztl?Aqvm-hToO`A_?;XW@A+FsxsXm*n zWk=$5)D3~HiMD5}wc782-R`@26~W!oMfkU#(E}m(v`$L|Vw?AN5)1MYSJv@e_gT6J zs^A51l@OB(KK7v&qO%=QL=I}2`=dYdXnfN>?H)v%@%vFI$Kz);9E!NIM@=vw5TEo` z${*bu2MIi9^B8G&=P6HL4dm!tdjubg>a#W|MIoJ$D0E;qr6w~s2GG4#MltlZeO6dG z`C{$qUUQWaRcZ0??YlQWNZr9I$5Dq$9$tfK-+jg4AJ&$Up02s3>e~;1SwVx+;XuqV z(n|x=LhWVt80$?LIDZehr(J)Up!`-bM~k?8T1Y9VP}Pd3WMX|6$>ID<5Fy(E0g_!O zD&(b(aHRa2o<+IKmM(D6zTM(;(NS}@@5pSEKo`!SZ-E$!y06;cEZYX#qLuGCr+~)O z-Yeuh1K&ldU_-9BsL`zdnxE-=UF!1H)QayX#3cQ}5p>t&L1fY?-Zg$abs=HWrmK_L z^I0?o^kXc8jVEX41Kww=Mk#R@XC19X)0FllZkT$OE5Ds=Y9GJLH21jA+B+2O2@|2C z6FW5lUcTfvtHk{G`F)WXo9^4OK3Y!9w%XcB^?dy!%{owfGJJW)!XvhwiKqOEDeTT` z`U7CSmK#OS{pugg9K)Sp)w`$urpg1-@zxu8x}9T6BX$|$trv*pRt$(&+rP*-n7pwo z7)^8vTSy-h8y^$vGeqt+7N*+!paK>PL_TK3D)3pr4H-Uk4-M>Fc8`yc(dPV}4g*W6?-)p_Jue6ZF*A5MY zlrA}chd%LXdI0cvx3U|9V|>&g4lJkJa!hT#v7!A|HHVHg=4z<9U{}@u{n@)fq1PwJyT`&eCOT@Q=6m_v!H; z3%pX-m_HSdI#DiEsx6KTA?;JE%Nl5PP1fjRAQ6{`tD zz&5uzP@vAp^^dY;TD0_K$VAD)x=#xyiUTLy&p2XKKj+>ZVGS-<0)Y12_>^AL=cZ_; z3W0jv!NB;j5UP0pn~Om$rq04}ml8NQTZxFAQ~G z(TB`(_I+fLA(=5qMpndowwoVcHE3eRwO=D;bCU7|4%Np#V%HhympjWOL{-FKl~=># zm8Bsbte00&6YG&u*mbU=x%^CBA&{U8QQ4~0UF8qdQ7rk;JAZ8~Aweehnv!|6Uus}R z0CA{$abL2SRb-_84Bi*dan$;@Rq92O| zBxpKOO)@LxG$ONqBBa_EFO%>K)uqH>xi;Ba*R+>o(0Cq@Ki&fgeFu+NF>|2Ey@|!$ z9)G4S2p_}>4(ptVKS}DX=XV#2i~n@t`Fx>oJ5L4(Utf~tPJisuz=g{RHlDFB`yNS< z!&Br7{{z|+)4@C{J|z~0+`tCDFcf#|6iAL2M7DPKe?A(mtA$~VqL$|}gs~qwLQkeamYGUMY z90ks|B}`~C0hMF*`Rt&w8<)ftUgVM)Ln9&(II!gRj~;6hOpMtGvTX68yVAtR+Kk#R zga%HfH#SP#xqXpcWC^oRxb)l)S6dE*GUq|Pwa;##?r6rY`xqg_(qluEfPr5(OhS#$ z@I;%DD#xCn^jhO-fLznFNjyvfL!JC+c*K>5vNC%>z56GWA1vRbj4@s}c6y)8{u4T+ z2N(TZ$>zhQ(<{m8nesab9ScD@bhI%Vtb(X$Bp*C4=@xFtz%q& zvN`Yk95|HS=<3>Q#5LH7rCR0dDE@{E+I*K$gu}9zsh`I6rm9+a-xzI+QcadX!Sue; zQrd_lpV8wm9>k;AQ+Vcs0dYx-F%;#e5~GiGIdQ08R10C#Ii};+t$Qa~?C1Pd@UIm> zr7rH7UZrO~Gk`xH|20v)h@VeEUGgk3X(cZ2b>s2QWj2?lo!V!QF1PRe7F%-i&aj@M z_eW-bML0Cx5eZ~KA$w^H-=gP>*nuy%oCgDdpca1dw}VR z-x18fT{x3V!OH&2OMEulPQV1|&()vaA1W3f8AF2SVoQxMCMakT*(A*0{c9mwrOr0( zNG#e^`Gj$|Dv%Saa|&;GDZZw=a(~Xo+rpePorA@-rC*JsU1Xw+J#6Dg96g~Ke`Eg0 zmkQ^Nm#brp6~8T{J1H<3bo;3KGUF541NDgL2USd7EIfbNJ#`8Z_+=i&ZnlVf3Jrdn z@6P%*ymuA|-Fn81 z0?Wut04RiznTQiM=PXvx_hp5?-FAmjC=$1BfJNe>Qqp0t-0(2WNL9LqAs}=nQ9wTC z`_M&(VR?NHzwDG$p=lapcsf@pn2l9^Eh*1<5K%*M@=r-*@Dwm-LA9Hq)?Si{{x@0# z*D0N-XNHjIaBZ+s;(Q2YWq`IiZ^^g{sTmrt3_lz7g|rK!u|I9{H5{1{VzSI`ynM>p z*xWm%&kVnZYrosZxUu5&Axg=LM8_C{EhMl@l1*OCg+8trsD%%ev&L@~Z1p|~;1r53ZYWwXc6{B% zKR}gLlYT)zSpxb!4uIL>AqS82kg`{EfnQqw_PX9`2Ux$kTbmX(|Fd zWc%=xLwwxw3f|Dv7Qj#W5|NWRl&F31s4uWl{Vd+nt67vKo|RkqyZ8ey5 z7+y2mNqA}5v!5}}+lFqjHMNKmY2L4T-%q%h;C;sc!Lu`Nyxbe=F{Dca2aAuqheJNf zG{~#UVW|N0YsBj#;`uGX3ArH*gqp2`M=<2%?g9o{LgCoi$NTp1TVsLQT1uj_k;h=b zasc)*Y%qSq9p?2X6eSiUpx;Yj8hQCh5o{%W-DUf}f#=jwykNrTk5X9Z-!zA-mmDO! z60mXDL-BOjlS?zXe;90RyeOl7QVlIaJg9a=a3()o7z1+QPdhSTl@7XBaZmU0#>T$6f8Lg8|?SxYawWC$MP_G z*%yV(xlzr-$mF8-C3Y1(Ya%@bHSqTW5fK%RVrU_BTaXBW{zIffgc51w_+^uO8wtHz2=o&M z#8UT(BsB&!ai)O4$HbbPModc2OGuq_x*Dcz?-}?-#k419wiL!fGxg)ev!(7M>kb;? z;r$mphn94xxRqoK9-*0!qn5WTeSb0cmVdtCJD>5i7b`1iE5FB&IQ13x@!PeaUpv=#F>?8JFA28J^EvF1{k&9>`73Ajh1R8HY`o7buJMco_an81Jk z*OD1S==G$*zGnOZAj3KsqJeQc5)9En465_2g`nsoEl-r^A6cSHZ&wfegKTG7JgGgO-MtqcLD zIYY=H>{z&{@}*8e+3Z{;K}n)T)70yI+4X&l@eA9Na?S=0OP(6DtMYoKH-2d#h%CQr zSDQI)H*iiHkBdZs;j?y{}!q*QrdZjp&bFS9K**yZPpZCw#><#M)XrIYHvU_j~m&Gzg-#Uth{w2`h9 z*U-^H+1^-~;8VcG**cECV1rD-RCQj5SM@sjw|fsi1^vkm zeC$4v2UC@=4r;!lfY(7ZKGO~h>UD5v>Ya;oP4{W+)7+((RdSakrq$jhCTEnc>sJVA z8R$5`6-rg4kELClbQ0S*c%Ny_*EhSAb{Tg9p$FH!h_QUTRMN}X5#!SJ)BYq{!YQG} ztgWwpt7~N$yN5k5R3LnOoZf<}{`oiZ9B=&0>xl6dE^Ldc{~ul9Wpc!k<247=F8a7md®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 + + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
diff --git a/spp_dashboard_base/static/src/chart/chart.js b/spp_dashboard_base/static/src/chart/chart.js new file mode 100644 index 000000000..62876fcd4 --- /dev/null +++ b/spp_dashboard_base/static/src/chart/chart.js @@ -0,0 +1,71 @@ +/** @odoo-module **/ + +import {Component, onMounted, onWillStart, useRef} from "@odoo/owl"; +import {loadBundle} from "@web/core/assets"; + +export class ChartComponent extends Component { + setup() { + onMounted(() => this.renderChart()); + this.canvasRef = useRef("canvas"); + + this.chartTitle = ""; + if (this.props.chart_type === "pie") { + this.chartTitle = this.props.data_label; + } + + onWillStart(async () => { + return Promise.all([ + // Load external JavaScript and CSS libraries. + loadBundle({ + jsLibs: [ + // "/awesome_dashboard/static/lib/chart-js.4.4.4/chart.umd.min.js", + "https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js", + ], + }), + ]); + }); + } + + renderChart() { + const ctx = this.canvasRef.el.getContext("2d"); + + new Chart(ctx, { + type: this.props.chart_type, + data: { + labels: this.props.labels, + datasets: [ + { + label: this.props.data_label, + data: this.props.data, + backgroundColor: this.props.backgroundColor, + hoverOffset: 2, + }, + ], + }, + options: {...this.props.options}, + }); + } +} + +ChartComponent.template = "spp_dashboard_base.ChartComponentTemplate"; +ChartComponent.props = { + chart_type: {type: String, optional: true}, + labels: {type: Array, optional: true}, + data_label: {type: String, optional: true}, + data: {type: Array, optional: true}, + backgroundColor: {type: Array, optional: true}, + options: {type: Object, optional: true}, + size: {type: String, optional: true}, +}; +ChartComponent.defaultProps = { + chart_type: "pie", + labels: ["Red", "Blue", "Yellow"], + data_label: "Number of Colors", + data: [300, 50, 150], + backgroundColor: ["rgb(255, 99, 132)", "rgb(54, 162, 235)", "rgb(255, 205, 86)"], + options: { + maintainAspectRatio: true, + aspectRatio: 2, + }, + size: "col-md-6", +}; diff --git a/spp_dashboard_base/static/src/chart/chart.xml b/spp_dashboard_base/static/src/chart/chart.xml new file mode 100644 index 000000000..97973bfc1 --- /dev/null +++ b/spp_dashboard_base/static/src/chart/chart.xml @@ -0,0 +1,18 @@ + + + + +
+
+

+ +
+
+
+
diff --git a/spp_dashboard_base/static/src/dashboard/dashboard.js b/spp_dashboard_base/static/src/dashboard/dashboard.js new file mode 100644 index 000000000..a23cde99f --- /dev/null +++ b/spp_dashboard_base/static/src/dashboard/dashboard.js @@ -0,0 +1,28 @@ +/** @odoo-module **/ +import {Component, onWillStart, useState} from "@odoo/owl"; +import {CardBoardComponent} from "../card_board/card_board"; +import {ChartComponent} from "../chart/chart"; +import {registry} from "@web/core/registry"; +import {useService} from "@web/core/utils/hooks"; + +export class SppDashboard extends Component { + setup() { + super.setup(); + this.orm = useService("orm"); + this.state = useState({hierarchy: []}); + this.card_board_data = {}; + onWillStart(this.onWillStart); + this.dashboard_title = "Dashboard"; + } + + async onWillStart() { + // Super this function to get data from the server + // sample + // this.dashboard_data = await this.orm.call("res.partner", "get_data", []); + } +} + +SppDashboard.template = "spp_dashboard_base.dashboard_page"; +SppDashboard.components = {ChartComponent, CardBoardComponent}; + +registry.category("actions").add("spp_dashboard_tag", SppDashboard); diff --git a/spp_dashboard_base/static/src/dashboard/dashboard.xml b/spp_dashboard_base/static/src/dashboard/dashboard.xml new file mode 100644 index 000000000..46edcd960 --- /dev/null +++ b/spp_dashboard_base/static/src/dashboard/dashboard.xml @@ -0,0 +1,14 @@ + + + +
+
+
+

+
+
+
+
+
+
+
From 2c72ebcbdf9584b25200c2c0b5834ea2b9a75925 Mon Sep 17 00:00:00 2001 From: red Date: Sat, 21 Sep 2024 19:04:55 +0800 Subject: [PATCH 2/9] improved title of the chart --- spp_dashboard_base/static/src/chart/chart.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spp_dashboard_base/static/src/chart/chart.js b/spp_dashboard_base/static/src/chart/chart.js index 62876fcd4..d170d4ea6 100644 --- a/spp_dashboard_base/static/src/chart/chart.js +++ b/spp_dashboard_base/static/src/chart/chart.js @@ -9,7 +9,8 @@ export class ChartComponent extends Component { this.canvasRef = useRef("canvas"); this.chartTitle = ""; - if (this.props.chart_type === "pie") { + const chartTypesWithTitle = ["pie", "doughnut"]; + if (chartTypesWithTitle.includes(this.props.chart_type)) { this.chartTitle = this.props.data_label; } From 07a0c95d346bb68ac83c458d4aae54a200186883 Mon Sep 17 00:00:00 2001 From: red Date: Fri, 18 Oct 2024 16:07:36 +0800 Subject: [PATCH 3/9] Improvements of farmer demo generator --- .../models/generate_farmer_data.py | 43 +++++++++++++++++-- .../views/generate_farmer_data_view.xml | 19 +++++++- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/spp_farmer_registry_demo/models/generate_farmer_data.py b/spp_farmer_registry_demo/models/generate_farmer_data.py index cfdda75b5..16cfc3d04 100644 --- a/spp_farmer_registry_demo/models/generate_farmer_data.py +++ b/spp_farmer_registry_demo/models/generate_farmer_data.py @@ -7,6 +7,7 @@ from odoo import Command, api, fields, models +from odoo.addons.queue_job.delay import group from odoo.addons.spp_base_demo.locale_providers import create_faker from .. import tools @@ -57,16 +58,52 @@ class SPPGenerateFarmerData(models.Model): required=True, ) + locked = fields.Boolean(default=False) + locked_reason = fields.Char(readonly=True) + + GROUPS_PER_BATCH = 100 + def generate_sample_data(self): - batches = math.ceil(self.num_groups / 1000) + batches = math.ceil(self.num_groups / self.GROUPS_PER_BATCH) + + self.locked = True + self.locked_reason = "Generating Sample Data" + num_groups = self.num_groups + + jobs = [] for _ in range(0, batches): + jobs.append(self.delayable()._generate_sample_data(res=self, num_groups=num_groups)) + batch_num_groups = min(num_groups, self.GROUPS_PER_BATCH) + num_groups -= batch_num_groups # self.with_delay()._generate_sample_data(res_id=self.id) - self._generate_sample_data(res=self) + # self._generate_sample_data(res=self) + + main_job = group(*jobs) + main_job.on_done(self.delayable(channel="root.laos_data_generator")._mark_done()) + main_job.delay() + + def _mark_done(self): + self.ensure_one() + self.locked = False + self.locked_reason = "" + + def refresh_page(self): + """ + The function `refresh_page` returns a dictionary with the type and tag values to reload the + page. + :return: The code is returning a dictionary with two key-value pairs. The "type" key has the + value "ir.actions.client" and the "tag" key has the value "reload". + """ + return { + "type": "ir.actions.client", + "tag": "reload", + } @api.model def _generate_sample_data(self, **kwargs): res = kwargs.get("res") + num_groups = kwargs.get("num_groups") kind_farm_id = self.env.ref("spp_farmer_registry_base.kind_farm").id @@ -77,7 +114,7 @@ def _generate_sample_data(self, **kwargs): sex_choices = [option.value for option in options] sex_choice_range = sex_choices * 50 - num_groups = min(res.num_groups, 1000) + num_groups = min(num_groups, self.GROUPS_PER_BATCH) for i in range(0, num_groups): group_id = res._generate_group_data(i, fake, sex_choice_range, kind_farm_id) diff --git a/spp_farmer_registry_demo/views/generate_farmer_data_view.xml b/spp_farmer_registry_demo/views/generate_farmer_data_view.xml index 59e6ccf16..077c66e81 100644 --- a/spp_farmer_registry_demo/views/generate_farmer_data_view.xml +++ b/spp_farmer_registry_demo/views/generate_farmer_data_view.xml @@ -24,8 +24,25 @@
+ +
+ Warning: Operation in progress: + +
-
+
+ From ed7f049c69c4d181474580fd4c3363e53881d58d Mon Sep 17 00:00:00 2001 From: emjay0921 Date: Mon, 4 Nov 2024 13:52:50 +0800 Subject: [PATCH 7/9] change list title for cycle beneficiaries --- .../models/g2p_cycle.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/spp_programs_compliance_criteria/models/g2p_cycle.py b/spp_programs_compliance_criteria/models/g2p_cycle.py index 18f1ffd18..958e7e99c 100644 --- a/spp_programs_compliance_criteria/models/g2p_cycle.py +++ b/spp_programs_compliance_criteria/models/g2p_cycle.py @@ -59,3 +59,20 @@ def open_all_members_form(self): "domain": [("cycle_id", "=", self.id)], } return action + + def open_members_form(self): + self.ensure_one() + + action = { + "name": _("Cycle Beneficiaries"), + "type": "ir.actions.act_window", + "res_model": "g2p.cycle.membership", + "context": { + "create": False, + "default_cycle_id": self.id, + "search_default_enrolled_state": 1, + }, + "view_mode": "list,form", + "domain": [("cycle_id", "=", self.id)], + } + return action From 229e00ad895e56ef3fbc722446d8e2e87ca2cd3c Mon Sep 17 00:00:00 2001 From: emjay0921 Date: Mon, 4 Nov 2024 14:06:54 +0800 Subject: [PATCH 8/9] change icons --- spp_programs/views/cycle_view.xml | 7 ++++++- spp_programs_compliance_criteria/views/g2p_cycle_views.xml | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/spp_programs/views/cycle_view.xml b/spp_programs/views/cycle_view.xml index 5f9dc9934..82a9b556f 100644 --- a/spp_programs/views/cycle_view.xml +++ b/spp_programs/views/cycle_view.xml @@ -28,12 +28,13 @@ Part of OpenSPP. See LICENSE file for full copyright and licensing details. entitlements_count == 0 + fa-calculator