diff --git a/README.md b/README.md index 7866db1..9d753c6 100644 --- a/README.md +++ b/README.md @@ -50,20 +50,29 @@ If you have any questions and commissions for me, feel free to tell me. # Update History -- v1.0.0b (February 17, 2020) +- v1.1.0 (May 4, 2025) - 1. Initial release as a sample. + 1. Major UI/UX enhancement: + - Responsive design for better mobile experience + - Modern UI with Google Material Design inspired styling + - Improved accessibility with ARIA labels and semantic HTML + - Better error handling and loading states + - Updated dependencies to latest versions -- v1.0.0 (March 12, 2020) +- v1.0.2 (February 1, 2022) - 1. An application for searching GAS libraries from the database was completed. By this, [the script is published](https://github.com/tanaikech/Google-Apps-Script-Library-Database/blob/master/searchApp.html). + 1. I noticed that the sheet ID of sheet of Andrew Roberts had been changed. So I used the sheet name of "Libraries" instead of the sheet ID. - v1.0.1 (May 26, 2020) 1. Added the duplicate checker. -- v1.0.2 (February 1, 2022) +- v1.0.0 (March 12, 2020) + + 1. An application for searching GAS libraries from the database was completed. By this, [the script is published](https://github.com/tanaikech/Google-Apps-Script-Library-Database/blob/master/searchApp.html). - 1. I noticed that the sheet ID of sheet of Andrew Roberts had been changed. So I used the sheet name of "Libraries" instead of the sheet ID. +- v1.0.0b (February 17, 2020) + + 1. Initial release as a sample. [TOP](#top) diff --git a/Update.md b/Update.md new file mode 100644 index 0000000..c3b237e --- /dev/null +++ b/Update.md @@ -0,0 +1,38 @@ +# Update Log + +## 2025-05-04: v1.1.0 - Major UI/UX Enhancement + +### Added + +- Responsive design for better mobile experience +- Modern UI with Google Material Design inspired styling +- Loading spinner for better feedback during searches +- Error handling with user-friendly error messages +- Accessibility improvements (ARIA labels, semantic HTML) +- Meta tags for better SEO and device compatibility + +### Changed + +- Updated PapaParse library to version 5.3.2 +- Improved form layout with flexbox +- Enhanced search input field styling +- Better checkbox group organization +- Modernized button styling with hover effects +- Async/await implementation for better error handling +- Added proper HTML document language attribute + +### Technical Improvements + +- CSS custom properties (variables) for consistent theming +- Mobile-first responsive design +- Improved error handling for API calls +- Better loading state management +- Enhanced accessibility for screen readers +- Proper semantic HTML structure +- Optimized CSS with modern best practices + +### Previous Updates + +- 2022-02-01: v1.0.2 - Updated sheet name reference +- 2020-05-26: v1.0.1 - Added duplicate checker +- 2020-03-12: v1.0.0 - Initial release diff --git a/searchApp.html b/searchApp.html index e9e594d..62ac7dd 100644 --- a/searchApp.html +++ b/searchApp.html @@ -1,6 +1,6 @@ - + + + + Search Google Apps Script Libraries - + -
-

Search Google Apps Script Libraries v1.0.0

-

Author: Tanaike

-

Input text for searching :

-

Searching the specific properties with the inputted text : Library name Description Authors Tags All

+ +

Search Google Apps Script Libraries

+

Author: Tanaike

+ +
+ + +
+ +
+ + + + + +

- In the current stage, the library data is retrieved from 2 databases by Tanaike and Andrew Roberts.

- When you push "search" button without the search text, all libraries are shown.

- When you can add new GAS libraries to this database, please add them using this Google Form by Andrew Roberts.

