diff --git a/.gitattributes b/.gitattributes index b97ca5dc8c5a6926fcbec5d5dbff8718879cf70e..20d27105d52df8e742d27e9f8d212bcf79a43044 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,6 +5,7 @@ action/changer_mode_document.php -text action/copier_local.php -text action/dissocier_document.php -text action/editer_document.php -text +action/ordonner_liens_documents.php -text action/supprimer_document.php -text action/supprimer_tous_orphelins.php -text action/tourner.php -text @@ -282,6 +283,8 @@ prive/themes/spip/images/base/video-16.png -text prive/themes/spip/images/base/video-22.png -text prive/themes/spip/images/base/video-32.png -text prive/themes/spip/images/base/vu-16.png -text +prive/themes/spip/images/deplacer-16.png -text +prive/themes/spip/images/deplacer-24.png -text prive/themes/spip/images/distant-16.png -text prive/themes/spip/images/doc-16.png -text prive/themes/spip/images/doc-24.png -text diff --git a/action/ordonner_liens_documents.php b/action/ordonner_liens_documents.php new file mode 100644 index 0000000000000000000000000000000000000000..a1be0467a21c8c2d05a5649b7f6102290cab8d2c --- /dev/null +++ b/action/ordonner_liens_documents.php @@ -0,0 +1,103 @@ +<?php + +/** + * Action ordonnant un lien sur une table de liens + * + * @plugin Medias + * @copyright 2017 + * @author Matthieu Marcillaud + * @licence GNU/GPL + * @package SPIP\Ordoc\Action + */ + +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} + +function action_ordonner_liens_documents_dist() { + action_ordonner_liens_dist(); +} + + +function action_ordonner_liens_dist() { + include_spip('inc/autoriser'); + include_spip('base/objets'); + include_spip('action/editer_liens'); + + // source (table spip_xx_liens) + $objet = objet_type(_request('objet_source')); + + // objet lié + $objet_lie = _request('objet_lie'); + $id_objet_lie = intval(_request('id_objet_lie')); + + // ordre des éléments + $ordre = _request('ordre'); + + if (!$objet or !$objet_lie or !$id_objet_lie OR !$ordre or !objet_associable($objet)) { + return envoyer_json_erreur(_T('medias:erreur_objet_absent') . ' ' . _T('medias:erreur_deplacement_impossible')); + } + + if (!autoriser('modifier', $objet_lie, $id_objet_lie)) { + return envoyer_json_erreur(_T('medias:erreur_autorisation') . ' ' . _T('medias:erreur_deplacement_impossible')); + } + + list($_id_objet, $table_liens) = objet_associable($objet); + + $success = $errors = array(); + + $actuels = sql_allfetsel( + array($_id_objet . ' AS id', 'rang_lien'), + $table_liens, + array( + sql_in($_id_objet, $ordre), + 'objet = ' . sql_quote($objet_lie), + 'id_objet = ' . sql_quote($id_objet_lie) + ) + ); + + $futurs = array_flip($ordre); + // ordre de 1 à n (pas de 0 à n). + array_walk($futurs, function(&$v) { $v++; }); + + $updates = array(); + + foreach ($actuels as $l) { + if ($futurs[$l['id']] !== $l['rang_lien']) { + $updates[$l['id']] = $futurs[$l['id']]; + } + } + + if ($updates) { + foreach ($updates as $id => $ordre) { + sql_updateq( + $table_liens, + array('rang_lien' => $ordre), + array( + $_id_objet . ' = ' . $id, + 'objet = ' . sql_quote($objet_lie), + 'id_objet = ' . sql_quote($id_objet_lie) + ) + ); + } + } + + return envoyer_json_envoi(array( + 'done' => true, + 'success' => $success, + 'errors' => $errors, + )); +} + +function envoyer_json_envoi($data) { + header('Content-Type: application/json; charset=' . $GLOBALS['meta']['charset']); + echo json_encode($data); +} + +function envoyer_json_erreur($msg) { + return envoyer_json_envoi(array( + 'done' => false, + 'success' => array(), + 'errors' => array($msg) + )); +} diff --git a/base/medias.php b/base/medias.php index 778c457bb58b2bc60854d71f6618bbbd83fd30a9..73d508ca4698e394b870b7df0567a76361fbbd83 100644 --- a/base/medias.php +++ b/base/medias.php @@ -87,7 +87,8 @@ function medias_declarer_tables_auxiliaires($tables_auxiliaires) { 'id_document' => "bigint(21) DEFAULT '0' NOT NULL", 'id_objet' => "bigint(21) DEFAULT '0' NOT NULL", 'objet' => "VARCHAR (25) DEFAULT '' NOT NULL", - 'vu' => "ENUM('non', 'oui') DEFAULT 'non' NOT NULL" + 'vu' => "ENUM('non', 'oui') DEFAULT 'non' NOT NULL", + 'rang_lien' => "int(4) DEFAULT '0' NOT NULL" ); $spip_documents_liens_key = array( diff --git a/lang/medias_fr.php b/lang/medias_fr.php index e55b0288d46f347235cdb7426a28c54a72473b4b..b07ad0017fe5f15f6c684f597c72be3c5b9b8e90 100644 --- a/lang/medias_fr.php +++ b/lang/medias_fr.php @@ -74,14 +74,17 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'entree_titre_image' => 'Titre de l’image :', 'erreur_aucun_document' => 'Ce document n’existe pas dans la médiathèque', 'erreur_aucun_fichier' => 'Aucun fichier n’a été trouvé', + 'erreur_autorisation' => 'Échec de l’autorisation.', 'erreur_chemin_distant' => 'Le fichier distant @nom@ n’a pas pu être trouvé', 'erreur_chemin_ftp' => 'Le fichier indiqué n’a pas été trouvé sur le serveur', 'erreur_copie_fichier' => 'Impossible de copier le fichier @nom@', + 'erreur_deplacement_impossible' => 'Déplacement impossible.', 'erreur_dossier_tmp_manquant' => 'Un dossier temporaire est manquant pour télécharger les fichiers', 'erreur_ecriture_fichier' => 'Erreur lors de l’écriture du fichier sur le disque', 'erreur_format_fichier_image' => 'Le format de @nom@ ne convient pas pour une image', 'erreur_indiquez_un_fichier' => 'Indiquez un fichier !', 'erreur_insertion_document_base' => 'Impossible d’enregistrer le document @fichier@ en base de données', + 'erreur_objet_absent' => 'Informations reçues incomplètes.', 'erreur_suppression_vignette' => 'Erreur lors de la suppression de la vignette', 'erreur_upload_type_interdit' => 'Le téléchargement des fichiers du type de @nom@ n’est pas autorisé', 'erreur_upload_vignette' => 'Erreur lors du chargement de la vignette @nom@', @@ -155,6 +158,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // O 'objet_document' => 'Document', 'objet_documents' => 'Documents', + 'ordonner_ce_document' => 'Ordonner ce document', // P 'par_date' => 'Date', diff --git a/medias_administrations.php b/medias_administrations.php index 99922362715247026087987eec49d032c61050cf..1979fc9fba19862264fffe8f8f767e6c5f7da671 100644 --- a/medias_administrations.php +++ b/medias_administrations.php @@ -169,6 +169,10 @@ function medias_upgrade($nom_meta_base_version, $version_cible) { // ajout de ics + vcf array('creer_base_types_doc') ); + $maj['1.3.0'] = array( + // ajout de rang_lien + array('maj_tables', 'spip_documents_liens'), + ); include_spip('base/upgrade'); include_spip('base/medias'); maj_plugin($nom_meta_base_version, $version_cible, $maj); diff --git a/modeles/document_desc.html b/modeles/document_desc.html index 62e814bc8798173b89f3f29d0b86d96a903658ae..2908ed6ef41c88cd0eadb94d3fc7c7a063143130 100644 --- a/modeles/document_desc.html +++ b/modeles/document_desc.html @@ -12,7 +12,7 @@ Distribue sous licence GPL <div class="descriptions"> <h4 class="titrem"> - [(#VU|=={oui}|oui)<img src='#CHEMIN_IMAGE{vu-16-10.png}' width='16' height='10' alt='<:medias:document_vu:>' title='<:medias:document_vu:>'/> ] + [(#VU|=={oui}|oui)<img src='#CHEMIN_IMAGE{vu-16-10.png}' width='16' height='10' alt='<:medias:document_vu|attribut_html:>' title='<:medias:document_vu:>'/> ] <span class="#EDIT{titre} titre" title="[(#FICHIER*|basename|attribut_html)]"> [(#TITRE|oui)#TITRE] [(#TITRE|non) @@ -27,7 +27,7 @@ Distribue sous licence GPL <div class="infos"> <div class="permanentes"> - [(#DISTANT|=={oui}|oui)<img src='#CHEMIN_IMAGE{distant-16.png}' width='16' height='16' alt='<:medias:fichier_distant:>' title='<:medias:fichier_distant:>'/> ]<:info_numero_abbreviation:>#ID_DOCUMENT - #EXTENSION + [(#DISTANT|=={oui}|oui)<img src='#CHEMIN_IMAGE{distant-16.png}' width='16' height='16' alt='<:medias:fichier_distant|attribut_html:>' title='<:medias:fichier_distant|attribut_html:>'/> ]<:info_numero_abbreviation:>#ID_DOCUMENT - #EXTENSION <a class="lien_details" onClick="$(this).parent().next('.detaillees').toggle(); return true;" @@ -76,9 +76,10 @@ Distribue sous licence GPL <BOUCLE_compte(documents_liens){id_document}{0,2} /> [(#TOTAL_BOUCLE|=={1}|et{#AUTORISER{dissocierdocuments,#OBJET,#ID_OBJET}}|et{#VU|=={non}})[(#BOUTON_ACTION{<:medias:bouton_enlever_supprimer_document:>,#URL_ACTION_AUTEUR{dissocier_document,#ID_OBJET-#OBJET-#ID_DOCUMENT-suppr-safe,#SELF},ajax,<:medias:bouton_enlever_supprimer_document_confirmation:>,'',[(function(){jQuery("#doc(#ID_DOCUMENT)").animateRemove();return true;})()]})]] [(#AUTORISER{dissocierdocuments,#OBJET,#ID_OBJET})[(#BOUTON_ACTION{<:medias:bouton_enlever_document:>,#URL_ACTION_AUTEUR{dissocier_document,#ID_OBJET-#OBJET-#ID_DOCUMENT--safe,#SELF},ajax,'','',[(function(){jQuery("#doc(#ID_DOCUMENT)").animateRemove();return true;})()]})]] - [(#AUTORISER{modifier,document,#ID_DOCUMENT}|oui) + [(#AUTORISER{modifier,document,#ID_DOCUMENT}|oui) + <span class="deplacer-document"><img src='#CHEMIN_IMAGE{deplacer-16.png}' width='16' height='16' alt='<:medias:ordonner_ce_document|attribut_html:>' /></span> <a href="#URL_ECRIRE{document_edit,id_document=#ID_DOCUMENT}" target="_blank" class="editbox" tabindex="0" role="button"><:medias:bouton_modifier_document:></a> - ]<//B_compte> + ]<//B_compte> [(#PIPELINE{document_desc_actions,#ARRAY{args,#ARRAY{id_document,#ID_DOCUMENT,position,document_desc,objet,#OBJET,id_objet,#ID_OBJET},data,''}})] </div> diff --git a/paquet.xml b/paquet.xml index d9a894f130a0fa8f9831590ee02a97548044394b..b8077a6a4ef75b119cfe70486f088c880752dade 100644 --- a/paquet.xml +++ b/paquet.xml @@ -1,11 +1,11 @@ <paquet prefix="medias" categorie="multimedia" - version="2.16.0" + version="2.17.0" etat="stable" compatibilite="[3.2.0-dev;]" logo="prive/themes/spip/images/portfolio-32.png" - schema="1.2.7" + schema="1.3.0" > <nom>Medias</nom> diff --git a/prive/squelettes/inclure/portfolio-documents.html b/prive/squelettes/inclure/portfolio-documents.html index c9e9afb65a4c33cc0835a5144cf7b9d22422e20a..663c71dd22d98c8f8b191e18e841eb36792b428b 100644 --- a/prive/squelettes/inclure/portfolio-documents.html +++ b/prive/squelettes/inclure/portfolio-documents.html @@ -14,7 +14,7 @@ <h3><span class="image_loading"></span><:medias:info_illustrations:></h3> <div class="liste_items documents" id="illustrations#ENV{id_unique}"> [<p class="pagination">(#PAGINATION)</p>] -<BOUCLE_illustrations(DOCUMENTS documents_liens types_documents){inclus=image}{mode=image}{id_objet}{objet}{par num titre,date,id_document}{pagination 50}{statut?}> +<BOUCLE_illustrations(DOCUMENTS documents_liens types_documents){inclus=image}{mode=image}{id_objet}{objet}{par rang_lien, num titre, date,id_document}{pagination 50}{statut?}> #MODELE{document_desc,id_document,id_objet,objet} </BOUCLE_illustrations> [(#TOTAL_BOUCLE|>{20}|oui)<p class="pagination">#PAGINATION</p>] @@ -28,7 +28,7 @@ <h3><:medias:info_portfolio:></h3> <div class="liste_items documents" id="portfolio#ENV{id_unique}"> [<p class="pagination">(#PAGINATION)</p>] -<BOUCLE_portfolio(DOCUMENTS documents_liens types_documents){inclus=image}{mode=document}{id_objet}{objet}{par num titre,date,id_document}{pagination 50}{statut?}> +<BOUCLE_portfolio(DOCUMENTS documents_liens types_documents){inclus=image}{mode=document}{id_objet}{objet}{par rang_lien, num titre, date,id_document}{pagination 50}{statut?}> #MODELE{document_desc,id_document,id_objet,objet} </BOUCLE_portfolio> [(#TOTAL_BOUCLE|>{20}|oui)<p class="pagination">#PAGINATION</p>] @@ -42,7 +42,7 @@ <h3><:medias:info_documents:></h3> <div class="liste_items documents" id="documents#ENV{id_unique}"> [<p class="pagination">(#PAGINATION)</p>] -<BOUCLE_documents(DOCUMENTS documents_liens types_documents){inclus!=image}{mode!=vignette}{id_objet}{objet}{par num titre,date,id_document}{pagination 50}{statut?}> +<BOUCLE_documents(DOCUMENTS documents_liens types_documents){inclus!=image}{mode!=vignette}{id_objet}{objet}{par rang_lien, num titre, date,id_document}{pagination 50}{statut?}> #MODELE{document_desc,id_document,id_objet,objet} </BOUCLE_documents> [(#TOTAL_BOUCLE|>{20}|oui)<p class="pagination">#PAGINATION</p>] @@ -134,11 +134,90 @@ function choix_affichages_documents() { }); } +/* Gestion du tri des listes de documents et de leur enregistrement */ +function ordonner_listes_documents() { + if ($.fn.sortable) { + $("#illustrations#ENV{id_unique}, #portfolio#ENV{id_unique}, #documents#ENV{id_unique}").each(function () { + // détruire / recréer le sortable à chaque appel ajax + if ($(this).has('.ui-sortable').length) { + $(this).sortable('destroy'); + } + // pas de tri possible s'il n'y a qu'un seul élément. + if ($(this).find('> .item').length < 2) { + $(this).find('.deplacer-document').hide(); + return true; // continue + } else { + $(this).find('.deplacer-document').show(); + } + $(this).sortable({ + /*axis: "y",*/ /* minidoc a un affichage en case */ + handle: "", + placeholder: "ui-state-highlight deplacer-document-placeholder", + cancel: 'img.croix_centre_image', + start: function(event, ui) { + ui.item.addClass('document-en-mouvement'); + }, + stop: function(event, ui) { + ui.item.removeClass('document-en-mouvement'); + }, + update: function (event, ui) { + var items = $(this); + var item = ui.item; + var liste = items.sortable('toArray'); + var ordre = []; + + $.each(liste, function(i, id) { + if (id) { + ordre.push( id.substring(3) ); // doc123 => 123 + } + }); + + var action = '[(#VAL{ordonner_liens_documents}|generer_url_action{"", 1})]'; + var params = { + objet_source: 'document', + objet_lie: '#OBJET', + id_objet_lie: '#ID_OBJET', + ordre: ordre, + }; + + item.animateLoading(); + + $.ajax({ + url: action, + data: params, + dataType: 'json', + cache: false, + }).done(function(data) { + + var couleur_origine = item.css('background-color'); + var couleur_erreur = $("<div class='remove'></div>").css('background-color'); + var couleur_succes = $("<div class='append'></div>").css('background-color'); + item.endLoading(true); + + if (data.errors.length) { + items.sortable('cancel'); + item.css({backgroundColor: couleur_erreur}).animate({backgroundColor: couleur_origine}, 'normal', function(){ + item.css({backgroundColor: ''}); + }); + } else { + item.css({backgroundColor: couleur_succes}).animate({backgroundColor: couleur_origine}, 'normal', function(){ + item.css({backgroundColor: ''}); + }); + } + }); + } + }); + }); + } +} + if (window.jQuery) { jQuery(function($){ onAjaxLoad(check_reload_page); choix_affichages_documents(); onAjaxLoad(choix_affichages_documents); + ordonner_listes_documents(); + onAjaxLoad(ordonner_listes_documents); }); } /*]]>*/</script> diff --git a/prive/style_prive_plugin_medias.html b/prive/style_prive_plugin_medias.html index ca0d7f0577aa69aa8d22589a0f26ee05b99ad199..51255b81c2ecadf8ebd9c26fb58f56b326127ad2 100644 --- a/prive/style_prive_plugin_medias.html +++ b/prive/style_prive_plugin_medias.html @@ -197,6 +197,12 @@ p.actions {clear:both;} .item.vu_oui {background:#f9f9f9;} +.deplacer-document-placeholder { height:130px; } +.deplacer-document { margin-#GET{right}:0.5em; float: #GET{left}; margin-top:2px; cursor:move; } +.document-en-mouvement { cursor:move; } + +.portfolios .item .actions a.editbox { margin-top: 0 !important; } + /* Types d'affichages des listes de douments */ h3 .affichages { @@ -275,13 +281,16 @@ h3 .affichages { } .portfolios .documents_liste .item .actions { align-items:center; + text-align:#GET{right}; margin-#GET{left}:1em; padding-#GET{right}:0; + min-width:80px; } .portfolios .documents_liste .item .actions .editbox, -.portfolios .documents_liste .item .actions .ordoc-deplacer { +.portfolios .documents_liste .item .actions .deplacer-document { display:inline-block; } +.documents_liste .deplacer-document-placeholder { height:40px; } /* Grille en cases des documents. */ @@ -310,10 +319,12 @@ h3 .affichages { display:inline-block; float:#GET{right}; } -.portfolios .documents_cases .item .actions .ordoc-deplacer { +.portfolios .documents_cases .item .actions .deplacer-document { display:inline-block; - float:#GET{left}; + margin-top:0px; } +.documents_cases .deplacer-document-placeholder { height:130px; width:113px; padding: 2px; margin: 2px;} + .portfolios .documents_cases .item .vignette { width:auto; height:auto; @@ -331,7 +342,7 @@ h3 .affichages { width:100%; margin-bottom:0; box-sizing:border-box; - padding: 4px 6px; + padding: 2px 5px 1px 5px; } .portfolios .documents_cases .tout_supprimer { flex-basis: 100%; diff --git a/prive/themes/spip/images/deplacer-16.png b/prive/themes/spip/images/deplacer-16.png new file mode 100644 index 0000000000000000000000000000000000000000..7823dce1acf400597e3d52634476d0485b5ed3a4 Binary files /dev/null and b/prive/themes/spip/images/deplacer-16.png differ diff --git a/prive/themes/spip/images/deplacer-24.png b/prive/themes/spip/images/deplacer-24.png new file mode 100644 index 0000000000000000000000000000000000000000..1b92b6afa36ca06f733e809246f149a18ae4531a Binary files /dev/null and b/prive/themes/spip/images/deplacer-24.png differ