mirror of https://github.com/nextcloud/calendar
Add routes to allow creating / editing events from outside
Signed-off-by: Georg Ehrke <developer@georgehrke.com>
This commit is contained in:
parent
eca3a76ad0
commit
a699f6b862
|
@ -27,6 +27,10 @@ return [
|
|||
'routes' => [
|
||||
// User views
|
||||
['name' => 'view#index', 'url' => '/', 'verb' => 'GET'],
|
||||
['name' => 'view#index', 'url' => '/new', 'verb' => 'GET', 'postfix' => 'direct.new'],
|
||||
['name' => 'view#index', 'url' => '/new/{isAllDay}/{dtStart}/{dtEnd}', 'verb' => 'GET', 'postfix' => 'direct.new.timerange'],
|
||||
['name' => 'view#index', 'url' => '/edit/{objectId}', 'verb' => 'GET', 'postfix' => 'direct.edit'],
|
||||
['name' => 'view#index', 'url' => '/edit/{objectId}/{recurrenceId}', 'verb' => 'GET', 'postfix' => 'direct.edit.recurrenceId'],
|
||||
['name' => 'view#index', 'url' => '/{view}/{timeRange}', 'verb' => 'GET', 'requirements' => ['view' => 'timeGridDay|timeGridWeek|dayGridMonth'], 'postfix' => 'view.timerange'],
|
||||
['name' => 'view#index', 'url' => '/{view}/{timeRange}/new/{mode}/{isAllDay}/{dtStart}/{dtEnd}', 'verb' => 'GET', 'requirements' => ['view' => 'timeGridDay|timeGridWeek|dayGridMonth'], 'postfix' => 'view.timerange.new'],
|
||||
['name' => 'view#index', 'url' => '/{view}/{timeRange}/edit/{mode}/{objectId}/{recurrenceId}', 'verb' => 'GET', 'requirements' => ['view' => 'timeGridDay|timeGridWeek|dayGridMonth'], 'postfix' => 'view.timerange.edit'],
|
||||
|
|
|
@ -31,43 +31,14 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { dateFactory } from '../../../utils/date'
|
||||
|
||||
export default {
|
||||
name: 'AppNavigationHeaderNewEvent',
|
||||
methods: {
|
||||
/**
|
||||
* Opens the new event dialog
|
||||
*/
|
||||
newEvent() {
|
||||
let name = this.$store.state.settings.skipPopover
|
||||
? 'NewSidebarView'
|
||||
: 'NewPopoverView'
|
||||
|
||||
if (window.innerWidth <= 768 && name === 'NewPopoverView') {
|
||||
name = 'NewSidebarView'
|
||||
}
|
||||
|
||||
const start = dateFactory()
|
||||
// Setting a value greater than 23 is actually supported with the expected behavior:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setHours
|
||||
start.setHours(start.getHours() + Math.ceil(start.getMinutes() / 60))
|
||||
start.setMinutes(0)
|
||||
const end = new Date(start.getTime())
|
||||
end.setHours(start.getHours() + 1)
|
||||
|
||||
const params = Object.assign({}, this.$store.state.route.params, {
|
||||
allDay: '0',
|
||||
dtstart: String(Math.floor(start.getTime() / 1000)),
|
||||
dtend: String(Math.floor(end.getTime() / 1000)),
|
||||
})
|
||||
|
||||
// Don't push new route when day didn't change
|
||||
if (name === this.$store.state.route.name
|
||||
&& params.allDay === this.$store.state.route.params.allDay
|
||||
&& params.dtstart === this.$store.state.route.params.dtstart
|
||||
&& params.dtend === this.$store.state.route.params.dtend) {
|
||||
return
|
||||
}
|
||||
|
||||
this.$router.push({ name, params })
|
||||
this.$router.push('/new')
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -26,7 +26,12 @@ import { getRootUrl, generateUrl } from '@nextcloud/router'
|
|||
import Calendar from './views/Calendar'
|
||||
import EditSimple from './views/EditSimple'
|
||||
import EditSidebar from './views/EditSidebar'
|
||||
import { getInitialView } from './utils/router.js'
|
||||
import {
|
||||
getDefaultEndDateForNewEvent,
|
||||
getDefaultStartDateForNewEvent,
|
||||
getInitialView,
|
||||
getPreferredEditorRoute,
|
||||
} from './utils/router.js'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
|
@ -97,20 +102,25 @@ const router = new Router({
|
|||
path: '/embed/:tokens',
|
||||
redirect: `/embed/:tokens/${getInitialView()}/now`,
|
||||
},
|
||||
{
|
||||
path: '/new',
|
||||
redirect: () => `/${getInitialView()}/now/new/${getPreferredEditorRoute()}/0/${getDefaultStartDateForNewEvent()}/${getDefaultEndDateForNewEvent()}`,
|
||||
},
|
||||
{
|
||||
path: '/new/:allDay/:dtstart/:dtend',
|
||||
redirect: () => `/${getInitialView()}/:dtstart/new/${getPreferredEditorRoute()}/:allDay/:dtstart/:dtend`,
|
||||
},
|
||||
{
|
||||
path: '/edit/:object',
|
||||
redirect: `/${getInitialView()}/now/edit/sidebar/:object/next`,
|
||||
redirect: () => `/${getInitialView()}/now/edit/${getPreferredEditorRoute()}/:object/next`,
|
||||
},
|
||||
{
|
||||
path: '/edit/:object/:recurrenceId',
|
||||
redirect: `/${getInitialView()}/now/edit/sidebar/:object/:recurrenceId`,
|
||||
redirect: () => `/${getInitialView()}/now/edit/${getPreferredEditorRoute()}/:object/:recurrenceId`,
|
||||
},
|
||||
/**
|
||||
* This is the main route that contains the current view and viewed day
|
||||
* It has to be last, so that other routes starting with /p/, etc. match first
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
{
|
||||
path: '/:view/:firstDay',
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
*
|
||||
*/
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import {
|
||||
dateFactory,
|
||||
getUnixTimestampFromDate,
|
||||
} from './date.js'
|
||||
|
||||
/**
|
||||
* Gets the initial view
|
||||
|
@ -33,6 +37,56 @@ export function getInitialView() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the preferred editor view
|
||||
*
|
||||
* @returns {string} Either popover or sidebar
|
||||
*/
|
||||
export function getPreferredEditorRoute() {
|
||||
let skipPopover
|
||||
try {
|
||||
skipPopover = loadState('calendar', 'skip_popover')
|
||||
} catch (error) {
|
||||
skipPopover = false
|
||||
}
|
||||
|
||||
if (window.innerWidth <= 768) {
|
||||
skipPopover = true
|
||||
}
|
||||
|
||||
return skipPopover
|
||||
? 'sidebar'
|
||||
: 'popover'
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default start-date for a new event
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getDefaultStartDateForNewEvent() {
|
||||
const start = dateFactory()
|
||||
start.setHours(start.getHours() + Math.ceil(start.getMinutes() / 60))
|
||||
start.setMinutes(0)
|
||||
|
||||
return String(getUnixTimestampFromDate(start))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default end-date for a new event
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getDefaultEndDateForNewEvent() {
|
||||
// When we have a setting for default event duration,
|
||||
// this needs to be taken into consideration here
|
||||
const start = getDefaultStartDateForNewEvent()
|
||||
const end = new Date(Number(start) * 1000)
|
||||
end.setHours(end.getHours() + 1)
|
||||
|
||||
return String(getUnixTimestampFromDate(end))
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefixes a desired route name based on the current route
|
||||
*
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
*/
|
||||
import {
|
||||
getInitialView,
|
||||
getPrefixedRoute, isPublicOrEmbeddedRoute
|
||||
getPrefixedRoute,
|
||||
isPublicOrEmbeddedRoute,
|
||||
getPreferredEditorRoute,
|
||||
} from '../../../../src/utils/router.js'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
|
||||
|
@ -29,6 +31,10 @@ jest.mock('@nextcloud/initial-state')
|
|||
|
||||
describe('utils/router test suite', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
loadState.mockClear()
|
||||
})
|
||||
|
||||
it('should get the initial view', () => {
|
||||
loadState
|
||||
.mockReturnValueOnce('dayGridView')
|
||||
|
@ -42,6 +48,42 @@ describe('utils/router test suite', () => {
|
|||
expect(loadState).toHaveBeenNthCalledWith(2, 'calendar', 'initial_view')
|
||||
})
|
||||
|
||||
it('should get the preferred editor view (big screens)', () => {
|
||||
window.innerWidth = 1920
|
||||
|
||||
loadState
|
||||
.mockReturnValueOnce(true)
|
||||
.mockReturnValueOnce(false)
|
||||
.mockImplementationOnce(() => { throw new Error() })
|
||||
|
||||
expect(getPreferredEditorRoute()).toEqual('sidebar')
|
||||
expect(getPreferredEditorRoute()).toEqual('popover')
|
||||
expect(getPreferredEditorRoute()).toEqual('popover')
|
||||
|
||||
expect(loadState).toHaveBeenCalledTimes(3)
|
||||
expect(loadState).toHaveBeenNthCalledWith(1, 'calendar', 'skip_popover')
|
||||
expect(loadState).toHaveBeenNthCalledWith(2, 'calendar', 'skip_popover')
|
||||
expect(loadState).toHaveBeenNthCalledWith(3, 'calendar', 'skip_popover')
|
||||
})
|
||||
|
||||
it('should get the preferred editor view (small screens)', () => {
|
||||
window.innerWidth = 760
|
||||
|
||||
loadState
|
||||
.mockReturnValueOnce(true)
|
||||
.mockReturnValueOnce(false)
|
||||
.mockImplementationOnce(() => { throw new Error() })
|
||||
|
||||
expect(getPreferredEditorRoute()).toEqual('sidebar')
|
||||
expect(getPreferredEditorRoute()).toEqual('sidebar')
|
||||
expect(getPreferredEditorRoute()).toEqual('sidebar')
|
||||
|
||||
expect(loadState).toHaveBeenCalledTimes(3)
|
||||
expect(loadState).toHaveBeenNthCalledWith(1, 'calendar', 'skip_popover')
|
||||
expect(loadState).toHaveBeenNthCalledWith(2, 'calendar', 'skip_popover')
|
||||
expect(loadState).toHaveBeenNthCalledWith(3, 'calendar', 'skip_popover')
|
||||
})
|
||||
|
||||
it('should provide the prefixed route name to navigate to', () => {
|
||||
expect(getPrefixedRoute('PublicCalendarView', 'EditPopoverView')).toEqual('PublicEditPopoverView')
|
||||
expect(getPrefixedRoute('PublicEditPopoverView', 'CalendarView')).toEqual('PublicCalendarView')
|
||||
|
|
Loading…
Reference in New Issue