Add sort and query functions to file list
Added sort functionality and query methods to the file list, enabling users to sort file entries by name, size or modification date. The sorting can be in ascending or descending order. Also, updated element.js for element retrieval and added 'getElementsOrThrow' and 'getElements' methods.
This commit is contained in:
parent
f45f23db1d
commit
e501969807
|
@ -1,8 +1,10 @@
|
|||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::time::{UNIX_EPOCH};
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::string::ToString;
|
||||
|
||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
#[tauri::command]
|
||||
|
@ -25,10 +27,29 @@ struct EntryMetaData {
|
|||
accessed: u64,
|
||||
}
|
||||
|
||||
enum EntryMetaDataFieldValues {
|
||||
Str(String),
|
||||
Int(u64),
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
impl EntryMetaData {
|
||||
pub fn get_field(&self, field: &str) -> Option<EntryMetaDataFieldValues> {
|
||||
match field {
|
||||
"name" => Some(EntryMetaDataFieldValues::Str(self.name.clone())),
|
||||
"size" => Some(EntryMetaDataFieldValues::Int(self.size)),
|
||||
"modified" => Some(EntryMetaDataFieldValues::Int(self.modified)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn get_files(
|
||||
_window: tauri::Window,
|
||||
directory: &str,
|
||||
sort: &str,
|
||||
order: &str,
|
||||
) -> Vec<EntryMetaData> {
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
@ -91,6 +112,47 @@ fn get_files(
|
|||
});
|
||||
}
|
||||
|
||||
if sort != "" && order != "" {
|
||||
let order_asc = order != "desc";
|
||||
data.sort_by(|a, b| {
|
||||
if let Some(field_a) = a.get_field(sort) {
|
||||
if let Some(field_b) = b.get_field(sort) {
|
||||
return match field_a {
|
||||
EntryMetaDataFieldValues::Str(a_string) => {
|
||||
match field_b {
|
||||
EntryMetaDataFieldValues::Str(b_string) => match order_asc {
|
||||
true => a_string.cmp(&b_string),
|
||||
false => b_string.cmp(&a_string)
|
||||
},
|
||||
_ => Ordering::Equal
|
||||
}
|
||||
}
|
||||
EntryMetaDataFieldValues::Int(a_int) => {
|
||||
match field_b {
|
||||
EntryMetaDataFieldValues::Int(b_int) => match order_asc {
|
||||
true => a_int.cmp(&b_int),
|
||||
false => b_int.cmp(&a_int)
|
||||
},
|
||||
_ => Ordering::Equal
|
||||
}
|
||||
}
|
||||
EntryMetaDataFieldValues::Bool(a_bool) => {
|
||||
match field_b {
|
||||
EntryMetaDataFieldValues::Bool(b_bool) => match order_asc {
|
||||
true => a_bool.cmp(&b_bool),
|
||||
false => b_bool.cmp(&a_bool)
|
||||
},
|
||||
_ => Ordering::Equal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ordering::Equal;
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,9 +57,15 @@
|
|||
<table class="w-full">
|
||||
<thead>
|
||||
<tr class="sticky top-0 bg-red-500">
|
||||
<th>Name</th>
|
||||
<th>Size</th>
|
||||
<th>Modified</th>
|
||||
<th data-el="sort" data-sort="name" data-order="">
|
||||
Name
|
||||
</th>
|
||||
<th data-el="sort" data-sort="size" data-order="">
|
||||
Size
|
||||
</th>
|
||||
<th data-el="sort" data-sort="modified" data-order="">
|
||||
Modified
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-el="body"></tbody>
|
||||
|
|
|
@ -25,7 +25,7 @@ export const getElementOrThrow = (source, selector) => {
|
|||
const element = getElement(source, selector);
|
||||
|
||||
if (!element) {
|
||||
throw new Error(`Element ${selector} not found in ${source}`);
|
||||
throw new Error(`Element ${selector} not found in ${source.innerHTML}`);
|
||||
}
|
||||
|
||||
return element;
|
||||
|
@ -40,7 +40,7 @@ export const getElementsOrThrow = (source, selector) => {
|
|||
const elements = getElements(source, selector);
|
||||
|
||||
if (elements.length <= 0) {
|
||||
throw new Error(`No elements found with ${selector} in ${source}`);
|
||||
throw new Error(`No elements found with ${selector} in ${source.innerHTML}`);
|
||||
}
|
||||
|
||||
return elements
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {getElementOrThrow, getOneElementOrThrow} from "./element.js";
|
||||
import {getElementOrThrow, getElements, getElementsOrThrow, getOneElementOrThrow} from "./element.js";
|
||||
|
||||
/**
|
||||
* @typedef {Object} Template
|
||||
|
@ -22,10 +22,24 @@ export const getTemplate = (name) => {
|
|||
*/
|
||||
const el = (selector) => getElementOrThrow(element, `[data-el=${selector}]`);
|
||||
|
||||
/**
|
||||
* @param {string} selector
|
||||
* @returns {HTMLElement[]}
|
||||
*/
|
||||
const els = (selector) => getElementsOrThrow(element, `[data-el=${selector}]`);
|
||||
|
||||
/**
|
||||
* @param {string} selector
|
||||
* @returns {HTMLElement[]}
|
||||
*/
|
||||
const query = (selector) => getElements(element, selector);
|
||||
|
||||
const render = () => element;
|
||||
|
||||
return {
|
||||
el,
|
||||
els,
|
||||
query,
|
||||
render
|
||||
}
|
||||
}
|
|
@ -56,10 +56,12 @@ export const renderFiles = async () => {
|
|||
|
||||
/**
|
||||
* @param {string} directory
|
||||
* @param {string} sort
|
||||
* @param {string} order
|
||||
* @returns {Promise<Entry[]>}
|
||||
*/
|
||||
export const getEntries = async (directory) => {
|
||||
return await tauriInvoke('get_files', { directory });
|
||||
export const getEntries = async (directory, sort = '', order = 'asc') => {
|
||||
return await tauriInvoke('get_files', { directory, sort, order });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,9 +6,9 @@ import {sep} from "../../libs/path.js";
|
|||
|
||||
export const renderListFiles = () => {
|
||||
const fileEl = getOneElementOrThrow(document, '[data-ui=files]');
|
||||
const containerTemplate = getTemplate('files-list');
|
||||
|
||||
const body = containerTemplate.el('body');
|
||||
let sort = '';
|
||||
let order = '';
|
||||
|
||||
/**
|
||||
* @callback ValueFormat
|
||||
|
@ -31,8 +31,11 @@ export const renderListFiles = () => {
|
|||
}
|
||||
|
||||
const renderList = async () => {
|
||||
let containerTemplate = getTemplate('files-list');
|
||||
const body = containerTemplate.el('body');
|
||||
|
||||
const currentDirectory = getCurrentDir();
|
||||
const entries = await getEntries(currentDirectory);
|
||||
const entries = await getEntries(currentDirectory, sort, order);
|
||||
|
||||
for (const entry of entries) {
|
||||
const itemTemplate = getTemplate('files-list-item');
|
||||
|
@ -75,6 +78,26 @@ export const renderListFiles = () => {
|
|||
body.appendChild(itemTemplate.render());
|
||||
}
|
||||
|
||||
const sortEls = containerTemplate.els('sort');
|
||||
const handleSort = (sortEl) => {
|
||||
sort = sortEl.dataset.sort;
|
||||
|
||||
sortEls.forEach(sortEl => sortEl.dataset.order = '');
|
||||
|
||||
switch (order) {
|
||||
case '': sortEl.dataset.order = 'asc'; break;
|
||||
case 'asc': sortEl.dataset.order = 'desc'; break;
|
||||
case 'desc': sortEl.dataset.order = ''; break;
|
||||
default: sortEl.dataset.order = ''; break;
|
||||
}
|
||||
|
||||
order = sortEl.dataset.order;
|
||||
|
||||
console.log({sort, order});
|
||||
renderList()
|
||||
};
|
||||
sortEls.forEach(sortEl => sortEl.addEventListener('click', () => handleSort(sortEl)));
|
||||
|
||||
fileEl.innerHTML = '';
|
||||
fileEl.appendChild(containerTemplate.render());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue