Event data not being populated dynamically in Fullcalendar 4 - javascript

I have a db which contains all the events for a month/period. I've used http.get and got the JSON file. This file has additional data which has to be modified or formatted before it can be used as an event. Eg: For event title: name +id .
So I've formatted it accordingly and storing it as a string in a local variable. I'm trying to assign this variable as event data. But this is not being populated.
I've already tried converting the string to Array,by using Array.to(var). The result is still the same. Ive also tried to store it in a uri and passing the same as event data, url: uri. This also failed to display the event.
Read in fullcalendar docs about addEvent method. But Im relatively new to Angular 8 so have no idea how to implement that.
So, rn theres no errors, but i seem to be missing the big picture. Ill put out all the things im doing.
Theres an interface evtdata:
export interface Evtdata {
startRecur?: any,
endRecur?: any,
startTime?: any,
endTime?: any,
title?: any,
daysOfWeek?: any
}
Updated Component:
this.options$ = this.evts.getEventDat().pipe(
map(data => {
for (var i = 0; i < this.data.length; i++) {
this.eventdat[i].startRecur = "\""+data[i].startDate+"\"";
this.eventdat[i].endRecur = "\""+data[i].endDate+"\"";
this.eventdat[i].startTime ="\""+ data[i].startTime+"\"";
this.eventdat[i].endTime = "\""+data[i].endTime+"\"";
this.eventdat[i].title ="\""+ data[i].name + " " + data[i].wwid+" "+data[i].sId+"\"";
this.eventdat[i].daysOfWeek ="\""+ "[" + data[i].workDays + "]"+"\"";
}
return {
businessHours: {
daysOfWeek: [1, 2, 3, 4, 5],
startTime: '00:00',
endTime: '24:00',
},
editable: true,
customButtons: {
},
header: {
left: 'prev,next',
center: 'title',
right: 'dayGridMonth,listView,timeGridWeek,timeGridDay'
},
plugins: [dayGridPlugin, interactionPlugin, listPlugin, bootstrapPlugin, timeGrigPlugin],
events: this.eventdat
}
})
);
calendar.html
<full-calendar
*ngIf="options$ | async"
#fullcalendar
themeSystem="bootstrap"
[businessHours]="(options$ | async).businessHours"
[editable]="true"
[events]="(options$ | async).events"
[header]="(options$ | async).header"
[customButtons]="(options$ | async).customButtons"
[plugins]="(options$ | async).plugins"
(addEventSource)="addEventSource($event)"
(eventClick)="eventClick($event)"
(setProp)="setProp($event)"
></full-calendar>
Ive added multiple logs to display the data, data is getting saved and is being executed in the required order. Events are still not being populated.

You're doing all kinds of manipulations of the data, few of which I really understand. If you're doing an HTTP call, it returns an Observable. You can then pipe in a map operator where you add/remove/modify anything you need to. You can then use the async pipe in the template to avoid all of the subscription problems.
ngOnInit() {
this.options = this.evts.getEventDat().pipe(
map(data => {
// format your options object here, using the data object as needed
// don't forget that this map operator is NOT the same as Array map
// you can of course do an Array map in here as well if you need to
})
);
}
Then, in the template:
<full-calendar
*ngIf="options | async"
#fullcalendar
themeSystem="bootstrap"
[businessHours]="(options | async).businessHours"
[editable]="true"
[events]="(options | async).events"
[header]="(options | async).header"
[customButtons]="(options | async).customButtons"
[plugins]="(options | async).plugins"
(eventClick)="eventClick($event)"
(setProp)="setProp($event)"
></full-calendar>
I still don't understand a lot of your formatting. It feels like you're trying to manipulate JSON as a string, which you don't need to do. You can manipulate it as an object, which is kinda the whole point.
P.S. If you need to go back and forth between JSON and string notation, use JSON.parse(myString) and JSON.stringify(myObject).

Related

How to get latest documents from FaunaDB, based on timestamp?

