React get array from MongoDB Stitch into react-bootstrap-table-next - javascript

I have a simple React app connected to MongoDB Stitch (Atlas) up and running, and am able to fetch some dummy data anonymously. I can display the array of data as text:
const {
Stitch,
RemoteMongoClient,
AnonymousCredential
} = require('mongodb-stitch-browser-sdk');
const client = Stitch.initializeDefaultAppClient('XXX-YYY');
const db = client.getServiceClient(RemoteMongoClient.factory, 'mongodb-atlas').db('vendor');
client.auth.loginWithCredential(new AnonymousCredential()).then(() =>
db.collection('vendor-item').find().asArray()
).then(docs => {
console.log("Found docs", docs);
const html = docs.map(docs => `
<div>${docs._id}</div>
<div>${docs.owner_id}</div>
<div>${docs.number}</div>`);
document.getElementById("comments").innerHTML = html;
}).catch(err => {
console.error(err)
});
And that displays as HTML as:
5e3dd30510807794cdef7968
5e3dac4310807794cde483f9
42
,
5e3dd30510807794cdef7978
5e3dd223340f9a51200f9192
42
,
5e3dd504ba978a97da4dc058
5e3dd503ba978a97da4dc020
42
However, I am trying to pull that data from the database and display it in a react-bootstrap-table-next table, which I have working out of the box, but also with different dummy data:
// dummy data
const data = [
{ id: 1, name: "Company 1", url: "http://www.google.com", loc:"san francisco, ca" },
{ id: 2, name: "Company 2", url: "http://www.bing.com", loc:"oakland, ca" }
];
const columns = [{
dataField: 'name',
text: 'Company'
}, {
dataField: 'url',
text: 'URL'
}, {
dataField: 'loc',
text: 'Location'
}];
Whereas I specifically need to combine the two methods and need the MongoDB array in the format that BootstrapTable is expecting, specifically as data={data} and columns={columns} as so:
<BootstrapTable
keyField="id"
data={data}
columns={columns}
striped
hover
condensed
bootstrap4
/>
I have already scoured the web for tutorials using "mongodb-stitch" and "react" and tried everything I could think of, with no luck.

Related

MapBox JS having issues connecting the data csv/google sheets files in our config.js code

