Fix errors and warnings 17/59817/1
authorMalek <malek.zoabi@amdocs.com>
Thu, 9 Aug 2018 09:07:58 +0000 (12:07 +0300)
committerMalek <malek.zoabi@amdocs.com>
Thu, 9 Aug 2018 09:08:27 +0000 (12:08 +0300)
Issue-ID: SDC-1622
Change-Id: I1a284c29ed1332545752bf04c14027d1199bbd4e
Signed-off-by: Malek <malek.zoabi@amdocs.com>
workflow-designer-ui/src/main/frontend/package.json
workflow-designer-ui/src/main/frontend/src/App.js
workflow-designer-ui/src/main/frontend/src/features/catalog/CatalogView.jsx
workflow-designer-ui/src/main/frontend/src/features/version/composition/CompositionView.js
workflow-designer-ui/src/main/frontend/src/features/version/create/__tests__/__snapshots__/CreateVersionView_snapshot-test.js.snap
workflow-designer-ui/src/main/frontend/src/features/version/general/GeneralView.js
workflow-designer-ui/src/main/frontend/src/features/workflow/create/__tests__/__snapshots__/CreateWorkflowView_snapshot-test.js.snap
workflow-designer-ui/src/main/frontend/src/index.js
workflow-designer-ui/src/main/frontend/src/shared/components/Description/index.js
workflow-designer-ui/src/main/frontend/src/shared/scroll/InfiniteScroll.js [new file with mode: 0644]
workflow-designer-ui/src/main/frontend/yarn.lock

index f1f3371..e3c657e 100644 (file)
@@ -34,7 +34,6 @@
                "react-datepicker": "^0.48.0",
                "react-dom": "^16.3.2",
                "react-hot-loader": "^4.3.3",
-               "react-infinite-scroller": "^1.2.0",
                "react-redux": "^5.0.6",
                "react-redux-i18n": "^1.9.2",
                "react-router": "^4.3.1",
index 4b42f6f..3d9f302 100644 (file)
@@ -5,9 +5,9 @@
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
- *      http://www.apache.org/licenses/LICENSE-2.0
+*      http://www.apache.org/licenses/LICENSE-2.0
 *
- * Unless required by applicable law or agreed to in writing, software
+* Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
@@ -17,6 +17,7 @@
 import { hot } from 'react-hot-loader';
 import React, { Component } from 'react';
 import { Route } from 'react-router-dom';
+import qs from 'qs';
 
 import { PluginPubSub } from 'shared/pubsub/plugin-pubsub';
 import 'resources/scss/style.scss';
