Time-based charts

I’m trying to set up a couple of time-based charts on my dashboard. These are for an e-commerce platform. Basically, we want to see the number of orders received over time, and the revenue generated by these.

Expected behavior

Show time-based charts in the dashboard. I asked about time-based charts before in this forum, and I was told that the date and price should be at the root of the document in order for it to work. We have made these changes but we are now experiencing a different issue.

Actual behavior

I’m getting this error in the console: (0 , _moment.default)(...).tz is not a function
Here’s an order object.

/** 
* Paste one or more documents here
*/
{
    "status": "unfulfilled",
    "cart": [{
        "_id": {
            "$oid": "5f784360f121c4d731af0cbd"
        },
        "productID": "B0199ANV1G",
        "image": "https://images-na.ssl-images-amazon.com/images/I/514iLbGzE1L.jpg",
        "title": "Huy Fong, Sriracha Hot Chili Salsa, 9 onzas botella (2 unidades) por Sriracha",
        "price": "11.76",
        "qty": 1,
        "link": "https://www.amazon.com/-/es/Sriracha-Chili-onzas-botella-unidades/dp/B0199ANV1G",
        "variant": "MAIN",
        "supplier": {
            "name": "Amazon"
        }
    }],
    "userID": "xxxxxxxxxxxxxx",
    "email": "someemail@gmail.com",
    "phoneNumber": "+34555555",
    "price": 21.75,
    "payment": {
        "txID": "xxxxxx",
        "method": "Stripe",
        "last4": "1111",
        "brand": "MasterCard"
    },
    "shipping": {
        "address": {
            "_id": {
                "$oid": "5f784360f121c481f9af0cbe"
            },
            "country": "Venezuela",
            "firstName": "Carlos Enrique",
            "lastName": "Suito",
            "phoneNumber": "+34555555",
            "street": "Ronda de Sant Antoni, 80",
            "houseOrAptNumber": "Atico",
            "city": "Caracas",
            "state": "Distrito Capital",
            "municipality": "Ciutat Vella",
            "postCode": "08001",
            "additionalInfo": "Tocar intercomunicador"
        },
        "courier": "Tiger shipping",
        "method": "sea",
        "weight": "1.37",
        "dimensions": "0.33",
        "total": {
            "cost": 4.95,
            "price": 10
        },
        "eta": "3 de noviembre",
        "timeline": []
    },
    "creationDate": {
        "$date": "2020-10-03T09:24:48.216Z"
    },
    "updatedOn": {
        "$date": "2020-10-03T09:24:48.216Z"
    },
    "__v": 0
}

So basically, creationDate is of type Date, but for some reason it’s messing up forest’s charts. Any ideas how might I solve this problem?

Thanks!

Failure Logs

VM2935:1 POST https://xxxx.herokuapp.com/forest/stats/orders 500 (Internal Server Error)
"{"errors":[{"status":500,"detail":"(0 , _moment.default)(...).tz is not a function"}]}"

Context

  • Package Version: 3.6.5
  • Express Version: ~4.16.3
  • Sequelize Version:
  • Database Dialect: MongoDB
  • Database Version: 4.2.8
  • Project Name: Tranki

Hi @Henry_O ! Can you tell me if you are using forest-express-mongoose or forest-express-sequelize ? And what is the version of the package you are using ?

Hi @Nicolas_Sailly ! I’m using mongoose.

Ok, let me check that and get back to you :+1:

Are you using Mongo Atlas, documentDB ?
Can you share the field type/declaration for your dates ?
When I use the classes specified in the mongo doc I get a well formatted Date :face_with_monocle:
For example:

Gives me:

@Nicolas_Sailly

We are using MongoDB Atlas indeed.

Here’s the declaration of the dates in the model:

  creationDate: { type: Date, required: true, default: Date.now },
  updatedOn: { type: Date, required: true, default: Date.now }

Can you share with me the body of the request sent when loading the chart ? It should have a timezone in it.

Hi @Nicolas_Sailly!

Here’s the body of the POST to /forest/stats/orders

{
   type: "Line",
   collection: "orders",
   timezone: "Europe/Madrid",
   aggregate_field: "price",
   aggregate: "Sum"
   aggregate_field: "price"
   collection: "orders"
   group_by_date_field: "creationDate"
   time_range: "Day"
   timezone: "Europe/Madrid"
   type: "Line"
}

