Skip to content

Commit

Permalink
Merge pull request #586 from studer-raimann/feature/5-3/ui-service-dr…
Browse files Browse the repository at this point in the history
…opzones-2

UI Service: Dropzones. Thanks everybody for the work!
  • Loading branch information
chfsx authored Aug 16, 2017
2 parents fdd2f77 + 954a27c commit 0b8d424
Show file tree
Hide file tree
Showing 124 changed files with 94,918 additions and 9 deletions.
229 changes: 229 additions & 0 deletions Services/Form/classes/class.ilFileStandardDropzoneInputGUI.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
<?php
/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */

/**
* Class ilFileStandardDropzoneInputGUI
*
* A ilFileStandardDropzoneInputGUI is used in a (legacy) Form to upload Files using the Dropzone
* of the UI-Framework introduced with ILIAS 5.3. In some cases this can be used as a
* Drop-In-Replacement of the ilFileInputGUI, but check your usecase after. If you need an example
* how to use it, see e.g. in UI/examples/Dropzone/File/Standard/with_usage_in_legacy_form.php
*
* Why make it a Drop-In-Replacement and not just replace ilFileInputGUI?
* - There are a lot of different ways a form is handled in ILIAS, sometimes only checkInput is
* called, sometime developers send their own error-messages and so on. The
* ilFileStandardDropzoneInputGUI excepts some standard-behavior and would fail in some cases when
* just replacing the ilFileInputGUI
* - There are a lot of options in ilFileInputGUI which would be difficult to reimplement in
* ilFileStandardDropzoneInputGUI without discussing them with all devs.
* - Beside ilFileInputGUI there are many other File-InputGUIs with different functionality. We
* should consolidate their use-cases first.
*
* Attention: This ilFileStandardDropzoneInputGUI changes the behaviour of your form when used: The
* Form will be sent asynchronously due to limitations of dropped files (see
* https://stackoverflow.com/questions/1017224/dynamically-set-value-of-a-file-input )
*
* @author Fabian Schmid <[email protected]>
*/
class ilFileStandardDropzoneInputGUI extends ilFileInputGUI implements ilToolbarItem {

const ASYNC_FILEUPLOAD = "async_fileupload";
/**
* @var int if there are more than one ilFileStandardDropzoneInputGUI in the same Form, this
* value will be incremented during rendering to make sure all Inputs will be handled
* correctly
*/
protected static $count = 0;
/**
* @var string Set it to the URL (using ilCtrl->getFormAction() ) to override the Endpoint the
* Form will be sent to. If not set, the ilFileStandardDropzoneInputGUI will get the
* Form-Action of it's nearest form
*/
protected $upload_url = '';
/**
* @var int The amount of files which can be uploaded. Standard is 1 since the old
* ilFileInputGUI in most cases allows one.
*/
protected $max_files = 1;
/**
* @var \ILIAS\Data\DataSize only files beneath this size will be accepted to upload. Currently
* this uses the defined valued of the php.ini
*/
protected $max_file_size;
/**
* @var string The message which will be rendered within the dropzone.
*/
protected $dropzone_message = '';


/**
* @return string the URL where the form will be sent to.
*/
public function getUploadUrl() {
return $this->upload_url;
}


/**
* Set the URL (using ilCtrl->getFormAction() ) to override the Endpoint the
* Form will be sent to. If not set, the ilFileStandardDropzoneInputGUI will get the
* Form-Action of it's nearest form
*
* @param string $upload_url
*
* @return $this
*/
public function setUploadUrl($upload_url) {
$this->upload_url = $upload_url;

return $this;
}


/**
* @return int Amount of allowed files in this input
*/
public function getMaxFiles() {
return $this->max_files;
}


/**
* @param int $max_files The amount of files which can be uploaded. Standard is 1 since the old
* ilFileInputGUI in most cases allows one.
*/
public function setMaxFiles($max_files) {
$this->max_files = $max_files;
}


/**
* @return \ILIAS\Data\DataSize allowed size of files which can be uploaded
*/
public function getMaxFilesize() {
return $this->max_file_size;
}


/**
* @param \ILIAS\Data\DataSize $max_file_size only files beneath this size will be accepted to
* upload. Currently this uses the defined valued of
* the php.ini
*/
public function setMaxFilesize(\ILIAS\Data\DataSize $max_file_size) {
$this->max_file_size = $max_file_size;
}


/**
* @return string The message which will be rendered within the dropzone.
*/
public function getDropzoneMessage() {
return $this->dropzone_message;
}


/**
* @param string $dropzone_message The message which will be rendered within the dropzone.
*/
public function setDropzoneMessage($dropzone_message) {
$this->dropzone_message = $dropzone_message;
}


/**
* @inheritdoc
*/
public function render($a_mode = "") {
global $DIC;

$this->handleUploadURL();
$this->handleSuffixes();

$f = $DIC->ui()->factory();
$r = $DIC->ui()->renderer();

$dropzone = $f->dropzone()
->file()
->standard($this->getUploadUrl())
->withParameterName($this->getPostVar())
->withMaxFiles($this->getMaxFiles())
->withMessage($this->getDropzoneMessage())
->withAllowedFileTypes($this->getSuffixes());
$dropzone = $this->handleMaxFileSize($dropzone);
if ($this->isFileNameSelectionEnabled()) {
$dropzone = $dropzone->withUserDefinedFileNamesEnabled(true);
}

$render = $r->render($dropzone);

$n = ++ self::$count;
$out = "<div id='ilFileStandardDropzoneInputGUIWrapper{$n}'>" . $render . '</div>';
// We need some javascript magic
/** @var ilTemplate $tpl */
$tpl = $DIC['tpl'];
$tpl->addJavaScript('./Services/Form/js/ilFileStandardDropzoneInputGUI.js');
$tpl->addOnLoadCode("ilFileStandardDropzoneInputGUI.init('ilFileStandardDropzoneInputGUIWrapper{$n}');");

return $out;
}


/**
* @inheritdoc
*/
public function checkInput() {
global $DIC;

$hasUploads = $DIC->upload()->hasUploads();
if ($this->getRequired() && !$hasUploads) {
return false; // No file uploaded but is was required
}

if ($hasUploads) {
try {
$_POST[$this->getPostVar()] = $_FILES[$this->getPostVar()];
} catch (Exception $e) {
return false;
}

return true;
}

return true;
}


protected function handleUploadURL() {
if (!$this->getUploadUrl()) {
$parentWrapper = $this;
while (!$parentWrapper instanceof ilPropertyFormGUI && $parentWrapper !== null) {
$parentWrapper = $parentWrapper->getParent();
}

$str_replace = str_replace("&amp;", "&", $parentWrapper->getFormAction());
$this->setUploadUrl($str_replace . "&" . self::ASYNC_FILEUPLOAD . "=true");
}
}


protected function handleSuffixes() {
if (!is_array($this->getSuffixes())) {
$this->setSuffixes(array());
}
}


/**
* @param ILIAS\UI\Component\Dropzone\File\Standard $dropzone
*
* @return ILIAS\UI\Component\Dropzone\File\Standard
*/
protected function handleMaxFileSize($dropzone) {
if ($this->getMaxFilesize()) {
$dropzone = $dropzone->withFileSizeLimit($this->getMaxFilesize());
}

return $dropzone;
}
}
61 changes: 61 additions & 0 deletions Services/Form/js/ilFileStandardDropzoneInputGUI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
var ilFileStandardDropzoneInputGUI = (function ($) {

var init = function (wrapper_id) {
var wrapper = $('#' + wrapper_id);
var uploadId = wrapper.find('.il-dropzone-base').attr('id');
var form = wrapper.closest('form');
var handledUpload = false;
var buttonName = form.find('input[type=submit]:first').attr('name');
form.find('input[type=submit]').on("click", function () {
buttonName = $(this).attr('name');
});

form.on('submit', function (event) {
if (handledUpload) {
return;
}
if ($(this)[0].checkValidity()) {
// If we have any files to upload, start uploading process prior to submitting form
if (il.UI.uploader.getUploads(uploadId).length) {
event.preventDefault();

var params = {};

$.each($(this).serializeArray(), function (_, kv) {
if (params.hasOwnProperty(kv.name)) {
params[kv.name] = $.makeArray(params[kv.name]);
params[kv.name].push(kv.value);
} else {
params[kv.name] = kv.value;
}
});

params[buttonName] = true;

il.UI.uploader.setUploadParams(uploadId, params);
il.UI.uploader.onError(uploadId, function (xmlHttpRequest) {
handledUpload = true;
return false;
});
il.UI.uploader.onAllUploadCompleted(uploadId, function () {
handledUpload = true;
return true;
}, function () {
handledUpload = true;
return false;
});

il.UI.uploader.upload(uploadId);
}
else {
handledUpload = true;
}
}
});
};

return {
init: init
}

})($);
2 changes: 1 addition & 1 deletion Services/Style/System/data/data.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion lang/ilias_de.lang
Original file line number Diff line number Diff line change
Expand Up @@ -5311,6 +5311,7 @@ common#:#visitors#:#Besucher
common#:#visits#:#Besuche
common#:#web_resources#:#Weblinks
common#:#webdav#:#WebDAV
common#:#edit_metadata#:#Metadaten bearbeiten
common#:#webdav_pear_auth_http_needed#:#Sie benötigen PEAR-Auth_HTTP um diese Funktion zu verwenden. Geben Sie im Terminal-Fenster <code>pear install Auth_HTTP</code> ein.
common#:#webdav_pwd_instruction#:#Um das ILIAS-Magazin als Webordner außerhalb der aktuellen Sitzung als Webordner zu öffnen, empfehlen wir ein lokales Passwort anzulegen.<br />Dieses Passwort wird nur für die Webordner-Funktionalitäten benötigt, die ILIAS-Anmeldung erfolgt weiterhin mit Ihrem gewohnten Passwort.
common#:#webdav_pwd_instruction_success#:#Ein neues lokales Passwort wurde angelegt. Sie können nun das Magazin als Webordner öffnen.
Expand Down Expand Up @@ -12680,7 +12681,7 @@ trac#:#trac_lp_list_gui#:#Persönlicher Schreibtisch, Magazin, Suche
trac#:#trac_lp_list_gui_info#:#Wenn aktiviert, wird der Lernfortschrittsstatus in Objekt-Listen angezeigt.
common#:#hide_all_details#:#Alle Details ausblenden
common#:#show_all_details#:#Alle Details anzeigen
common#:#select_files_from_computer#:#Wählen Sie die Dateien von Ihrem Computer aus
common#:#select_files_from_computer#:#Dateien wählen
common#:#drag_files_here#:#Ziehen Sie die Dateien in diesen Bereich
common#:#selected_files#:#Ausgewählte Dateien
common#:#num_of_selected_files#:#%s Datei(en) ausgewählt
Expand Down
3 changes: 2 additions & 1 deletion lang/ilias_en.lang
Original file line number Diff line number Diff line change
Expand Up @@ -2790,6 +2790,7 @@ common#:#notes_and_comments#:#Notes and Comments
common#:#notes#:#Notes
common#:#notifications#:#Notifications
common#:#num_users#:#Number of Users
common#:#edit_metadata#:#Edit Metadata
rbac#:#nwss_edit_permission#:#User can change permission settings in News and Web Feeds administration
rbac#:#nwss_read#:#User has read access to ews and Web Feeds administration
rbac#:#nwss_visible#:#News and Web Feeds administration is visible
Expand Down Expand Up @@ -10426,7 +10427,7 @@ trac#:#trac_lp_list_gui#:#Personal Desktop, Repository, Search
trac#:#trac_lp_list_gui_info#:#If activated, the learning progress status is included in objects lists.
common#:#hide_all_details#:#Hide all details
common#:#show_all_details#:#Show all details
common#:#select_files_from_computer#:#Select the files from your computer
common#:#select_files_from_computer#:#Select Files
common#:#drag_files_here#:#Drag-and-drop your files here
common#:#selected_files#:#Selected files
common#:#num_of_selected_files#:#%s file(s) selected
Expand Down
5 changes: 3 additions & 2 deletions libs/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Dependency Management in ILIAS

The are currently three type of external libraries:
- PHP dependencies installed using composer in /libs/composer, see [composer-readme](libs/composer/README.md).
- PHP dependencies installed using composer in /libs/composer, see [composer-readme](composer/README.md).
- PHP dependencies installad manually, located in some /Services/\*/libs and /Modules/\*/libs
- JS- and client-side Frameworks, currently also located in /Services\/* and /Modules\/*
- JS- and client-side Frameworks installed using bower, see [bower-readme](bower/README.md)
- JS- and client-side Frameworks installed manually, currently also located in /Services\/* and /Modules\/*
21 changes: 21 additions & 0 deletions libs/bower/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# How to add dependencies with bower in ILIAS

**New dependencies need to be approved by the Jour Fixe of the ILIAS society.**

## Dependencies for production
- Comment all lines in libs/.gitignore which begin with bower/
- Add a new library using bower, e.g. "bower install [email protected] --save"
- Add a section in "extra" with the following metadata":
```json
"jquery": {
"introduction": "03.08.2017",
"introduced-by": "fschmid"
},
```
- Run "bower install --no-dev"
- Add all files to ILIAS git-repository and commit

## Dependencies for development
- Add a new library using bower, e.g. "bower install mocha --save-dev"
- Ignore all directories which are added by installation (uncomment existing)
- commit changes in gitignore and bower.json.
32 changes: 32 additions & 0 deletions libs/bower/bower.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "ilias",
"homepage": "https://ilias.de",
"authors": [
"ILIAS <[email protected]>"
],
"description": "",
"main": "",
"license": "GNUv3",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"fine-uploader": "5.13.0",
"jquery-dragster": "^1.0.3"
},
"extra": {
"fine-uploader": {
"introduction": "03.08.2017",
"introduced-by": "fschmid"
},
"jquery-dragster": {
"introduction": "03.08.2017",
"introduced-by": "fschmid"
}
}
}
Loading

0 comments on commit 0b8d424

Please sign in to comment.