source: SRUAggregator/trunk/src/main/resources/assets/js/main.jsx @ 7228

Last change on this file since 7228 was 7228, checked in by Leif-Jöran, 6 years ago

Some further proofing in main.jsx.

File size: 8.2 KB
RevLine 
[7148]1import AboutPage from "./pages/aboutpage.jsx";
2import AggregatorPage from "./pages/aggregatorpage.jsx";
3import HelpPage from "./pages/helppage.jsx";
4import StatisticsPage from "./pages/statisticspage.jsx";
5import ErrorPane from "./components/errorpane.jsx";
6import Footer from "./components/footer.jsx";
7import EmbeddedFooter from "./components/embeddedfooter.jsx";
8import PropTypes from "prop-types";
9import createReactClass from "create-react-class";
10
[5897]11(function() {
12"use strict";
[5720]13
[7148]14window.MyAggregator = window.MyAggregator || {};
[6144]15
[7223]16var VERSION = window.MyAggregator.VERSION = "v.3.0.0-64";
[7148]17
[6144]18var URLROOT = window.MyAggregator.URLROOT =
[7223]19        window.location.pathname.substring(0, window.location.pathname.indexOf("/", 2)) ||
20        //window.location.pathname ||
[7228]21        //"/ws/fcs/2.0/aggregator";
[6129]22        "/Aggregator";
[5971]23
[7228]24
[7148]25var PT = PropTypes;
[5758]26
[6172]27/**
28The FCS Aggregator UI is based on reactjs.
29- index.html: describes the general page structure, with a push-down footer;
30  on that structure the Main and Footer components are plugged.
[7148]31- main.jsx: composes the simple top components (Main, AggregatorPage, HelpPage,
32  AboutPage, StatisticsPage) in pages/
33- pages/aggregatorpage.jsx: defines
[6172]34        - the Corpora store of collections
35        - the AggregatorPage component which deals with search and displays the search results
[7148]36- components/corpusview.jsx: defines the CorpusView, rendered when the user views the available collections
37- plus in components/: various general usage React components
[6172]38
39The top-most component, Main, tracks of the window's location URL and, depending on the value,
40  renders various components inside its frame:
41        - AggregatorPage is the view corresponding to the normal search UI (search bar and all)
42          This is the most complex component.
43        - HelpPage renders the help page
[7148]44        - AboutPage renders the about page
45        - StatisticsPage renders the stats page
[6172]46        - another URL, /Aggregator/embed, determines Main and AggregatorPage to render just the search bar.
47          The embedded view is supposed to work like a YouTube embedded clip.
48*/
49
[7148]50var Main = createReactClass({
51// fixme! - class Main extends React.Component {
[5976]52        componentWillMount: function() {
[6123]53                routeFromLocation.bind(this)();
[5976]54        },
55
[5720]56        getInitialState: function () {
57                return {
[5890]58                        navbarCollapse: false,
59                        navbarPageFn: this.renderAggregator,
60                        errorMessages: [],
[5720]61                };
62        },
63
[5890]64        error: function(errObj) {
65                var err = "";
66                if (typeof errObj === 'string' || errObj instanceof String) {
67                        err = errObj;
68                } else if (typeof errObj === 'object' && errObj.statusText) {
69                        console.log("ERROR: jqXHR = ", errObj);
70                        err = errObj.statusText;
71                } else {
72                        return;
73                }
74
[5720]75                var that = this;
[5890]76                var errs = this.state.errorMessages.slice();
77                errs.push(err);
78                this.setState({errorMessages: errs});
79
80                setTimeout(function() {
81                        var errs = that.state.errorMessages.slice();
82                        errs.shift();
83                        that.setState({errorMessages: errs});
[5897]84                }, 10000);
[5890]85        },
[6144]86
[5890]87        ajax: function(ajaxObject) {
88                var that = this;
89                if (!ajaxObject.error) {
90                        ajaxObject.error = function(jqXHR, textStatus, error) {
91                                if (jqXHR.readyState === 0) {
92                                        that.error("Network error, please check your internet connection");
[5897]93                                } else if (jqXHR.responseText) {
94                                        that.error(jqXHR.responseText + " ("+error+")");
95                                } else  {
[5890]96                                        that.error(error + " ("+textStatus+")");
97                                }
98                                console.log("ajax error, jqXHR: ", jqXHR);
99                        };
100                }
[5957]101                // console.log("ajax", ajaxObject);
[5890]102                jQuery.ajax(ajaxObject);
103        },
104
[5976]105        toggleCollapse: function() {
106                this.setState({navbarCollapse: !this.state.navbarCollapse});
107        },
108
[5890]109        renderAggregator: function() {
[7053]110                return <AggregatorPage ajax={this.ajax} error={this.error} embedded={false}/>;
[5890]111        },
112
[5959]113        renderHelp: function() {
114                return <HelpPage />;
115        },
116
117        renderAbout: function() {
[7148]118                return <AboutPage toStatistics={this.toStatistics} />;
[5959]119        },
120
[5890]121        renderStatistics: function() {
122                return <StatisticsPage ajax={this.ajax} />;
123        },
124
[6111]125        renderEmbedded: function() {
[6197]126                return <AggregatorPage ajax={this.ajax} error={this.error} embedded={true}/>;
[6111]127        },
128
[6144]129        getPageFns: function() {
[5976]130                return {
131                        '': this.renderAggregator,
132                        'help': this.renderHelp,
133                        'about': this.renderAbout,
134                        'stats': this.renderStatistics,
[6111]135                        'embed': this.renderEmbedded,
[5976]136                };
[5890]137        },
138
[5976]139        gotoPage: function(doPushHistory, pageFnName) {
140                var pageFn = this.getPageFns()[pageFnName];
141                if (this.state.navbarPageFn !== pageFn) {
142                        if (doPushHistory) {
143                                window.history.pushState({page:pageFnName}, '', URLROOT+"/"+pageFnName);
144                        }
145                        this.setState({navbarPageFn: pageFn});
[7148]146                        console.log("new page: " + document.location + ", name: " + pageFnName);
[5976]147                }
[5959]148        },
149
[5976]150        toAggregator: function(doPushHistory) { this.gotoPage(doPushHistory, ''); },
151        toHelp: function(doPushHistory) { this.gotoPage(doPushHistory, 'help'); },
152        toAbout: function(doPushHistory) { this.gotoPage(doPushHistory, 'about'); },
153        toStatistics: function(doPushHistory) { this.gotoPage(doPushHistory, 'stats'); },
[6111]154        toEmbedded: function(doPushHistory) { this.gotoPage(doPushHistory, 'embed'); },
[5959]155
[6132]156        renderLogin: function() {
157                return false;
158                // return  <li className="unauthenticated">
159                //                      <a href="login" tabIndex="-1"><span className="glyphicon glyphicon-log-in"></span> LOGIN</a>
160                //              </li>;
161        },
162
[5890]163        renderCollapsible: function() {
164                var classname = "navbar-collapse collapse " + (this.state.navbarCollapse?"in":"");
165                return (
166                        <div className={classname}>
167                                <ul className="nav navbar-nav">
168                                        <li className={this.state.navbarPageFn === this.renderAggregator ? "active":""}>
[5976]169                                                <a className="link" tabIndex="-1" onClick={this.toAggregator.bind(this, true)}>Aggregator</a>
[5890]170                                        </li>
171                                        <li className={this.state.navbarPageFn === this.renderHelp ? "active":""}>
[5976]172                                                <a className="link" tabIndex="-1" onClick={this.toHelp.bind(this, true)}>Help</a>
[5890]173                                        </li>
174                                </ul>
[6171]175                                <ul className="nav navbar-nav navbar-right">
[6180]176                                        <li> <div id="clarinservices" style={{padding:4}}/> </li>
[6144]177                                        {this.renderLogin()}
[5890]178                                </ul>
179                        </div>
180                );
181        },
182
[6111]183        renderTop: function() {
184                if (this.state.navbarPageFn === this.renderEmbedded) {
185                        return false;
186                }
[5890]187                return  (
188                        <div>
189                                <div className="navbar navbar-default navbar-static-top" role="navigation">
190                                        <div className="container">
191                                                <div className="navbar-header">
192                                                        <button type="button" className="navbar-toggle" onClick={this.toggleCollapse}>
193                                                                <span className="sr-only">Toggle navigation</span>
194                                                                <span className="icon-bar"></span>
195                                                                <span className="icon-bar"></span>
196                                                                <span className="icon-bar"></span>
197                                                        </button>
[7228]198                                                        <a className="navbar-brand" href={URLROOT + "/"} tabIndex="-1">
[6172]199                                                                <img width="28px" height="28px" src="img/magglass1.png"/>
[7228]200                                                                <header className="inline"> Federated Content Search </header>
[6171]201                                                        </a>
[5890]202                                                </div>
203                                                {this.renderCollapsible()}
204                                        </div>
205                                </div>
206
207                                <ErrorPane errorMessages={this.state.errorMessages} />
[6171]208
[6111]209                        </div>
210                );
211        },
[5890]212
[6111]213        render: function() {
214                return  (
215                        <div>
216                                <div> { this.renderTop() } </div>
217
[5890]218                                <div id="push">
219                                        <div className="container">
220                                                {this.state.navbarPageFn()}
221                                        </div>
222                                        <div className="top-gap" />
223                                </div>
224                        </div>
225                );
226        }
227});
228
[7148]229// StatisticsPage
[5890]230
[7148]231// HelpPage
[5890]232
[7148]233// AboutPage
[5894]234
[7148]235// Footer
[5894]236
[7148]237// EmbeddedFooter
[5894]238
[6172]239function isEmbeddedView() {
240        var path = window.location.pathname.split('/');
[7054]241        return (path.length >= 3 && path[path.length - 1] === 'embed');
[6172]242}
243
[5976]244function endsWith(str, suffix) {
245    return str.indexOf(suffix, str.length - suffix.length) !== -1;
246}
247
[6043]248var routeFromLocation = function() {
[7148]249        console.log("routeFromLocation: " + document.location);
[6043]250        if (!this) throw "routeFromLocation must be bound to main";
[5976]251        var path = window.location.pathname.split('/');
[7148]252        console.log("path: " + path);
[7054]253        if (path.length >= 3) {
254                var p = path[path.length - 1];
[5976]255                if (p === 'help') {
[6043]256                        this.toHelp(false);
[5976]257                } else if (p === 'about') {
[6043]258                        this.toAbout(false);
[5976]259                } else if (p === 'stats') {
[6043]260                        this.toStatistics(false);
[6111]261                } else if (p === 'embed') {
262                        this.toEmbedded(false);
[5976]263                } else {
[6043]264                        this.toAggregator(false);
[5976]265                }
266        } else {
[6043]267                this.toAggregator(false);
[5976]268        }
269};
270
[7036]271var main = ReactDOM.render(<Main />,  document.getElementById('body'));
[6172]272if (!isEmbeddedView()) {
[7157]273        ReactDOM.render(<Footer VERSION={VERSION} toAbout={main.toAbout}/>, document.getElementById('footer') );
[6306]274} else {
[7148]275        ReactDOM.render(<EmbeddedFooter URLROOT={URLROOT} />, document.getElementById('footer') );
[6306]276        if (jQuery) { jQuery('body, #footer').addClass('embedded'); }
[6172]277}
[5957]278
[6043]279window.onpopstate = routeFromLocation.bind(main);
[5976]280
[5897]281})();
Note: See TracBrowser for help on using the repository browser.