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
Line 
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
11(function() {
12"use strict";
13
14window.MyAggregator = window.MyAggregator || {};
15
16var VERSION = window.MyAggregator.VERSION = "v.3.0.0-64";
17
18var URLROOT = window.MyAggregator.URLROOT =
19        window.location.pathname.substring(0, window.location.pathname.indexOf("/", 2)) ||
20        //window.location.pathname ||
21        //"/ws/fcs/2.0/aggregator";
22        "/Aggregator";
23
24
25var PT = PropTypes;
26
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.
31- main.jsx: composes the simple top components (Main, AggregatorPage, HelpPage,
32  AboutPage, StatisticsPage) in pages/
33- pages/aggregatorpage.jsx: defines
34        - the Corpora store of collections
35        - the AggregatorPage component which deals with search and displays the search results
36- components/corpusview.jsx: defines the CorpusView, rendered when the user views the available collections
37- plus in components/: various general usage React components
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
44        - AboutPage renders the about page
45        - StatisticsPage renders the stats page
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
50var Main = createReactClass({
51// fixme! - class Main extends React.Component {
52        componentWillMount: function() {
53                routeFromLocation.bind(this)();
54        },
55
56        getInitialState: function () {
57                return {
58                        navbarCollapse: false,
59                        navbarPageFn: this.renderAggregator,
60                        errorMessages: [],
61                };
62        },
63
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
75                var that = this;
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});
84                }, 10000);
85        },
86
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");
93                                } else if (jqXHR.responseText) {
94                                        that.error(jqXHR.responseText + " ("+error+")");
95                                } else  {
96                                        that.error(error + " ("+textStatus+")");
97                                }
98                                console.log("ajax error, jqXHR: ", jqXHR);
99                        };
100                }
101                // console.log("ajax", ajaxObject);
102                jQuery.ajax(ajaxObject);
103        },
104
105        toggleCollapse: function() {
106                this.setState({navbarCollapse: !this.state.navbarCollapse});
107        },
108
109        renderAggregator: function() {
110                return <AggregatorPage ajax={this.ajax} error={this.error} embedded={false}/>;
111        },
112
113        renderHelp: function() {
114                return <HelpPage />;
115        },
116
117        renderAbout: function() {
118                return <AboutPage toStatistics={this.toStatistics} />;
119        },
120
121        renderStatistics: function() {
122                return <StatisticsPage ajax={this.ajax} />;
123        },
124
125        renderEmbedded: function() {
126                return <AggregatorPage ajax={this.ajax} error={this.error} embedded={true}/>;
127        },
128
129        getPageFns: function() {
130                return {
131                        '': this.renderAggregator,
132                        'help': this.renderHelp,
133                        'about': this.renderAbout,
134                        'stats': this.renderStatistics,
135                        'embed': this.renderEmbedded,
136                };
137        },
138
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});
146                        console.log("new page: " + document.location + ", name: " + pageFnName);
147                }
148        },
149
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'); },
154        toEmbedded: function(doPushHistory) { this.gotoPage(doPushHistory, 'embed'); },
155
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
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":""}>
169                                                <a className="link" tabIndex="-1" onClick={this.toAggregator.bind(this, true)}>Aggregator</a>
170                                        </li>
171                                        <li className={this.state.navbarPageFn === this.renderHelp ? "active":""}>
172                                                <a className="link" tabIndex="-1" onClick={this.toHelp.bind(this, true)}>Help</a>
173                                        </li>
174                                </ul>
175                                <ul className="nav navbar-nav navbar-right">
176                                        <li> <div id="clarinservices" style={{padding:4}}/> </li>
177                                        {this.renderLogin()}
178                                </ul>
179                        </div>
180                );
181        },
182
183        renderTop: function() {
184                if (this.state.navbarPageFn === this.renderEmbedded) {
185                        return false;
186                }
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>
198                                                        <a className="navbar-brand" href={URLROOT + "/"} tabIndex="-1">
199                                                                <img width="28px" height="28px" src="img/magglass1.png"/>
200                                                                <header className="inline"> Federated Content Search </header>
201                                                        </a>
202                                                </div>
203                                                {this.renderCollapsible()}
204                                        </div>
205                                </div>
206
207                                <ErrorPane errorMessages={this.state.errorMessages} />
208
209                        </div>
210                );
211        },
212
213        render: function() {
214                return  (
215                        <div>
216                                <div> { this.renderTop() } </div>
217
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
229// StatisticsPage
230
231// HelpPage
232
233// AboutPage
234
235// Footer
236
237// EmbeddedFooter
238
239function isEmbeddedView() {
240        var path = window.location.pathname.split('/');
241        return (path.length >= 3 && path[path.length - 1] === 'embed');
242}
243
244function endsWith(str, suffix) {
245    return str.indexOf(suffix, str.length - suffix.length) !== -1;
246}
247
248var routeFromLocation = function() {
249        console.log("routeFromLocation: " + document.location);
250        if (!this) throw "routeFromLocation must be bound to main";
251        var path = window.location.pathname.split('/');
252        console.log("path: " + path);
253        if (path.length >= 3) {
254                var p = path[path.length - 1];
255                if (p === 'help') {
256                        this.toHelp(false);
257                } else if (p === 'about') {
258                        this.toAbout(false);
259                } else if (p === 'stats') {
260                        this.toStatistics(false);
261                } else if (p === 'embed') {
262                        this.toEmbedded(false);
263                } else {
264                        this.toAggregator(false);
265                }
266        } else {
267                this.toAggregator(false);
268        }
269};
270
271var main = ReactDOM.render(<Main />,  document.getElementById('body'));
272if (!isEmbeddedView()) {
273        ReactDOM.render(<Footer VERSION={VERSION} toAbout={main.toAbout}/>, document.getElementById('footer') );
274} else {
275        ReactDOM.render(<EmbeddedFooter URLROOT={URLROOT} />, document.getElementById('footer') );
276        if (jQuery) { jQuery('body, #footer').addClass('embedded'); }
277}
278
279window.onpopstate = routeFromLocation.bind(main);
280
281})();
Note: See TracBrowser for help on using the repository browser.