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

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

Bump version to 3.0.0 build 64.

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