Mongoose pre and post hooks do not work on models created with Model.discriminator

I am using mongoose 6.1.5.

I have a collection containing multiple types of related documents. Here is parameter-descriptor-item.model.js

const mongoose = require('mongoose');

const { Schema } = mongoose;

/** @summary The schema for a parameter item */
const itemSchema = new Schema({
  _id: String,
  name: Object,
});

itemSchema.pre(/^find/, function () {
  // eslint-disable-next-line no-console
  console.log('item pre hit');
});

/** @summary The base model for all parameter items */
module.exports = mongoose.model('Parameters', itemSchema);

ParameterDescriptor model inherits from ParameterDescriptorItem. Here is parameter-descriptor.model.js

const mongoose = require('mongoose');
const ParameterDescriptorItem = require('./parameter-descriptor-item.model');

const { Schema } = mongoose;

/** @summary The schema for additional fields for a project */
const parameterSchema = new Schema({
  direction: {
    type: String,
    enum: ['in', 'out'],
    required: true,
  },
  default: {
    type: Number,
    required: true,
  },
  min: {
    type: Number,
    required: false,
  },
  max: {
    type: Number,
    required: false,
  },
  unit: {
    type: String,
    required: false,
  },
});

parameterSchema.pre(/^find/, function () {
  // eslint-disable-next-line no-console
  console.log('parameter pre hit');
});


/** @summary The model for a parameter descriptor */
module.exports = ParameterDescriptorItem.discriminator('Parameter', parameterSchema);

And here is code to test the use of pre hooks.

const ParameterDescriptorItem = require('./parameter-descriptor-item.model');
const ParameterDescriptor = require('./parameter-descriptor.model');

await ParameterDescriptorItem.find();
// console shows: 'item pre hit'
await ParameterDescriptor.find();
// there is nothing additional in the console. Neither the 'pre' hooks from
// ParameterDescriptorItem or ParameterDescriptor is called.

This is a significant issue for me. Is there a way to address it? Is there a way to add pre and post hooks to models created with Model.discriminator?

How does one request additional scopes using google-auth-library with npm?

Our UI currently prompts the user to login with default scopes enabled.
In order to support a specific feature in our application, we’d like to request additional permissions only if they opt-in for the feature.

This link from Google explains how to do exactly that, but it uses their old javascript library that’s no longer supported.
How can I achieve the same thing with google-auth-library?

ExpressJS: Best way to separate routes and accepting params?

I made a Express.js system where the files in the /routes folder are acting as a classic route (but with one file per route)

Example: /routes/get/user.js will be accessible with http://localhost:8080/user (the /get is to separate methods, it can be /post, /put…)

Here’s my entire index.js file: https://pastebin.com/ALtSeHXc

But actually, my problem is that I can’t pass params into the url like https://localhost:8080/user/random_id_here.

With this system, I think the best idea is to find a way to pass params on separated files too, but I don’t know how can it be done…

Here’s an example of one of my separated file:

module.exports = class NameAPI {
    constructor(client) {
        this.client = client
    }

    async run(req, res) {
        // Code here
    }
}

Maybe you’ll have a better system, or a solution for this. Thanks.

amazon-cognito-identity-js setupMFA problems

I am attempting to setup MFA for users after they reset their passcode. The code runs smoothly until I hit mfaSetup, specifically the line user.associateSoftwareToken(). When I pass in ‘this’ instead of user, I get the following error:

Uncaught (in promise) TypeError: callback is undefined

When I pass in user I get Uncaught (in promise) TypeError: callback.onFailure is not a function

I am truly at a loss of what to do and would appreciate any help.

Code below:


  const onSubmit = (event) => {
    event.preventDefault();

    const authDetails = new AuthenticationDetails({
      Username: email,
      Password: password
    });

    const user = new CognitoUser({
      Username: email,
      Pool: UserPool
    });

    user.authenticateUser(authDetails, {
      onSuccess: (data) => {
        console.log('onSuccess:', data);
        if (location.pathname === '/') {
          // navigate('dashboard');
        }
      },
      onFailure: (err) => {
        console.error('onFailure:', err);
      },
      newPasswordRequired: (data) => {
        console.log(data);
        setNewPasscodeRequired(true);
      },
      mfaRequired: (data) => {
        console.log('mfa required');
      },
      mfaSetup: (challengeName, challengeParameters) => {
        console.log('in mfa setup');
        console.log(user.Session);
        user.associateSoftwareToken(user, {
          onFailure: (err) => {
            console.error('onFailure', err);
          },
          onSuccess: (result) => {
            console.log(result);
          }
        });
      },
      selectMFAType: (challengeName, challengeParameters) => {
        console.log(challengeName, challengeParameters);
        user.sendMFASelectionAnswer('SOFTWARE_TOKEN_MFA', this);
      },
      totpRequired: (secretCode) => {
        console.log(secretCode);
        const challengeAnswer = prompt('Please input the TOTP code.', '');
        user.sendMFACode(challengeAnswer, this, 'SOFTWARE_TOKEN_MFA');
      },
      associateSecretCode: (secretCode) => {
        const challengeAnswer = prompt('Please input the TOTP code.', '');
        user.verifySoftwareToken(challengeAnswer, 'My TOTP device', this);
      }
    });
  };

  const onSubmitPasscode = (event) => {
    event.preventDefault();

    if (passwordFirst !== passwordSecond) {
      alert('the two inputs provided are not the same');
    } else {
      const user = new CognitoUser({
        Username: email,
        Pool: UserPool
      });

      const authDetails = new AuthenticationDetails({
        Username: email,
        Password: password
      });

      user.authenticateUser(authDetails, {
        onFailure: (err) => {
          console.error('onFailure:', err);
        },
        onSuccess: (result) => {
          console.log(result);
        },
        newPasswordRequired: (userAttributes, requiredAttributes) => {
          console.log(userAttributes);
          console.log(requiredAttributes);
          delete userAttributes.email_verified;
          delete userAttributes.phone_number_verified;
          delete userAttributes.phone_number;
          console.log(userAttributes);
          user.completeNewPasswordChallenge(passwordFirst, userAttributes, {
            onFailure: (err) => {
              console.error('onFailure:', err);
            },
            onSuccess: (result) => {
              console.log('call result: ', result);
            },
            mfaSetup: (challengeName, challengeParameters) => {
              console.log('in mfa setup');
              console.log(user.Session);
              user.associateSoftwareToken(this, {
                onFailure: (err) => {
                  console.error('onFailure', err);
                },
                onSuccess: (result) => {
                  console.log(result);
                }
              });
            },
            selectMFAType: (challengeName, challengeParameters) => {
              console.log(challengeName, challengeParameters);
              user.sendMFASelectionAnswer('SOFTWARE_TOKEN_MFA', this);
            },
            totpRequired: (secretCode) => {
              console.log(secretCode);
              const challengeAnswer = prompt('Please input the TOTP code.', '');
              user.sendMFACode(challengeAnswer, this, 'SOFTWARE_TOKEN_MFA');
            },
            associateSecretCode: (secretCode) => {
              const challengeAnswer = prompt('Please input the TOTP code.', '');
              user.verifySoftwareToken(challengeAnswer, 'My TOTP device', this);
            }
          });
        }
      });
    }
  };

  const onMFASetup = () => {
    const user = new CognitoUser({
      Username: email,
      Pool: UserPool
    });

    const authDetails = new AuthenticationDetails({
      Username: email,
      Password: passwordFirst
    });

    console.log(email);
    console.log(passwordFirst);

    user.authenticateUser(authDetails, {
      onFailure: (err) => {
        console.error('onFailure:', err);
      },
      onSuccess: (result) => {
        console.log(result);
      },
      mfaSetup: (challengeName, challengeParameters) => {
        user.associateSoftwareToken(this);
      },
      selectMFAType: (challengeName, challengeParameters) => {
        user.sendMFASelectionAnswer('SOFTWARE_TOKEN_MFA', this);
      },
      totpRequired: (secretCode) => {
        const challengeAnswer = prompt('Please input the TOTP code.', '');
        user.sendMFACode(challengeAnswer, this, 'SOFTWARE_TOKEN_MFA');
      },
      mfaRequired: (codeDeliveryDetails) => {
        const verificationCode = prompt('Please input verification code', '');
        user.sendMFACode(verificationCode, this);
      }
    });
  };

  const sendVerificationPin = (event) => {
    event.preventDefault();
    const user = new CognitoUser({
      Username: email,
      Pool: UserPool
    });

    user.forgotPassword({
      onSuccess: (result) => {
        console.log('call result: ', result);
      },
      onFailure: (err) => {
        alert(err);
      }
    });
  };

  const onResetPassword = (event) => {
    event.preventDefault();

    console.log('in reset');

    const user = new CognitoUser({
      Username: email,
      Pool: UserPool
    });

    console.log('user made');

    if (passwordFirst !== passwordSecond) {
      alert('the two inputs provided are not the same');
    } else {
      console.log('inputs are the same');
      user.confirmPassword(pin, passwordSecond, {
        onSuccess() {
          console.log('Password confirmed!');
          window.location.reload(true);
        },
        onFailure(err) {
          console.log('Password not confirmed!');
          console.log(err);
        }
      });
    }
  };

  return (
    <div>
      {!newPasscodeRequired && !forgotPassword && !setupMFA && (
        <div>
          <form onSubmit={onSubmit}>
            <input type="text" required value={email} onChange={(e) => setEmail(e.target.value)} />
            <input
              type="text"
              required
              value={password}
              onChange={(e) => setPassword(e.target.value)}
            />
            <button type="submit">Login</button>
          </form>
          <button onClick={(e) => setForgotPassword(true)}>
            <Typography sx={{ paddingX: 5 }}>Forgot password?</Typography>
          </button>
        </div>
      )}
      {newPasscodeRequired && (
        <div>
          <form onSubmit={onSubmitPasscode}>
            <Typography>New Password</Typography>
            <input type="text" required onChange={(e) => setPasswordFirst(e.target.value)} />
            <Typography>New Password Again</Typography>
            <input type="text" required onChange={(e) => setPasswordSecond(e.target.value)} />
            <Typography>New Password Requirements</Typography>
            <Typography>
              At least 8 characters long, requiring upper and lower case letters, numbers, and
              special characters
            </Typography>
            <button type="submit">Submit new passcode</button>
          </form>
        </div>
      )}
      {forgotPassword && !newPasscodeRequired && (
        <div>
          <form onSubmit={sendVerificationPin}>
            <Typography>Please input the email for the account</Typography>
            <input type="text" required onChange={(e) => setEmail(e.target.value)} />
            <button type="submit">Send verification pin</button>
          </form>
          <form onSubmit={onResetPassword}>
            <Typography>Input the verification pin sent to your email below</Typography>
            <input type="text" required onChange={(e) => setPin(e.target.value)} />
            <Typography>New Password</Typography>
            <input type="text" required onChange={(e) => setPasswordFirst(e.target.value)} />
            <Typography>New Password Again</Typography>
            <input type="text" required onChange={(e) => setPasswordSecond(e.target.value)} />
            <Typography>New Password Requirements</Typography>
            <Typography>
              At least 8 characters long, requiring upper and lower case letters, numbers, and
              special characters
            </Typography>
            <button type="submit">Reset Password</button>
          </form>
        </div>
      )}
      {setupMFA && (
        <div>
          <div>SetupMFA</div>
          <button onClick={(e) => onMFASetup()}>Generate QR Code</button>
        </div>
      )}
    </div>
  );
};

