working on color customization
This commit is contained in:
@@ -99,6 +99,10 @@ public class Project implements Mappable {
|
||||
case NAME: name = json.getString(key); break;
|
||||
case SHOW_CLOSED: showClosed = json.getBoolean(SHOW_CLOSED); break;
|
||||
case STATUS: status = json.getInt(key); break;
|
||||
case TAG_COLORS:
|
||||
tagColors.clear();
|
||||
json.getJSONObject(TAG_COLORS).toMap().forEach((k,v) -> tagColors.put(k,v.toString()));
|
||||
break;
|
||||
default: key = null;
|
||||
}
|
||||
if (key != null) dirtyFields.add(key);
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
{#if stateList[state]}
|
||||
{#each Object.values(stateList[state]).sort((a,b) => a.name.localeCompare(b.name)) as task}
|
||||
{#if !filter || task.name.toLowerCase().includes(filter) || (task.tags && task.tags.filter(tag => tag.toLowerCase().includes(filter)).length)}
|
||||
<Card onclick={e => openTask(task.id)} ondragstart={ev => dragged=task} {task} />
|
||||
<Card onclick={e => openTask(task.id)} ondragstart={ev => dragged=task} {task} tag_colors={project.tag_colors} />
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
@@ -1,8 +1,22 @@
|
||||
<script>
|
||||
let { onclick, ondragstart, task } = $props();
|
||||
let { onclick, ondragstart, tag_colors = {}, task } = $props();
|
||||
|
||||
function calcStyle(){
|
||||
if (!task.tags || !tag_colors) return '';
|
||||
for (let tag of task.tags){
|
||||
let color = tag_colors[tag.toLowerCase()];
|
||||
if (color) return `background: ${color}`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
let style = $derived.by(calcStyle)
|
||||
|
||||
</script>
|
||||
|
||||
<div draggable="true" class={`box prio_${task.total_prio} p${Math.floor(task.total_prio/10)*10} p${task.total_prio % 10}`} {onclick} {ondragstart} >
|
||||
<div
|
||||
draggable="true"
|
||||
class={`box prio_${task.total_prio} p${Math.floor(task.total_prio/10)*10} p${task.total_prio % 10}`}
|
||||
{onclick} {ondragstart} style={style}>
|
||||
<span class="title">{task.name}</span>
|
||||
{#if task.estimated_time}
|
||||
<span class="estimate">
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
let showSettings = $state(false);
|
||||
let tasks = $state(null);
|
||||
let show_closed = $state(false);
|
||||
let new_color = $state({tag:null,color:'#00aa00'})
|
||||
|
||||
let new_state = $state({code:null,name:null})
|
||||
let state_available=$derived(new_state.name && new_state.code && !project.allowed_states[new_state.code]);
|
||||
@@ -55,6 +56,11 @@
|
||||
loadTasks();
|
||||
}
|
||||
|
||||
async function dropColor(tag){
|
||||
delete project.tag_colors[tag];
|
||||
update({tag_colors:project.tag_colors});
|
||||
}
|
||||
|
||||
async function dropMember(member){
|
||||
update({drop_member:member.user.id});
|
||||
}
|
||||
@@ -112,6 +118,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
function saveTagColor(){
|
||||
project.tag_colors[new_color.tag] = new_color.color;
|
||||
update({tag_colors:project.tag_colors});
|
||||
}
|
||||
|
||||
function toggleSettings(){
|
||||
showSettings = !showSettings;
|
||||
}
|
||||
|
||||
async function update(data){
|
||||
const url = api(`project/${id}`);
|
||||
const resp = await fetch(url,{
|
||||
@@ -129,11 +144,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSettings(){
|
||||
showSettings = !showSettings;
|
||||
}
|
||||
|
||||
|
||||
function updatePermission(user_id,permission){
|
||||
let members = {};
|
||||
members[user_id] = permission.code;
|
||||
@@ -188,8 +198,8 @@
|
||||
<input type="checkbox" bind:checked={project.show_closed} onchange={changeClosed} />
|
||||
{t('display_closed_tasks')}
|
||||
</label>
|
||||
<div>{t('members')}</div>
|
||||
<div>
|
||||
<div class="em">{t('members')}</div>
|
||||
<div class="em">
|
||||
<PermissionEditor members={project.members} {updatePermission} {addMember} {dropMember} {getCandidates} />
|
||||
</div>
|
||||
{#if project.allowed_states}
|
||||
@@ -212,7 +222,25 @@
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
<div class="em">
|
||||
{t('custom_tag_colors')}
|
||||
<input type="color" bind:value={new_color.color} >
|
||||
</div>
|
||||
<div class="em">
|
||||
<label>
|
||||
{t('tag_name')}:
|
||||
<input type="text" bind:value={new_color.tag} />
|
||||
</label>
|
||||
<button onclick={saveTagColor}>{t('add_object',{object:t('color')})}</button>
|
||||
</div>
|
||||
{#each Object.entries(project.tag_colors) as [k,v]}
|
||||
<div style="background: {v}">{k}</div>
|
||||
<div class="em">
|
||||
<button onclick={e => dropColor(k)}>{t('delete')}</button>
|
||||
</div>
|
||||
{/each}
|
||||
{/if} <!-- settings -->
|
||||
|
||||
{#if estimated_time.sum}
|
||||
<div>{t('estimated_time')}</div>
|
||||
<div class="estimated_time">{estimated_time.sum} h</div>
|
||||
|
||||
@@ -148,7 +148,7 @@ CREATE TABLE IF NOT EXISTS {0} (
|
||||
rs = select(VALUE).from(TABLE_SETTINGS).where(KEY,equal(colorKey(projectId))).exec(db);
|
||||
if (rs.next()) {
|
||||
var map = project.tagColors();
|
||||
new JSONObject(rs.getString(VALUE)).toMap().forEach((k, v) -> map.put(k, v.toString()));
|
||||
new JSONObject(rs.getString(VALUE)).toMap().forEach((k, v) -> map.put(k.toLowerCase(), v.toString()));
|
||||
}
|
||||
rs.close();
|
||||
return project;
|
||||
@@ -246,6 +246,10 @@ CREATE TABLE IF NOT EXISTS {0} (
|
||||
query.execute(db).close();
|
||||
prj.clean(MEMBERS);
|
||||
}
|
||||
if (prj.isDirty(TAG_COLORS)){
|
||||
replaceInto(TABLE_SETTINGS,KEY,VALUE).values(colorKey(prj.id()),new JSONObject(prj.tagColors()).toString()).execute(db).close();
|
||||
prj.clean(TAG_COLORS);
|
||||
}
|
||||
if (prj.isDirty()){
|
||||
update(TABLE_PROJECTS).set(NAME,DESCRIPTION,STATUS,COMPANY_ID,SHOW_CLOSED).where(ID,equal(prj.id())).prepare(db)
|
||||
.apply(prj.name(),prj.description(),prj.status(),prj.companyId(),prj.showClosed())
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"client_secret": "Client-Geheimnis",
|
||||
"close_settings": "Einstellungen schließen",
|
||||
"code": "Code",
|
||||
"color": "Farbe",
|
||||
"connect_service": "mit Service verbinden",
|
||||
"connected_services": "verbundene Login-Services",
|
||||
"confirm_delete": "Soll '{element}' wirklich gelöscht werden?",
|
||||
@@ -40,10 +41,11 @@
|
||||
"CREATE_USERS": "Nutzer anlegen",
|
||||
"create_pdf": "PDF erzeugen",
|
||||
"created_with": "erzeugt mit {tool} von {producer}",
|
||||
"customer": "Kunde",
|
||||
"customer_address": "Adresse",
|
||||
"customer_email": "Emailadresse des Kunden",
|
||||
"customer": "Kunde",
|
||||
"customer_id": "Kundennummer",
|
||||
"custom_tag_colors": "Nutzerdefinierte Tag-Farben",
|
||||
|
||||
"data_sent": "Daten übermittelt",
|
||||
"date": "Datum",
|
||||
@@ -237,6 +239,7 @@
|
||||
"succeeding_document": "Nachfolge-Dokument",
|
||||
"sum_of_records": "Summe der ausgewählten Einträge",
|
||||
|
||||
"tag_name": "Tag-Name",
|
||||
"tag_uses": "Verwendung des Tags „{tag}“",
|
||||
"tags": "Tags",
|
||||
"task": "Aufgabe",
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"client_secret": "client secret",
|
||||
"close_settings": "close settings",
|
||||
"code": "code",
|
||||
"color": "color",
|
||||
"connect_service": "connect with service",
|
||||
"connected_services": "connected login services",
|
||||
"confirm_delete": "Really delete '{element}'?",
|
||||
@@ -40,10 +41,11 @@
|
||||
"CREATE_USERS": "create users",
|
||||
"create_pdf": "create PDF",
|
||||
"created_with": "created with {tool} by {producer}",
|
||||
"customer": "customer",
|
||||
"customer_address": "address",
|
||||
"customer_email": "customer email address",
|
||||
"customer": "customer",
|
||||
"customer_id": "customer ID",
|
||||
"custom_tag_colors": "custom tag colors",
|
||||
|
||||
"data_sent": "data sent",
|
||||
"date": "date",
|
||||
@@ -237,6 +239,7 @@
|
||||
"succeeding_document": "succeeding document",
|
||||
"sum_of_records": "sum of records",
|
||||
|
||||
"tag_name": "tag name",
|
||||
"tag_uses": "usage of tag „{tag}“",
|
||||
"tags": "tags",
|
||||
"task": "task",
|
||||
|
||||
@@ -148,7 +148,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p10,
|
||||
.kanban .state_40 .box.p10{
|
||||
background-color: #ffa736;
|
||||
border: 5px solid #ffa736;
|
||||
}
|
||||
|
||||
.task.p20 .name{
|
||||
@@ -156,7 +156,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p20,
|
||||
.kanban .state_40 .box.p20{
|
||||
background-color: #ff8f00;
|
||||
border: 5px solid #ff8f00;
|
||||
}
|
||||
|
||||
.task.p30 .name{
|
||||
@@ -164,7 +164,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p30,
|
||||
.kanban .state_40 .box.p30{
|
||||
background-color: #ff7b06;
|
||||
border: 5px solid #ff7b06;
|
||||
}
|
||||
|
||||
.task.p40 .name{
|
||||
@@ -172,7 +172,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p40,
|
||||
.kanban .state_40 .box.p40{
|
||||
background-color: #ff6306;
|
||||
border: 5px solid #ff6306;
|
||||
}
|
||||
|
||||
.task.p50 .name{
|
||||
@@ -180,7 +180,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p50,
|
||||
.kanban .state_40 .box.p50{
|
||||
background-color: #ff4c06;
|
||||
border: 5px solid #ff4c06;
|
||||
}
|
||||
|
||||
.task.p60 .name{
|
||||
@@ -188,7 +188,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p60,
|
||||
.kanban .state_40 .box.p60{
|
||||
background-color: #ff3506;
|
||||
border: 5px solid #ff3506;
|
||||
}
|
||||
|
||||
.task.p70 .name{
|
||||
@@ -196,7 +196,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p70,
|
||||
.kanban .state_40 .box.p70{
|
||||
background-color: #ff0000;
|
||||
border: 5px solid #ff0000;
|
||||
}
|
||||
|
||||
.task.p80 .name{
|
||||
@@ -204,19 +204,23 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p80,
|
||||
.kanban .state_40 .box.p80{
|
||||
background-color: #df153b;
|
||||
border: 5px solid #df153b;
|
||||
}
|
||||
|
||||
.task.p90 .name,
|
||||
.kanban .state_20 .box.p90,
|
||||
.kanban .state_40 .box.p90{
|
||||
.task.p90 .name{
|
||||
background-color: #991c34;
|
||||
color: #ffff00;
|
||||
}
|
||||
.kanban .state_20 .box.p90,
|
||||
.kanban .state_40 .box.p90{
|
||||
border: 5px solid #991c34;
|
||||
}
|
||||
|
||||
.task.p100 .name,
|
||||
.kanban .state_20 .box.p100,
|
||||
.kanban .state_40 .box.p100{
|
||||
.task.p100 .name{
|
||||
background-color: #733440;
|
||||
color: #ffff00;
|
||||
}
|
||||
.kanban .state_20 .box.p100,
|
||||
.kanban .state_40 .box.p100{
|
||||
border: 5px solid #733440;
|
||||
}
|
||||
@@ -45,6 +45,10 @@ textarea{
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.em {
|
||||
background: rgba(255, 215, 0, 0.09);
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: red;
|
||||
color: black;
|
||||
@@ -150,7 +154,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p10,
|
||||
.kanban .state_40 .box.p10{
|
||||
background-color: #fff066;
|
||||
border: 5px solid #fff066;
|
||||
}
|
||||
|
||||
.task.p20 .name{
|
||||
@@ -158,7 +162,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p20,
|
||||
.kanban .state_40 .box.p20{
|
||||
background-color: #ffe706;
|
||||
border: 5px solid #ffe706;
|
||||
}
|
||||
|
||||
.task.p30 .name{
|
||||
@@ -166,7 +170,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p30,
|
||||
.kanban .state_40 .box.p30{
|
||||
background-color: #ffa906;
|
||||
border: 5px solid #ffa906;
|
||||
}
|
||||
|
||||
.task.p40 .name{
|
||||
@@ -174,7 +178,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p40,
|
||||
.kanban .state_40 .box.p40{
|
||||
background-color: #ff8606;
|
||||
border: 5px solid #ff8606;
|
||||
}
|
||||
|
||||
.task.p50 .name{
|
||||
@@ -182,7 +186,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p50,
|
||||
.kanban .state_40 .box.p50{
|
||||
background-color: #ff4c06;
|
||||
border: 5px solid #ff4c06;
|
||||
}
|
||||
|
||||
.task.p60 .name{
|
||||
@@ -190,7 +194,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p60,
|
||||
.kanban .state_40 .box.p60{
|
||||
background-color: #ff3506;
|
||||
border: 5px solid #ff3506;
|
||||
}
|
||||
|
||||
.task.p70 .name{
|
||||
@@ -198,7 +202,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p70,
|
||||
.kanban .state_40 .box.p70{
|
||||
background-color: #ff0000;
|
||||
border: 5px solid #ff0000;
|
||||
}
|
||||
|
||||
.task.p80 .name{
|
||||
@@ -206,19 +210,23 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p80,
|
||||
.kanban .state_40 .box.p80{
|
||||
background-color: #df153b;
|
||||
border: 5px solid #df153b;
|
||||
}
|
||||
|
||||
.task.p90 .name,
|
||||
.kanban .state_20 .box.p90,
|
||||
.kanban .state_40 .box.p90{
|
||||
.task.p90 .name{
|
||||
background-color: #991c34;
|
||||
color: #ffff00;
|
||||
}
|
||||
.kanban .state_20 .box.p90,
|
||||
.kanban .state_40 .box.p90{
|
||||
border: 5px solid #991c34;
|
||||
}
|
||||
|
||||
.task.p100 .name,
|
||||
.kanban .state_20 .box.p100,
|
||||
.kanban .state_40 .box.p100{
|
||||
.task.p100 .name{
|
||||
background-color: #733440;
|
||||
color: #ffff00;
|
||||
}
|
||||
.kanban .state_20 .box.p100,
|
||||
.kanban .state_40 .box.p100{
|
||||
border: 5px solid #733440;
|
||||
}
|
||||
@@ -142,7 +142,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p10,
|
||||
.kanban .state_40 .box.p10{
|
||||
background-color: #c9fbb2;
|
||||
border: 5px solid #c9fbb2;
|
||||
}
|
||||
|
||||
.task.p20 .name{
|
||||
@@ -150,7 +150,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p20,
|
||||
.kanban .state_40 .box.p20{
|
||||
background-color: #cbff57;
|
||||
border: 5px solid #cbff57;
|
||||
}
|
||||
|
||||
.task.p30 .name{
|
||||
@@ -158,7 +158,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p30,
|
||||
.kanban .state_40 .box.p30{
|
||||
background-color: #dfff44;
|
||||
border: 5px solid #dfff44;
|
||||
}
|
||||
|
||||
.task.p40 .name{
|
||||
@@ -166,7 +166,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p40,
|
||||
.kanban .state_40 .box.p40{
|
||||
background-color: #f8ff29;
|
||||
border: 5px solid #f8ff29;
|
||||
}
|
||||
|
||||
.task.p50 .name{
|
||||
@@ -174,7 +174,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p50,
|
||||
.kanban .state_40 .box.p50{
|
||||
background-color: #ffdb1b;
|
||||
border: 5px solid #ffdb1b;
|
||||
}
|
||||
|
||||
.task.p60 .name{
|
||||
@@ -182,7 +182,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p60,
|
||||
.kanban .state_40 .box.p60{
|
||||
background-color: #ff9309;
|
||||
border: 5px solid #ff9309;
|
||||
}
|
||||
|
||||
.task.p70 .name{
|
||||
@@ -190,7 +190,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p70,
|
||||
.kanban .state_40 .box.p70{
|
||||
background-color: #ff6c00;
|
||||
border: 5px solid #ff6c00;
|
||||
}
|
||||
|
||||
.task.p80 .name{
|
||||
@@ -198,7 +198,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p80,
|
||||
.kanban .state_40 .box.p80{
|
||||
background-color: #ff3c00;
|
||||
border: 5px solid #ff3c00;
|
||||
}
|
||||
|
||||
.task.p90 .name{
|
||||
@@ -206,7 +206,7 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p90,
|
||||
.kanban .state_40 .box.p90{
|
||||
background-color: #ff0000;
|
||||
border: 5px solid #ff0000;
|
||||
}
|
||||
|
||||
.task.p100 .name{
|
||||
@@ -214,5 +214,5 @@ textarea{
|
||||
}
|
||||
.kanban .state_20 .box.p100,
|
||||
.kanban .state_40 .box.p100{
|
||||
background-color: #ff0048;
|
||||
border: 5px solid #ff0048;
|
||||
}
|
||||
Reference in New Issue
Block a user