From 4fff9d3123d3c86ef63324e9877101b23b711a8e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cornelius=20Wei=C3=9F?=
Date: Tue, 10 Dec 2024 11:24:46 +0100
Subject: [PATCH] tests(Tinebase) add jest logic tests
---
tests/js/jest/Array.test.js | 3 +-
tests/js/jest/Readme.md | 27 +
tests/js/jest/common.test.js | 22 +
tests/js/jest/data/Record.test.js | 72 +
tests/js/jest/jest.config.js | 6 +-
tine20/Tinebase/Tinebase.jsb2 | 1262 -----------------
tine20/Tinebase/js/Models.js | 71 +-
tine20/Tinebase/js/Tinebase.js | 318 ++++-
tine20/Tinebase/js/app-loader.js | 2 +-
tine20/Tinebase/js/common.js | 80 +-
tine20/Tinebase/js/data/Record.js | 237 ++--
tine20/Tinebase/js/data/RecordMgr.js | 73 +
tine20/Tinebase/js/package.json | 1 +
tine20/Tinebase/js/tineInit.js | 7 +-
tine20/Tinebase/js/twingEnv.es6.js | 8 +-
tine20/Tinebase/js/ux/Log.js | 17 +-
tine20/Tinebase/js/webpack.common.js | 1 +
tine20/library/ExtJS/ext-custom.js | 26 +-
tine20/library/ExtJS/src/core/Error.js | 17 +-
tine20/library/ExtJS/src/core/Ext-more.js | 5 +-
tine20/library/ExtJS/src/core/core/Ext.js | 83 +-
tine20/library/ExtJS/src/data/DataField.js | 30 +-
tine20/library/ExtJS/src/data/DataReader.js | 69 +-
tine20/library/ExtJS/src/data/JsonReader.js | 62 +-
tine20/library/ExtJS/src/data/Record.js | 64 +-
tine20/library/ExtJS/src/data/Response.js | 8 +-
tine20/library/ExtJS/src/data/SortTypes.js | 18 +-
tine20/library/ExtJS/src/data/Store.js | 3 +-
tine20/library/ExtJS/src/data/XmlReader.js | 2 +
tine20/library/ExtJS/src/util/Format.js | 4 +-
.../library/ExtJS/src/util/MixedCollection.js | 54 +-
.../ExtJS/src/util/core/DelayedTask.js | 6 +-
.../library/ExtJS/src/util/core/Observable.js | 110 +-
33 files changed, 1021 insertions(+), 1747 deletions(-)
create mode 100644 tests/js/jest/Readme.md
create mode 100644 tests/js/jest/common.test.js
create mode 100644 tests/js/jest/data/Record.test.js
delete mode 100644 tine20/Tinebase/Tinebase.jsb2
create mode 100644 tine20/Tinebase/js/data/RecordMgr.js
diff --git a/tests/js/jest/Array.test.js b/tests/js/jest/Array.test.js
index 2ae5492329b..a9ef041f3c6 100644
--- a/tests/js/jest/Array.test.js
+++ b/tests/js/jest/Array.test.js
@@ -1,4 +1,5 @@
-const sum = require('ux/Array.js');
+// grr this pollutes global array object! how to cope whith it?
+require('ux/Array.js');
const testArr = ["green", "red", "blue", "red"];
diff --git a/tests/js/jest/Readme.md b/tests/js/jest/Readme.md
new file mode 100644
index 00000000000..d0fd5defd18
--- /dev/null
+++ b/tests/js/jest/Readme.md
@@ -0,0 +1,27 @@
+# jest tests
+
+## run tests
+run all tests (using npm command)
+
+ ./console src:npm 'test'
+
+run one test file only
+
+ ./console src:npm 'test -- Array.test.js'
+
+run on test only
+
+ ./console src:npm 'test -- Array.test.js --testNamePattern "Array.diff"'
+
+## debuging tests
+run tests in dbg mode
+
+ ./console src:npm 'run test-dbg'
+
+and attach a debugger, use [phpstorm](https://www.jetbrains.com/help/phpstorm/running-and-debugging-node-js.html#ws_node_debug_remote_chrome) or [chrome](chrome://inspect)
+
+## core concepts
+* pure logic tests, no DOM interaction / testing
+* no globals pollution (e.g. Tine, Ext, _, ...)
+ * neither in tests nor in program code to be tested
+ * you might need to rewrite / split your code so it stick to this rule
\ No newline at end of file
diff --git a/tests/js/jest/common.test.js b/tests/js/jest/common.test.js
new file mode 100644
index 00000000000..f4d1f7d0c7f
--- /dev/null
+++ b/tests/js/jest/common.test.js
@@ -0,0 +1,22 @@
+import common from "common";
+
+
+describe('common functions', () => {
+ describe('html2text', () => {
+ it('ignores empty divs', () => {
+ expect(common.html2text( 'Hello,
...
'))
+ .toEqual("\nHello,\n\n...")
+ })
+
+ it('copes with styled div tags', () => {
+ expect(common.html2text( 'Dipl.-Phys. Cornelius WeissTeam Leader Software Engineering
'))
+ .toEqual("Dipl.-Phys. Cornelius Weiss\nTeam Leader Software Engineering")
+ })
+
+ it('copes with nested blocks', () => {
+ expect(common.html2text(''))
+ .toEqual("\n")
+ })
+ })
+
+})
\ No newline at end of file
diff --git a/tests/js/jest/data/Record.test.js b/tests/js/jest/data/Record.test.js
new file mode 100644
index 00000000000..5ef824612e7
--- /dev/null
+++ b/tests/js/jest/data/Record.test.js
@@ -0,0 +1,72 @@
+import Record from "data/Record";
+
+let RecordCls;
+
+describe('data/Record', () => {
+ beforeAll(() => {
+ RecordCls = Record.create([
+ {name: 'name'},
+ {name: 'date', type: 'date', dateFormat: 'Y-m-d H:i:s'},
+ ], {
+ appName: 'Tinebase',
+ modelName: 'Test',
+ idProperty: 'id',
+ titleProperty: 'name',
+ recordName: 'TestRecord',
+ recordsName: 'TestRecords'
+ });
+ })
+
+ it('creates records by constructor', () => {
+ expect(RecordCls).toBeInstanceOf(Function)
+ const record = new RecordCls({id: 'test-id'})
+ expect(record).toBeInstanceOf(Record)
+ expect(record.id).toEqual('test-id')
+
+ })
+
+ it('assigns auto ids', () => {
+ expect(RecordCls).toBeInstanceOf(Function)
+ expect(typeof new RecordCls({}).id).toBe('number')
+ })
+
+ it('creates records statically by setFromJson', () => {
+ // @TODO deal with Date prototype overwrites
+ const testRecord = Record.setFromJson(JSON.stringify({id: 'abc', name: 'testname'/*, date: '2024-12-11 17:50:32'*/}), RecordCls)
+ expect(testRecord).toBeInstanceOf(Record)
+ expect(testRecord.id).toEqual('abc')
+ })
+
+ it('can track modifications', () => {
+ const testRecord = Record.setFromJson(JSON.stringify({id: 'abc', name: 'testname'/*, date: '2024-12-11 17:50:32'*/}), RecordCls)
+ expect(testRecord.dirty).toEqual(false)
+ expect(testRecord.editing).toEqual(false)
+ // expect(testRecord.phantom).toEqual(true)
+ expect(testRecord.isModified('name')).toEqual(false)
+
+ testRecord.set('name', 'update')
+ expect(testRecord.get('name')).toEqual('update')
+ expect(testRecord.isModified('name')).toEqual(true)
+ expect(testRecord.dirty).toEqual(true)
+ expect(testRecord.getChanges()).toEqual({ name: 'update' })
+ expect(testRecord.modified).toEqual({ name: 'testname' })
+
+ const recordData = testRecord.getData()
+ expect(recordData.__meta.dirty).toEqual(true)
+ expect(recordData.__meta.modified.name).toEqual('testname')
+ expect(recordData.name).toEqual('update')
+ })
+
+ it('copes with magic customfield names', () => {
+ const record = new RecordCls({})
+ record.set('#cftest', 'value')
+ expect(record.get('#cftest')).toEqual('value')
+ expect(JSON.stringify(record.data.customfields)).toEqual(JSON.stringify({cftest: 'value'}))
+ })
+
+ it('generates unique UIDs in different length', () => {
+ expect(Record.generateUID().length).toBe(40)
+ expect(Record.generateUID(5).length).toBe(5)
+ expect(Record.generateUID()).not.toEqual(Record.generateUID())
+ })
+});
\ No newline at end of file
diff --git a/tests/js/jest/jest.config.js b/tests/js/jest/jest.config.js
index 48d64501b10..3acab817988 100644
--- a/tests/js/jest/jest.config.js
+++ b/tests/js/jest/jest.config.js
@@ -71,7 +71,7 @@ const config = {
// globalTeardown: undefined,
// A set of global variables that need to be available in all test environments
- // globals: {},
+ globals: {},
// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
// maxWorkers: "50%",
@@ -103,7 +103,9 @@ const config = {
}, [])),
// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
- // moduleNameMapper: {},
+ moduleNameMapper: {
+ "^Ext(.*)$": "../../library/ExtJS/src$1",
+ },
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
// modulePathIgnorePatterns: [],
diff --git a/tine20/Tinebase/Tinebase.jsb2 b/tine20/Tinebase/Tinebase.jsb2
deleted file mode 100644
index 53a02886f1c..00000000000
--- a/tine20/Tinebase/Tinebase.jsb2
+++ /dev/null
@@ -1,1262 +0,0 @@
-{
- "projectName": "Tine 2.0 - Tinebase",
- "deployDir": "Tinebase",
- "licenseText": "Tine 2.0 - Tinebase \nCopyright (c) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)\nhttp://www.gnu.org/licenses/agpl.html AGPL Version 3",
- "resources": [],
- "pkgs": [
- {
- "name": "Tinebase FAT Client",
- "file": "js/Tinebase-FAT.js",
- "isDebug": true,
- "fileIncludes": [
- {
- "text": "extFixes.js",
- "path": "js/"
- },
- {
- "text": "checkboxGridSelection.js",
- "path": "js/touch/"
- },
- {
- "text": "Portal.js",
- "path": "js/ux/"
- },
- {
- "text": "PortalColumn.js",
- "path": "js/ux/"
- },
- {
- "text": "Portlet.js",
- "path": "js/ux/"
- },
- {
- "text": "extInit.js",
- "path": "js/"
- },
- {
- "text": "store.compat.js",
- "path": "js/ux/util/"
- },
- {
- "text": "addressparser.js",
- "path": "../library/addressparser.js/"
- },
- {
- "text": "MapPanel.js",
- "path": "js/widgets/"
- },
- {
- "text": "ContentTypeTreePanel.js",
- "path": "js/widgets/"
- },
- {
- "text": "RecordPickerManager.js",
- "path": "js/widgets/form/"
- },
- {
- "text": "AddToRecordPanel.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "ExceptionHandlerDialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "Cookie.js",
- "path": "js/ux/util/"
- },
- {
- "text": "urlCoder.js",
- "path": "js/ux/util/"
- },
- {
- "text": "FieldLabeler.js",
- "path": "js/ux/"
- },
- {
- "text": "String.js",
- "path": "js/ux/"
- },
- {
- "text": "Array.js",
- "path": "js/ux/"
- },
- {
- "text": "Date.js",
- "path": "js/ux/"
- },
- {
- "text": "Log.js",
- "path": "js/ux/"
- },
- {
- "text": "ConnectionStatus.js",
- "path": "js/ux/"
- },
- {
- "text": "JsonRpcProvider.js",
- "path": "js/ux/Direct/"
- },
- {
- "text": "DatePickerWeekPlugin.js",
- "path": "js/ux/"
- },
- {
- "text": "ButtonLockedToggle.js",
- "path": "js/ux/"
- },
- {
- "text": "Percentage.js",
- "path": "js/ux/"
- },
- {
- "text": "ApplicationStarter.js",
- "path": "js/"
- },
- {
- "text": "PopupWindow.js",
- "path": "js/ux/"
- },
- {
- "text": "PopupWindowManager.js",
- "path": "js/ux/"
- },
- {
- "text": "Notification.js",
- "path": "js/ux/"
- },
- {
- "text": "WindowFactory.js",
- "path": "js/ux/"
- },
- {
- "text": "SliderTip.js",
- "path": "js/ux/"
- },
- {
- "text": "Wizard.js",
- "path": "js/ux/"
- },
- {
- "text": "SearchField.js",
- "path": "js/ux/"
- },
- {
- "text": "BrowseButton.js",
- "path": "js/ux/"
- },
- {
- "text": "ColumnManager.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "CheckColumn.js",
- "path": "js/ux/grid/"
- },
- {
- "text": "ActionColumnPlugin.js",
- "path": "js/ux/grid/"
- },
- {
- "text": "QuickaddGridPanel.js",
- "path": "js/ux/grid/"
- },
- {
- "text": "RowExpander.js",
- "path": "js/ux/grid/"
- },
- {
- "text": "PagingToolbar.js",
- "path": "js/ux/grid/"
- },
- {
- "text": "GridDropZone.js",
- "path": "js/ux/grid/"
- },
- {
- "text": "GridViewMenuPlugin.js",
- "path": "js/ux/grid/"
- },
- {
- "text": "MultiCellSelectionModel.js",
- "path": "js/ux/grid/"
- },
- {
- "text": "UploadManager.js",
- "path": "js/ux/file/"
- },
- {
- "text": "Upload.js",
- "path": "js/ux/file/"
- },
- {
- "text": "BrowsePlugin.js",
- "path": "js/ux/file/"
- },
- {
- "text": "Download.js",
- "path": "js/ux/file/"
- },
- {
- "text": "ColorField.js",
- "path": "js/ux/form/"
- },
- {
- "text": "IconTextField.js",
- "path": "js/ux/form/"
- },
- {
- "text": "FieldMaximizePlugin.js",
- "path": "js/ux/form/"
- },
- {
- "text": "MirrorTextField.js",
- "path": "js/ux/form/"
- },
- {
- "text": "ColumnFormPanel.js",
- "path": "js/ux/form/"
- },
- {
- "text": "NumberField.js",
- "path": "js/ux/form/"
- },
- {
- "text": "PeriodPicker.js",
- "path": "js/ux/form/"
- },
- {
- "text": "MoneyField.js",
- "path": "js/ux/form/"
- },
- {
- "text": "DiscountField.js",
- "path": "js/widgets/form/"
- },
- {
- "text": "BytesField.js",
- "path": "js/ux/form/"
- },
- {
- "text": "LayerCombo.js",
- "path": "js/ux/form/"
- },
- {
- "text": "ClearableComboBox.js",
- "path": "js/ux/form/"
- },
- {
- "text": "ClearableTextField.js",
- "path": "js/ux/form/"
- },
- {
- "text": "index.js",
- "path": "js/widgets/form/VMultiPicker"
- },
- {
- "text": "DateTimeField.js",
- "path": "js/ux/form/"
- },
- {
- "text": "BooleanCombo.js",
- "path": "js/ux/form/"
- },
- {
- "text": "ClearableDateField.js",
- "path": "js/ux/form/"
- },
- {
- "text": "ImageField.js",
- "path": "js/ux/form/"
- },
- {
- "text": "ImageCropper.js",
- "path": "js/ux/form/"
- },
- {
- "text": "Spinner.js",
- "path": "js/ux/form/"
- },
- {
- "text": "SpinnerStrategy.js",
- "path": "js/ux/form/"
- },
- {
- "text": "DurationSpinner.js",
- "path": "js/ux/form/"
- },
- {
- "text": "LockCombo.js",
- "path": "js/ux/form/"
- },
- {
- "text": "LockTextfield.js",
- "path": "js/ux/form/"
- },
- {
- "text": "HtmlEditor.js",
- "path": "js/ux/form/"
- },
- {
- "text": "ComboBoxRecentsPlugin.js",
- "path": "js/ux/form/"
- },
- {
- "text": "HorizontalFitLayout.js",
- "path": "js/ux/layout/"
- },
- {
- "text": "CenterLayout.js",
- "path": "js/ux/layout/"
- },
- {
- "text": "RowLayout.js",
- "path": "js/ux/layout/"
- },
- {
- "text": "cardLayoutHelper.js",
- "path": "js/ux/layout/"
- },
- {
- "text": "MultiAccordionLayout.js",
- "path": "js/ux/layout/"
- },
- {
- "text": "GMapPanel.js",
- "path": "js/ux/"
- },
- {
- "text": "CheckboxSelectionModel.js",
- "path": "js/ux/tree/"
- },
- {
- "text": "TreeGridSorter.js",
- "path": "js/ux/tree/"
- },
- {
- "text": "TreeGridColumnResizer.js",
- "path": "js/ux/tree/"
- },
- {
- "text": "TreeGridNodeUI.js",
- "path": "js/ux/tree/"
- },
- {
- "text": "TreeGridLoader.js",
- "path": "js/ux/tree/"
- },
- {
- "text": "TreeGridColumns.js",
- "path": "js/ux/tree/"
- },
- {
- "text": "TreeGrid.js",
- "path": "js/ux/tree/"
- },
- {
- "text": "DisplayPanel.js",
- "path": "js/ux/display/"
- },
- {
- "text": "DisplayField.js",
- "path": "js/ux/display/"
- },
- {
- "text": "DisplayTextArea.js",
- "path": "js/ux/display/"
- },
- {
- "text": "Display.js",
- "path": "js/ux/layout/"
- },
- {
- "text": "MessageBox.js",
- "path": "js/ux/"
- },
- {
- "text": "TabPanelSortPlugin.js",
- "path": "js/ux/"
- },
- {
- "text": "pluginRegistry.js",
- "path": "js/ux/"
- },
- {
- "text": "ItemRegistry.js",
- "path": "js/ux/"
- },
- {
- "text": "Function.deferByTickets.js",
- "path": "js/ux/"
- },
- {
- "text": "Function.createBuffered.js",
- "path": "js/ux/"
- },
- {
- "text": "Printer.js",
- "path": "js/ux/Printer/"
- },
- {
- "text": "Base.js",
- "path": "js/ux/Printer/renderers/"
- },
- {
- "text": "GridPanel.js",
- "path": "js/ux/Printer/renderers/"
- },
- {
- "text": "ColumnTree.js",
- "path": "js/ux/Printer/renderers/"
- },
- {
- "text": "Field.js",
- "path": "js/ux/Printer/renderers/"
- },
- {
- "text": "Check.js",
- "path": "js/ux/Printer/renderers/"
- },
- {
- "text": "Combo.js",
- "path": "js/ux/Printer/renderers/"
- },
- {
- "text": "Container.js",
- "path": "js/ux/Printer/renderers/"
- },
- {
- "text": "Panel.js",
- "path": "js/ux/Printer/renderers/"
- },
- {
- "text": "Tags.js",
- "path": "js/ux/Printer/renderers/"
- },
- {
- "text": "EditDialogRenderer.js",
- "path": "js/ux/Printer/renderers/"
- },
- {
- "text": "TitleRendererManager.js",
- "path": "js/data/"
- },
- {
- "text": "Record.js",
- "path": "js/data/"
- },
- {
- "text": "RecordStore.js",
- "path": "js/data/"
- },
- {
- "text": "GroupedStoreCollection.js",
- "path": "js/data/"
- },
- {
- "text": "RecordProxy.js",
- "path": "js/data/"
- },
- {
- "text": "AbstractBackend.js",
- "path": "js/data/"
- },
- {
- "text": "Clipboard.js",
- "path": "js/data/"
- },
- {
- "text": "RecentsManager.js",
- "path": "js/"
- },
- {
- "text": "StateProvider.js",
- "path": "js/"
- },
- {
- "text": "AppManager.js",
- "path": "js/"
- },
- {
- "text": "ExceptionHandler.js",
- "path": "js/"
- },
- {
- "text": "ExceptionHandlerRegistry.js",
- "path": "js/"
- },
- {
- "text": "ExceptionDialog.js",
- "path": "js/"
- },
- {
- "text": "Container.js",
- "path": "js/"
- },
- {
- "text": "EncodingHelper.js",
- "path": "js/"
- },
- {
- "text": "common.js",
- "path": "js/"
- },
- {
- "text": "configManager.js",
- "path": "js/"
- },
- {
- "text": "RendererManager.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "Models.js",
- "path": "js/"
- },
- {
- "text": "Application.js",
- "path": "js/"
- },
- {
- "text": "Store.js",
- "path": "js/widgets/keyfield/"
- },
- {
- "text": "ComboBox.js",
- "path": "js/widgets/keyfield/"
- },
- {
- "text": "Renderer.js",
- "path": "js/widgets/keyfield/"
- },
- {
- "text": "LangChooser.js",
- "path": "js/widgets/"
- },
- {
- "text": "ActionManager.js",
- "path": "js/widgets/"
- },
- {
- "text": "ActionUpdater.js",
- "path": "js/widgets/"
- },
- {
- "text": "EditRecord.js",
- "path": "js/widgets/"
- },
- {
- "text": "VersionCheck.js",
- "path": "js/widgets/"
- },
- {
- "text": "AlarmPanel.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "Dialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "EditDialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "SimpleRecordEditDialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "MultipleEditDialogPlugin.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "AddRelationsEditDialogPlugin.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "MultipleEditResultSummary.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "RecordDisplayPanel.js",
- "path": "js/widgets/display/"
- },
- {
- "text": "DefaultDisplayPanel.js",
- "path": "js/widgets/display/"
- },
- {
- "text": "TabPanelKeyPlugin.js",
- "path": "js/ux/"
- },
- {
- "text": "TokenModeEditDialogPlugin.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "WizardPanel.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "AdminPanel.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "CredentialsDialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "PreferencesDialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "PreferencesTreePanel.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "PreferencesPanel.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "ImportDialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "SimpleImportDialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "ExportDialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "index.js",
- "path": "js/widgets/dialog/vue/ModalDialog/"
- },
- {
- "text": "index.js",
- "path": "js/widgets/dialog/vue/MultiOptionsDialog/"
- },
- {
- "text": "index.js",
- "path": "js/widgets/dialog/vue/ModalDialog/"
- },
- {
- "text": "FileListDialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "DuplicateMergeDialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "DuplicateResolveGridPanel.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "DetailsPanel.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "FilterModel.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "MonthFilter.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "FilterPlugin.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "FilterButton.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "ExportButton.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "exportAction.js",
- "path": "js/widgets/"
- },
- {
- "text": "importAction.js",
- "path": "js/widgets/"
- },
- {
- "text": "FilterToolbar.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "FilterStructureTreePanel.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "FilterPanel.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "PickerFilter.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "FilterToolbarQuickFilterPlugin.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "FilterSelectionModel.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "ForeignRecordFilter.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "GroupingGridPlugin.js",
- "path": "js/ux/grid/"
- },
- {
- "text": "OwnRecordFilter.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "QuickaddGridPanel.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "FileUploadGrid.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "AttachmentsGridPanel.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "PickerGridPanel.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "FieldManager.js",
- "path": "js/widgets/form/"
- },
- {
- "text": "MappingPickerGridPanel.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "LinkGridPanel.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "FilterModelMultiSelect.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "QuotaRenderer.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "Manager.js",
- "path": "js/widgets/relation/"
- },
- {
- "text": "GridRenderer.js",
- "path": "js/widgets/relation/"
- },
- {
- "text": "MenuItemManager.js",
- "path": "js/widgets/relation/"
- },
- {
- "text": "GenericPickerGridPanel.js",
- "path": "js/widgets/relation/"
- },
- {
- "text": "PickerGridPanel.js",
- "path": "js/widgets/relation/"
- },
- {
- "text": "RecordRenderer.js",
- "path": "js/widgets/printer/"
- },
- {
- "text": "GridPanel.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "BbarGridPanel.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "Filter.js",
- "path": "js/widgets/keyfield/"
- },
- {
- "text": "ConfigGrid.js",
- "path": "js/widgets/keyfield/"
- },
- {
- "text": "ConfigField.js",
- "path": "js/widgets/keyfield/"
- },
- {
- "text": "Loader.js",
- "path": "js/widgets/tree/"
- },
- {
- "text": "ContextMenu.js",
- "path": "js/widgets/tree/"
- },
- {
- "text": "FilterPlugin.js",
- "path": "js/widgets/tree/"
- },
- {
- "text": "ConfigManager.js",
- "path": "js/widgets/customfields/"
- },
- {
- "text": "Field.js",
- "path": "js/widgets/customfields/"
- },
- {
- "text": "FilterModel.js",
- "path": "js/widgets/customfields/"
- },
- {
- "text": "Renderer.js",
- "path": "js/widgets/customfields/"
- },
- {
- "text": "CustomfieldSearchCombo.js",
- "path": "js/widgets/customfields/"
- },
- {
- "text": "EditDialogPlugin.js",
- "path": "js/widgets/customfields/"
- },
- {
- "text": "CustomfieldsCombo.js",
- "path": "js/widgets/customfields/"
- },
- {
- "text": "FilterModel.js",
- "path": "js/widgets/relation/"
- },
- {
- "text": "Renderer.js",
- "path": "js/widgets/relation/"
- },
- {
- "text": "PickerGridPanel.js",
- "path": "js/widgets/account/"
- },
- {
- "text": "ChangeAccountAction.js",
- "path": "js/widgets/account/"
- },
- {
- "text": "SelectionComboBox.js",
- "path": "js/widgets/container/"
- },
- {
- "text": "SelectionDialog.js",
- "path": "js/widgets/container/"
- },
- {
- "text": "CalDAVContainerPropertiesHookField.js",
- "path": "js/widgets/container/"
- },
- {
- "text": "GrantsGrid.js",
- "path": "js/widgets/container/"
- },
- {
- "text": "GrantsDialog.js",
- "path": "js/widgets/container/"
- },
- {
- "text": "TreePanel.js",
- "path": "js/widgets/container/"
- },
- {
- "text": "PropertiesDialog.js",
- "path": "js/widgets/container/"
- },
- {
- "text": "FilterModel.js",
- "path": "js/widgets/container/"
- },
- {
- "text": "TagsPanel.js",
- "path": "js/widgets/tags/"
- },
- {
- "text": "TagCombo.js",
- "path": "js/widgets/tags/"
- },
- {
- "text": "TagToggleBox.js",
- "path": "js/widgets/tags/"
- },
- {
- "text": "TagFilter.js",
- "path": "js/widgets/tags/"
- },
- {
- "text": "TagsMassAttachAction.js",
- "path": "js/widgets/tags/"
- },
- {
- "text": "TagsMassDetachAction.js",
- "path": "js/widgets/tags/"
- },
- {
- "text": "WestPanel.js",
- "path": "js/widgets/mainscreen/"
- },
- {
- "text": "MainScreen.js",
- "path": "js/widgets/"
- },
- {
- "text": "LicenseScreen.js",
- "path": "js/"
- },
- {
- "text": "CreditsScreen.js",
- "path": "js/"
- },
- {
- "text": "CountryCombo.js",
- "path": "js/widgets/"
- },
- {
- "text": "ActivitiesPanel.js",
- "path": "js/widgets/"
- },
- {
- "text": "ActivitiesGridPanel.js",
- "path": "js/widgets/"
- },
- {
- "text": "RecordPickerComboBox.js",
- "path": "js/widgets/form/"
- },
- {
- "text": "PickerCombo.js",
- "path": "js/widgets/relation/"
- },
- {
- "text": "PickerGridLayerCombo.js",
- "path": "js/widgets/grid/"
- },
- {
- "text": "ConfigPanel.js",
- "path": "js/widgets/form/"
- },
- {
- "text": "AutoCompleteField.js",
- "path": "js/widgets/form/"
- },
- {
- "text": "FileUploadButton.js",
- "path": "js/widgets/form/"
- },
- {
- "text": "UidTriggerField.js",
- "path": "js/widgets/form/"
- },
- {
- "text": "PasswordTriggerField.js",
- "path": "js/widgets/form/"
- },
- {
- "text": "LocationTypePluginFactory.js",
- "path": "js/widgets/file/"
- },
- {
- "text": "SelectionField.js",
- "path": "js/widgets/file/"
- },
- {
- "text": "MountpointPicker.js",
- "path": "js/widgets/file/"
- },
- {
- "text": "mountpointRenderer.js",
- "path": "js/widgets/file/"
- },
- {
- "text": "index.js",
- "path": "js/widgets/dialog/vue/PasswordDialog/"
- },
- {
- "text": "SecondFactorDialog.js",
- "path": "js/widgets/dialog/"
- },
- {
- "text": "RecordForm.js",
- "path": "js/widgets/form/"
- },
- {
- "text": "Model.js",
- "path": "js/widgets/persistentfilter/"
- },
- {
- "text": "Store.js",
- "path": "js/widgets/persistentfilter/"
- },
- {
- "text": "PickerPanel.js",
- "path": "js/widgets/persistentfilter/"
- },
- {
- "text": "EditPersistentFilterPanel.js",
- "path": "js/widgets/persistentfilter/"
- },
- {
- "text": "renderer.js",
- "path": "js/widgets/path/"
- },
- {
- "text": "index.js",
- "path": "js/widgets/dialog/vue/PasswordChangeDialog/"
- },
- {
- "text": "AboutDialog.js",
- "path": "js/"
- },
- {
- "text": "AppPile.js",
- "path": "js/"
- },
- {
- "text": "index.js",
- "path": "js/TineBar/"
- },
- {
- "text": "index.js",
- "path": "js/TineDock/"
- },
- {
- "text": "AppTabsPanel.js",
- "path": "js/"
- },
- {
- "text": "MainContextMenu.js",
- "path": "js/"
- },
- {
- "text": "MainMenu.js",
- "path": "js/"
- },
- {
- "text": "MainScreenPanel.js",
- "path": "js/"
- },
- {
- "text": "LoginPanel.js",
- "path": "js/"
- },
- {
- "text": "AdminPanel.js",
- "path": "js/"
- },
- {
- "text": "UserProfilePanel.js",
- "path": "js/"
- },
- {
- "text": "prototypeTranslations.js",
- "path": "js/"
- },
- {
- "text": "CanonicalPath.js",
- "path": "js/"
- },
- {
- "text": "PresenceObserver.js",
- "path": "js/"
- },
- {
- "text": "PasswordGenerator.js",
- "path": "js/"
- },
- {
- "text": "RangeSliderComponent.js",
- "path": "js/"
- },
- {
- "text": "FileSelectionArea.js",
- "path": "js/widgets/form/"
- },
- {
- "text": "BLConfigPanel.js",
- "path": "js/BL/"
- }
- ]
- },
- {
- "name": "Tinebase FAT Client",
- "file": "css/Tinebase-FAT.css",
- "isDebug": true,
- "fileIncludes": [
- {
- "text": "ExtFixes.css",
- "path": "css/"
- },
- {
- "text": "Tinebase.less",
- "path": "css/"
- },
- {
- "text": "mimetypes.css",
- "path": "css/"
- },
- {
- "text": "SmallForms.css",
- "path": "css/"
- },
- {
- "text": "ArrowCollapse.css",
- "path": "css/ux/"
- },
- {
- "text": "SubFormPanel.css",
- "path": "css/ux/"
- },
- {
- "text": "ConnectionStatus.css",
- "path": "css/ux/"
- },
- {
- "text": "Wizard.css",
- "path": "css/ux/"
- },
- {
- "text": "Percentage.css",
- "path": "css/ux/"
- },
- {
- "text": "DatePickerWeekPlugin.css",
- "path": "css/ux/"
- },
- {
- "text": "QuickaddGridPanel.css",
- "path": "css/ux/grid/"
- },
- {
- "text": "IconTextField.css",
- "path": "css/ux/grid/"
- },
- {
- "text": "GridDropZone.css",
- "path": "css/ux/grid/"
- },
- {
- "text": "ActionColumnPlugin.css",
- "path": "css/ux/grid/"
- },
- {
- "text": "GridViewMenuPlugin.css",
- "path": "css/ux/grid/"
- },
- {
- "text": "ExpandFieldSet.css",
- "path": "css/ux/form/"
- },
- {
- "text": "ImageField.css",
- "path": "css/ux/form/"
- },
- {
- "text": "Spinner.css",
- "path": "css/ux/form/"
- },
- {
- "text": "HtmlEditor.css",
- "path": "css/ux/form/"
- },
- {
- "text": "LayerCombo.css",
- "path": "css/ux/form/"
- },
- {
- "text": "PeriodPicker.css",
- "path": "css/ux/form/"
- },
- {
- "text": "DisplayPanel.css",
- "path": "css/ux/display/"
- },
- {
- "text": "CenterLayout.css",
- "path": "css/ux/layout/"
- },
- {
- "text": "treegrid.css",
- "path": "css/ux/tree/"
- },
- {
- "text": "LockCombo.css",
- "path": "css/ux/"
- },
- {
- "text": "LockTextField.css",
- "path": "css/ux/"
- },
- {
- "text": "Menu.css",
- "path": "css/ux/"
- },
- {
- "text": "MessageBox.css",
- "path": "css/ux/"
- },
- {
- "text": "EditRecord.css",
- "path": "css/widgets/"
- },
- {
- "text": "TagsPanel.css",
- "path": "css/widgets/"
- },
- {
- "text": "FilterToolbar.css",
- "path": "css/widgets/"
- },
- {
- "text": "AccountPicker.css",
- "path": "css/widgets/"
- },
- {
- "text": "PreviewPanel.css",
- "path": "css/widgets/"
- },
- {
- "text": "PreferencesPanel.css",
- "path": "css/widgets/"
- },
- {
- "text": "UidTriggerField.css",
- "path": "css/widgets/"
- },
- {
- "text": "FileSelectionArea.css",
- "path": "css/widgets/"
- },
- {
- "text": "PasswordTriggerField.css",
- "path": "css/widgets/"
- },
- {
- "text": "print.css",
- "path": "css/widgets/"
- }
- ]
- }
- ]
-}
diff --git a/tine20/Tinebase/js/Models.js b/tine20/Tinebase/js/Models.js
index b61fb106b19..c40301237c3 100644
--- a/tine20/Tinebase/js/Models.js
+++ b/tine20/Tinebase/js/Models.js
@@ -5,37 +5,18 @@
* @author Cornelius Weiss
* @copyright Copyright (c) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)
*/
-Ext.ns('Tine.Tinebase.Model');
-/**
- * @type {Array}
- *
- * modlog Fields
- */
+import Record from 'data/Record'
-Tine.Tinebase.Model.modlogFields = [
- { name: 'creation_time', type: 'date', dateFormat: Date.patterns.ISO8601Long, omitDuplicateResolving: true },
- { name: 'created_by', omitDuplicateResolving: true },
- { name: 'last_modified_time', type: 'date', dateFormat: Date.patterns.ISO8601Long, omitDuplicateResolving: true },
- { name: 'last_modified_by', omitDuplicateResolving: true },
- { name: 'is_deleted', type: 'boolean', omitDuplicateResolving: true },
- { name: 'deleted_time', type: 'date', dateFormat: Date.patterns.ISO8601Long, omitDuplicateResolving: true },
- { name: 'deleted_by', omitDuplicateResolving: true },
- { name: 'seq', omitDuplicateResolving: true }
-];
+Ext.ns('Tine.Tinebase.Model');
-/**
- * @type {Array}
- * generic Record fields
- */
-Tine.Tinebase.Model.genericFields = Tine.Tinebase.Model.modlogFields.concat([
- { name: 'container_id', header: 'Container', omitDuplicateResolving: false}
-]);
+Tine.Tinebase.Model.modlogFields = Record.modlogFields
+Tine.Tinebase.Model.genericFields = Record.genericFields
/**
* Model of a country
*/
-Tine.Tinebase.Model.Country = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.Country = Record.create([
{ name: 'shortName' },
{ name: 'translatedName' }
], {
@@ -68,7 +49,7 @@ Tine.Tinebase.Model.Timezone = Ext.data.Record.create([
/**
* Model of a role
*/
-Tine.Tinebase.Model.Role = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.Role = Record.create([
{name: 'id'},
{name: 'name'},
{name: 'description'}
@@ -84,7 +65,7 @@ Tine.Tinebase.Model.Role = Tine.Tinebase.data.Record.create([
/**
* Model of a generalised account (user or group)
*/
-Tine.Tinebase.Model.Account = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.Account = Record.create([
{name: 'id'},
{name: 'type'},
{name: 'name'},
@@ -99,7 +80,7 @@ Tine.Tinebase.Model.Account = Tine.Tinebase.data.Record.create([
/**
* Model of a container
*/
-Tine.Tinebase.Model.Container = Tine.Tinebase.data.Record.create(Tine.Tinebase.Model.modlogFields.concat([
+Tine.Tinebase.Model.Container = Record.create(Record.modlogFields.concat([
{name: 'id'},
{name: 'name'},
{name: 'hierarchy'},
@@ -129,7 +110,7 @@ Tine.Tinebase.Model.Container = Tine.Tinebase.data.Record.create(Tine.Tinebase.M
/**
* Model of a grant
*/
-Tine.Tinebase.Model.Grant = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.Grant = Record.create([
{name: 'id'},
{name: 'record_id'},
{name: 'account_id'},
@@ -161,9 +142,9 @@ Tine.Tinebase.Model.Grant = Tine.Tinebase.data.Record.create([
/**
* Model of a tag
*
- * @constructor {Tine.Tinebase.data.Record}
+ * @constructor {Record}
*/
-Tine.Tinebase.Model.Tag = Tine.Tinebase.data.Record.create(Tine.Tinebase.Model.modlogFields.concat([
+Tine.Tinebase.Model.Tag = Record.create(Record.modlogFields.concat([
{name: 'id' },
{name: 'app' },
{name: 'owner' },
@@ -286,7 +267,7 @@ Tine.Tinebase.Model.Preference = Ext.data.Record.create([
*
* @constructor {Ext.data.Record}
*/
-Tine.Tinebase.Model.Alarm = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.Alarm = Record.create([
{name: 'id' },
{name: 'record_id' },
{name: 'model' },
@@ -322,11 +303,11 @@ Tine.Tinebase.Model.Alarm = Tine.Tinebase.data.Record.create([
/**
* @namespace Tine.Tinebase.Model
* @class Tine.Tinebase.Model.ImportJob
- * @extends Tine.Tinebase.data.Record
+ * @extends Record
*
* Model of an import job
*/
-Tine.Tinebase.Model.ImportJob = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.ImportJob = Record.create([
{name: 'files' },
{name: 'import_definition_id' },
{name: 'model' },
@@ -347,11 +328,11 @@ Tine.Tinebase.Model.ImportJob = Tine.Tinebase.data.Record.create([
/**
* @namespace Tine.Tinebase.Model
* @class Tine.Tinebase.Model.ExportJob
- * @extends Tine.Tinebase.data.Record
+ * @extends Record
*
* Model of an export job
*/
-Tine.Tinebase.Model.ExportJob = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.ExportJob = Record.create([
{name: 'scope' },
{name: 'filter' },
{name: 'definitionId' },
@@ -375,11 +356,11 @@ Tine.Tinebase.Model.ExportJob = Tine.Tinebase.data.Record.create([
/**
* @namespace Tine.Tinebase.Model
* @class Tine.Tinebase.Model.Credentials
- * @extends Tine.Tinebase.data.Record
+ * @extends Record
*
* Model of user credentials
*/
-Tine.Tinebase.Model.Credentials = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.Credentials = Record.create([
{name: 'id'},
{name: 'username'},
{name: 'password'}
@@ -396,11 +377,11 @@ Tine.Tinebase.Model.Credentials = Tine.Tinebase.data.Record.create([
/**
* @namespace Tine.Tinebase.Model
* @class Tine.Tinebase.Model.Relation
- * @extends Tine.Tinebase.data.Record
+ * @extends Record
*
* Model of a Relation
*/
-Tine.Tinebase.Model.Relation = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.Relation = Record.create([
{name: 'id'},
{name: 'own_model'},
{name: 'own_id'},
@@ -438,11 +419,11 @@ Tine.Tinebase.Model.Relation.findDuplicate = function(store, record) {
/**
* @namespace Tine.Tinebase.Model
* @class Tine.Tinebase.Model.Department
- * @extends Tine.Tinebase.data.Record
+ * @extends Record
*
* Model of a Department
*/
-Tine.Tinebase.Model.Department = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.Department = Record.create([
{name: 'id'},
{name: 'name'},
{name: 'description'}
@@ -465,11 +446,11 @@ Tine.Tinebase.Model.Department.getFilterModel = function() {
/**
* @namespace Tine.Tinebase.Model
* @class Tine.Tinebase.Model.Config
- * @extends Tine.Tinebase.data.Record
+ * @extends Record
*
* Model of a application config settings
*/
-Tine.Tinebase.Model.Config = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.Config = Record.create([
{name: 'id'},
{name: 'application_id'},
{name: 'name'},
@@ -496,7 +477,7 @@ Tine.Tinebase.Model.Config = Tine.Tinebase.data.Record.create([
Tine.widgets.grid.RendererManager.register('Tinebase', 'Tree_Node', 'size', Tine.Tinebase.common.byteRenderer);
Tine.widgets.grid.RendererManager.register('Tinebase', 'Tree_Node', 'revision_size', Tine.Tinebase.common.byteRenderer);
-Tine.Tinebase.Model.KeyFieldRecord = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.KeyFieldRecord = Record.create([
{ name: 'id' },
{ name: 'value' },
{ name: 'i18nValue' },
@@ -510,7 +491,7 @@ Tine.Tinebase.Model.KeyFieldRecord = Tine.Tinebase.data.Record.create([
titleProperty: 'value'
});
-Tine.Tinebase.Model.Path = Tine.Tinebase.data.Record.create([
+Tine.Tinebase.Model.Path = Record.create([
{ name: 'id' },
{ name: 'path' },
{ name: 'shadow_path' },
diff --git a/tine20/Tinebase/js/Tinebase.js b/tine20/Tinebase/js/Tinebase.js
index 4812b0c1ce7..fd16426879c 100644
--- a/tine20/Tinebase/js/Tinebase.js
+++ b/tine20/Tinebase/js/Tinebase.js
@@ -27,8 +27,322 @@ require('postal.request-response');
// custom ext build
require('../../library/ExtJS/ext-custom');
-// include traditional stuff as defined in jsb2
-require('./../../Tinebase/Tinebase.jsb2');
+(typeof window !== "undefined" ? window : global)['Tine'] =
+ (typeof window !== "undefined" ? window : global)['Tine'] || {}
+
+/* pkg: Tinebase FAT Client (js/Tinebase-FAT.js)*/
+require("./extFixes.js");
+require("./touch/checkboxGridSelection.js");
+require("./ux/Portal.js");
+require("./ux/PortalColumn.js");
+require("./ux/Portlet.js");
+require("./extInit.js");
+require("./ux/util/store.compat.js");
+require("./../../library/addressparser.js/addressparser.js");
+require("./widgets/MapPanel.js");
+require("./widgets/ContentTypeTreePanel.js");
+require("./widgets/form/RecordPickerManager.js");
+require("./widgets/dialog/AddToRecordPanel.js");
+require("./widgets/dialog/ExceptionHandlerDialog.js");
+require("./ux/util/Cookie.js");
+require("./ux/util/urlCoder.js");
+require("./ux/FieldLabeler.js");
+require("./ux/String.js");
+require("./ux/Array.js");
+require("./ux/Date.js");
+require("./ux/ConnectionStatus.js");
+require("./ux/Direct/JsonRpcProvider.js");
+require("./ux/DatePickerWeekPlugin.js");
+require("./ux/ButtonLockedToggle.js");
+require("./ux/Percentage.js");
+require("./ApplicationStarter.js");
+require("./ux/PopupWindow.js");
+require("./ux/PopupWindowManager.js");
+require("./ux/Notification.js");
+require("./ux/WindowFactory.js");
+require("./ux/SliderTip.js");
+require("./ux/Wizard.js");
+require("./ux/SearchField.js");
+require("./ux/BrowseButton.js");
+require("./widgets/grid/ColumnManager.js");
+require("./ux/grid/CheckColumn.js");
+require("./ux/grid/ActionColumnPlugin.js");
+require("./ux/grid/QuickaddGridPanel.js");
+require("./ux/grid/RowExpander.js");
+require("./ux/grid/PagingToolbar.js");
+require("./ux/grid/GridDropZone.js");
+require("./ux/grid/GridViewMenuPlugin.js");
+require("./ux/grid/MultiCellSelectionModel.js");
+require("./ux/file/UploadManager.js");
+require("./ux/file/Upload.js");
+require("./ux/file/BrowsePlugin.js");
+require("./ux/file/Download.js");
+require("./ux/form/ColorField.js");
+require("./ux/form/IconTextField.js");
+require("./ux/form/FieldMaximizePlugin.js");
+require("./ux/form/MirrorTextField.js");
+require("./ux/form/ColumnFormPanel.js");
+require("./ux/form/NumberField.js");
+require("./ux/form/PeriodPicker.js");
+require("./ux/form/MoneyField.js");
+require("./widgets/form/DiscountField.js");
+require("./ux/form/BytesField.js");
+require("./ux/form/LayerCombo.js");
+require("./ux/form/ClearableComboBox.js");
+require("./ux/form/ClearableTextField.js");
+require("./widgets/form/VMultiPicker/index.js");
+require("./ux/form/DateTimeField.js");
+require("./ux/form/BooleanCombo.js");
+require("./ux/form/ClearableDateField.js");
+require("./ux/form/ImageField.js");
+require("./ux/form/ImageCropper.js");
+require("./ux/form/Spinner.js");
+require("./ux/form/SpinnerStrategy.js");
+require("./ux/form/DurationSpinner.js");
+require("./ux/form/LockCombo.js");
+require("./ux/form/LockTextfield.js");
+require("./ux/form/HtmlEditor.js");
+require("./ux/form/ComboBoxRecentsPlugin.js");
+require("./ux/layout/HorizontalFitLayout.js");
+require("./ux/layout/CenterLayout.js");
+require("./ux/layout/RowLayout.js");
+require("./ux/layout/cardLayoutHelper.js");
+require("./ux/layout/MultiAccordionLayout.js");
+require("./ux/GMapPanel.js");
+require("./ux/tree/CheckboxSelectionModel.js");
+require("./ux/tree/TreeGridSorter.js");
+require("./ux/tree/TreeGridColumnResizer.js");
+require("./ux/tree/TreeGridNodeUI.js");
+require("./ux/tree/TreeGridLoader.js");
+require("./ux/tree/TreeGridColumns.js");
+require("./ux/tree/TreeGrid.js");
+require("./ux/display/DisplayPanel.js");
+require("./ux/display/DisplayField.js");
+require("./ux/display/DisplayTextArea.js");
+require("./ux/layout/Display.js");
+require("./ux/MessageBox.js");
+require("./ux/TabPanelSortPlugin.js");
+require("./ux/pluginRegistry.js");
+require("./ux/ItemRegistry.js");
+require("./ux/Function.deferByTickets.js");
+require("./ux/Function.createBuffered.js");
+require("./ux/Printer/Printer.js");
+require("./ux/Printer/renderers/Base.js");
+require("./ux/Printer/renderers/GridPanel.js");
+require("./ux/Printer/renderers/ColumnTree.js");
+require("./ux/Printer/renderers/Field.js");
+require("./ux/Printer/renderers/Check.js");
+require("./ux/Printer/renderers/Combo.js");
+require("./ux/Printer/renderers/Container.js");
+require("./ux/Printer/renderers/Panel.js");
+require("./ux/Printer/renderers/Tags.js");
+require("./ux/Printer/renderers/EditDialogRenderer.js");
+require("./data/TitleRendererManager.js");
+Tine.Tinebase.data.Record = require("./data/Record.js").default;
+Tine.Tinebase.data.RecordMgr = require("./data/RecordMgr.js");
+require("./data/RecordStore.js");
+require("./data/GroupedStoreCollection.js");
+require("./data/RecordProxy.js");
+require("./data/AbstractBackend.js");
+require("./data/Clipboard.js");
+require("./RecentsManager.js");
+require("./StateProvider.js");
+require("./AppManager.js");
+require("./ExceptionHandler.js");
+require("./ExceptionHandlerRegistry.js");
+require("./ExceptionDialog.js");
+require("./Container.js");
+require("./EncodingHelper.js");
+Tine.Tinebase.common = require("./common.js");
+require("./configManager.js");
+require("./widgets/grid/RendererManager.js");
+require("./Models.js");
+require("./Application.js");
+require("./widgets/keyfield/Store.js");
+require("./widgets/keyfield/ComboBox.js");
+require("./widgets/keyfield/Renderer.js");
+require("./widgets/LangChooser.js");
+require("./widgets/ActionManager.js");
+require("./widgets/ActionUpdater.js");
+require("./widgets/EditRecord.js");
+require("./widgets/VersionCheck.js");
+require("./widgets/dialog/AlarmPanel.js");
+require("./widgets/dialog/Dialog.js");
+require("./widgets/dialog/EditDialog.js");
+require("./widgets/dialog/SimpleRecordEditDialog.js");
+require("./widgets/dialog/MultipleEditDialogPlugin.js");
+require("./widgets/dialog/AddRelationsEditDialogPlugin.js");
+require("./widgets/dialog/MultipleEditResultSummary.js");
+require("./widgets/display/RecordDisplayPanel.js");
+require("./widgets/display/DefaultDisplayPanel.js");
+require("./ux/TabPanelKeyPlugin.js");
+require("./widgets/dialog/TokenModeEditDialogPlugin.js");
+require("./widgets/dialog/WizardPanel.js");
+require("./widgets/dialog/AdminPanel.js");
+require("./widgets/dialog/CredentialsDialog.js");
+require("./widgets/dialog/PreferencesDialog.js");
+require("./widgets/dialog/PreferencesTreePanel.js");
+require("./widgets/dialog/PreferencesPanel.js");
+require("./widgets/dialog/ImportDialog.js");
+require("./widgets/dialog/SimpleImportDialog.js");
+require("./widgets/dialog/ExportDialog.js");
+require("./widgets/dialog/vue/ModalDialog/index.js");
+require("./widgets/dialog/vue/MultiOptionsDialog/index.js");
+require("./widgets/dialog/vue/ModalDialog/index.js");
+require("./widgets/dialog/FileListDialog.js");
+require("./widgets/dialog/DuplicateMergeDialog.js");
+require("./widgets/dialog/DuplicateResolveGridPanel.js");
+require("./widgets/grid/DetailsPanel.js");
+require("./widgets/grid/FilterModel.js");
+require("./widgets/grid/MonthFilter.js");
+require("./widgets/grid/FilterPlugin.js");
+require("./widgets/grid/FilterButton.js");
+require("./widgets/grid/ExportButton.js");
+require("./widgets/exportAction.js");
+require("./widgets/importAction.js");
+require("./widgets/grid/FilterToolbar.js");
+require("./widgets/grid/FilterStructureTreePanel.js");
+require("./widgets/grid/FilterPanel.js");
+require("./widgets/grid/PickerFilter.js");
+require("./widgets/grid/FilterToolbarQuickFilterPlugin.js");
+require("./widgets/grid/FilterSelectionModel.js");
+require("./widgets/grid/ForeignRecordFilter.js");
+require("./ux/grid/GroupingGridPlugin.js");
+require("./widgets/grid/OwnRecordFilter.js");
+require("./widgets/grid/QuickaddGridPanel.js");
+require("./widgets/grid/FileUploadGrid.js");
+require("./widgets/dialog/AttachmentsGridPanel.js");
+require("./widgets/grid/PickerGridPanel.js");
+require("./widgets/form/FieldManager.js");
+require("./widgets/grid/MappingPickerGridPanel.js");
+require("./widgets/grid/LinkGridPanel.js");
+require("./widgets/grid/FilterModelMultiSelect.js");
+require("./widgets/grid/QuotaRenderer.js");
+require("./widgets/relation/Manager.js");
+require("./widgets/relation/GridRenderer.js");
+require("./widgets/relation/MenuItemManager.js");
+require("./widgets/relation/GenericPickerGridPanel.js");
+require("./widgets/relation/PickerGridPanel.js");
+require("./widgets/printer/RecordRenderer.js");
+require("./widgets/grid/GridPanel.js");
+require("./widgets/grid/BbarGridPanel.js");
+require("./widgets/keyfield/Filter.js");
+require("./widgets/keyfield/ConfigGrid.js");
+require("./widgets/keyfield/ConfigField.js");
+require("./widgets/tree/Loader.js");
+require("./widgets/tree/ContextMenu.js");
+require("./widgets/tree/FilterPlugin.js");
+require("./widgets/customfields/ConfigManager.js");
+require("./widgets/customfields/Field.js");
+require("./widgets/customfields/FilterModel.js");
+require("./widgets/customfields/Renderer.js");
+require("./widgets/customfields/CustomfieldSearchCombo.js");
+require("./widgets/customfields/EditDialogPlugin.js");
+require("./widgets/customfields/CustomfieldsCombo.js");
+require("./widgets/relation/FilterModel.js");
+require("./widgets/relation/Renderer.js");
+require("./widgets/account/PickerGridPanel.js");
+require("./widgets/account/ChangeAccountAction.js");
+require("./widgets/container/SelectionComboBox.js");
+require("./widgets/container/SelectionDialog.js");
+require("./widgets/container/CalDAVContainerPropertiesHookField.js");
+require("./widgets/container/GrantsGrid.js");
+require("./widgets/container/GrantsDialog.js");
+require("./widgets/container/TreePanel.js");
+require("./widgets/container/PropertiesDialog.js");
+require("./widgets/container/FilterModel.js");
+require("./widgets/tags/TagsPanel.js");
+require("./widgets/tags/TagCombo.js");
+require("./widgets/tags/TagToggleBox.js");
+require("./widgets/tags/TagFilter.js");
+require("./widgets/tags/TagsMassAttachAction.js");
+require("./widgets/tags/TagsMassDetachAction.js");
+require("./widgets/mainscreen/WestPanel.js");
+require("./widgets/MainScreen.js");
+require("./LicenseScreen.js");
+require("./CreditsScreen.js");
+require("./widgets/CountryCombo.js");
+require("./widgets/ActivitiesPanel.js");
+require("./widgets/ActivitiesGridPanel.js");
+require("./widgets/form/RecordPickerComboBox.js");
+require("./widgets/relation/PickerCombo.js");
+require("./widgets/grid/PickerGridLayerCombo.js");
+require("./widgets/form/ConfigPanel.js");
+require("./widgets/form/AutoCompleteField.js");
+require("./widgets/form/FileUploadButton.js");
+require("./widgets/form/UidTriggerField.js");
+require("./widgets/form/PasswordTriggerField.js");
+require("./widgets/file/LocationTypePluginFactory.js");
+require("./widgets/file/SelectionField.js");
+require("./widgets/file/MountpointPicker.js");
+require("./widgets/file/mountpointRenderer.js");
+require("./widgets/dialog/vue/PasswordDialog/index.js");
+require("./widgets/dialog/SecondFactorDialog.js");
+require("./widgets/form/RecordForm.js");
+require("./widgets/persistentfilter/Model.js");
+require("./widgets/persistentfilter/Store.js");
+require("./widgets/persistentfilter/PickerPanel.js");
+require("./widgets/persistentfilter/EditPersistentFilterPanel.js");
+require("./widgets/path/renderer.js");
+require("./widgets/dialog/vue/PasswordChangeDialog/index.js");
+require("./AboutDialog.js");
+require("./AppPile.js");
+require("./TineBar/index.js");
+require("./TineDock/index.js");
+require("./AppTabsPanel.js");
+require("./MainContextMenu.js");
+require("./MainMenu.js");
+require("./MainScreenPanel.js");
+require("./LoginPanel.js");
+require("./AdminPanel.js");
+require("./UserProfilePanel.js");
+require("./prototypeTranslations.js");
+require("./CanonicalPath.js");
+require("./PresenceObserver.js");
+require("./PasswordGenerator.js");
+require("./RangeSliderComponent.js");
+require("./widgets/form/FileSelectionArea.js");
+require("./BL/BLConfigPanel.js");
+/* pkg: Tinebase FAT Client (css/Tinebase-FAT.css)*/
+require("../css/ExtFixes.css");
+require("../css/Tinebase.less");
+require("../css/mimetypes.css");
+require("../css/SmallForms.css");
+require("../css/ux/ArrowCollapse.css");
+require("../css/ux/SubFormPanel.css");
+require("../css/ux/ConnectionStatus.css");
+require("../css/ux/Wizard.css");
+require("../css/ux/Percentage.css");
+require("../css/ux/DatePickerWeekPlugin.css");
+require("../css/ux/grid/QuickaddGridPanel.css");
+require("../css/ux/grid/IconTextField.css");
+require("../css/ux/grid/GridDropZone.css");
+require("../css/ux/grid/ActionColumnPlugin.css");
+require("../css/ux/grid/GridViewMenuPlugin.css");
+require("../css/ux/form/ExpandFieldSet.css");
+require("../css/ux/form/ImageField.css");
+require("../css/ux/form/Spinner.css");
+require("../css/ux/form/HtmlEditor.css");
+require("../css/ux/form/LayerCombo.css");
+require("../css/ux/form/PeriodPicker.css");
+require("../css/ux/display/DisplayPanel.css");
+require("../css/ux/layout/CenterLayout.css");
+require("../css/ux/tree/treegrid.css");
+require("../css/ux/LockCombo.css");
+require("../css/ux/LockTextField.css");
+require("../css/ux/Menu.css");
+require("../css/ux/MessageBox.css");
+require("../css/widgets/EditRecord.css");
+require("../css/widgets/TagsPanel.css");
+require("../css/widgets/FilterToolbar.css");
+require("../css/widgets/AccountPicker.css");
+require("../css/widgets/PreviewPanel.css");
+require("../css/widgets/PreferencesPanel.css");
+require("../css/widgets/UidTriggerField.css");
+require("../css/widgets/FileSelectionArea.css");
+require("../css/widgets/PasswordTriggerField.css");
+require("../css/widgets/print.css");
+
require('./MunicipalityKey/model');
require('./MunicipalityKey/explainer');
require('./MunicipalityKey/picker');
diff --git a/tine20/Tinebase/js/app-loader.js b/tine20/Tinebase/js/app-loader.js
index ba09f813feb..52fc5322d64 100644
--- a/tine20/Tinebase/js/app-loader.js
+++ b/tine20/Tinebase/js/app-loader.js
@@ -90,7 +90,7 @@ module.exports = function() {
runtime += ' )}).then(function() {\n';
runtime += ' appLoadedStates[appName] = "fulfilled";\n';
runtime += ' appResolves[appName]();\n';
- runtime += ' }).catch(function() {\n';
+ runtime += ' }).catch(function(e) {\n';
runtime += ' appLoadedStates[appName] = "rejected";\n';
runtime += ' appRejects[appName]();\n';
runtime += ' });\n';
diff --git a/tine20/Tinebase/js/common.js b/tine20/Tinebase/js/common.js
index f86fcf6c658..ab150a28f61 100644
--- a/tine20/Tinebase/js/common.js
+++ b/tine20/Tinebase/js/common.js
@@ -10,12 +10,12 @@
/*global Ext, Tine, Locale*/
-Ext.ns('Tine', 'Tine.Tinebase');
-
+const { isObject, isArray, map, isString, get, escapeRegExp, each, find } = require('lodash')
+const { htmlEncode, htmlDecode, date: dateFormat, number, round, capitalize} = require('Ext/util/Format')
/**
* static common helpers
*/
-Tine.Tinebase.common = {
+const common = {
/**
*
* @param {String} part
@@ -111,7 +111,7 @@ Tine.Tinebase.common = {
*
* @param {mixed} $_iso8601
* @param metadata
- * @see Ext.util.Format.date
+ * @see date
* @return {String} localised date and time
*/
dateTimeRenderer: function ($_iso8601, metadata) {
@@ -135,14 +135,14 @@ Tine.Tinebase.common = {
const dateObj = date instanceof Date ? date : Date.parseDate(date, Date.patterns.ISO8601Long);
const formatDate = (key) => key === 'wkday'
? dateObj.format('l').substr(0, 2)
- : Ext.util.Format.date(dateObj, Locale.getTranslationData('Date', key));
+ : dateFormat(dateObj, Locale.getTranslationData('Date', key));
- const isGridCell = _.isObject(metadata) && metadata.hasOwnProperty('cellAttr');
+ const isGridCell = isObject(metadata) && metadata.hasOwnProperty('cellAttr');
if (isGridCell) {
metadata.css = (metadata.css || '') + ' tine-gird-cell-date';
}
- return dateObj ? _.map(format, (key) => {
+ return dateObj ? map(format, (key) => {
return isGridCell ? `${formatDate(key)}` : formatDate(key);
}).join(' ') : '';
},
@@ -161,7 +161,7 @@ Tine.Tinebase.common = {
// default format by locale and with two decimals
format = '0' + Tine.Tinebase.registry.get('thousandSeparator') + '000' + Tine.Tinebase.registry.get('decimalSeparator') + '00';
}
- return Ext.util.Format.number(v, format);
+ return number(v, format);
},
/**
@@ -181,7 +181,7 @@ Tine.Tinebase.common = {
v = parseInt(v, 10) || 0;
}
- v = Ext.util.Format.number(v, (type == 'float' ? '0.00' : '0'));
+ v = number(v, (type == 'float' ? '0.00' : '0'));
if (type == 'float') {
var decimalSeparator = Tine.Tinebase.registry.get('decimalSeparator');
@@ -204,14 +204,14 @@ Tine.Tinebase.common = {
timeRenderer: function (date, metadata) {
const format = this?.format ? (this.format?.Time || this.format) : ['medium'];
const dateObj = date instanceof Date ? date : Date.parseDate(date, Date.patterns.ISO8601Time);
- const formatTime = (key) => Ext.util.Format.date(dateObj, Locale.getTranslationData('Time', key));
+ const formatTime = (key) => dateFormat(dateObj, Locale.getTranslationData('Time', key));
- const isGridCell = _.isObject(metadata) && metadata.hasOwnProperty('cellAttr');
+ const isGridCell = isObject(metadata) && metadata.hasOwnProperty('cellAttr');
if (isGridCell) {
metadata.css = (metadata.css || '') + ' tine-gird-cell-time';
}
- return dateObj ? _.map(format, (key) => {
+ return dateObj ? map(format, (key) => {
return isGridCell ? `${formatTime(key)}` : formatTime(key);
}).join(' ') : '';
},
@@ -256,7 +256,7 @@ Tine.Tinebase.common = {
if (value < Math.pow(divisor, i)) break;
}
}
- value = ((i<=1) ? value : Ext.util.Format.round(value/(Math.pow(divisor, Math.max(1, i-1))), decimals)) + ' ' + suffix[i];
+ value = ((i<=1) ? value : round(value/(Math.pow(divisor, Math.max(1, i-1))), decimals)) + ' ' + suffix[i];
return String(value).replace('.', decimalSeparator);
},
@@ -370,7 +370,7 @@ Tine.Tinebase.common = {
if (name) {
result = Tine.Tinebase.common.containerRenderer.tpl.apply({
- name: Ext.util.Format.htmlEncode(name).replace(/ /g," "),
+ name: htmlEncode(name).replace(/ /g," "),
color: color ? color : '#808080'
});
} else if (Ext.isObject(metaData)) {
@@ -390,7 +390,7 @@ Tine.Tinebase.common = {
* TODO use/invent renderer registry to show more information on relations
*/
relationsRenderer: function(relations, metaData) {
- if (_.isString(relations)) {
+ if (isString(relations)) {
// e.g. history panel
return relations;
}
@@ -430,7 +430,7 @@ Tine.Tinebase.common = {
}
if (! format || ! Ext.isString(format)) {
- const isGridCell = _.isObject(format) && format.hasOwnProperty('cellAttr');
+ const isGridCell = isObject(format) && format.hasOwnProperty('cellAttr');
const mediumRenderer = (i, H) => {
const minutes = i> 0 ? String.format(i18n.ngettext(`{0} minute`, `{0} minutes`, i), i) : '';
const hours = H > 0 ? String.format(i18n.ngettext(`{0} hour`, `{0} hours`, H), H) : '';
@@ -484,7 +484,7 @@ Tine.Tinebase.common = {
usernameRenderer: function (accountObject) {
var result = (accountObject) ? accountObject.accountDisplayName : '';
- return Ext.util.Format.htmlEncode(result);
+ return htmlEncode(result);
},
/**
@@ -497,13 +497,13 @@ Tine.Tinebase.common = {
let type, iconCls, displayName, email;
if (accountObject.accountDisplayName) {
- type = _.get(record, 'data.account_type', 'user');
+ type = get(record, 'data.account_type', 'user');
const contactRecord = Tine.Tinebase.data.Record.setFromJson({
n_fileas: accountObject.accountDisplayName,
email: accountObject?.accountEmailAddress
}, Tine.Addressbook.Model.Contact);
displayName = contactRecord.getTitle();
- } else if (accountObject.name && ! _.get(record, 'data.account_type')) {
+ } else if (accountObject.name && ! get(record, 'data.account_type')) {
type = 'group';
displayName = accountObject.name;
} else if (record && record.data.name) {
@@ -513,7 +513,7 @@ Tine.Tinebase.common = {
// so odd, - new records, picked via pickerGridPanel
} else if (record && record.data.account_name) {
type = record.data.account_type;
- displayName = _.get(record, 'data.account_name.name', record.data.account_name);
+ displayName = get(record, 'data.account_name.name', record.data.account_name);
}
if (displayName === 'Anyone') {
@@ -521,8 +521,8 @@ Tine.Tinebase.common = {
type = 'group';
}
- iconCls = 'tine-grid-row-action-icon renderer renderer_account' + Ext.util.Format.capitalize(type) + 'Icon';
- return '
' + Ext.util.Format.htmlEncode(displayName || '');
+ iconCls = 'tine-grid-row-action-icon renderer renderer_account' + capitalize(type) + 'Icon';
+ return '
' + htmlEncode(displayName || '');
},
/**
@@ -578,7 +578,7 @@ Tine.Tinebase.common = {
// normalize
color = String(color).replace('#', '');
- return '
';
+ return '
';
},
/**
@@ -691,9 +691,8 @@ Tine.Tinebase.common = {
* @return {mixed} o
*/
assertComparable: function(o) {
- // NOTE: Ext estimates Object/Array by a toString operation
- if (Ext.isObject(o) || Ext.isArray(o)) {
- Tine.Tinebase.common.applyComparableToString(o);
+ if (isObject(o) || isArray(o)) {
+ common.applyComparableToString(o);
}
return o;
@@ -705,7 +704,7 @@ Tine.Tinebase.common = {
* @param {mixed} o
*/
applyComparableToString: function(o) {
- o.toString = function() {return Ext.encode(o)};
+ o.toString = function() {return JSON.stringify(o)};
},
/**
@@ -786,7 +785,7 @@ Tine.Tinebase.common = {
* @return {String}
*/
doubleEncode: function(value) {
- return Ext.util.Format.htmlEncode(Ext.util.Format.htmlEncode(value));
+ return htmlEncode(htmlEncode(value));
},
/**
@@ -807,7 +806,7 @@ Tine.Tinebase.common = {
.replace(/--block\n--br/g, '')
.replace(/(--block|--br)/g, '');
- return Ext.util.Format.htmlDecode(text);
+ return htmlDecode(text);
},
/**
@@ -844,7 +843,7 @@ Tine.Tinebase.common = {
}
// find record from deeplink
- const urlRegex = '^' + _.escapeRegExp(Tine.Tinebase.common.getUrl());
+ const urlRegex = '^' + escapeRegExp(Tine.Tinebase.common.getUrl());
const recordRegex = '#\/(?[a-zA-Z]+)\/(?[a-zA-Z]+)\/(?[a-f0-9]{40,})';
const regex = new RegExp(`${urlRegex}${recordRegex}`);
const matches = target?.dom?.href.match(regex);
@@ -883,7 +882,7 @@ Tine.Tinebase.common = {
addresses = addresses.replaceAll(';', ',');
addresses = addresses.replace(/['"]+/g, '');
- addresses = _.compact(addresses.split(','));
+ addresses = compact(addresses.split(','));
const {default: addrs} = await import(/* webpackChunkName: "Tinebase/js/email-addresses" */ 'email-addresses')
@@ -896,18 +895,18 @@ Tine.Tinebase.common = {
if (address) parsedList.push(address);
})
- const emails = _.map(parsedList, (parsed) => {
+ const emails = map(parsedList, (parsed) => {
return parsed.address ?? '';
});
- const names = _.map(parsedList, (parsed) => {
+ const names = map(parsedList, (parsed) => {
return parsed?.name ?? '';
});
const {results: tokens} = await Tine.Addressbook.searchRecipientTokensByEmailArrays(emails, names);
- _.each(parsedList, (parsed) => {
+ each(parsedList, (parsed) => {
if (!parsed.address) return;
- const existingToken = _.find(tokens, function (token) {
+ const existingToken = find(tokens, function (token) {
return parsed.address === token['email'];
});
@@ -1015,13 +1014,4 @@ Tine.Tinebase.common = {
},
};
-/*
-var s = 'Hello,
...
';
-if (Tine.Tinebase.common.html2text(s) != "\nHello,\n\n...") console.error('ignore empty div: "' + Tine.Tinebase.common.html2text(s) + '"');
-
-var s = 'Dipl.-Phys. Cornelius WeissTeam Leader Software Engineering
';
-if (Tine.Tinebase.common.html2text(s) != "Dipl.-Phys. Cornelius Weiss\nTeam Leader Software Engineering") console.error('cope with styled div tag: ' + Tine.Tinebase.common.html2text(s));
-
-var s = '';
-if (Tine.Tinebase.common.html2text(s) != "\n") console.error('cope with nested blocks: "' + Tine.Tinebase.common.html2text(s) + '"');
-*/
+module.exports = common;
diff --git a/tine20/Tinebase/js/data/Record.js b/tine20/Tinebase/js/data/Record.js
index 0f0ba8fe678..4ee9566b7fb 100644
--- a/tine20/Tinebase/js/data/Record.js
+++ b/tine20/Tinebase/js/data/Record.js
@@ -5,17 +5,31 @@
* @subpackage Tinebase
* @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
* @author Cornelius Weiss
- * @copyright Copyright (c) 2007-2008 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright Copyright (c) 2007-2024 Metaways Infosystems GmbH (http://www.metaways.de)
*/
+const { apply, extend, isPrimitive, isArray, isString } = require("Ext/core/core/Ext");
+const { emptyFn } = require("Ext/core/Ext-more");
+const { lowerFirst, get, find, forEach, isFunction, isObject, indexOf, map, difference, compact } = require('lodash');
+const ExtRecord = require("Ext/data/Record");
+const MixedCollection = require("Ext/util/MixedCollection");
+const Field = require("Ext/data/DataField");
+const JsonReader = require("Ext/data/JsonReader");
+const recordMgr = require("./RecordMgr");
+const { assertComparable } = require("common")
+import log from "ux/Log.js"
+
+// getTitle() dependenciesn - use dynamic includes? (also twig)
+// - Tine.Tinebase.appMgr
+// - Tine.Tinebase.data.TitleRendererManager
+// - Tine.Tinebase.widgets.keyfield
+
// @see https://github.com/ericmorand/twing/issues/332
-// #if process.env.NODE_ENV !== 'unittest'
-import getTwingEnv from "twingEnv";
+// #if typeof window !== "undefined"
+import getTwingEnv from "twingEnv.es6";
// #endif
-Ext.ns('Tine.Tinebase', 'Tine.Tinebase.data');
-
-Tine.Tinebase.data.Record = function(data, id) {
+const Record = function(data, id) {
if (id || id === 0) {
this.id = id;
if (!data[this.idProperty]) {
@@ -24,7 +38,7 @@ Tine.Tinebase.data.Record = function(data, id) {
} else if (data[this.idProperty]) {
this.id = data[this.idProperty];
} else {
- this.id = ++Ext.data.Record.AUTO_ID;
+ this.id = ++ExtRecord.AUTO_ID;
}
this.data = data;
this.initData();
@@ -33,12 +47,12 @@ Tine.Tinebase.data.Record = function(data, id) {
/**
* @namespace Tine.Tinebase.data
- * @class Tine.Tinebase.data.Record
+ * @class Record
* @extends Ext.data.Record
*
* Baseclass of Tine 2.0 models
*/
-Ext.extend(Tine.Tinebase.data.Record, Ext.data.Record, {
+extend(Record, ExtRecord, {
/**
* @cfg {String} appName
* internal/untranslated app name (required)
@@ -105,11 +119,11 @@ Ext.extend(Tine.Tinebase.data.Record, Ext.data.Record, {
/**
* template fn called when record is instanciated
*/
- initData: Ext.emptyFn,
+ initData: emptyFn,
/**
- * Get the value of the {@link Ext.data.Field#name named field}.
- * @param {String} name The {@link Ext.data.Field#name name of the field} to get the value of.
+ * Get the value of the {@link Field#name named field}.
+ * @param {String} name The {@link Field#name name of the field} to get the value of.
* @return {Object} The value of the field.
*/
get: function(name) {
@@ -123,12 +137,12 @@ Ext.extend(Tine.Tinebase.data.Record, Ext.data.Record, {
},
/**
- * Set the value of the {@link Ext.data.Field#name named field}.
- * @param {String} name The {@link Ext.data.Field#name name of the field} to get the value of.
+ * Set the value of the {@link Field#name named field}.
+ * @param {String} name The {@link Field#name name of the field} to get the value of.
* @return {Object} The value of the field.
*/
set : function(name, value) {
- var encode = Ext.isPrimitive(value) ? String : Ext.encode,
+ var encode = isPrimitive(value) ? String : JSON.stringify,
current = this.get(name),
cfName;
@@ -152,7 +166,7 @@ Ext.extend(Tine.Tinebase.data.Record, Ext.data.Record, {
var oldValueJSON = JSON.stringify(this.get('customfields') || {}),
valueObject = JSON.parse(oldValueJSON);
- Tine.Tinebase.common.assertComparable(valueObject);
+ assertComparable(valueObject);
valueObject[cfName[1]] = value;
if (JSON.stringify(valueObject) != oldValueJSON) {
@@ -176,7 +190,7 @@ Ext.extend(Tine.Tinebase.data.Record, Ext.data.Record, {
var _ = window.lodash,
me = this;
- const template = Tine.Tinebase.appMgr.get(this.appName).getRegistry().get('preferences')?.get(`${_.lowerFirst(this.modelName)}TitleTemplate`);
+ const template = Tine.Tinebase.appMgr.get(this.appName).getRegistry().get('preferences')?.get(`${lowerFirst(this.modelName)}TitleTemplate`);
if (template) {
this.titleProperty = template;
}
@@ -197,17 +211,17 @@ Ext.extend(Tine.Tinebase.data.Record, Ext.data.Record, {
}
return this.constructor.titleTwing.renderProxy(this.constructor.getPhpClassName() + 'Title', Object.assign({record: this}, this.data));
- } else if (_.get(this.fields.get(this.titleProperty), 'fieldDefinition.config.specialType') === 'localizedString') {
+ } else if (get(this.fields.get(this.titleProperty), 'fieldDefinition.config.specialType') === 'localizedString') {
// const keyFieldDef = Tine.Tinebase.widgets.keyfield.getDefinitionFromMC(this.constructor, this.titleProperty);
- const languagesAvailableDef = _.get(this.constructor.getModelConfiguration(), 'languagesAvailable')
- const keyFieldDef = Tine.Tinebase.widgets.keyfield.getDefinition(_.get(languagesAvailableDef, 'config.appName', this.appName), languagesAvailableDef.name)
+ const languagesAvailableDef = get(this.constructor.getModelConfiguration(), 'languagesAvailable')
+ const keyFieldDef = Tine.Tinebase.widgets.keyfield.getDefinition(get(languagesAvailableDef, 'config.appName', this.appName), languagesAvailableDef.name)
let language = options?.language || keyFieldDef.default;
const value = this.get(this.titleProperty);
const preferredLanguage = Tine.Tinebase.registry.get('preferences')?.get('locale');
if (preferredLanguage !== 'auto') {
language = preferredLanguage;
}
- return _.get(_.find(value, { language }), 'text', '') || _.find(value, (r) => {return r.text})?.text || i18n._('Translation not found')
+ return get(find(value, { language }), 'text', '') || find(value, (r) => {return r.text})?.text || i18n._('Translation not found')
} else {
var s = this.titleProperty ? this.titleProperty.split('.') : [null];
return (s.length > 0 && this.get(s[0]) && this.get(s[0])[s[1]]) ? this.get(s[0])[s[1]] : s[0] ? this.get(this.titleProperty) : '';
@@ -236,7 +250,7 @@ Ext.extend(Tine.Tinebase.data.Record, Ext.data.Record, {
* @return {String}
*/
toString: function() {
- return Ext.encode(this.data);
+ return JSON.stringify(this.data);
},
toJSON: function() {
@@ -250,12 +264,12 @@ Ext.extend(Tine.Tinebase.data.Record, Ext.data.Record, {
* handling of updated records work in the grid panel
* @see 0009464: user grid does not refresh after ctx menu action
*
- * @param {Tine.Tinebase.data.Record} record
+ * @param {Record} record
* @return {Boolean}
*/
isObsoletedBy: function(record) {
if (record.modelName !== this.modelName || record.getId() !== this.getId()) {
- throw new Ext.Error('Records could not be compared');
+ throw new Error('Records could not be compared');
}
if (this.constructor.hasField('seq') && record.get('seq') != this.get('seq')) {
@@ -275,13 +289,13 @@ Ext.extend(Tine.Tinebase.data.Record, Ext.data.Record, {
* @param record
*/
update: function(record) {
- record = _.get(record, 'data', false) ? record :
- Tine.Tinebase.data.Record.setFromJson(record, this.constructor);
+ record = get(record, 'data', false) ? record :
+ Record.setFromJson(record, this.constructor);
this.beginEdit();
this.fields.each((field) => {
- let newValue = Tine.Tinebase.common.assertComparable(record.get(field.name));
- Tine.Tinebase.common.assertComparable(_.get(this, 'data.' + field.name));
+ let newValue = assertComparable(record.get(field.name));
+ assertComparable(get(this, 'data.' + field.name));
this.set(field.name, newValue);
}, this);
this.endEdit();
@@ -291,18 +305,18 @@ Ext.extend(Tine.Tinebase.data.Record, Ext.data.Record, {
const fieldDefs = this.constructor.getModelConfiguration().fields;
const pms = [];
- _.each(this.constructor.getModelConfiguration().fields, (def, fieldName) => {
- if (fields && _.indexOf(fields, fieldName) < 0) return;
+ forEach(this.constructor.getModelConfiguration().fields, (def, fieldName) => {
+ if (fields && indexOf(fields, fieldName) < 0) return;
let value = this.get(fieldName);
- if (_.get(def, 'type') === 'record' && value && ! _.isFunction(_.get(value, 'beginEdit'))) {
- const recordClass = Tine.Tinebase.data.RecordMgr.get(def.config.appName, def.config.modelName);
+ if (get(def, 'type') === 'record' && value && ! isFunction(get(value, 'beginEdit'))) {
+ const recordClass = recordMgr.get(def.config.appName, def.config.modelName);
if (! recordClass) return;
- if (String(value)[0] === '{' || _.isObject(value)) {
- this.set(fieldName, Tine.Tinebase.data.Record.setFromJson(value, recordClass));
+ if (String(value)[0] === '{' || isObject(value)) {
+ this.set(fieldName, Record.setFromJson(value, recordClass));
} else {
- const proxy = new Tine.Tinebase.data.RecordProxy({
+ const proxy = new RecordProxy({
recordClass: recordClass
});
pms.push(proxy.promiseLoadRecord(value)
@@ -321,12 +335,12 @@ Ext.extend(Tine.Tinebase.data.Record, Ext.data.Record, {
* Generate a constructor for a specific Record layout.
*
* @param {Array} def see {@link Ext.data.Record#create}
- * @param {Object} meta information see {@link Tine.Tinebase.data.Record}
+ * @param {Object} meta information see {@link Record}
*
*
usage:
IMPORTANT: the ngettext comments are required for the translation system!
-var TopicRecord = Tine.Tinebase.data.Record.create([
+var TopicRecord = Record.create([
{name: 'summary', mapping: 'topic_title'},
{name: 'details', mapping: 'username'}
], {
@@ -345,11 +359,11 @@ var TopicRecord = Tine.Tinebase.data.Record.create([
* @static
*/
-Tine.Tinebase.data.Record.create = function(o, meta) {
- var f = Ext.extend(Tine.Tinebase.data.Record, {});
+Record.create = function(o, meta) {
+ var f = extend(Record, {});
var p = f.prototype;
- Ext.apply(p, meta);
- p.fields = new Ext.util.MixedCollection(false, function(field) {
+ apply(p, meta);
+ p.fields = new MixedCollection(false, function(field) {
return field.name;
});
p.fields.get = function(name) {
@@ -360,14 +374,14 @@ Tine.Tinebase.data.Record.create = function(o, meta) {
sortDir: 'DESC'
};
} else {
- return Ext.util.MixedCollection.prototype.get.apply(this, arguments);
+ return MixedCollection.prototype.get.apply(this, arguments);
}
};
for(var i = 0, len = o.length; i < len; i++) {
if (o[i]['name'] == meta.containerProperty && meta.allowBlankContainer === false) {
o[i]['allowBlank'] = false;
}
- p.fields.add(new Ext.data.Field(o[i]));
+ p.fields.add(new Field(o[i]));
}
f.getField = function(name) {
return p.fields.get(name);
@@ -392,7 +406,7 @@ Tine.Tinebase.data.Record.create = function(o, meta) {
f.getFieldNames = function() {
if (! p.fieldsarray) {
var arr = p.fieldsarray = [];
- Ext.each(p.fields.items, function(item) {arr.push(item.name);});
+ forEach(p.fields.items, function(item) {arr.push(item.name);});
}
return p.fieldsarray;
};
@@ -400,11 +414,11 @@ Tine.Tinebase.data.Record.create = function(o, meta) {
return p.fields.indexOfKey(n) >= 0;
};
f.getDataFields = function() {
- const systemFields = _.map(Tine.Tinebase.Model.genericFields, 'name')
+ const systemFields = map(Record.genericFields, 'name')
.concat(f.getMeta('idProperty'))
.concat(p.modelConfiguration?.hasNotes ? [] : 'notes')
.concat(p.modelConfiguration?.delegateAclField && p.grantsPath ? String(p.grantsPath).replace(/^data\./, '') : []);
- return _.difference(p.modelConfiguration?.fieldKeys, systemFields);
+ return difference(p.modelConfiguration?.fieldKeys, systemFields);
};
f.getRecordName = function() {
var app = Tine.Tinebase.appMgr.get(p.appName),
@@ -477,18 +491,18 @@ Tine.Tinebase.data.Record.create = function(o, meta) {
return f.getMeta('phpClassName');
}
// if var app is a record class, the getMeta method is called
- if (Ext.isFunction(app.getMeta)) {
+ if (isFunction(app.getMeta)) {
return app.getMeta('phpClassName');
}
- var appName = (Ext.isObject(app) && app.hasOwnProperty('name')) ? app.name : app;
+ var appName = (isObject(app) && app.hasOwnProperty('name')) ? app.name : app;
return appName + '_Model_' + model;
};
f.getModelConfiguration = function() {
return p.modelConfiguration;
};
f.getProxy = function() {
- return _.get(window, `Tine.${p.appName}.${p.modelName.toLowerCase()}Backend`);
+ return get(window, `Tine.${p.appName}.${p.modelName.toLowerCase()}Backend`);
}
// sanitize containerProperty label
@@ -502,11 +516,11 @@ Tine.Tinebase.data.Record.create = function(o, meta) {
if (!p.grantsPath) {
p.grantsPath = 'data' + (containerProperty ? ('.' + containerProperty) : '') + '.account_grants';
}
- Tine.Tinebase.data.RecordMgr.add(f);
+ recordMgr.add(f);
return f;
};
-Tine.Tinebase.data.Record.generateUID = function(length) {
+Record.generateUID = function(length) {
length = length || 40;
var s = '0123456789abcdef',
@@ -517,17 +531,17 @@ Tine.Tinebase.data.Record.generateUID = function(length) {
return uuid.join('');
};
-Tine.Tinebase.data.Record.getDefaultData = function(recordClass, defaults) {
+Record.getDefaultData = function(recordClass, defaults) {
var modelConfig = recordClass.getModelConfiguration(),
appName = modelConfig.appName,
modelName = modelConfig.modelName;
// if default data is empty, it will be resolved to an array
- if (Ext.isArray(modelConfig.defaultData)) {
+ if (isArray(modelConfig.defaultData)) {
modelConfig.defaultData = {};
}
- const dd = Ext.decode(Ext.encode(modelConfig.defaultData));
+ const dd = JSON.parse(JSON.stringify(modelConfig.defaultData));
// find container by selection or use defaultContainer by registry
if (modelConfig.containerProperty) {
@@ -536,7 +550,7 @@ Tine.Tinebase.data.Record.getDefaultData = function(recordClass, defaults) {
registry = app.getRegistry(),
ctp = app.getMainScreen().getWestPanel().getContainerTreePanel();
- var container = (ctp && Ext.isFunction(ctp.getDefaultContainer) ? ctp.getDefaultContainer() : null)
+ var container = (ctp && isFunction(ctp.getDefaultContainer) ? ctp.getDefaultContainer() : null)
|| (registry ? registry.get("default" + modelName + "Container") : null);
if (container) {
@@ -549,8 +563,8 @@ Tine.Tinebase.data.Record.getDefaultData = function(recordClass, defaults) {
dd['account_grants'] = {'adminGrant': true};
// NOTE: ui config overwrites db config
- _.forEach(modelConfig.fields, (config, name) => {
- const fieldDefault = _.get(config, 'uiconfig.default', this);
+ forEach(modelConfig.fields, (config, name) => {
+ const fieldDefault = get(config, 'uiconfig.default', this);
if (fieldDefault !== this) {
dd[name] = fieldDefault;
}
@@ -559,76 +573,17 @@ Tine.Tinebase.data.Record.getDefaultData = function(recordClass, defaults) {
return Object.assign(dd, defaults);
};
-Tine.Tinebase.data.RecordManager = Ext.extend(Ext.util.MixedCollection, {
- add: function(record) {
- if (! Ext.isFunction(record.getMeta)) {
- throw new Ext.Error('only records of type Tinebase.data.Record could be added');
- }
- var appName = record.getMeta('appName'),
- modelName = record.getMeta('modelName');
-
- if (! appName && modelName) {
- throw new Ext.Error('appName and modelName must be in the metadatas');
- }
-
- Tine.Tinebase.data.RecordManager.superclass.add.call(this, appName + '.' + modelName, record);
- },
-
- get: function(appName, modelName) {
- if (! appName && _.isFunction(_.get(modelName, 'getMeta'))) {
- return modelName;
- }
- if (! appName) return;
- if (Ext.isFunction(appName.getField)) {
- return appName;
- }
- if (! modelName && appName.modelName) {
- modelName = appName.modelName;
- }
- if (appName.appName) {
- appName = appName.appName;
- }
-
- if (_.isString(appName) && !modelName) {
- appName = appName.replace(/^Tine[._]/, '')
- .replace(/[._]Model[._]/, '.');
-
- let appPart = appName.match(/^.+\./);
- if (appPart) {
- modelName = appName.replace(appPart[0], '')
- appName = appPart[0].replace(/\.$/, '');
- }
- }
-
- if (! Ext.isString(appName)) {
- throw new Ext.Error('appName must be a string');
- }
-
- Ext.each([appName, modelName], function(what) {
- if (! Ext.isString(what)) return;
- var parts = what.split(/(?:_Model_)|(?:\.)/);
- if (parts.length > 1) {
- appName = parts[0];
- modelName = parts[1];
- }
- });
-
- return Tine.Tinebase.data.RecordManager.superclass.get.call(this, appName + '.' + modelName);
- }
-});
-Tine.Tinebase.data.RecordMgr = new Tine.Tinebase.data.RecordManager(true);
-
/**
* create record from json string
*
* @param {String} json
- * @param {Tine.Tinebase.data.Record} recordClass
- * @returns {Tine.Tinebase.data.Record}
+ * @param {Record} recordClass
+ * @returns {Record}
*/
-Tine.Tinebase.data.Record.setFromJson = function(json, recordClass) {
- recordClass = Tine.Tinebase.data.RecordMgr.get(recordClass);
+Record.setFromJson = function(json, recordClass) {
+ recordClass = recordMgr.get(recordClass);
if (!recordClass) return null;
- var jsonReader = new Ext.data.JsonReader({
+ var jsonReader = new JsonReader({
id: recordClass.idProperty,
root: 'results',
totalProperty: 'totalcount'
@@ -636,20 +591,20 @@ Tine.Tinebase.data.Record.setFromJson = function(json, recordClass) {
try {
var recordData = {
- results: _.compact([
- Ext.isString(json) ? Ext.decode(json) : json
+ results: compact([
+ isString(json) ? JSON.parse(json) : json
])
},
data = jsonReader.readRecords(recordData),
record = data.records[0];
} catch (e) {
- Tine.log.warn('Exception in setFromJson:');
- Tine.log.warn(e);
+ log.warn('Exception in setFromJson:');
+ log.warn(e);
}
- let recordId = _.get(record, 'data.' + _.get(record, 'idProperty'));
+ let recordId = get(record, 'data.' + get(record, 'idProperty'));
if (!recordId && [0, '0'].indexOf(recordId) < 0 ) {
- recordId = Tine.Tinebase.data.Record.generateUID();
+ recordId = Record.generateUID();
}
if (! record) {
@@ -660,3 +615,31 @@ Tine.Tinebase.data.Record.setFromJson = function(json, recordClass) {
return record;
};
+
+/**
+ * @type {Array}
+ *
+ * modlog Fields
+ */
+
+Record.modlogFields = [
+ { name: 'creation_time', type: 'date', dateFormat: "Y-m-d H:i:s", omitDuplicateResolving: true },
+ { name: 'created_by', omitDuplicateResolving: true },
+ { name: 'last_modified_time', type: 'date', dateFormat: "Y-m-d H:i:s", omitDuplicateResolving: true },
+ { name: 'last_modified_by', omitDuplicateResolving: true },
+ { name: 'is_deleted', type: 'boolean', omitDuplicateResolving: true },
+ { name: 'deleted_time', type: 'date', dateFormat: "Y-m-d H:i:s", omitDuplicateResolving: true },
+ { name: 'deleted_by', omitDuplicateResolving: true },
+ { name: 'seq', omitDuplicateResolving: true }
+];
+
+/**
+ * @type {Array}
+ * generic Record fields
+ */
+Record.genericFields = Record.modlogFields.concat([
+ { name: 'container_id', header: 'Container', omitDuplicateResolving: false}
+]);
+
+
+export default Record
diff --git a/tine20/Tinebase/js/data/RecordMgr.js b/tine20/Tinebase/js/data/RecordMgr.js
new file mode 100644
index 00000000000..9f508e072ba
--- /dev/null
+++ b/tine20/Tinebase/js/data/RecordMgr.js
@@ -0,0 +1,73 @@
+/*
+ * Tine 2.0
+ *
+ * @package Tine
+ * @subpackage Tinebase
+ * @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author Cornelius Weiss
+ * @copyright Copyright (c) 2007-2024 Metaways Infosystems GmbH (http://www.metaways.de)
+ */
+
+const { extend, each } = require("Ext/core/core/Ext");
+const MixedCollection = require("Ext/util/MixedCollection");
+const { isFunction, get, isString} = require('lodash');
+
+const RecordMgr = extend(MixedCollection, {
+ add: function(record) {
+ if (! isFunction(record.getMeta)) {
+ throw new Error('only records of type Tinebase.data.Record could be added');
+ }
+ var appName = record.getMeta('appName'),
+ modelName = record.getMeta('modelName');
+
+ if (! appName && modelName) {
+ throw new Error('appName and modelName must be in the metadatas');
+ }
+
+ RecordMgr.superclass.add.call(this, appName + '.' + modelName, record);
+ },
+
+ get: function(appName, modelName) {
+ if (! appName && isFunction(get(modelName, 'getMeta'))) {
+ return modelName;
+ }
+ if (! appName) return;
+ if (isFunction(appName.getField)) {
+ return appName;
+ }
+ if (! modelName && appName.modelName) {
+ modelName = appName.modelName;
+ }
+ if (appName.appName) {
+ appName = appName.appName;
+ }
+
+ if (isString(appName) && !modelName) {
+ appName = appName.replace(/^Tine[._]/, '')
+ .replace(/[._]Model[._]/, '.');
+
+ let appPart = appName.match(/^.+\./);
+ if (appPart) {
+ modelName = appName.replace(appPart[0], '')
+ appName = appPart[0].replace(/\.$/, '');
+ }
+ }
+
+ if (! isString(appName)) {
+ throw new Error('appName must be a string');
+ }
+
+ each([appName, modelName], function(what) {
+ if (! isString(what)) return;
+ var parts = what.split(/(?:_Model_)|(?:\.)/);
+ if (parts.length > 1) {
+ appName = parts[0];
+ modelName = parts[1];
+ }
+ });
+
+ return RecordMgr.superclass.get.call(this, appName + '.' + modelName);
+ }
+});
+
+module.exports = new RecordMgr(true);
\ No newline at end of file
diff --git a/tine20/Tinebase/js/package.json b/tine20/Tinebase/js/package.json
index cad57f6a780..eaa9ab623ec 100644
--- a/tine20/Tinebase/js/package.json
+++ b/tine20/Tinebase/js/package.json
@@ -6,6 +6,7 @@
"start": "./node_modules/webpack-dev-server/bin/webpack-dev-server.js --config webpack.dev.js",
"build": "./node_modules/webpack/bin/webpack.js --progress --config webpack.prod.js",
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js -c /usr/share/tests/js/jest/jest.config.js",
+ "test-dbg": "node --experimental-vm-modules --inspect-brk=0.0.0.0 node_modules/jest/bin/jest.js --runInBand -c /usr/share/tests/js/jest/jest.config.js",
"test:watch": "NODE_ENV=unittest karma start karma.unittest.conf.js",
"test:watchnoreports": "NODE_ENV=unittest karma start karma.unittest.noreports.conf.js"
},
diff --git a/tine20/Tinebase/js/tineInit.js b/tine20/Tinebase/js/tineInit.js
index 46075258c7c..3c78111b898 100644
--- a/tine20/Tinebase/js/tineInit.js
+++ b/tine20/Tinebase/js/tineInit.js
@@ -25,11 +25,6 @@ Ext.ux.Printer.BaseRenderer.prototype.stylesheetPath = 'Tinebase/js/ux/Printer/p
/** ------------------------ Tine 2.0 Initialisation ----------------------- **/
-/**
- * @class Tine
- */
-Ext.namespace('Tine');
-
/**
* version of Tine 2.0 javascript client version, gets set a build / release time
* Supported Properties:
@@ -77,7 +72,7 @@ Tine.onAllAppsLoaded = () => {
/**
* quiet logging in release mode
*/
-Tine.log = Ext.ux.log;
+Tine.log = require("./ux/Log.js").default;
Tine.log.setPrio(Tine.clientVersion.buildType === 'RELEASE' ? 0 : 7);
/**
diff --git a/tine20/Tinebase/js/twingEnv.es6.js b/tine20/Tinebase/js/twingEnv.es6.js
index 7594bcdec07..46326fbb07c 100644
--- a/tine20/Tinebase/js/twingEnv.es6.js
+++ b/tine20/Tinebase/js/twingEnv.es6.js
@@ -24,9 +24,11 @@ class Expression extends String {
let proxyId = 0
const replaceProxyFns = {}
-const proxyDocuments = [
- document
-]
+const proxyDocuments = []
+if (typeof window !== 'undefined') {
+ proxyDocuments.push(document)
+}
+
const proxyPromisesCollections = []
/**
diff --git a/tine20/Tinebase/js/ux/Log.js b/tine20/Tinebase/js/ux/Log.js
index 82806c435b6..8f494ee9e00 100644
--- a/tine20/Tinebase/js/ux/Log.js
+++ b/tine20/Tinebase/js/ux/Log.js
@@ -1,4 +1,5 @@
-Ext.ns('Ext.ux');
+
+
/**
* logging extension (only to console atm.)
@@ -9,9 +10,9 @@ Ext.ns('Ext.ux');
* @namespace Ext.ux.log
* @author Cornelius Weiss
*/
-Ext.ux.log = window.console || {};
+const log = (typeof window !== "undefined" ? window : global)['console'];
-Ext.apply(Ext.ux.log, {
+Object.assign(log, {
/**
* @cfg {Number} prio (defaults to 7)
*/
@@ -65,15 +66,11 @@ Ext.apply(Ext.ux.log, {
* @param {Number} prio
*/
setPrio: function(prio) {
- this.PRIO = Ext.LOGLEVEL = prio;
+ this.PRIO = prio;
for (var name in this.priorities) {
- this[name] = this[name.toLowerCase()] = prio >= this.priorities[name] ? this.prioLogFnMap[name] : Ext.emptyFn;
+ this[name] = this[name.toLowerCase()] = prio >= this.priorities[name] ? this.prioLogFnMap[name] : function(){};
}
}
});
-// init Ext.ux.log
-Ext.onReady(function() {
- Ext.ux.log.setPrio(Ext.LOGLEVEL||8);
- Ext.ux.log.debug('logger initialized');
-});
+export default log
\ No newline at end of file
diff --git a/tine20/Tinebase/js/webpack.common.js b/tine20/Tinebase/js/webpack.common.js
index 9216b6355e5..6ca8753a656 100644
--- a/tine20/Tinebase/js/webpack.common.js
+++ b/tine20/Tinebase/js/webpack.common.js
@@ -208,6 +208,7 @@ module.exports = {
alias: {
// convinence alias
"tine-vue$": path.resolve(__dirname, "node_modules/vue/dist/vue.runtime.esm-bundler.js"),
+ "Ext": path.resolve(__dirname, "../../library/ExtJS/src/"),
}
}
};
diff --git a/tine20/library/ExtJS/ext-custom.js b/tine20/library/ExtJS/ext-custom.js
index bbaaac7825f..4be3bcb9f65 100644
--- a/tine20/library/ExtJS/ext-custom.js
+++ b/tine20/library/ExtJS/ext-custom.js
@@ -1,8 +1,8 @@
// custom ext definition
/* pkg: Ext Base (adapter/ext/ext-base.js)*/
-require('./src/core/core/Ext');
-require('./src/core/Ext-more');
+(typeof window !== "undefined" ? window : global)['Ext'] = require('./src/core/core/Ext');
+Object.assign(Ext, require('./src/core/Ext-more'));
require('./src/util/core/TaskMgr');
require('./src/adapter/ext-core');
@@ -12,8 +12,8 @@ require('./src/core/DomHelper-more');
require('./src/core/core/Template');
require('./src/core/Template-more');
require('./src/core/core/DomQuery');
-require('./src/util/core/DelayedTask');
-require('./src/util/core/Observable');
+Ext.util.DelayedTask = require('./src/util/core/DelayedTask');
+Object.assign(Ext.util, require('./src/util/core/Observable'));
require('./src/util/Observable-more');
require('./src/core/core/EventManager');
require('./src/core/EventManager-more');
@@ -40,9 +40,9 @@ require('./src/core/CompositeElement');
require('./src/data/core/Connection');
require('./src/util/UpdateManager');
require('./src/util/Date');
-require('./src/util/MixedCollection');
+Ext.util.MixedCollection = require('./src/util/MixedCollection');
require('./src/util/core/JSON');
-require('./src/util/Format');
+Ext.util.Format = require('./src/util/Format');
require('./src/util/XTemplate');
require('./src/util/CSS');
require('./src/util/ClickRepeater');
@@ -50,7 +50,7 @@ require('./src/util/KeyNav');
require('./src/util/KeyMap');
require('./src/util/TextMetrics');
require('./src/util/Cookies');
-require('./src/core/Error');
+Ext.Error = require('./src/core/Error');
/* pkg: Component Foundation (pkgs/cmp-foundation.js)*/
require('./src/widgets/ComponentMgr');
@@ -98,23 +98,23 @@ require('./src/core/Element.dd');
/* pkg: Data Foundation (pkgs/data-foundation.js)*/
require('./src/data/Api');
-require('./src/data/SortTypes');
-require('./src/data/Record');
+Ext.data.SortTypes = require('./src/data/SortTypes');
+Ext.data.Record = require('./src/data/Record');
require('./src/data/StoreMgr');
require('./src/data/Store');
-require('./src/data/DataField');
-require('./src/data/DataReader');
+Ext.data.Field = require('./src/data/DataField');
+Ext.data.DataReader = require('./src/data/DataReader');
require('./src/data/DataWriter');
require('./src/data/DataProxy');
require('./src/data/Request');
-require('./src/data/Response');
+Ext.data.Response = require('./src/data/Response');
require('./src/data/ScriptTagProxy');
require('./src/data/HttpProxy');
require('./src/data/MemoryProxy');
/* pkg: Data - Json (pkgs/data-json.js)*/
require('./src/data/JsonWriter');
-require('./src/data/JsonReader');
+Ext.data.JsonReader = require('./src/data/JsonReader');
require('./src/data/ArrayReader');
require('./src/data/ArrayStore');
require('./src/data/JsonStore');
diff --git a/tine20/library/ExtJS/src/core/Error.js b/tine20/library/ExtJS/src/core/Error.js
index 87c91d8ae3f..0c54d2b5bb0 100644
--- a/tine20/library/ExtJS/src/core/Error.js
+++ b/tine20/library/ExtJS/src/core/Error.js
@@ -4,16 +4,6 @@
* licensing@extjs.com
* http://www.extjs.com/license
*/
-/**
- * Framework-wide error-handler. Developers can override this method to provide
- * custom exception-handling. Framework errors will often extend from the base
- * Ext.Error class.
- * @param {Object/Error} e The thrown exception object.
- */
-Ext.handleError = function(e) {
- throw e;
-};
-
/**
* @class Ext.Error
* @extends Error
@@ -46,12 +36,12 @@ function generateError(data) {
*
* @param {String} message
*/
-Ext.Error = function(message) {
+const ExtError = function(message) {
// Try to read the message from Ext.Error.lang
this.message = (this.lang[message]) ? this.lang[message] : message;
}
-Ext.Error.prototype = new Error();
-Ext.apply(Ext.Error.prototype, {
+ExtError.prototype = new Error();
+Object.assign(ExtError.prototype, {
// protected. Extensions place their error-strings here.
lang: {},
@@ -79,3 +69,4 @@ Ext.apply(Ext.Error.prototype, {
}
});
+module.exports = ExtError;
diff --git a/tine20/library/ExtJS/src/core/Ext-more.js b/tine20/library/ExtJS/src/core/Ext-more.js
index 7d5ef0b5c34..b3db9cdc295 100644
--- a/tine20/library/ExtJS/src/core/Ext-more.js
+++ b/tine20/library/ExtJS/src/core/Ext-more.js
@@ -7,6 +7,7 @@
/**
* @class Ext
*/
+const Ext = require("Ext/core/core/Ext");
Ext.ns("Ext.grid", "Ext.list", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu",
"Ext.state", "Ext.layout", "Ext.app", "Ext.ux", "Ext.chart", "Ext.direct");
@@ -16,7 +17,7 @@ Ext.ns("Ext.grid", "Ext.list", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu",
* @type Object
*/
-Ext.apply(Ext, function(){
+module.exports = function(){
var E = Ext,
idSeed = 0,
scrollWidth = null;
@@ -541,7 +542,7 @@ Ext.zip(
}
}
};
-}());
+}();
/**
* @class Function
diff --git a/tine20/library/ExtJS/src/core/core/Ext.js b/tine20/library/ExtJS/src/core/core/Ext.js
index 6642833743a..49bf067c6b3 100644
--- a/tine20/library/ExtJS/src/core/core/Ext.js
+++ b/tine20/library/ExtJS/src/core/core/Ext.js
@@ -5,8 +5,7 @@
* http://www.extjs.com/license
*/
-// for old browsers
-window.undefined = window.undefined;
+const isFunction = require("lodash/isFunction")
/**
* @class Ext
@@ -14,7 +13,7 @@ window.undefined = window.undefined;
* @singleton
*/
-Ext = {
+const Ext = {
/**
* The version of the framework
* @type String
@@ -44,14 +43,16 @@ Ext.apply = function(o, c, defaults){
};
(function(){
- var idSeed = 0,
+ var DOC = typeof document !== 'undefined' ? document : {},
+ NAV = typeof navigator !== 'undefined' ? navigator : { userAgent: 'other' },
+ WIN = typeof window !== 'undefined' ? window : { location: '', matchMedia: () => { return '' } },
+ idSeed = 0,
toString = Object.prototype.toString,
- ua = navigator.userAgent.toLowerCase(),
+ ua = NAV.userAgent.toLowerCase(),
check = function(r){
return r.test(ua);
},
- docMode = document.documentMode,
- DOC = document,
+ docMode = DOC.documentMode,
isStrict = DOC.compatMode == "CSS1Compat",
isOpera = check(/opera/),
isChrome = check(/\bchrome\b/),
@@ -76,17 +77,17 @@ Ext.apply = function(o, c, defaults){
isMac = check(/macintosh|mac os x/),
isAir = check(/adobeair/),
isLinux = check(/linux/),
- isSecure = /^https/i.test(window.location.protocol),
- isIOS = check(/iphone/) || /* iPadOS pre v13 */ check(/ipad/) || (isMac && navigator.maxTouchPoints && navigator.maxTouchPoints > 2),
+ isSecure = /^https/i.test(WIN.location.protocol),
+ isIOS = check(/iphone/) || /* iPadOS pre v13 */ check(/ipad/) || (isMac && NAV.maxTouchPoints && NAV.maxTouchPoints > 2),
isAndroid = check(/android/),
isTouchDevice =
// @see http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
- 'ontouchstart' in window // works on most browsers
- || navigator.maxTouchPoints, // works on IE10/11 and Surface
+ 'ontouchstart' in WIN // works on most browsers
+ || NAV.maxTouchPoints, // works on IE10/11 and Surface
isWebApp =
// @see https://stackoverflow.com/questions/17989777/detect-if-ios-is-using-webapp/40932301#40932301
- (window.navigator.standalone == true) // iOS safari
- || (window.matchMedia('(display-mode: standalone)').matches), // android chrome
+ (NAV.standalone == true) // iOS safari
+ || (WIN.matchMedia('(display-mode: standalone)').matches), // android chrome
// NOTE: some browsers require user interaction (like click events)
// for focus to work (e.g. iOS dosn't show keyborad)
supportsUserFocus = ! (isTouchDevice && !isWebApp),
@@ -327,10 +328,11 @@ Company.data.CustomStore = function(config) { ... }
* @method namespace
*/
namespace : function(){
- var o, d;
+ var o, d, scope = (typeof window !== "undefined" ? window : global);
Ext.each(arguments, function(v) {
d = v.split(".");
- o = window[d[0]] = window[d[0]] || {};
+ o = d[0] === 'Ext' ? Ext : scope[d[0]]; // use 'interna' Ext we create and export here
+ if (!o) return; // don't polute global namspace if no one else did
Ext.each(d.slice(1), function(v2){
o = o[v2] = o[v2] || {};
});
@@ -426,17 +428,11 @@ Ext.urlDecode("foo=1&bar=2&bar=3&bar=4", false); // returns {foo: "1", bar: ["2"
}(),
isIterable : function(v){
- //check for array or arguments
- if(Ext.isArray(v) || v.callee){
- return true;
+ // checks for null and undefined
+ if (v == null) {
+ return false;
}
- //check for node list type
- if(/NodeList|HTMLCollection/.test(toString.call(v))){
- return true;
- }
- //NodeList has an item and length property
- //IXMLDOMNodeList has nextNode method, needs to be checked first.
- return ((typeof v.nextNode != 'undefined' || v.item) && Ext.isNumber(v.length));
+ return typeof v[Symbol.iterator] === 'function';
},
/**
@@ -656,9 +652,7 @@ function(el){
* @param {Mixed} value The value to test
* @return {Boolean}
*/
- isFunction : function(v){
- return _.isFunction(v); // cope with async functions
- },
+ isFunction,
/**
* Returns true if the passed value is a number. Returns false for non-finite numbers.
@@ -1060,3 +1054,36 @@ Ext.applyIf(Array.prototype, {
return this;
}
});
+
+// NOTE: we can't use export / import syntax as es6 modules require strict mode and this code can't cope with it
+module.exports = Ext
+/*
+export const apply = Ext.apply;
+export const applyIf = Ext.applyIf;
+export const id = Ext.id;
+export const extend = Ext.extend;
+export const override = Ext.override;
+export const namespace = Ext.namespace;
+export const urlEncode = Ext.urlEncode;
+export const urlDecode = Ext.urlDecode;
+export const urlAppend = Ext.urlAppend;
+export const toArray = Ext.toArray;
+export const isIterable = Ext.isIterable;
+export const each = Ext.each;
+export const iterate = Ext.iterate;
+// export const getDom = Ext.getDom;
+// export const getBody = Ext.getBody;
+// export const removeNode = Ext.removeNode;
+export const isEmpty = Ext.isEmpty;
+export const isArray = Ext.isArray;
+export const isDate = Ext.isDate;
+export const isObject = Ext.isObject;
+export const isPrimitive = Ext.isPrimitive;
+export const isFunction = Ext.isFunction;
+export const isNumber = Ext.isNumber;
+export const isString = Ext.isString;
+export const isBoolean = Ext.isBoolean;
+export const isElement = Ext.isElement;
+export const isDefined = Ext.isDefined;
+export const ns = Ext.ns;
+*/
\ No newline at end of file
diff --git a/tine20/library/ExtJS/src/data/DataField.js b/tine20/library/ExtJS/src/data/DataField.js
index 86140c647a5..ca69d4550ac 100644
--- a/tine20/library/ExtJS/src/data/DataField.js
+++ b/tine20/library/ExtJS/src/data/DataField.js
@@ -4,6 +4,11 @@
* licensing@extjs.com
* http://www.extjs.com/license
*/
+
+const { apply, isDate } = require("Ext/core/core/Ext");
+const SortTypes = require("Ext/data/SortTypes");
+const isObject = require("lodash/isObject");
+
/**
* @class Ext.data.Field
* This class encapsulates the field definition information specified in the field definition objects
@@ -11,17 +16,17 @@
*
Developers do not need to instantiate this class. Instances are created by {@link Ext.data.Record.create}
* and cached in the {@link Ext.data.Record#fields fields} property of the created Record constructor's prototype.
*/
-Ext.data.Field = function(config){
+const Field = function(config){
if(typeof config == "string"){
config = {name: config};
}
- Ext.apply(this, config);
+ apply(this, config);
if(!this.type){
this.type = "auto";
}
- var st = Ext.data.SortTypes;
+ var st = SortTypes;
// named sortTypes are supported, here we look them up
if(typeof this.sortType == "string"){
this.sortType = st[this.sortType];
@@ -55,7 +60,7 @@ Ext.data.Field = function(config){
cv = function(v){ return v; };
break;
case "string":
- cv = function(v){ return (v === undefined || v === null) ? '' : (_.isObject(v) ? JSON.stringify(v) : String(v)); };
+ cv = function(v){ return (v === undefined || v === null) ? '' : (isObject(v) ? JSON.stringify(v) : String(v)); };
break;
case "int":
cv = function(v){
@@ -73,7 +78,7 @@ Ext.data.Field = function(config){
cv = function(v){ return v === true || v === "true" || v == 1; };
break;
case "date":
- cv = function(v){
+ var c1 = function(v){
if(!v){
return '';
}
@@ -83,7 +88,7 @@ Ext.data.Field = function(config){
if (v === 'CURRENT_TIME') {
return new Date().clearTime();
}
- if(Ext.isDate(v)){
+ if(isDate(v)){
return v;
}
if(dateFormat){
@@ -98,6 +103,15 @@ Ext.data.Field = function(config){
var parsed = Date.parse(v);
return parsed ? new Date(parsed) : null;
};
+ cv = function(v) {
+ var d = c1(v);
+ if (isDate(d)) {
+ d.toJSON = function() {
+ return this.format(config.dateFormat);
+ }
+ }
+ return d;
+ };
break;
default:
cv = function(v){ return v; };
@@ -108,7 +122,7 @@ Ext.data.Field = function(config){
}
};
-Ext.data.Field.prototype = {
+Field.prototype = {
/**
* @cfg {String} name
* The name by which the field is referenced within the Record. This is referenced by, for example,
@@ -255,3 +269,5 @@ sortType: function(value) {
*/
allowBlank : true
};
+
+module.exports = Field;
\ No newline at end of file
diff --git a/tine20/library/ExtJS/src/data/DataReader.js b/tine20/library/ExtJS/src/data/DataReader.js
index ec08cec6748..6ef571fe088 100644
--- a/tine20/library/ExtJS/src/data/DataReader.js
+++ b/tine20/library/ExtJS/src/data/DataReader.js
@@ -4,8 +4,14 @@
* licensing@extjs.com
* http://www.extjs.com/license
*/
+
+const { extend, isObject, isEmpty, isArray, apply } = require("Ext/core/core/Ext");
+const Record = require("Ext/data/Record");
+const ExtError = require('Ext/core/Error');
+const emptyFn = () => {};
+
/**
- * @class Ext.data.DataReader
+ * @class DataReader
* Abstract base class for reading structured data from a data source and converting
* it into an object containing {@link Ext.data.Record} objects and metadata for use
* by an {@link Ext.data.Store}. This class is intended to be extended and should not
@@ -18,7 +24,7 @@
* will be passed to {@link Ext.data.Record#create}, or a {@link Ext.data.Record Record}
* constructor created using {@link Ext.data.Record#create}.
*/
-Ext.data.DataReader = function(meta, recordType){
+const DataReader = function(meta, recordType){
/**
* This DataReader's configured metadata as passed to the constructor.
* @type Mixed
@@ -31,8 +37,8 @@ Ext.data.DataReader = function(meta, recordType){
* will be passed to {@link Ext.data.Record#create}, or a {@link Ext.data.Record Record}
* constructor created from {@link Ext.data.Record#create}.
*/
- this.recordType = Ext.isArray(recordType) ?
- Ext.data.Record.create(recordType) : recordType;
+ this.recordType = isArray(recordType) ?
+ Record.create(recordType) : recordType;
// if recordType defined make sure extraction functions are defined
if (this.recordType){
@@ -42,42 +48,43 @@ Ext.data.DataReader = function(meta, recordType){
}
};
-Ext.data.DataReader.prototype = {
+DataReader.prototype = {
+ readerType: 'json',
/**
* @cfg {String} messageProperty [undefined] Optional name of a property within a server-response that represents a user-feedback message.
*/
/**
* Abstract method created in extension's buildExtractors impl.
*/
- getTotal: Ext.emptyFn,
+ getTotal: emptyFn,
/**
* Abstract method created in extension's buildExtractors impl.
*/
- getRoot: Ext.emptyFn,
+ getRoot: emptyFn,
/**
* Abstract method created in extension's buildExtractors impl.
*/
- getMessage: Ext.emptyFn,
+ getMessage: emptyFn,
/**
* Abstract method created in extension's buildExtractors impl.
*/
- getSuccess: Ext.emptyFn,
+ getSuccess: emptyFn,
/**
* Abstract method created in extension's buildExtractors impl.
*/
- getId: Ext.emptyFn,
+ getId: emptyFn,
/**
* Abstract method, overridden in DataReader extensions such as {@link Ext.data.JsonReader} and {@link Ext.data.XmlReader}
*/
- buildExtractors : Ext.emptyFn,
+ buildExtractors : emptyFn,
/**
* Abstract method overridden in DataReader extensions such as {@link Ext.data.JsonReader} and {@link Ext.data.XmlReader}
*/
- extractData : Ext.emptyFn,
+ extractData : emptyFn,
/**
* Abstract method overridden in DataReader extensions such as {@link Ext.data.JsonReader} and {@link Ext.data.XmlReader}
*/
- extractValues : Ext.emptyFn,
+ extractValues : emptyFn,
/**
* Used for un-phantoming a record after a successful database insert. Sets the records pk along with new data from server.
@@ -89,10 +96,10 @@ Ext.data.DataReader.prototype = {
* @param {Object/Object[]} data The new record data to apply. Must include the primary-key from database defined in idProperty field.
*/
realize: function(rs, data){
- if (Ext.isArray(rs)) {
+ if (isArray(rs)) {
for (var i = rs.length - 1; i >= 0; i--) {
// recurse
- if (Ext.isArray(data)) {
+ if (isArray(data)) {
this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
}
else {
@@ -104,13 +111,13 @@ Ext.data.DataReader.prototype = {
}
else {
// If rs is NOT an array but data IS, see if data contains just 1 record. If so extract it and carry on.
- if (Ext.isArray(data) && data.length == 1) {
+ if (isArray(data) && data.length == 1) {
data = data.shift();
}
if (!this.isData(data)) {
// TODO: Let exception-handler choose to commit or not rather than blindly rs.commit() here.
//rs.commit();
- throw new Ext.data.DataReader.Error('realize', rs);
+ throw new DataReader.Error('realize', rs);
}
rs.phantom = false; // <-- That's what it's all about
rs._phid = rs.id; // <-- copy phantom-id -> _phid, so we can remap in Store#onCreateRecords
@@ -134,9 +141,9 @@ Ext.data.DataReader.prototype = {
* @param {Object/Object[]} data
*/
update : function(rs, data) {
- if (Ext.isArray(rs)) {
+ if (isArray(rs)) {
for (var i=rs.length-1; i >= 0; i--) {
- if (Ext.isArray(data)) {
+ if (isArray(data)) {
this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
}
else {
@@ -148,7 +155,7 @@ Ext.data.DataReader.prototype = {
}
else {
// If rs is NOT an array but data IS, see if data contains just 1 record. If so extract it and carry on.
- if (Ext.isArray(data) && data.length == 1) {
+ if (isArray(data) && data.length == 1) {
data = data.shift();
}
if (this.isData(data)) {
@@ -170,13 +177,13 @@ Ext.data.DataReader.prototype = {
*/
extractData : function(root, returnRecords) {
// A bit ugly this, too bad the Record's raw data couldn't be saved in a common property named "raw" or something.
- var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';
+ var rawName = (this.readerType === 'json') ? 'json' : 'node';
var rs = [];
// Had to add Check for XmlReader, #isData returns true if root is an Xml-object. Want to check in order to re-factor
// #extractData into DataReader base, since the implementations are almost identical for JsonReader, XmlReader
- if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {
+ if (this.isData(root) && !(this.readerType === 'xml')) {
root = [root];
}
var f = this.recordType.prototype.fields,
@@ -210,7 +217,7 @@ Ext.data.DataReader.prototype = {
* @return {Boolean}
*/
isData : function(data) {
- return (data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
+ return (data && isObject(data) && !isEmpty(this.getId(data))) ? true : false;
},
// private function a store will createSequence upon
@@ -218,28 +225,30 @@ Ext.data.DataReader.prototype = {
delete this.ef;
if (meta) {
this.meta = meta;
- this.recordType = Ext.data.Record.create(meta.fields);
+ this.recordType = Record.create(meta.fields);
}
this.buildExtractors();
}
};
/**
- * @class Ext.data.DataReader.Error
+ * @class DataReader.Error
* @extends Ext.Error
- * General error class for Ext.data.DataReader
+ * General error class for DataReader
*/
-Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
+DataReader.Error = extend(ExtError, {
constructor : function(message, arg) {
this.arg = arg;
- Ext.Error.call(this, message);
+ ExtError.call(this, message);
},
- name: 'Ext.data.DataReader'
+ name: 'DataReader'
});
-Ext.apply(Ext.data.DataReader.Error.prototype, {
+apply(DataReader.Error.prototype, {
lang : {
'update': "#update received invalid data from server. Please see docs for DataReader#update and review your DataReader configuration.",
'realize': "#realize was called with invalid remote-data. Please see the docs for DataReader#realize and review your DataReader configuration.",
'invalid-response': "#readResponse received an invalid response from the server."
}
});
+
+module.exports = DataReader;
\ No newline at end of file
diff --git a/tine20/library/ExtJS/src/data/JsonReader.js b/tine20/library/ExtJS/src/data/JsonReader.js
index 952c2cf2d21..bd09458ebd2 100644
--- a/tine20/library/ExtJS/src/data/JsonReader.js
+++ b/tine20/library/ExtJS/src/data/JsonReader.js
@@ -4,15 +4,21 @@
* licensing@extjs.com
* http://www.extjs.com/license
*/
+
+const { applyIf, extend, isDefined, isEmpty, isArray, isFunction, apply } = require("Ext/core/core/Ext");
+const ExtError = require('Ext/core/Error');
+const DataReader = require('./DataReader');
+const Response = require('./Response');
+
/**
- * @class Ext.data.JsonReader
+ * @class JsonReader
* @extends Ext.data.DataReader
* Data reader class to create an Array of {@link Ext.data.Record} objects
* from a JSON packet based on mappings in a provided {@link Ext.data.Record}
* constructor.
* Example code:
*
-var myReader = new Ext.data.JsonReader({
+var myReader = new JsonReader({
// metadata configuration options:
{@link #idProperty}: 'id'
{@link #root}: 'rows',
@@ -51,7 +57,7 @@ var myReader = new Ext.data.JsonReader({
* Note that reconfiguring a Store potentially invalidates objects which may
* refer to Fields or Records which no longer exist.
* To use this facility you would create the JsonReader like this:
-var myReader = new Ext.data.JsonReader();
+var myReader = new JsonReader();
* The first data packet from the server would configure the reader by
* containing a metaData property and the data. For
@@ -110,7 +116,7 @@ var myReader = new Ext.data.JsonReader();
* will be passed to {@link Ext.data.Record#create}, or a {@link Ext.data.Record Record}
* constructor created from {@link Ext.data.Record#create}.
*/
-Ext.data.JsonReader = function(meta, recordType){
+const JsonReader = function(meta, recordType){
meta = meta || {};
/**
* @cfg {String} idProperty [id] Name of the property within a row object
@@ -135,15 +141,15 @@ Ext.data.JsonReader = function(meta, recordType){
* packet value for this property should be an empty array to clear the data
* or show no data.
*/
- Ext.applyIf(meta, {
+ applyIf(meta, {
idProperty: 'id',
successProperty: 'success',
totalProperty: 'total'
});
- Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
+ JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
};
-Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
+extend(JsonReader, DataReader, {
/**
* This JsonReader's metadata as passed to the constructor, or as passed in
* the last data packet's metaData property.
@@ -158,7 +164,7 @@ Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
*/
read : function(response){
var json = response.responseText;
- var o = Ext.decode(json);
+ var o = JSON.parse(json);
if(!o) {
throw {message: 'JsonReader.read: Json object not found'};
}
@@ -173,24 +179,24 @@ Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
* there's ugly duplication going on due to maintaining backwards compat. with 2.0. It's time to do this.
*/
readResponse : function(action, response) {
- var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response;
+ var o = (response.responseText !== undefined) ? JSON.parse(response.responseText) : response;
if(!o) {
- throw new Ext.data.JsonReader.Error('response');
+ throw new JsonReader.Error('response');
}
var root = this.getRoot(o);
- if (action === Ext.data.Api.actions.create) {
- var def = Ext.isDefined(root);
- if (def && Ext.isEmpty(root)) {
- throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
+ if (action === 'create') {
+ var def = isDefined(root);
+ if (def && isEmpty(root)) {
+ throw new JsonReader.Error('root-empty', this.meta.root);
}
else if (!def) {
- throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
+ throw new JsonReader.Error('root-undefined-response', this.meta.root);
}
}
// instantiate response object
- var res = new Ext.data.Response({
+ var res = new Response({
action: action,
success: this.getSuccess(o),
data: (root) ? this.extractData(root, false) : [],
@@ -199,8 +205,8 @@ Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
});
// blow up if no successProperty
- if (Ext.isEmpty(res.success)) {
- throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty);
+ if (isEmpty(res.success)) {
+ throw new JsonReader.Error('successProperty-response', this.meta.successProperty);
}
return res;
},
@@ -298,10 +304,10 @@ Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
createAccessor : function(){
var re = /[\[\.]/;
return function(expr) {
- if(Ext.isEmpty(expr)){
- return Ext.emptyFn;
+ if(isEmpty(expr)){
+ return () => {};
}
- if(Ext.isFunction(expr)){
+ if(isFunction(expr)){
return expr;
}
var i = String(expr).search(re);
@@ -310,7 +316,7 @@ Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
}
return function(obj){
// support array as roots
- return Ext.isArray(obj) && obj.length > 0 ? obj : obj[expr];
+ return isArray(obj) && obj.length > 0 ? obj : obj[expr];
};
};
@@ -335,17 +341,17 @@ Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
});
/**
- * @class Ext.data.JsonReader.Error
+ * @class JsonReader.Error
* Error class for JsonReader
*/
-Ext.data.JsonReader.Error = Ext.extend(Ext.Error, {
+JsonReader.Error = extend(ExtError, {
constructor : function(message, arg) {
this.arg = arg;
- Ext.Error.call(this, message);
+ ExtError.call(this, message);
},
- name : 'Ext.data.JsonReader'
+ name : 'JsonReader'
});
-Ext.apply(Ext.data.JsonReader.Error.prototype, {
+apply(JsonReader.Error.prototype, {
lang: {
'response': 'An error occurred while json-decoding your server response',
'successProperty-response': 'Could not locate your "successProperty" in your server response. Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response. See the JsonReader docs.',
@@ -354,3 +360,5 @@ Ext.apply(Ext.data.JsonReader.Error.prototype, {
'root-empty': 'Data was expected to be returned by the server in the "root" property of the response. Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response. See JsonReader docs.'
}
});
+
+module.exports = JsonReader;
\ No newline at end of file
diff --git a/tine20/library/ExtJS/src/data/Record.js b/tine20/library/ExtJS/src/data/Record.js
index 04696d5cb6f..20286a06de6 100644
--- a/tine20/library/ExtJS/src/data/Record.js
+++ b/tine20/library/ExtJS/src/data/Record.js
@@ -4,8 +4,14 @@
* licensing@extjs.com
* http://www.extjs.com/license
*/
+
+const { extend, isPrimitive, isEmpty } = require("Ext/core/core/Ext");
+const Field = require("Ext/data/DataField");
+const MixedCollection = require("Ext/util/MixedCollection");
+const { cloneDeep, forEach } = require('lodash');
+
/**
- * @class Ext.data.Record
+ * @class Record
* Instances of this class encapsulate both Record definition information, and Record
* value information for use in {@link Ext.data.Store} objects, or any code which needs
* to access Records cached in an {@link Ext.data.Store} object.
@@ -19,10 +25,10 @@
* properties, and also a reference to its owning Store which in turn holds references to its Records.
* This means that a whole Record may not be encoded using {@link Ext.util.JSON.encode}. Instead, use the
* {@link #data}
and {@link #id}
properties.
- * Record objects generated by this constructor inherit all the methods of Ext.data.Record listed below.
+ * Record objects generated by this constructor inherit all the methods of Record listed below.
* @constructor
* This constructor should not be used to create Record objects. Instead, use {@link #create} to
- * generate a subclass of Ext.data.Record configured with information about its constituent fields.
+ * generate a subclass of Record configured with information about its constituent fields.
*
The generated constructor has the same signature as this constructor.
* @param {Object} data (Optional) An object, the properties of which provide values for the new Record's
* fields. If not specified the {@link Ext.data.Field#defaultValue defaultValue}
@@ -33,9 +39,9 @@
* id
is not specified a {@link #phantom}
* Record will be created with an {@link #Record.id automatically generated id}.
*/
-Ext.data.Record = function(data, id){
+const Record = function(data, id){
// if no id, call the auto id method
- this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
+ this.id = (id || id === 0) ? id : Record.id(this);
Object.assign(this, data.__meta || {});
delete(data.__meta);
this.data = data || {};
@@ -48,7 +54,7 @@ Ext.data.Record = function(data, id){
* object must contain properties named after the {@link Ext.data.Field field}
* {@link Ext.data.Field#name}s. Example usage:
// create a Record constructor from a description of the fields
-var TopicRecord = Ext.data.Record.create([ // creates a subclass of Ext.data.Record
+var TopicRecord = Record.create([ // creates a subclass of Record
{{@link Ext.data.Field#name name}: 'title', {@link Ext.data.Field#mapping mapping}: 'topic_title'},
{name: 'author', mapping: 'username', allowBlank: false},
{name: 'totalPosts', mapping: 'topic_replies', type: 'int'},
@@ -80,14 +86,14 @@ myStore.{@link Ext.data.Store#add add}(myNewRecord);
* to the definition. The constructor has the same signature as {@link #Record}.
* @static
*/
-Ext.data.Record.create = function(o){
- var f = Ext.extend(Ext.data.Record, {});
+Record.create = function(o){
+ var f = extend(Record, {});
var p = f.prototype;
- p.fields = new Ext.util.MixedCollection(false, function(field){
+ p.fields = new MixedCollection(false, function(field){
return field.name;
});
for(var i = 0, len = o.length; i < len; i++){
- p.fields.add(new Ext.data.Field(o[i]));
+ p.fields.add(new Field(o[i]));
}
f.getField = function(name){
return p.fields.get(name);
@@ -95,31 +101,31 @@ Ext.data.Record.create = function(o){
return f;
};
-Ext.data.Record.PREFIX = 'ext-record';
-Ext.data.Record.AUTO_ID = 1;
-Ext.data.Record.EDIT = 'edit';
-Ext.data.Record.REJECT = 'reject';
-Ext.data.Record.COMMIT = 'commit';
+Record.PREFIX = 'ext-record';
+Record.AUTO_ID = 1;
+Record.EDIT = 'edit';
+Record.REJECT = 'reject';
+Record.COMMIT = 'commit';
/**
* Generates a sequential id. This method is typically called when a record is {@link #create}d
* and {@link #Record no id has been specified}. The returned id takes the form:
* {PREFIX}-{AUTO_ID}.
- * - PREFIX : String
Ext.data.Record.PREFIX
+ *
- PREFIX : String
Record.PREFIX
* (defaults to 'ext-record')
- * - AUTO_ID : String
Ext.data.Record.AUTO_ID
+ *
- AUTO_ID : String
Record.AUTO_ID
* (defaults to 1 initially)
*
* @param {Record} rec The record being created. The record does not exist, it's a {@link #phantom}.
* @return {String} auto-generated string id, "ext-record-i++';
*/
-Ext.data.Record.id = function(rec) {
+Record.id = function(rec) {
rec.phantom = true;
- return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
+ return [Record.PREFIX, '-', Record.AUTO_ID++].join('');
};
-Ext.data.Record.prototype = {
+Record.prototype = {
/**
* This property is stored in the Record definition's prototype
* A MixedCollection containing the defined {@link Ext.data.Field Field}s for this Record. Read-only.
@@ -197,9 +203,9 @@ Ext.data.Record.prototype = {
},
setData: function(data) {
- _.forEach(data, (v,k) => {
+ forEach(data, (v,k) => {
if (k === '__meta') {
- _.forEach(this.__metaFields, (m) => {
+ forEach(this.__metaFields, (m) => {
if (v.hasOwnProperty(m)) {
this[m] = v[m];
}
@@ -214,7 +220,7 @@ Ext.data.Record.prototype = {
* Set the {@link Ext.data.Field#name named field} to the specified value. For example:
*
// record has a field named 'firstname'
-var Employee = Ext.data.Record.{@link #create}([
+var Employee = Record.{@link #create}([
{name: 'firstname'},
...
]);
@@ -246,7 +252,7 @@ rec.{@link #commit}(); // updates the view
*/
set : function(name, value){
Tine.Tinebase.common.assertComparable(value);
- var encode = Ext.isPrimitive(value) ? String : Ext.encode;
+ var encode = isPrimitive(value) ? String : JSON.stringify;
if(encode(this.data[name]) == encode(value)) {
return;
}
@@ -378,7 +384,7 @@ rec.{@link #commit}(); // updates the view
getChanges : function(){
var m = this.modified, cs = {};
for(var n in m){
- const encode = Ext.isPrimitive(this.modified[n]) ? String : Ext.encode;
+ const encode = isPrimitive(this.modified[n]) ? String : JSON.stringify;
if(m.hasOwnProperty(n) && encode(this.modified[n]) !== encode(this.data[n])){
cs[n] = this.data[n];
}
@@ -402,12 +408,12 @@ rec.{@link #commit}(); // updates the view
* of the record being copied. See {@link #id}
.
* To generate a phantom record with a new id use:
var rec = record.copy(); // clone the record
-Ext.data.Record.id(rec); // automatically generate a unique sequential id
+Record.id(rec); // automatically generate a unique sequential id
*
* @return {Record}
*/
copy : function(newId) {
- return new this.constructor(_.cloneDeep(this.data), newId || this.id);
+ return new this.constructor(cloneDeep(this.data), newId || this.id);
},
/**
@@ -428,7 +434,7 @@ Ext.data.Record.id(rec); // automatically generate a unique sequential id
*/
isValid : function() {
return this.fields.find(function(f) {
- return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
+ return (f.allowBlank === false && isEmpty(this.data[f.name])) ? true : false;
},this) ? false : true;
},
@@ -451,3 +457,5 @@ Ext.data.Record.id(rec); // automatically generate a unique sequential id
},this);
}
};
+
+module.exports = Record;
\ No newline at end of file
diff --git a/tine20/library/ExtJS/src/data/Response.js b/tine20/library/ExtJS/src/data/Response.js
index 83949195fcf..8b6f0748d7c 100644
--- a/tine20/library/ExtJS/src/data/Response.js
+++ b/tine20/library/ExtJS/src/data/Response.js
@@ -8,10 +8,10 @@
* @class Ext.data.Response
* A generic response class to normalize response-handling internally to the framework.
*/
-Ext.data.Response = function(params) {
- Ext.apply(this, params);
+const Response = function(params) {
+ Object.assign(this, params);
};
-Ext.data.Response.prototype = {
+Response.prototype = {
/**
* @cfg {String} action {@link Ext.data.Api#actions}
*/
@@ -37,3 +37,5 @@ Ext.data.Response.prototype = {
*/
records: undefined
};
+
+module.exports = Response;
\ No newline at end of file
diff --git a/tine20/library/ExtJS/src/data/SortTypes.js b/tine20/library/ExtJS/src/data/SortTypes.js
index 05fa285a9ce..764509f0d2b 100644
--- a/tine20/library/ExtJS/src/data/SortTypes.js
+++ b/tine20/library/ExtJS/src/data/SortTypes.js
@@ -1,16 +1,18 @@
-/*!
- * Ext JS Library 3.1.1
- * Copyright(c) 2006-2010 Ext JS, LLC
- * licensing@extjs.com
- * http://www.extjs.com/license
- */
+/*!
+ * Ext JS Library 3.1.1
+ * Copyright(c) 2006-2010 Ext JS, LLC
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+
+const { isDate } = require("Ext/core/core/Ext");
/**
* @class Ext.data.SortTypes
* @singleton
* Defines the default sorting (casting?) comparison functions used when sorting data.
*/
-Ext.data.SortTypes = {
+module.exports = {
/**
* Default sort that does nothing
* @param {Mixed} s The value being converted
@@ -63,7 +65,7 @@ Ext.data.SortTypes = {
if(!s){
return 0;
}
- if(Ext.isDate(s)){
+ if(isDate(s)){
return s.getTime();
}
return Date.parse(String(s));
diff --git a/tine20/library/ExtJS/src/data/Store.js b/tine20/library/ExtJS/src/data/Store.js
index a1d98382216..913963aec8e 100644
--- a/tine20/library/ExtJS/src/data/Store.js
+++ b/tine20/library/ExtJS/src/data/Store.js
@@ -1238,8 +1238,7 @@ sortInfo: {
// protected handleException. Possibly temporary until Ext framework has an exception-handler.
handleException : function(e) {
- // @see core/Error.js
- Ext.handleError(e);
+ throw e;
},
/**
diff --git a/tine20/library/ExtJS/src/data/XmlReader.js b/tine20/library/ExtJS/src/data/XmlReader.js
index d75a37e1042..755647473aa 100644
--- a/tine20/library/ExtJS/src/data/XmlReader.js
+++ b/tine20/library/ExtJS/src/data/XmlReader.js
@@ -68,6 +68,8 @@ Ext.data.XmlReader = function(meta, recordType){
Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
};
Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
+ readerType: 'xml',
+
/**
* This method is only used by a DataProxy which has retrieved data from a remote server.
* @param {Object} response The XHR object which contains the parsed XML document. The response is expected
diff --git a/tine20/library/ExtJS/src/util/Format.js b/tine20/library/ExtJS/src/util/Format.js
index 938d14b7af4..ca7f4b31af7 100644
--- a/tine20/library/ExtJS/src/util/Format.js
+++ b/tine20/library/ExtJS/src/util/Format.js
@@ -32,7 +32,7 @@ var trimRe = /^\s+|\s+$/g,
*/
// import emojiRegex from 'emoji-regex';
-Ext.util.Format = function(){
+var Format = function(){
return {
/**
* Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
@@ -401,3 +401,5 @@ Ext.util.Format = function(){
}
}
}();
+
+module.exports = Format
\ No newline at end of file
diff --git a/tine20/library/ExtJS/src/util/MixedCollection.js b/tine20/library/ExtJS/src/util/MixedCollection.js
index 6827facf841..20199218ba6 100644
--- a/tine20/library/ExtJS/src/util/MixedCollection.js
+++ b/tine20/library/ExtJS/src/util/MixedCollection.js
@@ -4,6 +4,14 @@
* licensing@extjs.com
* http://www.extjs.com/license
*/
+
+const { extend, isArray, isFunction, isEmpty } = require("Ext/core/core/Ext");
+const { Observable } = require("Ext/util/core/Observable");
+const { escapeRe } = require("Ext/core/Ext-more");
+const cloneDeep = require("lodash/cloneDeep");
+
+
+
/**
* @class Ext.util.MixedCollection
* @extends Ext.util.Observable
@@ -17,7 +25,7 @@
* were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
* equivalent to providing an implementation for the {@link #getKey} method.
*/
-Ext.util.MixedCollection = function(allowFunctions, keyFn, returnClones){
+const MixedCollection = function(allowFunctions, keyFn, returnClones){
this.items = [];
this.map = {};
this.keys = [];
@@ -58,10 +66,10 @@ Ext.util.MixedCollection = function(allowFunctions, keyFn, returnClones){
if(keyFn){
this.getKey = keyFn;
}
- Ext.util.MixedCollection.superclass.constructor.call(this);
+ MixedCollection.superclass.constructor.call(this);
};
-Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
+extend(MixedCollection, Observable, {
/**
* @cfg {Boolean} allowFunctions Specify true if the {@link #addAll}
@@ -81,7 +89,7 @@ Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
},
getAll: function() {
- return this.returnClones ? _.cloneDeep(this.map) : this.map;
+ return this.returnClones ? cloneDeep(this.map) : this.map;
},
/**
@@ -187,7 +195,7 @@ mc.add(otherEl);
* @param suppressEvent
*/
addAll : function(objs, suppressEvent){
- if(arguments.length > 2 || Ext.isArray(objs)){
+ if(arguments.length > 2 || isArray(objs)){
var args = arguments.length > 1 ? arguments : objs;
for(var i = 0, len = args.length; i < len; i++){
this.add(args[i]);
@@ -355,10 +363,10 @@ mc.add(otherEl);
item : function(key){
var mk = this.map[key],
item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;
- if (this.returnClones && !Ext.isFunction(item)) {
- item = _.cloneDeep(item);
+ if (this.returnClones && !isFunction(item)) {
+ item = cloneDeep(item);
}
- return !Ext.isFunction(item) || this.allowFunctions ? item : null; // for prototype!
+ return !isFunction(item) || this.allowFunctions ? item : null; // for prototype!
},
/**
@@ -368,8 +376,8 @@ mc.add(otherEl);
*/
itemAt : function(index){
let item = this.items[index];
- if (this.returnClones && !Ext.isFunction(item)) {
- item = _.cloneDeep(item);
+ if (this.returnClones && !isFunction(item)) {
+ item = cloneDeep(item);
}
return item;
},
@@ -418,8 +426,8 @@ mc.add(otherEl);
*/
first : function(){
let item = this.items[0];
- if (this.returnClones && !Ext.isFunction(item)) {
- item = _.cloneDeep(item);
+ if (this.returnClones && !isFunction(item)) {
+ item = cloneDeep(item);
}
return item;
@@ -431,8 +439,8 @@ mc.add(otherEl);
*/
last : function(){
let item = this.items[this.length-1];
- if (this.returnClones && !Ext.isFunction(item)) {
- item = _.cloneDeep(item);
+ if (this.returnClones && !isFunction(item)) {
+ item = cloneDeep(item);
}
return item;
},
@@ -517,7 +525,7 @@ mc.add(otherEl);
}
}
if (this.returnClones) {
- r = _.cloneDeep(r);
+ r = cloneDeep(r);
}
return r;
},
@@ -533,7 +541,7 @@ mc.add(otherEl);
* @return {MixedCollection} The new filtered collection
*/
filter : function(property, value, anyMatch, caseSensitive){
- if(Ext.isEmpty(value, false)){
+ if(isEmpty(value, false)){
return this.clone();
}
value = this.createValueMatcher(value, anyMatch, caseSensitive);
@@ -551,7 +559,7 @@ mc.add(otherEl);
* @return {MixedCollection} The new filtered collection
*/
filterBy : function(fn, scope){
- var r = new Ext.util.MixedCollection();
+ var r = new MixedCollection();
r.getKey = this.getKey;
var k = this.keys, it = this.items;
for(var i = 0, len = it.length; i < len; i++){
@@ -560,7 +568,7 @@ mc.add(otherEl);
}
}
if (this.returnClones) {
- r = _.cloneDeep(r);
+ r = cloneDeep(r);
}
return r;
},
@@ -576,7 +584,7 @@ mc.add(otherEl);
* @return {Number} The matched index or -1
*/
findIndex : function(property, value, start, anyMatch, caseSensitive){
- if(Ext.isEmpty(value, false)){
+ if(isEmpty(value, false)){
return -1;
}
value = this.createValueMatcher(value, anyMatch, caseSensitive);
@@ -606,7 +614,7 @@ mc.add(otherEl);
// private
createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
if (!value.exec) { // not a regex
- var er = Ext.escapeRe;
+ var er = escapeRe;
value = String(value);
if (anyMatch === true) {
value = er(value);
@@ -626,7 +634,7 @@ mc.add(otherEl);
* @return {MixedCollection}
*/
clone : function(){
- var r = new Ext.util.MixedCollection();
+ var r = new MixedCollection();
var k = this.keys, it = this.items;
for(var i = 0, len = it.length; i < len; i++){
r.add(k[i], it[i]);
@@ -645,4 +653,6 @@ mc.add(otherEl);
* not found, returns undefined. If an item was found, but is a Class,
* returns null.
*/
-Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
+MixedCollection.prototype.get = MixedCollection.prototype.item;
+
+module.exports = MixedCollection
\ No newline at end of file
diff --git a/tine20/library/ExtJS/src/util/core/DelayedTask.js b/tine20/library/ExtJS/src/util/core/DelayedTask.js
index 5a48a62a941..d222545cf08 100644
--- a/tine20/library/ExtJS/src/util/core/DelayedTask.js
+++ b/tine20/library/ExtJS/src/util/core/DelayedTask.js
@@ -33,7 +33,7 @@ Ext.get('myInputField').on('keypress', function(){
* function is called. If not specified, this
will refer to the browser window.
* @param {Array} args (optional) The default Array of arguments.
*/
-Ext.util.DelayedTask = function(fn, scope, args){
+const DelayedTask = function(fn, scope, args){
var me = this,
id,
call = function(){
@@ -67,4 +67,6 @@ Ext.util.DelayedTask = function(fn, scope, args){
id = null;
}
};
-};
\ No newline at end of file
+};
+
+module.exports = DelayedTask;
\ No newline at end of file
diff --git a/tine20/library/ExtJS/src/util/core/Observable.js b/tine20/library/ExtJS/src/util/core/Observable.js
index 5b7c89548fb..aa96f8b049a 100644
--- a/tine20/library/ExtJS/src/util/core/Observable.js
+++ b/tine20/library/ExtJS/src/util/core/Observable.js
@@ -4,14 +4,10 @@
* licensing@extjs.com
* http://www.extjs.com/license
*/
-(function(){
-
-var EXTUTIL = Ext.util,
- TOARRAY = Ext.toArray,
- EACH = Ext.each,
- ISOBJECT = Ext.isObject,
- TRUE = true,
- FALSE = false;
+
+const { toArray, each, isObject, isString, applyIf, isFunction, isBoolean } = require("Ext/core/core/Ext");
+const DelayedTask = require("Ext/util/core/DelayedTask");
+
/**
* @class Ext.util.Observable
* Base class that provides a common interface for publishing events. Subclasses are expected to
@@ -48,7 +44,7 @@ var newEmployee = new Employee({
});
*/
-EXTUTIL.Observable = function(){
+const Observable = function(){
/**
* @cfg {Object} listeners (optional) A config object containing one or more event handlers to be added to this
* object during initialization. This should be a valid listeners config object as specified in the
@@ -116,7 +112,7 @@ var combo = new Ext.form.ComboBox({
me.events = e || {};
};
-EXTUTIL.Observable.prototype = {
+Observable.prototype = {
// private
filterOptRe : /^(?:scope|delay|buffer|single)$/,
@@ -129,32 +125,32 @@ EXTUTIL.Observable.prototype = {
* @return {Boolean} returns false if any of the handlers return false otherwise it returns true.
*/
fireEvent : function(){
- var a = TOARRAY(arguments),
+ var a = toArray(arguments),
ename = a[0].toLowerCase(),
me = this,
- ret = TRUE,
+ ret = true,
ce = me.events[ename],
q,
c;
- if (me.eventsSuspended === TRUE) {
+ if (me.eventsSuspended === true) {
if (q = me.eventQueue) {
q.push(a);
}
}
- else if(ISOBJECT(ce) && ce.bubble){
- if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
- return FALSE;
+ else if(isObject(ce) && ce.bubble){
+ if(ce.fire.apply(ce, a.slice(1)) === false) {
+ return false;
}
c = me.getBubbleTarget && me.getBubbleTarget();
if(c && c.enableBubble) {
- if(!c.events[ename] || !Ext.isObject(c.events[ename]) || !c.events[ename].bubble) {
+ if(!c.events[ename] || !isObject(c.events[ename]) || !c.events[ename].bubble) {
c.enableBubble(ename);
}
return c.fireEvent.apply(c, a);
}
}
else {
- if (ISOBJECT(ce)) {
+ if (isObject(ce)) {
a.shift();
ret = ce.fire.apply(ce, a);
}
@@ -167,7 +163,7 @@ EXTUTIL.Observable.prototype = {
ce.isAsync = true;
const r = this.fireEvent.apply(this, arguments);
ce.isAsync = false;
- return !r || r === true ? Promise.resolve() : (Ext.isFunction(r.then) ? r : Promise.reject());
+ return !r || r === true ? Promise.resolve() : (isFunction(r.then) ? r : Promise.reject());
},
/**
@@ -235,7 +231,7 @@ myGridPanel.on({
oe,
isF,
ce;
- if (ISOBJECT(eventName)) {
+ if (isObject(eventName)) {
o = eventName;
for (e in o){
oe = o[e];
@@ -245,11 +241,11 @@ myGridPanel.on({
}
} else {
eventName = eventName.toLowerCase();
- ce = me.events[eventName] || TRUE;
- if (Ext.isBoolean(ce)) {
- me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
+ ce = me.events[eventName] || true;
+ if (isBoolean(ce)) {
+ me.events[eventName] = ce = new Event(me, eventName);
}
- ce.addListener(fn, scope, ISOBJECT(o) ? o : {});
+ ce.addListener(fn, scope, isObject(o) ? o : {});
}
},
@@ -261,7 +257,7 @@ myGridPanel.on({
*/
removeListener : function(eventName, fn, scope){
var ce = this.events[eventName.toLowerCase()];
- if (ISOBJECT(ce)) {
+ if (isObject(ce)) {
ce.removeListener(fn, scope);
}
},
@@ -275,7 +271,7 @@ myGridPanel.on({
key;
for(key in events){
evt = events[key];
- if(ISOBJECT(evt)){
+ if(isObject(evt)){
evt.clearListeners();
}
}
@@ -293,14 +289,14 @@ this.addEvents('storeloaded', 'storecleared');
addEvents : function(o){
var me = this;
me.events = me.events || {};
- if (Ext.isString(o)) {
+ if (isString(o)) {
var a = arguments,
i = a.length;
while(i--) {
- me.events[a[i]] = me.events[a[i]] || TRUE;
+ me.events[a[i]] = me.events[a[i]] || true;
}
} else {
- Ext.applyIf(me.events, o);
+ applyIf(me.events, o);
}
},
@@ -311,7 +307,7 @@ this.addEvents('storeloaded', 'storecleared');
*/
hasListener : function(eventName){
var e = this.events[eventName];
- return ISOBJECT(e) && e.listeners.length > 0;
+ return isObject(e) && e.listeners.length > 0;
},
/**
@@ -320,7 +316,7 @@ this.addEvents('storeloaded', 'storecleared');
* after the {@link #resumeEvents} call instead of discarding all suspended events;
*/
suspendEvents : function(queueSuspended){
- this.eventsSuspended = TRUE;
+ this.eventsSuspended = true;
if(queueSuspended && !this.eventQueue){
this.eventQueue = [];
}
@@ -334,15 +330,14 @@ this.addEvents('storeloaded', 'storecleared');
resumeEvents : function(){
var me = this,
queued = me.eventQueue || [];
- me.eventsSuspended = FALSE;
+ me.eventsSuspended = false;
delete me.eventQueue;
- EACH(queued, function(e) {
+ each(queued, function(e) {
me.fireEvent.apply(me, e);
});
}
};
-var OBSERVABLE = EXTUTIL.Observable.prototype;
/**
* Appends an event handler to this object (shorthand for {@link #addListener}.)
* @param {String} eventName The type of event to listen for
@@ -352,7 +347,7 @@ var OBSERVABLE = EXTUTIL.Observable.prototype;
* @param {Object} options (optional) An object containing handler configuration.
* @method
*/
-OBSERVABLE.on = OBSERVABLE.addListener;
+Observable.prototype.on = Observable.prototype.addListener;
/**
* Removes an event handler (shorthand for {@link #removeListener}.)
* @param {String} eventName The type of event the handler was associated with.
@@ -360,29 +355,29 @@ OBSERVABLE.on = OBSERVABLE.addListener;
* @param {Object} scope (optional) The scope originally specified for the handler.
* @method
*/
-OBSERVABLE.un = OBSERVABLE.removeListener;
+Observable.prototype.un = Observable.prototype.removeListener;
/**
* Removes all added captures from the Observable.
* @param {Observable} o The Observable to release
* @static
*/
-EXTUTIL.Observable.releaseCapture = function(o){
- o.fireEvent = OBSERVABLE.fireEvent;
+Observable.releaseCapture = function(o){
+ o.fireEvent = Observable.prototype.fireEvent;
};
function createTargeted(h, o, scope){
return function(){
if(o.target == arguments[0]){
- h.apply(scope, TOARRAY(arguments));
+ h.apply(scope, toArray(arguments));
}
};
};
function createBuffered(h, o, l, scope){
- l.task = new EXTUTIL.DelayedTask();
+ l.task = new DelayedTask();
return function(){
- l.task.delay(o.buffer, h, scope, TOARRAY(arguments));
+ l.task.delay(o.buffer, h, scope, toArray(arguments));
};
};
@@ -395,23 +390,23 @@ function createSingle(h, e, fn, scope){
function createDelayed(h, o, l, scope){
return function(){
- var task = new EXTUTIL.DelayedTask();
+ var task = new DelayedTask();
if(!l.tasks) {
l.tasks = [];
}
l.tasks.push(task);
- task.delay(o.delay || 10, h, scope, TOARRAY(arguments));
+ task.delay(o.delay || 10, h, scope, toArray(arguments));
};
};
-EXTUTIL.Event = function(obj, name){
+const Event = function(obj, name){
this.name = name;
this.obj = obj;
this.listeners = [];
this.isAsync = false;
};
-EXTUTIL.Event.prototype = {
+Event.prototype = {
addListener : function(fn, scope, options){
var me = this,
l;
@@ -474,7 +469,7 @@ EXTUTIL.Event.prototype = {
l,
k,
me = this,
- ret = FALSE;
+ ret = false;
if((index = me.findListener(fn, scope)) != -1){
if (me.firing) {
me.listeners = me.listeners.slice(0);
@@ -492,7 +487,7 @@ EXTUTIL.Event.prototype = {
delete l.tasks;
}
me.listeners.splice(index, 1);
- ret = TRUE;
+ ret = true;
}
return ret;
},
@@ -511,31 +506,31 @@ EXTUTIL.Event.prototype = {
if (this.isAsync) return this.fireAsync.apply(this, arguments);
var me = this,
- args = TOARRAY(arguments),
+ args = toArray(arguments),
listeners = me.listeners,
len = listeners.length,
i = 0,
l;
if(len > 0){
- me.firing = TRUE;
+ me.firing = true;
for (; i < len; i++) {
l = listeners[i];
- if(l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
- return (me.firing = FALSE);
+ if(l && l.fireFn.apply(l.scope || me.obj || window, args) === false) {
+ return (me.firing = false);
}
}
}
- me.firing = FALSE;
- return TRUE;
+ me.firing = false;
+ return true;
},
fireAsync : async function() {
- const args = TOARRAY(arguments);
+ const args = toArray(arguments);
let result = Promise.resolve();
if (this.listeners.length) {
- this.firing = TRUE;
+ this.firing = true;
for (let listener of this.listeners) {
try {
@@ -548,9 +543,10 @@ EXTUTIL.Event.prototype = {
}
}
- this.firing = FALSE;
+ this.firing = false;
}
return result;
}
};
-})();
+
+module.exports = { Observable, Event }
\ No newline at end of file