Loading src/webui/service/slice/routes.py +6 −4 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ # import grpc from flask import current_app, redirect, render_template, Blueprint, flash, session, url_for from common.proto.context_pb2 import ContextId, Slice, SliceId, SliceList, Connection from common.proto.context_pb2 import ContextId, Slice, SliceId, SliceList, Connection, SliceStatusEnum from context.client.ContextClient import ContextClient #from slice.client.SliceClient import SliceClient Loading Loading @@ -48,7 +48,7 @@ def home(): slices = [] context_not_found = True context_client.close() return render_template('slice/home.html',slices=slices, context_not_found=context_not_found) return render_template('slice/home.html',slices=slices, context_not_found=context_not_found, sse=SliceStatusEnum) # #@slice.route('add', methods=['GET', 'POST']) Loading @@ -68,16 +68,18 @@ def detail(slice_uuid: str): request: SliceId = SliceId() request.slice_uuid.uuid = slice_uuid request.context_id.context_uuid.uuid = context_uuid req = ContextId() req.context_uuid.uuid = context_uuid try: context_client.connect() response: Slice = context_client.GetSlice(request) #services: Service = context_client.ListServices(request) services = context_client.ListServices(req) context_client.close() except Exception as e: flash('The system encountered an error and cannot show the details of this slice.', 'warning') current_app.logger.exception(e) return redirect(url_for('slice.home')) return render_template('slice/detail.html', slice=response) return render_template('slice/detail.html', slice=response, sse=SliceStatusEnum, services=services) # #@slice.get('<path:slice_uuid>/delete') #def delete(slice_uuid: str): Loading src/webui/service/templates/service/detail.html +60 −3 Original line number Diff line number Diff line Loading @@ -63,9 +63,12 @@ <td> <a href="{{ url_for('device.detail', device_uuid=endpoint.device_id.device_uuid.uuid) }}"> {{ endpoint.device_id.device_uuid.uuid }} <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/> <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z" /> <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z" /> </svg> </a> </td> Loading @@ -79,13 +82,18 @@ <table class="table table-striped table-hover"> <thead> <tr> <th scope="col">Kind</th> <th scope="col">Type</th> <th scope="col">Value</th> </tr> </thead> <tbody> {% for constraint in service.service_constraints %} {% if constraint.WhichOneof('constraint')=='custom' %} <tr> <td> Custom </td> <td> {{ constraint.custom.constraint_type }} </td> Loading @@ -95,6 +103,55 @@ </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='endpoint_location' %} <tr> <td> Endpoint Location </td> <td> {{ constraint.endpoint_location.endpoint_id.device_id.device_uuid.uuid }} / {{ constraint.endpoint_location.endpoint_id.endpoint_uuid.uuid }} </td> <td> <ul> {{ constraint.endpoint_location.location }} </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='endpoint_priority' %} <tr> <td> Endpoint Priority </td> <td> {{ constraint.endpoint_priority.endpoint_id.device_id.device_uuid.uuid }} / {{ constraint.endpoint_priority.endpoint_id.endpoint_uuid.uuid }} </td> <td> <ul> {{ constraint.endpoint_priority.priority }} </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='sla_availability' %} <tr> <td> SLA Availability </td> <td> / </td> <td> <ul> <li> num_disjoint_paths: {{ constraint.sla_availability.num_disjoint_paths }} </li> <li> all_active: {{ constraint.sla_availability.all_active }} </li> </ul> </td> </tr> {% endif %} {% endfor %} </tbody> </table> Loading src/webui/service/templates/slice/detail.html +139 −38 Original line number Diff line number Diff line Loading @@ -19,10 +19,18 @@ {% block content %} <h1>Slice {{ slice.slice_id.slice_uuid.uuid }} </h1> <div class="row mb-3"> <div class="col-sm-3"> <button type="button" class="btn btn-success" onclick="window.location.href='{{ url_for('slice.home') }}'"> <i class="bi bi-box-arrow-in-left"></i> Back to slice list </button> </div> </div> <div class="row mb-3"> <div class="col-sm-4"> <b>UUID: </b> {{ slice.slice_id.slice_uuid.uuid }}<br><br> <b>Status: </b> {{ slice.slice_status.slice_status }}<br><br> <b>Status: </b> {{ sse.Name(slice.slice_status.slice_status).replace('SLICESTATUS_', '') }}<br><br> </div> <div class="col-sm-8"> <table class="table table-striped table-hover"> Loading Loading @@ -56,18 +64,22 @@ </table> </div> </div> <b>Constraints:</b> <table class="table table-striped table-hover"> <thead> <tr> <th scope="col">Kind</th> <th scope="col">Type</th> <th scope="col">Value</th> </tr> </thead> <tbody> {% for constraint in slice.slice_constraints %} {% if constraint.WhichOneof('constraint')=='custom' %} <tr> <td> Custom </td> <td> {{ constraint.custom.constraint_type }} </td> Loading @@ -77,38 +89,127 @@ </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='endpoint_location' %} <tr> <td> Endpoint Location </td> <td> {{ constraint.endpoint_location.endpoint_id.device_id.device_uuid.uuid }} / {{ constraint.endpoint_location.endpoint_id.endpoint_uuid.uuid }} </td> <td> <ul> {{ constraint.endpoint_location.location }} </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='endpoint_priority' %} <tr> <td> Endpoint Priority </td> <td> {{ constraint.endpoint_priority.endpoint_id.device_id.device_uuid.uuid }} / {{ constraint.endpoint_priority.endpoint_id.endpoint_uuid.uuid }} </td> <td> <ul> {{ constraint.endpoint_priority.priority }} </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='sla_availability' %} <tr> <td> SLA Availability </td> <td> / </td> <td> <ul> <li> num_disjoint_paths: {{ constraint.sla_availability.num_disjoint_paths }} </li> <li> all_active: {{ constraint.sla_availability.all_active }} </li> </ul> </td> </tr> {% endif %} {% endfor %} </tbody> </table> <!-- <b>Configurations:</b> <table class="table table-striped table-hover"> <thead> <tr> <th scope="col">Service Id</th> <th scope="col">Sub-slice</th> <th scope="col">Key</th> <th scope="col">Value</th> </tr> </thead> <tbody> {% for connections in connections.connections %} {% for config in slice.slice_config.config_rules %} {% if config.WhichOneof('config_rule') == 'custom' %} <tr> <td> {{ connections.connection_id.connection_uuid.uuid }} {{ config.custom.resource_key }} </td> <td> {{ connections.sub_service_ids|map(attribute='service_uuid')|map(attribute='uuid')|join(', ') }} <ul> {% for key, value in (config.custom.resource_value | from_json).items() %} <li><b>{{ key }}:</b> {{ value }}</li> {% endfor %} </ul> </td> {% for i in range(connections.path_hops_endpoint_ids|length) %} </tr> {% endif %} {% endfor %} </tbody> </table> <div class="row mb-2"> <div class="col-sm-6"> <table class="table table-striped table-hover"> <thead> <tr> <th scope="col">Service Id</th> </tr> </thead> <tbody> {% for services in services.services %} <tr> <td> {{ connections.path_hops_endpoint_ids[i].device_id.device_uuid.uuid }} / {{ connections.path_hops_endpoint_ids[i].endpoint_uuid.uuid }} <a href="{{ url_for('service.detail', service_uuid=services.service_id.service_uuid.uuid) }}"> {{ services.service_id.service_uuid.uuid }} <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/> <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/> </svg> </a> </td> </tr> {% endfor %} </tbody> </table> </div> <div class="col-sm-6"> <table class="table table-striped table-hover"> <thead> <tr> <th scope="col">Sub-slice</th> </tr> </thead> <tbody> {% for services in services.services %} <tr> <td> {{ services.sub_slice_ids|map(attribute='slice_uuid')|map(attribute='uuid')|join(', ') }} </td> </tr> {% endfor %} </tbody> </table> --> </table> </div> </div> {% endblock %} No newline at end of file src/webui/service/templates/slice/home.html +15 −5 Original line number Diff line number Diff line Loading @@ -19,6 +19,14 @@ {% block content %} <h1>Slice</h1> <div class="row"> <div class="col"> {{ slices | length }} slices found in context <i>{{ session['context_uuid'] }}</i> </div> </div> <table class="table table-striped table-hover"> <thead> Loading @@ -35,15 +43,17 @@ {% for slice in slices %} <tr> <td> <!-- <a href="{{ url_for('slice.detail', slice_uuid=slice.slice_id.slice_uuid.uuid) }}"> --> {{ slice.slice_id.slice_uuid.uuid }} <!-- </a> --> </td> <td> {{ slice.slice_endpoint_ids }} {% for i in range(slice.slice_endpoint_ids|length) %} <ul> <li> {{ slice.slice_endpoint_ids[i].device_id.device_uuid.uuid }} / {{ slice.slice_endpoint_ids[i].endpoint_uuid.uuid }} </li> </ul> {% endfor %} </td> <td> {{ slice.slice_status }} {{ sse.Name(slice.slice_status.slice_status).replace('SLICESTATUS_', '') }} </td> <td> <a href="{{ url_for('slice.detail', slice_uuid=slice.slice_id.slice_uuid.uuid) }}"> Loading Loading
src/webui/service/slice/routes.py +6 −4 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ # import grpc from flask import current_app, redirect, render_template, Blueprint, flash, session, url_for from common.proto.context_pb2 import ContextId, Slice, SliceId, SliceList, Connection from common.proto.context_pb2 import ContextId, Slice, SliceId, SliceList, Connection, SliceStatusEnum from context.client.ContextClient import ContextClient #from slice.client.SliceClient import SliceClient Loading Loading @@ -48,7 +48,7 @@ def home(): slices = [] context_not_found = True context_client.close() return render_template('slice/home.html',slices=slices, context_not_found=context_not_found) return render_template('slice/home.html',slices=slices, context_not_found=context_not_found, sse=SliceStatusEnum) # #@slice.route('add', methods=['GET', 'POST']) Loading @@ -68,16 +68,18 @@ def detail(slice_uuid: str): request: SliceId = SliceId() request.slice_uuid.uuid = slice_uuid request.context_id.context_uuid.uuid = context_uuid req = ContextId() req.context_uuid.uuid = context_uuid try: context_client.connect() response: Slice = context_client.GetSlice(request) #services: Service = context_client.ListServices(request) services = context_client.ListServices(req) context_client.close() except Exception as e: flash('The system encountered an error and cannot show the details of this slice.', 'warning') current_app.logger.exception(e) return redirect(url_for('slice.home')) return render_template('slice/detail.html', slice=response) return render_template('slice/detail.html', slice=response, sse=SliceStatusEnum, services=services) # #@slice.get('<path:slice_uuid>/delete') #def delete(slice_uuid: str): Loading
src/webui/service/templates/service/detail.html +60 −3 Original line number Diff line number Diff line Loading @@ -63,9 +63,12 @@ <td> <a href="{{ url_for('device.detail', device_uuid=endpoint.device_id.device_uuid.uuid) }}"> {{ endpoint.device_id.device_uuid.uuid }} <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/> <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z" /> <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z" /> </svg> </a> </td> Loading @@ -79,13 +82,18 @@ <table class="table table-striped table-hover"> <thead> <tr> <th scope="col">Kind</th> <th scope="col">Type</th> <th scope="col">Value</th> </tr> </thead> <tbody> {% for constraint in service.service_constraints %} {% if constraint.WhichOneof('constraint')=='custom' %} <tr> <td> Custom </td> <td> {{ constraint.custom.constraint_type }} </td> Loading @@ -95,6 +103,55 @@ </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='endpoint_location' %} <tr> <td> Endpoint Location </td> <td> {{ constraint.endpoint_location.endpoint_id.device_id.device_uuid.uuid }} / {{ constraint.endpoint_location.endpoint_id.endpoint_uuid.uuid }} </td> <td> <ul> {{ constraint.endpoint_location.location }} </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='endpoint_priority' %} <tr> <td> Endpoint Priority </td> <td> {{ constraint.endpoint_priority.endpoint_id.device_id.device_uuid.uuid }} / {{ constraint.endpoint_priority.endpoint_id.endpoint_uuid.uuid }} </td> <td> <ul> {{ constraint.endpoint_priority.priority }} </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='sla_availability' %} <tr> <td> SLA Availability </td> <td> / </td> <td> <ul> <li> num_disjoint_paths: {{ constraint.sla_availability.num_disjoint_paths }} </li> <li> all_active: {{ constraint.sla_availability.all_active }} </li> </ul> </td> </tr> {% endif %} {% endfor %} </tbody> </table> Loading
src/webui/service/templates/slice/detail.html +139 −38 Original line number Diff line number Diff line Loading @@ -19,10 +19,18 @@ {% block content %} <h1>Slice {{ slice.slice_id.slice_uuid.uuid }} </h1> <div class="row mb-3"> <div class="col-sm-3"> <button type="button" class="btn btn-success" onclick="window.location.href='{{ url_for('slice.home') }}'"> <i class="bi bi-box-arrow-in-left"></i> Back to slice list </button> </div> </div> <div class="row mb-3"> <div class="col-sm-4"> <b>UUID: </b> {{ slice.slice_id.slice_uuid.uuid }}<br><br> <b>Status: </b> {{ slice.slice_status.slice_status }}<br><br> <b>Status: </b> {{ sse.Name(slice.slice_status.slice_status).replace('SLICESTATUS_', '') }}<br><br> </div> <div class="col-sm-8"> <table class="table table-striped table-hover"> Loading Loading @@ -56,18 +64,22 @@ </table> </div> </div> <b>Constraints:</b> <table class="table table-striped table-hover"> <thead> <tr> <th scope="col">Kind</th> <th scope="col">Type</th> <th scope="col">Value</th> </tr> </thead> <tbody> {% for constraint in slice.slice_constraints %} {% if constraint.WhichOneof('constraint')=='custom' %} <tr> <td> Custom </td> <td> {{ constraint.custom.constraint_type }} </td> Loading @@ -77,38 +89,127 @@ </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='endpoint_location' %} <tr> <td> Endpoint Location </td> <td> {{ constraint.endpoint_location.endpoint_id.device_id.device_uuid.uuid }} / {{ constraint.endpoint_location.endpoint_id.endpoint_uuid.uuid }} </td> <td> <ul> {{ constraint.endpoint_location.location }} </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='endpoint_priority' %} <tr> <td> Endpoint Priority </td> <td> {{ constraint.endpoint_priority.endpoint_id.device_id.device_uuid.uuid }} / {{ constraint.endpoint_priority.endpoint_id.endpoint_uuid.uuid }} </td> <td> <ul> {{ constraint.endpoint_priority.priority }} </ul> </td> </tr> {% endif %} {% if constraint.WhichOneof('constraint')=='sla_availability' %} <tr> <td> SLA Availability </td> <td> / </td> <td> <ul> <li> num_disjoint_paths: {{ constraint.sla_availability.num_disjoint_paths }} </li> <li> all_active: {{ constraint.sla_availability.all_active }} </li> </ul> </td> </tr> {% endif %} {% endfor %} </tbody> </table> <!-- <b>Configurations:</b> <table class="table table-striped table-hover"> <thead> <tr> <th scope="col">Service Id</th> <th scope="col">Sub-slice</th> <th scope="col">Key</th> <th scope="col">Value</th> </tr> </thead> <tbody> {% for connections in connections.connections %} {% for config in slice.slice_config.config_rules %} {% if config.WhichOneof('config_rule') == 'custom' %} <tr> <td> {{ connections.connection_id.connection_uuid.uuid }} {{ config.custom.resource_key }} </td> <td> {{ connections.sub_service_ids|map(attribute='service_uuid')|map(attribute='uuid')|join(', ') }} <ul> {% for key, value in (config.custom.resource_value | from_json).items() %} <li><b>{{ key }}:</b> {{ value }}</li> {% endfor %} </ul> </td> {% for i in range(connections.path_hops_endpoint_ids|length) %} </tr> {% endif %} {% endfor %} </tbody> </table> <div class="row mb-2"> <div class="col-sm-6"> <table class="table table-striped table-hover"> <thead> <tr> <th scope="col">Service Id</th> </tr> </thead> <tbody> {% for services in services.services %} <tr> <td> {{ connections.path_hops_endpoint_ids[i].device_id.device_uuid.uuid }} / {{ connections.path_hops_endpoint_ids[i].endpoint_uuid.uuid }} <a href="{{ url_for('service.detail', service_uuid=services.service_id.service_uuid.uuid) }}"> {{ services.service_id.service_uuid.uuid }} <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/> <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/> </svg> </a> </td> </tr> {% endfor %} </tbody> </table> </div> <div class="col-sm-6"> <table class="table table-striped table-hover"> <thead> <tr> <th scope="col">Sub-slice</th> </tr> </thead> <tbody> {% for services in services.services %} <tr> <td> {{ services.sub_slice_ids|map(attribute='slice_uuid')|map(attribute='uuid')|join(', ') }} </td> </tr> {% endfor %} </tbody> </table> --> </table> </div> </div> {% endblock %} No newline at end of file
src/webui/service/templates/slice/home.html +15 −5 Original line number Diff line number Diff line Loading @@ -19,6 +19,14 @@ {% block content %} <h1>Slice</h1> <div class="row"> <div class="col"> {{ slices | length }} slices found in context <i>{{ session['context_uuid'] }}</i> </div> </div> <table class="table table-striped table-hover"> <thead> Loading @@ -35,15 +43,17 @@ {% for slice in slices %} <tr> <td> <!-- <a href="{{ url_for('slice.detail', slice_uuid=slice.slice_id.slice_uuid.uuid) }}"> --> {{ slice.slice_id.slice_uuid.uuid }} <!-- </a> --> </td> <td> {{ slice.slice_endpoint_ids }} {% for i in range(slice.slice_endpoint_ids|length) %} <ul> <li> {{ slice.slice_endpoint_ids[i].device_id.device_uuid.uuid }} / {{ slice.slice_endpoint_ids[i].endpoint_uuid.uuid }} </li> </ul> {% endfor %} </td> <td> {{ slice.slice_status }} {{ sse.Name(slice.slice_status.slice_status).replace('SLICESTATUS_', '') }} </td> <td> <a href="{{ url_for('slice.detail', slice_uuid=slice.slice_id.slice_uuid.uuid) }}"> Loading