Currently I store some data in FaunaDB every week. This is done using a cronjob. In my code I'm trying to fetch the documents from only the last two weeks. I'd like to use the timestamp to do so.
One of the documents to fetch:
{
"ref": Ref(Collection("weeklyContributors"), "350395411XXXXXXXX"),
"ts": 1670421954340000,
"data": {
...allMyDataFields
}
}
My code
const now = Date.now() * 1000;
const twoWeeksAgo = (Date.now() - 12096e5) * 1000;
console.log(now); //returns 1670493608804000
console.log(twoWeeksAgo); // returns 1669284008804000
// the stored document has a timestamp of 1670421954340000, so this should be in between [now] and [twoWeeksAgo]
await client.query(
q.Paginate(
q.Range(
q.Match(q.Index("get_weekly_list_by_ts")),
twoWeeksAgo,
now
)
)
);
This is a screenshot of the index I created in Fauna
Above code should fetch all documents where the timestamp's between now and twoWeeksAgo but it returns an empty array (so no documents match the query). Above code doesn't generate any errors, it does return a statuscode 200, so syntax should be fine. Why can't I fetch the document I gave in this example?
UPDATE
Found the solution for the index. The index should filter on Values, not Terms. Enter TS and Ref returns the document. BUt now I don't know how to get the corresponding document.
This returns an error
await client.query(
q.Map(
q.Paginate(
q.Range(
q.Match(q.Index("get_weekly_list_by_ts")),
twoWeeksAgo,
now
)
),
q.Lambda((x) => q.Get(x))
)
);
Changed index screenshot here
Congratulations on figuring out most of the answer for yourself!
As you deduced, the terms definition in an index specifies the fields to search for, and the values definition specifies the field values to return for matching entries.
Since you added the document reference to the values definition, all that you need now is to fetch that document. To do that, you need to Map over the results.
The following example uses Shell syntax, and involves sample documents that I created with a createdAt field recording the creation timestamp (since ts is the last-modified timestamp):
> Map(
Paginate(
Range(
Match(Index("get_weekly_list_by_ts")),
TimeSubtract(Now(), 14, "days"),
Now()
)
),
Lambda(
["ts", "ref"],
Get(Var("ref"))
)
)
{
data: [
{
ref: Ref(Collection("weeklyContributors"), "350498857823502848"),
ts: 1670520608640000,
data: { createdAt: Time("2022-12-01T17:30:08.633Z"), name: 'Fourth' }
},
{
ref: Ref(Collection("weeklyContributors"), "350498864657072640"),
ts: 1670520615160000,
data: { createdAt: Time("2022-12-07T17:30:15.152Z"), name: 'Fifth' }
}
]
}
Since your index returns ts and ref, notice that the Lambda function accepts both parameters in an array. The Lambda parameters have to match the number returned by the index. Then the Lambda calls Get to fetch the document.
In case you're wondering, here's the index definition that I used for my example:
> Get(Index("get_weekly_list_by_ts"))
{
ref: Index("get_weekly_list_by_ts"),
ts: 1670520331720000,
active: true,
serialized: true,
name: 'get_weekly_list_by_ts',
source: Collection("weeklyContributors"),
values: [ { field: [ 'data', 'createdAt' ] }, { field: [ 'ref' ] } ],
partitions: 8
}
My index is misnamed: I used the same name from your original query to help you correlate what is being used.
Note: there is no need to mask the document ID in a document that you share. It is only valid for the database containing the document.

How to draw separater in giftedchat?

