source: js/human_3d_alignment/src/index.jsx @ 911

Last change on this file since 911 was 911, checked in by Maciej Komosinski, 4 years ago

Added the actual functionality of the app in place of previous draft

File size: 25.9 KB
Line 
1/*global Module*/
2"use strict";
3import http from 'http';
4import React from 'react';
5import Genotypes from './utils/genotypes';
6import TitlePanel from './viewskeleton/titlepanel';
7import WidgetsContainer from './viewskeleton/widgetscontainer';
8import TextViewer from './widgets/textviewer';
9import ParmViewer from './widgets/parmviewer';
10import SimilViewer from './widgets/similviewer';
11import FitViewer from './widgets/fitviewer';
12import SliderViewer from './widgets/sliderviewer';
13import EndViewer from './widgets/endviewer';
14
15const ROUNDS = 15;
16
17const styles = {
18    contentHeaderMenuLink: {
19        textDecoration: 'none',
20        color: 'white',
21        padding: 8,
22    },
23    content: {
24        padding: '16px',
25    },
26    sidebarLink: {
27        display: 'block',
28        padding: '16px 0px',
29        color: 'gray',
30        textDecoration: 'none',
31    },
32    divider: {
33        margin: '8px 0',
34        height: 1,
35        backgroundColor: 'gray',
36    },
37};
38
39
40/**
41 * Main class running Framsticks.JS page.
42 */
43class MainView extends React.Component {
44    /**
45     * Basic constructor holding informations about sidebar states
46     * @param {any} props component properties
47     */
48    constructor(props) {
49        super(props);
50        this.onLayoutChange = this.onLayoutChange.bind(this);
51
52        window.genetics = new Module.PreconfiguredGenetics();
53        this.layout = [
54            {name:'0,textviewer', x: 0, y: 0, w: 9, h: 1},
55            {name:'2,similviewer', x: 0, y: 1, w: 6, h: 4},
56            {name:'3,fitviewer', x: 6, y: 1, w: 6, h: 2},
57            {name:'4,sliderviewer', x: 6, y: 3, w: 6, h: 2},
58            {name:'1,parmviewer', x: 9, y: 0, w: 3, h: 1}
59        ];
60
61        this.container = <WidgetsContainer onRef={ref => (this.widgetscontainer = ref)} onLayoutChange={this.onLayoutChange} />;
62
63        this.state = {
64            genotypes: 0,
65            round: 0,
66            genotype1: '',
67            genotype2: '',
68            pairs: [],
69            id1: 0,
70            id2: 0,
71            parts1: 0,
72            parts2: 0,
73            selected1: [],
74            selected2: [],
75            position1: [0, 0, 0],
76            position2: [0, 0, 0],
77            rotation1: [0, 0, 0],
78            rotation2: [0, 0, 0],
79            userId: 0,
80            userIp: 'localhost',
81            timeStart: 0,
82            selectedGender: {value: "empty", label: " "},
83            selectedYear: {value: "empty", label: " "},
84            percent: 0,
85            sliderUpdated: true,
86            isDisable: true,
87            isFinished: false,
88            fitHeight: 2,
89            fitWidth: 6,
90            controlMode: 'translate',
91            blockView: true,
92            result: ''
93        };
94
95        this.start = this.start.bind(this);
96        this.getIp = this.getIp.bind(this);
97        this.nextRound = this.nextRound.bind(this);
98        this.saveRound = this.saveRound.bind(this);
99        this.saveFit = this.saveFit.bind(this);
100        this.refresh = this.refresh.bind(this);
101        this.sendToServer = this.sendToServer.bind(this);
102        this.finishApp = this.finishApp.bind(this);
103        this.isReady = this.isReady.bind(this);
104        this.isFitted = this.isFitted.bind(this);
105        this.browserData = this.browserData.bind(this);
106        this.loadNewGenotypes = this.loadNewGenotypes.bind(this);
107        this.handleChangeStartTime = this.handleChangeStartTime.bind(this);
108        this.handleChangeId = this.handleChangeId.bind(this);
109        this.handleChangeIp = this.handleChangeIp.bind(this);
110        this.handleChangeGender =  this.handleChangeGender.bind(this);
111        this.handleChangeYear = this.handleChangeYear.bind(this);
112        this.handleChangePercent = this.handleChangePercent.bind(this);
113        this.handleChangeStartTime = this.handleChangeStartTime.bind(this);
114        this.handleChangeFitHeight = this.handleChangeFitHeight.bind(this);
115        this.handleChangeFitWidth = this.handleChangeFitWidth.bind(this);
116        this.handleChangeControlMode = this.handleChangeControlMode.bind(this);
117        this.handleChangePosition1 = this.handleChangePosition1.bind(this);
118        this.handleChangePosition2 = this.handleChangePosition2.bind(this);
119        this.handleChangeRotation1 = this.handleChangeRotation1.bind(this);
120        this.handleChangeRotation2 = this.handleChangeRotation2.bind(this);
121        this.handleChangeBlockView = this.handleChangeBlockView.bind(this);
122        this.onClickNext = this.onClickNext.bind(this);
123        this.onClickFinish = this.onClickFinish.bind(this);
124    }
125
126    /**
127     * Uses default layout.
128    */
129    componentDidMount() {
130        window.addEventListener( 'keydown', ( event ) => {
131            switch ( event.keyCode ) {
132                case 84: // T
133                    this.handleChangeControlMode( "translate" );
134                    break;
135                case 82: // R
136                    this.handleChangeControlMode( "rotate" );
137                    break;
138            }
139        } );
140        let timeStart = new Date();
141        this.handleChangeStartTime(timeStart); //set time start
142        this.handleChangeId(  Math.round(timeStart.getTime() / 1000).toString() +  (Math.floor(Math.random() * (9999999 - 1000000 + 1) ) + 1000000).toString() + this.browserData().toString() ); //set user id = time + random + browserData_hash
143        this.getIp();   //set user ip
144        this.genotypes = new Genotypes(this, "https://raw.githubusercontent.com/arturolejnik95/human_3d_alignment/master/walking.gen");   //load text from file to this.genotypes
145        let head = "'User ID'|'User IP'|'Gender'|'Year of born'|'Start time'|'Stop time'|'Position of 1st'|'Position of 2nd'|'Rotation of 1st'|'Rotation of 2nd'|'ID 1st'|'ID 2nd'|'Fit'|'Result'\n"
146        this.handleChangeResult(head);
147    }
148
149    /**
150     * Calls resize event in order to properly set layout
151    */
152    componentDidUpdate() {
153        //window.dispatchEvent(new Event('resize'));
154        if (this.state.genotype1 != '' && this.state.genotype2 != '') {
155            this.useLayout(this.layout);
156        }
157    }
158
159
160    /**
161     * Start questionnaire if genotypes are loaded
162     */
163    start() {
164        this.setState({ genotypes: this.genotypes.id.length }, function() {
165            console.log(`Genotypes: `, this.state.genotypes);
166        });
167
168        this.loadNewGenotypes();
169        this.handleChangeBlockView(false);
170        this.useLayout(this.layout);
171    }
172
173    getIp() {
174        http.get({'host': 'api.ipify.org', 'port': 80, 'path': '/'}, (resp) => {
175            resp.on('data', ip => {
176                this.handleChangeIp(ip)
177            });
178        });
179    }
180
181    /**
182     * Save data about this round
183     */
184    saveRound() {
185        this.setState({ sliderUpdated: false }, function() {
186            console.log('Slider Updated: ' + this.state.sliderUpdated);
187        });
188        this.isReady();
189    }
190
191    /**
192     * Preset result as:
193     * user ID - IP - gender - year of born - start : end - position of 1. : position of 2.
194     * - rotation of 1. : rotation of 2. - id of 1. : id of second - pairs (1. mesh : 2. mesh) - fit result (0 - 100) ;
195     */
196    saveFit() {
197        let min = Math.min(this.state.parts1, this.state.parts2);
198        let timeStop = new Date();
199        let start = this.state.timeStart;
200        let stop = timeStop;
201        start = ("0" + start.getDate()).slice(-2) + '.' + ("0" + (start.getMonth() + 1)).slice(-2) + '.' + start.getFullYear() + ' ' + String(start.getHours()).padStart(2, '0') + ':' + String(start.getMinutes()).padStart(2, '0') + ':' + String(start.getSeconds()).padStart(2, '0');
202        stop = ("0" + stop.getDate()).slice(-2) + '.' + ("0" + (stop.getMonth() + 1)).slice(-2) + '.' + stop.getFullYear() + ' ' + String(stop.getHours()).padStart(2, '0') + ':' + String(stop.getMinutes()).padStart(2, '0') + ':' + String(stop.getSeconds()).padStart(2, '0');
203
204        let fit =   this.state.userId + '|' +
205                    this.state.userIp + '|' +
206                    this.state.selectedGender.value + '|' +
207                    this.state.selectedYear.value + '|' +
208                    start + '|' +
209                    stop + '|' +
210                    '(' + this.state.position1[0] + ',' + this.state.position1[1] + ',' + this.state.position1[2] + ')|' + 
211                    '(' + this.state.position2[0] + ',' + this.state.position2[1] + ',' + this.state.position2[2] + ')|' + 
212                    '(' + this.state.rotation1[0] + ',' + this.state.rotation1[1] + ',' + this.state.rotation1[2] + ')|' + 
213                    '(' + this.state.rotation2[0] + ',' + this.state.rotation2[1] + ',' + this.state.rotation2[2] + ')|'; 
214                   
215       
216        let pair = this.state.pairs[this.state.pairs.length - 1];
217        fit = fit + this.genotypes.id[pair[0]] + '|' + this.genotypes.id[pair[1]] + '|';
218
219        for (let i = 0; i < min; i++) {
220            fit = fit + this.state.selected1[i] + ':' + (this.state.selected2[i].charCodeAt(0) - 65 + 1);
221            if (i < min - 1) {
222                fit = fit + ';';
223            }
224        }
225        fit = fit + '|' + this.state.percent + '\n';
226
227        this.sendToServer(fit);
228
229        this.handleChangeResult(this.state.result + fit);
230        this.handleChangeStartTime(timeStop);
231    }
232
233
234
235    sendToServer(fit) {
236        let rawFile = new XMLHttpRequest();
237        rawFile.addEventListener('load', () => {
238            console.log(rawFile.responseText);
239        });
240        rawFile.addEventListener('error', () => {
241            console.log('Błąd wysyłania na serwer');
242        });
243       
244        rawFile.open("POST", 'https://ptsv2.com/t/b7nhq-1578108725/post');
245        rawFile.setRequestHeader("Content-type", 'text/plain');
246        rawFile.send(fit);
247    }
248
249    /**
250     * Load next pair of genotypes
251     */
252    nextRound() {
253        this.loadNewGenotypes();
254        this.handleChangeBlockView(false);
255    }
256
257    /**
258     * Refresh used default layout
259     */
260    refresh() {
261        this.useLayout(this.layout);
262    }
263
264    /**
265     * Load new genotypes to simulator viewer
266     */
267    loadNewGenotypes() {
268        //Firstly it chooses pair of genotypes that user doesnt used before
269        let rand1, rand2, amount1, amount2, gen1, gen2;
270
271        do {
272            rand1 = 0, rand2 = 0;
273            do  {
274                while (rand1 == rand2) {
275                    rand1 = Math.floor(Math.random() * this.state.genotypes);
276                    rand2 = Math.floor(Math.random() * this.state.genotypes);
277                }
278            } while (this.state.pairs.includes([rand1, rand2]) || this.state.pairs.includes([rand2, rand1]));
279
280            //This part load genotypes to the state
281            gen1 = this.genotypes.genotype[rand1];
282            gen2 = this.genotypes.genotype[rand2];
283            amount1 = gen1.split('').filter(function(sign){return sign === 'X'}).length;
284            amount2 = gen2.split('').filter(function(sign){return sign === 'X'}).length;
285            if (amount1 > 0) {
286                amount1++;
287            }
288            if (amount2 > 0) {
289                amount2++
290            }
291        } while (amount1 > 52 || amount2 > 52);
292
293        let newpairs = this.state.pairs;
294        if (amount1 <= amount2) {
295            newpairs.push([rand1, rand2]);
296            this.setState({ genotype1: gen1, genotype2: gen2 }, function() {
297                console.log(`Genotypes: `, this.state.genotype1, this.state.genotype2);
298            });
299            this.setState({parts1: amount1, parts2: amount2}, function() {
300                console.log(this.state.parts1 + ' ' + this.state.parts2);
301            });
302        } else {
303            newpairs.push([rand2, rand1]);
304            this.setState({ genotype1: gen2, genotype2: gen1 }, function() {
305                console.log(`Genotypes: `, this.state.genotype1, this.state.genotype2);
306            });
307            this.setState({parts1: amount2, parts2: amount1}, function() {
308                console.log(this.state.parts1 + ' ' + this.state.parts2);
309            });
310        }
311        this.setState({ pairs: newpairs }, function() {
312            console.log(`Pairs: `, this.state.pairs);
313        });
314
315        //Load tables of selected parts in fitviewer
316        let min = Math.min(amount1, amount2);
317        let s1 = [];
318        let s2 = [];
319        for (let i = 0; i < min; i++) {
320            s1.push((i+1).toString());
321            s2.push(' ');
322        }
323
324        //Start new round and load to state tables of selected and round
325        let r = this.state.round + 1;
326        this.setState({ round: r, selected1: s1, selected2: s2}, function() {
327            console.log(`Round and state `, this.state.round + '. ' + this.state.selected1 + ' ' + this.state.selected2);
328        });
329    }
330
331    /**
332     * Check is user ready to go to the next question by checking choosed gender, birth year and percent of similarity
333     */
334    isReady() {
335        if (this.state.selectedGender.value != 'empty' && this.state.selectedYear.value != 'empty' && this.state.sliderUpdated) {
336            this.setState({isDisable: false}, function() {
337                console.log(this.state.isDisable);
338            });
339        } else {
340            if (!this.state.isDisable) {
341                this.setState({isDisable: true}, function() {
342                    console.log(this.state.isDisable);
343                });
344            }
345        }
346    }
347
348    /**
349     * Check is user matched all needed sticks
350     */
351    isFitted() {
352        let index1 = this.state.selected1.indexOf(' ');
353        let index2 = this.state.selected2.indexOf(' ');
354
355        if (index1 < 0 && index2 < 0 && this.state.sliderUpdated) {
356            this.setState({sliderUpdated: false}, function() {
357                console.log(this.state.sliderUpdated);
358                this.isReady();
359            });
360        }
361    }
362
363    /**
364     * Return hash data of browser
365     */
366    browserData() {
367        let data = navigator.userAgent;
368        let hash = 0;
369        for (let i = 0; i < data.length; i++) {
370            let character = data.charCodeAt(i);
371            hash = ((hash<<5)-hash)+character;
372            hash = hash & hash; // Convert to 32bit integer
373        }
374        return hash;
375    }
376
377    /**
378     * Performed at the end of the survey
379     */
380    finishApp() {
381        this.layout = [
382            {name:'5,endviewer', x: 0, y: 0, w: 12, h: 4}
383        ];
384        this.useLayout(this.layout);
385    }
386
387    /**
388     * Allow to change gender in state
389     * @param {string} gen choosed gender by user in listbox
390     */
391    handleChangeGender(gen) {
392        this.setState({ selectedGender: gen }, function() {
393            console.log(`Gender selected:`, this.state.selectedGender);
394            console.log(this.genotypes.id.length)
395            this.isReady();
396        });
397    };
398   
399    /**
400     * Allow to change IP
401     * @param {number} ip user IP
402     */
403    handleChangeIp(ip) {
404        this.setState({ userIp: ip }, function() {
405            console.log(`IP:`, this.state.userIp);
406        });
407    }
408   
409    /**
410     * Allow to change user ID
411     * @param {number} id user ID
412     */
413    handleChangeId(id) {
414        this.setState({ userId: id }, function() {
415            console.log(`ID:`, this.state.userId);
416        });
417    }
418   
419    /**
420     * Allow to change start time
421     * @param {number} time time of begging fitting framsticks
422     */
423    handleChangeStartTime(time) {
424        this.setState({ timeStart: time }, function() {
425            console.log(`Start time:`, this.state.timeStart);
426        });
427    }
428
429    /**
430     * Allow to change birth year in state
431     * @param {number} year choosed birth year by user in listbox
432     */
433    handleChangeYear(year) {
434        this.setState({ selectedYear: year }, function() {
435            console.log(`Birth year selected:`, this.state.selectedYear);
436            this.isReady();
437        });
438    }
439
440    /**
441     * Allow to change percent in state and mark this in state.sliderUpdated
442     * @param {Integer} per choosed similarity of framsticks by user in percentage
443     */
444    handleChangePercent(per) {
445        this.setState({ percent: per, sliderUpdated: true }, function() {
446            console.log('Percent selected: ' + this.state.percent + ' ' + this.state.sliderUpdated);
447            this.isReady();
448        });
449    }
450
451    /**
452     *
453     * @param {number} nr framstick id
454     * @param {number} pos position on the match map
455     * @param {*} val id of choosed stick
456     */
457    handleChangeSelected(nr, pos, val) {
458        if (nr == 1) {
459            this.setState(state => {
460                const selected1 = state.selected1.map((item, i) => {
461                    if (pos === i) {
462                        return val;
463                    } else {
464                        return item;
465                    }
466                });
467
468                return {
469                    selected1,
470                };
471            },  function() {
472                console.log(this.state.selected1);
473                this.isFitted();
474            });
475        } else {
476            this.setState(state => {
477                const selected2 = state.selected2.map((item, i) => {
478                    if (pos === i) {
479                        let v = val.charCodeAt(0);
480                        if (v > 90) {
481                            v = v - 6;
482                        }
483                        let res = String.fromCharCode(v);
484                        return res;
485                    } else {
486                        return item;
487                    }
488                });
489
490                return {
491                    selected2,
492                };
493            }, function() {
494                console.log(this.state.selected2);
495                this.isFitted();
496            });
497        }
498    }
499   
500    /**
501     * Function to inform fitviewer about change of height to update scrollbar (for firefox)
502     * @param {number} h height
503     */
504    handleChangeFitHeight(h) {
505        this.setState({ fitHeight: h }, function() {
506            console.log(`Fit Height:`, this.state.fitHeight);
507        });
508    }
509   
510    /**
511     * Function to inform fitviewer about change of width to update scrollbar (for firefox)
512     * @param {number} w width
513     */
514    handleChangeFitWidth(w) {
515        this.setState({ fitWidth: w }, function() {
516            console.log(`Fit Width:`, this.state.fitWidth);
517        });
518    }
519
520    /**
521     * Allow to change transform controler mode
522     * @param {number} mode translate or rotation
523     */
524    handleChangeControlMode(mode) {
525        this.setState({ controlMode: mode }, function() {
526            console.log(`Control mode:`, this.state.controlMode);
527        });
528    }
529
530    /**
531     * Allow to save actural position of first genotype
532     * @param {Array} pos position [x, y, z] of first genotype
533     */
534    handleChangePosition1(pos) {
535        this.setState({ position1: pos}, function() {
536            console.log('Position1: ', this.state.position1);
537        });
538    }
539
540    /**
541     * Allow to save actural position of second genotype
542     * @param {Array} pos position [x, y, z] of second genotype
543     */
544    handleChangePosition2(pos) {
545        this.setState({ position2: pos}, function() {
546            console.log('Position2: ', this.state.position2);
547        });
548    }
549
550    /**
551     * Allow to save actural rotation of first genotype
552     * @param {Array} rot rotation [x, y, z] of first genotype
553     */
554    handleChangeRotation1(rot) {
555        this.setState({ rotation1: rot}, function() {
556            console.log('Rotation1: ', this.state.rotation1);
557        });
558    }
559
560    /**
561     * Allow to save actural rotation of second genotype
562     * @param {Array} rot rotation [x, y, z] of second genotype
563     */
564    handleChangeRotation2(rot) {
565        this.setState({ rotation2: rot}, function() {
566            console.log('Rotation2: ', this.state.rotation2);
567        });
568    }
569
570    /**
571     * Allow to block view in simviewer
572     * @param {Array} rot rotation [x, y, z] of second genotype
573     */
574    handleChangeBlockView(bool) {
575        this.setState({ blockView: bool}, function() {
576            console.log('Block View: ', this.state.blockView);
577        });
578    }
579
580    /**
581     * Allow to change finish result that will be save in the file at the end
582     * @param {string} res text to be save in file
583     */
584    handleChangeResult(res) {
585        this.setState({ result: res }, function() {
586            console.log('Result: ', this.state.result);
587        });
588    }
589
590    /**
591     * Next button function
592     */
593    onClickNext() {
594        this.handleChangeBlockView(true);
595        this.saveFit();
596        if (this.state.round == ROUNDS) {
597            this.setState({ isFinished: true }, function() {
598                console.log('Finish state: ' + this.state.isFinished);
599   
600                if (this.state.isFinished) {
601                    this.finishApp();
602                }
603            });
604        } else {
605            this.nextRound();
606        }
607    }
608
609    /**
610     * Close button function
611     */
612    onClickFinish() {
613        this.setState({ isFinished: true }, function() {
614            console.log('Finish state: ' + this.state.isFinished);
615
616            if (this.state.isFinished) {
617                this.finishApp();
618            }
619        });
620    }
621
622    /**
623     * Stores layout, for LocalStorage layout saving
624     * @param {any} layout layout to be saved
625     */
626    onLayoutChange(layout) {
627        let newlayout = [];
628        for (let i = 0; i < layout.length; i++) {
629            newlayout.push({name: layout[i].i, x: layout[i].x, y: layout[i].y, w: layout[i].w, h: layout[i].h});
630            if (newlayout[i].name == '2fitviewer') {
631                this.handleChangeFitHeight(newlayout[i].h);
632                this.handleChangeFitWidth(newlayout[i].w);
633            }
634        }
635    }
636    /**
637     * Passes layout to widgetscontainer.
638     * @param {any} layout layout to be used
639     */
640    useLayout(layout) {
641        let items = [];
642        for (let i = 0; i < layout.length; i++) {
643            let name = layout[i].name.split(',')[1];
644            switch (name) {
645                case 'textviewer':
646                    items.push({content: <TextViewer/>, i: "" + i + 'textviewer',
647                        x: layout[i].x, y: layout[i].y, w: layout[i].w, h: layout[i].h});
648                    break;
649                case 'similviewer':
650                    items.push({content: <SimilViewer
651                            genotype1 = {this.state.genotype1}
652                            genotype2 = {this.state.genotype2}
653                            selected1 = {this.state.selected1}
654                            selected2 = {this.state.selected2}
655                            blockView = {this.state.blockView}
656                            handleChangePosition1 = {(pos) => this.handleChangePosition1(pos)}
657                            handleChangePosition2 = {(pos) => this.handleChangePosition2(pos)}
658                            handleChangeRotation1 = {(rot) => this.handleChangeRotation1(rot)}
659                            handleChangeRotation2 = {(rot) => this.handleChangeRotation2(rot)}
660                            controlMode = {this.state.controlMode}
661                            round = {this.state.round}/>,
662                        i: "" + i + 'similviewer',
663                        x: layout[i].x, y: layout[i].y, w: layout[i].w, h: layout[i].h});
664                    break;
665                case 'parmviewer':
666                    items.push({content: <ParmViewer
667                            handleChangeYear = {(year) => {this.handleChangeYear(year)}}
668                            handleChangeGender = {(gen) => {this.handleChangeGender(gen)}}
669                        />,
670                        i: "" + i + 'parmviewer',
671                        x: layout[i].x, y: layout[i].y, w: layout[i].w, h: layout[i].h});
672                    break;
673                case 'fitviewer':
674                    items.push({content: <FitViewer
675                            selected1 = {this.state.selected1}
676                            selected2 = {this.state.selected2}
677                            parts1 = {this.state.parts1}
678                            parts2 = {this.state.parts2}
679                            fitHeight = {this.state.fitHeight}
680                            fitWidth = {this.state.fitWidth}
681                            handleChangeSelected = {(nr, pos, val) => {this.handleChangeSelected(nr, pos, val)}}/>,
682                        i: "" + i + 'fitviewer',
683                        x: layout[i].x, y: layout[i].y, w: layout[i].w, h: layout[i].h});
684                    break;
685                case 'sliderviewer':
686                    items.push({content: <SliderViewer
687                            isDisable = {this.state.isDisable}
688                            parts1 = {this.state.parts1}
689                            parts2 = {this.state.parts2}
690                            selected1 = {this.state.selected1}
691                            selected2 = {this.state.selected2}
692                            onClickNext = {() => {this.onClickNext()}}
693                            onClickFinish = {() => {this.onClickFinish()}}
694                            handleChangePercent = {(per) => {this.handleChangePercent(per)}}/>,
695                        i: "" + i + 'sliderviewer',
696                        x: layout[i].x, y: layout[i].y, w: layout[i].w, h: layout[i].h});
697                    break;
698                case 'endviewer':
699                    items.push({content: <EndViewer
700                            userId = {this.state.userId}
701                            result = {this.state.result}/>,
702                        i: "" + i + 'endviewer',
703                        x: layout[i].x, y: layout[i].y, w: layout[i].w, h: layout[i].h});
704                    break;
705            }
706        }
707        this.widgetscontainer.addMultipleItems(items);
708    }
709
710    /**
711     * Render function.
712     * @returns {JSX.Element} main page of Framsticks.JS
713     */
714    render() {
715       
716        const contentHeader = (
717            <span>   
718                <span style={{marginLeft: '20px', fontFamily: "'Fira Mono', Monaco, 'Andale Mono', 'Lucida Console', 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace"}}>
719                    Ankieta
720                </span>
721            </span>
722        );
723
724        return (
725            <TitlePanel
726                title={contentHeader}
727            >
728                <div style={styles.content}>
729                    {this.container}
730                </div>
731            </TitlePanel>
732        );
733    }
734}
735
736export default MainView;
Note: See TracBrowser for help on using the repository browser.