How do I change the color of scatter plot points (with a changing data set)? — Google Apps Script — SpreadSheet

I’ve been having trouble changing the color of my scatter plot points. Here’s what it looks like now:

Current Spreadsheet

I’m trying to set series B28:B60 to be red, and C28:C60 to be green (to indicate departure/arrival). I can’t seem to get it though..

Here is my code now:

function doGet(n) {
  Logger.log("--- doGet ---");

  var name = "",
    status = "";

  try {
    if (n == null) { n = {}; n.parameters = { name: "test", status: "-1" }; }

    name = n.parameters.name;
    status = n.parameters.status;
    save_data(name, status);
    return ContentService.createTextOutput("Wrote:n  name: " + name + "n  status: " + status);
  }
  catch (error) {
    Logger.log(error);
    return ContentService.createTextOutput("oops...." + error.message
      + "n" + new Date()
      + "nname: " + name +
      + "nstatus: " + status);
  }
}

function addNewSheetForToday() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var date = new Date();
  var formattedDate = Utilities.formatDate(date, spreadsheet.getSpreadsheetTimeZone(), "MM-dd-yyyy");
  var existingSheet = spreadsheet.getSheetByName(formattedDate);
  if (existingSheet) {
    Logger.log("Sheet for today already exists.");
    return;
  }
  var newSheet = spreadsheet.insertSheet(formattedDate);
  createScatterPlot(newSheet);
  var numRows = 60;
  var numColumns = 15;
  var colors = ['#BBBBBB', '#CCCCCC'];
  for (var c = 28; c <= numRows; c++) {
    var colorIndex = (c - 2) % colors.length;
    var row = newSheet.getRange(c, 1,1, numColumns);
    row.setBackground(colors[colorIndex]);
  }
  var headerRow = newSheet.getRange(27, 2, 1, numColumns);
  headerRow.setFontStyle("italic");

  var headerColumn = newSheet.getRange(28,1, numRows, 1);
  headerColumn.setFontWeight("bold");
}

function createScatterPlot(newSheet) {
  Logger.log("--- createScatterPlot ---");
  var title = "Today's Timestamps";
  var titleFontSize = 18;
  var titleRow = 1;
  var titleColumn = 6;
  var titleCell = newSheet.getRange(titleRow, titleColumn);
  titleCell.setValue(title)
  .setFontWeight("bold")
  .setFontSize(titleFontSize)
  .setHorizontalAlignment("right");
  var range1 = newSheet.getRange('A28:A60');
  var range2 = newSheet.getRange('B28:O60');
  var chartBuilder = newSheet.newChart()
    .asScatterChart()
    .setXAxisTitle('Student')
    .setYAxisTitle('Time')
    .addRange(range1)
    .addRange(range2)
    .setPosition(2, 1, 0, 0)
    .setOption('width', 960)
    .setOption('height', 480)
    .build();
  newSheet.insertChart(chartBuilder);
}

function save_data(name, status) {
  Logger.log("--- save_data ---");
  try {
    addNewSheetForToday();
    var today = new Date();
    var time = Utilities.formatDate(today, "GMT-4", "hh:mm");
    var ss = SpreadsheetApp.openByUrl("//myURL");
    var dataLoggerSheet = ss.getSheetByName(Utilities.formatDate(today, ss.getSpreadsheetTimeZone(), "MM-dd-yyyy"));
    var studentnames = ["", "Alep", "Bet", "Gamal", "Dalat", "Heh", "Waw", "Zen", "Khet", "Tet", "Yod", "Kap", "Lamad", "Meem", "Noon", "Simkat", "Eh", "Peh", "Sahdeh", "Qope", "Resh", "Sheen", "Tao", "Martin", "Allyson", "Ashur", "Matilda", "Odin", "Ophelia", "Brownie", "Oreo", "SubCard1", "SubCard2", "SubCard3"];
    for (var i = 0; i < studentnames.length; i++) {
      dataLoggerSheet.getRange("A" + (i + 27)).setValue(studentnames[i]);
    }
    if (name == "Alep") {
      if (dataLoggerSheet.getRange("C28").getValue() == "" || dataLoggerSheet.getRange("C28").getValue() == null) {
        dataLoggerSheet.getRange("B27").setValue("1st Departure");
        dataLoggerSheet.getRange("C27").setValue("1st Return");
        if (status == "Departed") {
          dataLoggerSheet.getRange("B28").setValue(time);
        }
        else if (status == "Returned") {
          dataLoggerSheet.getRange("C28").setValue(time);
        }
      }
   }
//Goes on to list the other student names on the list

}

  catch (error) {
    Logger.log(JSON.stringify(error));
  }

  Logger.log("--- save_data end---");
}