@@ -36,28 +37,35 @@ class App extends Component {
     constructor(props) {
         super(props);
 
-        this.searchParams = new URLSearchParams(location.search);
+        this.searchParams = qs.parse(location.search, {
+            ignoreQueryPrefix: true
+        });
 
-        if (this.searchParams.get('userId')) {
-            localStorage.setItem(USER_ID, this.searchParams.get('userId'));
+        if (this.searchParams && this.searchParams.userId) {
+            localStorage.setItem(USER_ID, this.searchParams.userId);
         }
     }
 
     componentDidMount() {
-        const eventsClientId = this.searchParams.get('eventsClientId');
-        const parentUrl = this.searchParams.get('parentUrl');
+        if (this.searchParams) {
+            const { eventsClientId, parentUrl } = this.searchParams;
 
-        if (eventsClientId && parentUrl) {
-            const client = new PluginPubSub(eventsClientId, parentUrl);
+            if (eventsClientId && parentUrl) {
+                const client = new PluginPubSub(eventsClientId, parentUrl);
 
-            client.notify('READY');
+                client.notify('READY');
+            }
         }
     }
 
     render() {
-        return routes.map((route, i) => (
-            <RouteWithSubRoutes key={`App.route.${i}`} {...route} />
-        ));
+        return (
+            <div className="workflow-app">
+                {routes.map((route, i) => (
+                    <RouteWithSubRoutes key={`App.route.${i}`} {...route} />
+                ))}
+            </div>
+        );
     }
 }
 
index e833a01..2d8c8d7 100644 (file)
@@ -16,7 +16,7 @@
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import InfiniteScroll from 'react-infinite-scroller';
+import InfiniteScroll from 'shared/scroll/InfiniteScroll';
 import Workflows from 'features/catalog/views/Workflows';
 import AddWorkflow from 'features/catalog/views/AddWorkflow';
 
index d549456..f47a6ec 100644 (file)
@@ -27,7 +27,7 @@ class CompositionView extends Component {
     static propTypes = {
         compositionUpdate: PropTypes.func,
         showErrorModal: PropTypes.func,
-        composition: PropTypes.string,
+        composition: PropTypes.bool,
         name: PropTypes.string
     };
     constructor() {
index 08389c6..55357b5 100644 (file)
@@ -51,7 +51,7 @@ exports[`Create new version snapshot renders correctly 1`] = `
             className="custom-textarea field-section sdc-input__input"
             data-test-id="new-version-description"
             onChange={[Function]}
-            value={undefined}
+            value=""
           />
         </div>
       </div>
index 930c607..d10d578 100644 (file)
@@ -5,9 +5,9 @@
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
- *      http://www.apache.org/licenses/LICENSE-2.0
+*      http://www.apache.org/licenses/LICENSE-2.0
 *
- * Unless required by applicable law or agreed to in writing, software
+* Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 
 import React from 'react';
 import PropTypes from 'prop-types';
-import { I18n, Localize, Translate } from 'react-redux-i18n';
+import { I18n, Translate } from 'react-redux-i18n';
 
 import Description from 'shared/components/Description';
 import { VersionInfo, LabeledValue } from 'shared/components/VersionInfo';
 
-const GeneralView = ({ onDataChange, description, created, modified }) => (
-    <div className="general-page">
-        <div className="general-page-title">
-            <Translate value="workflow.general.headerTitle" />
-        </div>
-        <div className="general-page-content">
-            <Description
-                description={description}
-                onDataChange={onDataChange}
-            />
-            <VersionInfo>
-                <LabeledValue
-                    title={I18n.t('workflow.general.modified')}
-                    value={
-                        <Localize value={modified} dateFormat="date.short" />
-                    }
-                />
-                <LabeledValue
-                    title={I18n.t('workflow.general.created')}
-                    value={<Localize value={created} dateFormat="date.short" />}
+const GeneralView = ({ onDataChange, description, created, modified }) => {
+    const modifiedValue = I18n.l(modified, { dateFormat: 'date.short' });
+    const createdValue = I18n.l(created, { dateFormat: 'date.short' });
+
+    return (
+        <div className="general-page">
+            <div className="general-page-title">
+                <Translate value="workflow.general.headerTitle" />
+            </div>
+            <div className="general-page-content">
+                <Description
+                    description={description}
+                    onDataChange={onDataChange}
                 />
-            </VersionInfo>
+                <VersionInfo>
+                    <LabeledValue
+                        title={I18n.t('workflow.general.modified')}
+                        value={modifiedValue}
+                    />
+                    <LabeledValue
+                        title={I18n.t('workflow.general.created')}
+                        value={createdValue}
+                    />
+                </VersionInfo>
+            </div>
         </div>
-    </div>
-);
+    );
+};
 
 GeneralView.propTypes = {
     onDataChange: PropTypes.func,
index de14dc3..1a050ef 100644 (file)
@@ -49,7 +49,7 @@ exports[`New Workflow View Snapshot renders correctly 1`] = `
             className="custom-textarea field-section sdc-input__input"
             data-test-id="description"
             onChange={[Function]}
-            value={undefined}
+            value=""
           />
         </div>
       </div>
index d33f47c..46a8760 100644 (file)
@@ -27,18 +27,14 @@ import store from './store';
 
 ReactDOM.render(
     <Provider store={store}>
-        <React.Fragment>
-            <Notifications />
-            <Loader />
-            <BrowserRouter>
-                <React.Fragment>
-                    <div className="workflow-app">
-                        <App />
-                    </div>
-                    <ModalWrapper />
-                </React.Fragment>
-            </BrowserRouter>
-        </React.Fragment>
+        <BrowserRouter>
+            <React.Fragment>
+                <App />
+                <Notifications />
+                <ModalWrapper />
+                <Loader />
+            </React.Fragment>
+        </BrowserRouter>
     </Provider>,
     document.getElementById('root')
 );
index 15a8834..4aa48f8 100644 (file)
@@ -4,9 +4,9 @@
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
-* 
+*
 *      http://www.apache.org/licenses/LICENSE-2.0
-* 
+*
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -24,7 +24,7 @@ const Description = ({ description, onDataChange, dataTestId }) => (
                 {I18n.t('workflow.general.description')}
             </div>
             <textarea
-                value={description}
+                value={description || ''}
                 data-test-id={dataTestId || 'description'}
                 onChange={event => {
                     onDataChange({ description: event.target.value });
diff --git a/workflow-designer-ui/src/main/frontend/src/shared/scroll/InfiniteScroll.js b/workflow-designer-ui/src/main/frontend/src/shared/scroll/InfiniteScroll.js
new file mode 100644 (file)
index 0000000..8db3d84
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+* Copyright © 2018 European Support Limited
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import React from 'react';
+import PropTypes from 'prop-types';
+
+class InfiniteScroll extends React.Component {
+    componentDidMount() {
+        this.pageLoaded = this.props.pageStart;
+        this.scrollEl = this.getScrollElement();
+        this.attachScrollListener();
+    }
+
+    componentDidUpdate() {
+        this.attachScrollListener();
+    }
+
+    componentWillUnmount() {
+        this.detachScrollListener();
+    }
+
+    getParentElement(el) {
+        return el.parentNode;
+    }
+
+    getScrollElement() {
+        if (this.props.useWindow) {
+            return window;
+        }
+
+        return this.getParentElement(this.scrollComponent);
+    }
+
+    detachScrollListener() {
+        this.scrollEl.removeEventListener(
+            'scroll',
+            this.scrollListener,
+            this.props.useCapture
+        );
+        window.removeEventListener(
+            'resize',
+            this.scrollListener,
+            this.props.useCapture
+        );
+    }
+
+    attachScrollListener() {
+        if (!this.props.hasMore || !this.scrollEl) {
+            return;
+        }
+
+        const options = {
+            capture: this.props.useCapture,
+            passive: true
+        };
+
+        this.scrollEl.addEventListener('scroll', this.scrollListener, options);
+        window.addEventListener('resize', this.scrollListener, options);
+
+        if (this.props.initialLoad) {
+            this.scrollListener();
+        }
+    }
+
+    scrollListener = () => {
+        const el = this.scrollComponent;
+        const scrollEl = window;
+        const parentNode = this.getParentElement(el);
+
+        let offset;
+        if (this.props.useWindow) {
+            const doc =
+                document.documentElement ||
+                document.body.parentNode ||
+                document.body;
+            const scrollTop =
+                scrollEl.pageYOffset !== undefined
+                    ? scrollEl.pageYOffset
+                    : doc.scrollTop;
+
+            offset =
+                this.calculateTopPosition(el) +
+                (el.offsetHeight - scrollTop - window.innerHeight);
+        } else {
+            offset =
+                el.scrollHeight -
+                parentNode.scrollTop -
+                parentNode.clientHeight;
+        }
+
+        // Here we make sure the element is visible as well as checking the offset
+        if (offset < Number(this.props.threshold) && el.offsetParent !== null) {
+            this.detachScrollListener();
+            // Call loadMore after detachScrollListener to allow for non-async loadMore functions
+            if (typeof this.props.loadMore === 'function') {
+                this.props.loadMore((this.pageLoaded += 1));
+            }
+        }
+    };
+
+    calculateTopPosition(el) {
+        if (!el) {
+            return 0;
+        }
+        return el.offsetTop + this.calculateTopPosition(el.offsetParent);
+    }
+
+    render() {
+        const { children, element } = this.props;
+
+        const props = {
+            ref: node => {
+                this.scrollComponent = node;
+            }
+        };
+
+        const childrenArray = [children];
+
+        return React.createElement(element, props, childrenArray);
+    }
+}
+
+InfiniteScroll.propTypes = {
+    children: PropTypes.node.isRequired,
+    element: PropTypes.node,
+    hasMore: PropTypes.bool,
+    initialLoad: PropTypes.bool,
+    loadMore: PropTypes.func.isRequired,
+    pageStart: PropTypes.number,
+    threshold: PropTypes.number,
+    useCapture: PropTypes.bool,
+    useWindow: PropTypes.bool
+};
+
+InfiniteScroll.defaultProps = {
+    element: 'div',
+    hasMore: false,
+    initialLoad: true,
+    pageStart: 0,
+    threshold: 250,
+    useWindow: true,
+    useCapture: false
+};
+
+export default InfiniteScroll;
index 5a1ac9a..86a6301 100644 (file)
@@ -9479,12 +9479,6 @@ react-icons@^2.2.7:
   dependencies:
     react-icon-base "2.1.0"
 
-react-infinite-scroller@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/react-infinite-scroller/-/react-infinite-scroller-1.2.0.tgz#ea89906c5bc918dce486880b59e88847518aa538"
-  dependencies:
-    prop-types "^15.5.8"
-
 react-input-autosize@^2.1.2:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8"