diff --git a/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/Main.ts b/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/Main.ts new file mode 100644 index 0000000000000000000000000000000000000000..61d438de1a86defe8c6486ac1b5a9bee574b56ad --- /dev/null +++ b/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/Main.ts @@ -0,0 +1,356 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +import * as $ from 'jquery'; +import * as NProgress from 'nprogress'; +import Modal = require('TYPO3/CMS/Backend/Modal'); +import SplitButtons = require('TYPO3/CMS/Backend/SplitButtons'); +import Tooltip = require('TYPO3/CMS/Backend/Tooltip'); +import Severity = require('TYPO3/CMS/Backend/Severity'); +import SecurityUtility = require('TYPO3/CMS/Core/SecurityUtility'); +import ExtensionManagerRepository = require('./Repository'); +import ExtensionManagerUpdate = require('./Update'); +import ExtensionManagerUploadForm = require('./UploadForm'); +import 'datatables'; +import 'TYPO3/CMS/Backend/jquery.clearable'; + +const securityUtility = new SecurityUtility(); + +enum ExtensionManagerIdentifier { + extensionlist = '#typo3-extension-list', + searchField = '#Tx_Extensionmanager_extensionkey', +} + +/** + * Module: TYPO3/CMS/Extensionmanager/Main + * main logic holding everything together, consists of multiple parts + * ExtensionManager => Various functions for displaying the extension list / sorting + * Repository => Various AJAX functions for TER downloads + * ExtensionManager.Update => Various AJAX functions to display updates + * ExtensionManager.uploadForm => helper to show the upload form + */ +class ExtensionManager { + public Update: ExtensionManagerUpdate; + public UploadForm: ExtensionManagerUploadForm; + public Repository: ExtensionManagerRepository; + + constructor() { + $(() => { + $.fn.dataTableExt.oSort['extension-asc'] = (a: string, b: string) => { + return ExtensionManager.extensionCompare(a, b); + }; + + $.fn.dataTableExt.oSort['extension-desc'] = (a: string, b: string) => { + let result = ExtensionManager.extensionCompare(a, b); + return result * -1; + }; + + $.fn.dataTableExt.oSort['version-asc'] = (a: string, b: string) => { + let result = ExtensionManager.versionCompare(a, b); + return result * -1; + }; + + $.fn.dataTableExt.oSort['version-desc'] = (a: string, b: string) => { + return ExtensionManager.versionCompare(a, b); + }; + this.Update = new ExtensionManagerUpdate(); + this.UploadForm = new ExtensionManagerUploadForm(); + this.Repository = new ExtensionManagerRepository(); + + const dataTable: DataTables.Api = this.manageExtensionListing(); + $(document).on('click', '.onClickMaskExtensionManager', (): void => { + NProgress.start(); + }).on('click', 'a[data-action=update-extension]', (e: JQueryEventObject): void => { + e.preventDefault(); + $.ajax({ + url: $(this).attr('href'), + dataType: 'json', + beforeSend: (): void => { + NProgress.start(); + }, + success: this.updateExtension, + }); + }).on('change', 'input[name=unlockDependencyIgnoreButton]', (e: JQueryEventObject): void => { + const $actionButton = $('.t3js-dependencies'); + $actionButton.toggleClass('disabled', !$(e.currentTarget).prop('checked')); + }); + + $(ExtensionManagerIdentifier.searchField).clearable({ + onClear: (): void => { + dataTable.search('').draw(); + }, + }); + + $(document).on('click', '.t3-button-action-installdistribution', (): void => { + NProgress.start(); + }); + + SplitButtons.addPreSubmitCallback((e: JQueryEventObject): void => { + if ($(e.target).hasClass('t3js-save-close')) { + $('#configurationform').append($('<input />', { + type: 'hidden', + name: 'tx_extensionmanager_tools_extensionmanagerextensionmanager[action]', + value: 'saveAndClose', + })); + } + }); + + this.Repository.initDom(); + this.Update.initializeEvents(); + this.UploadForm.initializeEvents(); + + Tooltip.initialize('#typo3-extension-list [title]', { + delay: { + show: 500, + hide: 100, + }, + trigger: 'hover', + container: 'body', + }); + }); + } + + private manageExtensionListing(): DataTables.Api { + const $searchField = $(ExtensionManagerIdentifier.searchField); + const dataTable = $(ExtensionManagerIdentifier.extensionlist).DataTable({ + paging: false, + dom: 'lrtip', + lengthChange: false, + pageLength: 15, + stateSave: true, + drawCallback: this.bindExtensionListActions, + columns: [ + null, + null, + { + type: 'extension', + }, + null, + { + type: 'version', + }, { + orderable: false, + }, + null, + null, + ], + }); + + $searchField.parents('form').on('submit', () => { + return false; + }); + + const getVars: any = ExtensionManager.getUrlVars(); + + // restore filter + const currentSearch = (getVars.search ? getVars.search : dataTable.search()); + $searchField.val(currentSearch); + + $searchField.on('input', (e: JQueryEventObject): void => { + dataTable.search($(e.currentTarget).val()).draw(); + }); + + return dataTable; + } + + private bindExtensionListActions = (): void => { + $('.removeExtension').not('.transformed').each((index: number, element: any) => { + const $me = $(element); + $me.data('href', $me.attr('href')); + $me.attr('href', '#'); + $me.addClass('transformed'); + $me.click((): void => { + Modal.confirm( + TYPO3.lang['extensionList.removalConfirmation.title'], + TYPO3.lang['extensionList.removalConfirmation.question'], + Severity.error, + [ + { + text: TYPO3.lang['button.cancel'], + active: true, + btnClass: 'btn-default', + trigger: (): void => { + Modal.dismiss(); + }, + }, { + text: TYPO3.lang['button.remove'], + btnClass: 'btn-danger', + trigger: (): void => { + this.removeExtensionFromDisk($me); + Modal.dismiss(); + }, + }, + ], + ); + }); + }); + } + + private removeExtensionFromDisk($extension: JQuery): void { + $.ajax({ + url: $extension.data('href'), + beforeSend: (): void => { + NProgress.start(); + }, + success: (): void => { + location.reload(); + }, + complete: (): void => { + NProgress.done(); + }, + }); + } + + private static getUrlVars(): any { + let vars: any = []; + let hash: Array<string>; + let hashes: Array<string> = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); + for (let i = 0; i < hashes.length; i++) { + hash = hashes[i].split('='); + vars.push(hash[0]); + vars[hash[0]] = hash[1]; + } + return vars; + } + + /** + * Special sorting for the extension version column + */ + private static versionCompare(a: string, b: string): number { + if (a === b) { + return 0; + } + + const a_components = a.split('.'); + const b_components = b.split('.'); + const len = Math.min(a_components.length, b_components.length); + + // loop while the components are equal + for (let i = 0; i < len; i++) { + // A bigger than B + if (parseInt(a_components[i], 10) > parseInt(b_components[i], 10)) { + return 1; + } + + // B bigger than A + if (parseInt(a_components[i], 10) < parseInt(b_components[i], 10)) { + return -1; + } + } + + // If one's a prefix of the other, the longer one is greaRepository. + if (a_components.length > b_components.length) { + return 1; + } + + if (a_components.length < b_components.length) { + return -1; + } + // Otherwise they are the same. + return 0; + } + + /** + * The extension name column can contain various forms of HTML that + * break a direct comparison of values + */ + private static extensionCompare(a: string, b: string): number { + const div = document.createElement('div'); + div.innerHTML = a; + const aStr = div.textContent || div.innerText || a; + + div.innerHTML = b; + const bStr = div.textContent || div.innerText || b; + + return aStr.trim().localeCompare(bStr.trim()); + } + + private updateExtension(data: any): void { + let i = 0; + const $form = $('<form>'); + $.each(data.updateComments, (version: string, comment: string): void => { + const $input = $('<input>').attr({type: 'radio', name: 'version'}).val(version); + if (i === 0) { + $input.attr('checked', 'checked'); + } + $form.append([ + $('<h3>').append([ + $input, + ' ' + securityUtility.encodeHtml(version), + ]), + $('<div>') + .append( + comment + .replace(/(\r\n|\n\r|\r|\n)/g, '\n') + .split(/\n/).map((line: string): string => { + return securityUtility.encodeHtml(line); + }) + .join('<br>'), + ), + ]); + i++; + }); + const $container = $('<div>').append([ + $('<h1>').text(TYPO3.lang['extensionList.updateConfirmation.title']), + $('<h2>').text(TYPO3.lang['extensionList.updateConfirmation.message']), + $form, + ]); + + NProgress.done(); + + Modal.confirm( + TYPO3.lang['extensionList.updateConfirmation.questionVersionComments'], + $container, + Severity.warning, + [ + { + text: TYPO3.lang['button.cancel'], + active: true, + btnClass: 'btn-default', + trigger: (): void => { + Modal.dismiss(); + }, + }, { + text: TYPO3.lang['button.updateExtension'], + btnClass: 'btn-warning', + trigger: (): void => { + $.ajax({ + url: data.url, + data: { + tx_extensionmanager_tools_extensionmanagerextensionmanager: { + version: $('input:radio[name=version]:checked', Modal.currentModal).val(), + }, + }, + dataType: 'json', + beforeSend: (): void => { + NProgress.start(); + }, + complete: (): void => { + location.reload(); + }, + }); + Modal.dismiss(); + }, + }, + ], + ); + } +} + +let extensionManagerObject = new ExtensionManager(); + +if (typeof TYPO3.ExtensionManager === 'undefined') { + TYPO3.ExtensionManager = extensionManagerObject; +} + +export = extensionManagerObject; diff --git a/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/Repository.ts b/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/Repository.ts new file mode 100644 index 0000000000000000000000000000000000000000..e54e116179534059acd37c14819b6ddce71cffa0 --- /dev/null +++ b/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/Repository.ts @@ -0,0 +1,203 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +import * as $ from 'jquery'; +import * as NProgress from 'nprogress'; +import Modal = require('TYPO3/CMS/Backend/Modal'); +import Notification = require('TYPO3/CMS/Backend/Notification'); +import Severity = require('TYPO3/CMS/Backend/Severity'); +import 'datatables'; +import 'TYPO3/CMS/Backend/jquery.clearable'; + +class Repository { + public downloadPath: string = ''; + + public initDom = (): void => { + NProgress.configure({parent: '.module-loading-indicator', showSpinner: false}); + + $('#terTable').DataTable({ + lengthChange: false, + pageLength: 15, + stateSave: false, + info: false, + paging: false, + searching: false, + ordering: false, + drawCallback: this.bindDownload, + }); + + $('#terVersionTable').DataTable({ + lengthChange: false, + pageLength: 15, + stateSave: false, + info: false, + paging: false, + searching: false, + drawCallback: this.bindDownload, + order: [ + [2, 'asc'], + ], + columns: [ + {orderable: false}, + null, + {type: 'version'}, + null, + null, + null, + ], + }); + + $('#terSearchTable').DataTable({ + paging: false, + lengthChange: false, + stateSave: false, + searching: false, + language: { + search: 'Filter results:', + }, + ordering: false, + drawCallback: this.bindDownload, + }); + + this.bindDownload(); + this.bindSearchFieldResetter(); + } + + private bindDownload = (): void => { + const installButtons = $('.downloadFromTer form.download button[type=submit]'); + installButtons.off('click'); + installButtons.on('click', (event: JQueryEventObject): void => { + event.preventDefault(); + const $element: any = $(event.currentTarget); + const url = $($element.form).attr('data-href'); + this.downloadPath = $($element.form).find('input.downloadPath:checked').val(); + $.ajax({ + url: url, + dataType: 'json', + beforeSend: (): void => { + NProgress.start(); + }, + success: this.getDependencies, + }); + }); + } + + private getDependencies = (data: any): boolean => { + NProgress.done(); + if (data.hasDependencies) { + Modal.confirm(data.title, $(data.message), Severity.info, [ + { + text: TYPO3.lang['button.cancel'], + active: true, + btnClass: 'btn-default', + trigger: (): void => { + Modal.dismiss(); + }, + }, { + text: TYPO3.lang['button.resolveDependencies'], + btnClass: 'btn-info', + trigger: (): void => { + this.getResolveDependenciesAndInstallResult(data.url + + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + this.downloadPath); + Modal.dismiss(); + }, + }, + ]); + } else { + if (data.hasErrors) { + Notification.error(data.title, data.message, 15); + } else { + this.getResolveDependenciesAndInstallResult(data.url + + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + this.downloadPath); + } + } + return false; + } + + private getResolveDependenciesAndInstallResult = (url: string) => { + $.ajax({ + url: url, + dataType: 'json', + beforeSend: (): void => { + NProgress.start(); + }, + success: (data: any): void => { + if (data.errorCount > 0) { + Modal.confirm(data.errorTitle, $(data.errorMessage), Severity.error, [ + { + text: TYPO3.lang['button.cancel'], + active: true, + btnClass: 'btn-default', + trigger: (): void => { + Modal.dismiss(); + }, + }, { + text: TYPO3.lang['button.resolveDependenciesIgnore'], + btnClass: 'btn-danger disabled t3js-dependencies', + trigger: (e: JQueryEventObject): void => { + if (!$(e.currentTarget).hasClass('disabled')) { + this.getResolveDependenciesAndInstallResult(data.skipDependencyUri); + Modal.dismiss(); + } + }, + }, + ]); + Modal.currentModal.on('shown.bs.modal', (): void => { + const $actionButton = Modal.currentModal.find('.t3js-dependencies'); + $('input[name="unlockDependencyIgnoreButton"]', Modal.currentModal).on('change', (e: JQueryEventObject): void => { + $actionButton.toggleClass('disabled', !$(e.currentTarget).prop('checked')); + }); + }); + } else { + let successMessage = TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.message' + + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension); + + successMessage += '\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.header'] + ': '; + $.each(data.result, (index: number, value: any): void => { + successMessage += '\n\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.item'] + ' ' + index + ': '; + $.each(value, (extkey: string): void => { + successMessage += '\n* ' + extkey; + }); + }); + Notification.info( + TYPO3.lang['extensionList.dependenciesResolveFlashMessage.title' + data.installationTypeLanguageKey] + .replace(/\{0\}/g, data.extension), + successMessage, + 15, + ); + top.TYPO3.ModuleMenu.App.refreshMenu(); + } + }, + complete: (): void => { + NProgress.done(); + }, + }); + } + + private bindSearchFieldResetter(): void { + const $searchFields = $('.typo3-extensionmanager-searchTerForm input[type="text"]'); + const searchResultShown = ('' !== $searchFields.first().val()); + + $searchFields.clearable( + { + onClear: (e: JQueryEventObject): void => { + if (searchResultShown) { + $(e.currentTarget).closest('form').submit(); + } + }, + }, + ); + } +} + +export = Repository; diff --git a/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/Update.ts b/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/Update.ts new file mode 100644 index 0000000000000000000000000000000000000000..e9c0569177e46a56d8aa2a6d77cbed144cda4a30 --- /dev/null +++ b/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/Update.ts @@ -0,0 +1,129 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +import * as $ from 'jquery'; +import * as NProgress from 'nprogress'; +import Notification = require('TYPO3/CMS/Backend/Notification'); +import 'datatables'; +import 'TYPO3/CMS/Backend/jquery.clearable'; + +enum ExtensionManagerUpdateIdentifier { + extensionTable = '#terTable', + terUpdateAction = '.update-from-ter', + pagination = '.pagination-wrap', + splashscreen = '.splash-receivedata', + terTableDataTableWrapper = '#terTableWrapper .dataTables_wrapper', +} + +class ExtensionManagerUpdate { + /** + * Register "update from ter" action + */ + public initializeEvents(): void { + $(ExtensionManagerUpdateIdentifier.terUpdateAction).each((index: number, element: any): void => { + // "this" is the form which updates the extension list from + // TER on submit + const $me = $(element); + const updateURL = $me.attr('action'); + + $me.attr('action', '#'); + $me.submit((): boolean => { + // Force update on click. + this.updateFromTer(updateURL, true); + + // Prevent normal submit action. + return false; + }); + + // This might give problems when there are more "update"-buttons, + // each one would trigger a TER-this. + this.updateFromTer(updateURL, false); + }); + } + + private updateFromTer(url: string, forceUpdate: boolean): void { + if (forceUpdate) { + url = url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager%5BforceUpdateCheck%5D=1'; + } + + // Hide triggers for TER update + $(ExtensionManagerUpdateIdentifier.terUpdateAction).addClass('is-hidden'); + + // Hide extension table + $(ExtensionManagerUpdateIdentifier.extensionTable).hide(); + + // Show loaders + $(ExtensionManagerUpdateIdentifier.splashscreen).addClass('is-shown'); + $(ExtensionManagerUpdateIdentifier.terTableDataTableWrapper).addClass('is-loading'); + $(ExtensionManagerUpdateIdentifier.pagination).addClass('is-loading'); + + let reload = false; + + $.ajax({ + url: url, + dataType: 'json', + cache: false, + beforeSend: (): void => { + NProgress.start(); + }, + success: (data: any): void => { + // Something went wrong, show message + if (data.errorMessage.length) { + Notification.error(TYPO3.lang['extensionList.updateFromTerFlashMessage.title'], data.errorMessage, 10); + } + + // Message with latest updates + const $lastUpdate = $(ExtensionManagerUpdateIdentifier.terUpdateAction + ' .time-since-last-update'); + $lastUpdate.text(data.timeSinceLastUpdate); + $lastUpdate.attr( + 'title', + TYPO3.lang['extensionList.updateFromTer.lastUpdate.timeOfLastUpdate'] + data.lastUpdateTime, + ); + + if (data.updated) { + // Reload page + reload = true; + window.location.replace(window.location.href); + } + }, + error: (jqXHR: JQueryXHR, textStatus: string, errorThrown: string): void => { + // Create an error message with diagnosis info. + const errorMessage = textStatus + '(' + errorThrown + '): ' + jqXHR.responseText; + + Notification.warning( + TYPO3.lang['extensionList.updateFromTerFlashMessage.title'], + errorMessage, + 10, + ); + }, + complete: (): void => { + NProgress.done(); + + if (!reload) { + // Hide loaders + $(ExtensionManagerUpdateIdentifier.splashscreen).removeClass('is-shown'); + $(ExtensionManagerUpdateIdentifier.terTableDataTableWrapper).removeClass('is-loading'); + $(ExtensionManagerUpdateIdentifier.pagination).removeClass('is-loading'); + + // Show triggers for TER-update + $(ExtensionManagerUpdateIdentifier.terUpdateAction).removeClass('is-hidden'); + + // Show extension table + $(ExtensionManagerUpdateIdentifier.extensionTable).show(); + } + }, + }); + } +} + +export = ExtensionManagerUpdate; diff --git a/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/UploadForm.ts b/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/UploadForm.ts new file mode 100644 index 0000000000000000000000000000000000000000..5c290cfeecfc71c2fb87ec8712b004415bb795c4 --- /dev/null +++ b/Build/Sources/TypeScript/extensionmanager/Resources/Public/TypeScript/UploadForm.ts @@ -0,0 +1,47 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +import * as $ from 'jquery'; +import 'datatables'; +import 'TYPO3/CMS/Backend/jquery.clearable'; + +class UploadForm { + public expandedUploadFormClass: string = 'transformed'; + + public initializeEvents(): void { + // Show upload form + $(document).on('click', '.t3js-upload', (event: JQueryEventObject): void => { + const $me = $(event.currentTarget); + const $uploadForm = $('.uploadForm'); + + event.preventDefault(); + if ($me.hasClass(this.expandedUploadFormClass)) { + $uploadForm.stop().slideUp(); + $me.removeClass(this.expandedUploadFormClass); + } else { + $me.addClass(this.expandedUploadFormClass); + $uploadForm.stop().slideDown(); + + $.ajax({ + url: $me.attr('href'), + dataType: 'html', + success: (data: any): void => { + $uploadForm.html(data); + }, + }); + } + }); + } +} + +export = UploadForm; diff --git a/Build/types/TYPO3/index.d.ts b/Build/types/TYPO3/index.d.ts index 447b8df4390a49d1be4568336279577c38e21c6f..2e41db07977ced82f0c97823533757fe3126520d 100644 --- a/Build/types/TYPO3/index.d.ts +++ b/Build/types/TYPO3/index.d.ts @@ -7,6 +7,7 @@ declare namespace TYPO3 { export let Backend: any; export let DebugConsole: any; + export let ExtensionManager: any; export let Icons: any; export let InfoWindow: any; export let LoginRefresh: any; @@ -129,6 +130,12 @@ interface JQueryTypedEvent<T extends Event> extends JQueryEventObject { * Required to make jQuery plugins "available" in TypeScript */ interface JQuery { + dataTableExt: any; + + search(term?: string): JQuery; + + draw(): JQuery; + clearable(options?: any): JQuery; datetimepicker(options?: any): JQuery; diff --git a/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js index a8c96c397b8fbe5266444bb74aa088a386beaa6b..022f57162536be93324f2892137a358a99c50482 100644 --- a/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js +++ b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js @@ -10,746 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -/** - * Module: TYPO3/CMS/Extensionmanager/Main - * main logic holding everything together, consists of multiple parts - * ExtensionManager => Various functions for displaying the extension list / sorting - * Repository => Various AJAX functions for TER downloads - * ExtensionManager.Update => Various AJAX functions to display updates - * ExtensionManager.uploadForm => helper to show the upload form - */ -define([ - 'jquery', - 'nprogress', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/SplitButtons', - 'TYPO3/CMS/Backend/Tooltip', - 'TYPO3/CMS/Backend/Notification', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Core/SecurityUtility', - 'datatables', - 'TYPO3/CMS/Backend/jquery.clearable' -], function($, NProgress, Modal, SplitButtons, Tooltip, Notification, Severity, SecurityUtility) { - - var securityUtility = new SecurityUtility(); - - /** - * - * @type {{identifier: {extensionlist: string, searchField: string, extensionManager: string}}} - * @exports TYPO3/CMS/Extensionmanager/Main - */ - var ExtensionManager = { - identifier: { - extensionlist: '#typo3-extension-list', - searchField: '#Tx_Extensionmanager_extensionkey' - } - }; - - /** - * - * @returns {Object} - */ - ExtensionManager.manageExtensionListing = function() { - var $searchField = $(this.identifier.searchField), - dataTable = $(this.identifier.extensionlist).DataTable({ - paging: false, - dom: 'lrtip', - lengthChange: false, - pageLength: 15, - stateSave: true, - drawCallback: this.bindExtensionListActions, - columns: [ - null, - null, - { - type: 'extension' - }, - null, - { - type: 'version' - }, { - orderable: false - }, - null, - null - ] - }); - - $searchField.parents('form').on('submit', function() { - return false; - }); - - var getVars = ExtensionManager.getUrlVars(); - - // restore filter - var currentSearch = (getVars['search'] ? getVars['search'] : dataTable.search()); - $searchField.val(currentSearch); - - $searchField.on('input', function(e) { - dataTable.search($(this).val()).draw(); - }); - - return dataTable; - }; - - /** - * - */ - ExtensionManager.bindExtensionListActions = function() { - $('.removeExtension').not('.transformed').each(function() { - var $me = $(this); - $me.data('href', $me.attr('href')); - $me.attr('href', '#'); - $me.addClass('transformed'); - $me.click(function() { - Modal.confirm( - TYPO3.lang['extensionList.removalConfirmation.title'], - TYPO3.lang['extensionList.removalConfirmation.question'], - Severity.error, - [ - { - text: TYPO3.lang['button.cancel'], - active: true, - btnClass: 'btn-default', - trigger: function() { - Modal.dismiss(); - } - }, { - text: TYPO3.lang['button.remove'], - btnClass: 'btn-danger', - trigger: function() { - ExtensionManager.removeExtensionFromDisk($me); - Modal.dismiss(); - } - } - ] - ); - }); - }); - }; - - /** - * - * @param {Object} $extension - */ - ExtensionManager.removeExtensionFromDisk = function($extension) { - $.ajax({ - url: $extension.data('href'), - beforeSend: function() { - NProgress.start(); - }, - success: function() { - location.reload(); - }, - complete: function() { - NProgress.done(); - } - }); - }; - - /** - * - * @returns {Array} - */ - ExtensionManager.getUrlVars = function() { - var vars = [], hash; - var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); - for (var i = 0; i < hashes.length; i++) { - hash = hashes[i].split('='); - vars.push(hash[0]); - vars[hash[0]] = hash[1]; - } - return vars; - }; - - $.fn.dataTableExt.oSort['extension-asc'] = function(a, b) { - return ExtensionManager.extensionCompare(a, b); - }; - - $.fn.dataTableExt.oSort['extension-desc'] = function(a, b) { - var result = ExtensionManager.extensionCompare(a, b); - return result * -1; - }; - - $.fn.dataTableExt.oSort['version-asc'] = function(a, b) { - var result = ExtensionManager.versionCompare(a, b); - return result * -1; - }; - - $.fn.dataTableExt.oSort['version-desc'] = function(a, b) { - return ExtensionManager.versionCompare(a, b); - }; - - /** - * Special sorting for the extension version column - * - * @param {String} a - * @param {String} b - * @returns {Number} - */ - ExtensionManager.versionCompare = function(a, b) { - if (a === b) { - return 0; - } - - var a_components = a.split("."); - var b_components = b.split("."); - - var len = Math.min(a_components.length, b_components.length); - - // loop while the components are equal - for (var i = 0; i < len; i++) { - // A bigger than B - if (parseInt(a_components[i]) > parseInt(b_components[i])) { - return 1; - } - - // B bigger than A - if (parseInt(a_components[i]) < parseInt(b_components[i])) { - return -1; - } - } - - // If one's a prefix of the other, the longer one is greaRepository. - if (a_components.length > b_components.length) { - return 1; - } - - if (a_components.length < b_components.length) { - return -1; - } - // Otherwise they are the same. - return 0; - }; - - /** - * The extension name column can contain various forms of HTML that - * break a direct comparison of values - * - * @param {String} a - * @param {String} b - * @returns {Number} - */ - ExtensionManager.extensionCompare = function(a, b) { - var div = document.createElement("div"); - div.innerHTML = a; - var aStr = div.textContent || div.innerText || a; - - div.innerHTML = b; - var bStr = div.textContent || div.innerText || b; - - return aStr.trim().localeCompare(bStr.trim()); - } - - /** - * - * @param {Object} data - */ - ExtensionManager.updateExtension = function(data) { - var i = 0; - var $form = $('<form>'); - $.each(data.updateComments, function(version, comment) { - var $input = $('<input>').attr({type: 'radio', name: 'version'}).val(version); - if (i === 0) { - $input.attr('checked', 'checked'); - } - $form.append([ - $('<h3>').append([ - $input, - ' ' + securityUtility.encodeHtml(version) - ]), - $('<div>') - .append( - comment - .replace(/(\r\n|\n\r|\r|\n)/g, '\n') - .split(/\n/).map(function(line) { - return securityUtility.encodeHtml(line); - }) - .join('<br>') - ) - ]); - i++; - }); - var $container = $('<div>').append([ - $('<h1>').text(TYPO3.lang['extensionList.updateConfirmation.title']), - $('<h2>').text(TYPO3.lang['extensionList.updateConfirmation.message']), - $form - ]); - - NProgress.done(); - - Modal.confirm( - TYPO3.lang['extensionList.updateConfirmation.questionVersionComments'], - $container, - Severity.warning, - [ - { - text: TYPO3.lang['button.cancel'], - active: true, - btnClass: 'btn-default', - trigger: function() { - Modal.dismiss(); - } - }, { - text: TYPO3.lang['button.updateExtension'], - btnClass: 'btn-warning', - trigger: function() { - $.ajax({ - url: data.url, - data: { - tx_extensionmanager_tools_extensionmanagerextensionmanager: { - version: $('input:radio[name=version]:checked', Modal.currentModal).val() - } - }, - dataType: 'json', - beforeSend: function() { - NProgress.start(); - }, - complete: function() { - location.reload(); - } - }); - Modal.dismiss(); - } - } - ] - ); - }; - - /** - * - * @type {{downloadPath: string}} - */ - var Repository = { - downloadPath: '' - }; - - /** - * - */ - Repository.initDom = function() { - NProgress.configure({parent: '.module-loading-indicator', showSpinner: false}); - - $('#terTable').DataTable({ - lengthChange: false, - pageLength: 15, - stateSave: false, - info: false, - paging: false, - searching: false, - ordering: false, - drawCallback: Repository.bindDownload - }); - - $('#terVersionTable').DataTable({ - lengthChange: false, - pageLength: 15, - stateSave: false, - info: false, - paging: false, - searching: false, - drawCallback: Repository.bindDownload, - order: [ - [2, 'asc'] - ], - columns: [ - {orderable: false}, - null, - {type: 'version'}, - null, - null, - null - ] - }); - - $('#terSearchTable').DataTable({ - paging: false, - lengthChange: false, - stateSave: false, - searching: false, - language: { - search: 'Filter results:' - }, - ordering: false, - drawCallback: Repository.bindDownload - }); - - Repository.bindDownload(); - Repository.bindSearchFieldResetter(); - }; - - /** - * - */ - Repository.bindDownload = function() { - var installButtons = $('.downloadFromTer form.download button[type=submit]'); - installButtons.off('click'); - installButtons.on('click', function(event) { - event.preventDefault(); - var url = $(event.currentTarget.form).attr('data-href'); - Repository.downloadPath = $(event.currentTarget.form).find('input.downloadPath:checked').val(); - $.ajax({ - url: url, - dataType: 'json', - beforeSend: function() { - NProgress.start(); - }, - success: Repository.getDependencies - }); - }); - }; - - /** - * - * @param {Object} data - * @returns {Boolean} - */ - Repository.getDependencies = function(data) { - NProgress.done(); - if (data.hasDependencies) { - Modal.confirm(data.title, $(data.message), Severity.info, [ - { - text: TYPO3.lang['button.cancel'], - active: true, - btnClass: 'btn-default', - trigger: function() { - Modal.dismiss(); - } - }, { - text: TYPO3.lang['button.resolveDependencies'], - btnClass: 'btn-info', - trigger: function() { - Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath); - Modal.dismiss(); - } - } - ]); - } else { - if (data.hasErrors) { - Notification.error(data.title, data.message, 15); - } else { - Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath); - } - } - return false; - }; - - /** - * - * @param {String} url - */ - Repository.getResolveDependenciesAndInstallResult = function(url) { - $.ajax({ - url: url, - dataType: 'json', - beforeSend: function() { - NProgress.start(); - }, - success: function(data) { - if (data.errorCount > 0) { - Modal.confirm(data.errorTitle, $(data.errorMessage), Severity.error, [ - { - text: TYPO3.lang['button.cancel'], - active: true, - btnClass: 'btn-default', - trigger: function() { - Modal.dismiss(); - } - }, { - text: TYPO3.lang['button.resolveDependenciesIgnore'], - btnClass: 'btn-danger disabled t3js-dependencies', - trigger: function() { - if (!$(this).hasClass('disabled')) { - Repository.getResolveDependenciesAndInstallResult(data.skipDependencyUri); - Modal.dismiss(); - } - } - } - ]); - Modal.currentModal.on('shown.bs.modal', function() { - var $actionButton = Modal.currentModal.find('.t3js-dependencies'); - $('input[name="unlockDependencyIgnoreButton"]', Modal.currentModal).on('change', function() { - $actionButton.toggleClass('disabled', !$(this).prop('checked')); - }); - }); - } else { - var successMessage = TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.message' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension); - - successMessage += '\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.header'] + ': '; - $.each(data.result, function(index, value) { - successMessage += '\n\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.item'] + ' ' + index + ': '; - $.each(value, function(extkey) { - successMessage += '\n* ' + extkey - }); - }); - Notification.info(TYPO3.lang['extensionList.dependenciesResolveFlashMessage.title' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension), successMessage, 15); - top.TYPO3.ModuleMenu.App.refreshMenu(); - } - }, - complete: function() { - NProgress.done(); - } - }); - }; - - /** - * - */ - Repository.bindSearchFieldResetter = function() { - var $searchFields = $('.typo3-extensionmanager-searchTerForm input[type="text"]'); - var searchResultShown = ('' !== $searchFields.first().val()); - - $searchFields.clearable( - { - onClear: function() { - if (searchResultShown) { - $(this).closest('form').submit(); - } - } - } - ); - }; - - /** - * - * @type {{identifier: {extensionTable: string, terUpdateAction: string, pagination: string, splashscreen: string, terTableWrapper: string, terTableDataTableWrapper: string}}} - */ - ExtensionManager.Update = { - identifier: { - extensionTable: '#terTable', - terUpdateAction: '.update-from-ter', - pagination: '.pagination-wrap', - splashscreen: '.splash-receivedata', - terTableWrapper: '#terTableWrapper', - terTableDataTableWrapper: '#terTableWrapper .dataTables_wrapper' - } - }; - - /** - * Register "update from ter" action - */ - ExtensionManager.Update.initializeEvents = function() { - $(ExtensionManager.Update.identifier.terUpdateAction).each(function() { - - // "this" is the form which updates the extension list from - // TER on submit - var $me = $(this), - updateURL = $(this).attr('action'); - - $me.attr('action', '#'); - $me.submit(function() { - // Force update on click. - ExtensionManager.Update.updateFromTer(updateURL, true); - - // Prevent normal submit action. - return false; - }); - - // This might give problems when there are more "update"-buttons, - // each one would trigger a TER-ExtensionManager.Update. - ExtensionManager.Update.updateFromTer(updateURL, false); - }); - }; - - /** - * - * @param {String} url - * @param {Boolean} forceUpdate - */ - ExtensionManager.Update.updateFromTer = function(url, forceUpdate) { - if (forceUpdate) { - url = url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager%5BforceUpdateCheck%5D=1'; - } - - // Hide triggers for TER update - $(ExtensionManager.Update.identifier.terUpdateAction).addClass('is-hidden'); - - // Hide extension table - $(ExtensionManager.Update.identifier.extensionTable).hide(); - - // Show loaders - $(ExtensionManager.Update.identifier.splashscreen).addClass('is-shown'); - $(ExtensionManager.Update.identifier.terTableDataTableWrapper).addClass('is-loading'); - $(ExtensionManager.Update.identifier.pagination).addClass('is-loading'); - - var reload = false; - - $.ajax({ - url: url, - dataType: 'json', - cache: false, - beforeSend: function() { - NProgress.start(); - }, - success: function(data) { - // Something went wrong, show message - if (data.errorMessage.length) { - Notification.error(TYPO3.lang['extensionList.updateFromTerFlashMessage.title'], data.errorMessage, 10); - } - - // Message with latest updates - var $lastUpdate = $(ExtensionManager.Update.identifier.terUpdateAction + ' .time-since-last-update'); - $lastUpdate.text(data.timeSinceLastUpdate); - $lastUpdate.attr( - 'title', - TYPO3.lang['extensionList.updateFromTer.lastUpdate.timeOfLastUpdate'] + data.lastUpdateTime - ); - - if (data.updated) { - // Reload page - reload = true; - window.location.replace(window.location.href); - } - }, - error: function(jqXHR, textStatus, errorThrown) { - // Create an error message with diagnosis info. - var errorMessage = textStatus + '(' + errorThrown + '): ' + jqXHR.responseText; - - Notification.warning( - TYPO3.lang['extensionList.updateFromTerFlashMessage.title'], - errorMessage, - 10 - ); - }, - complete: function() { - NProgress.done(); - - if (!reload) { - // Hide loaders - $(ExtensionManager.Update.identifier.splashscreen).removeClass('is-shown'); - $(ExtensionManager.Update.identifier.terTableDataTableWrapper).removeClass('is-loading'); - $(ExtensionManager.Update.identifier.pagination).removeClass('is-loading'); - - // Show triggers for TER-update - $(ExtensionManager.Update.identifier.terUpdateAction).removeClass('is-hidden'); - - // Show extension table - $(ExtensionManager.Update.identifier.extensionTable).show(); - } - } - }); - }; - - /** - * - */ - ExtensionManager.Update.transformPaginatorToAjax = function() { - $(ExtensionManager.Update.identifier.pagination + ' a').each(function() { - var $me = $(this); - $me.data('href', $(this).attr('href')); - $me.attr('href', '#'); - $me.click(function() { - var $terTableWrapper = $(ExtensionManager.Update.identifier.terTableWrapper); - NProgress.start(); - $.ajax({ - url: $(this).data('href'), - dataType: 'json', - success: function(data) { - $terTableWrapper.html(data); - ExtensionManager.Update.transformPaginatorToAjax(); - }, - complete: function() { - NProgress.done(); - } - }); - }); - }); - }; - - /** - * show the uploading form - */ - ExtensionManager.UploadForm = { - expandedUploadFormClass: 'transformed' - }; - - /** - * - */ - ExtensionManager.UploadForm.initializeEvents = function() { - // Show upload form - $(document).on('click', '.t3js-upload', function(event) { - var $me = $(this), - $uploadForm = $('.uploadForm'); - - event.preventDefault(); - if ($me.hasClass(ExtensionManager.UploadForm.expandedUploadFormClass)) { - $uploadForm.stop().slideUp(); - $me.removeClass(ExtensionManager.UploadForm.expandedUploadFormClass); - } else { - $me.addClass(ExtensionManager.UploadForm.expandedUploadFormClass); - $uploadForm.stop().slideDown(); - - $.ajax({ - url: $me.attr('href'), - dataType: 'html', - success: function(data) { - $uploadForm.html(data); - } - }); - } - }); - }; - - $(function() { - var dataTable = ExtensionManager.manageExtensionListing(); - - $(document).on('click', '.onClickMaskExtensionManager', function() { - NProgress.start(); - }).on('click', 'a[data-action=update-extension]', function(e) { - e.preventDefault(); - $.ajax({ - url: $(this).attr('href'), - dataType: 'json', - beforeSend: function() { - NProgress.start(); - }, - success: ExtensionManager.updateExtension - }); - }).on('change', 'input[name=unlockDependencyIgnoreButton]', function() { - var $actionButton = $('.t3js-dependencies'); - $actionButton.toggleClass('disabled', !$(this).prop('checked')); - }); - - $(ExtensionManager.identifier.searchField).clearable({ - onClear: function() { - dataTable.search('').draw(); - } - }); - - $(document).on('click', '.t3-button-action-installdistribution', function() { - NProgress.start(); - }); - - SplitButtons.addPreSubmitCallback(function(e) { - if ($(e.target).hasClass('t3js-save-close')) { - $('#configurationform').append($('<input />', { - type: 'hidden', - name: 'tx_extensionmanager_tools_extensionmanagerextensionmanager[action]', - value: 'saveAndClose' - })); - } - }); - - // initialize the repository - Repository.initDom(); - - ExtensionManager.Update.initializeEvents(); - ExtensionManager.UploadForm.initializeEvents(); - - Tooltip.initialize('#typo3-extension-list [title]', { - delay: { - show: 500, - hide: 100 - }, - trigger: 'hover', - container: 'body' - }); - }); - - if (typeof TYPO3.ExtensionManager === 'undefined') { - TYPO3.ExtensionManager = ExtensionManager; - } - - return ExtensionManager; -}); +define(["require","exports","jquery","nprogress","TYPO3/CMS/Backend/Modal","TYPO3/CMS/Backend/SplitButtons","TYPO3/CMS/Backend/Tooltip","TYPO3/CMS/Backend/Severity","TYPO3/CMS/Core/SecurityUtility","./Repository","./Update","./UploadForm","datatables","TYPO3/CMS/Backend/jquery.clearable"],function(n,e,t,a,o,i,r,s,l,c,u,d){"use strict";var p,f,m=new l;(f=p||(p={})).extensionlist="#typo3-extension-list",f.searchField="#Tx_Extensionmanager_extensionkey";var g=new(function(){function n(){var e=this;this.bindExtensionListActions=function(){t(".removeExtension").not(".transformed").each(function(n,a){var i=t(a);i.data("href",i.attr("href")),i.attr("href","#"),i.addClass("transformed"),i.click(function(){o.confirm(TYPO3.lang["extensionList.removalConfirmation.title"],TYPO3.lang["extensionList.removalConfirmation.question"],s.error,[{text:TYPO3.lang["button.cancel"],active:!0,btnClass:"btn-default",trigger:function(){o.dismiss()}},{text:TYPO3.lang["button.remove"],btnClass:"btn-danger",trigger:function(){e.removeExtensionFromDisk(i),o.dismiss()}}])})})},t(function(){t.fn.dataTableExt.oSort["extension-asc"]=function(e,t){return n.extensionCompare(e,t)},t.fn.dataTableExt.oSort["extension-desc"]=function(e,t){return-1*n.extensionCompare(e,t)},t.fn.dataTableExt.oSort["version-asc"]=function(e,t){return-1*n.versionCompare(e,t)},t.fn.dataTableExt.oSort["version-desc"]=function(e,t){return n.versionCompare(e,t)},e.Update=new u,e.UploadForm=new d,e.Repository=new c;var o=e.manageExtensionListing();t(document).on("click",".onClickMaskExtensionManager",function(){a.start()}).on("click","a[data-action=update-extension]",function(n){n.preventDefault(),t.ajax({url:t(e).attr("href"),dataType:"json",beforeSend:function(){a.start()},success:e.updateExtension})}).on("change","input[name=unlockDependencyIgnoreButton]",function(n){t(".t3js-dependencies").toggleClass("disabled",!t(n.currentTarget).prop("checked"))}),t(p.searchField).clearable({onClear:function(){o.search("").draw()}}),t(document).on("click",".t3-button-action-installdistribution",function(){a.start()}),i.addPreSubmitCallback(function(n){t(n.target).hasClass("t3js-save-close")&&t("#configurationform").append(t("<input />",{type:"hidden",name:"tx_extensionmanager_tools_extensionmanagerextensionmanager[action]",value:"saveAndClose"}))}),e.Repository.initDom(),e.Update.initializeEvents(),e.UploadForm.initializeEvents(),r.initialize("#typo3-extension-list [title]",{delay:{show:500,hide:100},trigger:"hover",container:"body"})})}return n.prototype.manageExtensionListing=function(){var e=t(p.searchField),a=t(p.extensionlist).DataTable({paging:!1,dom:"lrtip",lengthChange:!1,pageLength:15,stateSave:!0,drawCallback:this.bindExtensionListActions,columns:[null,null,{type:"extension"},null,{type:"version"},{orderable:!1},null,null]});e.parents("form").on("submit",function(){return!1});var o=n.getUrlVars(),i=o.search?o.search:a.search();return e.val(i),e.on("input",function(n){a.search(t(n.currentTarget).val()).draw()}),a},n.prototype.removeExtensionFromDisk=function(n){t.ajax({url:n.data("href"),beforeSend:function(){a.start()},success:function(){location.reload()},complete:function(){a.done()}})},n.getUrlVars=function(){for(var n,e=[],t=window.location.href.slice(window.location.href.indexOf("?")+1).split("&"),a=0;a<t.length;a++)n=t[a].split("="),e.push(n[0]),e[n[0]]=n[1];return e},n.versionCompare=function(n,e){if(n===e)return 0;for(var t=n.split("."),a=e.split("."),o=Math.min(t.length,a.length),i=0;i<o;i++){if(parseInt(t[i],10)>parseInt(a[i],10))return 1;if(parseInt(t[i],10)<parseInt(a[i],10))return-1}return t.length>a.length?1:t.length<a.length?-1:0},n.extensionCompare=function(n,e){var t=document.createElement("div");t.innerHTML=n;var a=t.textContent||t.innerText||n;t.innerHTML=e;var o=t.textContent||t.innerText||e;return a.trim().localeCompare(o.trim())},n.prototype.updateExtension=function(n){var e=0,i=t("<form>");t.each(n.updateComments,function(n,a){var o=t("<input>").attr({type:"radio",name:"version"}).val(n);0===e&&o.attr("checked","checked"),i.append([t("<h3>").append([o," "+m.encodeHtml(n)]),t("<div>").append(a.replace(/(\r\n|\n\r|\r|\n)/g,"\n").split(/\n/).map(function(n){return m.encodeHtml(n)}).join("<br>"))]),e++});var r=t("<div>").append([t("<h1>").text(TYPO3.lang["extensionList.updateConfirmation.title"]),t("<h2>").text(TYPO3.lang["extensionList.updateConfirmation.message"]),i]);a.done(),o.confirm(TYPO3.lang["extensionList.updateConfirmation.questionVersionComments"],r,s.warning,[{text:TYPO3.lang["button.cancel"],active:!0,btnClass:"btn-default",trigger:function(){o.dismiss()}},{text:TYPO3.lang["button.updateExtension"],btnClass:"btn-warning",trigger:function(){t.ajax({url:n.url,data:{tx_extensionmanager_tools_extensionmanagerextensionmanager:{version:t("input:radio[name=version]:checked",o.currentModal).val()}},dataType:"json",beforeSend:function(){a.start()},complete:function(){location.reload()}}),o.dismiss()}}])},n}());return void 0===TYPO3.ExtensionManager&&(TYPO3.ExtensionManager=g),g}); \ No newline at end of file diff --git a/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Repository.js b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Repository.js new file mode 100644 index 0000000000000000000000000000000000000000..7a55562ea86f1a06646968efac6f67dccbd9f4c2 --- /dev/null +++ b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Repository.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +define(["require","exports","jquery","nprogress","TYPO3/CMS/Backend/Modal","TYPO3/CMS/Backend/Notification","TYPO3/CMS/Backend/Severity","datatables","TYPO3/CMS/Backend/jquery.clearable"],function(e,n,t,a,o,s,r){"use strict";return function(){function e(){var e=this;this.downloadPath="",this.initDom=function(){a.configure({parent:".module-loading-indicator",showSpinner:!1}),t("#terTable").DataTable({lengthChange:!1,pageLength:15,stateSave:!1,info:!1,paging:!1,searching:!1,ordering:!1,drawCallback:e.bindDownload}),t("#terVersionTable").DataTable({lengthChange:!1,pageLength:15,stateSave:!1,info:!1,paging:!1,searching:!1,drawCallback:e.bindDownload,order:[[2,"asc"]],columns:[{orderable:!1},null,{type:"version"},null,null,null]}),t("#terSearchTable").DataTable({paging:!1,lengthChange:!1,stateSave:!1,searching:!1,language:{search:"Filter results:"},ordering:!1,drawCallback:e.bindDownload}),e.bindDownload(),e.bindSearchFieldResetter()},this.bindDownload=function(){var n=t(".downloadFromTer form.download button[type=submit]");n.off("click"),n.on("click",function(n){n.preventDefault();var o=t(n.currentTarget),s=t(o.form).attr("data-href");e.downloadPath=t(o.form).find("input.downloadPath:checked").val(),t.ajax({url:s,dataType:"json",beforeSend:function(){a.start()},success:e.getDependencies})})},this.getDependencies=function(n){return a.done(),n.hasDependencies?o.confirm(n.title,t(n.message),r.info,[{text:TYPO3.lang["button.cancel"],active:!0,btnClass:"btn-default",trigger:function(){o.dismiss()}},{text:TYPO3.lang["button.resolveDependencies"],btnClass:"btn-info",trigger:function(){e.getResolveDependenciesAndInstallResult(n.url+"&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]="+e.downloadPath),o.dismiss()}}]):n.hasErrors?s.error(n.title,n.message,15):e.getResolveDependenciesAndInstallResult(n.url+"&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]="+e.downloadPath),!1},this.getResolveDependenciesAndInstallResult=function(n){t.ajax({url:n,dataType:"json",beforeSend:function(){a.start()},success:function(n){if(n.errorCount>0)o.confirm(n.errorTitle,t(n.errorMessage),r.error,[{text:TYPO3.lang["button.cancel"],active:!0,btnClass:"btn-default",trigger:function(){o.dismiss()}},{text:TYPO3.lang["button.resolveDependenciesIgnore"],btnClass:"btn-danger disabled t3js-dependencies",trigger:function(a){t(a.currentTarget).hasClass("disabled")||(e.getResolveDependenciesAndInstallResult(n.skipDependencyUri),o.dismiss())}}]),o.currentModal.on("shown.bs.modal",function(){var e=o.currentModal.find(".t3js-dependencies");t('input[name="unlockDependencyIgnoreButton"]',o.currentModal).on("change",function(n){e.toggleClass("disabled",!t(n.currentTarget).prop("checked"))})});else{var a=TYPO3.lang["extensionList.dependenciesResolveDownloadSuccess.message"+n.installationTypeLanguageKey].replace(/\{0\}/g,n.extension);a+="\n"+TYPO3.lang["extensionList.dependenciesResolveDownloadSuccess.header"]+": ",t.each(n.result,function(e,n){a+="\n\n"+TYPO3.lang["extensionList.dependenciesResolveDownloadSuccess.item"]+" "+e+": ",t.each(n,function(e){a+="\n* "+e})}),s.info(TYPO3.lang["extensionList.dependenciesResolveFlashMessage.title"+n.installationTypeLanguageKey].replace(/\{0\}/g,n.extension),a,15),top.TYPO3.ModuleMenu.App.refreshMenu()}},complete:function(){a.done()}})}}return e.prototype.bindSearchFieldResetter=function(){var e=t('.typo3-extensionmanager-searchTerForm input[type="text"]'),n=""!==e.first().val();e.clearable({onClear:function(e){n&&t(e.currentTarget).closest("form").submit()}})},e}()}); \ No newline at end of file diff --git a/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Update.js b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Update.js new file mode 100644 index 0000000000000000000000000000000000000000..cd563edb4a8606a2381a1d03f7ed8ef6f50e6a00 --- /dev/null +++ b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Update.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +define(["require","exports","jquery","nprogress","TYPO3/CMS/Backend/Notification","datatables","TYPO3/CMS/Backend/jquery.clearable"],function(e,a,t,n,r){"use strict";var s,i;return(i=s||(s={})).extensionTable="#terTable",i.terUpdateAction=".update-from-ter",i.pagination=".pagination-wrap",i.splashscreen=".splash-receivedata",i.terTableDataTableWrapper="#terTableWrapper .dataTables_wrapper",function(){function e(){}return e.prototype.initializeEvents=function(){var e=this;t(s.terUpdateAction).each(function(a,n){var r=t(n),s=r.attr("action");r.attr("action","#"),r.submit(function(){return e.updateFromTer(s,!0),!1}),e.updateFromTer(s,!1)})},e.prototype.updateFromTer=function(e,a){a&&(e+="&tx_extensionmanager_tools_extensionmanagerextensionmanager%5BforceUpdateCheck%5D=1"),t(s.terUpdateAction).addClass("is-hidden"),t(s.extensionTable).hide(),t(s.splashscreen).addClass("is-shown"),t(s.terTableDataTableWrapper).addClass("is-loading"),t(s.pagination).addClass("is-loading");var i=!1;t.ajax({url:e,dataType:"json",cache:!1,beforeSend:function(){n.start()},success:function(e){e.errorMessage.length&&r.error(TYPO3.lang["extensionList.updateFromTerFlashMessage.title"],e.errorMessage,10);var a=t(s.terUpdateAction+" .time-since-last-update");a.text(e.timeSinceLastUpdate),a.attr("title",TYPO3.lang["extensionList.updateFromTer.lastUpdate.timeOfLastUpdate"]+e.lastUpdateTime),e.updated&&(i=!0,window.location.replace(window.location.href))},error:function(e,a,t){var n=a+"("+t+"): "+e.responseText;r.warning(TYPO3.lang["extensionList.updateFromTerFlashMessage.title"],n,10)},complete:function(){n.done(),i||(t(s.splashscreen).removeClass("is-shown"),t(s.terTableDataTableWrapper).removeClass("is-loading"),t(s.pagination).removeClass("is-loading"),t(s.terUpdateAction).removeClass("is-hidden"),t(s.extensionTable).show())}})},e}()}); \ No newline at end of file diff --git a/typo3/sysext/extensionmanager/Resources/Public/JavaScript/UploadForm.js b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/UploadForm.js new file mode 100644 index 0000000000000000000000000000000000000000..aa06ea689ba99381a04bbab6ff77489a1a56914c --- /dev/null +++ b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/UploadForm.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +define(["require","exports","jquery","datatables","TYPO3/CMS/Backend/jquery.clearable"],function(e,a,t){"use strict";return function(){function e(){this.expandedUploadFormClass="transformed"}return e.prototype.initializeEvents=function(){var e=this;t(document).on("click",".t3js-upload",function(a){var s=t(a.currentTarget),r=t(".uploadForm");a.preventDefault(),s.hasClass(e.expandedUploadFormClass)?(r.stop().slideUp(),s.removeClass(e.expandedUploadFormClass)):(s.addClass(e.expandedUploadFormClass),r.stop().slideDown(),t.ajax({url:s.attr("href"),dataType:"html",success:function(e){r.html(e)}}))})},e}()}); \ No newline at end of file