@@ -43,15 +207,38 @@ const databaseUrls1 = "https://raw.githubusercontent.com/tanaikech/Google-Apps-Script-Library-Database/master/Google-Apps-Script-Library-Database.json"; const databaseUrls2 = "https://docs.google.com/spreadsheets/d/1Lk6OClOPA8p94fspQrs8-M-W080tb244U-fWGqvnApk/gviz/tq?tqx=out:csv&sheet=Libraries"; + async function fetchData() { + try { + showLoading(true); + const response = await fetch(databaseUrls1); + if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); + const data = await response.json(); + return data; + } catch (error) { + showError('Failed to fetch library database. Please try again later.'); + console.error('Error fetching database:', error); + throw error; + } + } + + function showLoading(show) { + const spinner = document.getElementById('loading-spinner'); + const buttonText = document.getElementById('search-button-text'); + spinner.style.display = show ? 'inline-block' : 'none'; + buttonText.textContent = show ? 'Loading...' : 'Search'; + } + + function showError(message) { + const errorDiv = document.createElement('div'); + errorDiv.className = 'error-message'; + errorDiv.setAttribute('role', 'alert'); + errorDiv.textContent = message; + document.getElementById('result').prepend(errorDiv); + setTimeout(() => errorDiv.remove(), 5000); + } + Promise.resolve() - .then(() => { - return new Promise((resolve, reject) => { - fetch(databaseUrls1) - .then(res => res.json()) - .then(obj => resolve(obj)) - .catch(err => reject(err)); - }); - }) + .then(() => fetchData()) .then(object => { return new Promise((resolve, reject) => { fetch(databaseUrls2) @@ -141,32 +328,46 @@ } }) - function search(e) { - const searchProps = [...e.props].reduce((ar, e) => { - if (e.checked) ar.push(e.value); - return ar; - }, []); - const searchTexts = e.searchtext.value.split(/,| /g).reduce((ar, e) => { - if (e) ar.push(e.trim()); - return ar; - }, []); - const res = searchLibraries({searchValues: searchTexts, searchProperties: searchProps}); - res.sort((a, b) => a.libraryName.toLowerCase() < b.libraryName.toLowerCase() ? -1 : 1); - const values = res.map(({libraryName, authors, publishedDate, siteUrl, projectKey, description}) => - [libraryName, authors.join(","), (publishedDate ? new Date(publishedDate * 1000) : null), (siteUrl ? 'link' : ""), projectKey, description] - ); - google.charts.setOnLoadCallback(() => { - var data = new google.visualization.DataTable(); - data.addColumn('string', 'Library name'); - data.addColumn('string', 'Author'); - data.addColumn('date', 'Published date'); - data.addColumn('string', 'Url'); - data.addColumn('string', 'Project key'); - data.addColumn('string', 'Description'); - data.addRows(values); - var table = new google.visualization.Table(document.getElementById('result')); - table.draw(data, {allowHtml: true, showRowNumber: true, width: '100%'}); - }); + async function search(e) { + try { + showLoading(true); + document.getElementById('result').innerHTML = ''; + + const searchProps = [...e.props].reduce((ar, e) => { + if (e.checked) ar.push(e.value); + return ar; + }, []); + + const searchTexts = e.searchtext.value.split(/,| /g).reduce((ar, e) => { + if (e) ar.push(e.trim()); + return ar; + }, []); + + const res = searchLibraries({searchValues: searchTexts, searchProperties: searchProps}); + res.sort((a, b) => a.libraryName.toLowerCase() < b.libraryName.toLowerCase() ? -1 : 1); + + const values = res.map(({libraryName, authors, publishedDate, siteUrl, projectKey, description}) => + [libraryName, authors.join(","), (publishedDate ? new Date(publishedDate * 1000) : null), (siteUrl ? 'link' : ""), projectKey, description] + ); + + google.charts.setOnLoadCallback(() => { + var data = new google.visualization.DataTable(); + data.addColumn('string', 'Library name'); + data.addColumn('string', 'Author'); + data.addColumn('date', 'Published date'); + data.addColumn('string', 'Url'); + data.addColumn('string', 'Project key'); + data.addColumn('string', 'Description'); + data.addRows(values); + var table = new google.visualization.Table(document.getElementById('result')); + table.draw(data, {allowHtml: true, showRowNumber: true, width: '100%'}); + }); + } catch (error) { + showError('An error occurred while searching. Please try again.'); + console.error('Search error:', error); + } finally { + showLoading(false); + } } function searchLibraries(searchObj) {