Hi @Henry_O,

I’ve just tried to reproduce your issue without success: my chart is well displayed and no error for a project using MongoDB Atlas.

Can I ask you what version of forest-express-mongoose you’re using please?

What’s more, I am really not an expert of mongo, but I’ve noticed your creationDate in your order is not directly given (as I had it in my test), but it’s underneath a $date object.
Why do you have this structure?

Thanks.

@adriguy Hi! I don’t really know why it’s inside an object. A few messages before I posted the model declaration of those two properties (creationDate and updatedOn), and both are pretty straightforward.

I’m using "forest-express-mongoose": "^6.0.0"

Here’s the model declaration for the dates:

  creationDate: { type: Date, required: true, default: Date.now },
  updatedOn: { type: Date, required: true, default: Date.now }

Could it be something MongoDB Atlas is doing?

Ok so the problem is probably not from forest-express-mongoose version.
And your model declaration in your admin backend seems fine, so is the data structure.

It’s weird because the error you get seems to come from the fact that the moment-timezone is not installed properly.
Can you confirm that it’s part of your forest-express-mongoose dependencies?
And could you try to remove and reinstall all the admin backend dependencies?

Hi @adriguy!

So I removed my node_modules and did yarn install again. moment-timezone is indeed in my node_modules and I can see in my yarn.lock that it is a dependency of forest-express-mongoose:

forest-express-mongoose@^6.0.0:
  version "6.3.3"
  resolved "https://registry.yarnpkg.com/forest-express-mongoose/-/forest-express-mongoose-6.3.3.tgz#2bbbb3d99c3f8fca4f79ce317bb867897278dd78"
  integrity sha512-6Eq+S1qo1lWth9DzctIilaema9jW80vSSRwWJr4wJcoHuwwJ+tCZTSiYvTxW/LVBI3Vr122SB2T6awMye225xA==
  dependencies:
    "@babel/runtime" "7.10.1"
    bluebird "2.9.25"
    forest-express "7.3.1"
    http-errors "1.7.2"
    lodash "4.17.13"
    moment "2.24.0"
    moment-timezone "0.5.27"
    semver "5.6.0"

Here’s the full error message, maybe you guys can spot what’s going wrong.

[forest] 🌳🌳🌳  Unexpected error: (0 , _moment.default)(...).tz is not a function
TypeError: (0 , _moment.default)(...).tz is not a function
    at new LineStatFinder (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/dist/services/line-stat-getter.js:31:54)
    at Stats.get (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/forest-express/dist/routes/stats.js:67:17)
    at Layer.handle [as handle_request] (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/express/lib/router/layer.js:95:5)
    at next (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/express/lib/router/route.js:137:13)
    at dispatch (/Users/henry/dev/Tranki/Forest/node_modules/compose-middleware/lib/index.js:46:24)
    at next (/Users/henry/dev/Tranki/Forest/node_modules/compose-middleware/lib/index.js:51:24)
    at ipAuthorizer (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/forest-express/dist/middlewares/ip-whitelist.js:23:12)
    at /Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/forest-express/dist/services/auth.js:61:10
    at dispatch (/Users/henry/dev/Tranki/Forest/node_modules/compose-middleware/lib/index.js:63:32)
    at next (/Users/henry/dev/Tranki/Forest/node_modules/compose-middleware/lib/index.js:51:24)
    at ensureAuthenticated (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/forest-express/dist/services/auth.js:31:10)
    at dispatch (/Users/henry/dev/Tranki/Forest/node_modules/compose-middleware/lib/index.js:63:32)
    at middleware (/Users/henry/dev/Tranki/Forest/node_modules/compose-middleware/lib/index.js:76:16)
    at /Users/henry/dev/Tranki/Forest/node_modules/compose-middleware/lib/index.js:15:47
    at Layer.handle [as handle_request] (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/express/lib/router/layer.js:95:5)
    at next (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/express/lib/router/layer.js:95:5)
    at /Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/express/lib/router/index.js:281:22
    at Function.process_params (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/express/lib/router/index.js:335:12)
    at next (/Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/express/lib/router/index.js:275:10)
    at /Users/henry/dev/Tranki/Forest/node_modules/forest-express-mongoose/node_modules/express-jwt/lib/index.js:128:7
    at /Users/henry/dev/Tranki/Forest/node_modules/async/lib/async.js:52:16
    at Immediate._onImmediate (/Users/henry/dev/Tranki/Forest/node_modules/async/lib/async.js:1206:34)
    at processImmediate (internal/timers.js:456:21)

