I want to know how I can get the information that I have on a sql table into a Kendo scheduler. What I currently have in the server is the Start, End, StartTimeZone, EndTimeZone, Description, Title... etc. All the stuff you need for Kendo Scheduler, but I have many events that I need to make and put into a calendar format and the scheduler seems like the best way to do it. Right now my calendar view looks like this
#(Html.Kendo().Scheduler<**censored**.Models.LeaveRequest>()
.Name("scheduler")
.Date(new DateTime(2013, 6, 13))
.StartTime(new DateTime(2013, 6, 13, 7, 00, 00))
.Height(600)
.Views(views =>
{
views.DayView();
views.WeekView();
views.MonthView(MonthView => MonthView.Selected(true));
})
.Timezone("Etc/UTC")
.DataSource(d => d
.Model(m =>
{
m.Id(f => f.LeaveRequestId);
m.Field(f => f.Title).DefaultValue("No title");
m.Field(f => f.EmployeeId).DefaultValue(1);
m.Field(f => f.Title).DefaultValue("No title");
m.RecurrenceId(f => f.LeaveRequestId);
})
.ServerOperation(true)
.Read(read => read.Action("Read", "Home").Data("getAdditionalData"))
.Create("Create", "Home")
.Destroy("Destroy", "Home")
.Update("Update", "Home")
)
)
<script>
function getAdditionalData() {
var scheduler = $("#scheduler").data("kendoScheduler");
var timezone = scheduler.options.timezone;
var startDate = kendo.timezone.convert(scheduler.view().startDate(), timezone, "Etc/UTC");
var endDate = kendo.timezone.convert(scheduler.view().endDate(), timezone, "Etc/UTC");
//optionally add startTime / endTime of the view
var startTime = kendo.date.getMilliseconds(scheduler.view().startTime());
var endTime = kendo.date.getMilliseconds(scheduler.view().endTime());
endTime = endTime == 0 ? kendo.date.MS_PER_DAY : endTime;
var result = {
Start: new Date(startDate.getTime() - (startDate.getTimezoneOffset() * kendo.date.MS_PER_MINUTE) + startTime),
End: new Date(endDate.getTime() - (endDate.getTimezoneOffset() * kendo.date.MS_PER_MINUTE) + endTime)
}
return result;
}
</script>
<style>
.invalid-slot {
background: red !important;
cursor: no-drop;
}
</style>
</div>
But I don't know what I need to do in the controllers and models, if anything.
I just completed the implementation of KendoUI Scheduler by integrating it with SQL data base. However, I made use of JavaScript API to do so in my MVC project.
To load the data i.e. "read" and perform insert, update and delete just return the model in JSON format from controller. The Scheduler will bind the data for you, if it gets the "know" format.
return Json(**censored**.Models.LeaveRequest, JsonRequestBehavior.AllowGet);
Couple of important points:
1. KendoUI Scheduler depends a lot on unique id, so in case you have anything other than "id" - then "do" configure it in your scheduler.
In JS API it was done using following syntax, where EventID was the unique ID my SQL table.
schema: {
model: {
"id": "EventID",
"fields": {
"EventID": {
"type": "number"
},
....
Always return JSON data from your Insert, Update and Delete method from Controller. For instance:
public JsonResult UpdateCalendarEvent(string models)
{
...
return Json(censored.Models.LeaveRequest, JsonRequestBehavior.AllowGet);
}
In case of Insert, before returning the JSON object, do update the ID or EventID with latest row id, so Scheduler will sync up all data on client side and can perform update and delete operation appropriately.
Hope that helps!
Related
Here is the code
public function send(Request $request): object
{
$apiClient = new ApiClient();
$apiClient->getOAuth()->setOAuthBasePath(env('DS_AUTH_SERVER'));
try {
$accessToken = $this->getToken($apiClient);
} catch (\Throwable $th) {
return back()->withError($th->getMessage())->withInput();
}
$userInfo = $apiClient->getUserInfo($accessToken);
$accountInfo = $userInfo[0]->getAccounts();
$apiClient->getConfig()->setHost($accountInfo[0]->getBaseUri() . env('DS_ESIGN_URI_SUFFIX'));
$envelopeDefenition = $this->buildEnvelope($request);
try {
$envelopeApi = new EnvelopesApi($apiClient);
$result = $envelopeApi->createEnvelope($accountInfo[0]->getAccountId(), $envelopeDefenition);
dd($result);
} catch (\Throwable $th) {
return back()->withError($th->getMessage())->withInput();
}
return view('backend.response')->with('result', $result);
}
When I print $result variable it returns a response like this
container: array:8 [
"bulk_envelope_status" => null
"envelope_id" => "b634f8c5-96c5-4a18-947f-59418d8c4e03"
"error_details" => null
"recipient_signing_uri" => null
"recipient_signing_uri_error" => null
"status" => "sent"
"status_date_time" => "2023-02-16T07:24:39.1570000Z"
"uri" => "/envelopes/b634f8`your text`c5-96c5-4a18-947f-59418d8c4e03"
]
I want to get the value of recipient signing uri in response but in my case it returns null
How I can achieve this? Will anyone suggests?
createEnvelope creates the envelope. It does not give you an URL for an embedded recipient view (signing ceremony). In order to get that URL, you need to make an additional call to
EnvelopeViews:createRecipient/
See this page for more info.
Also
$apiClient->getConfig()->setHost($accountInfo[0]->getBaseUri() . env('DS_ESIGN_URI_SUFFIX'));
You are using the first entry in the UserInfo returned data's accountInfo array. That's not a good idea. Instead, look for the entry that is the user's default account.
Or if your application is designed to work with a specific eSign account, then make sure the user has access to that account.
It is very common for DocuSign customers to have access to more than one account.
Here is what I am trying to accomplish: turn off a True/False Advanced Custom Fields(ACF) option on a post if the current date is on or past a selected date on the same post. Also after that code, turn off a Sample Lesson True/False option inside of the lessons attached to the current post.
At first, all I had was the update_sample_child_lessons function with an 'init' action (i.e.add_action( 'init', 'update_sample_child_lessons' );), but that seemed to only run when I clicked update on the post. It did work and everything switched over, but it only ran when I manually clicked Update on the post. So then I did a little research and found that a Cron job should do the trick if I want the code to run automatically without me having to click update, but for some reason I can't seem to get it to work.
So if you know of a way to accomplish what I am trying to do with the code below, or with other code that is completely different, any suggestions or help would be much appreciated.
//CRON JOB TO RUN EVERYDAY
function myprefix_custom_cron_schedule( $schedules ) {
$schedules['every_day'] = array(
'interval' => 86400, //24 HOURS IN SECONDS
'display' => __( 'Every 24 hours' ),
);
return $schedules;
}
add_filter( 'cron_schedules', 'myprefix_custom_cron_schedule' );
if ( ! wp_next_scheduled( 'myprefix_cron_hook' ) ) {
wp_schedule_event( time(), 'every_day', 'myprefix_cron_hook' );
}
//AUTOMATICALLY ADJUSTS SAMPLE LESSON FREE OPTIONS AND FREE BANNER IF DATE IS PASSED
add_action( 'myprefix_cron_hook', 'update_sample_child_lessons' );
function update_sample_child_lessons() {
$allcourses = array(
'post_type' => 'sfwd-courses', //CUSTOM POST TYPE: COURSES
'posts_per_page' => -1 //QUERY ALL OF THEM
);
$query = new WP_Query($allcourses);
if ($query->have_posts()) {
global $post;
if ( ( in_array( $post->post_type, array( 'sfwd-courses' ), true ) )) { //ONLY DO ACTION IF ON CPT OF COURSES
while ($query->have_posts()) {
$query->the_post();
$course_id = learndash_get_course_id( $post->ID ); //GET THE COURSE ID
$free = get_field('display_free_lessons', $course_id); //GET THE FREE COURSE OPTION (TRUE/FALSE TICKER)
if (!empty($free)) { //ONLY DO REST OF CODE IF FREE OPTION IS TURNED ON
$freeDate = get_field('free_until', $course_id); //GET THE DATE FIELD THAT THE COURSE IS FREE UNTIL
$currentDate = date('Ymd'); //GET CURRENT DATE
$diff = strtotime($freeDate) - strtotime($currentDate); //GET THE DIFFERENCE BETWEEN THE TWO DATES
if ($diff <= 0) { //ONLY DO REST OF CODE IF DATE DIFFERENCE IS LESS THAN OR EQUAL TO ZERO
$value = '';
update_field('display_free_lessons', $value, $course_id); //UPDATES THE FREE OPTION FIELD TO FALSE(OR NOTHING)
//LESSON CODE
$lessons = array_slice(learndash_course_get_lessons($course_id), 1); //GET ALL THE LESSONS FROM THE COURSE EXCEPT FOR THE FIRST ONE
foreach ($lessons as $lesson) {
$lessonID = $lesson->ID; //GET THE LESSON ID
$lesson_meta = get_post_meta($lessonID); //GET THE METADATA FOR THE LESSON
if ( is_array( $lesson_meta ) ) {
foreach ( $lesson_meta as $meta_key => $meta_value ) {
if ( '_sfwd-lessons' === $meta_key ) {
$lesson_settings = maybe_unserialize( $meta_value[0] ); //SOME OF THE ARRAYS ARE SERIALIZED, SO UNSERIALIZE IF NEEDED
if ( isset( $lesson_settings['sfwd-lessons_sample_lesson'] ) ) {
$lesson_settings['sfwd-lessons_sample_lesson'] = ''; //TURN OFF THE SAMPLE LESSON OPTION ON THE LESSONS
}
update_post_meta( $lessonID, $meta_key, $lesson_settings );
}
}
}
} //END FOREACH
} //END IF DIFF IS 0
wp_reset_postdata();
}
}
}
}
}
Thanks for the comment #Luke Chaffey, I was actually able to figure it out after finding I had my cron actions reversed. Below is the final code that I got working so that it runs every day at 12am:
//CRON JOB TO RUN EVERYDAY
function custom_cron_schedule( $schedules ) {
$schedules['every_day'] = array(
'interval' => 86400,
'display' => __( 'Every 24 hours' ),
);
return $schedules;
}
add_filter( 'cron_schedules', 'custom_cron_schedule' );
$ve = get_option('gmt_offset') > 0 ? '-' : '+';
if ( ! wp_next_scheduled('cron_sample_lesson' ) ) {
wp_schedule_event(strtotime('00:00 tomorrow ' . $ve .
absint(get_option('gmt_offset')) . ' HOURS'), 'daily','cron_sample_lesson' );
}
add_action('cron_sample_lesson', 'update_sample_child_lessons' );
function update_sample_child_lessons() {...
I am using a v-chip-group with v-chips to represent a tag cloud for records in my database. I have an object array with records that look something like { key:'device', count:100}. A record could have multiple tags, so as you click on a tag, a new query is made that filters on that tag, the result will then have a new tag cloud with a subset of the previous.
It looks something like this:
tag1 (1000), tag2 (100), tag3 (100)
When you click on tag1 you end up with:
tag1 (1000), tag3 (15) (no tag2 because there is no overlap between tag1 and tag2).
Here is the relevant template code:
<v-chip-group v-model="selectedTag" multiple #change="refresh">
<v-chip v-for="tag in tags" :key="tag.key" active-class="primary">
<v-avatar left class="grey">{{ tag.count }}</v-avatar>
{{ tag.key }}
</v-chip>
</v-chip-group>
The problem I have is that in the typescript I do something like this:
refresh() {
// get simple array of tag strings
const selectedTags = this.selectedTag.map((value: any) => {
if (this.tags && this.tags[value]) {
return this.tags[value].key
} else {
return null
}
}).filter((value: any) => {
return value != null
})
Promise.all([
...
ApiCall('GET', 'tags', {limit: 1000, tags: selectedTags}),
...
).then((values) => {
// decode response from server into new tags
this.tags = values[2].series['0'].values.map((item: any) => {
return {key: item.bucket, count: item.doc_count}
})
const newTags: number[] = []
this.tags.forEach((tag, index) => {
// find the new index of the previously selected tags and save them
if (selectedTags.find(st => {
return st === tag.key
})) {
newTags.push(index)
}
})
// update selectedTag with the new value
this.$set(this, 'selectedTag', newTags)
// did not work this.selectedTag = newTags
})
}
What I'm seeing is that when I click a chip, it correctly fires the #change event and calls refresh, but then when the refresh finishes, I see an additional refresh get called with an empty selectedTag, which clears my filters and recalls the above functionality.
Is there a way to get #change to fire when a chip is changed, but not fire (or filter it out) when the event is generated by changing the data referenced by v-model?
I am trying to get multi-table with pagination, sorting, filtering in a single component.
I can get pagination for one table, unable to get pagination for multiple tables in a single component.
I also received the data from all tables. I am receiving the data from the backend so it takes a few seconds.
I Couldn't find any multi-data table example in angular7 material
This is my code
displayedColumns: string[] = ['name', 'id', 'products_count', 'domain'];
public dataSource = new MatTableDataSource<PeriodicElement>(this.ELEMENT_DATA);
public NONAR_ELEMENT_DATA: NonARElement[];
displayedColumns1: string[] = ['pro_id', 'name', 'd_image'];
public dataSource1 = new MatTableDataSource<NonARElement>(this.NONAR_ELEMENT_DATA);
#ViewChild('paginator') paginator: MatPaginator;
#ViewChild('paginator1', { read: MatPaginator }) paginator1: MatPaginator;
_setDataSource(indexNumber) {
console.log("indexNumber", indexNumber)
setTimeout(() => {
switch (indexNumber) {
case 0:
!this.dataSource1.paginator ? this.dataSource1.paginator = this.paginator1 : null;
console.log("this.dataSource-NON AR.paginator", this.dataSource.paginator)
break;
case 1:
!this.dataSource.paginator ? this.dataSource.paginator = this.paginator : null;
console.log("this.dataSource-Storelist.paginator", this.dataSource1.paginator)
}
},1000);
}```
Can you share your html page. Have you used this #name in your paginator?
<mat-paginator #paginator length="100"
pageSize="20"
pageSizeOptions="[10,20,30]"
(page)="pageChanged($event)">
</mat-paginator>
#ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
How can i dynamically change the selected columns in the generated sql query when using a linq expression?
Its a new session for each time the query is executed.
Even when I set the MapExp as null after first creation an then changing the bool value to false, it still generates the column in the sql query.
The code runs in a wpf application.
System.Linq.Expressions.Expression<Func<Entity, Model>> MapExp = x => new Model
{
Id=xId,
Count= LoadFormulaField ? x.Count: null,
...
};
var result = session.Query<Entity>().Select(MapExp))
Your problem seems to be the ternary-conditional as part of the expression which is causing the "Count" column to always be queried.
One option to avoid this could be:
var query = session.Query<Entity>();
IQueryable<Model> result = null;
if (LoadFormulaField)
{
result = query.Select(x => new Model
{
Id = x.Id,
Count = x.Count,
});
}
else
{
result = query.Select(x => new Model
{
Id = x.Id,
});
}
Which would get a little less ugly if you separate in a couple of methods I think.