123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- {% extends "base.html" %}
- {% set active_page = "assets" %}
- {% block title %} {{asset.name}} {% endblock %}
- {% block divs %}
- {% block breadcrumbs %} {{ super() }} {% endblock %}
- <div class="container-fluid">
- <div class="row mx-1">
- <div class="alert alert-info d-none" id="tzwarn"></div>
- <div class="alert alert-info d-none" id="dstwarn"></div>
- </div>
- <div class="row">
- <div class="col-md-2 on-top-md">
- <div class="header-action-button">
- {% if user_can_delete_asset %}
- <div>
- <form action="/assets/delete_with_data/{{ asset.id }}" method="get">
- <button id="delete-asset-button" class="btn btn-sm btn-responsive btn-danger"
- type="submit">Delete this asset</button>
- </form>
- <script>
- $("#delete-asset-button").click(function () {
- if (confirm("Are you sure you want to delete this asset and all time series data associated with it?")) {
- return true;
- }
- else {
- return false;
- }
- });
- </script>
- </div>
- {% endif %}
- </div>
- <div class="sidepanel-container d-none d-md-block">
- <div class="left-sidepanel-label">Select dates</div>
- <div class="sidepanel left-sidepanel">
- <div id="datepicker"></div>
- </div>
- </div>
- {% if user_can_update_asset %}
- <div class="sidepanel-container">
- <div class="left-sidepanel-label">Edit asset</div>
- <div class="sidepanel left-sidepanel">
- <form class="form-horizontal" method="POST" action="/assets/{{ asset.id }}">
- {{ asset_form.csrf_token }}
- {{ asset_form.hidden_tag() }}
- <fieldset>
- <div class="asset-form">
- <h3>Edit {{ asset.name }}</h3>
- <small>Owned by account: {{ asset.account_id | accountname }} (ID: {{ asset.account_id
- }})</small>
- <div class="form-group">
- {{ asset_form.name.label(class="col-sm-3 control-label") }}
- <div class="col-md-3">
- {{ asset_form.name(class_="form-control") }}
- {% for error in asset_form.errors.name %}
- <span style="color: red;">[{{error}}]</span>
- {% endfor %}
- </div>
- </div>
- <div class="form-group">
- {{ asset_form.latitude.label(class="col-sm-6 control-label") }}
- <div class="col-md-6">
- {{ asset_form.latitude(class_="form-control") }}
- {% for error in asset_form.errors.latitude %}
- <span style="color: red;">[{{error}}]</span>
- {% endfor %}
- </div>
- </div>
- <div class="form-group">
- {{ asset_form.longitude.label(class="col-sm-6 control-label") }}
- <div class="col-md-6">
- {{ asset_form.longitude(class_="form-control") }}
- {% for error in asset_form.errors.longitude %}
- <span style="color: red;">[{{error}}]</span>
- {% endfor %}
- </div>
- </div>
- <div class="form-group">
- <label for="assset-type" class="col-sm-6 control-label">Asset Type</label>
- <div class="col-md-6">
- <input class="form-control" id="asset-type-id" name="asset-type" type="text"
- value="{{ asset.generic_asset_type.name }}" disabled></input>
- </div>
- </div>
- <div class="form-group">
- <label for="asset-id" class="col-sm-6 control-label">Asset id</label>
- <div class="col-md-6">
- <input class="form-control" id="asset-id" name="asset-id" type="text"
- value="{{ asset.id }}" disabled></input>
- </div>
- </div>
- <div class="form-group">
- {{ asset_form.attributes.label(class="col-sm-3 control-label") }}
- <div class="col-md-3">
- {{ asset_form.attributes(class_="form-control") }}
- {% for error in asset_form.errors.attributes %}
- <span style="color: red;">[{{error}}]</span>
- {% endfor %}
- </div>
- </div>
- <div class="form-group">
- <label class="control-label">Location</label>
- <small>(Click map to edit latitude and longitude in form)</small>
- <div id="mapid"></div>
- <button class="btn btn-sm btn-responsive btn-success create-button" type="submit"
- value="Save"
- style="margin-top: 20px; float: right; border: 1px solid var(--light-gray);">
- Save
- </button>
- </div>
- </div>
- </fieldset>
- </form>
- </div>
- </div>
- {% endif %}
-
- </div>
- <div class="col-md-8">
- <div class="sensors-asset card">
- <h3>Asset Properties - {{ asset.name }}</h3>
- <div class="row">
- <div class="col-md-7">
- <table class="table table-striped table-responsive">
- <thead>
- <tr>
- <th scope="col">Property</th>
- <th scope="col">Value</th>
- </tr>
- </thead>
- <tbody>
- {% for key, value in asset_summary.items() %}
- <tr>
- <td scope="row">{{ key }}</td>
- {% if key == "Parent Asset" and value != "No Parent" %}
- <td scope="row"><a href="/assets/{{ asset.parent_asset.id }}" class="no-style-link">{{ value }}</a></td>
- {% else %}
- <td scope="row">{{ value }}</td>
- {% endif %}
- </tr>
- {% endfor %}
- </tbody>
- </table>
- </div>
- <div class="col-md-5">
- {% from "_macros.html" import render_attributes %}
- {{ render_attributes(asset.attributes) }}
- </div>
- </div>
- </div>
- <div class="sensors-asset card">
- <h3>All sensors for {{ asset.name }}</h3>
- <div class="table-responsive">
- <table class="table table-striped paginate nav-on-click" title="View data" id="sensorsTable">
- </table>
- </div>
- </div>
- <div class="sensors-asset card">
- <h3>All child assets for {{ asset.name }}</h3>
- <div class="table-responsive">
- <table class="table table-striped paginate nav-on-click w-100 mx-auto" title="View this asset">
- <thead>
- <tr>
- <th><i class="left-icon">Name</i></th>
- <th>Location</th>
- <th>Asset ID</th>
- <th>Account</th>
- <th>Sensors</th>
- <th class="d-none">URL</th>
- <th class="no-sort"></th>
- </tr>
- </thead>
- <tbody>
- {% for child in asset.child_assets %}
- <tr>
- <td>
- <i class="{{ child.generic_asset_type.name | asset_icon }} left-icon">{{ child.name
- }}</i>
- </td>
- <td>
- {% if child.latitude and child.longitude %}
- LAT: {{ "{:,.4f}".format( child.latitude ) }} LONG:
- {{ "{:,.4f}".format( child.longitude ) }}
- {% endif %}
- </td>
- <td>
- {{ child.id }}
- </td>
- <td>
- {% if child.owner %}
- {{ child.owner.name }}
- {% else %}
- PUBLIC
- {% endif %}
- </td>
- <td>
- {{ child.sensors | length }}
- </td>
- <td class="d-none">
- /assets/{{ child.id }}
- </td>
- <td>
- <a href="/assets/{{ child.id }}/status">
- <button type="button" class="btn">Status</button>
- </a>
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- </div>
- </div>
- </div>
- </div>
- </div>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.7/jstz.js"></script>
- <script src="https://cdn.jsdelivr.net/npm/litepicker/dist/litepicker.js"></script>
- <script src="https://cdn.jsdelivr.net/npm/litepicker/dist/plugins/ranges.js"></script>
- <script src="https://cdn.jsdelivr.net/npm/litepicker/dist/plugins/keyboardnav.js"></script>
- {% block leftsidepanel %} {{ super() }} {% endblock %}
- <!-- Initialise the map -->
- <script src="https://cdn.jsdelivr.net/npm/leaflet@1.7.1/dist/leaflet-src.min.js"></script>
- <script src="{{ url_for('flexmeasures_ui.static', filename='js/map-init.js') }}"></script>
- <script type="text/javascript">
- // create map
- var assetMap = L
- .map('mapid', { center: [{{ asset.latitude | replace("None", 10) }}, {{ asset.longitude | replace("None", 10) }}], zoom: 10})
- .on('popupopen', function () {
- $(function () {
- $('[data-toggle="tooltip"]').tooltip();
- });
- });
- addTileLayer(assetMap, '{{ mapboxAccessToken }}');
- // create marker
- var asset_icon = new L.DivIcon({
- className: 'map-icon',
- html: '<i class="icon-empty-marker center-icon supersize"></i><i class="overlay center-icon {{ asset.generic_asset_type.name | default("info") | asset_icon }}"></i>',
- iconSize: [100, 100], // size of the icon
- iconAnchor: [50, 50], // point of the icon which will correspond to marker's location
- popupAnchor: [0, -50] // point from which the popup should open relative to the iconAnchor
- });
- var marker = L
- .marker(
- [{{ asset.latitude | replace("None", 10) }}, {{ asset.longitude | replace("None", 10) }}],
- { icon: asset_icon }
- ).addTo(assetMap);
- assetMap.on('click', function (e) {
- $("#latitude").val(e.latlng.lat.toFixed(4));
- $("#longitude").val(e.latlng.lng.toFixed(4));
- marker.setLatLng(e.latlng);
- });
- </script>
- <script>
- function Sensor(
- id,
- name,
- unit,
- resolution,
- entity_address,
- active
- ) {
- this.id = id;
- this.name = name;
- this.unit = unit;
- this.resolution = resolution
- this.entity_address = entity_address;
- this.url = `/sensors/${id}`;
- }
- $(document).ready(function () {
- let unit = "";
- // Initialize the DataTable
- const table = $("#sensorsTable").dataTable({
- order: [[0, "asc"]],
- pageLength: 5,
- lengthMenu: [5, 10, 25, 50, 75, 100],
- serverSide: true,
- // make the table row vertically aligned with header
- columns: [
- { data: "id", title: "ID", orderable: true },
- { data: "name", title: "Name", orderable: true },
- { data: "unit", title: "Unit", orderable: false },
- { data: "resolution", title: "Resolution", orderable: true },
- { data: "entity_address", title: "Entity address", orderable: false },
- { data: "url", title: "URL", className: "d-none" },
- ],
- ajax: function (data, callback, settings) {
- const basePath = window.location.origin;
- let filter = data["search"]["value"];
- let orderColumnIndex = data["order"][0]["column"]
- let orderDirection = data["order"][0]["dir"];
- let orderColumnName = data["columns"][orderColumnIndex]["data"];
- let url = `${basePath}/api/v3_0/assets/{{asset.id}}/sensors?page=${data["start"] / data["length"] + 1
- }&per_page=${data["length"]}`;
- if (orderColumnName) {
- url = `${url}&sort_by=${orderColumnName}&sort_dir=${orderDirection}`;
- }
- if (filter.length > 0) {
- url = `${url}&filter=${filter}`;
- }
- if (unit !== "") {
- url = `${url}&unit=${unit}`;
- }
- $.ajax({
- type: "get",
- url: url,
- success: function (response, text) {
- let clean_response = [];
- response["data"].forEach((element) =>
- clean_response.push(
- new Sensor(
- element["id"],
- element["name"],
- element["unit"],
- element["event_resolution"],
- element["entity_address"],
- element["active"]
- )
- )
- );
- callback({
- data: clean_response,
- recordsTotal: response["num-records"],
- recordsFiltered: response["filtered-records"],
- });
- },
- error: function (request, status, error) {
- showToast(error, "error");
- },
- });
- },
- });
- // Event listener for the select box
- $("#unitFilterOptions").change(function () {
- unit = this.value;
- table.api().ajax.reload();
- });
- });
- </script>
- {% block paginate_tables_script %} {{ super() }} {% endblock %}
- {% endblock %}
|