Commit b27858ddb52b2f6238294eea561e129c6194b1ab

Authored by Sergio Crisostomo
1 parent 3d50db5b

add date panel label format logic

src/components/date-picker/panel/date-panel-label.vue 0 → 100644
  1 +<template>
  2 + <span>
  3 + <span
  4 + v-if="datePanelLabel"
  5 + v-show="datePanelLabel.labels[0].type === 'year' || currentView === 'date'"
  6 + :class="[datePrefixCls + '-header-label']"
  7 + @click="datePanelLabel.labels[0].handler">{{ datePanelLabel.labels[0].label }}</span>
  8 + <template v-if="datePanelLabel && currentView === 'date'">{{ datePanelLabel.separator }}</template>
  9 + <span
  10 + v-if="datePanelLabel"
  11 + v-show="datePanelLabel.labels[1].type === 'year' || currentView === 'date'"
  12 + :class="[datePrefixCls + '-header-label']"
  13 + @click="datePanelLabel.labels[1].handler">{{ datePanelLabel.labels[1].label }}</span>
  14 + </span>
  15 +</template>
  16 +
  17 +<script>
  18 +export default {
  19 + props: {
  20 + datePanelLabel: Object,
  21 + currentView: String,
  22 + datePrefixCls: String
  23 + }
  24 +};
  25 +</script>
src/components/date-picker/panel/date-range.vue
@@ -16,13 +16,10 @@ @@ -16,13 +16,10 @@
16 :class="iconBtnCls('prev')" 16 :class="iconBtnCls('prev')"
17 @click="prevMonth" 17 @click="prevMonth"
18 v-show="leftCurrentView === 'date'"><Icon type="ios-arrow-left"></Icon></span> 18 v-show="leftCurrentView === 'date'"><Icon type="ios-arrow-left"></Icon></span>
19 - <span  
20 - :class="[datePrefixCls + '-header-label']"  
21 - @click="showYearPicker('left')">{{ leftYearLabel }}</span>  
22 - <span  
23 - :class="[datePrefixCls + '-header-label']"  
24 - @click="showMonthPicker('left')"  
25 - v-show="leftCurrentView === 'date'">{{ leftMonthLabel }}</span> 19 + <date-panel-label
  20 + :date-panel-label="leftDatePanelLabel"
  21 + :current-view="leftCurrentView"
  22 + :date-prefix-cls="datePrefixCls"/>
26 <span 23 <span
27 :class="iconBtnCls('next', '-double')" 24 :class="iconBtnCls('next', '-double')"
28 @click="nextYear('left')" 25 @click="nextYear('left')"
@@ -66,13 +63,10 @@ @@ -66,13 +63,10 @@
66 :class="iconBtnCls('prev', '-double')" 63 :class="iconBtnCls('prev', '-double')"
67 @click="prevYear('right')" 64 @click="prevYear('right')"
68 v-show="rightCurrentView === 'year' || rightCurrentView === 'month'"><Icon type="ios-arrow-left"></Icon></span> 65 v-show="rightCurrentView === 'year' || rightCurrentView === 'month'"><Icon type="ios-arrow-left"></Icon></span>
69 - <span  
70 - :class="[datePrefixCls + '-header-label']"  
71 - @click="showYearPicker('right')">{{ rightYearLabel }}</span>  
72 - <span  
73 - :class="[datePrefixCls + '-header-label']"  
74 - @click="showMonthPicker('right')"  
75 - v-show="rightCurrentView === 'date'">{{ rightMonthLabel }}</span> 66 + <date-panel-label
  67 + :date-panel-label="rightDatePanelLabel"
  68 + :current-view="rightCurrentView"
  69 + :date-prefix-cls="datePrefixCls"/>
76 <span 70 <span
77 :class="iconBtnCls('next', '-double')" 71 :class="iconBtnCls('next', '-double')"
78 @click="nextYear('right')"><Icon type="ios-arrow-right"></Icon></span> 72 @click="nextYear('right')"><Icon type="ios-arrow-right"></Icon></span>
@@ -138,7 +132,8 @@ @@ -138,7 +132,8 @@
138 import MonthTable from '../base/month-table.vue'; 132 import MonthTable from '../base/month-table.vue';
139 import TimePicker from './time-range.vue'; 133 import TimePicker from './time-range.vue';
140 import Confirm from '../base/confirm.vue'; 134 import Confirm from '../base/confirm.vue';
141 - import { toDate, prevMonth, nextMonth, initTimeDate } from '../util'; 135 + import { toDate, prevMonth, nextMonth, initTimeDate, formatDateLabels } from '../util';
  136 + import datePanelLabel from './date-panel-label.vue';