Anytime I try to change the color of the points in the scatterplot that gets created at the beginning, nothing happens. I don’t know what I’m doing wrong.

I posted recently about this and Tanaike gave me a good response: Last Post

This does create a scatter plot with green/red dots, but I can’t seem to get it to integrate with my already existing code.

Repeat header and footer in windows.print() stacked with content

I want to repeat header and footer with position fixed. but the content overlaps above the header and footer. I want the content to be in the middle of header and footer. i have try many solution but still have issue with overlap content. @page margin also doesn’t work because it also affects header and footer. please help me!

Code :

 window.print();
 
@media screen {
   .PrintOnly {display: none;}
    b {
        font-weight:bold;display: inline-block !important;}


strong {
        font-weight:bold;display: inline-block !important;}
}
@media print {
    
    @page{ margin:0;
  size: A4; }
  .margin-print {
    
    margin: 151px 94.5px 151px 94.5px;
  padding-top: 80px; /* Add enough padding to offset the header */
  padding-bottom: 40px; /* Add enough padding to offset the footer */
  }


   .PrintOnly {
    font-size: 10pt;   overflow-x: hidden;
    
    overflow-y: hidden; font-family:'Noto Sans' !important;
      }
    b {
        font-weight:bold;display: inline-block !important;
    }

    .image-footer {  position:fixed;
  background: #2658C9;
    bottom:0px;
    left:0px;
    width:100%;
    padding:8px;
  z-index: -99; }
    
    .image-header {  position:fixed;
  background: #2658C9;
  top: 0;
    left:0px;
    width:100%;
    padding:8px;
  z-index: -99;}
 
}
<!DOCTYPE html>
<html lang="en">  <style>
</style>
<head>
     
</head>
<div class="PrintOnly" >
    <br>
<img  class ='image-header' src='../../image.png'>
    <div class='margin-print'>

<p>Content</p>
<br>
</div>
<img class ='image-footer' src='../../image.png'>

</div>

Image :
enter image description here

JavaScript conditional logic for generating JSON, beginners stuck in the process

Goal: To create a conditional statement that generates JSON data in a predefined layout for the system.

example: if new item is selected, it should include its “id” and set “enable” to true.

{
  "draw": 1,
  "length": 1,
  "server": "argp",
  "data": [
    {
      "id": 4343,
      "enable": true
    }

  ]
}

example: if two new items are selected, and one existing item is deselected, the JSON data should look like this:

{
  "draw": 1,
  "length": 3,
  "server": "argp",
  "data": [
    {
      "id": 4343,
      "enable": true
    },
    {
      "id": 5555,
      "enable": true
    },
    {
      "id": 6666,
      "enable": false
    }
  ]
}


I’ve written a conditional statement that lists all the selected “id” with “enable: true”.

  • Figure 1 (Assuming there were initially two items selected):
    Figure 1

  • Figure 2 (After selecting the third item, it is also listed):Figure 2

Here’s the code with the conditional statement that is not achieving the desired effect yet:

