I am building a chat application using vueJs and I would like to display date labels just like whats app.
Messages are received in following format on client side
{
{
author: 21,
created_at: "12:09 pm",
data: "chat message",
message_group: "today",
type: "text"
},
{
author: 22,
created_at: "11:30 pm",
data: "chat message 2",
message_group: "today",
type: "text"
},
{
author: 22,
created_at: "11:29 pm",
data: "chat message 3",
message_group: "yesterday",
type: "text"
}
}
How do I print messages in following format.
Yesterday
Chat Message 3
Today
Chat Message 2
Chat Message
How can I do it without grouping the array?
Thank you
Can't do it in the comment up there so putting it as an answer.
You can have a computed property or getter (vuex) to get the day labels without grouping as below
// Do your sorting first
computed: {
dayLabels() {
return a.reduce((acc, message) => {
if (!acc.includes(message.message_group)) {
acc.push(message.message_group);
}
return acc;
}, []);
}
}
Related
I am using amplify cli having dynamo database along with GraphQL API. I have a sales model which keep sales record i.e sale amount along with the date. I want to aggregate the sales amount for each month in a year to show the sales statistics on a graph which show total sales made in each month over the year. Currently I am using GraphQL queries to query/search data from the backend.
Here is the model that I am using.
type Sales #model #searchable #auth(rules: [{ allow: private }]) {
id: ID!
userID: String! #index(name: "byAdded", sortKeyFields: ["createdAt"])
createdAt: AWSDateTime!
saleAmount: Float
}
Here is the example usage of graphQL query that I am currently using to get a aggregated amount for the whole year.
await API.graphql(
graphqlOperation(searchSales, {
filter: {
and: [
{ userID: { eq: userId } },
{ createdAt: { range:["2022-01-01", "2022-12-31"] } },
],
},
aggregates: {
type: 'sum',
field: 'saleAmount',
name: 'totalSales',
},
}),
);
Currenty Query result:
{"aggregateItems": [{"name": "totalSales", "result": {"value": 4608} }], "nextToken": "WyIwZTUyNmY2JkMjUiXQ==", "total": 7}
I want to have a result like following:
aggregations : { jan: 234, feb: 343, march: 3465, ...... }
I am facing an issue with an excel file. I receive some data from the DB and the user should be able to replace that data with a spreadsheet that looks like this:
This is how the data comes from the DB and how the excel file should be finally formatted:
"employers": [{
"id": "4147199311345513",
"shifts": [{
"url": "https://zoom.com/983493unsdkd/",
"days": "Mon,Tue,Wed,Thu,Fri",
"name": "Morning",
"endTime": "12:00",
"timezone": "CST",
"startTime": "8:00"
}, {
"url": "https://zoom.com/983493unsdkd/",
"days": "Mon,Tue,Wed,Thu,Fri",
"name": "Afternoon",
"endTime": "12:00",
"timezone": "CST",
"startTime": "8:00"
}],
"employerUrl": "http://www.google.com",
"employerName": "AT&T",
"employerUrlText": "URL Text",
"employerLogoSmall": "assets/images/att-logo.png",
"employerDescription": "AT&T is a world premier employer with a bunch of stuff here and there."
}, {
"id": "3763171269270198",
"shifts": [{
"url": "https://zoom.com/983493unsdkd/",
"days": "Mon,Tue,Wed,Thu,Fri",
"name": "Morning",
"endTime": "12:00",
"timezone": "CST",
"startTime": "8:00"
}, {
"url": "https://zoom.com/983493unsdkd/",
"days": "Mon,Tue,Wed,Thu,Fri",
"name": "Afternoon",
"endTime": "12:00",
"timezone": "CST",
"startTime": "8:00"
}],
"employerUrl": "http://www.google.com",
"employerName": "AT&T",
"employerUrlText": "URL Text",
"employerLogoSmall": "assets/images/att-logo.png",
"employerDescription": "AT&T is a world premier employer with a bunch of stuff here and there."
}]
So I need to take that spreadsheet and format it to look like that JSON above. All of this with Javascript/React.
This is what I have so far to format my excel file and render it:
const [excelData, setExcelData] = useState({ rows: [], fileName: "" });
const fileHandler = (event) => {
let fileObj = event.target.files[0];
ExcelRenderer(fileObj, (err, resp) => {
if (err) {
console.log(err);
} else {
let newRows = [];
let shiftRows = [];
console.log(resp.rows);
resp.rows.slice(1).map((row, index) => {
if (row && row !== "undefined") {
return newRows.push({
key: index,
employer: {
name: row[0],
description: row[1],
employerUrl: row[2],
employerUrlText: row[3],
shifts: shiftRows.push({ shift: row[2] }),
},
});
}
return false;
});
setExcelData({ rows: newRows, fileName: fileObj.name });
}
});
};
That console.log above (console.log(resp.rows)) returns this:
Where the first row are the headers of the excel file.
And the code above ends up like this and it should be exactly as the JSON I mentioned:
rows: [
{
key: 0,
employer: {
name: 'AT&T',
description: 'AT&T is a world premier employer with a bunch of stuff here and there.',
shifts: 1
}
},
{
key: 1,
employer: {
shifts: 2
}
},
{
key: 2,
employer: {
shifts: 3
}
},
{
key: 3,
employer: {
shifts: 4
}
},
{
key: 4,
employer: {
name: 'Verizon',
description: 'Verizon is a world premier employer with a bunch of stuff here and there.',
shifts: 5
}
},
{
key: 5,
employer: {
shifts: 6
}
},
{
key: 6,
employer: {
shifts: 7
}
},
{
key: 7,
employer: {
shifts: 8
}
}
],
fileName: 'EmployerChats.xlsx',
false: {
rows: [
{
url: 'https://www.youtube.com/kdfjkdjfieht/',
title: 'This is a video',
thumbnail: '/assets/images/pages/5/links/0/link.png',
description: 'This is some text'
},
{
url: 'https://www.youtube.com/kdfjkdjfieht/',
title: 'This is a video',
thumbnail: '/assets/images/pages/5/links/1/link.png',
description: 'This is some text'
}
]
},
I am using this plugin to help me render the excel file: https://www.npmjs.com/package/react-excel-renderer
Any ideas on what can I do to make format the spreadsheet data as the JSON?
Please notice those empty rows.
For example every time there is a new employer name, that's a new row or item in the array, then all of the columns and rows below and after Shift Name is a new nested array of objects. Hence, this file contains an array with a length of 2 and then it contains another array of items when it hits the Shift Name column.
Is it clear?
1st of all - you don't need to follow 'original', class based setState. In FC you can just use two separate useState.
const [rows, setRows] = useState([]);
const [fileName, setFileName] = useState("");
Data conversion
I know that you need a bit different workflow, but this can be usefull (common point - data structure), too - as conversion guide, read on.
You don't need to use ExcelRenderer to operate on data from db and render it as sheet. Converted data can be exported to file later.
You can just create array of array (aoa) that follows expected view (rows = array of row cells array). To do this you need very easy algorithm:
let newData = []
map over emplyers, for each (emp):
set flag let first = true;
map over shifts, for each (shift):
if( first ) { newData.push( [emp.name, emp.descr, shift.name, shift.timezone...]); first = false;
} else newData.push( [null, null, shift.name, shift.timezone...]);
setRows( newData );
Rendering
<OutTable/> operates on data and colums props - structures similar to internal state. 'datais ourrows, we only needcolumns` prop, just another state value:
const [columns, setColumns] = useState([
{ name: "Employer name", key: 0 },
{ name: "Employer description", key: 1 },
{ name: "Shift name", key: 2 },
// ...
]);
and finally we can render it
return (
<OutTable data={rows] columns />
Later
User can operate on sheet view - f.e. insert rows using setRows() or download this as file (XLSX.writeFile()) after simple conversion:
var ws = XLSX.utils.aoa_to_sheet( columns.concat( rows ) );
There is a lot of utils you can use for conversions - see samples.
Back to your needs
We have data loaded from db, data in aoa form, rendered as sheet. I don't fully understand format you need, but for your db format conversion is simple (opposite to above) - you can follow it and adjust to your needs.
let newEmployers = [];
let empCounter = -1;
// itarate on rows, on each (`row`):
rows.map( (row) => {
// new employer
if( row[0] ) {
newEmployers.push( {
// id should be here
"employerName": row[0],
"employerDescription": row[1],
"shifts": [
{
"shiftName": row[3],
"shiftDescription": row[4],
// ...
}
]
} );
empCounter ++;
} else {
// new shift for current employer
newEmployers[empCounter].shifts.push(
{
"shiftName": row[3],
"shiftDescription": row[4],
// ...
}
);
}
});
// newEmployers can be sent to backend (as json) to update DB
I am building a zapier integration for an app. The app returns a JSON response like this...
{
result: "Success",
message: "Showing a total of 1 bookings",
bookings: {
42: {
event: {
event_name: "Chris's Event",
event_date_uk: "Saturday 22nd Jun 2019"
}
}
}
}
In my zapier parser, I have the following....
const options = {
url: bundle.authData.url+`/api/v1/bookings`,
method: 'GET',
headers: {
'Accept': 'application/json'
},
params: {
'key': bundle.authData.api_key,
'secret': bundle.authData.client_secret,
'booking_id': 42,
'scope': 'full'
},
}
return z.request(options)
.then((response) => {
response.throwForStatus();
const results = z.JSON.parse(response.content);
return results["bookings"];
});
However, when I test, I get the following....
Results from triggers.new_booking.operation.perform must be an array of objects. We got {"42": {"event": {"event_name": "Chris's Event", "event_date_uk": "Saturday 22nd Jun 2019"}}}.
I thought JSON.parse did return an object? And from what I can see I have returned an array of objects. Any ideas what Im doing wrong?
This contains an array of objects (bookings):
{
"result": "Success",
"message": "Showing a total of 1 bookings",
"bookings": [
{
"42": {
"event": {
"event_name": "Chris's Event",
"event_date_uk": "Saturday 22nd Jun 2019"
}
}
}
]
}
Edit: To access the event property in your JSON it's bookings.42.event where in JSON above it's bookings[0].42.event.
There are 52 weeks in a year, If i manually group 13 weeks into one quarter, it will give me a wrong result in high charts. Sometimes 13th week will be in 2nd quarter,so is there any function which will group weeks into quarter ?
Iam gettting data in following format:
Response is an object,consists of quarterNumber, actual production and planned production and weekwisedata, which is a list consists of weeknumber and weekly planned production and weekly actual production.
{"response":[{"quarterNumber":"1","actualQuarterProduction":"1.5","plannedQuarterProduction":"13.49","weekwisedata":[{"quarterNumber":1,"weekNumber":"1","weeklyPlannedProduction":"0","weeklyActualProduction":"0"}, {"quarterNumber":1,"weekNumber":"2","weeklyPlannedProduction":"13.49","weeklyActualProduction":"0"}, {"quarterNumber":1,"weekNumber":"3","weeklyPlannedProduction":"0","weeklyActualProduction":"0"},
{"quarterNumber":"2","actualQuarterProduction":"211.18","plannedQuarterProduction":"850",
"weekwisedata":[{"quarterNumber":2,"weekNumber":"14","weeklyPlannedProduction":"67.45","weeklyActualProduction":"0"},{"quarterNumber":2,"weekNumber":"15","weeklyPlannedProduction":"67.45","weeklyActualProduction":"0"},{"quarterNumber":2,"weekNumber":"16","weeklyPlannedProduction":"67.45","weeklyActualProduction":"0"},{"quarterNumber":2,"weekNumber":"17","weeklyPlannedProduction":"53.96","weeklActualProduction":"0"},{"quarterNumber":2,"weekNumber":"18","weeklyPlannedProduction":"67.45","weeklyActualProduction":"46.45"}]}
In Highchart iam displayng the data manually as shown below:
function(dataVal){
drilldown: {
series: [{
id: 'Quarter1a',
name: 'Actual Quality ',
data: [{
name: 'Week1',
y:parseFloat(dataVal.response[0].weekwisedata[0].weeklyActualProduction)
},
{
name: 'Week2',
y:parseFloat(dataVal.response[0].weekwisedata[1].weeklyActualProduction)
}
]
},
{
id: 'Quarter1p',
name: 'Planned Quantity',
data: [{
name: 'Week1',
y:parseFloat(dataVal.response[0].weekwisedata[0].weeklyPlannedProduction)
},
{
name: 'Week2',
y:parseFloat(dataVal.response[0].weekwisedata[1].weeklyPlannedProduction)
},
{
name: 'Week3',
y:parseFloat(dataVal.response[0].weekwisedata[2].weeklyPlannedProduction)
}
]
} ]
}
As you can see the above code,manually iam setting week number and values. iam grouping 13 weeks into quarter. can it be automated based on year?
I've been learning Meteor for about 3 weeks, and am still trying to wrap my head around updating/querying collections. I'm trying to build a Slack clone, and created the following collection with one set of fixture documents:
Conversations.insert({
channel: "#defaultChannel",
createdBy: "coffeemeup",
timestamp: new Date(),
followers: ["username1", "username2"],
entries: [
{
message: "this is a message #1",
postedTime: new Date(),
author: "coffeemeup"
}]
});
I'm trying to insert another document into the entries array using the code below. But not only does that not work, it throws a "Mutating the [[Prototype]] of an object will cause your code to run very slowly..." error. I'd really appreciate some help!
Conversations.update({
channel: "#defaultChannel"
}, {
$push: {
entries: {
message: newMessage,
postedTime: new Date(),
author: "coffeemeup"
}
}
});
Also, I would love to hear suggestions on how to better structure/design this database to build a Slack clone.
If you want to run update operations on clients, you need to use the _id field. Otherwise you will get this error:
Error: Not permitted. Untrusted code may only update documents by ID.
[403]
As a result, get the document first and subsequently use the document's _id to run the update query.
For example:
var conversation = Conversations.findOne({
"channel": "#defaultChannel"
});
Conversations.update({
_id: conversation._id
}, {
$push: {
entries: {
message: "newMessage",
postedTime: new Date(),
author: "coffeemeup"
}
}
});
Here is what the updated conversation document looks like:
{
"_id": "wGixGJgoM6fk57mtN",
"channel": "#defaultChannel",
"createdBy": "coffeemeup",
"timestamp": "2015-07-27T19:25:52.842Z",
"followers": [
"username1",
"username2"
],
"entries": [
{
"message": "this is a message #1",
"postedTime": "2015-07-27T19:25:52.842Z",
"author": "coffeemeup"
},
{
"message": "newMessage",
"postedTime": "2015-07-27T19:27:54.930Z",
"author": "coffeemeup"
}
]
}