- >
} else if (channels === undefined) {
return <>
{header}
@@ -590,6 +573,7 @@ export function ChannelsPages() {
const re = new RegExp(_.escapeRegExp(searchStr), 'i');
filteredChannels = channels.filter(i => re.test(i['name']));
}
+ console.log(`filteredChannels=${filteredChannels === null}`);
return <>
{header}
diff --git a/app/src/components/SortableTable.js b/app/src/components/SortableTable.js
index b7c29dbe..4757035d 100644
--- a/app/src/components/SortableTable.js
+++ b/app/src/components/SortableTable.js
@@ -1,7 +1,8 @@
import React from "react";
import _ from "lodash";
-import {TableBody, TableHeader, TableHeaderCell, TableRow} from "semantic-ui-react";
+import {TableBody, TableCell, TableHeader, TableHeaderCell, TableRow} from "semantic-ui-react";
import {Table} from "./Theme";
+import {TextPlaceholder} from "./Placeholder";
export class SortableTable extends React.Component {
constructor(props) {
@@ -41,7 +42,7 @@ export class SortableTable extends React.Component {
let {direction} = this.state;
rowKey = rowKey || 'key';
- const data = this.sortData(this.props['data']);
+ const data = this.props['data'] ? this.sortData(this.props['data']) : null;
const tableHeader = (spec) => {
const {key, text, sortBy, width} = spec;
@@ -59,7 +60,11 @@ export class SortableTable extends React.Component {
}
}
- const rows = data.map(i => {rowFunc(i, this.sortData)});
+ // Use placeholder while data is null.
+ let rows = ;
+ if (data !== null) {
+ rows = data.map(i => {rowFunc(i, this.sortData)});
+ }
return
diff --git a/wrolpi/tags.py b/wrolpi/tags.py
index 5cecb5f1..f3c8e643 100644
--- a/wrolpi/tags.py
+++ b/wrolpi/tags.py
@@ -97,7 +97,7 @@ class Tag(ModelHelper, Base):
def has_relations(self) -> bool:
"""Returns True if this Tag has been used with any FileGroups or Zim Entries."""
- return not self.tag_files and not self.tag_zim_entries
+ return bool(self.tag_files or self.tag_zim_entries)
class TagsConfig(ConfigFile):
@@ -308,6 +308,7 @@ def import_tags_config(session: Session = None):
# Maintainer added a Tag to the config manually, or DB was wiped.
tag = Tag(name=name, color=attrs['color'])
new_tags.append(tag)
+ logger.info(f'Creating new {tag}')
tag.color = attrs['color']
if new_tags:
@@ -391,6 +392,7 @@ def import_tags_config(session: Session = None):
elif not tag:
logger.warning(f'Cannot find Tag for {repr(str(zim_path))}')
+ # Delete missing Tags last in case they are used above.
if config.tags:
config_tag_names = set(config.tags.keys())
for tag in session.query(Tag):
diff --git a/wrolpi/test/test_tags.py b/wrolpi/test/test_tags.py
index 9c34b344..1374e34e 100644
--- a/wrolpi/test/test_tags.py
+++ b/wrolpi/test/test_tags.py
@@ -141,7 +141,8 @@ def test_tags_crud(test_session, test_client, example_pdf, assert_tags_config):
request, response = test_client.post('/api/tag/1', content=json.dumps(content))
assert response.status_code == HTTPStatus.OK
request, response = test_client.get('/api/tag')
- assert response.json['tags'] == [dict(name='ガーデン', color='#000000', id=1, file_group_count=1, zim_entry_count=0)]
+ assert response.json['tags'] == [
+ dict(name='ガーデン', color='#000000', id=1, file_group_count=1, zim_entry_count=0)]
assert_tags_config(tags={'ガーデン': {'color': '#000000'}})
# Conflicting names return an error.
@@ -250,24 +251,29 @@ async def test_import_tags_delete_missing(test_session, test_directory, test_tag
assert tag3.name in test_tags_config.read_text()
assert tag4.name in test_tags_config.read_text()
- # Delete tag1 and tag2 from the config.
+ # Delete all tags but tag3.
config = tags.get_tags_config()
config_dict = config.dict()
- config_dict['tags'] = {k: v for k, v in config.tags.items() if k not in [tag1.name, tag2.name, tag4.name]}
+ config_dict['tags'] = {k: v for k, v in config.tags.items() if k == tag3.name}
config.update(config_dict)
+ config.initialize()
+ # Tag Files and Tag Zims are untouched. Only tag3 is left.
+ assert len(config.tag_files) == 1
+ assert len(config.tag_zims) == 1
+ assert len(config.tags) == 1
# Import the config. Only unused Tags not in the config are deleted.
tags.import_tags_config()
- assert {
- tag1.name, # tag1 is used by FileGroup.
- # tag2.name, tag2 is unused, and deleted.
- tag3.name, # tag3 was not deleted.
- tag4.name, # tag4 is used by ZimEntry.
- } == {i.name for i in test_session.query(tags.Tag)}
+ assert {i.name for i in test_session.query(tags.Tag)} == {
+ tag1.name, # tag1 is used by FileGroup.
+ # tag2.name, tag2 is unused, and deleted.
+ tag3.name, # tag3 was not deleted.
+ tag4.name, # tag4 is used by ZimEntry.
+ }
# DB is written to config with only those Tags left.
tags.schedule_save()
- assert f'{tag1.name}:' in test_tags_config.read_text()
- assert f'{tag2.name}:' not in test_tags_config.read_text()
- assert f'{tag3.name}:' in test_tags_config.read_text()
- assert f'{tag4.name}:' in test_tags_config.read_text()
+ # Tags that are used are restored.
+ assert len(config.tag_files) == 1
+ assert len(config.tag_zims) == 1
+ assert len(config.tags) == 3