<script>
  var old_data = []; // Define a variable to store previously selected data

  function modalTable() {
    console.log("TABLE MODAL");
    const getToken = localStorage.getItem("token");
    var new_edit_data = {
      draw: 1,
      length: 0,
      server: "argp",
      data: []
    };

    var tablefor4 = $("#example_04").DataTable({
      ajax: {
        url: "http://192.168.03.30:6000/api/message/all", // Fake API
        headers: {
          'Authorization': 'Bearer ' + getToken
        },
        dataSrc: function (response) {
          console.log("DATA MODAL TABLE", response.data);
          return response.data;
        },
      },
      destroy: true,
      columns: [
        { data: "sf", title: "sf" },
        { data: "code", title: "code" },
        { data: "subcode", title: "subcode" },
        { data: "msgtext", title: "msgtext" }, 
        { data: "description", title: "description" },    
        {
          data: null,
          title: "Alarm/Event Setting",
          render: function (data, type, row) {
            var switchId = 'customSwitch_' + row.id; // Assuming you have an 'id' field in your data
            var switchHTML = '<div class="custom-control custom-switch">';
            var isChecked = row.argp ? 'checked' : ''; // Check if rowData.argp is true and add the checked attribute if so
            switchHTML += '<input type="checkbox" class="custom-control-input" id="' + switchId + '" ' + isChecked + '>';
            switchHTML += '<label class="custom-control-label" for="' + switchId + '">Selected</label>';
            switchHTML += '</div>';
            return switchHTML;
          },
          createdCell: function (td, cellData, rowData, row, col) {
          var switchId = 'customSwitch_' + rowData.id; // Assuming you have an 'id' field in your data
          var switchElement = $(td).find('#' + switchId);
          var previousArgpValue = rowData.argp; // Store the previous argp value
          switchElement.change(function () {
            if ($(this).is(':checked')) {
              rowData.argp = true;
            } else {
              rowData.argp = false;
            }
            var selectedRows = tablefor4.rows({ selected: true }).data();
            var newSelectedData = selectedRows.filter(function(row) {
              return row.argp === true && !old_data.some(function(prevRow) {
                return prevRow.id === row.id;
              });
            }).map(function(row) {
              return { id: row.id, enable: true };
            });
            old_data = selectedRows.toArray(); // Update previously selected data
            new_edit_data.data = new_edit_data.data.concat(newSelectedData); // Combine newly selected data
            new_edit_data.length = new_edit_data.data.filter(function(row) {
              return row.enable === true;
            }).length;

            // If previously selected data was modified in the new selection, revert the argp value
            if (!old_data.some(function(prevRow) {
              return prevRow.id === rowData.id && prevRow.enable === previousArgpValue;
            })) {
              rowData.argp = previousArgpValue;
            }

            console.log("Selected Rows (new):", new_edit_data);
            console.log("old_data:", old_data);
          });
        }


        },
      ]
    });

    tablefor4.draw();
  }
</script>

The current output will look like this, listing all the selected “id” with “enable: true” (including both old and newly selected ones, but not the newly deselected ones):

I hope it calculates the number of modifications in the “length” and the newly modified “id” with their corresponding “enable” status.

For example:

Suppose we select two new items and deselect one old item, the result should be as follows:

{
  "draw": 1,
  "length": 3,
  "server": "argp",
  "data": [
    {
      "id": 4343,
      "enable": true
    },
    {
      "id": 5555,
      "enable": true
    },
    {
      "id": 6666,
      "enable": false
    }
  ]
}

For writing wizards, it might be quick, but I’m stuck on this and a bit puzzled. Any guidance would be greatly appreciated!

antd table scroll to top when click Pagination

This is my table code in AntD, on pagination clicked

<Table
        columns={fixedColumns}
        dataSource={fixedData}
        pagination={false}
        scroll={{ x: 2000, y: 500 }}
        bordered
        summary={() => (
          <Table.Summary fixed>
            <Table.Summary.Row>
              <Table.Summary.Cell index={0}>Summary</Table.Summary.Cell>
              <Table.Summary.Cell index={1}>
                This is a summary content
              </Table.Summary.Cell>
            </Table.Summary.Row>
          </Table.Summary>
        )}
      />

I want it to scroll to page top.

How to let users login in and send emails through their account?

I’m trying to build an application that users can log in to and send emails. I’m using FIrebase with ReactJS. For sending out emails, I am currently using email.js. It’s been working well, however, I can only send out emails through my own email.js account. So if I create an account with my gmail, it will send emails out through my own email. However, I want the user to login to my app (I’m using firebase auth), and when they send out emails, I want it to come from the email address they logged into my app with. I haven’t found out how to do this with email.js documentation and there isn’t anything that clear online. Any ideas on how to approach this?

Finding/filtering 2 dates of the same day

