diff --git a/package.json b/package.json index 9f1aa4e..e45b327 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", "alasql": "^0.5.4", + "console": "^0.7.2", "eslint-plugin-react-hooks": "^2.3.0", "leaflet": "^1.6.0", "lodash": "^4.17.15", diff --git a/src/database.js b/src/database.js index c6e2c74..d0b289a 100644 --- a/src/database.js +++ b/src/database.js @@ -1,13 +1,14 @@ import React, { useEffect, useState } from 'react'; +import NodeEnvironment from 'jest-environment-node'; export async function sqljs_async_queries(sqljs_object, queries) { - var t0 = performance.now(); + //var t0 = performance.now(); for (let i = 0; i < (queries.length - 1); i++) { sqljs_object.exec(queries[i]); } var r = sqljs_object.exec(queries[queries.length - 1]); - console.log("Queries took ", (performance.now() - t0), " ms."); - console.log("Query result for ", queries[queries.length - 1], ": ", r); + //console.log("Queries took ", (performance.now() - t0), " ms."); + //console.log("Query result for ", queries[queries.length - 1], ": ", r); return r; } @@ -40,6 +41,55 @@ export function add_custom_functions(db) { db.create_function("REGEXP", regexp_match); } +// Digikam stores its tree of tags as individual tags, +// linked only by their parent ID. This makes searching +// difficult. Therefore we add a column in the tag table +// which holds the "full tag" (e.g. People/John for the tag John). +export async function add_full_tag_info(db) { + var res = db.exec("SELECT id, pid, name FROM Tags LEFT JOIN TagProperties ON Tags.id=TagProperties.tagid"); + if (!Array.isArray(res) || res.length == 0) { + throw new Error("Couldn't get tags information."); + } + + var cols = res[0].columns; + var all_tags = res[0].values; + var full_tags = []; // id, full name pairs + + const get_tag_by_id = (id) => { + for (let i = 0; i < all_tags.length; i++) { + if (all_tags[i][cols.indexOf("id")] == id) { + return all_tags[i]; + } + } + return null; + }; + + // Solve the full paths for each tag. + all_tags.forEach(row => { + var name = row[cols.indexOf("name")]; + var full = name; + var pid = row[cols.indexOf("pid")]; + var id = row[cols.indexOf("id")]; + var parent = pid == 0 ? null : get_tag_by_id(pid); + while (parent != null) { + full = parent[cols.indexOf("name")] + "/" + full; + pid = parent[cols.indexOf("pid")]; + parent = pid == 0 ? null : get_tag_by_id(pid); + } + var new_entry = { id: id, fullname: full }; + full_tags.push(new_entry); + }); + + // Now put them in the database. + db.exec("ALTER TABLE Tags ADD fullname TEXT;"); + full_tags.forEach(tag => { + var query = 'UPDATE Tags SET fullname="' + tag.fullname + '" WHERE id=' + tag.id + ';'; + db.exec(query); + }); + + var r = db.exec("SELECT * FROM Tags;"); +} + export function ProvideDB(props) { const { children, db_url } = props; const [db, setDb] = useState(null); @@ -48,9 +98,11 @@ export function ProvideDB(props) { useEffect(() => { fetch_sqljs_db_from_sqlite(db_url) .then(db => { - add_custom_functions(db); - setError(false); - setDb(db); + add_full_tag_info(db).then(() => { + add_custom_functions(db); + setError(false); + setDb(db); + }) }) .catch(error => { setError(error); }); }, []) diff --git a/src/main.js b/src/main.js index b8d6c5d..bbb5b57 100644 --- a/src/main.js +++ b/src/main.js @@ -84,7 +84,9 @@ export function LoadedMainPage(props) { setPhotos(false); do_image_query(sql_image_query, database, photos_dir, thumbs_dir) .then(got_photos => { - setPhotos(got_photos); + // TODO: make the limit configurable and show a warning + var trunced = got_photos.slice(0, 300); + setPhotos(trunced); }); } diff --git a/src/queries.js b/src/queries.js index ea685f1..521138e 100644 --- a/src/queries.js +++ b/src/queries.js @@ -64,7 +64,7 @@ export function do_tag_query(query, database) { var cols = res[0].columns; var data = res[0].values; data.forEach(row => { - tags.push(create_tag(row[cols.indexOf("id")], row[cols.indexOf("name")])); + tags.push(create_tag(row[cols.indexOf("id")], row[cols.indexOf("fullname")])); }); } resolve(tags); @@ -248,8 +248,7 @@ export function image_query_with_where(maybe_where) { + "LEFT JOIN ImageTags ON Images.id=ImageTags.imageid " + "LEFT JOIN ImageInformation ON Images.id=ImageInformation.imageid " + "LEFT JOIN Tags ON ImageTags.tagid=Tags.id " + (maybe_where ? maybe_where : "") - + " GROUP BY Images.id LIMIT 300;"; - // TODO make the limit configurable and have a warning + + " GROUP BY Images.id;"; } // This query will return database entries with the fields "id" and "relativePath" for each matching album. @@ -259,7 +258,12 @@ export function album_query_with_where(maybe_where) { // This query will return database entries with the fields "id" and "name" for each matching tag. export function tag_query_with_where(maybe_where) { - return "SELECT Tags.id, Tags.name FROM Tags " + (maybe_where ? maybe_where : "") + ";"; + // Add a clause to the WHERE to hide internal tags. + var exclude_internal = ' (Tags.name="People" OR TagProperties.property IS NULL OR TagProperties.property<>"internalTag")'; + var where = maybe_where ? + maybe_where + ' AND' + exclude_internal : + "WHERE " + exclude_internal; + return "SELECT Tags.id, Tags.name, Tags.fullname FROM Tags LEFT JOIN TagProperties ON Tags.id=TagProperties.tagid " + where + " GROUP BY Tags.fullname;"; } export function maybe_image_query(user_query, database) { @@ -281,7 +285,7 @@ export function maybe_album_query(user_query, database) { export function maybe_tag_query(user_query) { var where = false; if (user_query.tag_filter) { - where = "WHERE (" + user_query.tag_filter.to_sql_where() + " AND Tags.pid = 0 AND NOT Tags.name=\"_Digikam_Internal_Tags_\")"; // TODO this way of doing the pid is hacky + where = "WHERE " + user_query.tag_filter.to_sql_where(); } return tag_query_with_where(where); } diff --git a/yarn.lock b/yarn.lock index d2c26a9..2c5e1d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3110,6 +3110,11 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== +console@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/console/-/console-0.7.2.tgz#f9a4331249291591b7bf9bffa8e205356f20a9f0" + integrity sha1-+aQzEkkpFZG3v5v/qOIFNW8gqfA= + constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"