How to get Vuex to add a urls from a Firebase getDownloadURL promise in Vue

I have an app that is using Firestore Storage JavaScript version 9, Vuex 4, and Vue 3. It needs to download image urls from Firestore Storage to display on an image tag.

My Firestore Storage is structured listings/${userID}/ with image files of that userID in it.

I have one component that needs image urls and is trying to get them from Firestore (line 35).

Listing.vue

<template>
  <div class="listing__container">
    <div class="listing__container_info">
      <h1 class="listing__header">{{ listing.title }}</h1>
      <p class="listing__paragraph">{{ listing.description }}</p>
      <div v-if="!isNaN(listing.stars)">
        <icon-star-line v-for="star in Number(listing.stars)" class="listing__icon" />
      </div>
    </div>
    <div class="listing__container_image">
      <img class="listing__image" :src="listingImageUrls[0]" alt="an image" />
    </div>
    <div class="listing__container_image">
      <img :src="listingImageUrls[1]" alt />
    </div>
  </div>
</template>

<script setup>
const props = defineProps({
  listing: Object,
})
import { computed, ref, toRefs } from 'vue'
import IconStarLine from '~icons/clarity/star-solid'
import { useStore } from 'vuex'

const store = useStore()
const { listing } = toRefs(props)

const userId = 'vlM46kRbhym3a3PW76t4'
store.dispatch('fetchUser', userId)
const user = computed(() => store.state.user)

