Change Dashboard Time

I have the following doubt, is it possible to change the dashboard time from a button inside a custom html block?, or change the generation and duration of a block through some command sent from another block?

I made an example code where I acquire the dashboard.time but I don’t know how to change this parameter, is it possible to do that?

Greetings @Lucas_Pinheiro !

The following should generate a date/time entry field in your Custom HTML Block, which, upon clicking Submit, sets the entered time as the dashboard time and refreshes your browser window:

<form method="get" id="myForm">
  <label for="time">Time</label>
  <input type="datetime-local" id="time">
  <button type="submit">Submit</button>
</form>
<script>
  let myDashboard;
  DashboardBlock.on('change', ({ dashboard }) => {
    myDashboard = dashboard;
  });
  document.getElementById('myForm').addEventListener('submit', (e) => {
    e.preventDefault();
    const time = Date.parse(document.getElementById('time').value);
    window.top.location.href = `/dashboards/${myDashboard.id}?t=${time}`;
  });

</script>

Which should look something similar to this:

Let us know if this works for your use-case!

(Kudos to @Dylan_Schuster for the code!)

This worked perfectly to change the time inside a dashboard, but I think I might have gotten a little confused, I thought that by changing this time my dashboard configured inside an end point would also be changed, but what happens is a change in the end point link by unconfiguring the path, is it possible to do something similar but to change the time of a dashboard configured within an experience page?

For an Experience page, you’ll want to configure the Dashboard Time Settings of the page to reference the time variable from the Custom HTML Block.

First, edit the Custom HTML Block code posted in my reply above to remove the dashboard ID parameter, since that’s irrelevant for Experience pages. As before, we’re writing time to the URL with variable t:

<form method="get" id="myForm">
  <label for="time">Time</label>
  <input type="datetime-local" id="time">
  <button type="submit">Submit</button>
</form>
<script>
  let myDashboard;
  DashboardBlock.on('change', ({ dashboard }) => {
    myDashboard = dashboard;
  });
  document.getElementById('myForm').addEventListener('submit', (e) => {
    e.preventDefault();
    const time = Date.parse(document.getElementById('time').value);
    window.top.location.href = `?t=${time}`;
  });

</script>

Then, in the relevant Experience page, set the Dashboard Time Settings to {{request.query.t}}:

This should reload the Experience page with the date/time value entered. Let us know if you have any other questions!

Thank you so much for your help. I have a doubt:
The purpose of the code that i am developing, is a custom range data filter, and for my task, I’m thinking in colect the “timeEnd” and “timeStart” string from url, but the reference code taking from Mozilla Developer is not working.
Below is the exemplo code that doesn’t work.

<form method="get" id="myForm">
    <label for="time">Time</label>
    <input type="datetime-local" id="timeStart">
    <input type="datetime-local" id="timeEnd">
    <button type="submit">Submit</button>
</form>
    <div id="urlSearch"></div>
    <div id="url"></div>

<script>
        let myDashboard;
        const url = new URL(window.location.href);
        console.log(window.location.href);
  

        function extractUrlSearchParams(url) {
            const t = url.searchParams.get("t");
            const ts = url.searchParams.get("ts");
            document.getElementById('urlSearch').innerHTML = `t=${t} ,ts=${ts}`;
            document.getElementById('url').innerHTML = url.href;    
        }
        extractUrlSearchParams(url);


        DashboardBlock.on('change', ({ dashboard }) => {
            myDashboard = dashboard;
            setCurrentTime();
        });

        function setCurrentTime() {
            const currentTime = new Date(myDashboard.time);
            document.getElementById('timeStart').value = currentTime.toISOString().slice(0, 16);
            document.getElementById('timeEnd').value = currentTime.toISOString().slice(0, 16);
        }

        document.getElementById('myForm').addEventListener('submit', (e) => {
            e.preventDefault();
            const timeStart = Date.parse(document.getElementById('timeStart').value);
            const timeEnd = Date.parse(document.getElementById('timeEnd').value);
            window.top.location.href = `?t=${timeEnd}&ts=${timeStart}`;
        });

 
</script>

Can you elaborate on how it is not working? What behavior are you seeing vs. what behavior are you expecting? And is this being used in an Experience Dashboard, a dashboard in the Losant user interface, or both?

Running your code, I see that window.location.href is returning the URL of the sandboxed iframe in which the Custom HTML Block is running, which is just about:srcdoc. You are probably trying to access the parent frame’s URL, which would normally be accessible at window.top.location.href, but that is blocked by the security policy we have applied to the iframe.

So, you will need to resolve these values as they’re passed in through other means. One of them - your end time - can come from dashboard.time, which is available in the callback that fires within the block. The other would have to be stored in a number context variable, which would then also be exposed through the callback.

I think I ended up following the wrong path because what I wanted was to get the iframe reference url where the url would have the timeStart & timeEnd values of the query. After some studies in the documentation provided by you and the content of the forum I am trying another approach, which is through an AJAX request using the GET method to obtain the query value with a given beginning and end. I developed a logic to make the API request, and I was successful in the query as shown below. but now I don’t know how I should proceed so that the values of this api query result are assigned to my custom htlm block, should I modify something in the workflow? I just want the result of this query to be displayed in the console.log at least, or in a field. I wonder if you can help me considering this context.

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>

<form id="target" style="padding:10px;">
  <div class="form-group">
    <label for="value-1">Value 1</label>
    <input type="text" class="form-control" name="value-1" id="value-1" placeholder="Value 1">
  </div>
  <div id="success" class="alert alert-success" role="alert">Success!</div>
  <div id="error" class="alert alert-danger" role="alert">Error!</div>
  <button type="submit" class="btn btn-default">Submit</button>