142 137
143 import Mixin from './mixin'; 138 import Mixin from './mixin';
144 import Locale from '../../../mixins/locale'; 139 import Locale from '../../../mixins/locale';
@@ -149,7 +144,7 @@ @@ -149,7 +144,7 @@
149 export default { 144 export default {
150 name: 'DatePicker', 145 name: 'DatePicker',
151 mixins: [ Mixin, Locale ], 146 mixins: [ Mixin, Locale ],
152 - components: { Icon, DateTable, YearTable, MonthTable, TimePicker, Confirm }, 147 + components: { Icon, DateTable, YearTable, MonthTable, TimePicker, Confirm, datePanelLabel },
153 data () { 148 data () {
154 return { 149 return {
155 prefixCls: prefixCls, 150 prefixCls: prefixCls,
@@ -195,26 +190,9 @@ @@ -195,26 +190,9 @@
195 return this.date; 190 return this.date;
196 } 191 }
197 }, 192 },
198 - leftYearLabel () {  
199 - const tYear = this.t('i.datepicker.year');  
200 - if (this.leftCurrentView === 'year') {  
201 - const year = this.leftTableYear;  
202 - if (!year) return '';  
203 - const startYear = Math.floor(year / 10) * 10;  
204 - return `${startYear}${tYear} - ${startYear + 9}${tYear}`;  
205 - } else {  
206 - const year = this.leftCurrentView === 'month' ? this.leftTableYear : this.leftYear;  
207 - if (!year) return '';  
208 - return `${year}${tYear}`;  
209 - }  
210 - },  
211 leftMonth () { 193 leftMonth () {
212 return this.date.getMonth(); 194 return this.date.getMonth();
213 }, 195 },
214 - leftMonthLabel () {  
215 - const month = this.leftMonth + 1;  
216 - return this.t(`i.datepicker.month${month}`);  
217 - },  
218 rightYear () { 196 rightYear () {
219 return this.rightDate.getFullYear(); 197 return this.rightDate.getFullYear();
220 }, 198 },
@@ -225,26 +203,9 @@ @@ -225,26 +203,9 @@
225 return this.date; 203 return this.date;
226 } 204 }
227 }, 205 },
228 - rightYearLabel () {  
229 - const tYear = this.t('i.datepicker.year');  
230 - if (this.rightCurrentView === 'year') {  
231 - const year = this.rightTableYear;  
232 - if (!year) return '';  
233 - const startYear = Math.floor(year / 10) * 10;  
234 - return `${startYear}${tYear} - ${startYear + 9}${tYear}`;  
235 - } else {  
236 - const year = this.rightCurrentView === 'month' ? this.rightTableYear : this.rightYear;  
237 - if (!year) return '';  
238 - return `${year}${tYear}`;  
239 - }  
240 - },  
241 rightMonth () { 206 rightMonth () {
242 return this.rightDate.getMonth(); 207 return this.rightDate.getMonth();
243 }, 208 },
244 - rightMonthLabel () {  
245 - const month = this.rightMonth + 1;  
246 - return this.t(`i.datepicker.month${month}`);  
247 - },  
248 rightDate () { 209 rightDate () {
249 const newDate = new Date(this.date); 210 const newDate = new Date(this.date);
250 const month = newDate.getMonth(); 211 const month = newDate.getMonth();
@@ -258,6 +219,14 @@ @@ -258,6 +219,14 @@
258 } 219 }
259 return newDate; 220 return newDate;
260 }, 221 },
  222 + leftDatePanelLabel () {
  223 + if (!this.leftYear) return null; // not ready yet
  224 + return this.panelLabelConfig('left');
  225 + },
  226 + rightDatePanelLabel () {
  227 + if (!this.leftYear) return null; // not ready yet
  228 + return this.panelLabelConfig('right');
  229 + },