store.dispatch('fetchListingImageUrls', user.value.id)
const listingImageUrls = computed(() => store.state.listingImageUrls)
</script>

<style lang="postcss">
.listing {
  @apply border-2 border-ui-100 rounded-3xl flex;
  &__header {
    @apply text-primary-900 text-3xl font-bold;
  }
  &__paragraph {
    @apply font-normal;
  }
  &__icon {
    @apply text-primary-500 inline;
  }
  &__container {
    @apply flex;
    &_info {
    }
    &_image {
      @apply w-52 h-36 overflow-hidden;
      .listing__image {
        /* @apply relative top-1/2 left-1/2; */
      }
    }
  }
}
</style>

I have another Vuex script that handles state and is calling getDownloadURL (line 57 to end of file)

store/index.js

import { createStore } from 'vuex'
import { initializeApp } from 'firebase/app'
import { getFirestore, collection, doc, addDoc, getDoc, getDocs, Timestamp } from 'firebase/firestore'
import { getStorage, ref, getDownloadURL, list } from 'firebase/storage'

const firebaseApp = initializeApp({
  apiKey: 'AIzaSyDANDyEb-LZn9OqcOECf93oLL48J1O2sWQ',
  authDomain: 'sploots-d050d.firebaseapp.com',
  projectId: 'sploots-d050d',
  storageBucket: 'sploots-d050d.appspot.com',
  messagingSenderId: '666246994336',
  appId: '1:666246994336:web:e6c1f5abd0467a63d22cc5',
  measurementId: 'G-173Y64V43X'
})

const db = getFirestore()
const storage = getStorage()

export const store = createStore({
  state: {
    user: {},
    listings: [],
    listingImageUrls: []
  },
  mutations: {
    addUser(state, user) {
      state.user = user
    },
    addListings(state, listings) {
      state.listings = listings
    },
    addListingImageUrls(state, urls) {
      state.listingImageUrls = urls
    }
  },
  actions: {
    async fetchUser({ commit }, userId) {
      const userRef = doc(db, `/users/${userId}`)
      const userSnap = await getDoc(userRef)
      commit('addUser', userSnap.data())
      if (!userSnap.exists()) {
        // doc.data() will be undefined in this case
        console.log("No such document!")
      }
    },
    async fetchListings({ commit }, userId) {
      const listingsRef = collection(db, `/users/${userId}/listings`)
      const listingsSnap = await getDocs(listingsRef)
      const listingsClean = []
      listingsSnap.forEach(doc => {
        let docClean = doc.data()
        listingsClean.push(docClean)
      })
      const listings = listingsClean
      commit('addListings', listings)
    },
    async fetchListingImageUrls({ commit }, userId) {
      const folderRef = await ref(storage, `listings/${userId}`)
      const imagesList = await list(folderRef)
      commit('addListingImageUrls', await getUrls(imagesList))
    },
  }
})

