mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-09 09:58:20 -05:00
Add automatic coloring of tags
Please see this as proposal on how to implement automatic/random colors for tags while keeping the current set of hard coded colors in place (at least in the frontend). Bear with me as I have even less Angular knowledge than Django and just tried to get away with as few changes as possible. :-) AIUI you want to change to a color picking system anyways in the future, which could also play well with this. fixes #51
This commit is contained in:
parent
72a4ff0fca
commit
26784a5325
1
Pipfile
1
Pipfile
@ -40,6 +40,7 @@ whoosh="~=2.7.4"
|
|||||||
inotifyrecursive = ">=0.3.4"
|
inotifyrecursive = ">=0.3.4"
|
||||||
ocrmypdf = "*"
|
ocrmypdf = "*"
|
||||||
tqdm = "*"
|
tqdm = "*"
|
||||||
|
colorhash = "*"
|
||||||
|
|
||||||
[dev-packages]
|
[dev-packages]
|
||||||
coveralls = "*"
|
coveralls = "*"
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
<span *ngIf="!clickable" class="badge" [style.background]="getColour().value" [style.color]="getColour().textColor">{{tag.name}}</span>
|
<span *ngIf="!clickable" class="badge" [style.background]="getColour().id" [style.color]="getColour().textColor">{{tag.name}}</span>
|
||||||
<a [routerLink]="" [title]="linkTitle" *ngIf="clickable" class="badge" [style.background]="getColour().value" [style.color]="getColour().textColor">{{tag.name}}</a>
|
<a [routerLink]="" [title]="linkTitle" *ngIf="clickable" class="badge" [style.background]="getColour().id" [style.color]="getColour().textColor">{{tag.name}}</a>
|
@ -23,7 +23,11 @@ export class TagComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getColour() {
|
getColour() {
|
||||||
return TAG_COLOURS.find(c => c.id == this.tag.colour)
|
var color = TAG_COLOURS.find(c => c.id == this.tag.colour)
|
||||||
|
if (color) {
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
return { id: this.tag.colour, name: this.tag.colour, textColor: "#ffffff" }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<app-input-text title="Name" formControlName="name"></app-input-text>
|
<app-input-text title="Name" formControlName="name"></app-input-text>
|
||||||
<app-input-select title="Colour" [items]="getColours()" formControlName="colour" [textColor]="getColor(objectForm.value.colour).textColor" [backgroundColor]="getColor(objectForm.value.colour).value"></app-input-select>
|
<app-input-select title="Colour" [items]="getColours()" formControlName="colour" [textColor]="getColor(objectForm.value.colour).textColor" [backgroundColor]="getColor(objectForm.value.colour).id"></app-input-select>
|
||||||
<app-input-check title="Inbox tag" formControlName="is_inbox_tag" hint="Inbox tags are automatically assigned to all consumed documents."></app-input-check>
|
<app-input-check title="Inbox tag" formControlName="is_inbox_tag" hint="Inbox tags are automatically assigned to all consumed documents."></app-input-check>
|
||||||
<app-input-text title="Match" formControlName="match"></app-input-text>
|
<app-input-text title="Match" formControlName="match"></app-input-text>
|
||||||
<app-input-select title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select>
|
<app-input-select title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select>
|
||||||
|
@ -13,14 +13,14 @@ import { ToastService } from 'src/app/services/toast.service';
|
|||||||
})
|
})
|
||||||
export class TagEditDialogComponent extends EditDialogComponent<PaperlessTag> {
|
export class TagEditDialogComponent extends EditDialogComponent<PaperlessTag> {
|
||||||
|
|
||||||
constructor(service: TagService, activeModal: NgbActiveModal, toastService: ToastService) {
|
constructor(service: TagService, activeModal: NgbActiveModal, toastService: ToastService) {
|
||||||
super(service, activeModal, toastService, 'tag')
|
super(service, activeModal, toastService, 'tag')
|
||||||
}
|
}
|
||||||
|
|
||||||
getForm(): FormGroup {
|
getForm(): FormGroup {
|
||||||
return new FormGroup({
|
return new FormGroup({
|
||||||
name: new FormControl(''),
|
name: new FormControl(''),
|
||||||
colour: new FormControl(1),
|
colour: new FormControl(''),
|
||||||
is_inbox_tag: new FormControl(false),
|
is_inbox_tag: new FormControl(false),
|
||||||
matching_algorithm: new FormControl(1),
|
matching_algorithm: new FormControl(1),
|
||||||
match: new FormControl(""),
|
match: new FormControl(""),
|
||||||
@ -32,7 +32,7 @@ export class TagEditDialogComponent extends EditDialogComponent<PaperlessTag> {
|
|||||||
return TAG_COLOURS
|
return TAG_COLOURS
|
||||||
}
|
}
|
||||||
|
|
||||||
getColor(id: number) {
|
getColor(id) {
|
||||||
return TAG_COLOURS.find(c => c.id == id)
|
return TAG_COLOURS.find(c => c.id == id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<tr *ngFor="let tag of data">
|
<tr *ngFor="let tag of data">
|
||||||
<td scope="row">{{ tag.name }}</td>
|
<td scope="row">{{ tag.name }}</td>
|
||||||
<td scope="row"><span class="badge" [style.color]="getColor(tag.colour).textColor"
|
<td scope="row"><span class="badge" [style.color]="getColor(tag.colour).textColor"
|
||||||
[style.background-color]="getColor(tag.colour).value">{{ getColor(tag.colour).name }}</span></td>
|
[style.background-color]="tag.colour">{{ getColor(tag.colour).name }}</span></td>
|
||||||
<td scope="row">{{ getMatching(tag) }}</td>
|
<td scope="row">{{ getMatching(tag) }}</td>
|
||||||
<td scope="row">{{ tag.document_count }}</td>
|
<td scope="row">{{ tag.document_count }}</td>
|
||||||
<td scope="row">
|
<td scope="row">
|
||||||
|
@ -15,10 +15,14 @@ export class TagListComponent extends GenericListComponent<PaperlessTag> {
|
|||||||
|
|
||||||
constructor(tagService: TagService, modalService: NgbModal) {
|
constructor(tagService: TagService, modalService: NgbModal) {
|
||||||
super(tagService, modalService, TagEditDialogComponent)
|
super(tagService, modalService, TagEditDialogComponent)
|
||||||
}
|
}
|
||||||
|
|
||||||
getColor(id) {
|
getColor(id) {
|
||||||
return TAG_COLOURS.find(c => c.id == id)
|
var color = TAG_COLOURS.find(c => c.id == id)
|
||||||
|
if (color) {
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
return { id: id, name: id, textColor: "#ffffff" }
|
||||||
}
|
}
|
||||||
|
|
||||||
getObjectName(object: PaperlessTag) {
|
getObjectName(object: PaperlessTag) {
|
||||||
|
@ -3,26 +3,27 @@ import { ObjectWithId } from './object-with-id';
|
|||||||
|
|
||||||
|
|
||||||
export const TAG_COLOURS = [
|
export const TAG_COLOURS = [
|
||||||
{id: 1, value: "#a6cee3", name: "Light Blue", textColor: "#000000"},
|
{ id: "", name: "Auto", textColor: "#000000" },
|
||||||
{id: 2, value: "#1f78b4", name: "Blue", textColor: "#ffffff"},
|
{ id: "#a6cee3", name: "Light Blue", textColor: "#000000" },
|
||||||
{id: 3, value: "#b2df8a", name: "Light Green", textColor: "#000000"},
|
{ id: "#1f78b4", name: "Blue", textColor: "#ffffff" },
|
||||||
{id: 4, value: "#33a02c", name: "Green", textColor: "#000000"},
|
{ id: "#b2df8a", name: "Light Green", textColor: "#000000" },
|
||||||
{id: 5, value: "#fb9a99", name: "Light Red", textColor: "#000000"},
|
{ id: "#33a02c", name: "Green", textColor: "#000000" },
|
||||||
{id: 6, value: "#e31a1c", name: "Red ", textColor: "#ffffff"},
|
{ id: "#fb9a99", name: "Light Red", textColor: "#000000" },
|
||||||
{id: 7, value: "#fdbf6f", name: "Light Orange", textColor: "#000000"},
|
{ id: "#e31a1c", name: "Red ", textColor: "#ffffff" },
|
||||||
{id: 8, value: "#ff7f00", name: "Orange", textColor: "#000000"},
|
{ id: "#fdbf6f", name: "Light Orange", textColor: "#000000" },
|
||||||
{id: 9, value: "#cab2d6", name: "Light Violet", textColor: "#000000"},
|
{ id: "#ff7f00", name: "Orange", textColor: "#000000" },
|
||||||
{id: 10, value: "#6a3d9a", name: "Violet", textColor: "#ffffff"},
|
{ id: "#cab2d6", name: "Light Violet", textColor: "#000000" },
|
||||||
{id: 11, value: "#b15928", name: "Brown", textColor: "#000000"},
|
{ id: "#6a3d9a", name: "Violet", textColor: "#ffffff" },
|
||||||
{id: 12, value: "#000000", name: "Black", textColor: "#ffffff"},
|
{ id: "#b15928", name: "Brown", textColor: "#000000" },
|
||||||
{id: 13, value: "#cccccc", name: "Light Grey", textColor: "#000000"}
|
{ id: "#000000", name: "Black", textColor: "#ffffff" },
|
||||||
|
{ id: "#cccccc", name: "Light Grey", textColor: "#000000" }
|
||||||
]
|
]
|
||||||
|
|
||||||
export interface PaperlessTag extends MatchingModel {
|
export interface PaperlessTag extends MatchingModel {
|
||||||
|
|
||||||
colour?: number
|
colour?: string
|
||||||
|
|
||||||
is_inbox_tag?: boolean
|
is_inbox_tag?: boolean
|
||||||
|
|
||||||
document_count?: number
|
document_count?: number
|
||||||
}
|
}
|
||||||
|
70
src/documents/migrations/1006_migrate_tag_colour.py
Normal file
70
src/documents/migrations/1006_migrate_tag_colour.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# Generated by Django 3.1.4 on 2020-12-02 21:43
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
COLOURS_OLD = {
|
||||||
|
1: "#a6cee3",
|
||||||
|
2: "#1f78b4",
|
||||||
|
3: "#b2df8a",
|
||||||
|
4: "#33a02c",
|
||||||
|
5: "#fb9a99",
|
||||||
|
6: "#e31a1c",
|
||||||
|
7: "#fdbf6f",
|
||||||
|
8: "#ff7f00",
|
||||||
|
9: "#cab2d6",
|
||||||
|
10: "#6a3d9a",
|
||||||
|
11: "#b15928",
|
||||||
|
12: "#000000",
|
||||||
|
13: "#cccccc",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def forward(apps, schema_editor):
|
||||||
|
Tag = apps.get_model('documents', 'Tag')
|
||||||
|
|
||||||
|
for tag in Tag.objects.all():
|
||||||
|
colour_old_id = tag.colour_old
|
||||||
|
rgb = COLOURS_OLD[colour_old_id]
|
||||||
|
tag.colour = rgb
|
||||||
|
tag.save()
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(apps, schema_editor):
|
||||||
|
Tag = apps.get_model('documents', 'Tag')
|
||||||
|
|
||||||
|
def _get_colour_id(rdb):
|
||||||
|
for idx, rdbx in COLOURS_OLD.items():
|
||||||
|
if rdbx == rdb:
|
||||||
|
return idx
|
||||||
|
# Return colour 1 if we can't match anything
|
||||||
|
return 1
|
||||||
|
|
||||||
|
for tag in Tag.objects.all():
|
||||||
|
colour_id = _get_colour_id(tag.colour)
|
||||||
|
tag.colour_old = colour_id
|
||||||
|
tag.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('documents', '1005_checksums'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='tag',
|
||||||
|
old_name='colour',
|
||||||
|
new_name='colour_old',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='tag',
|
||||||
|
name='colour',
|
||||||
|
field=models.CharField(blank=True, max_length=7),
|
||||||
|
),
|
||||||
|
migrations.RunPython(forward, reverse),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='tag',
|
||||||
|
name='colour_old',
|
||||||
|
)
|
||||||
|
]
|
@ -6,6 +6,7 @@ import re
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
|
from colorhash import ColorHash
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
@ -84,23 +85,7 @@ class Correspondent(MatchingModel):
|
|||||||
|
|
||||||
class Tag(MatchingModel):
|
class Tag(MatchingModel):
|
||||||
|
|
||||||
COLOURS = (
|
colour = models.CharField(blank=True, max_length=7)
|
||||||
(1, "#a6cee3"),
|
|
||||||
(2, "#1f78b4"),
|
|
||||||
(3, "#b2df8a"),
|
|
||||||
(4, "#33a02c"),
|
|
||||||
(5, "#fb9a99"),
|
|
||||||
(6, "#e31a1c"),
|
|
||||||
(7, "#fdbf6f"),
|
|
||||||
(8, "#ff7f00"),
|
|
||||||
(9, "#cab2d6"),
|
|
||||||
(10, "#6a3d9a"),
|
|
||||||
(11, "#b15928"),
|
|
||||||
(12, "#000000"),
|
|
||||||
(13, "#cccccc")
|
|
||||||
)
|
|
||||||
|
|
||||||
colour = models.PositiveIntegerField(choices=COLOURS, default=1)
|
|
||||||
|
|
||||||
is_inbox_tag = models.BooleanField(
|
is_inbox_tag = models.BooleanField(
|
||||||
default=False,
|
default=False,
|
||||||
@ -108,6 +93,15 @@ class Tag(MatchingModel):
|
|||||||
"documents will be tagged with inbox tags."
|
"documents will be tagged with inbox tags."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.colour == "":
|
||||||
|
self.colour = ColorHash(
|
||||||
|
self.name,
|
||||||
|
lightness=(0.35, 0.45, 0.55, 0.65),
|
||||||
|
saturation=(0.2, 0.3, 0.4, 0.5)).hex
|
||||||
|
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class DocumentType(MatchingModel):
|
class DocumentType(MatchingModel):
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user