﻿<?xml version="1.0" encoding="utf-8"?>
<EXOconfigData format="Rwav" version="2019.4.100.249">
  <Object type="View">
    <Attribute name="Name">PageViewCounter</Attribute>
    <Attribute name="Width">640</Attribute>
    <Attribute name="Height">480</Attribute>
    <Attribute name="Zoom">100%</Attribute>
    <Attribute name="ScaleValue">1.00</Attribute>
    <Attribute name="OnOpen">// The dot (.) before the server-side function name implicitly adds the current path
// (where the view resides).
//
// 'getPageViews' doesn't take any arguments but we're still required to pass an empty object ({})
this.view.call('.getPageViews', {}).then((result) =&gt; {

    // Get the result (number) or default to 0 if the result was null/undefined.
    let pageViews = result || 0;
    
    // Increase the value by one
    pageViews++;
    
    // Set the new pageViews value to the Numeric
    this.view.NumberOfPageViews.value(pageViews);
    
    // Save the new value to the state file
    this.view.call('.setPageViews', { pageViews }).then((result) =&gt; {
        // console.log's in client-side code will appear in the browser dev-tools console
        console.log("New page view value saved");
    });
});
</Attribute>
    <Attribute name="ServerSideFunctionRPC">accounts.%account%.services.ssf.execute</Attribute>
    <Attribute name="ServerSideJS">// We register two server-side functions and return them (to the server-side context)
return {
    // All registered functions must be async and they all must
    // declare 'args' and 'callInfo' as params.
    
    getPageViews: async (args, callInfo) =&gt; {
        // console.log's in server-side code can be seen by opening
        // the Arrigo Log Viewer in Project Builder:
        // * Select the 'Arrigo BMS' node
        // * Open the Tools menu and select 'Arrigo - View logs'
        // * Enter the number for 'arrigo-services-ssf' and press Enter
        console.log("Getting page views");

        // Just get the single value from the default state file for the path.
        // These files live in Proj:\Arrigo\state
        return await callInfo.context.state.get();
    },
    // 'getPageViews' can now be invoked from client-side code
    
    setPageViews: async (args, callInfo) =&gt; {
        // Set a single value in the default state file for the path.
        // 'pageViews' is the named arg we passed from the client-side code,
        // so therefor it can be found in the args object.
        return await callInfo.context.state.set({data: args.pageViews});
    }
    // 'setPageViews' can now be invoked from client-side code
}</Attribute>
    <Object type="ArgumentsFolder">
      <Attribute name="Name">Arguments</Attribute>
      <Attribute name="Comment">This folder contains all arguments for the view. The arguments can be sent to the view when it is used in run-time.</Attribute>
    </Object>
    <Object type="ElementsFolder">
      <Attribute name="Name">Elements</Attribute>
      <Attribute name="Comment">This folder contains all visual elements for the view.</Attribute>
      <Object type="Numeric">
        <Attribute name="Name">NumberOfPageViews</Attribute>
        <Attribute name="Left">140</Attribute>
        <Attribute name="Top">20</Attribute>
      </Object>
    </Object>
  </Object>
</EXOconfigData>