I’ve got an array of dates for the month of July like so:

  const dates = [
    { date: '2023-07-01', available: true },
    { date: '2023-07-02', available: true },
    { date: '2023-07-03', available: true },
    { date: '2023-07-04', available: true },
    { date: '2023-07-05', available: true },
    { date: '2023-07-06', available: true },
    { date: '2023-07-07', available: true },
    { date: '2023-07-08', available: true },
    { date: '2023-07-09', available: true },
    { date: '2023-07-10', available: true },
    { date: '2023-07-11', available: true },
    { date: '2023-07-12', available: true },
    { date: '2023-07-13', available: true },
    { date: '2023-07-14', available: true },
    { date: '2023-07-15', available: true },
    { date: '2023-07-16', available: true },
    { date: '2023-07-17', available: true },
    { date: '2023-07-18', available: true },
    { date: '2023-07-19', available: true },
    { date: '2023-07-20', available: true },
    { date: '2023-07-21', available: true },
    { date: '2023-07-22', available: true },
    { date: '2023-07-23', available: true },
    { date: '2023-07-24', available: true },
    { date: '2023-07-25', available: true },
    { date: '2023-07-26', available: true },
    { date: '2023-07-27', available: true },
    { date: '2023-07-28', available: true },
    { date: '2023-07-29', available: true },
    { date: '2023-07-30', available: true },
    { date: '2023-07-31', available: true }
  ];

There is an end date of 2023-07-05 in the first element of the array and a start date in the second element of the array with the same 2023-07-05 date.
This means there is a checkout on the 5th and a checkin on the 5th so I would like to update the dates array above and set available: false.
I would like to do this anytime I see this pattern of 2 match dates such as the 2023-07-08.

  const reserved = [
    { start: "2023-07-03", end: "2023-07-05" }, // check out 5th
    { start: "2023-07-05", end: "2023-07-08" }, // check in 5th, checkout 8th
    { start: "2023-07-08", end: "2023-07-10" }, // checkin 8th
    { start: "2023-07-18", end: "2023-07-20" }, // checkin 18th, check out 20th - ignore this completely, no overlap
    { start: "2023-07-22", end: "2023-07-24" }, // checkin out 24
    { start: "2023-07-24", end: "2023-07-26" }, // checkin 24
  ];

Any idea how I can accomplish this? I have tried a numerous amounts of filtering but I can never figure out the right pattern to update where there are
2 on the same day.

How can I get a div that moves using arrow keys to not be able to go off screen?

I want to make a pong game using HTML, CSS and javascript. I started with making a player and I got it to move using the arrow keys but it can go outside the screen which creates the sidebar. I want it to not be able to go off the screen.
Here is the javascript code:

const right = document.getElementById("right");

const player = document.createElement("player");
player.classList.add("player");
right.appendChild(player);

player.style.top = "300px";
player.style.left = 5;

let moveBy = 10;
window.addEventListener("keydown", (event) => {
  switch (event.key) {
    case "ArrowUp":
      player.style.top =
        parseInt(player.style.top) - moveBy + "px";
      break;
    case "ArrowDown":
      player.style.top =
        parseInt(player.style.top) + moveBy + "px";
      break;
  }
});

I tried adding if statements but it did not work, I have also tried to google it but I have not found the right answer for this.

What’s the difference in creating project between react-native-cli and react-native?

I’m trying to create [email protected] project recently.

The first way is like this:

npm install react-native-cli -g
npx react-native --init [name] --version 0.68.2

The second way is using npx directly, like this:

# there isn't react-native-cli in my global node_modules
npx react-native --init [name] --version 0.68.2

When I create react-native project using the first way, everything is fine.

But when I create project with the second way, some errors happened. The errors here are about my own code related to react native jsi and bundle file.

I want to know what’s the tiny difference in creating project between react-native-cli and react-native. So I can figure out my own code problem.

nodejs version: v18.12.1

npm version: 8.19.2

platform: Windows

How not to allow the main content to overlap the header and footer?

I have this html file, that I’m using to generate a pdf with a header and footer on every page, but after the first header, the main content overlaps with the footer and the header. How do i solve this?

