Переглянути джерело

Fix Due dates to be color coded and have icons.

Thanks to xet7 !

Fixes #5950
Lauri Ojansivu 6 днів тому
батько
коміт
d965faa317

+ 1 - 1
client/components/cards/cardDate.css

@@ -94,7 +94,7 @@
 
 /* Generic date badge and custom field date */
 .card-date:not(.received-date):not(.start-date):not(.due-date):not(.end-date) time::before {
-  content: "📅"; /* Calendar - represents generic date */
+  /*content: "📅"; // Calendar - represents generic date */
 }
 .card-date time::before {
   font-size: inherit;

+ 8 - 8
client/components/cards/cardDate.jade

@@ -24,14 +24,14 @@ template(name="dateCustomField")
 
 template(name="minicardReceivedDate")
   if canModifyCard
-    a.js-edit-date.card-date(title="{{_ 'card-received'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
+    a.js-edit-date.card-date.received-date(title="{{_ 'card-received'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
       time(datetime="{{showISODate}}")
         | {{showDate}}
         if showWeekOfYear
           b
             | {{showWeek}}
   else
-    a.card-date(title="{{_ 'card-received'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
+    a.card-date.received-date(title="{{_ 'card-received'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
       time(datetime="{{showISODate}}")
         | {{showDate}}
         if showWeekOfYear
@@ -40,14 +40,14 @@ template(name="minicardReceivedDate")
 
 template(name="minicardStartDate")
   if canModifyCard
-    a.js-edit-date.card-date(title="{{_ 'card-start'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
+    a.js-edit-date.card-date.start-date(title="{{_ 'card-start'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
       time(datetime="{{showISODate}}")
         | {{showDate}}
         if showWeekOfYear
           b
             | {{showWeek}}
   else
-    a.card-date(title="{{_ 'card-start'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
+    a.card-date.start-date(title="{{_ 'card-start'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
       time(datetime="{{showISODate}}")
         | {{showDate}}
         if showWeekOfYear
@@ -56,14 +56,14 @@ template(name="minicardStartDate")
 
 template(name="minicardDueDate")
   if canModifyCard
-    a.js-edit-date.card-date(title="{{_ 'card-due'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
+    a.js-edit-date.card-date.due-date(title="{{_ 'card-due'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
       time(datetime="{{showISODate}}")
         | {{showDate}}
         if showWeekOfYear
           b
             | {{showWeek}}
   else
-    a.card-date(title="{{_ 'card-due'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
+    a.card-date.due-date(title="{{_ 'card-due'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
       time(datetime="{{showISODate}}")
         | {{showDate}}
         if showWeekOfYear
@@ -72,14 +72,14 @@ template(name="minicardDueDate")
 
 template(name="minicardEndDate")
   if canModifyCard
-    a.js-edit-date.card-date(title="{{_ 'card-end'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
+    a.js-edit-date.card-date.end-date(title="{{_ 'card-end'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
       time(datetime="{{showISODate}}")
         | {{showDate}}
         if showWeekOfYear
           b
             | {{showWeek}}
   else
-    a.card-date(title="{{_ 'card-end'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
+    a.card-date.end-date(title="{{_ 'card-end'}} {{_ 'predicate-week'}} {{#if showWeekOfYear}}{{showWeek}}{{/if}}" class="{{classes}}")
       time(datetime="{{showISODate}}")
         | {{showDate}}
         if showWeekOfYear

+ 17 - 18
client/components/cards/cardDate.js

@@ -18,7 +18,8 @@ import {
   now, 
   createDate, 
   fromNow, 
-  calendar 
+  calendar,
+  diff
 } from '/imports/lib/dateUtils';
 
 // editCardReceivedDatePopup
@@ -169,9 +170,7 @@ class CardReceivedDate extends CardDate {
   }
 
   showTitle() {
-    return `${TAPi18n.__('card-received-on')} ${this.date
-      .get()
-      .format('LLLL')}`;
+    return `${TAPi18n.__('card-received-on')} ${format(this.date.get(), 'LLLL')}`;
   }
 
   events() {
@@ -198,15 +197,15 @@ class CardStartDate extends CardDate {
     const theDate = this.date.get();
     const now = this.now.get();
     // if dueAt or endAt exist & are > startAt, startAt doesn't need to be flagged
-    if ((endAt && theDate.isAfter(endAt)) || (dueAt && theDate.isAfter(dueAt)))
+    if ((endAt && isAfter(theDate, endAt)) || (dueAt && isAfter(theDate, dueAt)))
       classes += 'long-overdue';
-    else if (theDate.isAfter(now)) classes += '';
+    else if (isAfter(theDate, now)) classes += '';
     else classes += 'current';
     return classes;
   }
 
   showTitle() {
-    return `${TAPi18n.__('card-start-on')} ${this.date.get().format('LLLL')}`;
+    return `${TAPi18n.__('card-start-on')} ${format(this.date.get(), 'LLLL')}`;
   }
 
   events() {
@@ -232,17 +231,17 @@ class CardDueDate extends CardDate {
     const theDate = this.date.get();
     const now = this.now.get();
     // if the due date is after the end date, green - done early
-    if (endAt && theDate.isAfter(endAt)) classes += 'current';
+    if (endAt && isAfter(theDate, endAt)) classes += 'current';
     // if there is an end date, don't need to flag the due date
     else if (endAt) classes += '';
-    else if (now.diff(theDate, 'days') >= 2) classes += 'long-overdue';
-    else if (now.diff(theDate, 'minute') >= 0) classes += 'due';
-    else if (now.diff(theDate, 'days') >= -1) classes += 'almost-due';
+    else if (diff(now, theDate, 'days') >= 2) classes += 'long-overdue';
+    else if (diff(now, theDate, 'minute') >= 0) classes += 'due';
+    else if (diff(now, theDate, 'days') >= -1) classes += 'almost-due';
     return classes;
   }
 
   showTitle() {
-    return `${TAPi18n.__('card-due-on')} ${this.date.get().format('LLLL')}`;
+    return `${TAPi18n.__('card-due-on')} ${format(this.date.get(), 'LLLL')}`;
   }
 
   events() {
@@ -267,13 +266,13 @@ class CardEndDate extends CardDate {
     const dueAt = this.data().getDue();
     const theDate = this.date.get();
     if (!dueAt) classes += '';
-    else if (theDate.isBefore(dueAt)) classes += 'current';
-    else if (theDate.isAfter(dueAt)) classes += 'due';
+    else if (isBefore(theDate, dueAt)) classes += 'current';
+    else if (isAfter(theDate, dueAt)) classes += 'due';
     return classes;
   }
 
   showTitle() {
-    return `${TAPi18n.__('card-end-on')} ${this.date.get().format('LLLL')}`;
+    return `${TAPi18n.__('card-end-on')} ${format(this.date.get(), 'LLLL')}`;
   }
 
   events() {
@@ -315,7 +314,7 @@ class CardCustomFieldDate extends CardDate {
   }
 
   showTitle() {
-    return `${this.date.get().format('LLLL')}`;
+    return `${format(this.date.get(), 'LLLL')}`;
   }
 
   classes() {
@@ -418,10 +417,10 @@ class PokerEndDate extends CardDate {
     return classes;
   }
   showDate() {
-    return this.date.get().format('l LT');
+    return format(this.date.get(), 'l LT');
   }
   showTitle() {
-    return `${TAPi18n.__('card-end-on')} ${this.date.get().format('LLLL')}`;
+    return `${TAPi18n.__('card-end-on')} ${format(this.date.get(), 'LLLL')}`;
   }
 
   events() {

+ 57 - 0
client/components/cards/minicard.css

@@ -169,6 +169,63 @@
   margin-right: 0.4vw;
 }
 
+/* Unicode icons for minicard dates - matching cardDate.css */
+.minicard .card-date.end-date time::before {
+  content: "🏁"; /* Finish flag - represents end/completion */
+}
+.minicard .card-date.due-date time::before {
+  content: "⏰"; /* Alarm clock - represents due/deadline */
+}
+.minicard .card-date.start-date time::before {
+  content: "🚀"; /* Rocket - represents start/launch */
+}
+.minicard .card-date.received-date time::before {
+  content: "📥"; /* Inbox tray - represents received/incoming */
+}
+
+.minicard .card-date time::before {
+  font-size: inherit;
+  margin-right: 0.3em;
+  display: inline-block;
+}
+
+/* Date type specific colors for minicards - matching cardDate.css */
+.minicard .card-date.received-date {
+  background-color: #dbdbdb; /* Grey for received - same as base card-date */
+}
+
+.minicard .card-date.received-date:hover,
+.minicard .card-date.received-date.is-active {
+  background-color: #b3b3b3;
+}
+
+.minicard .card-date.start-date {
+  background-color: #3cb500; /* Green for start */
+}
+
+.minicard .card-date.start-date:hover,
+.minicard .card-date.start-date.is-active {
+  background-color: #2d8f00;
+}
+
+.minicard .card-date.due-date {
+  background-color: #ff9f19; /* Orange for due */
+}
+
+.minicard .card-date.due-date:hover,
+.minicard .card-date.due-date.is-active {
+  background-color: #e68a00;
+}
+
+.minicard .card-date.end-date {
+  background-color: #a632db; /* Purple for end */
+}
+
+.minicard .card-date.end-date:hover,
+.minicard .card-date.end-date.is-active {
+  background-color: #8a2bb8;
+}
+
 /* Font Awesome icons in minicard dates */
 .minicard .card-date i.fa {
   margin-right: 0.3vw;

+ 2 - 5
client/components/cards/minicard.jade

@@ -12,11 +12,8 @@ template(name="minicard")
         a.minicard-details-menu.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") | ☰
     .dates
       if getReceived
-        unless getStart
-          unless getDue
-            unless getEnd
-              .date
-                +minicardReceivedDate
+        .date
+          +minicardReceivedDate
       if getStart
         .date
           +minicardStartDate

+ 41 - 0
imports/lib/dateUtils.js

@@ -304,6 +304,10 @@ export function format(date, format = 'L') {
       return d.toLocaleString();
     case 'llll':
       return d.toLocaleString();
+    case 'LLLL':
+      return d.toLocaleString();
+    case 'l LT':
+      return `${month}/${day}/${year} ${hours}:${minutes}`;
     case 'YYYY-MM-DD':
       return `${year}-${month}-${day}`;
     case 'YYYY-MM-DD HH:mm':
@@ -490,3 +494,40 @@ export function calendar(date, now = new Date()) {
   
   return format(d, 'L');
 }
+
+/**
+ * Calculate the difference between two dates in the specified unit
+ * @param {Date|string} date1 - First date
+ * @param {Date|string} date2 - Second date  
+ * @param {string} unit - Unit of measurement ('millisecond', 'second', 'minute', 'hour', 'day', 'week', 'month', 'year')
+ * @returns {number} Difference in the specified unit
+ */
+export function diff(date1, date2, unit = 'millisecond') {
+  const d1 = new Date(date1);
+  const d2 = new Date(date2);
+  
+  if (isNaN(d1.getTime()) || isNaN(d2.getTime())) return 0;
+  
+  const diffMs = d1.getTime() - d2.getTime();
+  
+  switch (unit) {
+    case 'millisecond':
+      return diffMs;
+    case 'second':
+      return Math.floor(diffMs / 1000);
+    case 'minute':
+      return Math.floor(diffMs / (1000 * 60));
+    case 'hour':
+      return Math.floor(diffMs / (1000 * 60 * 60));
+    case 'day':
+      return Math.floor(diffMs / (1000 * 60 * 60 * 24));
+    case 'week':
+      return Math.floor(diffMs / (1000 * 60 * 60 * 24 * 7));
+    case 'month':
+      return Math.floor(diffMs / (1000 * 60 * 60 * 24 * 30));
+    case 'year':
+      return Math.floor(diffMs / (1000 * 60 * 60 * 24 * 365));
+    default:
+      return diffMs;
+  }
+}