How to consume a REST API properly on a multi page website

What is the best approach or best practice to consume a REST API within a multi-paged website on client side?

Lets assume I have the following REST API defined

/product -> all products, high level information 
/product/{id} -> detailed product information about product with given id

Further assume that my website has two .html pages, index.html and detail.html.

Inside the index.html I would query all products with high level information from my REST API with an AJAX call in Javascript. I then alter a table element inside the index.html page with the received JSON and display the high level information of each product inside this table.

Each table entry also has a link to the detailed product information, e.g. url/products/42.

Now to the interesting part. If I press the link of one specific product and want to show the detail.html page with detailed information about the pressed product id, how to I tell the Javascript inside detail.html which product the user pressed and is to be queried from the REST API?

I know how I perform these REST API calls in a native mobile app, since I always know, which element a user has pressed. I am a little bit lost how to do this on a multi paged website application.

Thanks to enrich my mind 🙂

How to get mapUrl of a spot knowing lat and lng of a spot? Using google-map-react library. Is there a library fixture or maybe google Api?

I have typescript + React app. I’m using google-map-react library. It’s very easy to use and I love it. So far I was able embed a map and put a custom dot on a map of specific location. What I want is by clicking on this dot get a direction to this spot on google maps. I don’t care if google map will open in a new tab and so on and so far. What I’m thinking is by knowing lat and lng generate a link of this specific spot and redirect to it. But how to generate this link ?

Is there a library fixture or maybe google Api ?

VueJS – i can’t hide readmore button before or after reach the selected limit data to show in vuejs

i’m using vuejs2. Try to hide the button before or after reach the amount of value, but i can’t event get the data length to compare with limit. I try to re-assign it into an array, still not work cause the length is 1. Any idea how to do or different way to do that? Thanks

