Tower: upload tk_construction_management 18.0.2.0.8 (was 18.0.2.0.8, via marketplace)
BIN
addons/tk_construction_management/static/.DS_Store
vendored
Normal file
BIN
addons/tk_construction_management/static/description/cover.gif
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
addons/tk_construction_management/static/description/icon.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
addons/tk_construction_management/static/description/img/ac1.png
Normal file
|
After Width: | Height: | Size: 504 KiB |
|
After Width: | Height: | Size: 158 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 629 KiB |
|
After Width: | Height: | Size: 217 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 110 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 444 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 76 KiB |
BIN
addons/tk_construction_management/static/description/img/ac2.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 280 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 276 KiB |
|
After Width: | Height: | Size: 265 KiB |
|
After Width: | Height: | Size: 313 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 268 KiB |
|
After Width: | Height: | Size: 239 KiB |
BIN
addons/tk_construction_management/static/description/img/ac3.png
Normal file
|
After Width: | Height: | Size: 186 KiB |
|
After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 200 KiB |
|
After Width: | Height: | Size: 239 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 204 KiB |
|
After Width: | Height: | Size: 200 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 170 KiB |
|
After Width: | Height: | Size: 204 KiB |
BIN
addons/tk_construction_management/static/description/img/ac4.png
Normal file
|
After Width: | Height: | Size: 187 KiB |
|
After Width: | Height: | Size: 201 KiB |
|
After Width: | Height: | Size: 206 KiB |
|
After Width: | Height: | Size: 224 KiB |
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 244 KiB |
|
After Width: | Height: | Size: 170 KiB |
|
After Width: | Height: | Size: 167 KiB |
BIN
addons/tk_construction_management/static/description/img/ac5.png
Normal file
|
After Width: | Height: | Size: 235 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 195 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 216 KiB |
|
After Width: | Height: | Size: 25 KiB |
BIN
addons/tk_construction_management/static/description/img/ac6.png
Normal file
|
After Width: | Height: | Size: 245 KiB |
|
After Width: | Height: | Size: 178 KiB |
|
After Width: | Height: | Size: 96 KiB |
BIN
addons/tk_construction_management/static/description/img/ac7.png
Normal file
|
After Width: | Height: | Size: 258 KiB |
BIN
addons/tk_construction_management/static/description/img/ac8.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
addons/tk_construction_management/static/description/img/ac9.png
Normal file
|
After Width: | Height: | Size: 147 KiB |
1011
addons/tk_construction_management/static/description/index.html
Normal file
@@ -0,0 +1,246 @@
|
||||
.content-area {
|
||||
max-width: 1070px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#topnav {
|
||||
background: #37474f;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.admin-menu {
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
flex: 0.05 0 0;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex: 1 0 0;
|
||||
}
|
||||
|
||||
.logo-t {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 2px solid #26c6da;
|
||||
text-align: center;
|
||||
line-height: 28px;
|
||||
border-radius: 50%;
|
||||
margin-right: 15px;
|
||||
margin-left: 5px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
flex: 2 0 0;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: #232e34;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
height: 36px;
|
||||
border-radius: 35px;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.search-bar-dropdown {
|
||||
flex: 1 0 0;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 18px;
|
||||
margin-right: 15px;
|
||||
background: #2c393f;
|
||||
|
||||
}
|
||||
|
||||
.search-bar-input {
|
||||
flex: 2 0 0;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 0 18px;
|
||||
line-height: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-bar-input input[type="text"] {
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.search-bar-input input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.box.banana_map {
|
||||
color: #fff;
|
||||
background: #eff4f7;
|
||||
padding: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.box.banana_map .title {
|
||||
padding-top: 40px;
|
||||
padding-left: 25px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.box.banana_map .subtitle {
|
||||
font-weight: 700;
|
||||
padding-top: 10px;
|
||||
padding-left: 25px;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.box {
|
||||
max-height: 444px;
|
||||
}
|
||||
.box-full {
|
||||
max-height: 470px;
|
||||
}
|
||||
.box .banana {
|
||||
min-height: 404px;
|
||||
background-image: url('img/banana.png');
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.box .map {
|
||||
min-height: 404px;
|
||||
background-image: url('img/map.png');
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.box .cog-icon {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 55px;
|
||||
top: 25px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
@media screen and (max-width:760px) {
|
||||
#topnav {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.admin-menu {
|
||||
flex-basis: 20%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
justify-content: flex-end;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
flex-basis: 80%;
|
||||
}
|
||||
|
||||
.topnav-rightmenu,
|
||||
.search-bar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.box {
|
||||
padding: 25px 35px 25px 30px;
|
||||
height: 100vh;
|
||||
background: #fff;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
#monthly-earnings-chart #apexcharts-canvas {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#monthly-earnings-chart #apexcharts-canvas:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 58%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: #24bdd3;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
#monthly-earnings-chart #apexcharts-title-text {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#monthly-earnings-chart #apexcharts-subtitle-text {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.monthly-earnings-text {
|
||||
position: absolute;
|
||||
left: 70px;
|
||||
top: 187px;
|
||||
color: #fff;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.monthly-earnings-text h6 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.chart-title h5 {
|
||||
font-size: 18px;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
margin-bottom: 38px;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width:767px) {
|
||||
.monthly-earnings-text {
|
||||
left: 30px;
|
||||
}
|
||||
.box {
|
||||
padding: 25px 2rem;
|
||||
}
|
||||
|
||||
.pos_dashboard select#date_filter {
|
||||
background-position: 29rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sparkboxes .box {
|
||||
padding: 3px 0 0 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#spark1,
|
||||
#spark2,
|
||||
#spark3,
|
||||
#spark4 {
|
||||
position: relative;
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
|
||||
/* overrides */
|
||||
.sparkboxes #apexcharts-subtitle-text {
|
||||
fill: #8799a2 !important;
|
||||
}
|
||||
.height-auto {
|
||||
height: auto !important;
|
||||
max-height: none !important;
|
||||
}
|
||||
.spinner-border {
|
||||
display: none;
|
||||
}
|
||||
212
addons/tk_construction_management/static/src/css/lib/style.css
Normal file
@@ -0,0 +1,212 @@
|
||||
.content-area {
|
||||
max-width: 1070px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#topnav {
|
||||
background: #37474f;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.admin-menu {
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
flex: 0.05 0 0;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex: 1 0 0;
|
||||
}
|
||||
|
||||
.logo-t {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 2px solid #26c6da;
|
||||
text-align: center;
|
||||
line-height: 28px;
|
||||
border-radius: 50%;
|
||||
margin-right: 15px;
|
||||
margin-left: 5px;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
flex: 2 0 0;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: #232e34;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
height: 36px;
|
||||
border-radius: 35px;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.search-bar-dropdown {
|
||||
flex: 1 0 0;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 18px;
|
||||
margin-right: 15px;
|
||||
background: #2c393f;
|
||||
|
||||
}
|
||||
|
||||
.search-bar-input {
|
||||
flex: 2 0 0;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 0 18px;
|
||||
line-height: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-bar-input input[type="text"] {
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.search-bar-input input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.box {
|
||||
max-height: 444px;
|
||||
}
|
||||
.box-full {
|
||||
max-height: 470px;
|
||||
}
|
||||
|
||||
.box .cog-icon {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 55px;
|
||||
top: 25px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
@media screen and (max-width:760px) {
|
||||
#topnav {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.admin-menu {
|
||||
flex-basis: 20%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
justify-content: flex-end;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
flex-basis: 80%;
|
||||
}
|
||||
|
||||
.topnav-rightmenu,
|
||||
.search-bar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.box {
|
||||
padding: 25px 35px 25px 30px;
|
||||
height: 100vh;
|
||||
background: #fff;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
#monthly-earnings-chart #apexcharts-canvas {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#monthly-earnings-chart #apexcharts-canvas:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 58%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: #24bdd3;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
#monthly-earnings-chart #apexcharts-title-text {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#monthly-earnings-chart #apexcharts-subtitle-text {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.monthly-earnings-text {
|
||||
position: absolute;
|
||||
left: 70px;
|
||||
top: 187px;
|
||||
color: #fff;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.monthly-earnings-text h6 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.chart-title h5 {
|
||||
font-size: 18px;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
margin-bottom: 38px;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width:760px) {
|
||||
.monthly-earnings-text {
|
||||
left: 30px;
|
||||
}
|
||||
|
||||
.box {
|
||||
padding: 25px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.sparkboxes .box {
|
||||
padding: 3px 0 0 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#spark1,
|
||||
#spark2,
|
||||
#spark3,
|
||||
#spark4 {
|
||||
position: relative;
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
|
||||
/* overrides */
|
||||
.sparkboxes #apexcharts-subtitle-text {
|
||||
fill: #8799a2 !important;
|
||||
}
|
||||
.height-auto {
|
||||
height: auto !important;
|
||||
max-height: none !important;
|
||||
}
|
||||
.spinner-border {
|
||||
display: none;
|
||||
}
|
||||
242
addons/tk_construction_management/static/src/css/style.scss
Normal file
@@ -0,0 +1,242 @@
|
||||
.o_action_manager {
|
||||
overflow: auto !important;
|
||||
}
|
||||
.construction_dashboard {
|
||||
background-color: #f8f9fa !important;
|
||||
height: 100%;
|
||||
.d-flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.just-end {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.tk-form-control {
|
||||
width: 150px;
|
||||
border-radius: 1px !important;
|
||||
border: none !important;
|
||||
background-color: #eef3f7;
|
||||
border-color: #F5F8FA;
|
||||
color: #5E6278;
|
||||
transition: color 0.2s ease, background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.tk-btn-prime {
|
||||
border-radius: 1px !important;
|
||||
}
|
||||
|
||||
.me-2 {
|
||||
margin-right: .5rem !important;
|
||||
}
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
word-wrap: break-word;
|
||||
background-color: #fff;
|
||||
background-clip: border-box;
|
||||
border-radius: .475rem;
|
||||
border: 0;
|
||||
box-shadow: 0 0 20px 0 rgba(76, 87, 125, .02);
|
||||
}
|
||||
.card.card-xl-stretch.mb-xl-8:hover {
|
||||
transform: translateY(-5px) scale(1.005) translateZ(0);
|
||||
box-shadow: 0 24px 36px rgba(0, 0, 0, 0.11), 0 24px 46px transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
.card-body {
|
||||
flex: 1 1 auto;
|
||||
padding: 1rem 1rem;
|
||||
}
|
||||
|
||||
.card-p {
|
||||
padding: 2rem 2.25rem !important;
|
||||
}
|
||||
|
||||
.flex-stack {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-grow-1 {
|
||||
flex-grow: 1 !important;
|
||||
}
|
||||
|
||||
.d-flex {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
.symbol {
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
border-radius: .475rem;
|
||||
}
|
||||
|
||||
.symbol .symbol-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 500;
|
||||
color: #3f4254;
|
||||
background-color: #f5f8fa;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
border-radius: .475rem;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.svg-icon.svg-icon-info svg [fill]:not(.permanent):not(g) {
|
||||
transition: fill .3s ease;
|
||||
fill: #009ef7;
|
||||
}
|
||||
|
||||
.svg-icon.svg-icon-warning svg [fill]:not(.permanent):not(g) {
|
||||
transition: fill .3s ease;
|
||||
fill: #ffc700;
|
||||
}
|
||||
|
||||
.svg-icon.svg-icon-success svg [fill]:not(.permanent):not(g) {
|
||||
transition: fill .3s ease;
|
||||
fill: #50cd89;
|
||||
}
|
||||
|
||||
.svg-icon.svg-icon-danger svg [fill]:not(.permanent):not(g) {
|
||||
transition: fill .3s ease;
|
||||
fill: #f1416c;
|
||||
}
|
||||
.svg-icon.svg-icon-general svg [fill]:not(.permanent):not(g) {
|
||||
transition: fill .3s ease;
|
||||
fill: #7239ea;
|
||||
}
|
||||
.svg-icon.svg-icon-progress svg [fill]:not(.permanent):not(g) {
|
||||
transition: fill .3s ease;
|
||||
fill: #ff9800;
|
||||
}
|
||||
|
||||
.bg-light-info {
|
||||
background-color: #f1faff !important;
|
||||
}
|
||||
|
||||
.bg-light-success {
|
||||
background-color: #e8fff3 !important;
|
||||
}
|
||||
|
||||
.bg-light-warning {
|
||||
background-color: #fff8dd !important;
|
||||
}
|
||||
|
||||
.bg-light-danger {
|
||||
background-color: #fff5f8 !important;
|
||||
}
|
||||
.bg-light-progress {
|
||||
background-color: #fff0ce !important;
|
||||
}
|
||||
|
||||
.bg-light-ship {
|
||||
background-color: #f8f5ff!important;
|
||||
}
|
||||
.text-end {
|
||||
text-align: right !important;
|
||||
}
|
||||
|
||||
.text-dark {
|
||||
color: #181c32 !important;
|
||||
}
|
||||
|
||||
.fw-bolder {
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: #a1a5b7 !important;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.btn.btn-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.btn-sm, .btn-group-sm > .btn {
|
||||
padding: 0.25rem 0.5rem;
|
||||
font-size: 0.94791667rem;
|
||||
line-height: 1.5;
|
||||
border-radius: 0.2rem;
|
||||
background-color: #f5f8fa;
|
||||
}
|
||||
|
||||
.svg-icon.svg-icon-3 svg {
|
||||
height: 2rem !important;
|
||||
width: 2rem !important;
|
||||
padding: 0.35rem;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.svg-icon svg [fill]:not(.permanent):not(g) {
|
||||
transition: fill .3s ease;
|
||||
fill: #a1a5b7;
|
||||
|
||||
&:hover{
|
||||
fill: #009ef7;
|
||||
}
|
||||
}
|
||||
.svg-icon svg:hover [fill]:not(.permanent):not(g) {
|
||||
transition: fill .3s ease;
|
||||
fill: #009ef7;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.5em 0.85em;
|
||||
font-size: .85rem;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: baseline;
|
||||
border-radius: 0.475rem;
|
||||
border: none !important;
|
||||
}
|
||||
.badge-light-success {
|
||||
color: #50cd89;
|
||||
background-color: #e8fff3;
|
||||
}
|
||||
.badge-light-danger {
|
||||
color: #f1416c;
|
||||
background-color: #fff5f8;
|
||||
}
|
||||
.badge-light-info {
|
||||
color: #009ef7;
|
||||
background-color: #f1faff;
|
||||
}
|
||||
.badge-light-warning {
|
||||
color: #ffc700;
|
||||
background-color: #fff8dd;
|
||||
}
|
||||
.badge-light-primary {
|
||||
color: #7239ea;
|
||||
background-color: #f8f5ff;
|
||||
}
|
||||
.fw-bolder-7 {
|
||||
font-weight: 700!important;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_filter input:focus-visible{
|
||||
outline: none !important;
|
||||
}
|
||||
div.dataTables_wrapper div.dataTables_filter input{
|
||||
border: 1px solid gray !important;
|
||||
}
|
||||
.paginate_button{
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 122.88 100.89" style="enable-background:new 0 0 122.88 100.89" xml:space="preserve"><style type="text/css">.st0{fill-rule:evenodd;clip-rule:evenodd;}</style><g><path class="st0" d="M115.39,56.45l-0.07,2.6L90.3,66.32l-1.46-3.2c-0.81-1.66-4.09-0.71-3.37,1.76c1.04,3.54,2.64,6.28,4.16,9.07 c8.37,15.42,37.85,10.55,29.51-13.36l-0.07-4.54c2.24-0.97,3.81-3.2,3.81-5.8c0-3.49-2.83-6.32-6.32-6.32c-0.08,0-0.16,0-0.24,0 l2.73-1.16l-12.2-31.65C103.06-0.66,99-2.21,92.42,2.41L57.85,35.36l-0.84-0.84h-7.55c-2.3,0-4.18,1.88-4.18,4.18v15.97H33.74V53.9 c0-1.5-1.23-2.73-2.73-2.73H15.74c-1.5,0-2.73,1.23-2.73,2.73v0.77H8.79c-2.86,0-5.2,2.34-5.2,5.2v6.49c0,2.87,2.35,5.21,5.21,5.21 h55.25c2.87,0,5.21-2.35,5.21-5.21v-8.22v-3.47v-7.88l-1.84-1.85L95.39,15.4l14.18,31.39l2.62-1.11c-1.2,1.15-1.94,2.77-1.94,4.56 C110.24,53.33,112.46,55.9,115.39,56.45L115.39,56.45z M13.59,73.72h45.48c7.47,0,13.59,6.11,13.59,13.59l0,0 c0,7.47-6.11,13.59-13.59,13.59H13.59C6.11,100.89,0,94.78,0,87.3l0,0C0,79.83,6.11,73.72,13.59,73.72L13.59,73.72z M17.45,86.08 c0.16,0,0.28,0.55,0.28,1.23s-0.13,1.23-0.28,1.23h-1.09v1.09c0,0.16-0.55,0.28-1.23,0.28c-0.68,0-1.23-0.13-1.23-0.28v-1.09h-1.09 c-0.16,0-0.28-0.55-0.28-1.23s0.13-1.23,0.28-1.23h1.09v-1.09c0-0.16,0.55-0.28,1.23-0.28c0.68,0,1.23,0.13,1.23,0.28v1.09H17.45 L17.45,86.08z M56.42,84.98c0-0.16,0.55-0.28,1.23-0.28s1.23,0.13,1.23,0.28v1.09h1.09c0.16,0,0.28,0.55,0.28,1.23 s-0.13,1.23-0.28,1.23h-1.09v1.09c0,0.16-0.55,0.28-1.23,0.28s-1.23-0.13-1.23-0.28v-1.09h-1.09c-0.16,0-0.28-0.55-0.28-1.23 s0.13-1.23,0.28-1.23h1.09V84.98L56.42,84.98z M57.65,77.36c5.49,0,9.94,4.45,9.94,9.94s-4.45,9.94-9.94,9.94 c-5.49,0-9.94-4.45-9.94-9.94S52.16,77.36,57.65,77.36L57.65,77.36z M15.13,77.36c5.49,0,9.94,4.45,9.94,9.94s-4.45,9.94-9.94,9.94 c-5.49,0-9.94-4.45-9.94-9.94S9.64,77.36,15.13,77.36L15.13,77.36z M97.01,5.3c1.93,0,3.5,1.57,3.5,3.5c0,1.93-1.57,3.5-3.5,3.5 c-1.93,0-3.5-1.57-3.5-3.5C93.51,6.87,95.07,5.3,97.01,5.3L97.01,5.3z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 122.88 83.03" style="enable-background:new 0 0 122.88 83.03" xml:space="preserve"><style type="text/css">.st0{fill-rule:evenodd;clip-rule:evenodd;}</style><g><path class="st0" d="M0,83.03h23.34V54.25c0-0.19,0.03-0.38,0.08-0.56C4,56.45,4.96,65.41,0.03,83.01L0,83.03L0,83.03z M65.53,83.03h0.57h14.4v-0.03h2.92v0.01l0,0h21.54V64.55c0-0.22,0.05-0.45,0.15-0.64L94.2,63.99l-10.44-0.07 c-2.74-5.46-7.27-8.75-17.73-10.24c0.05,0.19,0.08,0.38,0.08,0.56v26.71c-0.17,0.67-0.36,1.35-0.56,2.06L65.53,83.03L65.53,83.03z M84.51,45.71v2.32l0.79,1.08c0.12,0.17,0.19,0.36,0.19,0.55c0.29,4.04,1.36,6.56,2.98,8.12c1.57,1.53,3.72,2.24,6.16,2.63 c2.65-0.43,4.71-1.55,6.19-3.27c1.53-1.81,2.46-4.32,2.75-7.5c0.02-0.15,0.07-0.31,0.14-0.45l0.71-1.17l0.02-2.41h2.08l-0.02,2.63 c0.02,0.21-0.03,0.41-0.15,0.62l-0.74,1.2c-0.36,3.49-1.45,6.31-3.22,8.41c-1.84,2.15-4.37,3.51-7.59,4.01 c-0.1,0.02-0.22,0.02-0.34,0c-2.89-0.45-5.49-1.29-7.47-3.23c-1.93-1.89-3.24-4.75-3.58-9.19l-0.76-1.05 c-0.17-0.19-0.26-0.43-0.26-0.69V45.7h2.1L84.51,45.71L84.51,45.71z M94.08,29.78c1,0,1.98,0.1,2.91,0.29l-0.17,8.38L99.86,31 c4.28,1.91,7.47,5.88,8.26,10.65h1.65v1.96h-1.46v0.03H79.83v-0.03h-1.19v-1.96h1.38c0.83-4.92,4.18-9,8.69-10.82l2.67,7.5 L91.65,30c0.79-0.14,1.58-0.21,2.41-0.21L94.08,29.78L94.08,29.78z M92.61,76.32h3.18v3.18h-3.18V76.32L92.61,76.32z M92.61,68.46 h3.18v3.18h-3.18V68.46L92.61,68.46z M107.91,83.02h14.97c-3.18-11.29-2.55-17.03-15-18.81c0.03,0.12,0.05,0.24,0.05,0.36v18.46 L107.91,83.02L107.91,83.02z M29.59,24.84v3.62l1.23,1.69c0.19,0.27,0.3,0.56,0.3,0.86c0.46,6.3,2.12,10.22,4.64,12.66 c2.44,2.39,5.79,3.49,9.6,4.1c4.13-0.67,7.35-2.41,9.66-5.1c2.39-2.82,3.84-6.73,4.29-11.7c0.03-0.24,0.11-0.48,0.21-0.7l1.1-1.82 l0.03-3.76h3.25l-0.03,4.1c0.03,0.32-0.05,0.64-0.24,0.97l-1.15,1.88c-0.56,5.45-2.25,9.85-5.02,13.12 c-2.87,3.35-6.81,5.47-11.83,6.25c-0.16,0.03-0.35,0.03-0.54,0c-4.51-0.7-8.56-2.01-11.64-5.04c-3-2.95-5.04-7.4-5.58-14.33 l-1.18-1.64c-0.27-0.3-0.4-0.67-0.4-1.07v-4.13h3.27L29.59,24.84L29.59,24.84z M44.51,0c1.56,0,3.09,0.16,4.53,0.46l-0.27,13.07 L53.52,1.9c6.68,2.98,11.64,9.18,12.88,16.61h2.58v3.06h-2.28v0.05h-44.4v-0.05h-1.85v-3.06h2.15c1.29-7.67,6.52-14.03,13.55-16.87 l4.16,11.7l0.43-12.98c1.23-0.21,2.47-0.32,3.76-0.32L44.51,0L44.51,0z M42.23,72.57h4.96v4.96h-4.96V72.57L42.23,72.57z M42.23,60.31h4.96v4.96h-4.96V60.31L42.23,60.31z M27.9,83.01h33.59V54.22c0-0.35,0.08-0.7,0.24-0.99L44.7,53.33l-17.04-0.11 c0.16,0.3,0.24,0.64,0.24,0.99V83.01L27.9,83.01L27.9,83.01z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 6.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 109.77"><defs><style>.cls-1{fill-rule:evenodd;}</style></defs><title>toolbox-repairing</title><path class="cls-1" d="M26.13,8.81A17.18,17.18,0,0,0,13.24,4.72c14,11.42-2.58,26.17-11.79,9-3.78,8.49.16,16.31,8,20.33,3.7,1.9,5.65,3,7,4.53a11.73,11.73,0,0,1,1.86,2.92l3.49,8.26H7.11A2.32,2.32,0,0,0,4.8,52.1V93a16.87,16.87,0,0,0,16.82,16.82H96.79A16.87,16.87,0,0,0,113.61,93V52.1a2.32,2.32,0,0,0-2.32-2.32H88.89l13.07-22-9.37-5.4L76.21,49.78H65.79l0-2.86a.57.57,0,0,0-.12-.35c-.5-.6-.88-1-1.2-1.41h0c-.74-.86-1.12-1.29-1.12-1.57s.36-.75,1.09-1.65c.3-.37.66-.81,1.08-1.36a.57.57,0,0,0,.13-.36V37.05a.55.55,0,0,0-.55-.55l-4.85,0,.09-22.09,2.92-5.11a2.85,2.85,0,0,0,.46-1.55l0-5A2.83,2.83,0,0,0,60.82,0L54,0a2.83,2.83,0,0,0-2.79,2.87l.08,5.54A2.79,2.79,0,0,0,51.81,10l2.73,3.91-.09,22.63-5.74,0a.55.55,0,0,0-.55.56v3.1a.54.54,0,0,0,.14.36c.47.52.87,1,1.22,1.32,1,1.07,1.48,1.59,1.49,2s-.41.86-1.19,1.85c-.39.49-.87,1.1-1.44,1.86a.5.5,0,0,0-.12.35v1.86H35.19l-5.5-12.91a12.84,12.84,0,0,1-1.11-3.79,14.19,14.19,0,0,1,.28-3.75c1.33-7.78,4-14.25-2.73-20.52ZM9.43,63.94H109V54.41H9.43v9.53ZM109,68.57H95.13v7.79A3.17,3.17,0,0,1,92,79.53H80.86a3.18,3.18,0,0,1-3.17-3.17V68.57H41.82v7.79a3.18,3.18,0,0,1-3.17,3.17H27.55a3.18,3.18,0,0,1-3.18-3.17V68.57H9.43V93a12.24,12.24,0,0,0,12.19,12.2H96.79A12.24,12.24,0,0,0,109,93V68.57ZM75.29,18.83a15.81,15.81,0,0,1,5.3-2.57,10.13,10.13,0,0,1,7.87.85l20.38,11.75L107.61,31l7.75,4.51,7.52-13L115.14,18l-1.4,2.36L93.48,8.68a10.31,10.31,0,0,0-8-1.38c-4.24,1.14-7.65,5-10.23,11.53Z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,255 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { Component, useRef, onMounted, useState } from "@odoo/owl";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { rpc } from "@web/core/network/rpc";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
export class ConstructionDashboard extends Component {
|
||||
// static template = "ConstructionDashboard";
|
||||
setup() {
|
||||
this.rpc = rpc;
|
||||
this.action = useService("action");
|
||||
this.orm = useService("orm");
|
||||
// reactive state
|
||||
this.state = useState({
|
||||
selectedSite: "all_site",
|
||||
selectedProject: "all_project",
|
||||
sites: [],
|
||||
projects: [],
|
||||
stats: {},
|
||||
});
|
||||
|
||||
// Chart containers
|
||||
this.refs = {
|
||||
siteStateChart: useRef("siteStateChart"),
|
||||
mrqStateChart: useRef("mrqStateChart"),
|
||||
internalTransferChart: useRef("internalTransferChart"),
|
||||
constructionTimeline: useRef("constructionTimeline"),
|
||||
projectTimeline: useRef("projectTimeline"),
|
||||
projectStatusChart: useRef("projectStatusChart"),
|
||||
jobOrderPoChart: useRef("jobOrderPoChart"),
|
||||
};
|
||||
|
||||
// onMounted(() => this.loadInitialData());
|
||||
onMounted(() => {
|
||||
this.loadInitialData();
|
||||
});
|
||||
}
|
||||
|
||||
async loadInitialData() {
|
||||
// const result = await this.rpc({
|
||||
// model: "tk.construction.dashboard",
|
||||
// method: "get_construction_state",
|
||||
// args: [false, false],
|
||||
// });
|
||||
const result = await this.orm.call("tk.construction.dashboard", "get_construction_state", [false, false]);
|
||||
console.log(result,'dasdsa');
|
||||
|
||||
this.state.stats = result;
|
||||
this.state.sites = Object.entries(result.con_sites || {}).map(([id, name]) => ({ id, name }));
|
||||
this.renderCharts(result);
|
||||
|
||||
}
|
||||
|
||||
async onSiteChange(ev) {
|
||||
this.state.selectedSite = ev.target.value;
|
||||
this.state.selectedProject = "all_project";
|
||||
const data = await this.orm.call("tk.construction.dashboard", "get_project_list", [this.state.selectedSite]);
|
||||
// const data = await this.rpc({
|
||||
// model: "tk.construction.dashboard",
|
||||
// method: "get_project_list",
|
||||
// args: [this.state.selectedSite],
|
||||
// });
|
||||
|
||||
this.state.projects = Object.entries(data || {}).map(([id, name]) => ({ id, name }));
|
||||
await this.updateStats();
|
||||
}
|
||||
|
||||
async onProjectChange(ev) {
|
||||
this.state.selectedProject = ev.target.value;
|
||||
await this.updateStats();
|
||||
}
|
||||
|
||||
async updateStats() {
|
||||
// const data = await this.rpc({
|
||||
// model: "tk.construction.dashboard",
|
||||
// method: "get_construction_state",
|
||||
// args: [this.state.selectedSite, this.state.selectedProject],
|
||||
// });
|
||||
const data = await this.orm.call("tk.construction.dashboard", "get_construction_state", [this.state.selectedSite, this.state.selectedProject]);
|
||||
|
||||
this.state.stats = data;
|
||||
this.renderCharts(data);
|
||||
console.log(this.state.stats,'dasdsa');
|
||||
}
|
||||
|
||||
openAction(name, resModel, domain = []) {
|
||||
this.action.doAction({
|
||||
name: _t(name),
|
||||
type: "ir.actions.act_window",
|
||||
res_model: resModel,
|
||||
domain,
|
||||
views: [[false, "list"], [false, "form"]],
|
||||
target: "current",
|
||||
});
|
||||
}
|
||||
|
||||
// 👇 Public methods that are bound in template
|
||||
viewTotalSite = () => this.openAction("Project", "tk.construction.site");
|
||||
|
||||
async viewTotalProject() {
|
||||
const domain = await this.getProjectDomain(0);
|
||||
this.openAction("Projects", "tk.construction.project", domain);
|
||||
}
|
||||
|
||||
async viewTotalMrq() {
|
||||
const domain = await this.getProjectDomain(1);
|
||||
this.openAction("Material Requisition", "material.requisition", domain);
|
||||
}
|
||||
|
||||
async viewTotalJobSheet() {
|
||||
const domain = await this.getProjectDomain(1);
|
||||
this.openAction("Job Costing", "job.costing", domain);
|
||||
}
|
||||
|
||||
async viewTotalJobOrder() {
|
||||
const domain = await this.getProjectDomain(1);
|
||||
this.openAction("Work Order", "job.order", domain);
|
||||
}
|
||||
|
||||
async viewProjectPlanning() {
|
||||
const domain = await this.getProjectDomain(0);
|
||||
domain.push(["stage", "=", "Planning"]);
|
||||
this.openAction("Project Planning", "tk.construction.project", domain);
|
||||
}
|
||||
|
||||
async viewProjectProcurement() {
|
||||
const domain = await this.getProjectDomain(0);
|
||||
domain.push(["stage", "=", "Procurement"]);
|
||||
this.openAction("Project Procurement", "tk.construction.project", domain);
|
||||
}
|
||||
|
||||
async viewProjectConstruction() {
|
||||
const domain = await this.getProjectDomain(0);
|
||||
domain.push(["stage", "=", "Construction"]);
|
||||
this.openAction("Project Construction", "tk.construction.project", domain);
|
||||
}
|
||||
|
||||
async viewProjectHandover() {
|
||||
const domain = await this.getProjectDomain(0);
|
||||
domain.push(["stage", "=", "Handover"]);
|
||||
this.openAction("Project Handover", "tk.construction.project", domain);
|
||||
}
|
||||
|
||||
async getProjectDomain(index = 0) {
|
||||
// const res = await this.rpc({
|
||||
// model: "tk.construction.dashboard",
|
||||
// method: "get_construction_project_domain",
|
||||
// args: [this.state.selectedSite, this.state.selectedProject],
|
||||
// });
|
||||
const res = await this.orm.call("tk.construction.dashboard", "get_construction_project_domain", [this.state.selectedSite, this.state.selectedProject]);
|
||||
|
||||
return res && res.length ? res[index] : [];
|
||||
}
|
||||
|
||||
renderCharts(data) {
|
||||
if (!window.ApexCharts) return;
|
||||
|
||||
// Site State
|
||||
this.renderGraph(this.refs.siteStateChart.el, {
|
||||
chart: { type: "donut", height: 410 },
|
||||
series: data.site_state?.[1] || [],
|
||||
labels: data.site_state?.[0] || [],
|
||||
legend: { position: "bottom" },
|
||||
dataLabels: { enabled: false },
|
||||
});
|
||||
|
||||
// Material Requisition
|
||||
this.renderGraph(this.refs.mrqStateChart.el, {
|
||||
chart: { type: "pie", height: 410 },
|
||||
series: data.mrq_state?.[1] || [],
|
||||
labels: data.mrq_state?.[0] || [],
|
||||
legend: { position: "bottom" },
|
||||
dataLabels: { enabled: false },
|
||||
});
|
||||
|
||||
// Internal Transfer
|
||||
this.renderGraph(this.refs.internalTransferChart.el, {
|
||||
chart: { type: "donut", height: 410 },
|
||||
series: data.internal_state?.[1] || [],
|
||||
labels: data.internal_state?.[0] || [],
|
||||
legend: { position: "bottom" },
|
||||
dataLabels: { enabled: false },
|
||||
});
|
||||
|
||||
// Project Timeline
|
||||
this.renderTimeline(this.refs.projectTimeline.el, data.project_timeline || [], "Project");
|
||||
|
||||
// Site Timeline
|
||||
this.renderTimeline(this.refs.constructionTimeline.el, data.site_timeline || [], "Timeline");
|
||||
|
||||
// Project Status
|
||||
this.renderGraph(this.refs.projectStatusChart.el, {
|
||||
chart: { type: "donut", height: 410 },
|
||||
series: data.project_status?.[1] || [],
|
||||
labels: data.project_status?.[0] || [],
|
||||
legend: { position: "bottom" },
|
||||
dataLabels: { enabled: false },
|
||||
});
|
||||
|
||||
// Job Order PO
|
||||
this.renderGraph(this.refs.jobOrderPoChart.el, {
|
||||
chart: { type: "line", height: 350, zoom: { enabled: true } },
|
||||
series: [
|
||||
{ name: "Material PO", data: data.job_order_po?.[1] || [] },
|
||||
{ name: "Equipment PO", data: data.job_order_po?.[2] || [] },
|
||||
{ name: "Labour PO", data: data.job_order_po?.[3] || [] },
|
||||
{ name: "Overhead PO", data: data.job_order_po?.[4] || [] },
|
||||
],
|
||||
xaxis: { categories: data.job_order_po?.[0] || [] },
|
||||
dataLabels: { enabled: false },
|
||||
legend: {
|
||||
tooltipHoverFormatter: function (val, opts) {
|
||||
return `${val} - ${opts.w.globals.series[opts.seriesIndex][opts.dataPointIndex]}`;
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
renderGraph(el, options) {
|
||||
if (!el) return;
|
||||
el.innerHTML = "";
|
||||
const chart = new ApexCharts(el, options);
|
||||
chart.render();
|
||||
}
|
||||
|
||||
renderTimeline(el, timelineData, label = "Timeline") {
|
||||
const series = (timelineData || []).map((entry) => ({
|
||||
name: entry.name,
|
||||
data: [
|
||||
{
|
||||
x: label,
|
||||
y: [new Date(entry.start_date).getTime(), new Date(entry.end_date).getTime()],
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
this.renderGraph(el, {
|
||||
chart: { height: 350, type: "rangeBar" },
|
||||
plotOptions: { bar: { horizontal: true } },
|
||||
series,
|
||||
xaxis: { type: "datetime" },
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter: function (val) {
|
||||
const diff = (val[1] - val[0]) / (1000 * 60 * 60 * 24);
|
||||
return `${diff} ${diff > 1 ? "days" : "day"}`;
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
ConstructionDashboard.template = "tk_construction_management.ConstructionDashboard";
|
||||
registry.category("actions").add("construction_dashboard", ConstructionDashboard);
|
||||
31361
addons/tk_construction_management/static/src/js/lib/apexcharts.js
Normal file
164
addons/tk_construction_management/static/src/xml/template.xml
Normal file
@@ -0,0 +1,164 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="tk_construction_management.ConstructionDashboard" owl="1">
|
||||
<section>
|
||||
<div class="container construction_dashboard">
|
||||
<div class="row">
|
||||
<div class="col-md-12 mb-4 mt32 mb16">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-5">
|
||||
<h2 class="section-header">Construction</h2>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-7">
|
||||
<form class="form-group d-flex just-end">
|
||||
<select class="form-control tk-form-control col-md-4 mr8"
|
||||
t-on-change="onSiteChange">
|
||||
<option value="all_site">All Projects</option>
|
||||
<t t-foreach="state.sites" t-as="site" t-key="site.id">
|
||||
<option t-att-value="site.id"
|
||||
t-att-selected="site.id === state.selectedSite">
|
||||
<t t-esc="site.name"/>
|
||||
</option>
|
||||
</t>
|
||||
</select>
|
||||
|
||||
<select class="form-control tk-form-control col-md-4 mr8"
|
||||
t-on-change="onProjectChange">
|
||||
<option value="all_project">All Sub Projects</option>
|
||||
<t t-foreach="state.projects" t-as="project" t-key="project.id">
|
||||
<option t-att-value="project.id"
|
||||
t-att-selected="project.id === state.selectedProject">
|
||||
<t t-esc="project.name"/>
|
||||
</option>
|
||||
</t>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- STATS CARDS -->
|
||||
<div class="row">
|
||||
<t t-set="cards" t-value="[
|
||||
{ id: 'total_site', class: 'total-site', label: 'Project', stat: state.stats.total_site, onClick: viewTotalSite },
|
||||
{ id: 'total_project', class: 'total-project', label: 'Sub Project', stat: state.stats.total_project, onClick: viewTotalProject },
|
||||
{ id: 'total_mrq', class: 'total-mrq', label: 'Material Requisition', stat: state.stats.total_mrq, onClick: viewTotalMrq },
|
||||
{ id: 'job_sheet_count', class: 'job-sheet', label: 'Project Phase(WBS)', stat: state.stats.job_sheet_count, onClick: viewTotalJobSheet },
|
||||
{ id: 'job_order_count', class: 'job-order', label: 'Work Order', stat: state.stats.job_order_count, onClick: viewTotalJobOrder }
|
||||
]"/>
|
||||
<t t-foreach="cards" t-as="card" t-key="card.id">
|
||||
<div class="col-md-4 col-lg-4 col-sm-6" t-attf-class="#{card.class}" t-on-click="card.onClick">
|
||||
<div class="card card-xl-stretch mb-xl-8">
|
||||
<div class="card-body p-0">
|
||||
<div class="d-flex flex-stack card-p flex-grow-1">
|
||||
<span class="symbol symbol-50px me-2">
|
||||
<span class="symbol-label bg-light-info">
|
||||
<span class="svg-icon svg-icon-info svg-icon-2x">
|
||||
<!-- SVG Icon can be generalized or dynamic if needed -->
|
||||
<i class="fa fa-cube"/>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<div class="d-flex flex-column text-end">
|
||||
<span class="text-dark fw-bolder fs-2" t-att-id="card.id">
|
||||
<t t-esc="card.stat || 0"/>
|
||||
</span>
|
||||
<span class="text-muted fw-bold mt-1">
|
||||
<t t-esc="card.label"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<!-- PROJECT STAGES -->
|
||||
<div class="row mt32">
|
||||
<t t-set="stages" t-value="[
|
||||
{ id: 'project_planning', label: 'Planning', class: 'project-planning', onClick: viewProjectPlanning },
|
||||
{ id: 'project_procurement', label: 'Procurement', class: 'project-procurement', onClick: viewProjectProcurement },
|
||||
{ id: 'project_construction', label: 'Construction', class: 'project-construction', onClick: viewProjectConstruction },
|
||||
{ id: 'project_handover', label: 'Handover', class: 'project-handover', onClick: viewProjectHandover }
|
||||
]"/>
|
||||
<t t-foreach="stages" t-as="stage" t-key="stage.id">
|
||||
<div class="col-md-4 col-lg-4 col-sm-6" t-attf-class="#{stage.class}"
|
||||
t-on-click="stage.onClick">
|
||||
<div class="card card-xl-stretch mb-xl-8">
|
||||
<div class="card-body p-0">
|
||||
<div class="d-flex flex-stack card-p flex-grow-1">
|
||||
<span class="symbol symbol-50px me-2">
|
||||
<span class="symbol-label bg-light-warning">
|
||||
<i class="fa fa-cogs"/>
|
||||
</span>
|
||||
</span>
|
||||
<div class="d-flex flex-column text-end">
|
||||
<span class="text-dark fw-bolder fs-2" t-att-id="stage.id">
|
||||
<t t-esc="state.stats.project_status?.[1]?.[stage.id] === 1 ? 1 : 0"/>
|
||||
</span>
|
||||
<span class="text-muted fw-bold mt-1">
|
||||
<t t-esc="stage.label"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<!-- CHARTS -->
|
||||
<div class="mt32 mb16">
|
||||
<h2>Construction Statistics</h2>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="box mt16 mb16">
|
||||
<h5 class="mb16">Project Timeline</h5>
|
||||
<div t-ref="constructionTimeline" style="min-height: 350px"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="box mt16 mb16">
|
||||
<h5 class="mb16">Site State</h5>
|
||||
<div t-ref="siteStateChart" style="min-height: 410px"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="box mt16 mb16">
|
||||
<h5 class="mb16">Sub Project Status</h5>
|
||||
<div t-ref="projectStatusChart" style="min-height: 410px"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="box mt16 mb16">
|
||||
<h5 class="mb16">Sub Project Timeline</h5>
|
||||
<div t-ref="projectTimeline" style="min-height: 350px"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="box mt16 mb16">
|
||||
<h5 class="mb16">Material Requisition</h5>
|
||||
<div t-ref="mrqStateChart" style="min-height: 410px"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="box mt16 mb16">
|
||||
<h5 class="mb16">Internal Transfer</h5>
|
||||
<div t-ref="internalTransferChart" style="min-height: 410px"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="box mt16 mb16">
|
||||
<h5 class="mb16">Job Order Purchase Order</h5>
|
||||
<div t-ref="jobOrderPoChart" style="min-height: 350px"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</t>
|
||||
</templates>
|
||||