diff --git a/Build/Vue/src/App.tsx b/Build/Vue/src/App.tsx
index 0b15af3..5ffbb25 100644
--- a/Build/Vue/src/App.tsx
+++ b/Build/Vue/src/App.tsx
@@ -1,23 +1,30 @@
+import {AjaxRoutes} from '@/enums/AjaxRoutes';
+import {StorageInterface} from '@/interfaces/StorageInterface';
import {Component, Vue} from 'vue-property-decorator';
import {CreateElement, VNode} from 'vue';
import TreePanel from '@/components/TreePanel';
import ContentPanel from '@/components/ContentPanel';
-import {Action} from 'vuex-class';
-import {AjaxRoutes} from '@/enums/AjaxRoutes';
+import {Action, State} from 'vuex-class';
@Component
export default class App extends Vue {
+ @Action(AjaxRoutes.damGetStoragesAndMounts)
+ getStorages!: Function;
+
@Action(AjaxRoutes.damGetFolderItems)
fetchData: any;
+ @State
+ activeStorage!: StorageInterface;
- // lifecycle method
mounted(): void {
- // root content area - dummy
- this.fetchData('1:/');
+ this.getStorages();
}
- private render(h: CreateElement): VNode {
+ private render(h: CreateElement): VNode | null {
+ if (!this.activeStorage) {
+ return null;
+ }
return (
diff --git a/Build/Vue/src/components/Breadcrumb/index.tsx b/Build/Vue/src/components/Breadcrumb/index.tsx
index 11c7518..ca294c3 100644
--- a/Build/Vue/src/components/Breadcrumb/index.tsx
+++ b/Build/Vue/src/components/Breadcrumb/index.tsx
@@ -14,6 +14,9 @@ export default class Breadcrumb extends Vue {
@State
current!: String;
+ @State
+ showTree!: boolean;
+
@Action(AjaxRoutes.damGetFolderItems)
fetchData: any;
@@ -39,7 +42,7 @@ export default class Breadcrumb extends Vue {
});
return (
-
+ {!this.showTree ? : ''}
{items}
);
diff --git a/Build/Vue/src/components/ContentPanel/index.tsx b/Build/Vue/src/components/ContentPanel/index.tsx
index ccaf89c..a064b83 100644
--- a/Build/Vue/src/components/ContentPanel/index.tsx
+++ b/Build/Vue/src/components/ContentPanel/index.tsx
@@ -1,3 +1,4 @@
+import {StorageInterface} from '@/interfaces/StorageInterface';
import {Component, Prop, Vue} from 'vue-property-decorator';
import {VNode} from 'vue';
import DocHeader from '@/components/DocHeader';
@@ -42,6 +43,9 @@ export default class ContentPanel extends Vue {
@Action(AjaxRoutes.damGetFolderItems)
fetchData: any;
+ @State
+ activeStorage!: StorageInterface;
+
@State
items: any;
@@ -58,6 +62,14 @@ export default class ContentPanel extends Vue {
super(props);
}
+ get browsableIdentifier(): string {
+ return this.activeStorage.identifier + ':/';
+ }
+
+ mounted(): void {
+ this.fetchData(this.browsableIdentifier);
+ }
+
private renderFileTiles(): VNode | null {
return this.files ?
: null;
}
diff --git a/Build/Vue/src/components/Icon/index.tsx b/Build/Vue/src/components/Icon/index.tsx
new file mode 100644
index 0000000..aee81bc
--- /dev/null
+++ b/Build/Vue/src/components/Icon/index.tsx
@@ -0,0 +1,24 @@
+import {VNode} from 'vue';
+import {Component, Prop, Vue} from 'vue-property-decorator';
+import Icons from 'TYPO3/CMS/Backend/Icons';
+
+@Component
+export default class Icon extends Vue {
+ @Prop()
+ identifier!: string;
+
+ private icon: VNode | null = null;
+
+ constructor(props: any) {
+ super(props);
+ }
+
+ async mounted(): Promise
{
+ const iconRaw = await Icons.getIcon(this.$props.identifier, Icons.sizes.small, null, null, 'inline');
+ this.icon = ;
+ }
+
+ private render(): VNode | null {
+ return this.icon;
+ }
+}
diff --git a/Build/Vue/src/components/StorageSelector/index.tsx b/Build/Vue/src/components/StorageSelector/index.tsx
index 49623c9..06a3743 100644
--- a/Build/Vue/src/components/StorageSelector/index.tsx
+++ b/Build/Vue/src/components/StorageSelector/index.tsx
@@ -1,30 +1,114 @@
+import Icon from '@/components/Icon';
import {Mutations} from '@/enums/Mutations';
+import {StorageInterface} from '@/interfaces/StorageInterface';
import {Component, Vue} from 'vue-property-decorator';
import {VNode} from 'vue';
-import {Action} from 'vuex-class';
+import {Action, State} from 'vuex-class';
@Component
export default class StorageSelector extends Vue {
@Action(Mutations.SET_STORAGE)
setStorage!: Function;
+ @State
+ storages!: Array;
+
+ @State
+ activeStorage!: StorageInterface;
+
constructor(props: any) {
super(props);
}
- private render(): VNode {
+ private static toggleDropdown(e: Event): void {
+ const me = (e.target as HTMLElement);
+ const dropdown = me.closest('.component-dropdown');
+ if (dropdown === null) {
+ return;
+ }
+
+ let isActive = dropdown.classList.contains('component-dropdown-active');
+ dropdown.classList.toggle('component-dropdown-active', !isActive);
+ dropdown.classList.toggle('component-dropdown-inactive', isActive);
+
+ const dropdownToggle = dropdown.querySelector('.component-dropdown-toggle');
+ if (dropdownToggle !== null) {
+ dropdownToggle.setAttribute('aria-expanded', (!isActive).toString());
+ }
+ }
+
+ private static getBrowsableIdentifier(identifier: number): string {
+ return identifier + ':/';
+ }
+
+ private render(): VNode | null {
+ if (!this.storages.length) {
+ return null;
+ }
+
+ const options = this.storages.map(this.generateOption, this);
return (
-
-
-
+
+
+
+
+
+
+ );
+ }
+
+ private generateOption(storage: StorageInterface): VNode {
+ return(
+
);
}
private updateStorage(e: Event): void {
- const selectedStorage = (e.target as HTMLSelectElement).selectedOptions[0].value;
- this.setStorage(selectedStorage);
+ const me = (e.target as HTMLElement);
+ const link = me.closest('a');
+ if (link === null || typeof link.dataset.identifier === 'undefined') {
+ return;
+ }
+
+ const storageId = parseInt(link.dataset.identifier, 10);
+ if (storageId !== this.activeStorage.identifier) {
+ this.setStorage({
+ id: storageId,
+ browsableIdentifier: StorageSelector.getBrowsableIdentifier(storageId),
+ });
+ }
}
}
diff --git a/Build/Vue/src/components/Tree/index.tsx b/Build/Vue/src/components/Tree/index.tsx
index b13aa09..eb08afe 100644
--- a/Build/Vue/src/components/Tree/index.tsx
+++ b/Build/Vue/src/components/Tree/index.tsx
@@ -15,7 +15,10 @@ export default class Tree extends Vue {
fetchTreeData: any;
@State
- storage!: StorageInterface;
+ activeStorage!: StorageInterface;
+
+ @State
+ treeFolders!: Array;
private draggableService: DraggableService;
@@ -29,22 +32,22 @@ export default class Tree extends Vue {
this.draggableService = new DraggableService(configuration);
}
+ get browsableIdentifier(): string {
+ return this.activeStorage.identifier + ':/';
+ }
+
mounted(): void {
- this.fetchTreeData(this.storage.identifier);
this.draggableService.makeDraggable();
+ this.fetchTreeData(this.browsableIdentifier);
}
- private render(h: CreateElement): VNode|null {
- if (!this.storage.folders) {
- return null;
- }
-
- const nodes = [this.storage.folders].map(this.generateNodes, this);
+ private render(h: CreateElement): VNode | null {
+ const nodes = [this.treeFolders].map(this.generateNodes, this);
return(
diff --git a/Build/Vue/src/components/TreePanel/index.tsx b/Build/Vue/src/components/TreePanel/index.tsx
index 8aa48e5..11d0e84 100644
--- a/Build/Vue/src/components/TreePanel/index.tsx
+++ b/Build/Vue/src/components/TreePanel/index.tsx
@@ -3,6 +3,7 @@ import {VNode} from 'vue';
import DocHeader from '@/components/DocHeader';
import Tree from '@/components/Tree';
import StorageSelector from '@/components/StorageSelector';
+import {StorageInterface} from '@/interfaces/StorageInterface';
import {State} from 'vuex-class';
@Component
@@ -10,6 +11,9 @@ export default class TreePanel extends Vue {
@State
showTree!: boolean;
+ @State
+ activeStorage!: StorageInterface;
+
constructor(props: any) {
super(props);
}
@@ -19,17 +23,13 @@ export default class TreePanel extends Vue {
}
private render(): VNode|null {
- if (!this.shallShowTree) {
- return null;
- }
-
return (
-
+
-
+ {this.activeStorage ? : ''}
);
diff --git a/Build/Vue/src/components/TreeRootNode/index.tsx b/Build/Vue/src/components/TreeRootNode/index.tsx
index 955e2a6..c81e689 100644
--- a/Build/Vue/src/components/TreeRootNode/index.tsx
+++ b/Build/Vue/src/components/TreeRootNode/index.tsx
@@ -1,26 +1,31 @@
+import Icon from '@/components/Icon';
import {AjaxRoutes} from '@/enums/AjaxRoutes';
import {StorageInterface} from '@/interfaces/StorageInterface';
import {CreateElement, VNode} from 'vue';
-import {Action, State} from 'vuex-class';
-import {Component, Vue} from 'vue-property-decorator';
+import {Action} from 'vuex-class';
+import {Component, Prop, Vue} from 'vue-property-decorator';
@Component
export default class TreeNode extends Vue {
@Action(AjaxRoutes.damGetFolderItems)
fetchData: any;
- @State
+ @Prop()
storage!: StorageInterface;
constructor(props: any) {
super(props);
}
+ get browsableIdentifier(): string {
+ return this.storage.identifier + ':/';
+ }
+
private render(h: CreateElement): VNode {
return(
-
- this.fetchData(this.storage.identifier)}>
- {this.storage.title}
+
+ this.fetchData(this.browsableIdentifier)}>
+ {this.storage.storageName}
);
diff --git a/Build/Vue/src/enums/Mutations.ts b/Build/Vue/src/enums/Mutations.ts
index 12710d8..a626769 100644
--- a/Build/Vue/src/enums/Mutations.ts
+++ b/Build/Vue/src/enums/Mutations.ts
@@ -10,5 +10,6 @@ export enum Mutations {
CHANGE_SORTING = 'CHANGE_SORTING',
TOGGLE_TREE = 'TOGGLE_TREE',
SET_STORAGE = 'SET_STORAGE',
+ FETCH_STORAGES = 'FETCH_STORAGES',
FETCH_TREE_DATA = 'FETCH_TREE_DATA',
}
diff --git a/Build/Vue/src/interfaces/StorageInterface.ts b/Build/Vue/src/interfaces/StorageInterface.ts
index d3013e4..6b72e46 100644
--- a/Build/Vue/src/interfaces/StorageInterface.ts
+++ b/Build/Vue/src/interfaces/StorageInterface.ts
@@ -1,8 +1,9 @@
-import FolderTreeNode from '@/interfaces/FolderTreeNode';
-
export interface StorageInterface {
- folders: Array;
- title: string;
- identifier: string;
+ type: string;
+ identifier: number;
+ name: string;
+ storageName: string;
+ storageType: string;
+ storageOnline: boolean;
icon: string;
}
diff --git a/Build/Vue/src/store/store.ts b/Build/Vue/src/store/store.ts
index 9c9d591..93b841d 100644
--- a/Build/Vue/src/store/store.ts
+++ b/Build/Vue/src/store/store.ts
@@ -1,4 +1,5 @@
import FolderTreeNode from '@/interfaces/FolderTreeNode';
+import {StorageInterface} from '@/interfaces/StorageInterface';
import Vue from 'vue';
import Vuex, {StoreOptions} from 'vuex';
import {RootState} from 'types/types';
@@ -31,12 +32,9 @@ const options: StoreOptions = {
current: '',
viewMode: ViewType.TILE,
showTree: true,
- storage: {
- folders: [],
- title: '/fileadmin',
- identifier: '1:/',
- icon: '/typo3/sysext/core/Resources/Public/Icons/T3Icons/apps/apps-filetree-mount.svg',
- },
+ activeStorage: null,
+ treeFolders: [],
+ storages: [],
treeIdentifierLocationMap: {},
},
mutations: {
@@ -56,8 +54,22 @@ const options: StoreOptions = {
state.itemsGrouped.files.sort(sortItems);
state.itemsGrouped.images.sort(sortItems);
},
- [Mutations.SET_STORAGE](state: RootState, identifier: string): void {
- state.storage.identifier = identifier;
+ [Mutations.FETCH_STORAGES](state: RootState, data: Array): void {
+ state.storages = data;
+
+ if (!state.activeStorage) {
+ // TODO: Set active storage by value stored in UC
+ state.activeStorage = data[0];
+ }
+ },
+ [Mutations.SET_STORAGE](state: RootState, identifier: number): void {
+ state.treeFolders = [];
+
+ for (let storage of state.storages) {
+ if (storage.identifier === identifier) {
+ state.activeStorage = storage;
+ }
+ }
},
[Mutations.SELECT_ITEM](state: RootState, identifier: String): void {
if (!state.selected.includes(identifier)) {
@@ -83,6 +95,10 @@ const options: StoreOptions = {
state.viewMode = viewMode;
},
[Mutations.FETCH_TREE_DATA](state: RootState, data: {identifier: string, folders: Array}): void {
+ if (!state.activeStorage) {
+ return;
+ }
+
const nestingStructure = state.treeIdentifierLocationMap[data.identifier] || [];
data.folders.forEach((node: FolderTreeNode, index: number): void => {
@@ -96,10 +112,10 @@ const options: StoreOptions = {
if (data.identifier.match(/^\d+:\/$/)) {
// Storage root requested
- state.storage.folders = data.folders;
+ state.treeFolders = data.folders;
} else {
let node;
- let folders = state.storage.folders;
+ let folders = state.treeFolders;
for (let index of nestingStructure) {
node = folders[index];
folders = folders[index].folders;
@@ -162,10 +178,14 @@ const options: StoreOptions = {
const response = await client.get(TYPO3.settings.ajaxUrls[AjaxRoutes.damGetTreeFolders] + '&identifier=' + identifier);
commit(Mutations.FETCH_TREE_DATA, {identifier: identifier, folders: response.data});
},
- async [Mutations.SET_STORAGE]({commit, dispatch}: any, identifier: string): Promise {
- commit(Mutations.SET_STORAGE, identifier);
- dispatch(AjaxRoutes.damGetFolderItems, identifier);
- dispatch(AjaxRoutes.damGetTreeFolders, identifier);
+ async [AjaxRoutes.damGetStoragesAndMounts]({commit}: any): Promise {
+ const response = await client.get(TYPO3.settings.ajaxUrls[AjaxRoutes.damGetStoragesAndMounts]);
+ commit(Mutations.FETCH_STORAGES, response.data);
+ },
+ async [Mutations.SET_STORAGE]({commit, dispatch}: any, data: {id: number, browsableIdentifier: string}): Promise {
+ commit(Mutations.SET_STORAGE, data.id);
+ dispatch(AjaxRoutes.damGetTreeFolders, data.browsableIdentifier);
+ dispatch(AjaxRoutes.damGetFolderItems, data.browsableIdentifier);
},
},
};
diff --git a/Build/Vue/tsconfig.json b/Build/Vue/tsconfig.json
index ea750fc..77702ed 100644
--- a/Build/Vue/tsconfig.json
+++ b/Build/Vue/tsconfig.json
@@ -17,9 +17,6 @@
"noImplicitReturns": true,
"pretty": false,
"baseUrl": ".",
- "types": [
- "requirejs", "webpack-env", "mocha", "chai"
- ],
"paths": {
"@/*": [
"src/*"
@@ -27,12 +24,12 @@
},
"lib": [
"esnext", "dom", "dom.iterable", "scripthost"
+ ],
+ "typeRoots": [
+ "./node_modules/@types",
+ "./types"
]
},
- "typesRoot": [
- "./node_modules/@types",
- "./types"
- ],
"include": [
"src/**/*.ts",
"src/**/*.tsx",
diff --git a/Build/Vue/types/TYPO3/index.d.ts b/Build/Vue/types/TYPO3/index.d.ts
index f927b63..d9355da 100644
--- a/Build/Vue/types/TYPO3/index.d.ts
+++ b/Build/Vue/types/TYPO3/index.d.ts
@@ -1,87 +1,4 @@
-/* tslint:disable:max-classes-per-file */
-
-/**
- * Currently a mixture between namespace and global object
- * Add types as you use them
- */
-declare namespace TYPO3 {
- export let Backend: any;
- export let DebugConsole: any;
- export let Icons: any;
- export let InfoWindow: any;
- export let LoginRefresh: any;
- export let ModuleMenu: any;
- export let Notification: any;
- export let Modal: any;
- export let OpendocsMenu: any;
- export let Permissions: any;
- export let Popover: any;
- export let Severity: any;
- export let ShortcutMenu: any;
- export let Storage: any;
- export let Tooltip: any;
- export let Utility: any;
- export let Wizard: any;
- export let settings: any;
- export const lang: { [key: string]: string };
- export const configuration: any;
- export namespace CMS {
- export namespace Backend {
- export class FormEngineValidation {
- public readonly errorClass: string;
- public markFieldAsChanged($field: JQuery): void;
- public initializeInputFields(): void;
- public validate(): void;
- }
-
- export class FormEngine {
- public readonly Validation: FormEngineValidation;
- public legacyFieldChangedCb(): void;
- public getFieldElement(fieldName: string, appendix?: string, noFallback?: boolean): JQuery;
- public updateHiddenFieldValueFromSelect(selectFieldEl: HTMLElement, originalFieldEl: HTMLElement): void;
- public preventFollowLinkIfNotSaved(href: string): boolean;
- public setSelectOptionFromExternalSource(
- fieldName: string,
- value: string,
- label: string,
- title: string,
- exclusiveValues?: string,
- $optionEl?: JQuery,
- ): void;
- public reinitialize(): void;
- }
-
- export class Wizard {
- public addSlide(identifier: string, title: string, content: string, severity: number, callback?: Function): Wizard;
- public lockNextStep(): JQuery;
- public unlockNextStep(): JQuery;
- public getComponent(): JQuery;
- public addFinalProcessingSlide(callback?: Function): JQueryXHR;
- public show(): Wizard;
- public dismiss(): Wizard;
- }
- }
- }
-}
-
-declare namespace TBE_EDITOR {
- export let fieldChanged: Function;
-}
-
-/**
- * Current AMD/RequireJS modules are returning *instances* of ad-hoc *classes*, make that known to TypeScript
- */
-declare module 'TYPO3/CMS/Backend/FormEngineValidation' {
- export = new TYPO3.CMS.Backend.FormEngineValidation();
-}
-
-declare module 'TYPO3/CMS/Backend/FormEngine' {
- export = new TYPO3.CMS.Backend.FormEngine();
-}
-
-declare module 'TYPO3/CMS/Backend/Wizard' {
- export = new TYPO3.CMS.Backend.Wizard();
-}
+declare module 'TYPO3/CMS/Backend/Icons';
// type definition for global namespace object
interface Window {
@@ -99,51 +16,4 @@ interface Window {
currentModuleLoaded: string;
fsMod: { [key: string]: any };
nextLoadModuleUrl: string;
-
- // required for Paste.ts
- // TODO these should be passed as data attributes
- pasteAfterLinkTemplate: string;
- pasteIntoLinkTemplate: string;
-}
-
-/**
- * Needed type declarations for provided libs
- */
-declare module 'TYPO3/CMS/Core/Contrib/imagesloaded.pkgd.min' {
- import * as imagesloaded from 'imagesloaded';
- export = imagesloaded;
-}
-
-declare module 'TYPO3/CMS/Recordlist/LinkBrowser';
-declare module 'TYPO3/CMS/Backend/LegacyTree';
-
-declare module 'cm/lib/codemirror';
-declare module 'moment';
-
-interface JQueryTypedEvent extends JQueryEventObject {
- originalEvent: T;
-}
-
-/**
- * Required to make jQuery plugins "available" in TypeScript
- */
-interface JQuery {
- clearable(options?: any): JQuery;
-
- chosen(options?: any): JQuery;
-
- datetimepicker(options?: any): JQuery;
-
- dragUploader(options?: any): JQuery;
-
- t3FormEngineFlexFormElement(options?: any): JQuery;
-
- // To be able to use twbs/bootstrap-slider we have to override the definition of jquerui
- slider(options: { [key: string]: any }): any;
-
- // To be able to use jquery/autocomplete-slider we have to override the definition of jquerui
- autocomplete(options?: { [key: string]: any }): any;
-
- DataTable(options?: any): JQuery;
-}
-
+}
\ No newline at end of file
diff --git a/Build/Vue/types/types.ts b/Build/Vue/types/types.ts
index af36704..5ea9f2d 100644
--- a/Build/Vue/types/types.ts
+++ b/Build/Vue/types/types.ts
@@ -1,3 +1,4 @@
+import FolderTreeNode from '@/interfaces/FolderTreeNode';
import {StorageInterface} from '@/interfaces/StorageInterface';
import {GroupedResourcesInterface} from '@/interfaces/GroupedResourcesInterface';
@@ -9,16 +10,15 @@ export interface RootState {
viewMode: String; // LIST_VIEW|TILE_VIEW
sorting: any;
showTree: boolean;
- storage: StorageInterface;
+ activeStorage: StorageInterface | null;
+ treeFolders: Array;
+ storages: Array;
treeIdentifierLocationMap: {[key: string]: Array};
}
declare global {
+ const TYPO3: any;
interface Window { TYPO3: any; }
}
window.TYPO3 = window.TYPO3 || {};
-
-declare global {
- const TYPO3: any;
-}
diff --git a/Build/Vue/vue.config.js b/Build/Vue/vue.config.js
index 059f78b..8b9e8fa 100644
--- a/Build/Vue/vue.config.js
+++ b/Build/Vue/vue.config.js
@@ -17,7 +17,8 @@ module.exports = {
amd: 'Vue',
root: 'Vue' // indicates global variable
},
- }
- ]
+ },
+ 'TYPO3/CMS/Backend/Icons',
+ ],
}
};
diff --git a/Classes/Entity/FileMount.php b/Classes/Entity/FileMount.php
index 5c20fb8..be0e714 100644
--- a/Classes/Entity/FileMount.php
+++ b/Classes/Entity/FileMount.php
@@ -49,6 +49,11 @@ class FileMount implements \JsonSerializable
*/
protected $storageOnline;
+ /**
+ * @var string Markup of the storage icon
+ */
+ protected $icon;
+
/**
* @param ResourceStorage $storage
* @param array $fileMount
@@ -60,6 +65,7 @@ public function __construct(ResourceStorage $storage, array $fileMount)
$this->storageName = $storage->getName();
$this->storageType = $storage->getDriverType();
$this->storageOnline = $storage->isOnline();
+ $this->icon = 'apps-filetree-mount';
}
public function jsonSerialize()
@@ -70,7 +76,8 @@ public function jsonSerialize()
'name' => $this->name,
'storageName' => $this->storageName,
'storageType' => $this->storageType,
- 'storageOnline' => $this->storageOnline
+ 'storageOnline' => $this->storageOnline,
+ 'icon' => $this->icon
];
}
}
\ No newline at end of file
diff --git a/Classes/Entity/Storage.php b/Classes/Entity/Storage.php
index 39c6033..4015a49 100644
--- a/Classes/Entity/Storage.php
+++ b/Classes/Entity/Storage.php
@@ -48,6 +48,11 @@ class Storage implements \JsonSerializable
*/
protected $storageOnline;
+ /**
+ * @var string Markup of the storage icon
+ */
+ protected $icon;
+
/**
* @param ResourceStorage $storage
*/
@@ -57,6 +62,7 @@ public function __construct(ResourceStorage $storage)
$this->name = $this->storageName = $storage->getName();
$this->storageType = $storage->getDriverType();
$this->storageOnline = $storage->isOnline();
+ $this->icon = 'apps-filetree-root';
}
public function jsonSerialize()
@@ -67,7 +73,8 @@ public function jsonSerialize()
'name' => $this->name,
'storageName' => $this->storageName,
'storageType' => $this->storageType,
- 'storageOnline' => $this->storageOnline
+ 'storageOnline' => $this->storageOnline,
+ 'icon' => $this->icon
];
}
}
\ No newline at end of file
diff --git a/Resources/Private/Language/locallang_vue.xlf b/Resources/Private/Language/locallang_vue.xlf
index cb1b9ba..7933e59 100644
--- a/Resources/Private/Language/locallang_vue.xlf
+++ b/Resources/Private/Language/locallang_vue.xlf
@@ -24,6 +24,12 @@
+
+
+
+
+
+