aboutsummaryrefslogtreecommitdiffstats
path: root/demo-ui/app/views
diff options
context:
space:
mode:
authorSteven Saunders <steve@llantz9470.cablelabs.com>2015-08-12 08:48:07 -0600
committerSteven Saunders <steve@khiatt8460b.cablelabs.com>2015-08-12 18:21:36 -0600
commite8a4652f70284c414ceafc086669dfd4b935573d (patch)
treeedfa339167fee1863505f7a39b5b3cab431b3eee /demo-ui/app/views
parented73dbf357aff41edcbab401a94e5fbc266d9391 (diff)
Add demo-ui folder. This folder contains HTML/CSS/Javascript code for the VCPE Demo UI. The Demo UI allows you to CRUD CoS instances, and EPL instances, and will also display information about EVCs and UNIs that were created as well
Change-Id: I32eea1121c21e0b451efc057a0c0f30fe5601cd5 Signed-off-by: Steven Saunders <steve@llantz9470.cablelabs.com>
Diffstat (limited to 'demo-ui/app/views')
-rw-r--r--demo-ui/app/views/cos-panel.html171
-rw-r--r--demo-ui/app/views/css/vcpe.css340
-rw-r--r--demo-ui/app/views/epl-panel.html187
-rw-r--r--demo-ui/app/views/less/vcpe.less365
-rw-r--r--demo-ui/app/views/mef-panel.html370
-rw-r--r--demo-ui/app/views/vcpe-portal.html71
6 files changed, 1504 insertions, 0 deletions
diff --git a/demo-ui/app/views/cos-panel.html b/demo-ui/app/views/cos-panel.html
new file mode 100644
index 0000000..682f154
--- /dev/null
+++ b/demo-ui/app/views/cos-panel.html
@@ -0,0 +1,171 @@
+<!--
+
+To Do
+ Change Bandwidth to drop down, with selected levels (10M, 100M, 1G, etc)
+ -->
+
+<div class="primary-lable ">Service Levels</div>
+<div class="cos-list">
+ <div class="list-item choosable"
+ ng-repeat="cos in cosList track by $index"
+
+ ng-class="{'selected-item-idle' : $index === selectedCosIdx &&
+ !cosActionInProgress(),
+ 'selected-item-update' : $index === selectedCosIdx &&
+ cosUpdateInProgress(),
+ 'selected-item-delete' : $index === selectedCosIdx &&
+ cosDelInProgress() }"
+ ng-click="onCosClick($index)">
+ {{ cos.id }}
+ </div>
+</div>
+
+<div class = "action-icon-container">
+
+ <span class="action-icon glyphicon glyphicon-plus"
+ ng-click="onAddCos()"
+ ng-class="{'action' : cosAddInProgress()}">
+ </span>
+
+ <span class="action-icon glyphicon glyphicon-pencil"
+ ng-click="onUpdateCos()"
+ ng-class="{'action' : cosUpdateInProgress()}">
+ </span>
+
+ <span class="action-icon glyphicon glyphicon-minus"
+ ng-click="onDelCos()"
+ ng-class="{'action' : cosDelInProgress()}">
+ </span>
+</div>
+
+<div class="cos-info-contaier">
+ <form role="form" ng-submit="onCosInputSubmit()">
+
+ <!-- Name -->
+
+ <div class="data-row">
+ <div class="label-col">Name:</div>
+ <div class="data-col" ng-show="showCosName()">
+ <span class="data-item">
+ {{ cosList[selectedCosIdx].id }}
+ </span>
+ </div>
+ <div class="data-col" ng-show="showCosNameInput()">
+ <input class="data-input" name="id"
+ type="text" ng-required="showCosInputs()"
+ ng-model="cosToEdit.id">
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="label-col">Bandwidth:</div>
+ <div class="data-col" ng-show="showCosValues()">
+
+ <span class="data-item">
+ {{ bwText(cosList[selectedCosIdx]) }}
+ </span>
+ </div>
+ <div class="data-col" ng-show="showCosInputs()">
+ <select class="cos-dd-input"
+ name="bandwidth"
+ ng-required="showCosInputs()"
+ ng-model="cosToEdit.bwSelected"
+ ng-options="bw.name for bw in availableBWs"
+ >
+ </option>
+ </select>
+ </div>
+ </div>
+
+ <!-- Availability -->
+
+ <div class="data-row">
+ <div class="label-col">Availability:</div>
+ <div class="data-col" ng-show="showCosValues()">
+ <span class="data-item">
+ {{ cosList[selectedCosIdx].availbility }}
+ </span>
+ <span class="data-unit">%</span>
+ </div>
+ <div class="data-col" ng-show="showCosInputs()">
+ <input class="data-input" name="availbility"
+ type="number" step="any" ng-required="showCosInputs()"
+ min="1" max="100"
+ ng-model="cosToEdit.availbility">
+ <span class="data-unit">%</span>
+ </div>
+ </div>
+
+ <!-- Frame Delay -->
+
+ <div class="data-row">
+ <div class="label-col">Frame Delay:</div>
+ <div class="data-col" ng-show="showCosValues()">
+ <span class="data-item">
+ {{ cosList[selectedCosIdx].frameDelay }}
+ </span>
+ <span class="data-unit">ms</span>
+ </div>
+ <div class="data-col" ng-show="showCosInputs()">
+ <input class="data-input" name="frameDelay"
+ type="number" step="any" ng-required="showCosInputs()"
+ min="0"
+ ng-model="cosToEdit.frameDelay">
+ <span class="data-unit">ms</span>
+ </div>
+ </div>
+
+ <!-- Jitter -->
+
+ <div class="data-row">
+ <div class="label-col">Jitter:</div>
+ <div class="data-col" ng-show="showCosValues()">
+ <span class="data-item">
+ {{ cosList[selectedCosIdx].jitter }}
+ </span>
+ <span class="data-unit">ms</span>
+ </div>
+ <div class="data-col" ng-show="showCosInputs()">
+ <input class="data-input" name="jitter"
+ type="number" step="any" ng-required="showCosInputs()"
+ min="0"
+ ng-model="cosToEdit.jitter">
+ <span class="data-unit">ms</span>
+ </div>
+ </div>
+
+ <!-- Frame Loss -->
+
+ <div class="data-row">
+ <div class="label-col">Frame Loss:</div>
+ <div class="data-col" ng-show="showCosValues()">
+ <span class="data-item">
+ {{ cosList[selectedCosIdx].frameLoss }}
+ </span>
+ <span class="data-unit">%</span>
+ </div>
+ <div class="data-col" name="frameLoss"ng-show="showCosInputs()">
+ <input class="data-input" name="frameLoss"
+ type="number" step="any" ng-required="showCosInputs()"
+ min="0" max="100"
+ ng-model="cosToEdit.frameLoss">
+ <span class="data-unit">%</span>
+ </div>
+ </div>
+
+
+ <div class="warning-container">
+ <div class="warning" ng-show="cosNameConflict()">Please Enter Unique Name</div>
+ </div>
+ <div class="button-container">
+ <button type="submit"
+ class="btn btn-sm my-btn-addon"
+ <div ng-class="{'btn-success' : cosAddInProgress(),
+ 'btn-warning' : cosUpdateInProgress(),
+ 'btn-danger' : cosDelInProgress()}"
+ ng-disabled="!activateCosActionButton()"
+ ng-show="showCosActionButton()")>
+ {{ cosActionButtonText }}</button>
+ </div>
+ </form>
+</div>
diff --git a/demo-ui/app/views/css/vcpe.css b/demo-ui/app/views/css/vcpe.css
new file mode 100644
index 0000000..0d08734
--- /dev/null
+++ b/demo-ui/app/views/css/vcpe.css
@@ -0,0 +1,340 @@
+input[type='number'] {
+ font-size: 12px;
+}
+.choosable {
+ cursor: pointer;
+}
+.gradient {
+ background: -webkit-linear-gradient(rgba(255, 255, 255, 0) 0%, #ffffff 100%);
+ background: linear-gradient(to bottom, #ffffff 0%, rgba(255, 255, 255, 0) 100%);
+}
+.my-btn-addon {
+ height: 30px;
+ width: 100px;
+}
+.primary-lable {
+ color: darkred;
+ font-size: large;
+ font-weight: bold;
+ text-align: center;
+}
+.list-item {
+ color: black;
+ font-size: small;
+ font-weight: normal;
+ text-align: left;
+ background-color: none;
+}
+.selected-item-idle {
+ background-color: #e3e3e3;
+}
+.selected-item-delete {
+ background-color: #FFE4E1;
+}
+.selected-item-update {
+ background-color: #FFEFD5;
+}
+.primary-container {
+ border: 3px solid black;
+ background-color: #e3e3e3;
+ border-radius: 15px;
+ padding: 10px;
+ height: 400px;
+}
+.secondary-container {
+ border: 1px solid darkgray;
+ background-color: white;
+ padding: 5px 10px;
+ margin: 10px 10px -1px 10px;
+ height: 125px;
+ overflow-y: scroll;
+}
+.action-icon-container {
+ border: 1px solid darkgray;
+ background: -webkit-linear-gradient(rgba(255, 255, 255, 0) 0%, #ffffff 100%);
+ background: linear-gradient(to bottom, #ffffff 0%, rgba(255, 255, 255, 0) 100%);
+ margin: 0px 10px;
+ padding: 2px 10px;
+}
+.action-icon {
+ cursor: pointer;
+ padding: 0px 1px;
+ font-size: small;
+ color: black;
+ padding: 2px;
+}
+.action {
+ color: blue !important;
+}
+.warning {
+ color: red !important;
+ font-size: small !important;
+}
+.data-row {
+ display: flex;
+ flex-flow: row nowrap;
+ height: 20px;
+ width: 300;
+}
+.label-col {
+ color: purple;
+ font-size: small;
+ font-weight: normal;
+ text-align: left;
+ flex: 0 0 auto;
+ order: 1;
+ width: 85px;
+}
+.data-col {
+ flex: 0 0 auto;
+ order: 2;
+ color: black;
+ font-size: small;
+ font-weight: normal;
+ text-align: left;
+}
+.data-label {
+ color: purple;
+ font-size: small;
+ font-weight: normal;
+ text-align: left;
+ vertical-align: middle;
+}
+.data-item {
+ color: black;
+ font-size: small;
+ font-weight: bold;
+ text-align: left;
+}
+.data-input {
+ height: 20px;
+ width: 70px;
+ border-radius: 5px;
+}
+.cos-dd-input {
+ height: 20px;
+ width: 70px;
+}
+.epl-dd-input {
+ height: 20px;
+ width: 150px;
+}
+.data-unit {
+ color: black;
+ font-size: small;
+ font-weight: normal;
+ text-align: left;
+ margin-left: 5px;
+ vertical-align: middle;
+}
+.header-container {
+ display: flex;
+ flex-flow: row nowrap;
+ justify-content: space-between;
+}
+.header-container .hdr {
+ flex: 1 1 auto;
+ order: 1;
+}
+.header-container .img {
+ flex: 1 1 auto;
+ order: 2;
+ align-self: flex-end;
+ margin-bottom: 12px;
+}
+.frame {
+ display: flex;
+ flex-flow: row nowrap;
+ border: 1px solid lightgray;
+ margin: 20px;
+ padding: 20px 0px;
+}
+.frame .left {
+ flex: 1 6 5%;
+ order: 1;
+}
+.frame .right {
+ flex: 1 6 5%;
+ order: 3;
+}
+.frame .content {
+ border: none;
+ flex: 1 6 90%;
+ order: 2;
+}
+.frame .content .action-container {
+ border: none;
+ display: flex;
+ flex-flow: row nowrap;
+}
+.frame .content .action-container .cos-container {
+ border: 3px solid black;
+ background-color: #e3e3e3;
+ border-radius: 15px;
+ padding: 10px;
+ height: 400px;
+ flex: 1 1 50%;
+ order: 1;
+ margin-right: 20px;
+}
+.frame .content .action-container .cos-container .cos-list {
+ border: 1px solid darkgray;
+ background-color: white;
+ padding: 5px 10px;
+ margin: 10px 10px -1px 10px;
+ height: 125px;
+ overflow-y: scroll;
+}
+.frame .content .action-container .cos-container .cos-info-contaier {
+ display: flex;
+ flex-flow: column nowrap;
+ margin: 10px 20px;
+}
+.frame .content .action-container .cos-container .cos-info-contaier .labelContainer {
+ flex: 1 1 33%;
+ order: 1;
+ min-width: 80px;
+ color: purple;
+ font-size: small;
+ font-weight: normal;
+ text-align: left;
+ vertical-align: middle;
+}
+.frame .content .action-container .cos-container .warning-container {
+ height: 15px;
+ margin-top: 10px;
+}
+.frame .content .action-container .epl-container {
+ border: 3px solid black;
+ background-color: #e3e3e3;
+ border-radius: 15px;
+ padding: 10px;
+ height: 400px;
+ flex: 1 1 50%;
+ order: 2;
+ margin-right: 20px;
+}
+.frame .content .action-container .epl-container .epl-list {
+ border: 1px solid darkgray;
+ background-color: white;
+ padding: 5px 10px;
+ margin: 10px 10px -1px 10px;
+ height: 125px;
+ overflow-y: scroll;
+}
+.frame .content .action-container .epl-container .epl-info-contaier {
+ display: flex;
+ flex-flow: column nowrap;
+ margin: 10px 20px;
+}
+.frame .content .action-container .epl-container .epl-info-contaier .labelContainer {
+ flex: 1 1 33%;
+ order: 1;
+ min-width: 80px;
+ color: purple;
+ font-size: small;
+ font-weight: normal;
+ text-align: left;
+ vertical-align: middle;
+}
+.frame .content .action-container .epl-container .warning-container {
+ height: 15px;
+ margin-top: 10px;
+}
+.frame .content .monitor-container .mef-container {
+ border: 3px solid black;
+ background-color: #e3e3e3;
+ border-radius: 15px;
+ padding: 10px;
+ height: 400px;
+ height: 450px;
+ background-color: #B0C4DE;
+ margin: 20px 20px 20px 0px;
+}
+.frame .content .monitor-container .mef-container .primary-mef-lable {
+ color: SteelBlue;
+ font-size: large;
+ font-weight: bold;
+ text-align: center;
+ margin-bottom: 10px;
+}
+.frame .content .monitor-container .mef-container .mef-panel-hdr {
+ border-bottom: 1px solid SlateGray;
+}
+.frame .content .monitor-container .mef-container .secondary-mef-label {
+ color: SlateGray;
+ font-size: small;
+ font-weight: bold;
+ text-align: center;
+ background-color: #e3e3e3;
+}
+.frame .content .monitor-container .mef-container .mef-data-label {
+ color: purple;
+ font-size: small;
+ font-weight: normal;
+ text-align: left;
+ vertical-align: middle;
+}
+.frame .content .monitor-container .mef-container .mef-label-col {
+ color: purple;
+ font-size: small;
+ font-weight: normal;
+ text-align: left;
+ flex: 0 0 auto;
+ order: 1;
+ padding-left: 10px;
+}
+.frame .content .monitor-container .mef-container .evc-label-col {
+ color: purple;
+ font-size: small;
+ font-weight: normal;
+ text-align: left;
+ flex: 0 0 auto;
+ order: 1;
+ padding-left: 10px;
+ width: 200px;
+}
+.frame .content .monitor-container .mef-container .uni-label-col {
+ color: purple;
+ font-size: small;
+ font-weight: normal;
+ text-align: left;
+ flex: 0 0 auto;
+ order: 1;
+ padding-left: 10px;
+ width: 100px;
+}
+.frame .content .monitor-container .mef-container .mef-info-container {
+ display: flex;
+ flex-flow: row nowrap;
+ justify-content: center;
+}
+.frame .content .monitor-container .mef-container .mef-info-container .mef-secondary-container {
+ border: 1px solid darkgray;
+ background-color: WhiteSmoke;
+ margin: 5px;
+}
+.frame .content .monitor-container .mef-container .mef-info-container .uni1-container {
+ border: 1px solid darkgray;
+ background-color: WhiteSmoke;
+ margin: 5px;
+ border: 2px solid SlateGray;
+ flex: 1 1 24%;
+ order: 1;
+}
+.frame .content .monitor-container .mef-container .mef-info-container .evc-container {
+ border: 1px solid darkgray;
+ background-color: WhiteSmoke;
+ margin: 5px;
+ border: 2px solid SlateGray;
+ flex: 1 1 38%;
+ order: 2;
+}
+.frame .content .monitor-container .mef-container .mef-info-container .uni2-container {
+ border: 1px solid darkgray;
+ background-color: WhiteSmoke;
+ margin: 5px;
+ border: 2px solid SlateGray;
+ flex: 1 1 24%;
+ order: 3;
+}
diff --git a/demo-ui/app/views/epl-panel.html b/demo-ui/app/views/epl-panel.html
new file mode 100644
index 0000000..3de2523
--- /dev/null
+++ b/demo-ui/app/views/epl-panel.html
@@ -0,0 +1,187 @@
+<!--
+
+To Do
+ construct default name based on UNIs and COS
+ display EVC params when clicked
+ changed currently hardcoded widths (150) of input fields/dd's to be set by a class
+ update config file based on watch (already have hit issue), rather than wait
+ update available cos list when new cos added (low priority)
+
+ -->
+
+<!-- List of existing EPLs -->
+
+<div class="primary-lable ">Ethernet Private Line Services</div>
+<div class="epl-list">
+ <div class="list-item choosable"
+ ng-repeat="epl in eplList track by $index"
+
+ ng-class="{'selected-item-idle' : $index === selectedEplIdx &&
+ !eplActionInProgress(),
+ 'selected-item-update' : $index === selectedEplIdx &&
+ eplUpdateInProgress(),
+ 'selected-item-delete' : $index === selectedEplIdx &&
+ eplDelInProgress() }"
+ ng-click="onEplClick($index)">
+ {{ epl.id }}
+ </div>
+</div>
+
+
+<!-- Action Icons (add/mod/del) -->
+
+<div class = "action-icon-container">
+
+ <span class="action-icon glyphicon glyphicon-plus"
+ ng-click="onAddEpl()"
+ ng-class="{'action' : eplAddInProgress()}">
+ </span>
+
+ <span class="action-icon glyphicon glyphicon-pencil"
+ ng-click="onUpdateEpl()"
+ ng-class="{'action' : eplUpdateInProgress()}">
+ </span>
+
+ <span class="action-icon glyphicon glyphicon-minus"
+ ng-click="onDelEpl()"
+ ng-class="{'action' : eplDelInProgress()}">
+ </span>
+</div>
+
+<!-- Data for EPL selected / being acted on -->
+
+<div class="epl-info-contaier">
+ <form role="form" ng-submit="onEplInputSubmit()">
+
+ <!-- Name -->
+
+ <div class="data-row">
+ <div class="label-col">Name:</div>
+ <div class="data-col" ng-show="showEplName()">
+ <span class="data-item">
+ {{ eplList[selectedEplIdx].id }}
+ </span>
+ </div>
+
+ <div class="data-col" ng-show="showEplNameInput()">
+ <input class="data-input" name="id"
+ style="width:150"
+ type="text" ng-required="showEplInputs()"
+ ng-model="eplToEdit.id">
+ </div>
+ </div>
+
+ <!-- Class of servce -->
+
+ <div class="data-row">
+ <div class="label-col">Service level</div>
+ <div class="data-col" ng-show="showEplValues()">
+ <span class="data-item">
+ {{ eplList[selectedEplIdx].cos }}</span>
+ </div>
+ <div class="data-col" ng-show="showEplInputs()">
+ <select class="dd-input"
+ style="width:150"
+ name="cos Id"
+ ng-required="showEplInputs()"
+ ng-model="eplToEdit.cos"
+ >
+ <option ng-repeat="cos in availableCosIds"
+ value="{{ cos }}"
+ ng-selected="{{cos == eplToEdit.cos}}"
+ >
+ {{ cos }}
+ </option>
+ </select>
+ </div>
+ </div>
+
+
+ <!-- UNI 1 -->
+
+ <div class="data-row">
+ <div class="label-col">UNI 1</div>
+ <div class="data-col" ng-show="showEplValues()">
+ <span class="data-item">
+ {{ eplList[selectedEplIdx].uniHostIpList[0] }}&nbsp
+ ( {{ eplList[selectedEplIdx].custAddressList[0] }} )
+ </span>
+ </div>
+
+ <div class="data-col" ng-show="showEplInputs()">
+ <select class="dd-input"
+ style="width:150"
+ name="uni 1"
+ ng-required="showEplInputs()"
+ ng-model="eplToEdit.uni1Selected"
+ ng-options="uni.ip + ' ( ' + uni.address + ' )' for uni in availableUnis"
+ >
+ </option>
+ </select>
+ </div>
+ </div>
+
+
+ <!-- UNI 2 -->
+
+ <div class="data-row">
+ <div class="label-col">UNI 2</div>
+ <div class="data-col" ng-show="showEplValues()">
+ <span class="data-item">
+ {{ eplList[selectedEplIdx].uniHostIpList[1] }}&nbsp
+ ( {{ eplList[selectedEplIdx].custAddressList[1] }} )
+ </span>
+ </div>
+
+ <div class="data-col" ng-show="showEplInputs()">
+ <select class="dd-input"
+ style="width:150"
+ name="uni 1"
+ ng-required="showEplInputs()"
+ ng-model="eplToEdit.uni2Selected"
+ ng-options="uni.ip + ' ( ' + uni.address + ' )' for uni in availableUnis"
+ >
+ </option>
+ </select>
+ </div>
+ </div>
+
+
+ <!-- Evc -->
+
+ <div class="data-row" >
+ <div class="label-col" ng-hide="eplAddInProgress()">Assoc Evc:</div>
+ <div class="data-col">
+ <span class="data-item" ng-hide="eplAddInProgress()">
+ {{ eplList[selectedEplIdx].evcId }}
+ </span>
+ </div>
+ </div>
+
+ <!-- Action Buttons -->
+
+ <div class="warning-container">
+ &nbsp<span class="warning" ng-show="eplNameConflict()">[Please Enter Unique Name]&nbsp&nbsp&nbsp</span>
+ <span class="warning" ng-show="uniConflict()">[UNI-1 and UNI-2 must be different]&nbsp&nbsp&nbsp</span>
+ <span class="warning" ng-show="cosConflict()">[Must create SL before creating EPL]&nbsp&nbsp&nbsp</span>
+ </div>
+ <div class="button-container">
+ <button type="submit"
+ class="btn btn-sm my-btn-addon"
+ <div ng-class="{'btn-success' : eplAddInProgress(),
+ 'btn-warning' : eplUpdateInProgress(),
+ 'btn-danger' : eplDelInProgress()}"
+ ng-disabled="!activateEplActionButton()"
+ ng-show="showEplActionButton()")>
+ {{ eplActionButtonText }}</button>
+ </div>
+
+ <!-- Debug -->
+
+<!--
+ <div>
+ </div>
+ -->
+
+ </form>
+</div>
diff --git a/demo-ui/app/views/less/vcpe.less b/demo-ui/app/views/less/vcpe.less
new file mode 100644
index 0000000..5598160
--- /dev/null
+++ b/demo-ui/app/views/less/vcpe.less
@@ -0,0 +1,365 @@
+@dbg-flg: false;
+
+@side-panel-width: 5%;
+@main-panel-width: 100%-(2*@side-panel-width);
+
+@backgroundGray: #E3E3E3;
+
+@cos-basis: 50%;
+@epl-basis: 100%-(@cos-basis);
+
+
+//
+// Utilities
+//
+
+.dbg-border( // show border if @dbg-flg is true
+ @dbg-bordersFlg,
+ @dbg-borderClr,
+ @dbg-borderStyle)
+ when (@dbg-bordersFlg=true) {
+ border: 3px @dbg-borderStyle @dbg-borderClr;
+ margin: 1px; padding: 1px;
+}
+
+.set-text(@color,
+ @font-size,
+ @font-weight,
+ @text-align) {
+ color:@color; font-size:@font-size;
+ font-weight:@font-weight; text-align:@text-align;
+}
+
+//
+// Common Styles
+//
+
+input[type='number'] { font-size: 12px; }
+
+.choosable {
+ cursor: pointer;
+}
+
+.gradient {
+ background: -webkit-linear-gradient(rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
+ background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
+}
+
+.my-btn-addon {
+ height: 30px;
+ width: 100px;
+}
+
+.primary-lable {
+ .set-text(darkred, large, bold, center); }
+
+.list-item {
+ .set-text(black, small, normal, left);
+ background-color:none; }
+
+.selected-item-idle {
+ background-color: @backgroundGray; }
+
+.selected-item-delete {
+ background-color: #FFE4E1; }
+
+.selected-item-update {
+ background-color: #FFEFD5; }
+
+.primary-container {
+ border: 3px solid black;
+ .dbg-border(@dbg-flg, blue, solid);
+ background-color: @backgroundGray;
+ border-radius: 15px;
+ padding: 10px;
+ height: 400px;
+}
+
+.secondary-container {
+ border: 1px solid darkgray;
+ .dbg-border(@dbg-flg, green, solid);
+ background-color: white;
+ padding: 5px 10px; // TB RL
+ margin: 10px 10px -1px 10px; // T R B L
+ height: 125px;
+ overflow-y: scroll;
+}
+
+.action-icon-container {
+ border: 1px solid darkgray;
+ .dbg-border(@dbg-flg, magenta, solid);
+ .gradient;
+ margin: 0px 10px; // TB RL
+ padding: 2px 10px; // TB RL
+}
+
+.action-icon {
+ .choosable;
+ padding: 0px 1px; // TB RL
+ font-size: small;
+ color: black;
+ padding: 2px;
+}
+
+.action {
+ color: blue !important;
+}
+
+.warning {
+ color: red !important;
+ font-size: small !important;
+}
+
+.data-row {
+ .dbg-border(@dbg-flg, red, solid);
+ display: flex;
+ flex-flow:row nowrap;
+ height: 20px;
+ width: 300;
+ }
+.label-col {
+ .dbg-border(@dbg-flg, gray, solid);
+ .set-text(purple, small, normal, left);
+ flex: 0 0 auto; order: 1;
+ width: 85px;
+ }
+
+
+.data-col {
+ .dbg-border(@dbg-flg, gray, solid);
+ flex: 0 0 auto; order: 2;
+ .set-text(black, small, normal, left);
+
+ }
+
+.data-label {
+ .set-text(purple, small, normal, left);
+ vertical-align: middle;
+}
+.data-item {
+ .set-text(black, small, bold, left);
+}
+.data-input {
+ height: 20px;
+ width: 70px;
+ border-radius: 5px;
+}
+.cos-dd-input {
+ height: 20px;
+ width: 70px;
+}
+
+.epl-dd-input {
+ height: 20px;
+ width: 150px;
+}
+
+
+.data-unit {
+ .set-text(black, small, normal, left);
+ margin-left: 5px;
+ vertical-align: middle;
+}
+
+//
+// Page starts here
+//
+
+.header-container {
+ display: flex;
+ flex-flow:row nowrap;
+ justify-content: space-between;
+ .hdr {
+ flex: 1 1 auto; order: 1;
+ }
+ .img {
+ flex: 1 1 auto; order: 2;
+ align-self: flex-end;
+ margin-bottom: 12px;
+ }
+}
+
+
+.frame{
+ .dbg-border(@dbg-flg, lightgray, solid);
+ display: flex;
+ flex-flow:row nowrap;
+ border: 1px solid lightgray;
+
+ margin: 20px; // TBRL
+ padding: 20px 0px; // TB RL
+
+ .left { .dbg-border(@dbg-flg, lightgray, solid);
+ flex: 1 6 @side-panel-width; order: 1; }
+
+ .right{ .dbg-border(@dbg-flg, lightgray, solid);
+ flex: 1 6 @side-panel-width; order: 3; }
+
+ .content {
+ border: none;
+ .dbg-border(@dbg-flg, lightgray, solid);
+ flex: 1 6 @main-panel-width; order: 2;
+
+ .action-container {
+ border: none;
+ .dbg-border(@dbg-flg, yellow, solid);
+
+ display: flex;
+ flex-flow:row nowrap;
+
+ .cos-container {
+ .primary-container;
+ flex: 1 1 @cos-basis; order: 1;
+ margin-right: 20px;
+
+ .cos-list {
+ .secondary-container;
+ }
+ .cos-info-contaier {
+ .dbg-border(@dbg-flg, green, solid);
+ display: flex;
+ flex-flow:column nowrap;
+ margin: 10px 20px; // TB RL
+ .labelContainer {
+ .dbg-border(@dbg-flg, yellow, solid);
+ flex: 1 1 33%; order: 1;
+ min-width: 80px;
+ .data-label;
+ }
+ }
+ .warning-container {
+ .dbg-border(@dbg-flg, magenta, solid);
+ height: 15px;
+ margin-top: 10px;
+ }
+ .button-container {
+ .dbg-border(@dbg-flg, magenta, solid);
+ }
+ }
+ .epl-container {
+ .primary-container;
+ flex: 1 1 @epl-basis; order: 2;
+ margin-right: 20px;
+
+ .epl-list {
+ .secondary-container;
+ }
+ .epl-info-contaier {
+ .dbg-border(@dbg-flg, green, solid);
+ display: flex;
+ flex-flow:column nowrap;
+ margin: 10px 20px; // TB RL
+ .labelContainer {
+ .dbg-border(@dbg-flg, yellow, solid);
+ flex: 1 1 33%; order: 1;
+ min-width: 80px;
+ .data-label;
+ }
+ }
+ .warning-container {
+ .dbg-border(@dbg-flg, magenta, solid);
+ height: 15px;
+ margin-top: 10px;
+ }
+ .button-container {
+ .dbg-border(@dbg-flg, magenta, solid);
+ }
+ }
+ }
+
+ .monitor-container {
+ .dbg-border(@dbg-flg, yellow, solid);
+
+
+ .mef-container {
+ .primary-container;
+ height: 450px;
+
+ .dbg-border(@dbg-flg, blue, solid);
+ background-color: #B0C4DE;
+ margin: 20px 20px 20px 0px; // T R B L
+
+ .primary-mef-lable {
+ .set-text(SteelBlue, large, bold, center);
+ margin-bottom: 10px;
+ }
+
+ @mef-container-border-color: SlateGray;
+
+ .mef-panel-hdr {
+ border-bottom: 1px solid @mef-container-border-color;
+ .dbg-border(@dbg-flg, blue, solid);
+ }
+
+ .secondary-mef-label {
+ .set-text(SlateGray, small, bold, center);
+ background-color: @backgroundGray;
+ }
+
+ .mef-data-label {
+ .set-text(purple, small, normal, left);
+ vertical-align: middle;
+
+ }
+ .mef-label-col {
+ .dbg-border(@dbg-flg, gray, solid);
+ .set-text(purple, small, normal, left);
+ flex: 0 0 auto; order: 1;
+ padding-left: 10px;
+ }
+
+ .evc-label-col {
+ .mef-label-col;
+ width: 200px;
+
+ }
+ .uni-label-col {
+ .mef-label-col;
+ width: 100px;
+ }
+
+ .mef-info-container {
+ display: flex;
+ flex-flow:row nowrap;
+ justify-content: center;
+
+ .mef-secondary-container {
+ border: 1px solid darkgray;
+ .dbg-border(@dbg-flg, green, solid);
+ background-color: WhiteSmoke;
+ //padding: 5px 30px; // TB RL
+ margin: 5px;
+ }
+
+ @evc-basis: 38%;
+ @uni-basis: 100%-(2*@evc-basis);
+
+ .uni1-container {
+ .mef-secondary-container;
+ border: 2px solid @mef-container-border-color;
+ .dbg-border(@dbg-flg, darkred, solid);
+ flex: 1 1 @uni-basis; order: 1;
+
+ }
+ .evc-container {
+ .mef-secondary-container;
+ border: 2px solid @mef-container-border-color;
+ .dbg-border(@dbg-flg, darkred, solid);
+ flex: 1 1 @evc-basis; order: 2;
+
+ }
+ .uni2-container {
+ .mef-secondary-container;
+ border: 2px solid @mef-container-border-color;
+ .dbg-border(@dbg-flg, darkred, solid);
+ flex: 1 1 @uni-basis; order: 3;
+
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
diff --git a/demo-ui/app/views/mef-panel.html b/demo-ui/app/views/mef-panel.html
new file mode 100644
index 0000000..df9f60b
--- /dev/null
+++ b/demo-ui/app/views/mef-panel.html
@@ -0,0 +1,370 @@
+<!--
+
+To Do
+ Use cases to handle properly RE EVC/UNI displaying info
+ - EPL exist at start up
+ - no EPL at start up
+ - delete an EPL
+ - delete last EPL
+ -->
+
+<div class="primary-mef-lable">MEF EPL Data</div>
+<div class="mef-info-container">
+
+
+ <!-- UNI 1 -->
+
+ <div class="uni1-container">
+ <div class="mef-panel-hdr">
+ <div class="secondary-mef-label">UNI-1 MEF Attributes</div>
+ <div class="secondary-mef-label"
+ style="font-size: xx-small; font-weight: normal; color: #b3b3b3;">
+ (Source = ODL UNI Mgr DB)
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Uni ID:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[0].uni[0]["id"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">IP Address:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[0].uni[0]["ip-address"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">MAC Address:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[0].uni[0]["mac-address"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Speed:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ uniToSpeedString(currentEvcUnis[0]) }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Mac Layer:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[0].uni[0]["mac-layer"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Phys Medium:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[0].uni[0]["physical-medium"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">MTU Size:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[0].uni[0]["mtu-size"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Mode:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[0].uni[0]["mode"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Type:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[0].uni[0]["type"] }}
+ </span>
+ </div>
+ </div>
+
+ </div>
+
+ <!-- EVC -->
+
+ <div class="evc-container">
+
+ <div class="mef-panel-hdr">
+ <div class="secondary-mef-label">EVC MEF Attributes</div>
+ <div class="secondary-mef-label"
+ style="font-size: xx-small; font-weight: normal; color: #b3b3b3;">
+ (Source = EVC Mgr DB)</div>
+ </div>
+ <div class="data-row">
+ <div class="evc-label-col">Evc ID:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.id }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">CoS ID:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.cosId }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">Uni-1/2 IDs:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+
+ <span class="data-item">
+ {{ "[" + currentEplEvc.uniIdList[0] + "] | [" + currentEplEvc.uniIdList[1] + "]"}}
+ </span>
+
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">Uni-1/2 IPs:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.uniIpList[0] }}
+ </span>
+ </div>
+ </div>
+ <div class="data-row">
+ <div class="evc-label-col"></div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.uniIpList[1] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">Uni-1/2 MACs:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.uniMacList[0] }}
+ </span>
+ </div>
+ </div>
+ <div class="data-row">
+ <div class="evc-label-col"></div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.uniMacList[1] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">1-Way Availability:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.oneWayAvailability }}
+ </span>
+ <span class="data-unit">%</span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">1-Way Frame Delay:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.oneWayFrameDelay }}
+ </span>
+ <span class="data-unit">ms</span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">1-Way Frame Loss Ratio:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.oneWayFrameLossRatio }}
+ </span>
+ <span class="data-unit">%</span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">EVC Type:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.evcType }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">Unicast Frame Delivery:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.unicastFrameDelivery }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">Broadcast Frame Delivery:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.broadcastFrameDelivery }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">Multicast Frame Delivery:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.multicastFrameDelivery }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">CE VLAN ID Preservation:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.ceVLanIdPreservation }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">CE VLAN CoS Preservation:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.ceVlanCosPreservation }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="evc-label-col">Max Service Frame Size:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEplEvc.evcMaxSvcFrameSize }}
+ </span>
+ <span class="data-unit">bytes</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- UNI 2 -->
+
+ <div class="uni2-container">
+ <div class="mef-panel-hdr">
+ <div class="secondary-mef-label">UNI-2 MEF Attributes</div>
+ <div class="secondary-mef-label"
+ style="font-size: xx-small; font-weight: normal; color: #b3b3b3;">
+ (Source = ODL UNI Mgr DB)
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Uni ID:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[1].uni[0]["id"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">IP Address:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[1].uni[0]["ip-address"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">MAC Address:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[1].uni[0]["mac-address"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Speed:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ uniToSpeedString(currentEvcUnis[1]) }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Mac Layer:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[1].uni[0]["mac-layer"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Phys Medium:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[1].uni[0]["physical-medium"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">MTU Size:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[0].uni[0]["mtu-size"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Mode:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[1].uni[0]["mode"] }}
+ </span>
+ </div>
+ </div>
+
+ <div class="data-row">
+ <div class="uni-label-col">Type:</div>
+ <div class="data-col" ng-show="showEvcValues()">
+ <span class="data-item">
+ {{ currentEvcUnis[1].uni[0]["type"] }}
+ </span>
+ </div>
+ </div>
+
+ </div>
+</div> \ No newline at end of file
diff --git a/demo-ui/app/views/vcpe-portal.html b/demo-ui/app/views/vcpe-portal.html
new file mode 100644
index 0000000..437485f
--- /dev/null
+++ b/demo-ui/app/views/vcpe-portal.html
@@ -0,0 +1,71 @@
+<!--
+
+TODO
+ - Use watchers to trigger changes aftger config file reads as opposed
+ to the current "sleep for a bit" approach
+
+ -->
+
+<html ng-app="vcpe">
+<head ng-controller="MainController">
+
+ <script src="../../bower_components/angular/angular.min.js"></script>
+
+ <link rel="stylesheet" href="../../bower_components/bootstrap/dist/css/bootstrap.min.css">
+ <link rel="stylesheet" href="../../bower_components/bootstrap/dist/css/bootstrap-theme.min.css">
+
+ <link rel="stylesheet" href="css/vcpe.css" />
+ <script src="../controllers/MainController.js"></script>
+ <script src="../controllers/CosController.js"></script>
+ <script src="../controllers/EplController.js"></script>
+ <script src="../controllers/MefController.js"></script>
+ <script src="../services/cosServices.js"></script>
+ <script src="../services/eplServices.js"></script>
+ <script src="../services/mefServices.js"></script>
+ <script src="../services/model.js"></script>
+ <script src="../services/dbg.js"></script>
+
+</head>
+
+<body>
+<div class="frame">
+<div class="left"></div>
+
+<div class="content">
+
+ <div class="header-container">
+ <div class="hdr">
+ <h2>Virtual Business CPE Demo</h2>
+ </div>
+ </div>
+
+ <div class="action-container">
+
+ <div class="cos-container"
+ ng-controller="CosController"
+ ng-include="'cos-panel.html'">
+ </div>
+
+ <div class="epl-container"
+ ng-controller="EplController"
+ ng-include="'epl-panel.html'">
+ </div>
+
+ </div>
+
+ <div class="monitor-container">
+
+ <div class="mef-container"
+ ng-controller="MefController"
+ ng-include="'mef-panel.html'">
+ </div>
+
+
+ </div>
+
+</div>
+
+<div class="right"></div>
+</div>
+</body>
+</html>