We are working on a map with multiple points and trying to add a filter to it. Similar to this documentation: https://labs.mapbox.com/education/impact-tools/finder-with-filters/. Where we use a csv data file to add/update the location information.
We originally tried using the CSV: './Sample_Data.csv', line in our config.js file, but we were getting an error that said "XMLHttpRequest cannot load Sample_Data.csv due to access control checks.", and we are not sure what that error is or how to fix it.
config.js file with CSV code to link:
'use strict';
// eslint-disable-next-line no-unused-vars
const config = {
style: 'mapbox://styles/mapbox/light-v10',
accessToken:
'pk.eyJ1IjoicmItZmlkZWxpdHkiLCJhIjoiY2wyNjdjeTlkMXd3dTNjanIzb2h2bDN1cCJ9.diGkmbkrJJRQegleKOHhhA',
CSV: './Sample_Data.csv',
style: 'mapbox://styles/mapbox/streets-v11',
center: [-120.234, 47.398],
zoom: 5,
title: 'Replace with your title',
description:
'Replace with information about your application. Ex. You can search by address to sort the list below by distance. You can also filter the list by language support options, which days a location is open, and whether they have devices to use to complete the survey by phone or online.',
sideBarInfo: ['Location_Name', 'Address', 'Phone'],
popupInfo: ['Location_Name'],
filters: [
{
type: 'dropdown',
title: 'Languages supported: ',
columnHeader: 'Languages',
listItems: [
'Amharic',
'ASL',
'Cambodian',
'Chinese',
'Danish',
'English',
'French',
'German',
'Greek',
'Hindi',
'Italian',
'Japanese',
'Korean',
'Language Line Services',
'Norwegian',
'Oriya',
'Portuguese',
'Punjabi',
'Russian',
'Somali',
'Spanish',
'Swedish',
'Tagalog',
'Thai',
'Tigrinya',
'Tongan',
'Vietnamese',
'Ukranian',
'TEST'
],
},
{
type: 'checkbox',
title: 'Devices available: ',
columnHeader: 'Devices_available', // Case sensitive - must match spreadsheet entry
listItems: ['Computer', 'Wi-Fi', 'Adaptive Laptops'], // Case sensitive - must match spreadsheet entry; This will take up to six inputs but is best used with a maximum of three;
},
{
type: 'dropdown',
title: 'Clients: ',
columnHeader: 'Clients',
listItems: [
'Adults',
'Disabled',
'Homeless',
'Immigrants/Refugees',
'Low Income',
'Seniors',
'Youth: Pre-teen',
'Youth: Teen',
],
},
],
};
We also tried making a Google Sheet of the csv data, that we can use and update, but are not sure where we can place the code correctly, in our config.js file for it to connect to the sheet and use its data.
From the documentation that we read on Sheet Mapper: https://labs.mapbox.com/education/impact-tools/sheet-mapper/, we got this code:
$(document).ready(function () {
$.ajax({
type: "GET",
//YOUR TURN: Replace with csv export link
url: 'https://docs.google.com/spreadsheets/d/1DbFiU7vOnFFBI57HHjOOSZcRxoH7hbErn7kTlm3kwiw/gviz/tq?tqx=out:csv&sheet=FIDELITY-MAPBOX-DATA',
dataType: "text",
success: function (csvData) { makeGeoJSON(csvData); }
});
Either method we can't get to work and are stuck how to proceed.
Thank you for any help.

Refresh table LWC

I've been trying to rerender a table when I update an Account record with a lightning-record-form.
I tried looking up a solution to this with similar questions I found here but I'm still not able to achieve this.
In this case I hardcoded the recordId with the Account with the name 'Gonzalo' shown in the preview below all the code. So the wanted result is to update the account name or any field and see the instant outcome in the table.
Here's my code:
Apex method (just in case):
#AuraEnabled(cacheable=true)
public static List<Account> getCuentas() {
return [SELECT id, Name, Phone FROM Account LIMIT 5];
}
Form (HTML):
<lightning-record-form
object-api-name="Account"
record-id="0015e00000F2JoWAAV"
fields={fields}
onsubmit={handleSubmit}
>
</lightning-record-form>
Table (HTML):
<lightning-datatable
key-field="pk"
data={cuentas}
columns={columnas}
onrowselection={action}
hide-checkbox-column
onrowaction={handleRow}
default-sort-direction={defaultSortDirection}
sorted-direction={sortDirection}
sorted-by={sortedBy}
onsort={onHandleSort}
>
</lightning-datatable>
Related code (JS):
***Imports***
import { refreshApex } from '#salesforce/apex';
import NAME from '#salesforce/schema/Account.Name';
import PHONE from '#salesforce/schema/Account.Phone';
import getCuentas from '#salesforce/apex/ProbandoJSON.getCuentas';
import { LightningElement, api, wire, track } from 'lwc';
***Vars for the form fields***
fields = [NAME, PHONE];
***Columns***
columnas = [
{
label: 'View',
type: 'button',
initialWidth: 75,
typeAttributes: {
label: {
fieldName: 'Boton'
},
title: 'Preview',
alternativeText: 'View',
variant: 'border-filled'
}
},
{
label: 'Name',
fieldName: 'Name',
sortable: true
},
{
label: 'Phone',
fieldName: 'Phone'
}
];
***Accounts***
#track cuentas = [];
_wiredResult;
#wire(getCuentas)
wireCuentas(result) {
this._wiredResult = result;
if(result.data) {
console.log('cuentas');
console.log(result.data);
for(var i in result.data) {
let obj = {};
obj.Id = result.data[i].Id;
obj.Name = result.data[i].Name;
obj.Phone = result.data[i].Phone;
obj.Boton = parseInt(i) + 1;
this.cuentas = [...this.cuentas, obj];
}
console.log('cuentas de nuevo');
console.log(this.cuentas);
} else if(result.error) {
console.log('error cuentas');
console.log(result.error);
}
}
***Submit handler for the Save button in the form***
handleSubmit(event) {
console.log('saving...')
return refreshApex(this._wiredResult);
}
Preview of the component:
Table
Form
Looks like a cache issue.
We can solve this in a couple of ways as follow:
Removing cacheable
You need to remove (cacheable=true) and then have to call the apex method imperatively on each form updates or while loading initial data.
Creating an unnecessary parameter in apex method which will be having new value on each call
You need to receive an additional parameter as a integer in the apex method, and then in lwc just create a var initializing it with 0, and on each update increment it by 1.
Then use same var to call the apex method via wire or in imperative calls.

Is this a correct api response?

I'm trying to learn about API's and am creating a simple response when a user hit's an endpoint on my basic express app.
I'm not sure what constitutes a correct API response though, does it need to be an object?
The data I was given is an array of arrays and I export it from a file and return it in the express app as an object using response.json(), it displays ok but I'm not sure if I'm following the right approach for how I'm handling it and displaying it.
I would like to understand how should API data be returned, I had the feeling that it should always be an object but what I'm returning here is an array of arrays, some explanation to understand this better would be helpful please.
Here is my data file:
export const data = [
[
'a9e9c933-eda2-4f45-92c0-33d6c1b495d8',
{
title: 'The Testaments',
price: { currencyCode: 'GBP', amount: '10.00' },
},
],
[
'c1e435ad-f32b-4b6d-a3d4-bb6897eaa9ce',
{
title: 'Half a World Away',
price: { currencyCode: 'GBP', amount: '9.35' },
},
],
[
'48d17256-b109-4129-9274-0bff8b2db2d2',
{ title: 'Echo Burning', price: { currencyCode: 'GBP', amount: '29.84' } },
],
[
'df2555ad-7dc2-4b1f-b422-766184b5c925',
{
title: ' The Institute',
price: { currencyCode: 'GBP', amount: '10.99' },
},
],
];
Here is a snippet from my express app file which imports the data object for this endpoint:
app.get('/books', (request, response) => {
response.json({ books: data });
});
Looks okay, one thing I would do is ensure the root of the object you return always has the same name between api calls, so here your root object name is "books":
app.get('/books', (request, response) => {
response.json({ books: data });
});
I would personally change this to something like:
app.get('/books', (request, response) => {
response.json({ data: data });
});
Now that may seem confusing, but what that means is when your api is queried, the actual resources the api is returning is always in an object called data, it just builds a common pattern for where people should be expecting to see the api response resources in your JSON response.
So if you had another endpoint for authors for example, people will know the authors response will be under an object called data:
app.get('/authors', (request, response) => {
response.json({ data: authors });
});

Using PostgreSQL COPY instead of INSERT with Sequelize.bulkCreate()?

Read several sources stating how COPY is faster than INSERT statements in PostgreSQL when performing bulk ingests. Sequelize.js has a bulkCreate() function for doing bulk INSERTs.
Is it possible for Sequelize to do COPY instead of INSERT, and do you expect COPY to be faster? I am ingesting 10,000-1,000,000 rows at a time in each of the 5 parallel processes running for a total of 2 hours. Hope some speedups can be achieved using COPY and Sequelize.
Actual database is using TimescaleDB extension
Example Code
let Note = sequelize.define('notes', {
description: Sequelize.STRING
});
let notes = [
{ description: 'Tai chi in the morning' },
{ description: 'Visited friend' },
{ description: 'Went to cinema' },
{ description: 'Listened to music' },
{ description: 'Watched TV all day' },
{ description: 'Walked for a hour' },
];
Note.bulkCreate(notes, { logging: console.log }).then(() => {
console.log('notes created');
}).catch((err) => {
console.log(err);
}).finally(() => {
sequelize.close();
});
Generated SQL
INSERT INTO "notes" ("id","description") VALUES (DEFAULT,'Tai chi in the morning'),
(DEFAULT,'Visited friend'),(DEFAULT,'Went to cinema'),(DEFAULT,'Listened to music'),
(DEFAULT,'Watched TV all day'),(DEFAULT,'Walked for a hour') RETURNING *;

Vue not updating Vuetify data-table from array with data from Axios request

I have a problem and have been looking for hours to get it resolved, without any success.
In short: in a forEach loop I am adding my const "mijndata" to my array "Signalen". I can see that my array is filled successfully.
However, my data-table component from Vuetify is not showing my data. If I click the sort column or if I do a search, my data suddenly appears. So the problem must be that Vue doesn't detect changes to the "signalen" array.
I have already read multiple other threads on this issue and I have read: https://v2.vuejs.org/v2/guide/list.html#Caveats
But I am so far unable to resolve this issue.
Note: if I do a direct push into my "signalen" array from the results of my Axios calls, I don't have this problem. But unfortunately this is not an option as I am needing to create an object which is then pushed into the array.
Here is my problem in code:
mounted () {
axios.get('/my api url').then(response => {
const signalen = response.data.resources;
signalen.forEach((signaal) => {
const mijndata = {};
axios.get('/my api url').then(response => {
const relatedSensoren = response.data.resources;
relatedSensoren.forEach(relatedSensor => {
axios.get('/my api url').then(response => {
const sensorConfigs = response.data.resources;
sensorConfigs.forEach(sensorConfig => {
axios.get('/my api url').then(response => {
const alarmRegels = response.data.resources;
alarmRegels.forEach(alarmRegel => {
axios.all([axios.get('/my api url')])
.then(axios.spread((...responses) => {
mijndata.signaalid = signaal.ac_id;
mijndata.signaalsettingid = alarmRegel.ar_id;
}));
});
});
});
});
});
});
//A few more gets following the same logic as above...
//Push my const "mijndata" into my array "signalen"
this.signalen.push(mijndata)
});
});
//I can see that all of my objects are in my array "signalen"
window.console.log(this.signalen)
},
My data-table:
<v-data-table
:headers="headers"
:items="signalen"
:search="search"
class="elevation-1"
>
My array in my export:
export default {
data: () => ({
headers: [
{
text: 'Signaalnummer',
align: 'left',
value: 'signaalid',
},
{ text: 'Wanneer gaat dit alarm af?', value: 'signaalsetting' },
{ text: 'Manier van alarmeren', value: 'alarmsetting' },
{ text: 'Geadresseerde', value: 'alarmpersoon' },
{ text: 'Actions', value: 'action', sortable: false },
],
signalen: [],
}),
The headers match the keys from my array. Like I said, the problem is purely in pushing my "mijndata" object into my "signalen" array.
I would really appreciate any help!
Finally found the answer.
I fixed it by using Vue.set on the const "mijndata".
Eg: Vue.set(mijndata, 'signaalid', signaal.ac_id)

Categories