const getUrls = async (imagesList) => {
  const urls = imagesList.items.map(async imageRef => {
    const url = await getDownloadURL(imageRef)
    console.log(url)
    return url
  })
  return urls
}

And here is my package.json

{
  "name": "someApp",
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "serve": "vite preview"
  },
  "dependencies": {
    "firebase": "^9.4.1",
    "postcss-import": "^14.0.2",
    "vue": "^3.2.16",
    "vue-router": "^4.0.12",
    "vuex": "^4.0.2"
  },
  "devDependencies": {
    "@iconify-json/clarity": "^1.0.1",
    "@vitejs/plugin-vue": "^1.9.3",
    "autoprefixer": "^10.4.0",
    "eslint": "^8.2.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-vue": "^8.0.3",
    "postcss": "^8.4.4",
    "postcss-nested": "^5.0.6",
    "prettier": "^2.4.1",
    "tailwindcss": "^2.2.19",
    "unplugin-icons": "^0.12.23",
    "vite": "^2.6.4"
  }
}

Listing.vue is calling fetchListingImageURls on line 35 from store/index.js (line 57 and below) to get image urls from Firebase Storage. With this code the images don’t show. If I log listingImageUrls.value in listings.vue it is a proxy with a target that is an empty array. If I log urls from the store in getURLs it shows the urls as a fulfilled promise.

What is the issue here? I am pretty new to Vuex and Firestore so I think I am probably doing something wrong with one of those, or, as always, I am butchering something with my async calls.

Any help is appreciated 🙂

How to make a double await Node.js

Hi I can´t find a solution to my problem of functions in cascade,

Service A

print(await serviceB.methodA(myParameter));

Service B

async methodA(MyParameter){

            await methodB(MyParamter).then((value) =>{
                serviceA.methodC(value).then((result)=>{
                   console.log('result');
                   return result;
               });

            }
         );
         console.log('hi');
    }

So the output is

hi
undefined
result 

How I can wait to the second cascade of the then?? Because when getting undefined is broking my service A that must get “result”

Organize JSON data in HTML table with unique header rows for each data group

I have a JSON object that includes a key:value pair called callRoot. Example values for this key:value pair include @S, @C, and @W. There are multiple objects that have the same value and I hoping to set a HTML table head row at the start of each grouping and repeat it for each group of data.

Sample JSON data:

const commodities = [
  {
    actualSymbol: "@SF22",
    callRoot: "@S",
    open: 1.00,
    close: 2.00,
    userDescription: "SOYBEANS",
    // Other data
  },
  {
    actualSymbol: "@SH22",
    callRoot: "@S",
    open: 4.00,
    close: 6.00,
    userDescription: "SOYBEANS",
    // Other data
  },
  {
    actualSymbol: "@SK22",
    callRoot: "@S",
    open: 0.50,
    close: 2.30,
    userDescription: "SOYBEANS",
    // Other data
  },
  {
    actualSymbol: "@CH22",
    callRoot: "@C",
    open: 0.25,
    close: 0.75,
    userDescription: "CORN",
    // Other data
  },
  {
    actualSymbol: "@CK22",
    callRoot: "@C",
    open: 5.00,
    close: 6.75,
    userDescription: "CORN",
    // Other data
  },
  {
    actualSymbol: "@CN22",
    callRoot: "@C",
    open: 1.00,
    close: 2.00,
    userDescription: "CORN",
    // Other data
  },
  {
    actualSymbol: "@WH22",
    callRoot: "@W",
    open: 3.25,
    close: 2.00,
    userDescription: "WHEAT",
    // Other data
  },
  {
    actualSymbol: "@WK22",
    callRoot: "@W",
    open: 1.00,
    close: 2.00,
    userDescription: "WHEAT",
    // Other data
  },
  {
    actualSymbol: "@WN22",
    callRoot: "@W",
    open: 0.10,
    close: 0.20,
    userDescription: "WHEAT",
    // Other data
  }
];