export default {
  name: 'SlideEvents',
  props: {
    dataEvents: {
      type: Array,
      default () {
        return []
      }
    }
  },
  data () {
    return {
      limit: 6
    }
  },
  components: {
    CardSlide
  },
  computed: {
    dataFilter () {
      if (this.dataEvents) {
        return this.dataEvents.slice(0, this.limit)
      } else {
        return this.dataEvents
      }
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<div class="container-fluid more-top">
    <div class="row">
      <div class="col-md-12">
        <div class="card box-simple border-0">
          <h2>Agenda Terbaru</h2>
          <div class="mt-5 mb-5">
            <div class="row row-cols-1 row-cols-md-3 g-5 mt-2 px-4">
            
              <CardSlide class="mb-4" v-for="each in dataFilter"
              :key="each.id"
              :content="each" />
            </div>
            <button @click="limit*=2">Show More</button>
          </div>
        </div>
      </div>
    </div>
  </div>

Trying to edit row’s in a HTML table using react.js

I have built a table in which user enter’s values in first three Cols and next four get’s calculated. Till here it is working Fine but when I change a respective value in a Col the corresponding Col’s calculated value does not change and the problem which arises after deleting is the row get’s deleted but it’s value shift’s in the below row

  const row1 = [];
  const [row, setRow] = useState();
  const [NewRow2, setNewRow2] = useState([0, 1, 2, 3, 4]);
  const [allRowsAdded, updateAllRows] = useState(5);

  const [IntensificationRatio, setIntensificationRatio] = useState()

  const [editFormData, setEditFormData] = useState({
    Injection_Speed: "",
    Fill_Time: "",
    Peak_Inj_Press: "",
    Viscosity: "",
    Shear_Rate: ""
  })

  const [isRowId, setIsRowId] = useState(null)

  const handleEditFormChange = (event) => {
    event.preventDefault();
    const fieldName = event.target.getAttribute("name");
    const fieldValue = event.target.value;
    const newFormData = { ...editFormData };
    newFormData[fieldName] = fieldValue;
    setEditFormData(newFormData);
  }

  const handleEditFormSubmit = (event) => {
    event.preventDefault();
    const editedValue = {
      id: isRowId,
      Injection_Speed: editFormData.Injection_Speed,
      Fill_Time: editFormData.Fill_Time,
      Peak_Inj_Press: editFormData.Peak_Inj_Press,
      Viscosity: editFormData.Fill_Time * editFormData.Peak_Inj_Press * IntensificationRatio,
      Shear_Rate: 1 / editFormData.Fill_Time,
    }
    const newValues = [...NewRow2];
    const index = NewRow2.findIndex((value) => value === isRowId)
    newValues[index] = editedValue;
    setNewRow2(newValues);
    console.log(newValues)

  }

In this part of code “row1” array and “row” variable is to serve the purpose of increasing row’s as per user’s need. “NewRow2” is the actual array using which row’s are created and values are entered in them. “allRowsAdded” is to keep the track of row’s getting added so that the “id” doesn’t clash. The “IntensificationRatio” is needed to Calculate Viscosity as you can see in the ” handleEditFormSubmit” function.

<tr key={rowId} onClick={() => setId(rowId)}>

<td> {rowId} </td>

<td> <input type='text' className="form-control" defaultValue={NewRow2[rowId].Injection_Speed} name="Injection_Speed" onChange={handleEditFormChange} /> </td>

<td> <input type='text' className="form-control" defaultValue={NewRow2[rowId].Fill_Time} name="Fill_Time" onChange={handleEditFormChange} /></td>

<td><input type='text' className="form-control" defaultValue={NewRow2[rowId].Peak_Inj_Press} name="Peak_Inj_Press" onChange={handleEditFormChange} /> </td>

<td> <input type='text' className="form-control" name="Viscosity" value={isNaN(Math.round(element.Viscosity)) ? '-' : Math.round(element.Viscosity)} readOnly /> </td>

<td>  <input type='text' className="form-control" name="Shear_Rate" value={isNaN(Number(element.Shear_Rate)) ? '-' : Number(element.Shear_Rate).toFixed(3)} readOnly /> </td>

<td> <input type='text' name="Absolute_Viscosity" value={rowId === 0 ? '-' : (isNaN(Math.round(NewRow2[rowId - 1].Viscosity - NewRow2[rowId].Viscosity)) ? '-' : Math.round(NewRow2[rowId - 1].Viscosity - NewRow2[rowId].Viscosity))} className="form-control" readOnly /></td>

<td> <input type='text' name="Drop_Viscosity" value={rowId === 0 ? '-' : (isNaN(Number(((NewRow2[rowId - 1].Viscosity - NewRow2[rowId].Viscosity) * 100) / (NewRow2[rowId - 1].Viscosity))) ? '-' : (Number(((NewRow2[rowId - 1].Viscosity - NewRow2[rowId].Viscosity) * 100) / (NewRow2[rowId - 1].Viscosity))).toFixed(1))} className="form-control" readOnly /></td>

<td> <i className="fa fa-trash viscocity_icons" onClick={() => deleteRow2(element)}></i> </td>
</tr>

This is the Table Row with Table data’s 1st Three input field’s are editable and hence contain a “onChange” and the rest 4 are readOnly.
What changes should i make so that i can edit and delete.

CodeSandBox Link :

https://codesandbox.io/s/solitary-architecture-zur17?file=/src/App.js:77-111

Change between styles according to active

I’m trying to switch between list view and grid view using the code below:

// List view
<button className={styles.viewBtn `${view === 'list' ? 'active': ''}`} onClick={() => setView('list')} type="button" title="List View">
     // <svg>
</button>

// Grid view
<button className={styles.viewBtn `${view === 'grid' ? 'active': ''}`} onClick={() => setView('grid')} type="button" title="Grid View">
    // <svg>
</button>

So to style the buttons I do import styles from ./styles.less and here’s my css for the buttons:

.viewBtn {
    width: 36px;
    height: 36px;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 6px;
    border-radius: 4px;
    background-color: transparent;
    border: none;
    color: var(--main-color);
    margin-left: 8px;
    transition: .2s;
    
    &.active {
      background-color:  rgba(195, 207, 244, 0.2);
      color: #fff;
    }
    
    &:not(.active):hover {
      background-color:  rgba(195, 207, 244, 0.1);
      color: #fff;
    }
}

How do I switch between .active and :not(.active) for the style of the buttons? And would .active work in React?

What is the correct way to test a contract that depends on another contract?

Test Code:

let pim = await PassiveIncomeMethod.new(
        u.admin.address,
        "Test Method",
        sf.host.address,
        sf.agreements.cfa.address,
        daix.address
    );

    app = await Proposal.new(
        "Test project",
        "Test description.",
        1000000,
        10000,
        pim.address,
        3600 * 3 // deadline of 3 days in seconds
    );

I am using truffle to try and test a contract “Proposal” that needs the address of another contract “PassiveIncomeMethod”. I’m trying to create a PassiveIncomeMethod contract and then hand off the address to Proposal but I’m unsure of how to correctly pass the address. I’m currently getting the error:

TypeError: Cannot read properties of undefined (reading 'address')
at appStatus (test/Proposal.test.js:137:49)
at Context.<anonymous> (test/Proposal.test.js:168:19)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (node:internal/process/task_queues:96:5)

How to stop nested elements getting split into individual elements?

I have a custom conversion for text to convert it into span elements, but this conversion is not able to handle the nested span elements inside the p tag.

This is the given HTML data, the span‘s are nested in this

<p style="font: 10pt Times New Roman, Times, Serif; margin: 0pt 0;" xvid="f5ea22ec52553bc61525766b631e126f" class="">
    <span xvid="d224e02f7a225aa9bdc51ec18daded3d" data-fact="619959c0062c677faebd7b57" conceptid="619959bc062c677faebd7a6f" xbrlid="rr:ProspectusDate" class="">
        <span xvid="2b80c95cd4b851345ba4c3fe6937d30b" class="wrapped manual-map" data-fact="619959c0062c677faebd7b55">November 1, 2021</span>
    </span>
</p>

Output i get from the editor,here the span‘s are split instead of being nested.

<p style="font: 10pt Times New Roman, Times, Serif; margin: 0pt 0;" xvid="f5ea22ec52553bc61525766b631e126f">
    <span xvid="2b80c95cd4b851345ba4c3fe6937d30b" data-fact="619959c0062c677faebd7b55" conceptid="619959bc062c677faebd7a6f" xbrlid="rr:ProspectusDate">November 1, 2021</span>
    <span xvid="d224e02f7a225aa9bdc51ec18daded3d" data-fact="619959c0062c677faebd7b57" conceptid="619959bc062c677faebd7a6f" xbrlid="rr:ProspectusDate">&nbsp;</span>
</p>
'

This the conversion i have written for the text,here the

 const allowedAttrModelView = {
      'xvid': 'xvid',
       ....etc
}
    for (const [modelAttr, viewAttr] of Object.entries(allowedAttrModelView)) {
      conversion.for("downcast").attributeToElement({
        model: {
          key: modelAttr,
          name: "$text",
        },
        view: (value, {writer}) => {
          const attrs = {};
          attrs[viewAttr] = value;
          console.log(attrs);
          return writer.createAttributeElement("span", attrs, {
            priority: 7,
          });
        },
        converterPriority: "highest",
      });
    }

navigation.addListener didFocus error when saving file in react native app

I am using the code below to reload a screen when each time it’s in focus. This works fine except when I make changes to the file during development then I get the error shown below the code example. Not sure if this matters since I won’t be saving the file while people are actually using the app. Can’t see pushing this out into production though with this issue, any help would be appreciated.

this.focusListener = navigation.addListener('didFocus', () => {

    fetchData();

});

Error message when saving file in development:

TypeError: undefined is not an object (evaluating '_this.focusListener = navigation.addListener('didFocus', function () {
        fetchData();
      })')

My app completely blows up and I have to reload it. Using Expo if that matters.

how to add reove active class on up and down arrow keys in react

i am tying to implement dropdown
enter image description here

here is the image

now i want to add active class to option 1 and on keypress event like up and down i want to move between options

here is what i have tried

  useEffect(() => {
    let btns = document.getElementsByClassName("list-item");
    console.log(btns[3]);
    for (var i = 0; i < btns.length; i++) {
      btns[0].classList.add("active");
      btns[i].addEventListener("keydown", function (e) {
        if (e.key === 38 || e.key === 40) {
          var current = document.getElementsByClassName("active");
          current[0].className = current[0].className.replace("active", "");
          this.className += "active";
        }
      });
    }

  });

here is how i am rendering dropdown list

  const options = ["Option1", "Option2", "Option3", "Option4"];

 {open && (
            <ul className="list" id="lists">
              {options.map((option, i) => (
                <li
                  onClick={() => {
                    setSelected(option);
                    setOpen(false);
                  }}
                  className="list-item"
                >
                  {option}
                </li>
              ))}
            </ul>
          )}

please help me i am stuck here from 2 days.
i can add active class to first option but it is not switching on up and down key press

thanks in advance

How to make one modal work for multiple button

It’s working but only in one button here’s my code. When i click at first button it showed up but when i click on the other buttons it doesnt show up. it seems that only at the first buttons its working. I also used the class to call the modal but it seems it also doesnt work.

<!DOCTYPE HTML>
<html>
<head>
    <title>Video Records</title>
    <style type="text/css">
        *{
            margin:0;
            padding: 0;
            box-sizing: border-box;
        }
        body{
            background-image: url(wallpaper.jpg) ;
            background-repeat: no-repeat;
            background-size: cover;
            font-family: sans-serif;

        }
        .table-container{
            padding: 0 10%;
            margin: 40px auto 0;
        }
        .heading{
            font-size: 40px;
            text-align: center;
            color:#FFFFFF;
            text-shadow: -2px -2px 0 #000, 2px -2px 0 #000, -2px 2px 0 #000, 2px 2px 0 #000;
            margin-bottom: 40px;
        }
        .table{
            width: 100%;
            border-collapse: separate;
            border-spacing: 0;
            box-shadow: 0 0 0 2px #FFD700;
            border-radius: 6px;
        }
        .table thead{
            background-color: #FFD700;

        }
        .table thead tr th{
            font-size: 14px;
            font-weight: medium;
            letter-spacing: 0.35px;
            color: #000000;
            opacity: 1;
            padding: 12px;
            vertical-align: top;
            border: 1px solid #000000;
        }
        .table tbody tr td{
            font-size: 14px;
            letter-spacing: 0.35px;
            font-weight: normal;
            color: #000000;
            background-color: white;
            padding: 8px;
            text-align: center;
            border: 1px solid #000000; 
        }
        table tr:first-child th:first-child,
        table.table tr:first-child {
        border-top-left-radius: 6px;
        }

        table tr:first-child th:last-child,
        table.table tr:first-child {
        border-top-right-radius: 6px;
        }

        table tr:last-child td:first-child {
        border-bottom-left-radius: 6px;
        }
    
        table tr:last-child td:last-child {
        border-bottom-right-radius: 6px;
        }


        .table tbody tr td .btn{
            width: 130px;
            text-decoration: none;
            line-height: 35px;
            background-color:#ee2828;
            display: inline-block;
            font-weight: medium;
            color: #FFFFFF;
            text-align: center;
            vertical-align: middle;
            user-select: none;
            border: 1px solid transparent;
            font-size: 14px;
            opacity: 1;
            border-radius: 5px;
        }
        .table tbody tr td .btn:hover{
            font-weight: bold;
        }


    .video-container {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 999999;
        background-color: rgba(1, 1, 1, 0.7);
        display: flex;
        justify-content: center;
        align-items: center;
        opacity: 0;
        pointer-events: none;
        transition: all 0.3s;
    }

    .video-container .close{
        position: absolute;
        top:10%;
        right: 25px;
        font-size: 20px;
        cursor: pointer;
        color:white;
    }
    .video-container video{
        width: 90%;
        max-width: 800px;
        transform: scale(0);
        box-shadow: 0 20px 20px rgba(0, 0, 0, 0.2);
        outline: none;
        transition: all 0.3s;
    }

    .video-container.show{
        pointer-events: all;
        opacity: 1;
    }

    .video-container.show video{
        transform: scale(1);
    }

@media(max-width: 768px){
    .table thead{
        display: none;
    }
    .table, .table tbody, .table tr, .table td{
        display: block;
        width: 100%;
        box-shadow: none;
    }
    .table tr{
        margin-bottom: 15px;
    }
    .table tbody tr td{
        text-align: right;
        padding-left: 50%;
        position: relative;
    }
    .table td:before{
        content: attr(data-label);
        position: absolute;
        left: 0;
        width: 50%;
        padding-left: 15px;
        font-weight: 600;
        font-size: 14px;
        text-align: left;
    }

    }
    </style>

</head>
<body>
        <div class="video-container" id="videoContainer">
            <span class="close" id="close">&#10006;</span>
            <video src="video.mp4" controls autoplay></video>
        </div>
    

    <div class="table-container">
        <h1 class="heading">Video Records</h1>

        

        <table class="table">
            <thead>
            <tr>
                <th>Video ID</th>
                <th>File Name</th>
                <th>Date</th>
                <th>Time</th>
                <th>#</th>
            </tr>
            </thead>
            <tbody>
                <tr>
                    <td data-label="Video ID">0022332</td>
                    <td data-label="File Name">Videocapture.mp4</td>
                    <td data-label="Date">12 / 04 / 2021</td>
                    <td data-label="Time">11:34 PM</td>
                    <td data-label="#"><a href="#" class="btn">Play</a></td>
                </tr>
                <tr>
                    <td data-label="Video ID">0022311</td>
                    <td data-label="File Name">Videocapture1.mp4</td>
                    <td data-label="Date">12 / 04 / 2021</td>
                    <td data-label="Time">11:34 PM</td>
                    <td data-label="#"><a href="#"   class="btn">Play</a></td>
                </tr>
                <tr>
                    <td data-label="Video ID">0022131</td>
                    <td data-label="File Name">Videocapture2.mp4</td>
                    <td data-label="Date">12 / 04 / 2021</td>
                    <td data-label="Time">11:34 PM</td>
                    <td data-label="#"><a href="#"   class="btn">Play</a></td>
                </tr>
                <tr>
                    <td data-label="Video ID">0025321</td>
                    <td data-label="File Name">Videocapture3.mp4</td>
                    <td data-label="Date">12 / 04 / 2021</td>
                    <td data-label="Time">11:34 PM</td>
                    <td data-label="#"><a href="#"   class="btn">Play</a></td>
                </tr>
            </tbody>
    </div>

<script type="text/javascript">
    
    
    btn = document.getElementById("btn");

    videoContainer = document.getElementById("videoContainer");

    close = document.getElementById("close");

    btn.addEventListener('click',()=>{
        videoContainer.classList.add('show');
    })

    close.addEventListener('click',()=>{
        videoContainer.classList.remove('show');
    })


</script>


</body>
</html>

I think its because of my javascript so I kind of wondering if someone could help me to make it work in multiple buttons instead of one only

confused about how CRUD apis should be designed for different authentication approaches

I am aware that there are primarily two approaches for authentication – sessions and tokens. And for sessions for I guess the session id is normally stored in the cookie that gets sent along with each subsequent request. And for tokens e.g. JWT it is normally a string added to the authorization header prefixed by bearer in HTTP header.

My first question: for the APIs that the front end uses to perform CRUD on protected resources on behalf of the logged in user, should userId be part of the API signature. In other words, do the frontend develoeprs need to pass the userId when they make those API calls? For example, I have an api endpoint for updating a resource

UpdateTask(userId?: string, taskId: string, updatedTaskConfig: TaskConfig): Task - POST /v1/tasks/:id

Should we omit userId since the session ID or the token (depends on which authentication approach we choose) is going to be enough for the backend to identify by which user this request is sent? Or we still need to include it?

Another related question is, I am aware that both JWTs and session IDs can be sent via multiple avenues (cookies, headers, request bodies, URLs, etc). Does that affect the API on the inclusion of the userId?

My second question is, for any CRUD operation, do the API calls need to include a timestamp generated on the frontend? Or it should be generated on the backend since the api calls can fail because of a number of reasons so that it makes more sense to let the backend generated the timestamp?

Calling Google Local Services API from Google Sheets

I am attempting to call the Local Services API, which is documented here: Local Services API documentation

I am calling the API inside of Apps Script, which is a way to write JavaScript inside of a Google Sheet. I have closely followed the tutorial that has been written to call other Google APIs in Apps Script, but I have not been able to call this one.
Here is the function to call the API:

function makeRequest() {
  var adsService = getAdsService();
  console.log(adsService.getAccessToken()) //I am getting a token back here
  var response = UrlFetchApp.fetch('https://localservices.googleapis.com/v1/accountReports:search?query=manager_customer_id:{manager_customer_id}', {
    headers: {
      Authorization: 'Bearer ' + adsService.getAccessToken()
    }
  });}

The makeRequest() function calls the getAdsService function below. Inside of getAdsService I am specifying ‘adwords’ and I have set the scope for .setScope('https://www.googleapis.com/auth/adwords')

function getAdsService() {
  // Create a new service with the given name. The name will be used when
  // persisting the authorized token, so ensure it is unique within the
  // scope of the property store.
  return OAuth2.createService('adwords')
      // Set the endpoint URLs, which are the same for all Google services.
      .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
      .setTokenUrl('https://accounts.google.com/o/oauth2/token')

      // Set the client ID and secret, from the Google Developers Console.
      .setClientId(ClientID)
      .setClientSecret(ClientSecret)

      // Set the name of the callback function in the script referenced
      // above that should be invoked to complete the OAuth flow.
      .setCallbackFunction('authCallback')

      // Set the property store where authorized tokens should be persisted.
      .setPropertyStore(PropertiesService.getUserProperties())

      // Set the scopes to request (space-separated for Google services).
      .setScope('https://www.googleapis.com/auth/adwords')

      // Below are Google-specific OAuth2 parameters.

      // Sets the login hint, which will prevent the account chooser screen
      // from being shown to users logged in with multiple accounts.
      .setParam('login_hint', Session.getEffectiveUser().getEmail())

      // Requests offline access.
      .setParam('access_type', 'offline')

      // Consent prompt is required to ensure a refresh token is always
      // returned when requesting offline access.
      .setParam('prompt', 'consent');
}

There are also 2 other methods to redirect the user to authorize this application.

I believe the problem is the way I am structuring the request. I believe I need to supply more information to the API call in the makeRequest function. I have seen a 'payload' : JSON.stringify(request, null, 2) go in the headers section of the request function where request specifies a specific set of instructions to call from the API but I do not know how to structure that for this case. A solution would be super appreciated.

ReactJS SVG icon load fails with svgr in order to change SVG fill dinamically

I’ve been trying to use SVG in ReactJS for the past 2 hours but nothing seems to be working.

I’m using:

"react": "^17.0.2",
"react-dom": "^17.0.2",

"devDependencies": {
        "@svgr/webpack": "^6.0.0",
        "react-svg-loader": "^3.0.3",

Using create-react-app

I call the icon as:

import { ReactComponent as Logo } from '../../icons/logo.svg';
...
<Logo fill="white" />

And the error i get is:

./src/icons/logo.svg (./node_modules/@svgr/webpack/dist?-svgo,+titleProp,+ref!./src/icons/logo.svg)
TypeError: this.getOptions is not a function.

If i use it in an “img” tag, the icon shows, but I need to dinamically change the fill of the SVG.
If there is a way on how i can load an svg and change the fill dinamically, please help and thank you.