I would like to draw separator such like "---- alredy read ----" with
giftedchat (https://github.com/FaridSafi/react-native-gifted-chat).
I think it is basic function for chat program, and can do with giftedchat.
I googled a lot, but can't find the way.
Would you teach me how to? I wolud like to draw like below.
|----------|
| Hello |
|----------|
--------- alredy read --------
|----------|
| Hi |
|----------|
I think you may use System Message to achieve this. The example is already shows in the React-Native-Gifted-Chat.
e.g. System Message
{
_id: 1,
text: 'This is a system message',
createdAt: new Date(Date.UTC(2016, 5, 11, 17, 20, 0)),
system: true,
// Any additional custom parameters are passed through
}
Then you may use the props renderSystemMessage to style your message.
const renderSystemMessage = (props) => {
return <Text>-----{props.currentMessage.text}-----</Text>;
};

Conditional typing for redux reducer

I am trying to create a re-usable component that renders a 'select' form item and its associated options. It accepts redux prop that is an action creator that is responsible for passing the selected option into the redux store to be used throughout the application.
I have two action creators that are possible options:
The first is :
setCompany: (state, action: PayloadAction<string>) => {
state.selectedCompany = action.payload;
},
The second is:
setStatus: (state, action: PayloadAction<SelectStatus['status']>) => {
state.status = action.payload;
},
The JobState['status'] type is: status: 'success' | 'error' | 'default' | 'processing' | 'warning';
In the Select component, I attempt to do the following:
interface SelectsProps {
fetchOptionData?: () => void;
optionsArray?: [];
placeholder: string;
showSearch: boolean;
badges: boolean;
redux?: ActionCreatorWithPayload<string | SelectStatus['status']>;
// I also tried ActionCreatorWithPayload<string> | //ActionCreatorWithPayload<SelectStatus['status']> but neither is working
}
In my parent component, i try to pass in a redux action of setStatus, defined above. However, I receive an error of :
`Type 'ActionCreatorWithPayload<"success" | "error" | "default" | "processing" | "warning", string>' is not assignable to type 'ActionCreatorWithPayload<string, string>'.`
<Selects
redux={setStatus}
placeholder='Default'
showSearch={false}
badges={true}
optionsArray={badges}
/>
};
If I do it as a union, it seems to default to string and not accept a status to be passed if valid. Is there a way I can allow the correct payload type to be selected?
Thank you
Solution
You need a union of the two action creator types rather than an action creator of the union.
redux?: ActionCreatorWithPayload<string> | ActionCreatorWithPayload<SelectStatus["status"]>;
Explanation
ActionCreatorWithPayload<string | SelectStatus['status']> means an action creator that can be called with an argument of either string OR SelectStatus['status']. setCompany is ok because SelectStatus['status'] is a subset of string. But setStatus is an error because it can only accept SelectStatus['status']. It cannot accept the union.
You need the union of the two action creators which is ActionCreatorWithPayload<string> | ActionCreatorWithPayload<SelectStatus["status"]>. This means that you can have a function that accepts string or a function that accepts SelectStatus['status']. It no longer needs to accept the union of the two.
You may have problems when you call this union since you don't know which argument type it accepts.
Note: I don't know why you use SelectStatus["status"] is one place and JobState["status"] in the other. I am assuming that they are the same. I would extract that type to a named type:
export type JobStatus = JobState["status"]

MST: How to create the main store correctly?

I want to create rootStore which contains others store. The problem is that the children contain properties like:
id: types.identifier(types.string),
And when I create the rootStore, I get an error from the child:
[mobx-state-tree] Error while converting {} to SomeModelStore: at path "/id" value undefined is not assignable to type: identifier(string) (Value is not a string), expected an instance of identifier(string) or a snapshot like identifier(string) instead.
I tried to use types.late but it did not help.
The solution I found is to wrap all properties into types.maybe
Examples:
error:
https://codesandbox.io/s/yvnznxyvyj?module=%2Fmodels%2FSomeModelStore.js
workaround:
https://codesandbox.io/s/0mv558yq50?module=%2Fmodels%2FSomeModelStore.js
Here https://codesandbox.io/s/yvnznxyvyj?module=%2Fmodels%2FSomeModelStore.js you create an empty object
.model("FirstStore", {
item: types.optional(SomeModelStore, {})
})
but type
SomeModelStore
didn't support empty fields. If you write like this
export const FirstStore = types
.model("FirstStore", {
item: types.optional(SomeModelStore, {
id: 'defaultId',
activate: false,
name: 'defaultName'
})
})
it will work. Or you can use "types.maybe" instead of "types.optional".
export const FirstStore = types
.model("FirstStore", {item: types.maybe(SomeModelStore)})
Also read about types.reference
I think it's a better way to use it in your case.

How to use/define Enums with Flow type checking?

I'm trying to migrate an existing codebase to use Flow. Since this project started without Flow, I'm using a pretty typical JS pattern for enums and such.
Here are a few definitions I want to
export const LOAN_STATUS = {
PENDING: 'pending',
CURRENT: 'current',
DUE: 'due',
OVERDUE: 'overdue',
PENDING_PAYMENT: 'pending_payment',
CHARGED_OFF: 'charged_off',
VOIDED: 'voided',
DISPUTED: 'disputed',
REFUNDED: 'refunded',
SETTLED: 'settled',
}
export const ACTIVE_LOAN_STATUS = [
LOAN_STATUS.OVERDUE,
LOAN_STATUS.CURRENT,
LOAN_STATUS.DUE,
LOAN_STATUS.PENDING_PAYMENT,
]
Flow works fine until I import this file and it says I need to add type annotations. This seems odd -- why should I have to annotate objects that are entirely static and easily inferred?
Is there any way that define its type as "static" or "literal"?
So then I go about thinking how I'm going to add annotations to this. My first thought is just {[key: string]: string} and Array<string>. Flow works, but I'm realizing that these type definitions are totally worthless. So then I try this other approach:
type LoanStatusValues =
'pending' |
'current' |
'due' |
'overdue' |
'pending_payment' |
'charged_off' |
'voided' |
'disputed' |
'refunded' |
'settled'
type LoanStatusKeys =
'PENDING' |
'CURRENT' |
'DUE' |
'OVERDUE' |
'PENDING_PAYMENT' |
'CHARGED_OFF' |
'VOIDED' |
'DISPUTED' |
'REFUNDED' |
'SETTLED'
type ActiveLoanStatus =
"current" |
"due" |
"overdue" |
"pending_payment"
And I use the type annotations {[key: LoanStatusKeys]: LoanStatusValues} and Array<ActiveLoanStatus>. But even these annotations loose the fact that this is static!
It just seems so odd that I'm having to write this much duplicate code. And then if I want to convert just to Flow I can't actually use the types in JS. For example I might do this:
if (defs.ACTIVE_LOAN_STATUS.indexOf(loan.status) !== -1) {
}
Now if I want to use Flow types, I can't do anything like this:
type ActiveLoanStatus =
"current" |
"due" |
"overdue" |
"pending_payment"
if (loan.status isTypeOf ActiveLoanStatus) {
}
So how am I supposed to use these static enums? I must be doing this wrong!
To express an enum with flow you can use $Values utility in conjunction with frozen object type:
export const LOAN_STATUS = Object.freeze({
PENDING: 'pending',
CURRENT: 'current',
DUE: 'due',
OVERDUE: 'overdue',
PENDING_PAYMENT: 'pending_payment',
CHARGED_OFF: 'charged_off',
VOIDED: 'voided',
DISPUTED: 'disputed',
REFUNDED: 'refunded',
SETTLED: 'settled',
});
type LoanStatus = $Values<typeof LOAN_STATUS>;
export const ACTIVE_LOAN_STATUS: LoanStatus[] = [
LOAN_STATUS.OVERDUE,
LOAN_STATUS.CURRENT,
LOAN_STATUS.DUE,
LOAN_STATUS.PENDING_PAYMENT,
]
This works starting from 0.60.0 version.
Here is the most concise way to achieve this:
const activeLoanStatuses = {
current: 'current',
due: 'due',
overdue: 'overdue',
pending_payment: 'pending_payment'
};
const otherLoanStatuses = {
pending: 'pending',
charged_off: 'charged_off',
voided: 'voided',
disputed: 'disputed',
refunded: 'refunded',
settled: 'settled',
};
type ActiveLoanStatus = $Keys<typeof activeLoanStatuses>;
type LoanStatus = $Keys<typeof otherLoanStatuses> | ActiveLoanStatus;
const activeLoanStatusesMap: { [key: LoanStatus]: ?ActiveLoanStatus} = activeLoanStatuses;
if (activeLoanStatusesMap[loan.status]) {
}
While incredibly verbose, and non-scalable, this falls into Flow's "Disjoint Unions" case and such can be implemented using ===. As they mention on that page, Case Analysis is done via that operator, as javascript naturally does with switch-case statements.
In your case, that equates to:
switch(loan.status) {
'pending':
'current':
'due':
'overdue':
'pending_payment':
'charged_off':
'voided':
'disputed':
'refunded':
'settled':
// your behavior here
}
As I mentioned, this is highly verbose in code which uses your types, but to counter that, it has the benefit of defining your types without creating a boilerplate object- you simply define your literal options and union them together (your second implementation).
This has the obvious downside of coupling your type definition with your implementations of its consumers, so use with caution.

Categories