261 timeDisabled () { 230 timeDisabled () {
262 return !(this.minDate && this.maxDate); 231 return !(this.minDate && this.maxDate);
263 } 232 }
@@ -288,6 +257,22 @@ @@ -288,6 +257,22 @@
288 } 257 }
289 }, 258 },
290 methods: { 259 methods: {
  260 + panelLabelConfig (direction) {
  261 + const locale = this.t('i.locale');
  262 + const datePanelLabel = this.t('i.datepicker.datePanelLabel');
  263 + const handler = type => {
  264 + const fn = type == 'month' ? this.showMonthPicker : this.showYearPicker;
  265 + return () => fn(direction);
  266 + };
  267 +
  268 + const date = new Date(this[`${direction}Year`], this[`${direction}Month`]);
  269 + const { labels, separator } = formatDateLabels(locale, datePanelLabel, date);
  270 +
  271 + return {
  272 + separator: separator,
  273 + labels: labels.map(obj => ((obj.handler = handler(obj.type)), obj))
  274 + };
  275 + },
291 resetDate () { 276 resetDate () {
292 this.date = new Date(this.date); 277 this.date = new Date(this.date);
293 this.leftTableYear = this.date.getFullYear(); 278 this.leftTableYear = this.date.getFullYear();
src/components/date-picker/panel/date.vue
@@ -15,13 +15,10 @@ @@ -15,13 +15,10 @@
15 :class="iconBtnCls('prev')" 15 :class="iconBtnCls('prev')"
16 @click="changeMonth(-1)" 16 @click="changeMonth(-1)"
17 v-show="currentView === 'date'"><Icon type="ios-arrow-left"></Icon></span> 17 v-show="currentView === 'date'"><Icon type="ios-arrow-left"></Icon></span>
18 - <span  
19 - :class="[datePrefixCls + '-header-label']"  
20 - @click="showYearPicker">{{ yearLabel }}</span>  
21 - <span  
22 - :class="[datePrefixCls + '-header-label']"  
23 - @click="showMonthPicker"  
24 - v-show="currentView === 'date'">{{ monthLabel }}</span> 18 + <date-panel-label
  19 + :date-panel-label="datePanelLabel"
  20 + :current-view="currentView"
  21 + :date-prefix-cls="datePrefixCls"/>
25 <span 22 <span
26 :class="iconBtnCls('next', '-double')" 23 :class="iconBtnCls('next', '-double')"
27 @click="changeYear(+1)"><Icon type="ios-arrow-right"></Icon></span> 24 @click="changeYear(+1)"><Icon type="ios-arrow-right"></Icon></span>
@@ -83,11 +80,12 @@ @@ -83,11 +80,12 @@
83 import MonthTable from '../base/month-table.vue'; 80 import MonthTable from '../base/month-table.vue';
84 import TimePicker from './time.vue'; 81 import TimePicker from './time.vue';
85 import Confirm from '../base/confirm.vue'; 82 import Confirm from '../base/confirm.vue';
  83 + import datePanelLabel from './date-panel-label.vue';
86 84
87 import Mixin from './mixin'; 85 import Mixin from './mixin';
88 import Locale from '../../../mixins/locale'; 86 import Locale from '../../../mixins/locale';
89 87
90 - import { initTimeDate, siblingMonth } from '../util'; 88 + import { initTimeDate, siblingMonth, formatDateLabels } from '../util';
91 89
92 const prefixCls = 'ivu-picker-panel'; 90 const prefixCls = 'ivu-picker-panel';
93 const datePrefixCls = 'ivu-date-picker'; 91 const datePrefixCls = 'ivu-date-picker';
@@ -95,7 +93,7 @@ @@ -95,7 +93,7 @@
95 export default { 93 export default {
96 name: 'DatePicker', 94 name: 'DatePicker',
97 mixins: [ Mixin, Locale ], 95 mixins: [ Mixin, Locale ],
98 - components: { Icon, DateTable, YearTable, MonthTable, TimePicker, Confirm }, 96 + components: { Icon, DateTable, YearTable, MonthTable, TimePicker, Confirm, datePanelLabel },
99 data () { 97 data () {
100 return { 98 return {
101 prefixCls: prefixCls, 99 prefixCls: prefixCls,
@@ -123,19 +121,21 @@ @@ -123,19 +121,21 @@
123 } 121 }
124 ]; 122 ];
125 }, 123 },
126 - yearLabel () {  
127 - const tYear = this.t('i.datepicker.year');  
128 - const year = this.year;  
129 - if (!year) return '';  
130 - if (this.currentView === 'year') {  
131 - const startYear = Math.floor(year / 10) * 10;  
132 - return `${startYear}${tYear} - ${startYear + 9}${tYear}`;  
133 - }  
134 - return `${year}${tYear}`;  
135 - },  
136 - monthLabel () {  
137 - const month = this.month + 1;  
138 - return this.t(`i.datepicker.month${month}`); 124 + datePanelLabel () {
  125 + if (!this.year) return null; // not ready yet
  126 + const locale = this.t('i.locale');
  127 + const datePanelLabel = this.t('i.datepicker.datePanelLabel');
  128 + const date = new Date(this.year, this.month);
  129 + const { labels, separator } = formatDateLabels(locale, datePanelLabel, date);
  130 +
  131 + const handler = type => {
  132 + return () => (this.currentView = type);
  133 + };
  134 +
  135 + return {
  136 + separator: separator,
  137 + labels: labels.map(obj => ((obj.handler = handler(obj.type)), obj))
  138 + };
139 } 139 }
140 }, 140 },
141 watch: { 141 watch: {
@@ -196,12 +196,6 @@ @@ -196,12 +196,6 @@
196 this.date = siblingMonth(this.date, dir); 196 this.date = siblingMonth(this.date, dir);
197 this.setMonthYear(this.date); 197 this.setMonthYear(this.date);
198 }, 198 },
199 - showYearPicker () {  
200 - this.currentView = 'year';  
201 - },  
202 - showMonthPicker () {  
203 - this.currentView = 'month';  
204 - },  
205 handleToggleTime () { 199 handleToggleTime () {
206 if (this.currentView === 'date') { 200 if (this.currentView === 'date') {
207 this.currentView = 'time'; 201 this.currentView = 'time';
src/components/date-picker/util.js
@@ -61,3 +61,64 @@ export const initTimeDate = function() { @@ -61,3 +61,64 @@ export const initTimeDate = function() {
61 date.setSeconds(0); 61 date.setSeconds(0);
62 return date; 62 return date;
63 }; 63 };
  64 +
  65 +export const formatDateLabels = (function() {
  66 + /*
  67 + Formats:
  68 + yyyy - 4 digit year
  69 + m - month, numeric, 1 - 12
  70 + m - month, numeric, 01 - 12
  71 + mmm - month, 3 letters, as in `toLocaleDateString`
  72 + Mmm - month, 3 letters, capitalize the return from `toLocaleDateString`
  73 + mmmm - month, full name, as in `toLocaleDateString`
  74 + Mmmm - month, full name, capitalize the return from `toLocaleDateString`
  75 + */
  76 +
  77 + const formats = {
  78 + yyyy: date => date.getFullYear(),
  79 + m: date => date.getMonth(),
  80 + mm: date => ('0' + date.getMonth()).slice(-2),
  81 + mmm: (date, locale) => {
  82 + const monthName = date.toLocaleDateString(locale, {
  83 + month: 'long'
  84 + });
  85 + return monthName.slice(0, 3);
  86 + },
  87 + Mmm: (date, locale) => {
  88 + const monthName = date.toLocaleDateString(locale, {
  89 + month: 'long'
  90 + });
  91 + return (monthName[0].toUpperCase() + monthName.slice(1).toLowerCase()).slice(0, 3);
  92 + },
  93 + mmmm: (date, locale) =>
  94 + date.toLocaleDateString(locale, {
  95 + month: 'long'
  96 + }),
  97 + Mmmm: (date, locale) => {
  98 + const monthName = date.toLocaleDateString(locale, {
  99 + month: 'long'
  100 + });
  101 + return monthName[0].toUpperCase() + monthName.slice(1).toLowerCase();
  102 + }
  103 + };
  104 + const formatRegex = new RegExp(['yyyy', 'Mmmm', 'mmmm', 'Mmm', 'mmm', 'mm', 'm'].join('|'), 'g');
  105 +
  106 + return function(locale, format, date) {
  107 + const componetsRegex = /(\[[^\]]+\])([^\[\]]+)(\[[^\]]+\])/;
  108 + const components = format.match(componetsRegex).slice(1);
  109 + const separator = components[1];
  110 + const labels = [components[0], components[2]].map(component => {
  111 + const label = component.replace(/\[[^\]]+\]/, str => {
  112 + return str.slice(1, -1).replace(formatRegex, match => formats[match](date, locale));
  113 + });
  114 + return {
  115 + label: label,
  116 + type: component.includes('yy') ? 'year' : 'month'
  117 + };
  118 + });
  119 + return {
  120 + separator: separator,
  121 + labels: labels
  122 + };
  123 + };
  124 +})();