Skip to content
Snippets Groups Projects
Commit d2c7c69e authored by Jan-Hendrik Willms's avatar Jan-Hendrik Willms
Browse files

integration complete

parent 52e6ca9c
No related branches found
No related tags found
1 merge request!14Draft: Data vue app
......@@ -113,19 +113,13 @@ class MyCoursesController extends AuthenticatedController
}
$this->setupSidebar($sem_key, $group_field, $this->check_for_new($sem_courses, $group_field));
$data = $this->getMyCoursesData($sem_courses, $group_field);
PageLayout::addHeadElement(
'script',
['type' => 'text/javascript'],
'window.STUDIP.MyCoursesData = ' . json_encode($data) . ';'
);
$this->render_vue_app(
Studip\VueApp::create('MyCourses')
->withStore('MyCoursesStore')
->withStoreData('mycourses', $data)
);
$this->vueApp = Studip\VueApp::create('MyCourses')
->withStore(
'MyCoursesStore',
'mycourses',
$this->getMyCoursesData($sem_courses, $group_field)
);
}
/**
......@@ -803,10 +797,10 @@ class MyCoursesController extends AuthenticatedController
}
return [
'courses' => $this->sanitizeNavigations(array_map([$this, 'convertCourse'], $temp_courses)),
'groups' => $groups,
'user_id' => $GLOBALS['user']->id,
'config' => [
'setCourses' => $this->sanitizeNavigations(array_map([$this, 'convertCourse'], $temp_courses)),
'setGroups' => $groups,
'setUserId' => $GLOBALS['user']->id,
'setConfig' => [
'allow_dozent_visibility' => Config::get()->ALLOW_DOZENT_VISIBILITY,
'open_groups' => array_values($GLOBALS['user']->cfg->MY_COURSES_OPEN_GROUPS),
'sem_number' => Config::get()->IMPORTANT_SEMNUMBER,
......
<?php
/**
* @var Studip\VueApp $vueApp
* @var array $my_bosses
* @var array $waiting_list
*/
?>
<? if ($waiting_list) : ?>
<?= $this->render_partial('my_courses/waiting_list.php', compact('waiting_list')) ?>
<? endif ?>
<div class="my-courses-vue-app">
<my-courses />
</div>
<?= $vueApp->render() ?>
<? if (count($my_bosses) > 0) : ?>
<?= $this->render_partial('my_courses/_deputy_bosses'); ?>
......
......@@ -590,41 +590,7 @@ abstract class StudipController extends Trails\Controller
public function render_vue_app(\Studip\VueApp $app): void
{
$attributes = [
'data-vue-app' => json_encode([
'components' => [$app->getBaseComponent()],
'store' => $app->getStore(),
]),
'is' => $app->getBaseComponent(),
...$app->getProps(),
];
$content = '';
if ($app->getStoreData()) {
$content .= '<script>';
foreach ($app->getStoreData() as $key => $data) {
$content .= sprintf(
"window.STUDIP.Vue.setStoreData('%s', %s);",
$key,
json_encode($data),
);
}
$content .= '</script>';
}
$content .= '<div ' . arrayToHtmlAttributes($attributes) . '></div>';
if ($this->layout) {
$content = $this->get_template_factory()->render(
$this->layout,
['content_for_layout' => $content]
);
}
$this->render_text($content);
$this->render_template($app->getTemplate(), $this->layout);
}
/**
......
<?php
namespace Studip;
class VueApp
use Flexi\Template;
use Stringable;
final class VueApp implements Stringable
{
public static function create(string $base_component, array $props = []): VueApp
{
return new self($base_component, $props);
}
protected ?string $store = null;
protected array $storeData = [];
private array $components = [];
private array $stores = [];
private array $storeData = [];
public function __construct(
protected string $base_component,
protected array $props = []
private function __construct(
private string $base_component,
private array $props = []
) {
}
public function withBaseComponent(string $base_component): VueApp
{
$this->base_component = $base_component;
return $this;
$clone = clone $this;
$clone->base_component = $base_component;
return $clone;
}
public function withComponents(string ...$components): VueApp
{
$clone = clone $this;
foreach ($components as $component) {
$clone = $clone->withAddedComponent($component);
}
return $clone;
}
public function withAddedComponent(string $component): VueApp
{
$clone = clone $this;
if (!in_array($component, $clone->components)) {
$clone->components[] = $component;
}
return $clone;
}
public function getBaseComponent(): string
......@@ -30,8 +54,9 @@ class VueApp
public function withProps(array $props): VueApp
{
$this->props = $props;
return $this;
$clone = clone $this;
$clone->props = $props;
return $clone;
}
public function getProps(): array
......@@ -39,25 +64,52 @@ class VueApp
return $this->props;
}
public function withStore(?string $store): VueApp
public function withStore(?string $store, ?string $index = null, ?array $data = null): VueApp
{
$this->store = $store;
return $this;
}
$clone = clone $this;
public function getStore(): ?string
{
return $this->store;
$clone->stores[$index ?? $store] = $store;
if ($data !== null) {
$clone->storeData[$index ?? $store] = $data;
}
return $clone;
}
public function withStoreData(string $key, array $data): VueApp
public function getStores(): array
{
$this->storeData[$key] = $data;
return $this;
return $this->stores;
}
public function getStoreData(): array
{
return $this->storeData;
}
public function getTemplate(): Template
{
$template = $GLOBALS['template_factory']->open('vue-app.php');
$template->attributes = [
'data-vue-app' => json_encode([
'components' => [$this->base_component, ...$this->components],
'stores' => $this->stores,
]),
'is' => $this->base_component,
...$this->props,
];
$template->storeData = $this->storeData;
return $template;
}
public function render(): string
{
return $this->getTemplate()->render();
}
public function __toString(): string
{
return $this->render();
}
}
import MyCourses from '../../../vue/components/MyCourses.vue';
import storeConfig from '../../../vue/store/MyCoursesStore.js';
STUDIP.domReady(async () => {
if ($('.my-courses-vue-app').length === 0) {
return;
}
const { createApp, store } = await STUDIP.Vue.load();
store.registerModule('mycourses', storeConfig);
store.commit('mycourses/setCourses', window.STUDIP.MyCoursesData['courses']);
store.commit('mycourses/setGroups', window.STUDIP.MyCoursesData['groups']);
store.commit('mycourses/setUserId', window.STUDIP.MyCoursesData['user_id']);
store.commit('mycourses/setConfig', window.STUDIP.MyCoursesData['config']);
const vm = createApp({
components: { MyCourses }
});
vm.$mount('.my-courses-vue-app');
});
......@@ -6,21 +6,14 @@
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
*/
STUDIP.ready(() => {
$('[data-vue-app]').each(function () {
if ($(this).is('[data-vue-app-created]')) {
return;
}
const config = Object.assign({}, {
id: false,
components: [],
store: false
}, $(this).data().vueApp);
let data = {};
if (config.id && window.STUDIP.AppData && window.STUDIP.AppData[config.id] !== undefined) {
data = window.STUDIP.AppData[config.id];
}
document.querySelectorAll('[data-vue-app]:not([data-vue-app-created])').forEach((node) => {
const config = Object.assign(
{
components: [],
stores: {}
},
JSON.parse(node.dataset.vueApp)
);
let components = {};
config.components.forEach(component => {
......@@ -28,29 +21,51 @@ STUDIP.ready(() => {
});
STUDIP.Vue.load().then(async ({createApp, store}) => {
let vm;
if (config.store) {
const storeConfig = await import(`../../../vue/store/${config.store}.js`);
console.log('store', storeConfig.default);
for (const [index, name] of Object.entries(config.stores)) {
import(`../../../vue/store/${name}.js`).then(storeConfig => {
store.registerModule(index, storeConfig.default);
store.registerModule(config.id, storeConfig.default);
Object.keys(data).forEach(command => {
store.commit(`${config.id}/${command}`, data[command]);
const dataElement = document.getElementById(`vue-store-data-${index}`);
if (dataElement) {
const data = JSON.parse(dataElement.innerText);
Object.keys(data).forEach(command => {
store.commit(`${index}/${command}`, data[command]);
});
}
});
vm = createApp({components});
} else {
vm = createApp({data, components});
}
// import myCoursesStore from '../stores/MyCoursesStore.js';
//
// myCoursesStore.namespaced = true;
//
// store.registerModule('my-courses', myCoursesStore);
createApp({
components,
store,
vm.$mount(this);
beforeCreate() {
STUDIP.Vue.emit('VueAppWillCreate', this);
},
created() {
STUDIP.Vue.emit('VueAppDidCreate', this);
},
beforeMount() {
STUDIP.Vue.emit('VueAppWillMount', this);
},
mounted() {
STUDIP.Vue.emit('VueAppDidMount', this);
},
beforeUpdate() {
STUDIP.Vue.emit('VueAppWillUpdate', this);
},
updated() {
STUDIP.Vue.emit('VueAppDidUpdate', this);
},
beforeDestroy() {
STUDIP.Vue.emit('VueAppWillDestroy', this);
},
destroyed() {
STUDIP.Vue.emit('VueAppDidDestroy', this);
},
}).$mount(node);
});
$(this).attr('data-vue-app-created', '');
node.dataset.vueAppCreated = 'true';
});
});
......@@ -16,8 +16,6 @@ import "./init.js"
import "./bootstrap/responsive.js"
import "./bootstrap/vue.js"
import "./bootstrap/my-courses.js";
import "./studip-ui.js"
import "./bootstrap/fullscreen.js"
import "./bootstrap/tfa.js"
......
class Vue
{
static #storeData = {};
static async load()
{
return STUDIP.loadChunk('vue');
......@@ -18,16 +16,6 @@ class Vue
const { eventBus } = await this.load();
eventBus.emit(...args);
}
static setStoreData(key, data)
{
this.#storeData[key] = data;
}
static getStoreData(key)
{
return this.#storeData[key] ?? null;
}
}
export default Vue;
<?php
/**
* @var array $attributes
* @var array $storeData
*/
?>
<? foreach ($storeData as $store => $data): ?>
<script type="application/json" id="vue-store-data-<?= htmlReady($store) ?>"><?= json_encode($data) ?></script>
<? endforeach; ?>
<div <?= arrayToHtmlAttributes($attributes) ?>></div>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment