mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
This reverts commit 3725b14e04
.
This commit is contained in:
parent
727d64b646
commit
25b96937f0
@ -1,6 +1,7 @@
|
|||||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||||
import { _ } from '@joplin/lib/locale';
|
import { _ } from '@joplin/lib/locale';
|
||||||
import Tag from '@joplin/lib/models/Tag';
|
import Tag from '@joplin/lib/models/Tag';
|
||||||
|
import { TagEntity } from '@joplin/lib/services/database/types';
|
||||||
|
|
||||||
export const declaration: CommandDeclaration = {
|
export const declaration: CommandDeclaration = {
|
||||||
name: 'setTags',
|
name: 'setTags',
|
||||||
@ -14,23 +15,16 @@ export const runtime = (comp: any): CommandRuntime => {
|
|||||||
noteIds = noteIds || context.state.selectedNoteIds;
|
noteIds = noteIds || context.state.selectedNoteIds;
|
||||||
|
|
||||||
const tags = await Tag.commonTagsByNoteIds(noteIds);
|
const tags = await Tag.commonTagsByNoteIds(noteIds);
|
||||||
const startTags = tags
|
const sortedTags = Tag.sortTags(tags);
|
||||||
.map((a: any) => {
|
const startTags = sortedTags
|
||||||
|
.map((a: TagEntity) => {
|
||||||
return { value: a.id, label: a.title };
|
return { value: a.id, label: a.title };
|
||||||
})
|
|
||||||
.sort((a: any, b: any) => {
|
|
||||||
// sensitivity accent will treat accented characters as differemt
|
|
||||||
// but treats caps as equal
|
|
||||||
return a.label.localeCompare(b.label, undefined, { sensitivity: 'accent' });
|
|
||||||
});
|
});
|
||||||
const allTags = await Tag.allWithNotes();
|
const allTags = await Tag.allWithNotes();
|
||||||
const tagSuggestions = allTags.map((a: any) => {
|
const sortedAllTags = Tag.sortTags(allTags);
|
||||||
return { value: a.id, label: a.title };
|
const tagSuggestions = sortedAllTags
|
||||||
})
|
.map((a: TagEntity) => {
|
||||||
.sort((a: any, b: any) => {
|
return { value: a.id, label: a.title };
|
||||||
// sensitivity accent will treat accented characters as differemt
|
|
||||||
// but treats caps as equal
|
|
||||||
return a.label.localeCompare(b.label, undefined, { sensitivity: 'accent' });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
comp.setState({
|
comp.setState({
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { AppState } from '../app.reducer';
|
import { AppState } from '../app.reducer';
|
||||||
|
import Tag from '@joplin/lib/models/Tag';
|
||||||
|
|
||||||
const { connect } = require('react-redux');
|
const { connect } = require('react-redux');
|
||||||
const { themeStyle } = require('@joplin/lib/theme');
|
const { themeStyle } = require('@joplin/lib/theme');
|
||||||
@ -28,11 +29,7 @@ function TagList(props: Props) {
|
|||||||
}, [props.style, props.themeId]);
|
}, [props.style, props.themeId]);
|
||||||
|
|
||||||
const tags = useMemo(() => {
|
const tags = useMemo(() => {
|
||||||
const output = props.items.slice();
|
const output = Tag.sortTags(props.items.slice());
|
||||||
|
|
||||||
output.sort((a: any, b: any) => {
|
|
||||||
return a.title < b.title ? -1 : +1;
|
|
||||||
});
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}, [props.items]);
|
}, [props.items]);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const Folder = require('../../models/Folder').default;
|
const Folder = require('../../models/Folder').default;
|
||||||
const Setting = require('../../models/Setting').default;
|
const Setting = require('../../models/Setting').default;
|
||||||
const BaseModel = require('../../BaseModel').default;
|
const BaseModel = require('../../BaseModel').default;
|
||||||
|
const Tag = require('../../models/Tag').default;
|
||||||
|
|
||||||
const shared = {};
|
const shared = {};
|
||||||
|
|
||||||
@ -50,20 +51,7 @@ shared.renderFolders = function(props, renderItem) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
shared.renderTags = function(props, renderItem) {
|
shared.renderTags = function(props, renderItem) {
|
||||||
const tags = props.tags.slice();
|
const tags = Tag.sortTags(props.tags.slice());
|
||||||
tags.sort((a, b) => {
|
|
||||||
// It seems title can sometimes be undefined (perhaps when syncing
|
|
||||||
// and before tag has been decrypted?). It would be best to find
|
|
||||||
// the root cause but for now that will do.
|
|
||||||
//
|
|
||||||
// Fixes https://github.com/laurent22/joplin/issues/4051
|
|
||||||
if (!a || !a.title || !b || !b.title) return 0;
|
|
||||||
|
|
||||||
// Note: while newly created tags are normalized and lowercase
|
|
||||||
// imported tags might be any case, so we need to do case-insensitive
|
|
||||||
// sort.
|
|
||||||
return a.title.toLowerCase() < b.title.toLowerCase() ? -1 : +1;
|
|
||||||
});
|
|
||||||
const tagItems = [];
|
const tagItems = [];
|
||||||
const order = [];
|
const order = [];
|
||||||
for (let i = 0; i < tags.length; i++) {
|
for (let i = 0; i < tags.length; i++) {
|
||||||
|
@ -50,7 +50,7 @@ describe('models/Tag', function() {
|
|||||||
it('should return tags with note counts', (async () => {
|
it('should return tags with note counts', (async () => {
|
||||||
const folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
const note2 = await Note.save({ title: 'ma 2nd note', parent_id: folder1.id });
|
const note2 = await Note.save({ title: 'ma 2nd note',parent_id: folder1.id });
|
||||||
const todo1 = await Note.save({ title: 'todo 1', parent_id: folder1.id, is_todo: 1, todo_completed: 1590085027710 });
|
const todo1 = await Note.save({ title: 'todo 1', parent_id: folder1.id, is_todo: 1, todo_completed: 1590085027710 });
|
||||||
await Tag.setNoteTagsByTitles(note1.id, ['un']);
|
await Tag.setNoteTagsByTitles(note1.id, ['un']);
|
||||||
await Tag.setNoteTagsByTitles(note2.id, ['un']);
|
await Tag.setNoteTagsByTitles(note2.id, ['un']);
|
||||||
@ -156,4 +156,24 @@ describe('models/Tag', function() {
|
|||||||
expect(commonTagIds.includes(tagc.id)).toBe(true);
|
expect(commonTagIds.includes(tagc.id)).toBe(true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should sort tags', (async () => {
|
||||||
|
// test for tags with titles
|
||||||
|
const unsortedTags = [{ title: '@⏲15 min' },{ title: '#house' },{ title: '#coding' }, { title: '@⏲60 min' }, { title: '#wait' }, { title: '@⏲30 min' }];
|
||||||
|
const sortedTags = Tag.sortTags(unsortedTags);
|
||||||
|
expect(sortedTags).toEqual([{ title: '@⏲15 min' }, { title: '@⏲30 min' }, { title: '@⏲60 min' }, { title: '#coding' }, { title: '#house' }, { title: '#wait' }]);
|
||||||
|
|
||||||
|
// test for tags without titles
|
||||||
|
const unsortedTags2 = [{ id: '40' } , { id: '50' }, { id: '10' }, { id: '30' }, { id: '20' }];
|
||||||
|
const sortedTags2 = Tag.sortTags(unsortedTags2);
|
||||||
|
expect(sortedTags2).toEqual([{ id: '40' } , { id: '50' }, { id: '10' }, { id: '30' }, { id: '20' }]);
|
||||||
|
|
||||||
|
// test for tags with titles, without titles and empty tags
|
||||||
|
const unsortedTags3 = [{ id: '1' }, { id: '2', title: 'two' }, {}, { id: '3' }, { id: '4', title: 'four' }, { id: '5',title: 'five' }];
|
||||||
|
const sortedTags3 = Tag.sortTags(unsortedTags3);
|
||||||
|
expect(sortedTags3).toEqual([{ id: '1' }, { id: '2', title: 'two' }, {}, { id: '3' }, { id: '5', title: 'five' }, { id: '4', title: 'four' }]);
|
||||||
|
|
||||||
|
// test for empty list
|
||||||
|
const emptyListSort = Tag.sortTags([]);
|
||||||
|
expect(emptyListSort).toEqual([]);
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@ -216,4 +216,18 @@ export default class Tag extends BaseItem {
|
|||||||
return tag;
|
return tag;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static sortTags(tags: TagEntity[]) {
|
||||||
|
return tags.sort((a: TagEntity,b: TagEntity) => {
|
||||||
|
// It seems title can sometimes be undefined (perhaps when syncing and before tag has been decrypted?). It would be best to find the root cause but for now that will do.
|
||||||
|
// Fixes https://github.com/laurent22/joplin/issues/4051
|
||||||
|
if (!a || !a.title || !b || !b.title) return 0;
|
||||||
|
|
||||||
|
// Note: while newly created tags are normalized and lowercase
|
||||||
|
// imported tags might be any case, so we need to do case-insensitive
|
||||||
|
// sort.
|
||||||
|
return a.title.localeCompare(b.title, undefined, { sensitivity: 'accent' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user