Merge branch 'develop' of https://bitbucket.org/ncarminati/cms_thermo_active into feature/recipe

This commit is contained in:
Samuele Locatelli
2020-07-14 19:26:07 +02:00
14 changed files with 339 additions and 11 deletions
@@ -293,6 +293,7 @@
height: 100%;
display: flex;
flex-flow: column;
max-height: 836px;
.recipe {
@@ -301,6 +302,7 @@
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
&::before {
content: "";
@@ -361,11 +363,8 @@
font-size: 120px;
font-weight: 300;
}
}
}
}
.pieces {
@@ -377,4 +376,86 @@
}
}
}
}
.history-item {
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: flex-end;
.body {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 25px;
width: 630px;
align-items: center;
height: 84px;
background-color: #e8e8e8;
border-bottom: 1px solid #4b4b4b;
}
.subitems {
width: 630px;
.row {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
height: 60px;
margin-left: 151px;
width: calc(100% - 151px - 25px);
background-color: #e8e8e8;
border-bottom: 1px solid #4b4b4b;
}
}
label {
text-align: right;
font-size: 54px;
font-weight: 500;
}
.col {
display: flex;
flex-flow: column;
align-items: center;
justify-content: space-evenly;
height: 100%;
small {
font-size: 12px;
font-weight: 500;
text-transform: uppercase;
text-align: center;
}
span {
font-size: 25px;
font-weight: 500px;
}
i {
font-size: 32px;
cursor: pointer;
}
}
button.trash {
border-radius: 25px;
width: 50px;
height: 50px;
border: 2px solid #4b4b4b;
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.5);
}
}
.history-list {
height: 100%;
overflow-y: scroll;
margin-right: 8px;
margin-top: 2px;
;
}
@@ -4367,6 +4367,7 @@ article .box .body {
height: 100%;
display: flex;
flex-flow: column;
max-height: 836px;
}
.dashboard .third_col .recipe {
height: 97px;
@@ -4374,6 +4375,7 @@ article .box .body {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.dashboard .third_col .recipe::before {
content: "";
@@ -4433,6 +4435,72 @@ article .box .body {
margin-top: 10px;
height: calc(100% - 78px);
}
.history-item {
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: flex-end;
}
.history-item .body {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 25px;
width: 630px;
align-items: center;
height: 84px;
background-color: #e8e8e8;
border-bottom: 1px solid #4b4b4b;
}
.history-item .subitems {
width: 630px;
}
.history-item .subitems .row {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
height: 60px;
margin-left: 151px;
width: calc(100% - 151px - 25px);
background-color: #e8e8e8;
border-bottom: 1px solid #4b4b4b;
}
.history-item label {
text-align: right;
font-size: 54px;
font-weight: 500;
}
.history-item .col {
display: flex;
flex-flow: column;
align-items: center;
justify-content: space-evenly;
height: 100%;
}
.history-item .col small {
font-size: 12px;
font-weight: 500;
text-transform: uppercase;
text-align: center;
}
.history-item .col span {
font-size: 25px;
font-weight: 500px;
}
.history-item .col i {
font-size: 32px;
cursor: pointer;
}
.history-item button.trash {
border-radius: 25px;
width: 50px;
height: 50px;
border: 2px solid #4b4b4b;
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.5);
}
.history-list {
height: 100%;
overflow-y: scroll;
margin-right: 8px;
margin-top: 2px;
}
.warmers {
position: relative;
}
@@ -4,13 +4,15 @@ import Vue from "vue";
import keyboard from "./keyboard.vue";
import clock from "./clock.vue";
import combo from "./combo.vue"
import loadMore from "./loadMore/loadMore.vue";
export default {
numeric,
slider,
keyboard,
clock,
combo
combo,
loadMore
}
Vue.directive('focusOn', {
@@ -0,0 +1,33 @@
import Vue from 'vue';
import { Prop, Component } from 'vue-property-decorator';
@Component({})
export default class loadMoreItems extends Vue {
observer = new IntersectionObserver(this.whenObservedChange, { threshold: 0.5 })
@Prop({ default: false })
loading: boolean;
visible: boolean = false;
mounted() {
this.observer.observe(this.$el);
}
beforeDestroy() {
this.observer.disconnect();
}
whenObservedChange(entries: IntersectionObserverEntry[]) {
for (const entry of entries) {
if (entry.intersectionRatio > 0) {
this.$emit("onview");
this.visible = false;
}
else
this.visible = true;
}
}
}
@@ -0,0 +1,14 @@
<template>
<div class="loadmore">
<i class="fa fa-spinner fa-spin" v-if="loading && visible"></i>
</div>
</template>
<style>
.loadmore {
display: flex;
align-items: center;
justify-content: center;
min-height: 50px;
}
</style>
<script src="./loadMore.ts" lang="ts"></script>
@@ -0,0 +1,12 @@
import Component from "vue-class-component";
import Vue from "vue";
import { Prop } from "vue-property-decorator";
@Component({})
export default class Item extends Vue {
@Prop()
value: Prod.IProd;
showDetails: boolean = false;
}
@@ -0,0 +1,69 @@
<template>
<div class="history-item">
<div class="body">
<label>{{value.numDone}}</label>
<div class="col">
<small>{{'history-item_warmup' | localize("tempo riscaldo")}}</small>
<span>{{value.timeWarm / 60 | round(0)}}'{{value.timeWarm % 60 | round(0)}}''</span>
</div>
<div class="col">
<small>{{'history-item_vacuum' | localize("vuoto")}}</small>
<span>{{value.vacuumReadVal | round(1)}} bar</span>
</div>
<div class="col">
<small>{{'history-item_cycletime' | localize("tempo ciclo netto")}}</small>
<span>{{value.timeCycleNet / 60 | round(0)}}'{{value.timeCycleNet % 60 | round(0)}}''</span>
</div>
<div class="col">
<i class="fa fa-caret-left" @click="showDetails = !showDetails" v-if="!showDetails"></i>
<i class="fa fa-caret-down" @click="showDetails = !showDetails" v-if="showDetails"></i>
</div>
</div>
<div class="subitems" v-if="showDetails">
<div class="row">
<div class="col">
<button class="trash">
<i class="fa fa-trash-o" aria-hidden="true"></i>
</button>
</div>
<div class="col">
<small>{{'history-item_venttime' | localize("tempo ventilazione")}}</small>
<span>{{value.timeVent / 60 | round(0)}}'{{value.timeVent % 60 | round(0)}}''</span>
</div>
<div class="col">
<small>{{'history-item_cycletimegross' | localize("tempo ciclo lordo")}}</small>
<span>{{value.timeCycleGross / 60 | round(0)}}'{{value.timeCycleGross % 60 | round(0)}}''</span>
</div>
</div>
<div class="row">
<div class="col">
<small>{{'history-item_tempstampo' | localize("Temperatura stampo")}}</small>
<span>{{value.moldTemp | round(0)}}°C</span>
</div>
<div class="col">
<small>{{'history-item_materialTempEndWarm' | localize("T. Materiale fine riscaldo")}}</small>
<span>{{value.materialTempEndWarm | round(0)}}°C</span>
</div>
<div class="col">
<small>{{'history-item_materialTempEndVent' | localize("T. Materiale fine ventilazione")}}</small>
<span>{{value.materialTempEndVent | round(0)}}°C</span>
</div>
</div>
<div class="row">
<div class="col">
<small>{{'history-item_vacuumtime' | localize("tempo vuoto")}}</small>
<span>{{value.timeVacuum / 60 | round(0)}}'{{value.timeVacuum % 60 | round(0)}}''</span>
</div>
<div class="col">
<small>{{'history-item_mouldEnergyIN' | localize("energia utilizzata in")}}</small>
<span>{{value.mouldEnergyIN | round(1)}}kW</span>
</div>
<div class="col">
<small>{{'history-item_mouldEnergyOUT' | localize("energia utilizzata out")}}</small>
<span>{{value.mouldEnergyOUT | round(1)}}kW</span>
</div>
</div>
</div>
</div>
</template>
<script src="./item.ts" lang="ts"></script>
@@ -1,6 +1,6 @@
import Vue from 'vue';
import Component from 'vue-class-component';
import { Prop } from 'vue-property-decorator';
import { Prop, Watch } from 'vue-property-decorator';
import { messageService } from '@/_base';
import AppRibbon from "@/components/app-ribbon.vue";
import { alarmList } from "@/app_modules/alarms";
@@ -11,6 +11,7 @@ import gauge from "./base-components/gauge.vue";
import { prodService } from '@/services/prodService';
import moment from 'moment';
import stats from "./base-components/stats.vue";
import hitem from "./base-components/item.vue";
@Component({
components: {
@@ -18,7 +19,8 @@ import stats from "./base-components/stats.vue";
archInterface: ArchInterface,
alarmList,
gauge,
stats
stats,
hitem
}
})
export default class Dashboard extends Vue {
@@ -28,6 +30,17 @@ export default class Dashboard extends Vue {
return (this.$store.state as AppModel).prod.panel;
}
get lastItem() {
return (this.$store.state as AppModel).prod.prod;
}
@Watch("lastItem", { deep: true })
async lastitemChanged(n: Prod.IProd, o) {
this.items.splice(0, 0, ...await prodService.History(n.numDone - 1, 1));
}
items: Prod.IProd[] = [];
now = moment();
get elapsed() {
@@ -52,6 +65,17 @@ export default class Dashboard extends Vue {
}
loading = false;
async loadMore() {
if (this.loading) return;
this.loading = true;
let min = Math.min(this.lastItem.numDone, ... this.items.map(i => i.numDone));
this.items.push(...await prodService.History(min - 1));
this.loading = false;
}
getColor(nome, cognome) {
return getColorFromName(nome, cognome);
}
@@ -148,6 +148,13 @@
</div>
<stats class="stats" :width="614" :height="65" :value="panel.tS_TCiclo"></stats>
</div>
<div class="current-item">
<hitem :value="lastItem"></hitem>
</div>
<div class="history-list scrollable">
<hitem :value="item" v-for="item in items" :key="item"></hitem>
<load-more :loading="true" @onview="loadMore"></load-more>
</div>
</div>
</div>
</template>
@@ -157,6 +164,10 @@
grid-column-end: -1;
width: 100%;
}
.current-item {
margin-right: 24px;
}
</style>
<script lang="ts" src="./dashboard.ts"></script>
@@ -18,7 +18,7 @@
</div>
</foreignObject>
<foreignObject :width="delayDuration * ganttOptions.secondSize" height="26" x="0" y="44">
<div class="delay-footer">{{(value.estimatedDelay ) | round(1)}}s</div>
<div class="delay-footer">{{Math.max(value.actualDelay, value.estimatedDelay) | round(1)}}s</div>
</foreignObject>
<line
class="vertical-line"
@@ -34,7 +34,9 @@
<div class="body-header">{{value.label | localize(value.label)}}</div>
</foreignObject>
<foreignObject :width="duration * ganttOptions.secondSize" height="26" x="0" y="44">
<div class="body-footer">{{(value.estimatedDuration ) | round(1)}}s</div>
<div
class="body-footer"
>{{Math.max(value.actualDuration, value.estimatedDuration ) | round(1)}}s</div>
</foreignObject>
<line
v-if="showStatus && recipeValue"
@@ -50,8 +50,9 @@
<time-line
:padding-horizontal="padX "
:zoom-factor="zoomFactor"
:x="ganttOptions.stepDuration * ganttOptions.secondSize - 15"
:position="currentTime * ganttOptions.secondSize"
:speed="1.5"
:x="ganttOptions.stepDuration * ganttOptions.secondSize - 15"
:position="(currentTime) * ganttOptions.secondSize"
:line-height="getRowHeight($refs.section1) + getRowHeight($refs.section2) +getRowHeight($refs.section2)+ ganttOptions.elementPadding*3"
/>
</svg>
@@ -17,4 +17,7 @@ export default class timeline extends Vue {
@Prop({ default: 0 })
position: number;
@Prop({ default: .5 })
speed: number;
}
@@ -1,6 +1,9 @@
<template>
<svg class="timeline">
<g :transform="`translate(${(position * zoomFactor) + paddingHorizontal} 0)`">
<g
:transform="`translate(${(position * zoomFactor) + paddingHorizontal} 0)`"
:style="`transition: transform ${speed}s linear`"
>
<path class="arrow" d="M 0 0 L 30 0 L 15 24 Z" />
<line x1="15" y1="24" x2="15" :y2="lineHeight" />
</g>
@@ -19,5 +19,10 @@ export class ProdService extends baseRestService {
return result;
}
async History(from: number, count: number = 20) {
let result = await this.Get<any>((await this.BASE_URL()) + `history?indexStart=${from}&numRecord=${count}`, true);
return result;
}
}
export const prodService = new ProdService();