Here is some of the code I have been playing with, though I could be way off on achieving my set requirements. A switch statement may be better suited than the if/else if statement

// Create empty arrays for each callRoot grouping
const soybeans = [];
const corn = [];
const wheat = [];

for(let commodity of commodities) {
  let callRoot = commodity.callRoot;
  if(callRoot.includes("@S")) {

  } else if(callRoot.includes("@C")) {

  } else if(callRoot.includes("@W")) {
  
  }
}

const soyHeader = soybean[0];
if(soyHeader) {
  // Render table header row HTML
}
// Render table row HTML

const cornHeader = corn[0];
if(cornHeader) {
  // Render table header row HTML
}
// Render table row HTML

const wheatHeader = wheat[0];
if(wheatHeader) {
  // Render table header row HTML
}
// Render table row HTML

Example HTML table structure:

<table>
  <tbody>
    <tr>
      <th colspan="9">SOYBEANS</th>
    </tr>
    <tr>
      <td>Month</td>
      <td>Last</td>
      <td>Change</td>
      <td>High</td>
      <td>Low</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="9">CORN</th>
    </tr>
    <tr>
      <td>Month</td>
      <td>Last</td>
      <td>Change</td>
      <td>High</td>
      <td>Low</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="9">WHEAT</th>
    </tr>
    <tr>
      <td>Month</td>
      <td>Last</td>
      <td>Change</td>
      <td>High</td>
      <td>Low</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
    <tr>
      <td>August 2022</td>
      <td>1265'2</td>
      <td>-2'4</td>
      <td>1275'2</td>
      <td>1261'4</td>
    </tr>
  </tbody>
</table>

Rendered HTML table example

React | how to display random string from array and choose another random on btn press

So I’m learning react and wanted to make an idea generator that would pull a string from an array (the ‘researchTitles’) file, and display it in the h1 and then on the button click it would pick another at random and display that. so far I’ve just got the outline and the method to pick a string at random, is there a better way to do this? and if so can I get some help

import researchTitles from './
import React from 'react';

function App() {

  const title = researchTitles[Math.floor(Math.random() * researchTitles.length)];
  
  return (
    <div className="App">
      <h1>{title}</h1>
      <button onClick={}>Generate</button>
    </div>
  );
}

export default App;

How to get property from TopoJSON file using D3.js version 7?

I have the following TopoJSON file:

{
    "type":"Topology",
    "arcs":[...],
    "transform":{
        "scale":[...],
        "translate":[...]
    },
    "objects":{
        "BRGR":{
            "type":"GeometryCollection",
            "geometries":[
                {
                "arcs":[[0,1,2]],
                "type":"Polygon",
                "properties":{
                    "codarea":"1"
                }
            },
            {
                "arcs":[[[3,4,5,-1]],[[6]]],
                "type":"MultiPolygon",
                "properties":{
                    "codarea":"2"
                }
            },
            {
                "arcs":[[[-5,7,8,9]],[[10]]],
                "type":"MultiPolygon",
                "properties":{
                    "codarea":"3"
                }
            },
            {
                "arcs":[[11,12,-9]],
                "type":"Polygon",
                "properties":{
                    "codarea":"4"
                }
            },
            {
                "arcs":[[-13,13,-2,-6,-10]],
                "type":"Polygon",
                "properties":{
                    "codarea":"5"
                }
            }]
        }
    }
}

