I have a problem with locale in full Calendar in Laravel.
I use "maddhatter/laravel-fullcalendar": "~1.0" and i can't pass locale in FR.
If you have any idea, i take it.
Thanks
My Controller
class EventController extends Controller
{
public function index() {
$events = [];
$events[] = \Calendar::event(
'Event One', //event title
false, //full day event?
'2017-07-31T1000', //start time (you can also use Carbon instead of DateTime)
'2017-07-31T1200', //end time (you can also use Carbon instead of DateTime)
0 //optionally, you can specify an event ID
);
$calendar = \Calendar::addEvents($events)
->setOptions([ //set fullcalendar options
'header' => array('left' => 'prev,next today', 'center' => 'title', 'right' => ''),
'locale' => 'fr',
'editable'=> true,
'navLinks'=> true,
'selectable' => true,
'defaultView' => 'month'
])->setCallbacks([ //set fullcalendar callback options (will not be JSON encoded)
'viewRender' => 'function() {alert("Callbacks!");}'
]); //add an array with addEvents
return view('agenda', array('calendar' => $calendar));
}
1.Download the fullcalendar package.
2. Extract it wherever you like.
3. Go to the locale directory and copy the language files you need.
4. Go to your public/js directory and create a directory called 'fullcalendar' into which you paste the copied language files.
4. Alternatively, you could copy the files to the resources directory and compile them using laravel-mix.
5. Just below the fullcalendar script (e.g. <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.min.js"></script>), add the language script using an if or switch condition, for example:
#if ($locale == 'fr') {{-- $locale is a predefined variable holding the user's locale--}}
<script src="{{ asset('js/fullcalendar/fr.js') }}"></script>
#endif
6. You're all set!!
One applicable solution is this:
Edit the options of default in the class calendar:
protected $defaultOptions = [
'header' => [
'left' => 'prev,next today',
'center' => 'title',
'right' => 'month,agendaWeek,agendaDay',
],
'monthNames' => ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
'dayNames' => ['Domingo', 'Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado'],
'dayNamesShort' => ['Dom','Lun','Mar','Mie','Jue','Vie','Sáb'],
'monthNamesShort' => ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
'buttonText' => [
'month' => 'mes',
'week' => 'semana',
'day' => 'día',
'today' => 'Hoy',
],
'eventLimit' => true,
];
Related
I have a form in my application that allows users to create posts and while doing so upload multiple images to the post being created.
I am using Laravel Livewire and Filepond to achieve this.
The problem I am having is I need to allow the user to reorder the images (as it is a gallery and the order is important), and save the order in the database when the form in submitted.
Another issue I am running into is allowing a user to edit their post later. I need their pre-existing post images loaded in filepond, and also allow them to upload more, delete, and/or reorder.
When the user saves the post I need to be able to update my database and file system.
All info online is how to upload files, but no info on how to reorder, or pre-populate with pre-existing files.
Here is my current code for reference:
<div
x-data=""
x-init="
FilePond.setOptions({
allowMultiple: true,
allowReorder: true,
itemInsertLocation: 'after',
server: {
process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
#this.upload('images', file, load, error, progress)
},
revert: (filename, load) => {
#this.removeUpload('images', filename, load)
},
load: (source, load, error, progress, abort, headers) => {
var myRequest = new Request(source);
fetch(myRequest).then(function(response) {
response.blob().then(function(myBlob) {
load(myBlob)
});
});
},
},
});
const pond = FilePond.create($refs.input, {
acceptedFileTypes: ['image/png', 'image/jpeg'],
maxFileSize: '7MB',
allowImageCrop: true,
allowReorder: true,
allowImageResize: true,
imageResizeTargetWidth: '1000px',
imageResizeTargetHeight: '1000px',
filePosterMaxHeight: '256px',
files: {{ $existingImages }} // used for when editing a post and it already has images. see php component on how I set this variable
});
"
>
<div wire:ignore wire:key="images">
<div class="form-group text-center">
<input
id="image-upload"
type="file"
x-ref="input"
multiple
data-allow-reorder="true"
data-max-file-size="3MB"
data-max-files="10"
>
</div>
</div>
</div>
My Livewire PHP component:
public $images = [];
public $existingImages;
public function mountMedia($post) {
if($post){
$this->existingImages = $post->images->map(function ($image) use ($post) {
return [
'source' => $image->id,
'options' => [
'type' => 'local',
'file' => [
'name' => $image->getUrl(),
'size' => $image->file_size,
'type' => $image->mime_type,
],
'metadata' => [
'poster' => $image->getUrl(),
'position' => $image->position
],
],
];
});
}
}
public function saveImage($file, $post, $position) {
// Create a unique random string
$randString = Str::random(3);
// Get time
$time = time();
// Set file name
$filename = $time. '-' . $randString.'-'.auth()->user()->id;
$extension = '.'.$file->getClientOriginalExtension();
// Save images for gallery
$regImage = $file->storeAs('/'. $post->id, $filename.$extension, 'post_images');
// Create a new image in db
Image::create([
'user_id' => auth()->user()->id,
'post_id' => $post->id,
'position' => $position,
'filename' => $filename,
'extension' => $extension,
'src' => 'post_images',
'mime_type' => $file->getMimeType(),
'file_size' => $file->getSize(),
]);
}
public function saveMedia($post) {
// Make sure user owns post
abort_unless($post->user_id == auth()->user()->id, 403);
// Set default position
$position = 1;
// Save each image
foreach ($this->images as $file) {
$this->saveImage($file, $post, $position);
// Increment position for next image
$position++;
}
}
}
For sorting items in Livewire I would use https://github.com/livewire/sortable.
Sortable is very easy to use.
For filepond if the original image should be used again later I would save that image as well with a relation to the edited version.
I am using the laravel-charts package in Laravel 7. I added the datalabels plugin for chartjs into the Chart object like this:
$this->options = [
'responsive' => true,
'maintainAspectRatio' => false,
'legend' => [ 'display' => false ],
'plugins' => [
'datalabels' => [
'color' => 'white',
'weight' => 'bold',
'font' => ['size' => 14],
'formatter' => ''
]
]
In another version when I was using vue.js and vue-chartjs, I was able to format the lable using this:
plugins: {
datalabels: {
formatter: function(value, context) {
return '$' + Number(value).toLocaleString();
},
}
}
As you can see, the javascript is passed as a PHP array. I cannot figure out how to pass that formatter to my laravel-charts version.
Any help is greatly appreciated.
Laravel Charts plugins option has to be a string that's representing a plain Javascript object. I couldn't find any actual documentation, but you can read a related issue here "How to use ChartsJs plugin Datalabels js?".
You'll have to pass it like this:
$chart = new ChartTest;
$chart->labels(['One Thousand', 'Two Thousand', 'Three Thousand', 'Four Thousand']);
$chart->dataset('My dataset', 'bar', [1000, 2000, 3000, 4000]);
$chart->options([
// The whole plugins element is a string representing a JS object with plugins options
'plugins' => "{
datalabels: {
color: 'red',
font: {
size: 14,
weight: 'bold'
},
formatter: (value) => `\\$\${value}`
}
}"
]);
return view('chart', ['chart' => $chart]);
Will apply chartjs-plugin-datalabels options:
PS: The weight property has to be inside the font object like in my example.
I have a field that is a Select2 widget field and it's usually used in many forms, but copy pasting the same code after a while gets really annoying. Therefore I decided perhaps its best to create a widget just for this field.
The field is as follows
<?= $form->field($model, 'contact_id')->widget(Select2::className(), [
'initValueText' => empty($model->contact_id) ? '' : $model->contact->contact_id . ' ' . $model->contact->fullname,
'options' => [
'class' => 'input-sm',
'id' => 'contact_id',
'placeholder' => '-- Search --',
'disabled' => $disabled,
'onchange' => new JsExpression("get_contact_info($(this).val())"),
],
'pluginOptions' => [
'allowClear' => true,
'language' => [
'errorLoading' => new JsExpression("function () { return 'Waiting for results...'; }"),
],
'ajax' => [
'url' => $fetch_url,
'dataType' => 'json',
'data' => new JsExpression('function(params) { return {q:params.term}; }'),
'results' => new JsExpression('function(data,page) { return {results:data.results.text}; }'),
],
'escapeMarkup' => new JsExpression('function (markup) { return markup; }'),
'templateResult' => new JsExpression('function(contact) { return contact.text; }'),
'templateSelection' => new JsExpression('function (contact) { return contact.text; }'),
],
]); ?>
This field utilizes Ajax Fetching, and must allow to be used in create and update forms.
Can anyone please point me to the right direction.
I see two solution:
a) create widget - more work, but flexible using by adding additional settings
b) create separate view and render it - faster, but no so flexible
I'm getting confused by AJAX/S2 when I need to pass some arguments retrieved with JavaScript to a method in the controller.
In my script I have at some point, I get the position var:
function handle_geolocation_query(position){
alert('Lat: ' + position.coords.latitude + ' ' +
'Lon: ' + position.coords.longitude);
$.when( getLakes(position.coords.latitude, position.coords.longitude)).done(function(result1) {
console.log(result1);
});
};
function getLakes(lat, long) {
return $.ajax({
url: "{{ path('getLakes') }}",
data: { lat:lat, lng: lng },
dataType: 'jsonp'
});
};
then the router is set that way:
getLakes:
pattern: /lakes
defaults: { _controller: PondipGeolocBundle:Default:getLakesSurrounding }
And In my controller I'm supposed to return an array:
public function getLakesSurrounding($lat=0, $lng=0, $limit = 50, $distance = 50, $unit = 'km')
{
$lat = $this->getRequest()->get('lat');
$lng = $this->getRequest()->get('lont');
$return= array( '1'=> array( 'title' => 'lake1',
'venue' => 'lake2',
'dist' => 'lake3',
'species' => 'lake4',
'stock' => 'lake4'),
'2'=> array( 'title' => 'lake1',
'venue' => 'lake2',
'dist' => 'lake3',
'species' => 'lake4',
'stock' => 'lake4'),
'3'=> array( 'title' => 'lake1',
'venue' => 'lake2',
'dist' => 'lake3',
'species' => 'lake4',
'stock' => 'lake4'),
'4'=> array( 'title' => 'lake1',
'venue' => 'lake2',
'dist' => 'lake3',
'species' => 'lake4',
'stock' => 'lake4'),
'5'=> array( 'title' => 'lake1',
'venue' => 'lake2',
'dist' => 'lake3',
'species' => 'lake4',
'stock' => 'lake4')
);
$return=json_encode($return); //jscon encode the array
return new Response($return,200,array('Content-Type'=>'application/json')); //make sure it has the correct content type
}
And then I'd like to pass it to another function that would set up the template with moustache to print it in the view (I'm not here yet ..)
My question is: I can't pass the needed lat and long data to my function. the router gets mad, the controller doesnt get anything and I don't get anything back from that script.
EDIT:I found my way to pass the variables, but I still can't get any response from my controller, nohing happen and the $.when does not execute any callback
I'm fairly new with AJAX, please advise.
Have a look at FOSJsRoutingBundle. With it you can use router from JS:
Routing.generate('my_route_to_expose', { "id": 10, "foo": "bar" });
When users click on a button (with id graph), I'd like to fill the default Drupal content div (<div class="content">) with a graphael instance.
The JavaScript:
jQuery(document).ready(function($) {
$('#toggle #graph').click(function() {
$.ajax({
url: "http://www.mysite.com/?q=publications/callback",
type: 'POST',
data: {
'format' : 'graph'
},
success: function(response) {
$('div#content div.content').html(response);
}
});
});
});
The PHP:
$items['publications/callback'] = array(
'type' => MENU_CALLBACK,
'title' => 'All Publications Callback',
'page callback' => '_process_publications',
'page arguments' => array(t('journal')),
'access callback' => TRUE,
);
which leads to the page callback: (I'm concerned with the if code block)
function _process_publications($venue) {
if( isset($_POST['format']) && $_POST['format'] == "graph" ){
_make_bar_chart($venue);
}
elseif( isset($_POST['format']) && $_POST['format'] == "list" ) {
_make_list($venue);
}
else{
return("<p>blah</p>");
}
}
and finally the function called within the callback function:
function _make_bar_chart($venue) {
// get active database connection
$mysql = Database::getConnection();
// if connection is successful, proceed
if($mysql){
// do stuff
$graphael = array(
'method' => 'bar',
'values' => $ycoordinates,
'params' => array(
'colors' => $colors,
'font' => '10px Arial, sans-serif',
'opts' => array(
'gutter' => '20%',
'type' => 'square',
),
'label' => array(
'values' => $xcoordinates,
'isBottom' => true,
),
),
'extend' => array(
'label' => array(
'values' => $ycoordinates,
'params' => array('attrText' => array(
'fill' => '#aaa',
'font' => '10px Arial, sans-serif',
)),
),
),
);
return theme('graphael', $graphael);
}
// else, connection was unsuccessful
else{
print("<p>bad connection</p>");
}
}
THE PROBLEM: returning a theme doesn't really send anything back to the AJAX request (unlike print statements). I tried to print the theme, but that produces a white screen of death. How would I generate the graph without printing something?
Much thanks to nevets on the Drupal forums for the helpful hint: http://drupal.org/node/1664798#comment-6177944
If you want to use AJAX with Drupal, you are best off actually using Drupal-specific AJAX-related functions. In my theme's page.tpl.php file, I added the following to make the links which would call AJAX:
<?php
// drupal_add_library is invoked automatically when a form element has the
// '#ajax' property, but since we are not rendering a form here, we have to
// do it ourselves.
drupal_add_library('system', 'drupal.ajax');
// The use-ajax class is special, so that the link will call without causing
// a page reload. Note the /nojs portion of the path - if javascript is
// enabled, this part will be stripped from the path before it is called.
$link1 = l(t('Graph'), 'ajax_link_callback/graph/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$link2 = l(t('List'), 'ajax_link_callback/list/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$link3 = l(t('Create Alert'), 'ajax_link_callback/alert/nojs/', array('attributes' => array('class' => array('use-ajax'))));
$output = "<span>$link1</span><span>$link2</span><span>$link3</span><div id='myDiv'></div>";
print $output;
?>
When one of the links above is clicked, the callback function is called (e.g. ajax_link_callback/graph):
// A menu callback is required when using ajax outside of the Form API.
$items['ajax_link_callback/graph'] = array(
'page callback' => 'ajax_link_response_graph',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
.. and the callback to which it refers:
function ajax_link_response_graph($type = 'ajax') {
if ($type == 'ajax') {
$output = _make_bar_chart('journal');
$commands = array();
// See ajax_example_advanced.inc for more details on the available commands
// and how to use them.
$commands[] = ajax_command_html('div#content div.content', $output);
$page = array('#type' => 'ajax', '#commands' => $commands);
ajax_deliver($page);
}
else {
$output = t("This is some content delivered via a page load.");
return $output;
}
}
This replaces any HTML within <div class="content"> with the graphael chart returned from _make_bar_chart above.