Properly localize date in document title

Signed-off-by: Georg Ehrke <developer@georgehrke.com>
This commit is contained in:
Georg Ehrke 2020-01-29 15:54:23 +01:00
parent 7ff5b02a6e
commit dd5c94ac49
No known key found for this signature in database
GPG Key ID: 9D98FD9380A1CB43
5 changed files with 226 additions and 10 deletions

View File

@ -34,6 +34,7 @@ import { translate, translatePlural } from '@nextcloud/l10n'
import ClickOutside from 'vue-click-outside'
import VueClipboard from 'vue-clipboard2'
import VTooltip from 'v-tooltip'
import windowTitleService from './services/windowTitleService.js'
// register global components
Vue.directive('ClickOutside', ClickOutside)
@ -61,6 +62,8 @@ Vue.prototype.$toast = OCP.Toast // eslint-disable-line no-undef
Vue.prototype.t = translate
Vue.prototype.n = translatePlural
windowTitleService(router, store)
export default new Vue({
el: '#content',
router,

View File

@ -26,7 +26,6 @@ import { getRootUrl, generateUrl } from '@nextcloud/router'
import Calendar from './views/Calendar'
import EditSimple from './views/EditSimple'
import EditSidebar from './views/EditSidebar'
import windowTitleService from './services/windowTitleService.js'
import { getInitialView } from './utils/router.js'
Vue.use(Router)
@ -143,6 +142,4 @@ const router = new Router({
],
})
windowTitleService(router)
export default router

View File

@ -29,8 +29,28 @@ const originalWindowTitle = document.title
* automatically adjusts the title of the window
*
* @param {VueRouter} router The VueJS Router instance
* @param {Store} store The vuex store
*/
export default function(router) {
export default function(router, store) {
/**
* Updates the title of the window
*
* @param {Date} date viewed Date
* @param {String} view Name of the current view
* @param {String} locale Locale to be used for formatting
*/
function updateTitle(date, view, locale) {
const title = dateRangeFormat(date, view, locale)
document.title = [
title,
originalWindowTitle,
].join(' - ')
}
/**
* This listens to router changes and automatically
* updates the title
*/
router.beforeEach((to, from, next) => {
if (!to.params.firstDay) {
next()
@ -38,14 +58,27 @@ export default function(router) {
}
const date = getDateFromFirstdayParam(to.params.firstDay)
const currentView = to.params.view
const view = to.params.view
const locale = store.state.settings.momentLocale
const title = dateRangeFormat(date, currentView, 'en')
document.title = [
title,
originalWindowTitle,
].join(' - ')
updateTitle(date, view, locale)
next()
})
/**
* This listens to changes of the locale
* and automatically updates it.
*/
store.subscribe(mutation => {
if (mutation.type !== 'setMomentLocale') {
return
}
const date = getDateFromFirstdayParam(router.currentRoute.params.firstDay)
const view = router.currentRoute.params.view
const locale = mutation.payload
updateTitle(date, view, locale)
})
}

View File

@ -1,2 +1,4 @@
import 'core-js/stable';
import 'regenerator-runtime/runtime';
document.title = 'Standard Nextcloud title'

View File

@ -0,0 +1,181 @@
/**
* @copyright Copyright (c) 2019 Georg Ehrke
*
* @author Georg Ehrke <oc.list@georgehrke.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import dateRangeFormat from '../../../../src/filters/dateRangeFormat.js'
import { getDateFromFirstdayParam } from '../../../../src/utils/date.js'
import windowTitleService from "../../../../src/services/windowTitleService.js";
jest.mock('../../../../src/filters/dateRangeFormat.js')
jest.mock('../../../../src/utils/date.js')
describe('services/windowTitleService', () => {
beforeEach(() => {
dateRangeFormat.mockClear()
getDateFromFirstdayParam.mockClear()
// Reset to previous one
document.title = 'Standard Nextcloud title'
})
it('should update the title on route changes', () => {
const router = {
beforeEach: jest.fn(),
}
const store = {
subscribe: jest.fn(),
state: {
settings: {
momentLocale: 'momentLocaleLoadedFromState',
},
},
}
const to = {
params: {
firstDay: 'first-day-param-of-to',
view: 'view-param-of-to',
}
}
const from = {
params: {
firstDay: 'first-day-param-of-from',
view: 'view-param-of-from',
}
}
const next = jest.fn()
dateRangeFormat
.mockReturnValueOnce('formatted date range')
getDateFromFirstdayParam
.mockReturnValueOnce('processed first-day-param')
expect(document.title).toEqual('Standard Nextcloud title')
windowTitleService(router, store)
expect(document.title).toEqual('Standard Nextcloud title')
router.beforeEach.mock.calls[0][0](to, from, next)
expect(document.title).toEqual('formatted date range - Standard Nextcloud title')
expect(dateRangeFormat).toHaveBeenCalledTimes(1)
expect(dateRangeFormat).toHaveBeenNthCalledWith(1, 'processed first-day-param', 'view-param-of-to', 'momentLocaleLoadedFromState')
expect(getDateFromFirstdayParam).toHaveBeenCalledTimes(1)
expect(getDateFromFirstdayParam).toHaveBeenNthCalledWith(1, 'first-day-param-of-to')
expect(next).toHaveBeenCalledTimes(1)
})
it('should not update the title if there is no firstDay in route', () => {
const router = {
beforeEach: jest.fn(),
}
const store = {
subscribe: jest.fn(),
state: {
settings: {
momentLocale: 'momentLocaleLoadedFromState',
},
},
}
const to = {
params: {
view: 'view-param-of-to',
}
}
const from = {
params: {
view: 'view-param-of-from',
}
}
const next = jest.fn()
dateRangeFormat
.mockReturnValueOnce('formatted date range')
getDateFromFirstdayParam
.mockReturnValueOnce('processed first-day-param')
expect(document.title).toEqual('Standard Nextcloud title')
windowTitleService(router, store)
expect(document.title).toEqual('Standard Nextcloud title')
router.beforeEach.mock.calls[0][0](to, from, next)
expect(document.title).toEqual('Standard Nextcloud title')
expect(dateRangeFormat).toHaveBeenCalledTimes(0)
expect(getDateFromFirstdayParam).toHaveBeenCalledTimes(0)
expect(next).toHaveBeenCalledTimes(1)
})
it('should update the title on update of locale', () => {
const router = {
beforeEach: jest.fn(),
currentRoute: {
params: {
firstDay: 'first-day-param-of-current-route',
view: 'view-param-of-current-route',
}
}
}
const store = {
subscribe: jest.fn(),
}
dateRangeFormat
.mockReturnValueOnce('formatted date range')
getDateFromFirstdayParam
.mockReturnValueOnce('processed first-day-param')
expect(document.title).toEqual('Standard Nextcloud title')
windowTitleService(router, store)
expect(document.title).toEqual('Standard Nextcloud title')
store.subscribe.mock.calls[0][0]({
type: 'some_other_mutation',
})
expect(document.title).toEqual('Standard Nextcloud title')
store.subscribe.mock.calls[0][0]({
type: 'setMomentLocale',
payload: 'momentLocaleFromPayload'
})
expect(document.title).toEqual('formatted date range - Standard Nextcloud title')
expect(dateRangeFormat).toHaveBeenCalledTimes(1)
expect(dateRangeFormat).toHaveBeenNthCalledWith(1, 'processed first-day-param', 'view-param-of-current-route', 'momentLocaleFromPayload')
expect(getDateFromFirstdayParam).toHaveBeenCalledTimes(1)
expect(getDateFromFirstdayParam).toHaveBeenNthCalledWith(1, 'first-day-param-of-current-route')
})
})