@Henry_O it is very strange…
Can you tell me what is your Node version?

Hi,

Did you find a solution ?

I’m experiencing the same issue issue with any date field on my collection.
The moment and moment-timezone package are well installed and I’ve also tried to install them manually but nothing change.

  • I’m using a self hosted mongo docker image (mongo:4.2)
"meta": {
    "database_type": "MongoDB",
    "liana": "forest-express-mongoose",
    "liana_version": "6.3.8",
    "engine": "nodejs",
    "engine_version": "10.22.1",
    "framework": "other",
    "framework_version": null,
    "orm_version": "5.10.8"
  }

Hi @Florian_Belliard @Henry_O

I’m currently not able to reproduce your issue either, running forest-express-mongoose 6.3.8 or 6.3.3.
In fact, I also did log moment inside the forest-express-mongoose, and in my case, _moment.default has a tz function (This is most likely the reason why I’m not able to reproduce).

In order to debug this, and if that’s possible on your end, could modify node_modules/forest-express-mongoose/dist/services/line-stat-getter.js and log the _moment.default value L.30 ?

Also, your node version would be useful, just in case this issue could come from there, or any other informations that could be useful to reproduce your issue ?

Thanks in advance.

Hey guys, I have fixed the problem by going to node_modules/forest-express-mongoose/dist/services/line-stat-getter.js and changing the import of _moment.

The issue seems to be that even though forest-express-mongoose has moment-timezone as a dependency, it is not using it.

Before:
L15
var _moment = _interopRequireDefault(require("moment"));

Now:
L15
var _moment = _interopRequireDefault(require("moment-timezone"));

I did log the _moment["default"]() function and I realized it didn’t have any of the moment-timezone methods. That’s when I noticed the file was importing moment and not moment-timezone.

Now the problem is that I can’t change this in my Heroku production deployment. :frowning:

@Florian_Belliard

BTW, I’m currently using node 14.14 but was using 12.16 yesterday. I don’t think the problem is related to the node version.

From what I can see here, moment-timezone should extends moment by adding it’s feature.

This was done like this most likely because of the mentionned issue (Just like describe on this SO post, found using your error).

In the meantime, if you feel like it, I would suggest to create a PR on forest-express-mongoose with what leads you to this fix.

I’ll need to further investigate to see exactly what is wrong & why we are not able to reproduce this issue on our end (The fix you proposed makes me think that we should all experience the issue, but I might be wrong here).

Sorry for the inconvenience here, but since I’m not able to reproduce, it’s not very easy for me to fix it :pray:

Hey @jeffladiray!

So I believe it may be an issue with the build in production. I just forked Forest and when I go to that specific file I can see you guys are directly importing both moment and moment-timezone:

// src/services/line-stat-getter.js


import P from 'bluebird';
import moment from 'moment';
// NOTICE: moment-timezone extends moment itself,
//         Importing it will automatically add functions to moment.
import 'moment-timezone';

Then when I build the repo, I can see both modules being imported as well:

// dist/services/line-stat-getter.js
// L15-17
var _moment = _interopRequireDefault(require("moment"));
require("moment-timezone");

However, as we can see in my project, the master branch with the built version is only importing moment.

The thing is I can’t make a PR with the fixed because it looks fixed in the src and dist folders. Which only makes it even more confusing lol.

EDIT:

So I just deleted my node_modules folder and rebuilt it with yarn and now I can see both the moment and moment-timezone imports. However, I still have to manually modify the import of moment to moment-timezone in order to make it work.

1 Like

Thank you!

I’m totally able to reproduce your issue, and your last message really helped! Most of us are yarn linked to the forest-express-mongoose, My best guess is that the issue is not visible when linked.

Anyway, I’m opening a ticket on our end to fix this.

@jeffladiray Great!

I do believe importing moment-timezone alone is enough. I believe this package is just a buffed up version of moment with all the original functionality + the timezone stuff. So I’m guessing simply modifying

// src/services/line-stat-getter.js
// L4
import moment from 'moment';

to:

// src/services/line-stat-getter.js
// L4
import moment from 'moment-timezone';

Should fix it alltogether.

If you want I can make a PR with that change.

Thanks!

1 Like