Skip to content

Commit

Permalink
working on a widget, part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
mutantsan committed Jun 26, 2024
1 parent 80f37be commit a78be0f
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 38 deletions.
53 changes: 49 additions & 4 deletions ckanext/file_upload_widget/assets/css/styles.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

147 changes: 135 additions & 12 deletions ckanext/file_upload_widget/assets/js/file-upload-widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ ckan.module("file-upload-widget", function ($, _) {
fileInputButton: '.btn-file-input',
urlInputButton: '.btn-url-input',
mediaInputButton: '.btn-media-input',
//
mainWindowBlock: '.fuw-main-window',
urlInputBlock: '.fuw-url-input',
mediaInputBlock: '.fuw-media-input',
Expand All @@ -17,7 +16,6 @@ ckan.module("file-upload-widget", function ($, _) {

console.log('file-upload-widget initialized');

this.initBtn = this.el.find(".fuw-init-btn");
this.fileInputBtn = this.el.find(this.const.fileInputButton);
this.urlInputBtn = this.el.find(this.const.urlInputButton);
this.mediaInputBtn = this.el.find(this.const.mediaInputButton);
Expand All @@ -26,42 +24,167 @@ ckan.module("file-upload-widget", function ($, _) {
this.urlWindow = this.el.find(this.const.urlInputBlock);
this.mediaWindow = this.el.find(this.const.mediaInputBlock);

this.fileSearchInput = this.el.find('#fuw-media-input--search');
this.fileSelectBtn = this.el.find('.btn-file-select');
this.cancelFileSelectBtn = this.el.find('.btn-cancel-file-select');

this.cancelBtn = this.el.find(this.const.cancelBtn);

// Bind events
this.initBtn.on('click', this._onTriggerModal);
this.fileInputBtn.on('click', this._onFileInputTriggered);
this.urlInputBtn.on('click', this._onUrlInputTriggered);
this.mediaInputBtn.on('click', this._onMediaInputTriggered);
this.cancelBtn.on('click', this._onCancelAction);
this.fileSearchInput.on('input', this._onFileSearch);
this.el.find('li.files--file-item input').on('change', this._onFileSelect);
this.cancelFileSelectBtn.on('click', this._onCancelFileSelect);
},
_onTriggerModal: function (e) {
console.log('trigger modal');
},

/**
* Handle file input trigger
*
* On file input trigger show an HTML file selector
*
* @param {Event} e
*/
_onFileInputTriggered: function (e) {
console.log('file input triggered');
},
_onUrlInputTriggered: function (e) {
console.log('url input triggered');

/**
* Handle url input trigger
*
* On url input trigger show url input block and hide main window
*
* @param {Event} e
*/
_onUrlInputTriggered: function (e) {
this.urlWindow.toggle();
this.mainWindow.toggle();
this.cancelBtn.toggle();
},
_onMediaInputTriggered: function (e) {
console.log('media input triggered');

/**
* Handle media input trigger
*
* On media input trigger show media input block and hide main window
*
* @param {Event} e
*/
_onMediaInputTriggered: function (e) {
this.mediaWindow.toggle();
this.mainWindow.toggle();
this.cancelBtn.toggle();
},
_onCancelAction: function (e) {
console.log('cancel action');

/**
* Handle cancel action
*
* On cancel action hide url and media input blocks and show main window
* and hide the cancel button.
*
* @param {Event} e
*/
_onCancelAction: function (e) {
this.urlWindow.hide();
this.mediaWindow.hide();
this.mainWindow.toggle();
this.cancelBtn.toggle();
},

/**
* Handle file search input
*
* On file search input change hide files that don't match search query
* and highlight text that matches search query.
*
* If there are no visible files show empty state message.
*
* @param {Event} e
*/
_onFileSearch: function (e) {
let search = this.fileSearchInput.val().toLowerCase();
let isEmpty = true;

this.mediaWindow.find('li.files--file-item').each((_, element) => {
let title = $(element).find("label span").text().trim().toLowerCase();

if (!!search && title.indexOf(search) === -1) {
$(element).hide();
} else {
$(element).show();

isEmpty = false;

this._highlightText(element, search);
};
});

let visibleFilesNum = this.el.find("li.files--file-item:visible").length;

if (isEmpty && !visibleFilesNum) {
this.el.find(".fuw-media-input--empty").show();
this.el.find(".fuw-media-input--files").hide();
} else {
this.el.find(".fuw-media-input--empty").hide();
this.el.find(".fuw-media-input--files").show();
}
},

/**
* Highlight text in file name
*
* If text is provided highlight it in file name
* If text is empty remove highlight using the original file name
*
* @param {HTMLElement} element - file li item
* @param {String} text - text to highlight
*/
_highlightText: function (element, text) {
let originalName = $(element).attr("fuw-original-file-name");

let highlightedName = originalName;

if (text) {
let regex = new RegExp(text, 'gi'); // 'g' for global, 'i' for case-insensitive

highlightedName = originalName.replace(regex, function (match) {
return "<span class='highlight'>" + match + "</span>";
});
}

$(element).find("label span").html(highlightedName);
},

/**
* Handle file selection
*
* @param {Event} e
*/
_onFileSelect: function (e) {
let selectedFilesNum = this._countSelectedFiles();

this.fileSelectBtn.find("span").text(selectedFilesNum);
this.el.find(".modal-footer").toggle(!!selectedFilesNum);
},

/**
* Count selected files
*
* @returns {Number} - number of selected files
*/
_countSelectedFiles: function () {
return this.el.find('li.files--file-item input:checked').length;
},

/**
* Cancel file selection
*
* @param {Event} e
*/
_onCancelFileSelect: function (e) {
this.el.find('li.files--file-item input:checked').prop('checked', false);
this.el.find('li.files--file-item input:first').trigger('change');
}
};
});
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="btn btn-black fuw-cancel-btn" style="display: none;">{{ _("Cancel") }}</button>
<i class="fa-solid fa-angles-left fuw-cancel-btn" style="display: none;"></i>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Expand Down Expand Up @@ -59,34 +59,38 @@
<!-- MEDIA GALLERY WINDOW -->
<div class="fuw-media-input" style="display: none;">
<div class="search-input">
<input aria-label="Search files..." id="fuw-media-input--search" type="text" class="form-control input-lg" value="" autocomplete="off" placeholder="Search files...">
<input aria-label="Search files..." id="fuw-media-input--search" type="search" class="form-control input-lg" value="" autocomplete="off" placeholder="Search files...">

<span class="input-group-btn">
<i class="fa fa-search"></i>
</span>
</div>

<div class="fuw-media-input--files">
<div class="fuw-media-input--file">
<img src="https://via.placeholder.com/150" alt="Placeholder image">
<button type="button" class="btn btn-primary">{{ _("Select") }}</button>
</div>
<div class="fuw-media-input--file">
<img src="https://via.placeholder.com/150" alt="Placeholder image">
<button type="button" class="btn btn-primary">{{ _("Select") }}</button>
</div>
<div class="fuw-media-input--file">
<img src="https://via.placeholder.com/150" alt="Placeholder image">
<button type="button" class="btn btn-primary">{{ _("Select") }}</button>
</div>
<div class="fuw-media-input--file">
<img src="https://via.placeholder.com/150" alt="Placeholder image">
<button type="button" class="btn btn-primary">{{ _("Select") }}</button>
</div>
<ul class="fuw-media-input--files">
{% for i in range(21) %}
{% set file_name = "Existing file " + i|string + ".csv" %}
<li class="files--file-item" fuw-original-file-name="{{ file_name }}">
<input type="checkbox" name="{{ 'file-item-{}'.format(i) }}" id="{{ 'file-item-{}'.format(i) }}">
<label for="{{ 'file-item-{}'.format(i) }}">
<div class="file-item--icon-wrapper">
<img src="https://via.placeholder.com/16" referrerpolicy="no-referrer" loading="lazy" width="16" height="16">
</div>
<span>{{ file_name }}</span>
</label>
</li>
{% endfor %}
</ul>

<div class="fuw-media-input--empty" style="display: none;">
<p>{{ _("No files found") }}</p>
</div>
</div>

</div>
<div class="modal-footer" style="display: none;">
<button type="button" class="btn btn-primary btn-file-select">{{ _("Select") }} <span>0</span></button>
<button type="button" class="btn btn-black btn-cancel-file-select">{{ _("Cancel") }}</button>
</div>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit a78be0f

Please sign in to comment.