I’m able to log it in the console using:

console.log(topology.objects.BRGR);

Having the following expected result:

{type: 'GeometryCollection', geometries: Array(5)}
  geometries: Array(5)
    0: {arcs: Array(1), type: 'Polygon', properties: {…}}
    1: {arcs: Array(2), type: 'MultiPolygon', properties: {…}}
    2: {arcs: Array(2), type: 'MultiPolygon', properties: {…}}
    3: {arcs: Array(1), type: 'Polygon', properties: {…}}
    4: {arcs: Array(1), type: 'Polygon', properties: {…}}
    length: 5
    [[Prototype]]: Array(0)
    type: "GeometryCollection"
    [[Prototype]]: Object

I’m unable to log the value of codarea directly. What brought me the closest solution was:

console.log(topojson.feature(topology, topology.objects.BRGR).features);

I’ve tried a lot of possibilities such as:

console.log(topojson.feature(topology, topology.objects.BRGR).features.properties.codarea);

without success. I have no idea what we have to do to get this value.
Actually I’d like to use it in a D3.js script to modify the color of the map on the fly.
The code is:

// svg general properties
var width = 1024,
    height = 512;

// set projection
// https://github.com/d3/d3-geo#projections
var projection = geo.geoCylindricalEqualArea() // projeção cilíndrica equivalente de Lambert
    .parallel(32)
    .scale(670)
    .rotate([45,14,0]);

// color scheme
var colorScheme = d3.schemeBlues[5];
colorScheme.unshift("#eeeeee")
var colorScale = d3.scaleThreshold()
    .domain([0, 1])
    .range(colorScheme);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var path = d3.geoPath()
    .projection(projection);

var g = svg.append("g");

// load and display the map
d3.json("map.json").then(function(topology) {

    g.selectAll("path")
        .data(topojson.feature(topology, topology.objects.BRGR).features)
        .enter().append("path")

//---->
//----> THIS IS WHERE CODAREA WOULD MODIFY COLOR
//---->
        .style("fill", function (event, d) {
            // pull data for this state
            d.codarea = ???;
            // set the color
            return colorScale(d.codarea);
        })

        .attr("d", path)
});

And the highlighted part I extracted from http://bl.ocks.org/palewire/d2906de347a160f38bc0b7ca57721328 but differently from the source I’m using D3 version 7

//----> MY CODE
//----> THIS IS WHERE CODAREA WOULD MODIFY COLOR
//---->
        .style("fill", function (event, d) {
            // pull data for this state
            d.codarea = ???;
            // set the color
            return colorScale(d.codarea);
        })

And here the original code:

   .attr("fill", function (d){
        // Pull data for this country
        d.total = data.get(d.id) || 0;
        // Set the color
        return colorScale(d.total);
    })

But as I said, I can’t get the proper data from my TopoJSON. How would this be possible, so I can use it in the script?

sumifs for matching data and week of month

I’m trying to create a spreadsheet that sums expenses and returns them based on week of month.

Table 1 has 4 columns (date, description, amount, sumbyweek_rows)
table 2 has multiple columns (key for “sumbyweek_rows,” summed amount from “amount,” and several cells that check data against “description” to know whether to sum it or not)

On table 2 I’m struggling with sumifs. I’d like my summed amount to sum if there is any cell with matching data from the amount cell on table 1, it uses the description cell as a key. But I’d like a second check to see if the date column is week 1, 2, 3, or 4 of month.

I can do it without the date by doing this:

SUM(ARRAYFORMULA(SUMIF(CurrentMonth!$BC$2:$BC$1000,
{C6:AC6},CurrentMonth!$BD$2:$BD$1000)))

But I’m stuck at trying to convert it to SUMIFS including date checks. I’ve tried testing 3 dating methods and none of them work, but I don’t see why:

