Allow to create talk rooms from calendar

Signed-off-by: Georg Ehrke <developer@georgehrke.com>
This commit is contained in:
Georg Ehrke 2019-12-17 14:38:03 +01:00
parent e13c352134
commit 7a8f32d124
No known key found for this signature in database
GPG Key ID: 9D98FD9380A1CB43
8 changed files with 158 additions and 3 deletions

View File

@ -22,11 +22,13 @@ declare(strict_types=1);
*/
namespace OCA\Calendar\Controller;
use OCP\App\IAppManager;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\Notification\IApp;
/**
* Class ViewController
@ -45,19 +47,27 @@ class ViewController extends Controller {
*/
private $userId;
/**
* @var IAppManager
*/
private $appManager;
/**
* @param string $appName
* @param IRequest $request an instance of the request
* @param IAppManager $appManager
* @param IConfig $config
* @param string $userId
*/
public function __construct(string $appName,
IRequest $request,
IConfig $config,
IAppManager $appManager,
string $userId) {
parent::__construct($appName, $request);
$this->config = $config;
$this->userId = $userId;
$this->appManager = $appManager;
}
/**
@ -76,6 +86,7 @@ class ViewController extends Controller {
'show_weekends' => $this->config->getUserValue($this->userId, $this->appName, 'showWeekends', 'yes') === 'yes',
'show_week_numbers' => $this->config->getUserValue($this->userId, $this->appName, 'showWeekNr', 'no') === 'yes',
'skip_popover' => $this->config->getUserValue($this->userId, $this->appName, 'skipPopover', 'no') === 'yes',
'talk_enabled' => $this->appManager->isEnabledForUser('spreed'),
'timezone' => $this->config->getUserValue($this->userId, $this->appName, 'timezone', 'automatic'),
]);
}

4
package-lock.json generated
View File

@ -5276,7 +5276,7 @@
},
"calendar-js": {
"version": "git+https://github.com/georgehrke/calendar-js.git#c1bf1a23b0422416390c58aede640f280cdc1c78",
"from": "git+https://github.com/georgehrke/calendar-js.git#c1bf1a23b0422416390c58aede640f280cdc1c78",
"from": "git+https://github.com/georgehrke/calendar-js.git",
"requires": {
"ical.js": "^1.3.0",
"uuid": "^3.3.3"
@ -5347,7 +5347,7 @@
},
"cdav-library": {
"version": "github:nextcloud/cdav-library#723e23686b20fb095a36a56ba69032c08318abfc",
"from": "github:nextcloud/cdav-library#723e23686b20fb095a36a56ba69032c08318abfc",
"from": "github:nextcloud/cdav-library",
"requires": {
"@babel/polyfill": "^7.7.0"
}

View File

@ -43,15 +43,23 @@
v-if="!isReadOnly && isListEmpty && hasUserEmailAddress" />
<OrganizerNoEmailError
v-if="!isReadOnly && isListEmpty && !hasUserEmailAddress" />
<button
v-if="isCreateTalkRoomButtonVisible"
:disabled="isCreateTalkRoomButtonDisabled"
@click="createTalkRoom">
{{ $t('calendar', 'Create Talk room for this event') }}
</button>
</div>
</template>
<script>
import { mapState } from 'vuex'
import InviteesListSearch from './InviteesListSearch'
import InviteesListItem from './InviteesListItem'
import OrganizerListItem from './OrganizerListItem'
import NoInviteesView from './NoInviteesView.vue'
import OrganizerNoEmailError from './OrganizerNoEmailError.vue'
import { createTalkRoom, doesDescriptionContainTalkLink } from '../../../services/talkService.js'
export default {
name: 'InviteesList',
@ -72,7 +80,15 @@ export default {
required: true,
},
},
data() {
return {
creatingTalkRoom: false,
}
},
computed: {
...mapState({
talkEnabled: state => state.settings.talkEnabled,
}),
inviteesWithoutOrganizer() {
if (!this.calendarObjectInstance.organizer) {
return this.calendarObjectInstance.attendees
@ -127,6 +143,20 @@ export default {
return !!principal.emailAddress
},
isCreateTalkRoomButtonVisible() {
return this.talkEnabled
},
isCreateTalkRoomButtonDisabled() {
if (this.creatingTalkRoom) {
return true
}
if (doesDescriptionContainTalkLink(this.calendarObjectInstance.description)) {
return true
}
return false
},
},
methods: {
addAttendee({ commonName, email, calendarUserType, language, timezoneId }) {
@ -161,6 +191,31 @@ export default {
attendee,
})
},
async createTalkRoom() {
const NEW_LINE = '\r\n'
try {
this.creatingTalkRoom = true
const url = await createTalkRoom(this.calendarObjectInstance.title)
let newDescription
if (!this.calendarObjectInstance.description) {
newDescription = url + NEW_LINE
} else {
newDescription = this.calendarObjectInstance.description + NEW_LINE + NEW_LINE + url + NEW_LINE
}
this.$store.commit('changeDescription', {
calendarObjectInstance: this.calendarObjectInstance,
description: newDescription,
})
this.$toast.success(this.$t('calendar', 'Successfully appended link to talk room to description.'))
} catch (error) {
this.$toast.error(this.$t('calendar', 'Error creating Talk room'))
} finally {
this.creatingTalkRoom = false
}
},
},
}
</script>

View File

@ -0,0 +1,75 @@
/**
* @copyright Copyright (c) 2019 Georg Ehrke
*
* @author Team Popcorn <teampopcornberlin@gmail.com>
* @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 HTTPClient from '@nextcloud/axios'
import { translate as t } from '@nextcloud/l10n'
import { generateUrl, generateOcsUrl } from '@nextcloud/router'
/**
* Creates a new public talk room
*
* @param {String?} eventTitle Title of the event
* @returns {Promise<String>}
*/
export async function createTalkRoom(eventTitle = null) {
let response
try {
response = await HTTPClient.post(generateOcsUrl('apps/spreed/api/v1', 2) + `room`, {
roomType: 3,
roomName: eventTitle || t('calendar', 'Chat room for event'),
})
const conversation = response.data.ocs.data
const token = conversation.token
return generateURLForToken(token)
} catch (error) {
console.debug(error)
}
}
/**
* Checks whether the description already contains a talk link
*
* @param {String?} description Description of event
* @returns {boolean}
*/
export function doesDescriptionContainTalkLink(description) {
if (!description) {
return false
}
// TODO: there is most definitely a more reliable way,
// but this works for now
const fakeUrl = generateURLForToken()
return description.includes(fakeUrl)
}
/**
* Generates an absolute URL to the talk room based on the token
*
* @param {String} token The token to the call room
* @returns {string}
*/
function generateURLForToken(token = '') {
return window.location.protocol + '//' + window.location.host + generateUrl('/call/' + token)
}

