retold-data-service 2.0.42 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +15 -13
- package/source/services/data-cloner/DataCloner-Command-Connection.js +41 -1
- package/source/services/data-cloner/pict-app/Pict-Application-DataCloner.js +50 -16
- package/source/services/data-cloner/pict-app/providers/Pict-Provider-DataCloner.js +185 -96
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Connection.js +181 -383
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Export.js +34 -57
- package/source/services/data-cloner/web/data-cloner.js +1116 -530
- package/source/services/data-cloner/web/data-cloner.js.map +1 -1
- package/source/services/data-cloner/web/data-cloner.min.js +1 -1
- package/source/services/data-cloner/web/data-cloner.min.js.map +1 -1
|
@@ -1817,6 +1817,626 @@
|
|
|
1817
1817
|
"fable-serviceproviderbase": 2
|
|
1818
1818
|
}],
|
|
1819
1819
|
7: [function (require, module, exports) {
|
|
1820
|
+
/**
|
|
1821
|
+
* Default Pict-view configuration for PictSection-ConnectionForm.
|
|
1822
|
+
*
|
|
1823
|
+
* Host applications register the view with their own ContainerSelector
|
|
1824
|
+
* and field-id prefix (so multiple connection forms can coexist without
|
|
1825
|
+
* DOM-id collisions). All other defaults live here.
|
|
1826
|
+
*
|
|
1827
|
+
* The host owns:
|
|
1828
|
+
* - Where in the DOM the form lands (DefaultDestinationAddress / TargetSelector)
|
|
1829
|
+
* - Where in AppData the schemas + active provider live (SchemasAddress / ActiveAddress)
|
|
1830
|
+
* - The DOM-id prefix used to namespace per-field input ids (FieldIDPrefix)
|
|
1831
|
+
* - Whether the provider <select> is visible at all (ShowProviderSelect)
|
|
1832
|
+
* - Whether the "Advanced" <details> block is rendered (ShowAdvancedToggle)
|
|
1833
|
+
*/
|
|
1834
|
+
'use strict';
|
|
1835
|
+
|
|
1836
|
+
module.exports = {
|
|
1837
|
+
ViewIdentifier: 'PictSection-ConnectionForm',
|
|
1838
|
+
DefaultRenderable: 'PictSection-ConnectionForm-Main',
|
|
1839
|
+
DefaultDestinationAddress: '#PictSection-ConnectionForm-Slot',
|
|
1840
|
+
AutoRender: false,
|
|
1841
|
+
// Host-overridable knobs
|
|
1842
|
+
SchemasAddress: 'AppData.Connection.Schemas',
|
|
1843
|
+
ActiveAddress: 'AppData.Connection.ActiveProvider',
|
|
1844
|
+
FieldIDPrefix: 'pict-conn',
|
|
1845
|
+
ShowProviderSelect: true,
|
|
1846
|
+
ShowAdvancedToggle: true
|
|
1847
|
+
};
|
|
1848
|
+
}, {}],
|
|
1849
|
+
8: [function (require, module, exports) {
|
|
1850
|
+
/**
|
|
1851
|
+
* PictSection-ConnectionForm
|
|
1852
|
+
*
|
|
1853
|
+
* Schema-driven Meadow connection-form view. Renders a provider
|
|
1854
|
+
* <select> + per-provider field block from the form schemas exported
|
|
1855
|
+
* by each `meadow-connection-*` module (and aggregated server-side via
|
|
1856
|
+
* `meadow-connection-manager#getAllProviderFormSchemas()`).
|
|
1857
|
+
*
|
|
1858
|
+
* Three host applications consume this:
|
|
1859
|
+
* - retold-data-service / DataCloner (single active provider, "connect/test" UX)
|
|
1860
|
+
* - retold-databeacon / Connection list (add/edit named saved connections)
|
|
1861
|
+
* - retold-facto / Store connections (add/edit named saved connections)
|
|
1862
|
+
*
|
|
1863
|
+
* Each host wires it with a different DOM destination + AppData
|
|
1864
|
+
* address + DOM-id prefix so multiple connection forms can coexist
|
|
1865
|
+
* without colliding on element ids.
|
|
1866
|
+
*
|
|
1867
|
+
* ── Wiring contract ────────────────────────────────────────────────
|
|
1868
|
+
* Host AppData (configurable via SchemasAddress / ActiveAddress):
|
|
1869
|
+
* AppData.<...>.Schemas array of schemas (see field shape)
|
|
1870
|
+
* AppData.<...>.ActiveProvider string — currently selected Provider
|
|
1871
|
+
*
|
|
1872
|
+
* Host options on the view (registered via pict.addView):
|
|
1873
|
+
* ContainerSelector — where to render (overrides DefaultDestinationAddress)
|
|
1874
|
+
* SchemasAddress — AppData address of the Schemas array
|
|
1875
|
+
* ActiveAddress — AppData address of the ActiveProvider string
|
|
1876
|
+
* FieldIDPrefix — DOM-id namespace ('pict-conn' default)
|
|
1877
|
+
* ShowProviderSelect — whether to render the <select> (false = single-provider mode)
|
|
1878
|
+
* ShowAdvancedToggle — whether the Advanced group is collapsible
|
|
1879
|
+
* OnProviderChange(p) — optional callback when the user picks a different provider
|
|
1880
|
+
*
|
|
1881
|
+
* Host calls (instance methods):
|
|
1882
|
+
* setSchemas(pSchemas) — replace schema list and re-render
|
|
1883
|
+
* setActiveProvider(pProvider) — switch active provider
|
|
1884
|
+
* getProviderConfig() — collect form values → { Provider, Config }
|
|
1885
|
+
* setValues(pProvider, pConfig) — populate fields from a saved config blob
|
|
1886
|
+
* clear() — reset all fields to schema defaults
|
|
1887
|
+
*
|
|
1888
|
+
* ── Field shape (from each meadow-connection-* schema) ─────────────
|
|
1889
|
+
* Name — canonical config key (lowercase for SQL drivers, dotted for nested)
|
|
1890
|
+
* Label — UI label
|
|
1891
|
+
* Type — String | Number | Password | Boolean | Path | Select
|
|
1892
|
+
* Default — initial value
|
|
1893
|
+
* Required — boolean
|
|
1894
|
+
* Placeholder, Help, Min, Max — UI hints
|
|
1895
|
+
* Group — 'Basic' (default) or 'Advanced' (rendered under <details>)
|
|
1896
|
+
* Multiplier — form value × multiplier = stored value (sec→ms via 1000)
|
|
1897
|
+
* MapTo — array of dotted-path targets (one input → multiple keys)
|
|
1898
|
+
* OmitIfFalsy — drop key from emitted config when value is 0/empty/false
|
|
1899
|
+
* Options — for Select: [{ Value, Label }]
|
|
1900
|
+
*
|
|
1901
|
+
* Pure presentation — does NOT fetch schemas itself. Host fetches
|
|
1902
|
+
* them however it likes (typical: GET /<app>/connection/schemas
|
|
1903
|
+
* backed by MCM) and calls setSchemas() once they arrive.
|
|
1904
|
+
*/
|
|
1905
|
+
'use strict';
|
|
1906
|
+
|
|
1907
|
+
const libPictView = require('pict-view');
|
|
1908
|
+
const _DefaultConfiguration = require('./Pict-Section-ConnectionForm-DefaultConfiguration.js');
|
|
1909
|
+
const _BaseCSS = /*css*/`
|
|
1910
|
+
.pict-conn-form {
|
|
1911
|
+
display: flex;
|
|
1912
|
+
flex-direction: column;
|
|
1913
|
+
gap: 10px;
|
|
1914
|
+
}
|
|
1915
|
+
.pict-conn-form__provider-row {
|
|
1916
|
+
display: flex;
|
|
1917
|
+
gap: 10px;
|
|
1918
|
+
align-items: flex-end;
|
|
1919
|
+
}
|
|
1920
|
+
.pict-conn-form__provider-row label {
|
|
1921
|
+
font-size: 12px;
|
|
1922
|
+
font-weight: 600;
|
|
1923
|
+
color: #475569;
|
|
1924
|
+
text-transform: uppercase;
|
|
1925
|
+
letter-spacing: 0.3px;
|
|
1926
|
+
display: flex;
|
|
1927
|
+
flex-direction: column;
|
|
1928
|
+
gap: 4px;
|
|
1929
|
+
flex: 0 0 200px;
|
|
1930
|
+
}
|
|
1931
|
+
.pict-conn-form__provider-row select {
|
|
1932
|
+
font-family: inherit;
|
|
1933
|
+
font-size: 14px;
|
|
1934
|
+
padding: 7px 10px;
|
|
1935
|
+
border: 1px solid #cbd5e1;
|
|
1936
|
+
border-radius: 6px;
|
|
1937
|
+
background: #fff;
|
|
1938
|
+
color: #0f172a;
|
|
1939
|
+
height: 36px;
|
|
1940
|
+
}
|
|
1941
|
+
.pict-conn-form__provider-form {
|
|
1942
|
+
display: grid;
|
|
1943
|
+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
1944
|
+
gap: 10px 16px;
|
|
1945
|
+
}
|
|
1946
|
+
.pict-conn-form__field {
|
|
1947
|
+
display: flex;
|
|
1948
|
+
flex-direction: column;
|
|
1949
|
+
gap: 4px;
|
|
1950
|
+
}
|
|
1951
|
+
.pict-conn-form__field label {
|
|
1952
|
+
font-size: 12px;
|
|
1953
|
+
font-weight: 600;
|
|
1954
|
+
color: #475569;
|
|
1955
|
+
text-transform: uppercase;
|
|
1956
|
+
letter-spacing: 0.3px;
|
|
1957
|
+
}
|
|
1958
|
+
.pict-conn-form__field input,
|
|
1959
|
+
.pict-conn-form__field select {
|
|
1960
|
+
font-family: inherit;
|
|
1961
|
+
font-size: 14px;
|
|
1962
|
+
padding: 7px 10px;
|
|
1963
|
+
border: 1px solid #cbd5e1;
|
|
1964
|
+
border-radius: 6px;
|
|
1965
|
+
background: #fff;
|
|
1966
|
+
color: #0f172a;
|
|
1967
|
+
}
|
|
1968
|
+
.pict-conn-form__field input[type="checkbox"] {
|
|
1969
|
+
width: auto;
|
|
1970
|
+
height: auto;
|
|
1971
|
+
align-self: flex-start;
|
|
1972
|
+
}
|
|
1973
|
+
.pict-conn-form__field-help {
|
|
1974
|
+
font-size: 11px;
|
|
1975
|
+
color: #64748b;
|
|
1976
|
+
}
|
|
1977
|
+
.pict-conn-form__advanced {
|
|
1978
|
+
grid-column: 1 / -1;
|
|
1979
|
+
margin-top: 4px;
|
|
1980
|
+
}
|
|
1981
|
+
.pict-conn-form__advanced > summary {
|
|
1982
|
+
cursor: pointer;
|
|
1983
|
+
font-weight: 600;
|
|
1984
|
+
color: #475569;
|
|
1985
|
+
font-size: 12px;
|
|
1986
|
+
text-transform: uppercase;
|
|
1987
|
+
letter-spacing: 0.3px;
|
|
1988
|
+
padding: 4px 0;
|
|
1989
|
+
}
|
|
1990
|
+
.pict-conn-form__advanced > p {
|
|
1991
|
+
margin: 8px 0;
|
|
1992
|
+
font-size: 12px;
|
|
1993
|
+
color: #64748b;
|
|
1994
|
+
}
|
|
1995
|
+
.pict-conn-form__advanced > .pict-conn-form__advanced-fields {
|
|
1996
|
+
display: grid;
|
|
1997
|
+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
1998
|
+
gap: 10px 16px;
|
|
1999
|
+
}
|
|
2000
|
+
.pict-conn-form__no-schemas {
|
|
2001
|
+
padding: 12px;
|
|
2002
|
+
background: #fef3c7;
|
|
2003
|
+
border: 1px solid #f59e0b;
|
|
2004
|
+
border-radius: 6px;
|
|
2005
|
+
color: #92400e;
|
|
2006
|
+
font-size: 13px;
|
|
2007
|
+
}
|
|
2008
|
+
`;
|
|
2009
|
+
const _BaseTemplates = [{
|
|
2010
|
+
Hash: 'PictSection-ConnectionForm-Main',
|
|
2011
|
+
Template: /*html*/`
|
|
2012
|
+
<div class="pict-conn-form" id="{~D:AppData.PictSectionConnectionForm.RootId~}">
|
|
2013
|
+
{~TS:PictSection-ConnectionForm-Selector:AppData.PictSectionConnectionForm.SelectorSlot~}
|
|
2014
|
+
<div class="pict-conn-form__forms" id="{~D:AppData.PictSectionConnectionForm.FormsId~}">
|
|
2015
|
+
{~TS:PictSection-ConnectionForm-ProviderForm:AppData.PictSectionConnectionForm.ProviderForms~}
|
|
2016
|
+
</div>
|
|
2017
|
+
{~TS:PictSection-ConnectionForm-NoSchemas:AppData.PictSectionConnectionForm.NoSchemasSlot~}
|
|
2018
|
+
</div>`
|
|
2019
|
+
}, {
|
|
2020
|
+
Hash: 'PictSection-ConnectionForm-Selector',
|
|
2021
|
+
Template: /*html*/`
|
|
2022
|
+
<div class="pict-conn-form__provider-row">
|
|
2023
|
+
<label>Provider
|
|
2024
|
+
<select id="{~D:Record.SelectId~}" onchange="{~P~}.views['{~D:Record.ViewHash~}'].onProviderSelectChange(this.value)">
|
|
2025
|
+
{~TS:PictSection-ConnectionForm-ProviderOption:Record.Options~}
|
|
2026
|
+
</select>
|
|
2027
|
+
</label>
|
|
2028
|
+
</div>`
|
|
2029
|
+
}, {
|
|
2030
|
+
Hash: 'PictSection-ConnectionForm-ProviderOption',
|
|
2031
|
+
Template: /*html*/`<option value="{~D:Record.Provider~}" {~D:Record.SelectedAttr~}>{~D:Record.DisplayName~}</option>`
|
|
2032
|
+
}, {
|
|
2033
|
+
Hash: 'PictSection-ConnectionForm-ProviderForm',
|
|
2034
|
+
Template: /*html*/`
|
|
2035
|
+
<div class="pict-conn-form__provider-form" id="{~D:Record.FormId~}" style="display:{~D:Record.DisplayStyle~}">
|
|
2036
|
+
{~TS:PictSection-ConnectionForm-Field:Record.BasicFields~}
|
|
2037
|
+
{~TS:PictSection-ConnectionForm-Advanced:Record.AdvancedSlot~}
|
|
2038
|
+
</div>`
|
|
2039
|
+
}, {
|
|
2040
|
+
Hash: 'PictSection-ConnectionForm-Field',
|
|
2041
|
+
Template: /*html*/`
|
|
2042
|
+
<div class="pict-conn-form__field">
|
|
2043
|
+
<label for="{~D:Record.DOMId~}">{~D:Record.Label~}</label>
|
|
2044
|
+
{~D:Record.InputHTML~}
|
|
2045
|
+
{~TS:PictSection-ConnectionForm-FieldHelp:Record.HelpSlot~}
|
|
2046
|
+
</div>`
|
|
2047
|
+
}, {
|
|
2048
|
+
Hash: 'PictSection-ConnectionForm-FieldHelp',
|
|
2049
|
+
Template: /*html*/`<small class="pict-conn-form__field-help">{~D:Record.Help~}</small>`
|
|
2050
|
+
}, {
|
|
2051
|
+
Hash: 'PictSection-ConnectionForm-Advanced',
|
|
2052
|
+
Template: /*html*/`
|
|
2053
|
+
<details class="pict-conn-form__advanced">
|
|
2054
|
+
<summary>Advanced settings</summary>
|
|
2055
|
+
<p>Optional tuning — leave blank or zero to use the connection driver's defaults.</p>
|
|
2056
|
+
<div class="pict-conn-form__advanced-fields">
|
|
2057
|
+
{~TS:PictSection-ConnectionForm-Field:Record.Fields~}
|
|
2058
|
+
</div>
|
|
2059
|
+
</details>`
|
|
2060
|
+
}, {
|
|
2061
|
+
Hash: 'PictSection-ConnectionForm-NoSchemas',
|
|
2062
|
+
Template: /*html*/`<div class="pict-conn-form__no-schemas">No connection providers detected. Either <code>meadow-connection-manager</code> is older than 1.1.0 or no provider modules are installed in the host environment.</div>`
|
|
2063
|
+
}];
|
|
2064
|
+
class PictSectionConnectionForm extends libPictView {
|
|
2065
|
+
constructor(pFable, pOptions, pServiceHash) {
|
|
2066
|
+
// Merge host-supplied options on top of the module defaults.
|
|
2067
|
+
// Templates + CSS come from this module; host can override the
|
|
2068
|
+
// AppData addresses, the DOM destination, and the field-id prefix.
|
|
2069
|
+
let tmpOptions = Object.assign({}, _DefaultConfiguration, pOptions || {});
|
|
2070
|
+
if (!tmpOptions.Templates) {
|
|
2071
|
+
tmpOptions.Templates = _BaseTemplates;
|
|
2072
|
+
}
|
|
2073
|
+
if (!tmpOptions.CSS) {
|
|
2074
|
+
tmpOptions.CSS = _BaseCSS;
|
|
2075
|
+
}
|
|
2076
|
+
if (!tmpOptions.Renderables) {
|
|
2077
|
+
tmpOptions.Renderables = [{
|
|
2078
|
+
RenderableHash: 'PictSection-ConnectionForm-Main',
|
|
2079
|
+
TemplateHash: 'PictSection-ConnectionForm-Main',
|
|
2080
|
+
ContentDestinationAddress: tmpOptions.ContainerSelector || tmpOptions.DefaultDestinationAddress,
|
|
2081
|
+
RenderMethod: 'replace'
|
|
2082
|
+
}];
|
|
2083
|
+
}
|
|
2084
|
+
super(pFable, tmpOptions, pServiceHash);
|
|
2085
|
+
this._Schemas = [];
|
|
2086
|
+
this._ActiveProvider = '';
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
// ====================================================================
|
|
2090
|
+
// Public API — hosts call these to drive the view
|
|
2091
|
+
// ====================================================================
|
|
2092
|
+
|
|
2093
|
+
setSchemas(pSchemas) {
|
|
2094
|
+
this._Schemas = Array.isArray(pSchemas) ? pSchemas : [];
|
|
2095
|
+
// If no active provider yet, default to the first schema.
|
|
2096
|
+
if (!this._ActiveProvider && this._Schemas.length > 0) {
|
|
2097
|
+
this._ActiveProvider = this._Schemas[0].Provider;
|
|
2098
|
+
}
|
|
2099
|
+
this._writeAppData();
|
|
2100
|
+
this.render();
|
|
2101
|
+
}
|
|
2102
|
+
setActiveProvider(pProvider) {
|
|
2103
|
+
this._ActiveProvider = pProvider || '';
|
|
2104
|
+
this._writeAppData();
|
|
2105
|
+
this.render();
|
|
2106
|
+
this._invokeProviderChangeCallback();
|
|
2107
|
+
}
|
|
2108
|
+
getActiveProvider() {
|
|
2109
|
+
return this._ActiveProvider;
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
/**
|
|
2113
|
+
* Read the active provider's form values out of the DOM and
|
|
2114
|
+
* collect them into the canonical wire-format config blob the
|
|
2115
|
+
* provider's connection driver expects. Honors:
|
|
2116
|
+
* - Multiplier (form value × multiplier = stored value)
|
|
2117
|
+
* - MapTo (one input → multiple dotted-path targets)
|
|
2118
|
+
* - OmitIfFalsy (drop key when value is 0/empty/false)
|
|
2119
|
+
* - Type-aware reads (Boolean→.checked, Number→parseInt, else trimmed string)
|
|
2120
|
+
*
|
|
2121
|
+
* @returns {{Provider: string, Config: object}}
|
|
2122
|
+
*/
|
|
2123
|
+
getProviderConfig() {
|
|
2124
|
+
let tmpProvider = this._ActiveProvider;
|
|
2125
|
+
let tmpSchema = this._Schemas.find(pS => pS.Provider === tmpProvider);
|
|
2126
|
+
if (!tmpSchema) {
|
|
2127
|
+
return {
|
|
2128
|
+
Provider: tmpProvider,
|
|
2129
|
+
Config: {}
|
|
2130
|
+
};
|
|
2131
|
+
}
|
|
2132
|
+
let tmpConfig = {};
|
|
2133
|
+
(tmpSchema.Fields || []).forEach(pField => this._collectField(tmpProvider, pField, tmpConfig));
|
|
2134
|
+
return {
|
|
2135
|
+
Provider: tmpProvider,
|
|
2136
|
+
Config: tmpConfig
|
|
2137
|
+
};
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2140
|
+
/**
|
|
2141
|
+
* Populate the form from a saved config blob. Used by edit
|
|
2142
|
+
* workflows (DataBeacon / Facto) that load a named connection
|
|
2143
|
+
* record and want its values pre-filled.
|
|
2144
|
+
*
|
|
2145
|
+
* @param {string} pProvider
|
|
2146
|
+
* @param {object} pConfig — wire-format config (same shape getProviderConfig returns)
|
|
2147
|
+
*/
|
|
2148
|
+
setValues(pProvider, pConfig) {
|
|
2149
|
+
this._ActiveProvider = pProvider || '';
|
|
2150
|
+
this._writeAppData();
|
|
2151
|
+
this.render();
|
|
2152
|
+
let tmpSchema = this._Schemas.find(pS => pS.Provider === pProvider);
|
|
2153
|
+
if (!tmpSchema || typeof document === 'undefined') {
|
|
2154
|
+
return;
|
|
2155
|
+
}
|
|
2156
|
+
(tmpSchema.Fields || []).forEach(pField => {
|
|
2157
|
+
let tmpDOMId = this.fieldDOMId(pProvider, pField.Name);
|
|
2158
|
+
let tmpEl = document.getElementById(tmpDOMId);
|
|
2159
|
+
if (!tmpEl) {
|
|
2160
|
+
return;
|
|
2161
|
+
}
|
|
2162
|
+
let tmpVal = this._readNested(pConfig || {}, pField.MapTo && pField.MapTo[0] ? pField.MapTo[0] : pField.Name);
|
|
2163
|
+
// Reverse-apply Multiplier (storage unit → display unit).
|
|
2164
|
+
if (pField.Multiplier && typeof tmpVal === 'number') {
|
|
2165
|
+
tmpVal = Math.floor(tmpVal / pField.Multiplier);
|
|
2166
|
+
}
|
|
2167
|
+
if (pField.Type === 'Boolean') {
|
|
2168
|
+
tmpEl.checked = !!tmpVal;
|
|
2169
|
+
} else if (tmpVal === undefined || tmpVal === null) {/* leave default */} else {
|
|
2170
|
+
tmpEl.value = String(tmpVal);
|
|
2171
|
+
}
|
|
2172
|
+
});
|
|
2173
|
+
}
|
|
2174
|
+
clear() {
|
|
2175
|
+
this._ActiveProvider = this._Schemas.length > 0 ? this._Schemas[0].Provider : '';
|
|
2176
|
+
this._writeAppData();
|
|
2177
|
+
this.render();
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
// ====================================================================
|
|
2181
|
+
// DOM-id helper — host code can use this to find a specific input
|
|
2182
|
+
// ====================================================================
|
|
2183
|
+
|
|
2184
|
+
fieldDOMId(pProvider, pFieldName) {
|
|
2185
|
+
let tmpPrefix = this.options.FieldIDPrefix || 'pict-conn';
|
|
2186
|
+
let tmpProvider = String(pProvider || '').toLowerCase();
|
|
2187
|
+
let tmpField = String(pFieldName || '').replace(/\./g, '_');
|
|
2188
|
+
return `${tmpPrefix}-${tmpProvider}-${tmpField}`;
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
// ====================================================================
|
|
2192
|
+
// Lifecycle hooks
|
|
2193
|
+
// ====================================================================
|
|
2194
|
+
|
|
2195
|
+
onBeforeRender(pRenderable) {
|
|
2196
|
+
this._writeAppData();
|
|
2197
|
+
return super.onBeforeRender(pRenderable);
|
|
2198
|
+
}
|
|
2199
|
+
onAfterRender(pRenderable, pAddress, pRecord, pContent) {
|
|
2200
|
+
// Toggle visibility on the active provider's form (the templates
|
|
2201
|
+
// pre-render a wrapper for every schema so values persist when
|
|
2202
|
+
// the user switches between providers).
|
|
2203
|
+
if (typeof document !== 'undefined') {
|
|
2204
|
+
this._Schemas.forEach(pSchema => {
|
|
2205
|
+
let tmpEl = document.getElementById(this._formId(pSchema.Provider));
|
|
2206
|
+
if (tmpEl) {
|
|
2207
|
+
tmpEl.style.display = pSchema.Provider === this._ActiveProvider ? '' : 'none';
|
|
2208
|
+
}
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2211
|
+
this.pict.CSSMap.injectCSS();
|
|
2212
|
+
return super.onAfterRender(pRenderable, pAddress, pRecord, pContent);
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
// ====================================================================
|
|
2216
|
+
// Selector-change handler (called from the rendered <select>)
|
|
2217
|
+
// ====================================================================
|
|
2218
|
+
|
|
2219
|
+
onProviderSelectChange(pProvider) {
|
|
2220
|
+
this.setActiveProvider(pProvider);
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
// ====================================================================
|
|
2224
|
+
// Internals
|
|
2225
|
+
// ====================================================================
|
|
2226
|
+
|
|
2227
|
+
/**
|
|
2228
|
+
* Push the computed render records into AppData under the address
|
|
2229
|
+
* the templates read from. Templates always read from
|
|
2230
|
+
* `AppData.PictSectionConnectionForm.*` regardless of where the
|
|
2231
|
+
* host's "real" Schemas / ActiveProvider live; that's because Pict
|
|
2232
|
+
* template addresses are static strings and we want one set of
|
|
2233
|
+
* templates to work for many host configurations. The real
|
|
2234
|
+
* SchemasAddress / ActiveAddress are also written so hosts can
|
|
2235
|
+
* read them out for their own state-tracking.
|
|
2236
|
+
*/
|
|
2237
|
+
_writeAppData() {
|
|
2238
|
+
if (!this.pict.AppData) {
|
|
2239
|
+
this.pict.AppData = {};
|
|
2240
|
+
}
|
|
2241
|
+
let tmpRoot = this.pict.AppData.PictSectionConnectionForm = this.pict.AppData.PictSectionConnectionForm || {};
|
|
2242
|
+
let tmpPrefix = this.options.FieldIDPrefix || 'pict-conn';
|
|
2243
|
+
tmpRoot.RootId = `${tmpPrefix}-root`;
|
|
2244
|
+
tmpRoot.FormsId = `${tmpPrefix}-forms`;
|
|
2245
|
+
|
|
2246
|
+
// Selector slot — empty array hides the <select>, single-element
|
|
2247
|
+
// renders it once. Honors ShowProviderSelect.
|
|
2248
|
+
if (this.options.ShowProviderSelect && this._Schemas.length > 0) {
|
|
2249
|
+
tmpRoot.SelectorSlot = [{
|
|
2250
|
+
SelectId: `${tmpPrefix}-provider-select`,
|
|
2251
|
+
ViewHash: this.Hash,
|
|
2252
|
+
Options: this._Schemas.map(pS => ({
|
|
2253
|
+
Provider: pS.Provider,
|
|
2254
|
+
DisplayName: this._escape(pS.DisplayName || pS.Provider),
|
|
2255
|
+
SelectedAttr: pS.Provider === this._ActiveProvider ? 'selected' : ''
|
|
2256
|
+
}))
|
|
2257
|
+
}];
|
|
2258
|
+
} else {
|
|
2259
|
+
tmpRoot.SelectorSlot = [];
|
|
2260
|
+
}
|
|
2261
|
+
tmpRoot.ProviderForms = this._Schemas.map(pSchema => this._buildProviderForm(pSchema, pSchema.Provider === this._ActiveProvider));
|
|
2262
|
+
tmpRoot.NoSchemasSlot = this._Schemas.length === 0 ? [{}] : [];
|
|
2263
|
+
|
|
2264
|
+
// Mirror state into the host's configured AppData addresses (so
|
|
2265
|
+
// hosts that read AppData directly see live values).
|
|
2266
|
+
if (this.options.SchemasAddress) {
|
|
2267
|
+
this._writeAppDataAddress(this.options.SchemasAddress, this._Schemas);
|
|
2268
|
+
}
|
|
2269
|
+
if (this.options.ActiveAddress) {
|
|
2270
|
+
this._writeAppDataAddress(this.options.ActiveAddress, this._ActiveProvider);
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
_buildProviderForm(pSchema, pIsActive) {
|
|
2274
|
+
let tmpFields = pSchema.Fields || [];
|
|
2275
|
+
let tmpBasic = [];
|
|
2276
|
+
let tmpAdvanced = [];
|
|
2277
|
+
tmpFields.forEach(pField => {
|
|
2278
|
+
let tmpRecord = this._buildFieldRecord(pField, pSchema.Provider);
|
|
2279
|
+
if (pField.Group === 'Advanced') {
|
|
2280
|
+
tmpAdvanced.push(tmpRecord);
|
|
2281
|
+
} else {
|
|
2282
|
+
tmpBasic.push(tmpRecord);
|
|
2283
|
+
}
|
|
2284
|
+
});
|
|
2285
|
+
return {
|
|
2286
|
+
Provider: pSchema.Provider,
|
|
2287
|
+
FormId: this._formId(pSchema.Provider),
|
|
2288
|
+
DisplayStyle: pIsActive ? '' : 'none',
|
|
2289
|
+
BasicFields: tmpBasic,
|
|
2290
|
+
AdvancedSlot: this.options.ShowAdvancedToggle && tmpAdvanced.length > 0 ? [{
|
|
2291
|
+
Fields: tmpAdvanced
|
|
2292
|
+
}] : []
|
|
2293
|
+
};
|
|
2294
|
+
}
|
|
2295
|
+
_buildFieldRecord(pField, pProvider) {
|
|
2296
|
+
let tmpDOMId = this.fieldDOMId(pProvider, pField.Name);
|
|
2297
|
+
return {
|
|
2298
|
+
DOMId: tmpDOMId,
|
|
2299
|
+
Label: this._escape(pField.Label || pField.Name),
|
|
2300
|
+
InputHTML: this._buildInputHTML(pField, tmpDOMId),
|
|
2301
|
+
HelpSlot: pField.Help ? [{
|
|
2302
|
+
Help: this._escape(pField.Help)
|
|
2303
|
+
}] : []
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
_buildInputHTML(pField, pDOMId) {
|
|
2307
|
+
let tmpDefault = pField.Default !== undefined && pField.Default !== null ? String(pField.Default) : '';
|
|
2308
|
+
let tmpPlaceholder = pField.Placeholder ? this._escape(pField.Placeholder) : '';
|
|
2309
|
+
let tmpRequired = pField.Required ? ' required' : '';
|
|
2310
|
+
switch (pField.Type) {
|
|
2311
|
+
case 'Number':
|
|
2312
|
+
{
|
|
2313
|
+
let tmpMin = pField.Min !== undefined && pField.Min !== null ? ` min="${this._escape(String(pField.Min))}"` : '';
|
|
2314
|
+
let tmpMax = pField.Max !== undefined && pField.Max !== null ? ` max="${this._escape(String(pField.Max))}"` : '';
|
|
2315
|
+
return `<input type="number" id="${this._escape(pDOMId)}" value="${this._escape(tmpDefault)}" placeholder="${tmpPlaceholder}"${tmpMin}${tmpMax}${tmpRequired}>`;
|
|
2316
|
+
}
|
|
2317
|
+
case 'Password':
|
|
2318
|
+
return `<input type="password" id="${this._escape(pDOMId)}" placeholder="${tmpPlaceholder || '(optional)'}"${tmpRequired}>`;
|
|
2319
|
+
case 'Boolean':
|
|
2320
|
+
{
|
|
2321
|
+
let tmpChecked = pField.Default ? ' checked' : '';
|
|
2322
|
+
return `<input type="checkbox" id="${this._escape(pDOMId)}"${tmpChecked}>`;
|
|
2323
|
+
}
|
|
2324
|
+
case 'Select':
|
|
2325
|
+
{
|
|
2326
|
+
let tmpOptions = (pField.Options || []).map(pOpt => {
|
|
2327
|
+
let tmpVal = String(pOpt.Value);
|
|
2328
|
+
let tmpSel = tmpVal === tmpDefault ? ' selected' : '';
|
|
2329
|
+
return `<option value="${this._escape(tmpVal)}"${tmpSel}>${this._escape(pOpt.Label || tmpVal)}</option>`;
|
|
2330
|
+
}).join('');
|
|
2331
|
+
return `<select id="${this._escape(pDOMId)}"${tmpRequired}>${tmpOptions}</select>`;
|
|
2332
|
+
}
|
|
2333
|
+
case 'Path':
|
|
2334
|
+
case 'String':
|
|
2335
|
+
default:
|
|
2336
|
+
return `<input type="text" id="${this._escape(pDOMId)}" value="${this._escape(tmpDefault)}" placeholder="${tmpPlaceholder}"${tmpRequired}>`;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
_collectField(pProvider, pField, pConfigOut) {
|
|
2340
|
+
if (typeof document === 'undefined') {
|
|
2341
|
+
return;
|
|
2342
|
+
}
|
|
2343
|
+
let tmpDOMId = this.fieldDOMId(pProvider, pField.Name);
|
|
2344
|
+
let tmpEl = document.getElementById(tmpDOMId);
|
|
2345
|
+
if (!tmpEl) {
|
|
2346
|
+
return;
|
|
2347
|
+
}
|
|
2348
|
+
let tmpRaw;
|
|
2349
|
+
if (pField.Type === 'Boolean') {
|
|
2350
|
+
tmpRaw = !!tmpEl.checked;
|
|
2351
|
+
} else if (pField.Type === 'Number') {
|
|
2352
|
+
let tmpParsed = parseInt(tmpEl.value, 10);
|
|
2353
|
+
tmpRaw = isNaN(tmpParsed) ? 0 : tmpParsed;
|
|
2354
|
+
} else {
|
|
2355
|
+
tmpRaw = String(tmpEl.value || '').trim();
|
|
2356
|
+
}
|
|
2357
|
+
let tmpFinal = tmpRaw;
|
|
2358
|
+
if (pField.Multiplier && typeof tmpFinal === 'number') {
|
|
2359
|
+
tmpFinal = tmpFinal * pField.Multiplier;
|
|
2360
|
+
}
|
|
2361
|
+
if (pField.OmitIfFalsy && !tmpFinal) {
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
let tmpTargets = pField.MapTo && pField.MapTo.length ? pField.MapTo : [pField.Name];
|
|
2365
|
+
tmpTargets.forEach(pPath => this._setNested(pConfigOut, pPath, tmpFinal));
|
|
2366
|
+
}
|
|
2367
|
+
_setNested(pTarget, pPath, pValue) {
|
|
2368
|
+
let tmpParts = String(pPath).split('.');
|
|
2369
|
+
let tmpCursor = pTarget;
|
|
2370
|
+
for (let i = 0; i < tmpParts.length - 1; i++) {
|
|
2371
|
+
let tmpKey = tmpParts[i];
|
|
2372
|
+
if (typeof tmpCursor[tmpKey] !== 'object' || tmpCursor[tmpKey] === null) {
|
|
2373
|
+
tmpCursor[tmpKey] = {};
|
|
2374
|
+
}
|
|
2375
|
+
tmpCursor = tmpCursor[tmpKey];
|
|
2376
|
+
}
|
|
2377
|
+
tmpCursor[tmpParts[tmpParts.length - 1]] = pValue;
|
|
2378
|
+
}
|
|
2379
|
+
_readNested(pSource, pPath) {
|
|
2380
|
+
let tmpParts = String(pPath).split('.');
|
|
2381
|
+
let tmpCursor = pSource;
|
|
2382
|
+
for (let i = 0; i < tmpParts.length; i++) {
|
|
2383
|
+
if (tmpCursor === undefined || tmpCursor === null) {
|
|
2384
|
+
return undefined;
|
|
2385
|
+
}
|
|
2386
|
+
tmpCursor = tmpCursor[tmpParts[i]];
|
|
2387
|
+
}
|
|
2388
|
+
return tmpCursor;
|
|
2389
|
+
}
|
|
2390
|
+
_writeAppDataAddress(pAddress, pValue) {
|
|
2391
|
+
// Address is "AppData.X.Y" — drop the leading "AppData." prefix
|
|
2392
|
+
// before walking; if it's missing, fall through and treat the
|
|
2393
|
+
// whole string as a property chain off pict.AppData.
|
|
2394
|
+
let tmpRoot = this.pict.AppData;
|
|
2395
|
+
let tmpAddr = String(pAddress || '');
|
|
2396
|
+
if (tmpAddr.indexOf('AppData.') === 0) {
|
|
2397
|
+
tmpAddr = tmpAddr.substring('AppData.'.length);
|
|
2398
|
+
}
|
|
2399
|
+
if (!tmpAddr) {
|
|
2400
|
+
return;
|
|
2401
|
+
}
|
|
2402
|
+
let tmpParts = tmpAddr.split('.');
|
|
2403
|
+
let tmpCursor = tmpRoot;
|
|
2404
|
+
for (let i = 0; i < tmpParts.length - 1; i++) {
|
|
2405
|
+
let tmpKey = tmpParts[i];
|
|
2406
|
+
if (typeof tmpCursor[tmpKey] !== 'object' || tmpCursor[tmpKey] === null) {
|
|
2407
|
+
tmpCursor[tmpKey] = {};
|
|
2408
|
+
}
|
|
2409
|
+
tmpCursor = tmpCursor[tmpKey];
|
|
2410
|
+
}
|
|
2411
|
+
tmpCursor[tmpParts[tmpParts.length - 1]] = pValue;
|
|
2412
|
+
}
|
|
2413
|
+
_invokeProviderChangeCallback() {
|
|
2414
|
+
let tmpCb = this.options.OnProviderChange;
|
|
2415
|
+
if (typeof tmpCb === 'function') {
|
|
2416
|
+
try {
|
|
2417
|
+
tmpCb(this._ActiveProvider);
|
|
2418
|
+
} catch (pError) {
|
|
2419
|
+
if (this.log && this.log.warn) {
|
|
2420
|
+
this.log.warn(`PictSection-ConnectionForm: OnProviderChange callback threw: ${pError && pError.message}`);
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
_formId(pProvider) {
|
|
2426
|
+
let tmpPrefix = this.options.FieldIDPrefix || 'pict-conn';
|
|
2427
|
+
return `${tmpPrefix}-form-${String(pProvider || '').toLowerCase()}`;
|
|
2428
|
+
}
|
|
2429
|
+
_escape(pStr) {
|
|
2430
|
+
return String(pStr == null ? '' : pStr).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
module.exports = PictSectionConnectionForm;
|
|
2434
|
+
module.exports.default_configuration = _DefaultConfiguration;
|
|
2435
|
+
}, {
|
|
2436
|
+
"./Pict-Section-ConnectionForm-DefaultConfiguration.js": 7,
|
|
2437
|
+
"pict-view": 15
|
|
2438
|
+
}],
|
|
2439
|
+
9: [function (require, module, exports) {
|
|
1820
2440
|
module.exports = {
|
|
1821
2441
|
"RenderOnLoad": true,
|
|
1822
2442
|
"DefaultRenderable": "Histogram-Wrap",
|
|
@@ -2068,7 +2688,7 @@
|
|
|
2068
2688
|
`
|
|
2069
2689
|
};
|
|
2070
2690
|
}, {}],
|
|
2071
|
-
|
|
2691
|
+
10: [function (require, module, exports) {
|
|
2072
2692
|
/**
|
|
2073
2693
|
* Pict Section Histogram
|
|
2074
2694
|
*
|
|
@@ -2447,13 +3067,13 @@
|
|
|
2447
3067
|
cli: libRendererCLI
|
|
2448
3068
|
};
|
|
2449
3069
|
}, {
|
|
2450
|
-
"./Pict-Section-Histogram-DefaultConfiguration.js":
|
|
2451
|
-
"./renderers/Pict-Histogram-Renderer-Browser.js":
|
|
2452
|
-
"./renderers/Pict-Histogram-Renderer-CLI.js":
|
|
2453
|
-
"./renderers/Pict-Histogram-Renderer-ConsoleUI.js":
|
|
2454
|
-
"pict-view":
|
|
3070
|
+
"./Pict-Section-Histogram-DefaultConfiguration.js": 9,
|
|
3071
|
+
"./renderers/Pict-Histogram-Renderer-Browser.js": 11,
|
|
3072
|
+
"./renderers/Pict-Histogram-Renderer-CLI.js": 12,
|
|
3073
|
+
"./renderers/Pict-Histogram-Renderer-ConsoleUI.js": 13,
|
|
3074
|
+
"pict-view": 15
|
|
2455
3075
|
}],
|
|
2456
|
-
|
|
3076
|
+
11: [function (require, module, exports) {
|
|
2457
3077
|
/**
|
|
2458
3078
|
* Browser renderer for pict-section-histogram.
|
|
2459
3079
|
*
|
|
@@ -2756,7 +3376,7 @@
|
|
|
2756
3376
|
wireEvents
|
|
2757
3377
|
};
|
|
2758
3378
|
}, {}],
|
|
2759
|
-
|
|
3379
|
+
12: [function (require, module, exports) {
|
|
2760
3380
|
(function (process) {
|
|
2761
3381
|
(function () {
|
|
2762
3382
|
/**
|
|
@@ -3065,9 +3685,9 @@
|
|
|
3065
3685
|
}).call(this);
|
|
3066
3686
|
}).call(this, require('_process'));
|
|
3067
3687
|
}, {
|
|
3068
|
-
"_process":
|
|
3688
|
+
"_process": 16
|
|
3069
3689
|
}],
|
|
3070
|
-
|
|
3690
|
+
13: [function (require, module, exports) {
|
|
3071
3691
|
/**
|
|
3072
3692
|
* Console UI (blessed) renderer for pict-section-histogram.
|
|
3073
3693
|
*
|
|
@@ -3312,7 +3932,7 @@
|
|
|
3312
3932
|
renderHorizontal
|
|
3313
3933
|
};
|
|
3314
3934
|
}, {}],
|
|
3315
|
-
|
|
3935
|
+
14: [function (require, module, exports) {
|
|
3316
3936
|
module.exports = {
|
|
3317
3937
|
"name": "pict-view",
|
|
3318
3938
|
"version": "1.0.68",
|
|
@@ -3366,7 +3986,7 @@
|
|
|
3366
3986
|
}
|
|
3367
3987
|
};
|
|
3368
3988
|
}, {}],
|
|
3369
|
-
|
|
3989
|
+
15: [function (require, module, exports) {
|
|
3370
3990
|
const libFableServiceBase = require('fable-serviceproviderbase');
|
|
3371
3991
|
const libPackage = require('../package.json');
|
|
3372
3992
|
const defaultPictViewSettings = {
|
|
@@ -4553,10 +5173,10 @@
|
|
|
4553
5173
|
}
|
|
4554
5174
|
module.exports = PictView;
|
|
4555
5175
|
}, {
|
|
4556
|
-
"../package.json":
|
|
5176
|
+
"../package.json": 14,
|
|
4557
5177
|
"fable-serviceproviderbase": 2
|
|
4558
5178
|
}],
|
|
4559
|
-
|
|
5179
|
+
16: [function (require, module, exports) {
|
|
4560
5180
|
// shim for using process in browser
|
|
4561
5181
|
var process = module.exports = {};
|
|
4562
5182
|
|
|
@@ -4733,7 +5353,7 @@
|
|
|
4733
5353
|
return 0;
|
|
4734
5354
|
};
|
|
4735
5355
|
}, {}],
|
|
4736
|
-
|
|
5356
|
+
17: [function (require, module, exports) {
|
|
4737
5357
|
module.exports = {
|
|
4738
5358
|
"Name": "Retold Data Cloner",
|
|
4739
5359
|
"Hash": "DataCloner",
|
|
@@ -4746,7 +5366,7 @@
|
|
|
4746
5366
|
"AutoRenderMainViewportViewAfterInitialize": false
|
|
4747
5367
|
};
|
|
4748
5368
|
}, {}],
|
|
4749
|
-
|
|
5369
|
+
18: [function (require, module, exports) {
|
|
4750
5370
|
const libPictApplication = require('pict-application');
|
|
4751
5371
|
const libProvider = require('./providers/Pict-Provider-DataCloner.js');
|
|
4752
5372
|
const libViewLayout = require('./views/PictView-DataCloner-Layout.js');
|
|
@@ -4758,6 +5378,7 @@
|
|
|
4758
5378
|
const libViewExport = require('./views/PictView-DataCloner-Export.js');
|
|
4759
5379
|
const libViewViewData = require('./views/PictView-DataCloner-ViewData.js');
|
|
4760
5380
|
const libViewHistogram = require('pict-section-histogram');
|
|
5381
|
+
const libViewConnectionForm = require('pict-section-connection-form');
|
|
4761
5382
|
class DataClonerApplication extends libPictApplication {
|
|
4762
5383
|
constructor(pFable, pOptions, pServiceHash) {
|
|
4763
5384
|
super(pFable, pOptions, pServiceHash);
|
|
@@ -4788,9 +5409,31 @@
|
|
|
4788
5409
|
BarColor: '#4a90d9',
|
|
4789
5410
|
Bins: []
|
|
4790
5411
|
}, libViewHistogram);
|
|
5412
|
+
|
|
5413
|
+
// Shared schema-driven connection form. Renders into the slot
|
|
5414
|
+
// the DataCloner-Connection accordion shell exposes; the
|
|
5415
|
+
// provider's bootstrapConnectionSchemas() pumps the schemas in
|
|
5416
|
+
// once the host's /clone/connection/schemas endpoint responds.
|
|
5417
|
+
this.pict.addView('PictSection-ConnectionForm', Object.assign({}, libViewConnectionForm.default_configuration, {
|
|
5418
|
+
ContainerSelector: '#DataCloner-Connection-FormSlot',
|
|
5419
|
+
DefaultDestinationAddress: '#DataCloner-Connection-FormSlot',
|
|
5420
|
+
SchemasAddress: 'AppData.DataCloner.Connection.Schemas',
|
|
5421
|
+
ActiveAddress: 'AppData.DataCloner.Connection.ActiveProvider',
|
|
5422
|
+
FieldIDPrefix: 'datacloner-conn'
|
|
5423
|
+
}), libViewConnectionForm);
|
|
4791
5424
|
}
|
|
4792
5425
|
onAfterInitializeAsync(fCallback) {
|
|
4793
|
-
// Centralized state (replaces global variables)
|
|
5426
|
+
// Centralized state (replaces global variables).
|
|
5427
|
+
//
|
|
5428
|
+
// PersistFields covers the static, non-connection inputs only.
|
|
5429
|
+
// Connection-section fields (provider picker + per-provider
|
|
5430
|
+
// inputs) are schema-driven now: their DOM ids and
|
|
5431
|
+
// localStorage keys are derived at runtime from the host's
|
|
5432
|
+
// /clone/connection/schemas response and persistence is hooked
|
|
5433
|
+
// up by Pict-Provider-DataCloner#bootstrapConnectionSchemas
|
|
5434
|
+
// after the schema-driven Connection view re-renders. See
|
|
5435
|
+
// PictView-DataCloner-Connection.js for the field-id
|
|
5436
|
+
// convention.
|
|
4794
5437
|
this.pict.AppData.DataCloner = {
|
|
4795
5438
|
FetchedTables: [],
|
|
4796
5439
|
DeployedTables: [],
|
|
@@ -4803,44 +5446,64 @@
|
|
|
4803
5446
|
StatusDetailTimer: null,
|
|
4804
5447
|
StatusDetailData: null,
|
|
4805
5448
|
LastLiveStatus: null,
|
|
4806
|
-
PersistFields: ['serverURL', 'authMethod', 'authURI', 'checkURI', 'cookieName', 'cookieValueAddr', 'cookieValueTemplate', 'loginMarker', 'userName', 'password', 'schemaURL', 'pageSize', 'dateTimePrecisionMS', '
|
|
5449
|
+
PersistFields: ['serverURL', 'authMethod', 'authURI', 'checkURI', 'cookieName', 'cookieValueAddr', 'cookieValueTemplate', 'loginMarker', 'userName', 'password', 'schemaURL', 'pageSize', 'dateTimePrecisionMS', 'syncMaxRecords'],
|
|
5450
|
+
// Connection state — populated by bootstrapConnectionSchemas().
|
|
5451
|
+
// Initialized empty here so the Connection view's first
|
|
5452
|
+
// onBeforeRender finds a valid (if empty) shape.
|
|
5453
|
+
Connection: {
|
|
5454
|
+
Schemas: [],
|
|
5455
|
+
ActiveProvider: '',
|
|
5456
|
+
ProviderOptions: [],
|
|
5457
|
+
ProviderForms: [],
|
|
5458
|
+
NoSchemasSlot: [{}],
|
|
5459
|
+
PreviewText: 'Loading providers…'
|
|
5460
|
+
}
|
|
4807
5461
|
};
|
|
4808
5462
|
|
|
4809
5463
|
// Make pict available for inline onclick handlers
|
|
4810
5464
|
window.pict = this.pict;
|
|
4811
5465
|
|
|
4812
|
-
// Render layout (which chains child view renders via onAfterRender)
|
|
5466
|
+
// Render layout (which chains child view renders via onAfterRender).
|
|
5467
|
+
// The Connection view renders an empty shell here — the schemas
|
|
5468
|
+
// arrive asynchronously and trigger a re-render once they land.
|
|
4813
5469
|
this.pict.views['DataCloner-Layout'].render();
|
|
4814
5470
|
|
|
4815
|
-
// Post-render initialization
|
|
5471
|
+
// Post-render initialization for the static (non-connection) UI.
|
|
4816
5472
|
this.pict.providers.DataCloner.initPersistence();
|
|
4817
|
-
this.pict.views['DataCloner-Connection'].onProviderChange();
|
|
4818
5473
|
this.pict.providers.DataCloner.restoreDeployedTables();
|
|
4819
5474
|
this.pict.providers.DataCloner.startLiveStatusPolling();
|
|
4820
5475
|
this.pict.providers.DataCloner.initAccordionPreviews();
|
|
4821
5476
|
this.pict.providers.DataCloner.updateAllPreviews();
|
|
4822
5477
|
this.pict.views['DataCloner-Layout'].collapseAllSections();
|
|
4823
5478
|
this.pict.providers.DataCloner.initAutoProcess();
|
|
5479
|
+
|
|
5480
|
+
// Async: fetch the host's connection-form schemas and re-render
|
|
5481
|
+
// the Connection section. bootstrapConnectionSchemas restores
|
|
5482
|
+
// localStorage values + hooks save listeners once the new DOM
|
|
5483
|
+
// is in place, then invokes onProviderChange() to surface the
|
|
5484
|
+
// active provider's form.
|
|
5485
|
+
this.pict.providers.DataCloner.bootstrapConnectionSchemas(function () {/* fire-and-forget */});
|
|
4824
5486
|
return fCallback();
|
|
4825
5487
|
}
|
|
4826
5488
|
}
|
|
4827
5489
|
module.exports = DataClonerApplication;
|
|
4828
5490
|
module.exports.default_configuration = require('./Pict-Application-DataCloner-Configuration.json');
|
|
4829
5491
|
}, {
|
|
4830
|
-
"./Pict-Application-DataCloner-Configuration.json":
|
|
4831
|
-
"./providers/Pict-Provider-DataCloner.js":
|
|
4832
|
-
"./views/PictView-DataCloner-Connection.js":
|
|
4833
|
-
"./views/PictView-DataCloner-Deploy.js":
|
|
4834
|
-
"./views/PictView-DataCloner-Export.js":
|
|
4835
|
-
"./views/PictView-DataCloner-Layout.js":
|
|
4836
|
-
"./views/PictView-DataCloner-Schema.js":
|
|
4837
|
-
"./views/PictView-DataCloner-Session.js":
|
|
4838
|
-
"./views/PictView-DataCloner-Sync.js":
|
|
4839
|
-
"./views/PictView-DataCloner-ViewData.js":
|
|
5492
|
+
"./Pict-Application-DataCloner-Configuration.json": 17,
|
|
5493
|
+
"./providers/Pict-Provider-DataCloner.js": 20,
|
|
5494
|
+
"./views/PictView-DataCloner-Connection.js": 21,
|
|
5495
|
+
"./views/PictView-DataCloner-Deploy.js": 22,
|
|
5496
|
+
"./views/PictView-DataCloner-Export.js": 23,
|
|
5497
|
+
"./views/PictView-DataCloner-Layout.js": 24,
|
|
5498
|
+
"./views/PictView-DataCloner-Schema.js": 25,
|
|
5499
|
+
"./views/PictView-DataCloner-Session.js": 26,
|
|
5500
|
+
"./views/PictView-DataCloner-Sync.js": 27,
|
|
5501
|
+
"./views/PictView-DataCloner-ViewData.js": 28,
|
|
4840
5502
|
"pict-application": 4,
|
|
4841
|
-
"pict-section-
|
|
5503
|
+
"pict-section-connection-form": 8,
|
|
5504
|
+
"pict-section-histogram": 10
|
|
4842
5505
|
}],
|
|
4843
|
-
|
|
5506
|
+
19: [function (require, module, exports) {
|
|
4844
5507
|
module.exports = {
|
|
4845
5508
|
DataClonerApplication: require('./Pict-Application-DataCloner.js')
|
|
4846
5509
|
};
|
|
@@ -4848,9 +5511,9 @@
|
|
|
4848
5511
|
window.DataClonerApplication = module.exports.DataClonerApplication;
|
|
4849
5512
|
}
|
|
4850
5513
|
}, {
|
|
4851
|
-
"./Pict-Application-DataCloner.js":
|
|
5514
|
+
"./Pict-Application-DataCloner.js": 18
|
|
4852
5515
|
}],
|
|
4853
|
-
|
|
5516
|
+
20: [function (require, module, exports) {
|
|
4854
5517
|
const libPictProvider = require('pict-provider');
|
|
4855
5518
|
class DataClonerProvider extends libPictProvider {
|
|
4856
5519
|
constructor(pFable, pOptions, pServiceHash) {
|
|
@@ -4914,45 +5577,24 @@
|
|
|
4914
5577
|
// ================================================================
|
|
4915
5578
|
|
|
4916
5579
|
updateAllPreviews() {
|
|
4917
|
-
// Section 1 — Database Connection
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
}
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
} else if (tmpProvider === 'PostgreSQL') {
|
|
4936
|
-
let tmpHost = document.getElementById('postgresqlHost').value || '127.0.0.1';
|
|
4937
|
-
let tmpPort = document.getElementById('postgresqlPort').value || '5432';
|
|
4938
|
-
let tmpUser = document.getElementById('postgresqlUser').value || 'postgres';
|
|
4939
|
-
tmpPreview1 = 'PostgreSQL on ' + tmpHost + ':' + tmpPort + ' as ' + tmpUser;
|
|
4940
|
-
} else if (tmpProvider === 'MongoDB') {
|
|
4941
|
-
let tmpHost = document.getElementById('mongodbHost').value || '127.0.0.1';
|
|
4942
|
-
let tmpPort = document.getElementById('mongodbPort').value || '27017';
|
|
4943
|
-
tmpPreview1 = 'MongoDB on ' + tmpHost + ':' + tmpPort;
|
|
4944
|
-
} else if (tmpProvider === 'Solr') {
|
|
4945
|
-
let tmpHost = document.getElementById('solrHost').value || '127.0.0.1';
|
|
4946
|
-
let tmpPort = document.getElementById('solrPort').value || '8983';
|
|
4947
|
-
tmpPreview1 = 'Solr on ' + tmpHost + ':' + tmpPort;
|
|
4948
|
-
} else if (tmpProvider === 'RocksDB') {
|
|
4949
|
-
let tmpFolder = document.getElementById('rocksdbFolder').value || '~/headlight-liveconnect-local/rocksdb';
|
|
4950
|
-
tmpPreview1 = 'RocksDB at ' + tmpFolder;
|
|
4951
|
-
} else if (tmpProvider === 'Bibliograph') {
|
|
4952
|
-
let tmpFolder = document.getElementById('bibliographFolder').value || '~/headlight-liveconnect-local/bibliograph';
|
|
4953
|
-
tmpPreview1 = 'Bibliograph at ' + tmpFolder;
|
|
4954
|
-
}
|
|
4955
|
-
document.getElementById('preview1').textContent = tmpPreview1;
|
|
5580
|
+
// Section 1 — Database Connection (schema-driven; the
|
|
5581
|
+
// Connection view owns the heuristic that turns the active
|
|
5582
|
+
// schema's field values into preview text). The view's
|
|
5583
|
+
// _buildPreviewText reads live DOM values for the active
|
|
5584
|
+
// provider and falls back to schema Defaults if a field's
|
|
5585
|
+
// element doesn't exist yet.
|
|
5586
|
+
let tmpConnView = this.pict.views['DataCloner-Connection'];
|
|
5587
|
+
let tmpConnState = this.pict.AppData.DataCloner && this.pict.AppData.DataCloner.Connection || null;
|
|
5588
|
+
let tmpPreview1Text;
|
|
5589
|
+
if (tmpConnView && tmpConnState && (tmpConnState.Schemas || []).length > 0) {
|
|
5590
|
+
tmpPreview1Text = tmpConnView._buildPreviewText(tmpConnState);
|
|
5591
|
+
} else {
|
|
5592
|
+
tmpPreview1Text = tmpConnState && tmpConnState.PreviewText || 'Loading providers…';
|
|
5593
|
+
}
|
|
5594
|
+
let tmpPreview1El = document.getElementById('preview1');
|
|
5595
|
+
if (tmpPreview1El) {
|
|
5596
|
+
tmpPreview1El.textContent = tmpPreview1Text;
|
|
5597
|
+
}
|
|
4956
5598
|
|
|
4957
5599
|
// Section 2 — Remote Session
|
|
4958
5600
|
let tmpServerURL = document.getElementById('serverURL').value;
|
|
@@ -5014,7 +5656,12 @@
|
|
|
5014
5656
|
}
|
|
5015
5657
|
initAccordionPreviews() {
|
|
5016
5658
|
let tmpSelf = this;
|
|
5017
|
-
|
|
5659
|
+
|
|
5660
|
+
// Static (non-connection) fields that drive accordion previews.
|
|
5661
|
+
// Connection-section fields hook updateAllPreviews via
|
|
5662
|
+
// _persistConnectionFields() once schemas load — see
|
|
5663
|
+
// bootstrapConnectionSchemas().
|
|
5664
|
+
let tmpPreviewFields = ['connProvider', 'serverURL', 'userName', 'schemaURL', 'pageSize', 'dateTimePrecisionMS', 'syncMaxRecords', 'viewTable', 'viewLimit'];
|
|
5018
5665
|
let tmpHandler = function () {
|
|
5019
5666
|
tmpSelf.updateAllPreviews();
|
|
5020
5667
|
};
|
|
@@ -5043,7 +5690,17 @@
|
|
|
5043
5690
|
|
|
5044
5691
|
saveField(pFieldId) {
|
|
5045
5692
|
let tmpEl = document.getElementById(pFieldId);
|
|
5046
|
-
if (tmpEl) {
|
|
5693
|
+
if (!tmpEl) {
|
|
5694
|
+
return;
|
|
5695
|
+
}
|
|
5696
|
+
// Checkboxes persist .checked, everything else persists .value.
|
|
5697
|
+
// Older code special-cased a small set of checkbox ids (solrSecure,
|
|
5698
|
+
// mssqlLegacyPagination, etc.); the schema-driven path no longer
|
|
5699
|
+
// needs those — the checkbox handler in bootstrapConnectionSchemas
|
|
5700
|
+
// stores 'true' / 'false' which restore picks up below.
|
|
5701
|
+
if (tmpEl.type === 'checkbox') {
|
|
5702
|
+
localStorage.setItem('dataCloner_' + pFieldId, tmpEl.checked ? 'true' : 'false');
|
|
5703
|
+
} else {
|
|
5047
5704
|
localStorage.setItem('dataCloner_' + pFieldId, tmpEl.value);
|
|
5048
5705
|
}
|
|
5049
5706
|
}
|
|
@@ -5054,33 +5711,33 @@
|
|
|
5054
5711
|
let tmpSaved = localStorage.getItem('dataCloner_' + tmpId);
|
|
5055
5712
|
if (tmpSaved !== null) {
|
|
5056
5713
|
let tmpEl = document.getElementById(tmpId);
|
|
5057
|
-
if (tmpEl)
|
|
5714
|
+
if (tmpEl) {
|
|
5715
|
+
if (tmpEl.type === 'checkbox') {
|
|
5716
|
+
tmpEl.checked = tmpSaved === 'true';
|
|
5717
|
+
} else {
|
|
5718
|
+
tmpEl.value = tmpSaved;
|
|
5719
|
+
}
|
|
5720
|
+
}
|
|
5058
5721
|
}
|
|
5059
5722
|
}
|
|
5060
5723
|
|
|
5061
|
-
// Restore checkbox state
|
|
5724
|
+
// Restore checkbox state for non-connection checkboxes that
|
|
5725
|
+
// aren't in PersistFields (these all live outside the schema-
|
|
5726
|
+
// driven Connection section, so they stay hardcoded).
|
|
5062
5727
|
let tmpSyncDeleted = localStorage.getItem('dataCloner_syncDeletedRecords');
|
|
5063
5728
|
if (tmpSyncDeleted !== null) {
|
|
5064
|
-
document.getElementById('syncDeletedRecords')
|
|
5729
|
+
let tmpEl = document.getElementById('syncDeletedRecords');
|
|
5730
|
+
if (tmpEl) tmpEl.checked = tmpSyncDeleted === 'true';
|
|
5065
5731
|
}
|
|
5066
|
-
// Restore sync mode
|
|
5067
5732
|
let tmpSyncMode = localStorage.getItem('dataCloner_syncMode');
|
|
5068
5733
|
if (tmpSyncMode === 'Ongoing') {
|
|
5069
|
-
document.getElementById('syncModeOngoing')
|
|
5070
|
-
|
|
5071
|
-
let tmpSolrSecure = localStorage.getItem('dataCloner_solrSecure');
|
|
5072
|
-
if (tmpSolrSecure !== null) {
|
|
5073
|
-
document.getElementById('solrSecure').checked = tmpSolrSecure === 'true';
|
|
5734
|
+
let tmpEl = document.getElementById('syncModeOngoing');
|
|
5735
|
+
if (tmpEl) tmpEl.checked = true;
|
|
5074
5736
|
}
|
|
5075
|
-
let tmpMssqlLegacyPagination = localStorage.getItem('dataCloner_mssqlLegacyPagination');
|
|
5076
|
-
if (tmpMssqlLegacyPagination !== null) {
|
|
5077
|
-
let tmpEl = document.getElementById('mssqlLegacyPagination');
|
|
5078
|
-
if (tmpEl) tmpEl.checked = tmpMssqlLegacyPagination === 'true';
|
|
5079
|
-
}
|
|
5080
|
-
// Restore advanced ID pagination checkbox
|
|
5081
5737
|
let tmpAdvancedIDPagination = localStorage.getItem('dataCloner_syncAdvancedIDPagination');
|
|
5082
5738
|
if (tmpAdvancedIDPagination !== null) {
|
|
5083
|
-
document.getElementById('syncAdvancedIDPagination')
|
|
5739
|
+
let tmpEl = document.getElementById('syncAdvancedIDPagination');
|
|
5740
|
+
if (tmpEl) tmpEl.checked = tmpAdvancedIDPagination === 'true';
|
|
5084
5741
|
}
|
|
5085
5742
|
}
|
|
5086
5743
|
initPersistence() {
|
|
@@ -5116,21 +5773,9 @@
|
|
|
5116
5773
|
});
|
|
5117
5774
|
});
|
|
5118
5775
|
|
|
5119
|
-
//
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
tmpSolrSecureEl.addEventListener('change', function () {
|
|
5123
|
-
localStorage.setItem('dataCloner_solrSecure', this.checked);
|
|
5124
|
-
});
|
|
5125
|
-
}
|
|
5126
|
-
|
|
5127
|
-
// Persist MSSQL legacy pagination checkbox
|
|
5128
|
-
let tmpMssqlLegacyPaginationEl = document.getElementById('mssqlLegacyPagination');
|
|
5129
|
-
if (tmpMssqlLegacyPaginationEl) {
|
|
5130
|
-
tmpMssqlLegacyPaginationEl.addEventListener('change', function () {
|
|
5131
|
-
localStorage.setItem('dataCloner_mssqlLegacyPagination', this.checked);
|
|
5132
|
-
});
|
|
5133
|
-
}
|
|
5776
|
+
// (Connection-section checkboxes — solrSecure, mssqlLegacyPagination —
|
|
5777
|
+
// are handled by bootstrapConnectionSchemas() which hooks change
|
|
5778
|
+
// listeners after the schema-driven form renders.)
|
|
5134
5779
|
|
|
5135
5780
|
// Persist advanced ID pagination checkbox
|
|
5136
5781
|
let tmpAdvancedIDPaginationEl = document.getElementById('syncAdvancedIDPagination');
|
|
@@ -5156,6 +5801,135 @@
|
|
|
5156
5801
|
}
|
|
5157
5802
|
}
|
|
5158
5803
|
|
|
5804
|
+
// ================================================================
|
|
5805
|
+
// Connection Schemas Bootstrap
|
|
5806
|
+
//
|
|
5807
|
+
// Fetches the host's aggregated connection-form schemas and re-
|
|
5808
|
+
// renders the Connection view so it shows the real provider list +
|
|
5809
|
+
// per-provider field blocks. Then restores localStorage values
|
|
5810
|
+
// for the new (schema-driven) DOM ids and hooks save listeners.
|
|
5811
|
+
// ================================================================
|
|
5812
|
+
|
|
5813
|
+
bootstrapConnectionSchemas(fCallback) {
|
|
5814
|
+
let tmpSelf = this;
|
|
5815
|
+
let tmpDone = typeof fCallback === 'function' ? fCallback : function () {};
|
|
5816
|
+
this.api('GET', '/clone/connection/schemas').then(function (pData) {
|
|
5817
|
+
let tmpSchemas = pData && Array.isArray(pData.Schemas) ? pData.Schemas : [];
|
|
5818
|
+
tmpSelf._applyConnectionSchemas(tmpSchemas);
|
|
5819
|
+
return tmpDone(null, tmpSchemas);
|
|
5820
|
+
}).catch(function (pError) {
|
|
5821
|
+
if (tmpSelf.fable && tmpSelf.fable.log && tmpSelf.fable.log.error) {
|
|
5822
|
+
tmpSelf.fable.log.error(`DataCloner: failed to fetch connection schemas: ${pError && pError.message}`);
|
|
5823
|
+
}
|
|
5824
|
+
// On failure, leave the empty-schema state in place — the
|
|
5825
|
+
// shared view's "no schemas detected" notice will surface.
|
|
5826
|
+
tmpSelf._applyConnectionSchemas([]);
|
|
5827
|
+
return tmpDone(pError);
|
|
5828
|
+
});
|
|
5829
|
+
}
|
|
5830
|
+
_applyConnectionSchemas(pSchemas) {
|
|
5831
|
+
let tmpAppData = this.pict.AppData.DataCloner;
|
|
5832
|
+
if (!tmpAppData.Connection) {
|
|
5833
|
+
tmpAppData.Connection = {
|
|
5834
|
+
Schemas: [],
|
|
5835
|
+
ActiveProvider: '',
|
|
5836
|
+
PreviewText: ''
|
|
5837
|
+
};
|
|
5838
|
+
}
|
|
5839
|
+
tmpAppData.Connection.Schemas = pSchemas;
|
|
5840
|
+
|
|
5841
|
+
// Pick an initial ActiveProvider — restore from localStorage
|
|
5842
|
+
// if the saved value matches one of the available providers,
|
|
5843
|
+
// otherwise default to the first schema (or stay empty).
|
|
5844
|
+
let tmpAvailable = pSchemas.map(function (pS) {
|
|
5845
|
+
return pS.Provider;
|
|
5846
|
+
});
|
|
5847
|
+
let tmpSavedProvider = localStorage.getItem('dataCloner_activeProvider');
|
|
5848
|
+
if (tmpSavedProvider && tmpAvailable.indexOf(tmpSavedProvider) >= 0) {
|
|
5849
|
+
tmpAppData.Connection.ActiveProvider = tmpSavedProvider;
|
|
5850
|
+
} else if (pSchemas.length > 0) {
|
|
5851
|
+
tmpAppData.Connection.ActiveProvider = pSchemas[0].Provider;
|
|
5852
|
+
}
|
|
5853
|
+
|
|
5854
|
+
// Hand the schemas to the shared view, which renders the form
|
|
5855
|
+
// into #DataCloner-Connection-FormSlot.
|
|
5856
|
+
let tmpForm = this.pict.views['PictSection-ConnectionForm'];
|
|
5857
|
+
if (tmpForm) {
|
|
5858
|
+
let tmpSelf = this;
|
|
5859
|
+
tmpForm.options.OnProviderChange = function (pProvider) {
|
|
5860
|
+
tmpAppData.Connection.ActiveProvider = pProvider;
|
|
5861
|
+
localStorage.setItem('dataCloner_activeProvider', pProvider);
|
|
5862
|
+
// Re-hook persistence on the new active form's inputs
|
|
5863
|
+
// (the shared view re-renders on provider change, so the
|
|
5864
|
+
// previous input listeners are gone).
|
|
5865
|
+
tmpSelf._persistConnectionFields(pSchemas);
|
|
5866
|
+
tmpSelf.updateAllPreviews();
|
|
5867
|
+
};
|
|
5868
|
+
if (tmpAppData.Connection.ActiveProvider) {
|
|
5869
|
+
tmpForm._ActiveProvider = tmpAppData.Connection.ActiveProvider;
|
|
5870
|
+
}
|
|
5871
|
+
tmpForm.setSchemas(pSchemas);
|
|
5872
|
+
}
|
|
5873
|
+
|
|
5874
|
+
// Re-render the DataCloner accordion shell so the preview text
|
|
5875
|
+
// reflects the active provider.
|
|
5876
|
+
let tmpAccordion = this.pict.views['DataCloner-Connection'];
|
|
5877
|
+
if (tmpAccordion) {
|
|
5878
|
+
tmpAccordion.render();
|
|
5879
|
+
}
|
|
5880
|
+
|
|
5881
|
+
// Restore values + hook input listeners on the freshly-rendered
|
|
5882
|
+
// shared-view inputs.
|
|
5883
|
+
this._persistConnectionFields(pSchemas);
|
|
5884
|
+
this.updateAllPreviews();
|
|
5885
|
+
}
|
|
5886
|
+
_persistConnectionFields(pSchemas) {
|
|
5887
|
+
let tmpForm = this.pict.views['PictSection-ConnectionForm'];
|
|
5888
|
+
if (!tmpForm) {
|
|
5889
|
+
return;
|
|
5890
|
+
}
|
|
5891
|
+
let tmpSelf = this;
|
|
5892
|
+
|
|
5893
|
+
// Restore + hook every per-provider field. saveField()
|
|
5894
|
+
// dispatches on element type internally so checkboxes and
|
|
5895
|
+
// text inputs share the same path.
|
|
5896
|
+
(pSchemas || []).forEach(function (pSchema) {
|
|
5897
|
+
(pSchema.Fields || []).forEach(function (pField) {
|
|
5898
|
+
let tmpId = tmpForm.fieldDOMId(pSchema.Provider, pField.Name);
|
|
5899
|
+
let tmpEl = document.getElementById(tmpId);
|
|
5900
|
+
if (!tmpEl) {
|
|
5901
|
+
return;
|
|
5902
|
+
}
|
|
5903
|
+
let tmpSaved = localStorage.getItem('dataCloner_' + tmpId);
|
|
5904
|
+
if (tmpSaved !== null) {
|
|
5905
|
+
if (tmpEl.type === 'checkbox') {
|
|
5906
|
+
tmpEl.checked = tmpSaved === 'true';
|
|
5907
|
+
} else {
|
|
5908
|
+
tmpEl.value = tmpSaved;
|
|
5909
|
+
}
|
|
5910
|
+
}
|
|
5911
|
+
|
|
5912
|
+
// Avoid double-binding when the shared view re-renders
|
|
5913
|
+
// on provider change. We tag the element so subsequent
|
|
5914
|
+
// runs of this method are no-ops.
|
|
5915
|
+
if (tmpEl.dataset && tmpEl.dataset.dataclonerHooked === '1') {
|
|
5916
|
+
return;
|
|
5917
|
+
}
|
|
5918
|
+
if (tmpEl.dataset) {
|
|
5919
|
+
tmpEl.dataset.dataclonerHooked = '1';
|
|
5920
|
+
}
|
|
5921
|
+
tmpEl.addEventListener('input', function () {
|
|
5922
|
+
tmpSelf.saveField(tmpId);
|
|
5923
|
+
tmpSelf.updateAllPreviews();
|
|
5924
|
+
});
|
|
5925
|
+
tmpEl.addEventListener('change', function () {
|
|
5926
|
+
tmpSelf.saveField(tmpId);
|
|
5927
|
+
tmpSelf.updateAllPreviews();
|
|
5928
|
+
});
|
|
5929
|
+
});
|
|
5930
|
+
});
|
|
5931
|
+
}
|
|
5932
|
+
|
|
5159
5933
|
// ================================================================
|
|
5160
5934
|
// Live Status Indicator
|
|
5161
5935
|
// ================================================================
|
|
@@ -5828,103 +6602,204 @@
|
|
|
5828
6602
|
}, {
|
|
5829
6603
|
"pict-provider": 6
|
|
5830
6604
|
}],
|
|
5831
|
-
|
|
6605
|
+
21: [function (require, module, exports) {
|
|
6606
|
+
/**
|
|
6607
|
+
* DataCloner — Database Connection (section 1)
|
|
6608
|
+
*
|
|
6609
|
+
* Thin accordion shell + connect/test wiring around the shared
|
|
6610
|
+
* `pict-section-connection-form` view, which owns the schema-driven
|
|
6611
|
+
* provider <select> + per-provider field rendering. The shared view
|
|
6612
|
+
* is registered separately in Pict-Application-DataCloner.js and
|
|
6613
|
+
* renders into the FormSlot below.
|
|
6614
|
+
*
|
|
6615
|
+
* Flow:
|
|
6616
|
+
* 1. Layout renders, this view paints the accordion shell with an
|
|
6617
|
+
* empty FormSlot + "Loading providers…" preview text.
|
|
6618
|
+
* 2. Pict-Provider-DataCloner#bootstrapConnectionSchemas() fetches
|
|
6619
|
+
* GET /clone/connection/schemas and calls setSchemas() on the
|
|
6620
|
+
* shared view, which renders the per-provider form into FormSlot.
|
|
6621
|
+
* 3. User clicks Connect / Test → this view delegates to the shared
|
|
6622
|
+
* view's getProviderConfig() to assemble the wire-format payload,
|
|
6623
|
+
* then POSTs to /clone/connection/{configure,test}.
|
|
6624
|
+
*
|
|
6625
|
+
* Earlier versions of this view contained the schema rendering inline;
|
|
6626
|
+
* that logic has been lifted into pict-section-connection-form so
|
|
6627
|
+
* retold-databeacon and retold-facto can share it. See:
|
|
6628
|
+
* modules/pict/pict-section-connection-form/source/Pict-Section-ConnectionForm.js
|
|
6629
|
+
*/
|
|
6630
|
+
'use strict';
|
|
6631
|
+
|
|
5832
6632
|
const libPictView = require('pict-view');
|
|
6633
|
+
const _ViewConfiguration = {
|
|
6634
|
+
ViewIdentifier: 'DataCloner-Connection',
|
|
6635
|
+
DefaultRenderable: 'DataCloner-Connection',
|
|
6636
|
+
DefaultDestinationAddress: '#DataCloner-Section-Connection',
|
|
6637
|
+
Templates: [{
|
|
6638
|
+
Hash: 'DataCloner-Connection',
|
|
6639
|
+
Template: /*html*/`
|
|
6640
|
+
<div class="accordion-row">
|
|
6641
|
+
<div class="accordion-number">1</div>
|
|
6642
|
+
<div class="accordion-card" id="section1" data-section="1">
|
|
6643
|
+
<div class="accordion-header" onclick="pict.views['DataCloner-Layout'].toggleSection('section1')">
|
|
6644
|
+
<label class="accordion-auto" onclick="event.stopPropagation()"><input type="checkbox" id="auto1"> <span class="auto-label">auto</span></label>
|
|
6645
|
+
<div class="accordion-title">Database Connection</div>
|
|
6646
|
+
<span class="accordion-phase" id="phase1"></span>
|
|
6647
|
+
<div class="accordion-preview" id="preview1">{~D:AppData.DataCloner.Connection.PreviewText~}</div>
|
|
6648
|
+
<div class="accordion-actions">
|
|
6649
|
+
<span class="accordion-go" onclick="event.stopPropagation(); pict.views['DataCloner-Connection'].connectProvider()">go</span>
|
|
6650
|
+
</div>
|
|
6651
|
+
<div class="accordion-toggle">▼</div>
|
|
6652
|
+
</div>
|
|
6653
|
+
<div class="accordion-body">
|
|
6654
|
+
<p style="font-size:0.9em; color:#666; margin-bottom:10px">Configure the local database where cloned data will be stored. The provider list comes from the host's installed meadow-connection modules.</p>
|
|
6655
|
+
|
|
6656
|
+
<div class="inline-group" style="margin-bottom:10px">
|
|
6657
|
+
<div style="flex:1; display:flex; align-items:flex-end; gap:8px; justify-content:flex-end">
|
|
6658
|
+
<button class="primary" onclick="pict.views['DataCloner-Connection'].connectProvider()">Connect</button>
|
|
6659
|
+
<button class="secondary" onclick="pict.views['DataCloner-Connection'].testConnection()">Test Connection</button>
|
|
6660
|
+
</div>
|
|
6661
|
+
</div>
|
|
6662
|
+
|
|
6663
|
+
<!-- pict-section-connection-form renders here -->
|
|
6664
|
+
<div id="DataCloner-Connection-FormSlot"></div>
|
|
6665
|
+
|
|
6666
|
+
<div id="connectionStatus"></div>
|
|
6667
|
+
</div>
|
|
6668
|
+
</div>
|
|
6669
|
+
</div>`
|
|
6670
|
+
}],
|
|
6671
|
+
Renderables: [{
|
|
6672
|
+
RenderableHash: 'DataCloner-Connection',
|
|
6673
|
+
TemplateHash: 'DataCloner-Connection',
|
|
6674
|
+
DestinationAddress: '#DataCloner-Section-Connection'
|
|
6675
|
+
}]
|
|
6676
|
+
};
|
|
5833
6677
|
class DataClonerConnectionView extends libPictView {
|
|
5834
6678
|
constructor(pFable, pOptions, pServiceHash) {
|
|
5835
6679
|
super(pFable, pOptions, pServiceHash);
|
|
5836
6680
|
}
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
6681
|
+
|
|
6682
|
+
// ====================================================================
|
|
6683
|
+
// Lifecycle
|
|
6684
|
+
// ====================================================================
|
|
6685
|
+
|
|
6686
|
+
onBeforeRender(pRenderable) {
|
|
6687
|
+
// Make sure AppData has the slot the accordion preview reads
|
|
6688
|
+
// from (the Provider's bootstrapConnectionSchemas() will fill in
|
|
6689
|
+
// the live values once schemas arrive).
|
|
6690
|
+
if (!this.pict.AppData.DataCloner) {
|
|
6691
|
+
this.pict.AppData.DataCloner = {};
|
|
6692
|
+
}
|
|
6693
|
+
if (!this.pict.AppData.DataCloner.Connection) {
|
|
6694
|
+
this.pict.AppData.DataCloner.Connection = {
|
|
6695
|
+
Schemas: [],
|
|
6696
|
+
ActiveProvider: '',
|
|
6697
|
+
PreviewText: 'Loading providers…'
|
|
6698
|
+
};
|
|
6699
|
+
}
|
|
6700
|
+
return super.onBeforeRender(pRenderable);
|
|
6701
|
+
}
|
|
6702
|
+
|
|
6703
|
+
// ====================================================================
|
|
6704
|
+
// Helpers used by the provider's preview / persistence layer
|
|
6705
|
+
// ====================================================================
|
|
6706
|
+
|
|
6707
|
+
/**
|
|
6708
|
+
* Build the section 1 accordion preview text. Reads live DOM
|
|
6709
|
+
* values via the shared view if it's mounted, otherwise falls back
|
|
6710
|
+
* to schema defaults.
|
|
6711
|
+
*
|
|
6712
|
+
* @param {{Schemas: object[], ActiveProvider: string}} pState
|
|
6713
|
+
* @returns {string}
|
|
6714
|
+
*/
|
|
6715
|
+
_buildPreviewText(pState) {
|
|
6716
|
+
let tmpActive = pState.ActiveProvider;
|
|
6717
|
+
let tmpSchema = (pState.Schemas || []).find(pS => pS.Provider === tmpActive);
|
|
6718
|
+
if (!tmpSchema) {
|
|
6719
|
+
return tmpActive || '(no provider selected)';
|
|
6720
|
+
}
|
|
6721
|
+
|
|
6722
|
+
// Heuristics:
|
|
6723
|
+
// - file-based providers (single Path field) → "<DisplayName> at <path>"
|
|
6724
|
+
// - host/port/user providers → "<DisplayName> on host:port [as user]"
|
|
6725
|
+
// Host/port/user are matched by canonical schema field names.
|
|
6726
|
+
let tmpFields = tmpSchema.Fields || [];
|
|
6727
|
+
let tmpPath = tmpFields.find(pF => pF.Type === 'Path');
|
|
6728
|
+
if (tmpPath) {
|
|
6729
|
+
let tmpVal = this._readFieldValue(tmpSchema.Provider, tmpPath) || tmpPath.Default || '';
|
|
6730
|
+
return `${tmpSchema.DisplayName} at ${tmpVal}`;
|
|
6731
|
+
}
|
|
6732
|
+
let tmpHostField = tmpFields.find(pF => pF.Name === 'host' || pF.Name === 'server');
|
|
6733
|
+
let tmpPortField = tmpFields.find(pF => pF.Name === 'port');
|
|
6734
|
+
let tmpUserField = tmpFields.find(pF => pF.Name === 'user');
|
|
6735
|
+
if (tmpHostField && tmpPortField) {
|
|
6736
|
+
let tmpHost = this._readFieldValue(tmpSchema.Provider, tmpHostField) || tmpHostField.Default || '';
|
|
6737
|
+
let tmpPort = this._readFieldValue(tmpSchema.Provider, tmpPortField) || tmpPortField.Default || '';
|
|
6738
|
+
let tmpPreview = `${tmpSchema.DisplayName} on ${tmpHost}:${tmpPort}`;
|
|
6739
|
+
if (tmpUserField) {
|
|
6740
|
+
let tmpUser = this._readFieldValue(tmpSchema.Provider, tmpUserField) || tmpUserField.Default || '';
|
|
6741
|
+
if (tmpUser) {
|
|
6742
|
+
tmpPreview += ` as ${tmpUser}`;
|
|
6743
|
+
}
|
|
5844
6744
|
}
|
|
6745
|
+
return tmpPreview;
|
|
5845
6746
|
}
|
|
5846
|
-
|
|
6747
|
+
return tmpSchema.DisplayName;
|
|
5847
6748
|
}
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
if (tmpProvider === 'SQLite') {
|
|
5852
|
-
tmpConfig.SQLiteFilePath = document.getElementById('sqliteFilePath').value.trim() || '~/headlight-liveconnect-local/cloned.sqlite';
|
|
5853
|
-
} else if (tmpProvider === 'MySQL') {
|
|
5854
|
-
tmpConfig.host = document.getElementById('mysqlServer').value.trim() || '127.0.0.1';
|
|
5855
|
-
tmpConfig.port = parseInt(document.getElementById('mysqlPort').value, 10) || 3306;
|
|
5856
|
-
tmpConfig.user = document.getElementById('mysqlUser').value.trim() || 'root';
|
|
5857
|
-
tmpConfig.password = document.getElementById('mysqlPassword').value;
|
|
5858
|
-
tmpConfig.database = document.getElementById('mysqlDatabase').value.trim();
|
|
5859
|
-
tmpConfig.connectionLimit = parseInt(document.getElementById('mysqlConnectionLimit').value, 10) || 20;
|
|
5860
|
-
} else if (tmpProvider === 'MSSQL') {
|
|
5861
|
-
tmpConfig.server = document.getElementById('mssqlServer').value.trim() || '127.0.0.1';
|
|
5862
|
-
tmpConfig.port = parseInt(document.getElementById('mssqlPort').value, 10) || 1433;
|
|
5863
|
-
tmpConfig.user = document.getElementById('mssqlUser').value.trim() || 'sa';
|
|
5864
|
-
tmpConfig.password = document.getElementById('mssqlPassword').value;
|
|
5865
|
-
tmpConfig.database = document.getElementById('mssqlDatabase').value.trim();
|
|
5866
|
-
tmpConfig.connectionLimit = parseInt(document.getElementById('mssqlConnectionLimit').value, 10) || 20;
|
|
5867
|
-
// Use ROW_NUMBER() pagination instead of OFFSET/FETCH for
|
|
5868
|
-
// SQL Server 2008 R2 / 2012 or databases whose compatibility
|
|
5869
|
-
// level is < 110 (the parser rejects OFFSET/FETCH syntax
|
|
5870
|
-
// otherwise).
|
|
5871
|
-
tmpConfig.LegacyPagination = document.getElementById('mssqlLegacyPagination').checked;
|
|
5872
|
-
|
|
5873
|
-
// Reliability tuning — pull from the advanced settings block.
|
|
5874
|
-
// All are optional; the connection provider falls back to
|
|
5875
|
-
// sensible defaults when a value is missing or zero.
|
|
5876
|
-
let tmpReqSec = parseInt(document.getElementById('mssqlRequestTimeoutSec').value, 10);
|
|
5877
|
-
if (tmpReqSec > 0) tmpConfig.RequestTimeoutMs = tmpReqSec * 1000;
|
|
5878
|
-
let tmpConnSec = parseInt(document.getElementById('mssqlConnectionTimeoutSec').value, 10);
|
|
5879
|
-
if (tmpConnSec > 0) tmpConfig.ConnectionTimeoutMs = tmpConnSec * 1000;
|
|
5880
|
-
let tmpConnectAttempts = parseInt(document.getElementById('mssqlConnectMaxAttempts').value, 10);
|
|
5881
|
-
let tmpDDLAttempts = parseInt(document.getElementById('mssqlDDLMaxAttempts').value, 10);
|
|
5882
|
-
let tmpInitialDelaySec = parseInt(document.getElementById('mssqlRetryInitialDelaySec').value, 10);
|
|
5883
|
-
let tmpMaxDelaySec = parseInt(document.getElementById('mssqlRetryMaxDelaySec').value, 10);
|
|
5884
|
-
if (tmpConnectAttempts > 0 || tmpInitialDelaySec > 0 || tmpMaxDelaySec > 0) {
|
|
5885
|
-
tmpConfig.ConnectRetryOptions = {};
|
|
5886
|
-
if (tmpConnectAttempts > 0) tmpConfig.ConnectRetryOptions.MaxAttempts = tmpConnectAttempts;
|
|
5887
|
-
if (tmpInitialDelaySec > 0) tmpConfig.ConnectRetryOptions.InitialDelayMs = tmpInitialDelaySec * 1000;
|
|
5888
|
-
if (tmpMaxDelaySec > 0) tmpConfig.ConnectRetryOptions.MaxDelayMs = tmpMaxDelaySec * 1000;
|
|
5889
|
-
}
|
|
5890
|
-
if (tmpDDLAttempts > 0 || tmpInitialDelaySec > 0 || tmpMaxDelaySec > 0) {
|
|
5891
|
-
tmpConfig.DDLRetryOptions = {};
|
|
5892
|
-
if (tmpDDLAttempts > 0) tmpConfig.DDLRetryOptions.MaxAttempts = tmpDDLAttempts;
|
|
5893
|
-
if (tmpInitialDelaySec > 0) tmpConfig.DDLRetryOptions.InitialDelayMs = tmpInitialDelaySec * 1000;
|
|
5894
|
-
if (tmpMaxDelaySec > 0) tmpConfig.DDLRetryOptions.MaxDelayMs = tmpMaxDelaySec * 1000;
|
|
5895
|
-
}
|
|
5896
|
-
} else if (tmpProvider === 'PostgreSQL') {
|
|
5897
|
-
tmpConfig.host = document.getElementById('postgresqlHost').value.trim() || '127.0.0.1';
|
|
5898
|
-
tmpConfig.port = parseInt(document.getElementById('postgresqlPort').value, 10) || 5432;
|
|
5899
|
-
tmpConfig.user = document.getElementById('postgresqlUser').value.trim() || 'postgres';
|
|
5900
|
-
tmpConfig.password = document.getElementById('postgresqlPassword').value;
|
|
5901
|
-
tmpConfig.database = document.getElementById('postgresqlDatabase').value.trim();
|
|
5902
|
-
tmpConfig.max = parseInt(document.getElementById('postgresqlConnectionLimit').value, 10) || 10;
|
|
5903
|
-
} else if (tmpProvider === 'Solr') {
|
|
5904
|
-
tmpConfig.host = document.getElementById('solrHost').value.trim() || 'localhost';
|
|
5905
|
-
tmpConfig.port = parseInt(document.getElementById('solrPort').value, 10) || 8983;
|
|
5906
|
-
tmpConfig.core = document.getElementById('solrCore').value.trim() || 'default';
|
|
5907
|
-
tmpConfig.path = document.getElementById('solrPath').value.trim() || '/solr';
|
|
5908
|
-
tmpConfig.secure = document.getElementById('solrSecure').checked;
|
|
5909
|
-
} else if (tmpProvider === 'MongoDB') {
|
|
5910
|
-
tmpConfig.host = document.getElementById('mongodbHost').value.trim() || '127.0.0.1';
|
|
5911
|
-
tmpConfig.port = parseInt(document.getElementById('mongodbPort').value, 10) || 27017;
|
|
5912
|
-
tmpConfig.user = document.getElementById('mongodbUser').value.trim();
|
|
5913
|
-
tmpConfig.password = document.getElementById('mongodbPassword').value;
|
|
5914
|
-
tmpConfig.database = document.getElementById('mongodbDatabase').value.trim() || 'test';
|
|
5915
|
-
tmpConfig.maxPoolSize = parseInt(document.getElementById('mongodbConnectionLimit').value, 10) || 10;
|
|
5916
|
-
} else if (tmpProvider === 'RocksDB') {
|
|
5917
|
-
tmpConfig.RocksDBFolder = document.getElementById('rocksdbFolder').value.trim() || 'data/rocksdb';
|
|
5918
|
-
} else if (tmpProvider === 'Bibliograph') {
|
|
5919
|
-
tmpConfig.StorageFolder = document.getElementById('bibliographFolder').value.trim() || 'data/bibliograph';
|
|
6749
|
+
_readFieldValue(pProvider, pField) {
|
|
6750
|
+
if (typeof document === 'undefined') {
|
|
6751
|
+
return '';
|
|
5920
6752
|
}
|
|
6753
|
+
let tmpForm = this.pict.views['PictSection-ConnectionForm'];
|
|
6754
|
+
if (!tmpForm) {
|
|
6755
|
+
return '';
|
|
6756
|
+
}
|
|
6757
|
+
let tmpEl = document.getElementById(tmpForm.fieldDOMId(pProvider, pField.Name));
|
|
6758
|
+
if (!tmpEl) {
|
|
6759
|
+
return '';
|
|
6760
|
+
}
|
|
6761
|
+
if (pField.Type === 'Boolean') {
|
|
6762
|
+
return tmpEl.checked ? 'true' : '';
|
|
6763
|
+
}
|
|
6764
|
+
return tmpEl.value;
|
|
6765
|
+
}
|
|
6766
|
+
|
|
6767
|
+
/**
|
|
6768
|
+
* DOM-id resolver for fields owned by the shared view. Forwarded
|
|
6769
|
+
* to PictSection-ConnectionForm so the provider's persistence
|
|
6770
|
+
* layer (saveField, restoreFields) can compute element ids without
|
|
6771
|
+
* needing to know the prefix.
|
|
6772
|
+
*/
|
|
6773
|
+
fieldDOMId(pProvider, pFieldName) {
|
|
6774
|
+
let tmpForm = this.pict.views['PictSection-ConnectionForm'];
|
|
6775
|
+
if (tmpForm && typeof tmpForm.fieldDOMId === 'function') {
|
|
6776
|
+
return tmpForm.fieldDOMId(pProvider, pFieldName);
|
|
6777
|
+
}
|
|
6778
|
+
// Fallback before the shared view is mounted.
|
|
6779
|
+
let tmpProvider = String(pProvider || '').toLowerCase();
|
|
6780
|
+
let tmpField = String(pFieldName || '').replace(/\./g, '_');
|
|
6781
|
+
return `datacloner-conn-${tmpProvider}-${tmpField}`;
|
|
6782
|
+
}
|
|
6783
|
+
|
|
6784
|
+
// ====================================================================
|
|
6785
|
+
// Connect / Test — delegate field collection to the shared view
|
|
6786
|
+
// ====================================================================
|
|
6787
|
+
|
|
6788
|
+
getProviderConfig() {
|
|
6789
|
+
let tmpForm = this.pict.views['PictSection-ConnectionForm'];
|
|
6790
|
+
if (tmpForm && typeof tmpForm.getProviderConfig === 'function') {
|
|
6791
|
+
return tmpForm.getProviderConfig();
|
|
6792
|
+
}
|
|
6793
|
+
// Shared view not mounted yet (early bootstrap, or schemas
|
|
6794
|
+
// failed to load). Surface a plain empty payload — the
|
|
6795
|
+
// connect/test handlers downstream will report the failure
|
|
6796
|
+
// from the server side.
|
|
5921
6797
|
return {
|
|
5922
|
-
Provider:
|
|
5923
|
-
Config:
|
|
6798
|
+
Provider: '',
|
|
6799
|
+
Config: {}
|
|
5924
6800
|
};
|
|
5925
6801
|
}
|
|
5926
6802
|
connectProvider() {
|
|
5927
|
-
// Guard against re-entrant calls (e.g. rapid auto-connect polling)
|
|
5928
6803
|
if (this._connectInFlight) {
|
|
5929
6804
|
return;
|
|
5930
6805
|
}
|
|
@@ -5967,288 +6842,15 @@
|
|
|
5967
6842
|
this.pict.providers.DataCloner.setStatus('connectionStatus', 'Connected: ' + pData.Provider, 'ok');
|
|
5968
6843
|
this.pict.providers.DataCloner.setSectionPhase(1, 'ok');
|
|
5969
6844
|
}
|
|
5970
|
-
}).catch(() => {
|
|
5971
|
-
/* ignore */
|
|
5972
|
-
});
|
|
6845
|
+
}).catch(() => {/* ignore */});
|
|
5973
6846
|
}
|
|
5974
6847
|
}
|
|
5975
6848
|
module.exports = DataClonerConnectionView;
|
|
5976
|
-
module.exports.default_configuration =
|
|
5977
|
-
ViewIdentifier: 'DataCloner-Connection',
|
|
5978
|
-
DefaultRenderable: 'DataCloner-Connection',
|
|
5979
|
-
DefaultDestinationAddress: '#DataCloner-Section-Connection',
|
|
5980
|
-
Templates: [{
|
|
5981
|
-
Hash: 'DataCloner-Connection',
|
|
5982
|
-
Template: /*html*/`
|
|
5983
|
-
<div class="accordion-row">
|
|
5984
|
-
<div class="accordion-number">1</div>
|
|
5985
|
-
<div class="accordion-card" id="section1" data-section="1">
|
|
5986
|
-
<div class="accordion-header" onclick="pict.views['DataCloner-Layout'].toggleSection('section1')">
|
|
5987
|
-
<label class="accordion-auto" onclick="event.stopPropagation()"><input type="checkbox" id="auto1"> <span class="auto-label">auto</span></label>
|
|
5988
|
-
<div class="accordion-title">Database Connection</div>
|
|
5989
|
-
<span class="accordion-phase" id="phase1"></span>
|
|
5990
|
-
<div class="accordion-preview" id="preview1">SQLite at data/cloned.sqlite</div>
|
|
5991
|
-
<div class="accordion-actions">
|
|
5992
|
-
<span class="accordion-go" onclick="event.stopPropagation(); pict.views['DataCloner-Connection'].connectProvider()">go</span>
|
|
5993
|
-
</div>
|
|
5994
|
-
<div class="accordion-toggle">▼</div>
|
|
5995
|
-
</div>
|
|
5996
|
-
<div class="accordion-body">
|
|
5997
|
-
<p style="font-size:0.9em; color:#666; margin-bottom:10px">Configure the local database where cloned data will be stored. SQLite is connected by default.</p>
|
|
5998
|
-
|
|
5999
|
-
<div class="inline-group">
|
|
6000
|
-
<div style="flex:0 0 200px">
|
|
6001
|
-
<label for="connProvider">Provider</label>
|
|
6002
|
-
<select id="connProvider" onchange="pict.views['DataCloner-Connection'].onProviderChange()">
|
|
6003
|
-
<option value="SQLite" selected>SQLite</option>
|
|
6004
|
-
<option value="MySQL">MySQL</option>
|
|
6005
|
-
<option value="MSSQL">MSSQL</option>
|
|
6006
|
-
<option value="PostgreSQL">PostgreSQL</option>
|
|
6007
|
-
<option value="Solr">Solr</option>
|
|
6008
|
-
<option value="MongoDB">MongoDB</option>
|
|
6009
|
-
<option value="RocksDB">RocksDB</option>
|
|
6010
|
-
<option value="Bibliograph">Bibliograph</option>
|
|
6011
|
-
</select>
|
|
6012
|
-
</div>
|
|
6013
|
-
<div style="flex:1; display:flex; align-items:flex-end; gap:8px">
|
|
6014
|
-
<button class="primary" onclick="pict.views['DataCloner-Connection'].connectProvider()">Connect</button>
|
|
6015
|
-
<button class="secondary" onclick="pict.views['DataCloner-Connection'].testConnection()">Test Connection</button>
|
|
6016
|
-
</div>
|
|
6017
|
-
</div>
|
|
6018
|
-
|
|
6019
|
-
<!-- SQLite Config -->
|
|
6020
|
-
<div id="configSQLite">
|
|
6021
|
-
<label for="sqliteFilePath">SQLite File Path</label>
|
|
6022
|
-
<input type="text" id="sqliteFilePath" placeholder="~/headlight-liveconnect-local/cloned.sqlite" value="~/headlight-liveconnect-local/cloned.sqlite">
|
|
6023
|
-
</div>
|
|
6024
|
-
|
|
6025
|
-
<!-- MySQL Config -->
|
|
6026
|
-
<div id="configMySQL" style="display:none">
|
|
6027
|
-
<div class="inline-group">
|
|
6028
|
-
<div style="flex:2">
|
|
6029
|
-
<label for="mysqlServer">Server</label>
|
|
6030
|
-
<input type="text" id="mysqlServer" placeholder="127.0.0.1" value="127.0.0.1">
|
|
6031
|
-
</div>
|
|
6032
|
-
<div style="flex:1">
|
|
6033
|
-
<label for="mysqlPort">Port</label>
|
|
6034
|
-
<input type="number" id="mysqlPort" placeholder="3306" value="3306">
|
|
6035
|
-
</div>
|
|
6036
|
-
</div>
|
|
6037
|
-
<div class="inline-group">
|
|
6038
|
-
<div>
|
|
6039
|
-
<label for="mysqlUser">User</label>
|
|
6040
|
-
<input type="text" id="mysqlUser" placeholder="root" value="root">
|
|
6041
|
-
</div>
|
|
6042
|
-
<div>
|
|
6043
|
-
<label for="mysqlPassword">Password</label>
|
|
6044
|
-
<input type="password" id="mysqlPassword" placeholder="password">
|
|
6045
|
-
</div>
|
|
6046
|
-
</div>
|
|
6047
|
-
<label for="mysqlDatabase">Database</label>
|
|
6048
|
-
<input type="text" id="mysqlDatabase" placeholder="meadow_clone">
|
|
6049
|
-
<div class="inline-group">
|
|
6050
|
-
<div>
|
|
6051
|
-
<label for="mysqlConnectionLimit">Connection Limit</label>
|
|
6052
|
-
<input type="number" id="mysqlConnectionLimit" placeholder="20" value="20">
|
|
6053
|
-
</div>
|
|
6054
|
-
<div></div>
|
|
6055
|
-
</div>
|
|
6056
|
-
</div>
|
|
6057
|
-
|
|
6058
|
-
<!-- MSSQL Config -->
|
|
6059
|
-
<div id="configMSSQL" style="display:none">
|
|
6060
|
-
<div class="inline-group">
|
|
6061
|
-
<div style="flex:2">
|
|
6062
|
-
<label for="mssqlServer">Server</label>
|
|
6063
|
-
<input type="text" id="mssqlServer" placeholder="127.0.0.1" value="127.0.0.1">
|
|
6064
|
-
</div>
|
|
6065
|
-
<div style="flex:1">
|
|
6066
|
-
<label for="mssqlPort">Port</label>
|
|
6067
|
-
<input type="number" id="mssqlPort" placeholder="1433" value="1433">
|
|
6068
|
-
</div>
|
|
6069
|
-
</div>
|
|
6070
|
-
<div class="inline-group">
|
|
6071
|
-
<div>
|
|
6072
|
-
<label for="mssqlUser">User</label>
|
|
6073
|
-
<input type="text" id="mssqlUser" placeholder="sa" value="sa">
|
|
6074
|
-
</div>
|
|
6075
|
-
<div>
|
|
6076
|
-
<label for="mssqlPassword">Password</label>
|
|
6077
|
-
<input type="password" id="mssqlPassword" placeholder="password">
|
|
6078
|
-
</div>
|
|
6079
|
-
</div>
|
|
6080
|
-
<label for="mssqlDatabase">Database</label>
|
|
6081
|
-
<input type="text" id="mssqlDatabase" placeholder="meadow_clone">
|
|
6082
|
-
<div class="inline-group">
|
|
6083
|
-
<div>
|
|
6084
|
-
<label for="mssqlConnectionLimit">Connection Limit</label>
|
|
6085
|
-
<input type="number" id="mssqlConnectionLimit" placeholder="20" value="20">
|
|
6086
|
-
</div>
|
|
6087
|
-
<div></div>
|
|
6088
|
-
</div>
|
|
6089
|
-
<div style="margin-top:8px">
|
|
6090
|
-
<input type="checkbox" id="mssqlLegacyPagination">
|
|
6091
|
-
<label for="mssqlLegacyPagination" title="Enable for SQL Server 2008 R2 / 2012 or databases at compatibility_level < 110. Uses ROW_NUMBER() pagination instead of OFFSET/FETCH.">Legacy pagination (SQL Server < 2012 / compat level < 110)</label>
|
|
6092
|
-
</div>
|
|
6093
|
-
|
|
6094
|
-
<details style="margin-top:8px">
|
|
6095
|
-
<summary style="cursor:pointer; font-weight:600">Reliability & timeouts (advanced)</summary>
|
|
6096
|
-
<p style="margin:8px 0; font-size:0.9em; color:#555">Tune these for slow / flaky customer networks. Connection and DDL operations will retry with exponential backoff, classifying each failure (NetworkError / RequestTimeout / PoolDegraded / ServerError) in the logs so the failure mode is obvious.</p>
|
|
6097
|
-
<div class="inline-group">
|
|
6098
|
-
<div>
|
|
6099
|
-
<label for="mssqlRequestTimeoutSec">Request timeout (sec)</label>
|
|
6100
|
-
<input type="number" id="mssqlRequestTimeoutSec" placeholder="120" value="120">
|
|
6101
|
-
</div>
|
|
6102
|
-
<div>
|
|
6103
|
-
<label for="mssqlConnectionTimeoutSec">Connection timeout (sec)</label>
|
|
6104
|
-
<input type="number" id="mssqlConnectionTimeoutSec" placeholder="60" value="60">
|
|
6105
|
-
</div>
|
|
6106
|
-
</div>
|
|
6107
|
-
<div class="inline-group">
|
|
6108
|
-
<div>
|
|
6109
|
-
<label for="mssqlConnectMaxAttempts">Connect retries (max attempts)</label>
|
|
6110
|
-
<input type="number" id="mssqlConnectMaxAttempts" placeholder="5" value="5" min="1" max="20">
|
|
6111
|
-
</div>
|
|
6112
|
-
<div>
|
|
6113
|
-
<label for="mssqlDDLMaxAttempts">DDL retries (max attempts)</label>
|
|
6114
|
-
<input type="number" id="mssqlDDLMaxAttempts" placeholder="5" value="5" min="1" max="20">
|
|
6115
|
-
</div>
|
|
6116
|
-
</div>
|
|
6117
|
-
<div class="inline-group">
|
|
6118
|
-
<div>
|
|
6119
|
-
<label for="mssqlRetryInitialDelaySec">Retry initial delay (sec)</label>
|
|
6120
|
-
<input type="number" id="mssqlRetryInitialDelaySec" placeholder="3" value="3" min="1" max="60">
|
|
6121
|
-
</div>
|
|
6122
|
-
<div>
|
|
6123
|
-
<label for="mssqlRetryMaxDelaySec">Retry max delay (sec)</label>
|
|
6124
|
-
<input type="number" id="mssqlRetryMaxDelaySec" placeholder="30" value="30" min="1" max="600">
|
|
6125
|
-
</div>
|
|
6126
|
-
</div>
|
|
6127
|
-
</details>
|
|
6128
|
-
</div>
|
|
6129
|
-
|
|
6130
|
-
<!-- PostgreSQL Config -->
|
|
6131
|
-
<div id="configPostgreSQL" style="display:none">
|
|
6132
|
-
<div class="inline-group">
|
|
6133
|
-
<div style="flex:2">
|
|
6134
|
-
<label for="postgresqlHost">Host</label>
|
|
6135
|
-
<input type="text" id="postgresqlHost" placeholder="127.0.0.1" value="127.0.0.1">
|
|
6136
|
-
</div>
|
|
6137
|
-
<div style="flex:1">
|
|
6138
|
-
<label for="postgresqlPort">Port</label>
|
|
6139
|
-
<input type="number" id="postgresqlPort" placeholder="5432" value="5432">
|
|
6140
|
-
</div>
|
|
6141
|
-
</div>
|
|
6142
|
-
<div class="inline-group">
|
|
6143
|
-
<div>
|
|
6144
|
-
<label for="postgresqlUser">User</label>
|
|
6145
|
-
<input type="text" id="postgresqlUser" placeholder="postgres" value="postgres">
|
|
6146
|
-
</div>
|
|
6147
|
-
<div>
|
|
6148
|
-
<label for="postgresqlPassword">Password</label>
|
|
6149
|
-
<input type="password" id="postgresqlPassword" placeholder="password">
|
|
6150
|
-
</div>
|
|
6151
|
-
</div>
|
|
6152
|
-
<label for="postgresqlDatabase">Database</label>
|
|
6153
|
-
<input type="text" id="postgresqlDatabase" placeholder="meadow_clone">
|
|
6154
|
-
<div class="inline-group">
|
|
6155
|
-
<div>
|
|
6156
|
-
<label for="postgresqlConnectionLimit">Connection Pool Limit</label>
|
|
6157
|
-
<input type="number" id="postgresqlConnectionLimit" placeholder="10" value="10">
|
|
6158
|
-
</div>
|
|
6159
|
-
<div></div>
|
|
6160
|
-
</div>
|
|
6161
|
-
</div>
|
|
6162
|
-
|
|
6163
|
-
<!-- Solr Config -->
|
|
6164
|
-
<div id="configSolr" style="display:none">
|
|
6165
|
-
<div class="inline-group">
|
|
6166
|
-
<div style="flex:2">
|
|
6167
|
-
<label for="solrHost">Host</label>
|
|
6168
|
-
<input type="text" id="solrHost" placeholder="localhost" value="localhost">
|
|
6169
|
-
</div>
|
|
6170
|
-
<div style="flex:1">
|
|
6171
|
-
<label for="solrPort">Port</label>
|
|
6172
|
-
<input type="number" id="solrPort" placeholder="8983" value="8983">
|
|
6173
|
-
</div>
|
|
6174
|
-
</div>
|
|
6175
|
-
<div class="inline-group">
|
|
6176
|
-
<div style="flex:2">
|
|
6177
|
-
<label for="solrCore">Core</label>
|
|
6178
|
-
<input type="text" id="solrCore" placeholder="default" value="default">
|
|
6179
|
-
</div>
|
|
6180
|
-
<div style="flex:1">
|
|
6181
|
-
<label for="solrPath">Path</label>
|
|
6182
|
-
<input type="text" id="solrPath" placeholder="/solr" value="/solr">
|
|
6183
|
-
</div>
|
|
6184
|
-
</div>
|
|
6185
|
-
<div class="checkbox-row">
|
|
6186
|
-
<input type="checkbox" id="solrSecure">
|
|
6187
|
-
<label for="solrSecure">Use HTTPS</label>
|
|
6188
|
-
</div>
|
|
6189
|
-
</div>
|
|
6190
|
-
|
|
6191
|
-
<!-- MongoDB Config -->
|
|
6192
|
-
<div id="configMongoDB" style="display:none">
|
|
6193
|
-
<div class="inline-group">
|
|
6194
|
-
<div style="flex:2">
|
|
6195
|
-
<label for="mongodbHost">Host</label>
|
|
6196
|
-
<input type="text" id="mongodbHost" placeholder="127.0.0.1" value="127.0.0.1">
|
|
6197
|
-
</div>
|
|
6198
|
-
<div style="flex:1">
|
|
6199
|
-
<label for="mongodbPort">Port</label>
|
|
6200
|
-
<input type="number" id="mongodbPort" placeholder="27017" value="27017">
|
|
6201
|
-
</div>
|
|
6202
|
-
</div>
|
|
6203
|
-
<div class="inline-group">
|
|
6204
|
-
<div>
|
|
6205
|
-
<label for="mongodbUser">User</label>
|
|
6206
|
-
<input type="text" id="mongodbUser" placeholder="(optional)">
|
|
6207
|
-
</div>
|
|
6208
|
-
<div>
|
|
6209
|
-
<label for="mongodbPassword">Password</label>
|
|
6210
|
-
<input type="password" id="mongodbPassword" placeholder="(optional)">
|
|
6211
|
-
</div>
|
|
6212
|
-
</div>
|
|
6213
|
-
<label for="mongodbDatabase">Database</label>
|
|
6214
|
-
<input type="text" id="mongodbDatabase" placeholder="test" value="test">
|
|
6215
|
-
<div class="inline-group">
|
|
6216
|
-
<div>
|
|
6217
|
-
<label for="mongodbConnectionLimit">Max Pool Size</label>
|
|
6218
|
-
<input type="number" id="mongodbConnectionLimit" placeholder="10" value="10">
|
|
6219
|
-
</div>
|
|
6220
|
-
<div></div>
|
|
6221
|
-
</div>
|
|
6222
|
-
</div>
|
|
6223
|
-
|
|
6224
|
-
<!-- RocksDB Config -->
|
|
6225
|
-
<div id="configRocksDB" style="display:none">
|
|
6226
|
-
<label for="rocksdbFolder">RocksDB Folder Path</label>
|
|
6227
|
-
<input type="text" id="rocksdbFolder" placeholder="data/rocksdb" value="data/rocksdb">
|
|
6228
|
-
</div>
|
|
6229
|
-
|
|
6230
|
-
<!-- Bibliograph Config -->
|
|
6231
|
-
<div id="configBibliograph" style="display:none">
|
|
6232
|
-
<label for="bibliographFolder">Storage Folder Path</label>
|
|
6233
|
-
<input type="text" id="bibliographFolder" placeholder="data/bibliograph" value="data/bibliograph">
|
|
6234
|
-
</div>
|
|
6235
|
-
|
|
6236
|
-
<div id="connectionStatus"></div>
|
|
6237
|
-
</div>
|
|
6238
|
-
</div>
|
|
6239
|
-
</div>
|
|
6240
|
-
`
|
|
6241
|
-
}],
|
|
6242
|
-
Renderables: [{
|
|
6243
|
-
RenderableHash: 'DataCloner-Connection',
|
|
6244
|
-
TemplateHash: 'DataCloner-Connection',
|
|
6245
|
-
DestinationAddress: '#DataCloner-Section-Connection'
|
|
6246
|
-
}]
|
|
6247
|
-
};
|
|
6849
|
+
module.exports.default_configuration = _ViewConfiguration;
|
|
6248
6850
|
}, {
|
|
6249
|
-
"pict-view":
|
|
6851
|
+
"pict-view": 15
|
|
6250
6852
|
}],
|
|
6251
|
-
|
|
6853
|
+
22: [function (require, module, exports) {
|
|
6252
6854
|
const libPictView = require('pict-view');
|
|
6253
6855
|
class DataClonerDeployView extends libPictView {
|
|
6254
6856
|
constructor(pFable, pOptions, pServiceHash) {
|
|
@@ -6409,51 +7011,26 @@
|
|
|
6409
7011
|
}]
|
|
6410
7012
|
};
|
|
6411
7013
|
}, {
|
|
6412
|
-
"pict-view":
|
|
7014
|
+
"pict-view": 15
|
|
6413
7015
|
}],
|
|
6414
|
-
|
|
7016
|
+
23: [function (require, module, exports) {
|
|
6415
7017
|
const libPictView = require('pict-view');
|
|
6416
7018
|
class DataClonerExportView extends libPictView {
|
|
6417
7019
|
constructor(pFable, pOptions, pServiceHash) {
|
|
6418
7020
|
super(pFable, pOptions, pServiceHash);
|
|
6419
7021
|
}
|
|
6420
7022
|
buildConfigObject() {
|
|
6421
|
-
|
|
7023
|
+
// LocalDatabase block — schema-driven via the Connection view's
|
|
7024
|
+
// getProviderConfig(). The wire format produced there matches
|
|
7025
|
+
// what each meadow-connection provider expects (lowercase field
|
|
7026
|
+
// names for SQL drivers, PascalCase for SQLite path, etc.).
|
|
7027
|
+
let tmpConnInfo = this.pict.views['DataCloner-Connection'].getProviderConfig();
|
|
7028
|
+
let tmpProvider = tmpConnInfo.Provider;
|
|
6422
7029
|
let tmpConfig = {};
|
|
6423
|
-
|
|
6424
|
-
// ---- Local Database ----
|
|
6425
7030
|
tmpConfig.LocalDatabase = {
|
|
6426
7031
|
Provider: tmpProvider,
|
|
6427
|
-
Config: {}
|
|
7032
|
+
Config: tmpConnInfo.Config || {}
|
|
6428
7033
|
};
|
|
6429
|
-
let tmpDbConfig = tmpConfig.LocalDatabase.Config;
|
|
6430
|
-
if (tmpProvider === 'SQLite') {
|
|
6431
|
-
tmpDbConfig.SQLiteFilePath = document.getElementById('sqliteFilePath').value.trim() || '~/headlight-liveconnect-local/cloned.sqlite';
|
|
6432
|
-
} else if (tmpProvider === 'MySQL') {
|
|
6433
|
-
tmpDbConfig.host = document.getElementById('mysqlServer').value.trim() || '127.0.0.1';
|
|
6434
|
-
tmpDbConfig.port = parseInt(document.getElementById('mysqlPort').value, 10) || 3306;
|
|
6435
|
-
tmpDbConfig.user = document.getElementById('mysqlUser').value.trim() || 'root';
|
|
6436
|
-
tmpDbConfig.password = document.getElementById('mysqlPassword').value;
|
|
6437
|
-
tmpDbConfig.database = document.getElementById('mysqlDatabase').value.trim();
|
|
6438
|
-
tmpDbConfig.connectionLimit = parseInt(document.getElementById('mysqlConnectionLimit').value, 10) || 20;
|
|
6439
|
-
} else if (tmpProvider === 'MSSQL') {
|
|
6440
|
-
tmpDbConfig.server = document.getElementById('mssqlServer').value.trim() || '127.0.0.1';
|
|
6441
|
-
tmpDbConfig.port = parseInt(document.getElementById('mssqlPort').value, 10) || 1433;
|
|
6442
|
-
tmpDbConfig.user = document.getElementById('mssqlUser').value.trim() || 'sa';
|
|
6443
|
-
tmpDbConfig.password = document.getElementById('mssqlPassword').value;
|
|
6444
|
-
tmpDbConfig.database = document.getElementById('mssqlDatabase').value.trim();
|
|
6445
|
-
tmpDbConfig.connectionLimit = parseInt(document.getElementById('mssqlConnectionLimit').value, 10) || 20;
|
|
6446
|
-
if (document.getElementById('mssqlLegacyPagination').checked) {
|
|
6447
|
-
tmpDbConfig.LegacyPagination = true;
|
|
6448
|
-
}
|
|
6449
|
-
} else if (tmpProvider === 'PostgreSQL') {
|
|
6450
|
-
tmpDbConfig.host = document.getElementById('postgresqlHost').value.trim() || '127.0.0.1';
|
|
6451
|
-
tmpDbConfig.port = parseInt(document.getElementById('postgresqlPort').value, 10) || 5432;
|
|
6452
|
-
tmpDbConfig.user = document.getElementById('postgresqlUser').value.trim() || 'postgres';
|
|
6453
|
-
tmpDbConfig.password = document.getElementById('postgresqlPassword').value;
|
|
6454
|
-
tmpDbConfig.database = document.getElementById('postgresqlDatabase').value.trim();
|
|
6455
|
-
tmpDbConfig.max = parseInt(document.getElementById('postgresqlConnectionLimit').value, 10) || 10;
|
|
6456
|
-
}
|
|
6457
7034
|
|
|
6458
7035
|
// ---- Remote Session ----
|
|
6459
7036
|
tmpConfig.RemoteSession = {};
|
|
@@ -6516,7 +7093,14 @@
|
|
|
6516
7093
|
return tmpConfig;
|
|
6517
7094
|
}
|
|
6518
7095
|
buildMeadowIntegrationConfig() {
|
|
6519
|
-
|
|
7096
|
+
// Pull current connection values via the schema-driven Connection
|
|
7097
|
+
// view. buildConfigObject() above can use the result directly,
|
|
7098
|
+
// but meadow-integration's clone CLI expects a slightly different
|
|
7099
|
+
// destination shape — `server` instead of `host`, `ConnectionPoolLimit`
|
|
7100
|
+
// instead of `connectionLimit` for MSSQL — so we adapt here.
|
|
7101
|
+
let tmpConnInfo = this.pict.views['DataCloner-Connection'].getProviderConfig();
|
|
7102
|
+
let tmpProvider = tmpConnInfo.Provider;
|
|
7103
|
+
let tmpConfigConn = tmpConnInfo.Config || {};
|
|
6520
7104
|
let tmpConfig = {};
|
|
6521
7105
|
|
|
6522
7106
|
// ---- Source ----
|
|
@@ -6533,23 +7117,25 @@
|
|
|
6533
7117
|
tmpConfig.Destination = {};
|
|
6534
7118
|
if (tmpProvider === 'MySQL') {
|
|
6535
7119
|
tmpConfig.Destination.Provider = 'MySQL';
|
|
6536
|
-
tmpConfig.Destination.MySQL = {
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
7120
|
+
tmpConfig.Destination.MySQL = {
|
|
7121
|
+
server: tmpConfigConn.host || '127.0.0.1',
|
|
7122
|
+
port: tmpConfigConn.port || 3306,
|
|
7123
|
+
user: tmpConfigConn.user || 'root',
|
|
7124
|
+
password: tmpConfigConn.password || '',
|
|
7125
|
+
database: tmpConfigConn.database || 'meadow',
|
|
7126
|
+
connectionLimit: tmpConfigConn.connectionLimit || 20
|
|
7127
|
+
};
|
|
6543
7128
|
} else if (tmpProvider === 'MSSQL') {
|
|
6544
7129
|
tmpConfig.Destination.Provider = 'MSSQL';
|
|
6545
|
-
tmpConfig.Destination.MSSQL = {
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
7130
|
+
tmpConfig.Destination.MSSQL = {
|
|
7131
|
+
server: tmpConfigConn.server || '127.0.0.1',
|
|
7132
|
+
port: tmpConfigConn.port || 1433,
|
|
7133
|
+
user: tmpConfigConn.user || 'sa',
|
|
7134
|
+
password: tmpConfigConn.password || '',
|
|
7135
|
+
database: tmpConfigConn.database || 'meadow',
|
|
7136
|
+
ConnectionPoolLimit: tmpConfigConn.connectionLimit || 20
|
|
7137
|
+
};
|
|
7138
|
+
if (tmpConfigConn.LegacyPagination) {
|
|
6553
7139
|
tmpConfig.Destination.MSSQL.LegacyPagination = true;
|
|
6554
7140
|
}
|
|
6555
7141
|
} else {
|
|
@@ -6852,9 +7438,9 @@
|
|
|
6852
7438
|
}]
|
|
6853
7439
|
};
|
|
6854
7440
|
}, {
|
|
6855
|
-
"pict-view":
|
|
7441
|
+
"pict-view": 15
|
|
6856
7442
|
}],
|
|
6857
|
-
|
|
7443
|
+
24: [function (require, module, exports) {
|
|
6858
7444
|
const libPictView = require('pict-view');
|
|
6859
7445
|
class DataClonerLayoutView extends libPictView {
|
|
6860
7446
|
constructor(pFable, pOptions, pServiceHash) {
|
|
@@ -7256,9 +7842,9 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
|
|
|
7256
7842
|
}]
|
|
7257
7843
|
};
|
|
7258
7844
|
}, {
|
|
7259
|
-
"pict-view":
|
|
7845
|
+
"pict-view": 15
|
|
7260
7846
|
}],
|
|
7261
|
-
|
|
7847
|
+
25: [function (require, module, exports) {
|
|
7262
7848
|
const libPictView = require('pict-view');
|
|
7263
7849
|
class DataClonerSchemaView extends libPictView {
|
|
7264
7850
|
constructor(pFable, pOptions, pServiceHash) {
|
|
@@ -7444,9 +8030,9 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
|
|
|
7444
8030
|
}]
|
|
7445
8031
|
};
|
|
7446
8032
|
}, {
|
|
7447
|
-
"pict-view":
|
|
8033
|
+
"pict-view": 15
|
|
7448
8034
|
}],
|
|
7449
|
-
|
|
8035
|
+
26: [function (require, module, exports) {
|
|
7450
8036
|
const libPictView = require('pict-view');
|
|
7451
8037
|
class DataClonerSessionView extends libPictView {
|
|
7452
8038
|
constructor(pFable, pOptions, pServiceHash) {
|
|
@@ -7639,9 +8225,9 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
|
|
|
7639
8225
|
}]
|
|
7640
8226
|
};
|
|
7641
8227
|
}, {
|
|
7642
|
-
"pict-view":
|
|
8228
|
+
"pict-view": 15
|
|
7643
8229
|
}],
|
|
7644
|
-
|
|
8230
|
+
27: [function (require, module, exports) {
|
|
7645
8231
|
const libPictView = require('pict-view');
|
|
7646
8232
|
class DataClonerSyncView extends libPictView {
|
|
7647
8233
|
constructor(pFable, pOptions, pServiceHash) {
|
|
@@ -8175,9 +8761,9 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
|
|
|
8175
8761
|
}]
|
|
8176
8762
|
};
|
|
8177
8763
|
}, {
|
|
8178
|
-
"pict-view":
|
|
8764
|
+
"pict-view": 15
|
|
8179
8765
|
}],
|
|
8180
|
-
|
|
8766
|
+
28: [function (require, module, exports) {
|
|
8181
8767
|
const libPictView = require('pict-view');
|
|
8182
8768
|
class DataClonerViewDataView extends libPictView {
|
|
8183
8769
|
constructor(pFable, pOptions, pServiceHash) {
|
|
@@ -8312,8 +8898,8 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
|
|
|
8312
8898
|
}]
|
|
8313
8899
|
};
|
|
8314
8900
|
}, {
|
|
8315
|
-
"pict-view":
|
|
8901
|
+
"pict-view": 15
|
|
8316
8902
|
}]
|
|
8317
|
-
}, {}, [
|
|
8903
|
+
}, {}, [19])(19);
|
|
8318
8904
|
});
|
|
8319
8905
|
//# sourceMappingURL=data-cloner.js.map
|