SUMIFS(CurrentMonth!$BD$2:$BD$1000,CurrentMonth!$BA$2:$BA$1000,”>=””/01/“,CurrentMonth!$BA$2:$BA$1000,”<=””/07/“)

SUMIFS(CurrentMonth!$BD$2:$BD$1000,CurrentMonth!$BA$2:$BA$1000,”>=”&date(,,01),CurrentMonth!$BA$2:$BA$1000,”<=”&date(,,07))

SUMIFS(CurrentMonth!$BD$2:$BD$1000,1,WEEKNUM(BA2:BA1001)-WEEKNUM(EOMONTH(BA2:BA1001,-1)+1)

How to install fullCalendar in apps script?

I’m currently developing a web app with Google Apps Script using server side JavaScript & client side HTML & JavaScript. The available Google Calendar class lacks all my required features so I’m using an external library. I am not experienced in using JavaScript 3rd party libraries and uncertain how to install the fullCalendar library. It appears as though I’d have to install through a zip folder but I don’t believe that is possible in Google Apps Script as there is no way to download and extract the setup. I started with python and know I can I host a self developed package for install through pip/conda but I don’t know how to do that with JavaScript.

https://fullcalendar.io/docs/initialize-globals

https://fullcalendar.io/docs/initialize-es6

How can I install this in Apps Script?

If I can’t install it directly in Apps Script, is there somewhere I can freely host the unzipped files to install from?
Is there a way to install fullCalendar in regular javascript besides downloading a zip folder?

Cypress overwrite ‘type’ command to add a small wait throws promise error if .clear() is called before

Not sure quite why this is occurring. I’d like to add a .wait() before all type commands in my app by overwriting the type command. However I’m running into some issues with the promise quirks of cypress.

Here’s some minimal code to reproduce

<html>
<body>
  <input/> 
</body>
</html>
//someSpec.js
cy.get('input').clear().type(name);
//commands.js
Cypress.Commands.overwrite(
  "type",
  (originalFn, subject, text, options) => {
    cy.wait(0).then(() => originalFn(subject,text,options))
  }
);

This will trigger a cypress error complaining about returning a promise:

Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise.

The command that returned the promise was:

  > cy.clear()

The cy command you invoked inside the promise was:

  > cy.wait()

Because Cypress commands are already promise-like, you don't need to wrap them or return your own promise.

Cypress will resolve your command with whatever the final Cypress command yields.

The reason this is an error instead of a warning is because Cypress internally queues commands serially whereas Promises execute as soon as they are invoked. Attempting to reconcile this would prevent Cypress from ever resolving.

Can anyone please help me get past this hurdle? Thanks!

Related issues: https://github.com/cypress-io/cypress/issues/3166

How to make content display in three columns instead of one column?

I am a beginner and learning from a tutorial using an API. I would like to change the layout of the design, and instead of having one column, I would like a three column layout. I don’t know if I am using flexbox correctly.

I have tried using row and then having three columns, but somehow its not displaying correctly.I am also using bootstrap.

jsfiddle.net/e5bqsywk/2/

Using Google App Script to find rental cars

Sorry for the rather generic title but making no assumptions on technical solutions…

I am new to Google Apps Script but learning fast. As a fun personal project, I want to build a small application which goes off to Avis and retrieves rental car prices and availability.

I have registered with developer.avis.com and successfully run the following code snippet:

function avis(){

  var avURL = 'https://developer.avis.com/swagger/spec/car_availability.json';
  var avHtml = UrlFetchApp.fetch(avURL).getContentText();
  var avDoc = JSON.parse(avHtml);

}

avDoc comes back as nice structured JSON with all the parameter fields the Avis document says will be needed to retrieve a rental quote.

I assume I now need to fill the parameters in and get avDoc back over to Avis.

But how ? Please indulge this total noob with pointers on how to do so !!

Thanks