</form>

<script>
  $('#success').hide();
  $('#error').hide();

  $("#target").submit(function(event) {
    event.preventDefault();

    let deviceId = DashboardBlock.input.ctx['deviceId-0'];
    console.log(deviceId);
    const url = `https://645d4d70c75c458ed63d441c.onlosant.com/api/receive/${deviceId}`;

    let body = {
      deviceId,
      startDate: moment()
        .startOf('month')
        .startOf('day')
        .unix() * 1000,
      endDate: moment().endOf('day').unix() * 1000,
      resolution: 3600000,
    };

    $.ajax({
      url: url,
      type: 'GET',
      data: body,
      contentType: 'application/json',
      dataType: 'json',
      beforeSend: appendAuth,
      error: () => { showMessage('#error') },
      success: () => { showMessage('#success') }
    });
	});
  
  let showMessage = (id) => {
    $(id).show();
    setTimeout(() => { $(id).hide(); }, 5000);
  };
  
  let appendAuth = (xhr) => {
    let username = 'admin'; // TODO: change
    let password = 'admin'; // TODO: change
    xhr.setRequestHeader('Authorization', 'Basic ' + btoa(username + ':' + password));
  };
</script>

I don’t know how I should proceed so that the values of this api query result are assigned to my custom htlm block

Reading your code, you are making the request but are not doing anything with the response from the server … You’ll need to assign that value to a local variable or pass it into another function in the $.ajax Promise chain. Check out jQuery’s documentation for more information (the jqXHR.done section). Or, alternatively, you could use the browser’s native Fetch API instead.

Good morning, analyzing the documentation that you sent, I tried to produce a new code, but it seems that the problem is in the api request, I am not getting a return but an error message when I look at the browser’s developer mode network “request failed”, I tried to link an api token to the request and even so I was not successful, my workflow continues with the one shown above where the result of the API appears in the debug, I even tried to add the replay endpoint but I was not successful in the response to the request, it still fails

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.17.15/lodash.min.js"></script>

<form id="target" style="padding:10px;">
  <button type="submit" class="btn btn-default">Submit</button>
</form>

<script>
	var aggregations = { '3600000': 'DD/MM/YYYY HH:mm', '86400000': 'DD/MM/YYYY', '2592000000': 'MM/YYYY' };

	const HEADERS = JSON.parse(DashboardBlock.input.ctx.headers);
	const HOST = HEADERS.host;
	let deviceId = DashboardBlock.input.ctx['deviceId-0'];

	$("#target").submit(function( event ) {
		event.preventDefault();

		const url = `https://${HOST}/api/receive/${deviceId}`;

		let body = {
			deviceId,
			startDate: moment()
			.startOf('month')
			.startOf('day')
			.unix() * 1000,
			endDate: moment().endOf('day').unix() * 1000,
			resolution: 3600000,
		};

		let jqxhr = $.ajax({
			url: url,
			type: 'GET',
			data: body,
			contentType: 'application/json',
			dataType: 'json',
			beforeSend: function (xhr) {
				xhr.setRequestHeader('Authorization', 'Bearer ' + DashboardBlock.input.ctx.authorization);
			}
		});

		jqxhr.done((data) => {
		  console.log("Success");

			let processedData = [];

			$.each(data.points, (index, value) => {
				value.time = moment.utc(value.time).subtract(1, 'hours').format();
			});

			var grouppedItems = _.groupBy(data.points, function(item) {
				return moment(item.time).format(aggregations[$('#aggregation').val().trim()])
			});

			console.log('Groupped Items: ', grouppedItems);

			Object.keys(grouppedItems).forEach((item) => {
				let valueEnergAtiv = grouppedItems[item].reduce((acc, val) => acc + Number(val.energAtiv), 0);
				processedData.push({energAtiv: valueEnergAtiv, time: item});
			});
		});

		jqxhr.fail((jqXHR, textStatus) => {
			console.log("Request failed: " + textStatus);
		});
	});
</script>

An error like that indicates an issue in the workflow backing your request. At this point I recommend the following resources before even trying to interact with this API from your Custom HTML Block:

I don’t know where I could be going wrong, I configured the workflow as explained in the api experience module.
• I created an experience endpoint of type get with custom authentication
• I created a workflow for the endpoint

• The first node is the endpoint
• The second node is one of device:get that receives the device id through the endpoint request (ID Template: {{data.params.deviceId}})
• Third one in Losant API with Resource and Action : Data: Time Series Query using

Json template ({
“aggregation”: “NONE”,
“attributes”: [
“energAtiv”
],
“deviceIds”: [
“{{data.params.deviceId}}”
],
“start”:{{data.query.startDate}},
“end”:{{data.query.endDate}}
}) where the values are sent through the same endpoint, after that I defined Payload Path to Store Response as apiResult.
• The last block before the debug block was the replay endpoint block, with Reply Type: custom and which uses the Response Body Payload Path as the apiResult to return the query to the endpoint that requested it.

What are you seeing in the Workflow Errors panel? What kind of messages are you getting in the live debug panel when requests hit your endpoint?

I took a look in your account … Here’s your issue:

You are removing the data.replyId property in your Mutate Node. That value is essential for the Endpoint Reply Node to know which of the open Experience Endpoint requests to send your response data to.

You will need to keep that value in place or move it to a different spot on your payload and then reference that new payload path for the value at the bottom of your Endpoint Reply Node config.