Fiz/summaries (#15653)
* dailies monthly weeks of month summary update monthly day-of-week scheduling summary, add scheduling summary to task form, and add 5th week warning * formatting * scheduling warning and summary UI updates * fix(svg): use extant icon --------- Co-authored-by: Hafiz <hafizbhamidi@gmail.com>
This commit is contained in:
@@ -412,6 +412,25 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p
|
||||
v-if="task.type === 'daily' && schedulingSummary"
|
||||
class="scheduling-summary mt-2 mb-0"
|
||||
>
|
||||
{{ schedulingSummary }}
|
||||
</p>
|
||||
<div
|
||||
v-if="task.type === 'daily' && schedulingWarning"
|
||||
class="scheduling-warning mt-2"
|
||||
>
|
||||
<span
|
||||
class="scheduling-warning-icon svg-icon color gray-50"
|
||||
v-html="icons.alert"
|
||||
></span>
|
||||
<span
|
||||
class="scheduling-warning-text"
|
||||
v-html="schedulingWarning"
|
||||
></span>
|
||||
</div>
|
||||
<div
|
||||
v-if="!groupId"
|
||||
class="tags-select option mt-3"
|
||||
@@ -1109,6 +1128,42 @@
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.scheduling-summary {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: $gray-50;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.scheduling-warning {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: $gray-50;
|
||||
}
|
||||
|
||||
.scheduling-warning-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
margin-right: 6px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.scheduling-warning-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@@ -1377,6 +1432,87 @@ export default {
|
||||
}
|
||||
return null;
|
||||
},
|
||||
schedulingSummary () {
|
||||
if (!this.task || this.task.type !== 'daily') return '';
|
||||
const { task } = this;
|
||||
const everyXValue = +task.everyX;
|
||||
|
||||
let interval;
|
||||
if (task.frequency === 'daily') {
|
||||
interval = everyXValue === 1 ? this.$t('everyDay') : this.$t('everyXDays', { count: everyXValue });
|
||||
} else if (task.frequency === 'weekly') {
|
||||
interval = everyXValue === 1 ? this.$t('everyWeek') : this.$t('everyXWeeks', { count: everyXValue });
|
||||
} else if (task.frequency === 'monthly') {
|
||||
interval = everyXValue === 1 ? this.$t('everyMonth') : this.$t('everyXMonths', { count: everyXValue });
|
||||
} else if (task.frequency === 'yearly') {
|
||||
interval = everyXValue === 1 ? this.$t('everyYear') : this.$t('everyXYears', { count: everyXValue });
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
|
||||
let details = '';
|
||||
if (task.frequency === 'weekly') {
|
||||
const dayNames = {
|
||||
su: 'Sunday',
|
||||
m: 'Monday',
|
||||
t: 'Tuesday',
|
||||
w: 'Wednesday',
|
||||
th: 'Thursday',
|
||||
f: 'Friday',
|
||||
s: 'Saturday',
|
||||
};
|
||||
const activeDays = Object.keys(task.repeat || {}).filter(d => task.repeat[d]);
|
||||
if (activeDays.length > 0) {
|
||||
details = ` on ${activeDays.map(d => dayNames[d]).join(', ')}`;
|
||||
}
|
||||
} else if (task.frequency === 'monthly' && task.startDate) {
|
||||
const dayOfMonth = moment(task.startDate).date();
|
||||
if (task.weeksOfMonth && task.weeksOfMonth.length > 0) {
|
||||
const weekNum = task.weeksOfMonth[0] + 1;
|
||||
const weekStr = String(weekNum);
|
||||
const lastDigit = weekStr.slice(-1);
|
||||
let suffix = 'th';
|
||||
if (lastDigit === '1' && weekStr !== '11') suffix = 'st';
|
||||
if (lastDigit === '2' && weekStr !== '12') suffix = 'nd';
|
||||
if (lastDigit === '3' && weekStr !== '13') suffix = 'rd';
|
||||
const dayName = moment(task.startDate).format('dddd');
|
||||
details = ` on the ${weekNum}${suffix} ${dayName} of the month`;
|
||||
} else if (task.daysOfMonth && task.daysOfMonth.length > 0) {
|
||||
const dom = task.daysOfMonth[0];
|
||||
const domStr = String(dom);
|
||||
const lastDigit = domStr.slice(-1);
|
||||
let suffix = 'th';
|
||||
if (lastDigit === '1' && domStr !== '11') suffix = 'st';
|
||||
if (lastDigit === '2' && domStr !== '12') suffix = 'nd';
|
||||
if (lastDigit === '3' && domStr !== '13') suffix = 'rd';
|
||||
details = ` on the ${dom}${suffix}`;
|
||||
} else {
|
||||
const domStr = String(dayOfMonth);
|
||||
const lastDigit = domStr.slice(-1);
|
||||
let suffix = 'th';
|
||||
if (lastDigit === '1' && domStr !== '11') suffix = 'st';
|
||||
if (lastDigit === '2' && domStr !== '12') suffix = 'nd';
|
||||
if (lastDigit === '3' && domStr !== '13') suffix = 'rd';
|
||||
details = ` on the ${dayOfMonth}${suffix}`;
|
||||
}
|
||||
} else if (task.frequency === 'yearly' && task.startDate) {
|
||||
details = ` on ${moment(task.startDate).format('MMMM Do')}`;
|
||||
}
|
||||
|
||||
return `${this.$t('repeats')} ${interval}${details}`;
|
||||
},
|
||||
schedulingWarning () {
|
||||
if (!this.task || this.task.type !== 'daily') return '';
|
||||
const { task } = this;
|
||||
if (task.frequency === 'monthly'
|
||||
&& task.weeksOfMonth && task.weeksOfMonth.length > 0
|
||||
&& task.weeksOfMonth[0] === 4
|
||||
&& task.startDate) {
|
||||
const dayName = moment(task.startDate).format('dddd');
|
||||
return this.$t('fifthWeekWarning', { day: dayName });
|
||||
}
|
||||
return '';
|
||||
},
|
||||
repeatsOn: {
|
||||
get () {
|
||||
let repeatsOn = 'dayOfMonth';
|
||||
|
||||
@@ -222,14 +222,22 @@ export default {
|
||||
return usernames;
|
||||
},
|
||||
summarySentence () {
|
||||
let fifthWeekWarning = '';
|
||||
if (this.task.type === 'daily' && this.task.frequency === 'monthly'
|
||||
&& this.task.weeksOfMonth && this.task.weeksOfMonth.length > 0
|
||||
&& this.task.weeksOfMonth[0] === 4) {
|
||||
const activeDays = keys(pickBy(this.task.repeat, value => value === true));
|
||||
const dayName = this.expandDayString[activeDays[0]];
|
||||
fifthWeekWarning = ` ${this.$t('fifthWeekWarning', { day: dayName })}`;
|
||||
}
|
||||
if (this.task.type === 'daily' && moment().isBefore(this.task.startDate)) {
|
||||
return `This is ${this.formattedDifficulty(this.task.priority)} task that will repeat
|
||||
${this.formattedRepeatInterval(this.task.frequency, this.task.everyX)}${this.formattedDays(this.task.frequency, this.task.repeat, this.task.daysOfMonth, this.task.weeksOfMonth, this.task.startDate)}
|
||||
starting on <strong>${moment(this.task.startDate).format('MM/DD/YYYY')}</strong>.`;
|
||||
starting on <strong>${moment(this.task.startDate).format('MM/DD/YYYY')}</strong>.${fifthWeekWarning}`;
|
||||
}
|
||||
if (this.task.type === 'daily') {
|
||||
return `This is ${this.formattedDifficulty(this.task.priority)} task that repeats
|
||||
${this.formattedRepeatInterval(this.task.frequency, this.task.everyX)}${this.formattedDays(this.task.frequency, this.task.repeat, this.task.daysOfMonth, this.task.weeksOfMonth, this.task.startDate)}.`;
|
||||
${this.formattedRepeatInterval(this.task.frequency, this.task.everyX)}${this.formattedDays(this.task.frequency, this.task.repeat, this.task.daysOfMonth, this.task.weeksOfMonth, this.task.startDate)}.${fifthWeekWarning}`;
|
||||
}
|
||||
if (this.task.date) {
|
||||
return `This is ${this.formattedDifficulty(this.task.priority)} task that is due <strong>${moment(this.task.date).format('MM/DD/YYYY')}.`;
|
||||
@@ -287,25 +295,14 @@ export default {
|
||||
});
|
||||
dayStringArray.push('</strong>');
|
||||
} else if (weeksOfMonth.length > 0) {
|
||||
switch (weeksOfMonth[0]) {
|
||||
case 0:
|
||||
dayStringArray.push('first');
|
||||
break;
|
||||
case 1:
|
||||
dayStringArray.push('second');
|
||||
break;
|
||||
case 2:
|
||||
dayStringArray.push('third');
|
||||
break;
|
||||
case 3:
|
||||
dayStringArray.push('fourth');
|
||||
break;
|
||||
case 4:
|
||||
dayStringArray.push('fifth');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const weekNum = weeksOfMonth[0] + 1;
|
||||
const weekNumStr = String(weekNum);
|
||||
const lastDigit = weekNumStr.slice(-1);
|
||||
let ordinalSuffix = 'th';
|
||||
if (lastDigit === '1' && weekNumStr !== '11') ordinalSuffix = 'st';
|
||||
if (lastDigit === '2' && weekNumStr !== '12') ordinalSuffix = 'nd';
|
||||
if (lastDigit === '3' && weekNumStr !== '13') ordinalSuffix = 'rd';
|
||||
dayStringArray.push(`${weekNum}${ordinalSuffix}`);
|
||||
activeDays = keys(pickBy(repeat, value => value === true));
|
||||
dayStringArray.push(` ${this.expandDayString[activeDays[0]]} of the month</strong>`);
|
||||
}
|
||||
@@ -343,9 +340,8 @@ export default {
|
||||
if (numericX === 2) return '<strong>every other week</strong>';
|
||||
return `<strong>every ${numericX} weeks</strong>`;
|
||||
case 'monthly':
|
||||
if (numericX === 1) return '<strong>every month</strong>';
|
||||
if (numericX === 2) return '<strong>every other month</strong>';
|
||||
return `<strong>every ${numericX} months</strong>`;
|
||||
if (numericX === 1) return `<strong>${this.$t('everyMonth')}</strong>`;
|
||||
return `<strong>${this.$t('everyXMonths', { count: numericX })}</strong>`;
|
||||
case 'yearly':
|
||||
if (numericX === 1) return '<strong>every year</strong>';
|
||||
return `<strong>every ${everyX} years</strong>`;
|
||||
|
||||
@@ -123,6 +123,16 @@
|
||||
"dayOfMonth": "Day of the Month",
|
||||
"month": "Month",
|
||||
"months": "Months",
|
||||
"every": "every",
|
||||
"everyDay": "every day",
|
||||
"everyXDays": "every <%= count %> days",
|
||||
"everyWeek": "every week",
|
||||
"everyXWeeks": "every <%= count %> weeks",
|
||||
"everyMonth": "every month",
|
||||
"everyXMonths": "every <%= count %> months",
|
||||
"everyYear": "every year",
|
||||
"everyXYears": "every <%= count %> years",
|
||||
"fifthWeekWarning": "This task <strong>will not</strong> appear due during months with fewer <%= day %>s",
|
||||
"week": "Week",
|
||||
"weeks": "Weeks",
|
||||
"year": "Year",
|
||||
|
||||
Reference in New Issue
Block a user