View File

@ -33,6 +33,7 @@ const state = {
showWeekends: null,
showWeekNumbers: null,
skipPopover: null,
talkEnabled: false,
timezone: null,
}
@ -90,6 +91,7 @@ const mutations = {
state.showWeekNumbers = settings.showWeekNumbers
state.showWeekends = settings.showWeekends
state.skipPopover = settings.skipPopover
state.talkEnabled = settings.talkEnabled
state.timezone = settings.timezone
},

View File

@ -289,6 +289,7 @@ export default {
showWeekends: getConfigValueFromHiddenInput('show-weekends') === 'true',
showWeekNumbers: getConfigValueFromHiddenInput('show-week-numbers') === 'true',
skipPopover: getConfigValueFromHiddenInput('skip-popover') === 'true',
talkEnabled: getConfigValueFromHiddenInput('talk-enabled') === 'true',
timezone: getConfigValueFromHiddenInput('timezone'),
})
this.$store.dispatch('initializeCalendarJsConfig')

View File

@ -29,4 +29,5 @@ style('calendar', 'calendar');
<input type="hidden" id="config-show-weekends" value="<?php p($_['show_weekends'] ? 'true' : 'false'); ?>">
<input type="hidden" id="config-show-week-numbers" value="<?php p($_['show_week_numbers'] ? 'true' : 'false'); ?>">
<input type="hidden" id="config-skip-popover" value="<?php p($_['skip_popover'] ? 'true' : 'false'); ?>">
<input type="hidden" id="config-talk-enabled" value="<?php p($_['talk_enabled'] ? 'true' : 'false'); ?>">
<input type="hidden" id="config-timezone" value="<?php p($_['timezone']); ?>">

View File

@ -22,6 +22,7 @@ declare(strict_types=1);
*/
namespace OCA\Calendar\Controller;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
use OCP\IRequest;
@ -35,6 +36,9 @@ class ViewControllerTest extends TestCase {
/** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */
private $request;
/** @var IAppManager|\PHPUnit_Framework_MockObject_MockObject */
private $appManager;
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
private $config;
@ -47,11 +51,12 @@ class ViewControllerTest extends TestCase {
protected function setUp():void {
$this->appName = 'calendar';
$this->request = $this->createMock(IRequest::class);
$this->appManager = $this->createMock(IAppManager::class);
$this->config = $this->createMock(IConfig::class);
$this->userId = 'user123';
$this->controller = new ViewController($this->appName, $this->request,
$this->config, $this->userId);
$this->config, $this->appManager, $this->userId);
}
public function testIndex():void {
@ -83,6 +88,10 @@ class ViewControllerTest extends TestCase {
->method('getUserValue')
->with('user123', 'calendar', 'timezone', 'automatic')
->willReturn('Europe/Berlin');
$this->appManager->expects($this->at(0))
->method('isEnabledForUser')
->with('spreed')
->willReturn(true);
$response = $this->controller->index();
@ -94,6 +103,7 @@ class ViewControllerTest extends TestCase {
'show_weekends' => true,
'show_week_numbers' => true,
'skip_popover' => true,
'talk_enabled' => true,
'timezone' => 'Europe/Berlin',
], $response->getParams());
$this->assertEquals('user', $response->getRenderAs());