<html>
        <head>
          <style>
            @page {
              size: A4;
            }
            body {
              margin: 0;
              padding: 0;
              width: 100%;
              height: 100%;
              display: flex;
              flex-direction: column;
            }
            /* Apply the header to every page */
            #header {
              font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
              color: #111111;
              font-size: 16px;
              text-align: left;
              position: relative;
              top: 0;
              left: 0;
              right: 0;
              height: 40mm; /* Adjust the height of the header */
              break-after: always;
            }
            /* Apply the footer to every page */
            #footer {
              font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
              color: #111111;
              font-size: 16px;
              text-align: left;
              position: fixed;
              bottom: 0;
              left: 0;
              right: 0;
              height: 40mm; /* Adjust the height of the footer */
              break-after: always;
              background-color: white;
            }
            /* Create a wrapper for the main content to offset for header and footer */
            #main-content-wrapper {
              flex: 1;
              padding-bottom: 40mm; /* Add the height of the footer */
              box-sizing: border-box;
            }
          </style>
          
        </head>
        <body>
          <div id="header">${headerWithData}</div>
          <div id="main-content-wrapper">
             <div id="main-content">${template}</div>
          </div>
          <div id="footer">${footerWithData}</div>
        </body>
      </html>

I tried adding page breaks to the footer but it didn’t work.

Dynamically change css to avoid conflict?

I have a main framework of a website which has its own CSS.
But in the content area, I use PHP to include different pages including different CSS styles.

It often causes CSS conflict.

Question 1:
Is there an easy approach to prevent CSS conflict?

Question 2:
If no easy approach, how can I dynamically add prefix to every id and class name to html and its external css files?

PHP Update Function Not Updating Correct Row (Using Modal)

I’m having trouble with the CRUD application in PHP.

The purpose of this code is to to get the user to click finish and the code will save the user input (calibratorID and current timestamp) into the database. But im having issue with it.

Here’s the issue: I have a table with several rows, each having its own ID. When I try to update a row by clicking on the finish button, it always updates the row with the latest ID that I added to the table. For example, if the table has rows with IDs 1, 2, and 3, when I click update on ID = 1, it still updates ID = 3 instead of the one I selected.

Please help me fix this issue. The code is below.

<?php
      if (mysqli_num_rows($result) > 0) {
      while($row = mysqli_fetch_assoc($result)) {
            echo "
            <tr>
            <th>  ".$row["id"]." </th>
            <td>  ".$row["instID"]." </td>
            <td>  ".$row["submitterID"]." </td>
            <td>  ".$row["submit_dt"]." </td>
            <td>
            <button type='button' class='btn btn-success' data-bs-toggle='modal' data-bs-target='#finishmodal'>
             FINISH
            </button>

            <div class='modal fade' id='finishmodal' tabindex='-1' aria-labelledby='exampleModalLabel' aria-     hidden='true'>
            <div class='modal-dialog'>
            <div class='modal-content'>
            <div class='modal-header'>
            <h1 class='modal-title fs-5' id='exampleModalLabel'>Finish Calibration</h1>
            <button type='button' class='btn-close' data-bs-dismiss='modal' aria-label='Close'></button>
             </div>
             <form action='finishcali.php?id=".$row['id']."' method='POST'>
                               
            <div class='modal-body'>
                  <div class='form-group'>
                        <label> Employee ID </label>
                        <input type='text' name='calibratorID' class='form-control' placeholder='Enter Employee ID' required>
                  </div>
            </div>
            <div class='modal-footer'>
                  <button type='button' class='btn btn-secondary' data-bs-dismiss='modal'>Cancel</button>
                   <button type='submit' name='finishcali' class='btn btn-success'>Finish Calibration</button>
            </div>
            </form>
            </div>
             </div>
            </div>
            </td>
            </tr>";
                            }}
                            else{
                                echo "No result found";
                            }
?>



<?php

include("dbconn.php");
$id = $_GET['id'];

if (isset($_POST['finishcali'])){

    $calibratorID = $_POST['calibratorID'];
    date_default_timezone_set('Asia/Kuala_Lumpur');
    $finish_dt = date('Y-m-d H:i:s');

    $sql = "UPDATE calisys SET calibratorID='$calibratorID', finish_dt='$finish_dt' WHERE id='$id'";
    if (mysqli_query($conn, $sql)) {
        header('location: finish.php');
    } else {
        echo '<script> alert("Data Not Saved"); </script>';
        mysqli_error($conn);
    }

}

?>