Commit 87346282 authored by Karl Petter Egseth Aubert's avatar Karl Petter Egseth Aubert

Merge branch '#12-favorite-button-and-save-layout' into 'master'

#12 favorite button and save layout

Closes #14 and #12

See merge request !12
parents f1bbc900 40f48c08
......@@ -2,118 +2,202 @@ import React from 'react';
import './App.css';
import Title from './components/Title';
import Artwork from './components/Artwork';
import DisplayChooserComponent from "./components/DisplayChooserComponent";
import Tabs from './components/Tabs';
import { render } from "react-dom";
import './artwork.css';
import {render} from "react-dom";
import Tabs from './components/Tabs';
import DisplayChooser from './components/DisplayChooser';
import FavoriteSection from './components/FavoriteSection';
import SessionElement from './components/SessionElement';
import './navbar.css';
window.onbeforeunload = () => {
sessionStorage.clear();
};
class App extends React.Component {
constructor(props) {
super(props);
this.handleArtworkChange = this.handleArtworkChange.bind(this);
this.getImageTitle = this.getImageTitle.bind(this);
this.handleCategoryChange = this.handleCategoryChange.bind(this);
this.checkForEmptyLocalStorage = this.checkForEmptyLocalStorage.bind(this);
this.state = {
artwork: 0,
categorySelections: {
textCat: parseInt(localStorage.getItem('text')),
imageCat: parseInt(localStorage.getItem('image')),
audioCat: parseInt(localStorage.getItem('audio')),
}
};
this.checkForEmptyLocalStorage();
}
checkForEmptyLocalStorage() {
if (localStorage.getItem('text') === null || localStorage.getItem('image') === null || localStorage.getItem('audio') === null) {
this.setState({
categorySelections: {
textCat: 0,
imageCat: 0,
audioCat: 0,
}
});
}
}
handleArtworkChange(artworkId) {
this.setState({artwork: artworkId});
}
getImageTitle() {
let titles = ["Artwork 1", "Artwork 2", "Artwork 3", "Artwork 4"];
return titles[this.state.artwork] + JSON.stringify(this.state.categorySelections); // CategorySelection added for testing
}
handleCategoryChange(name, valueAsString) {
let value = parseInt(valueAsString);
const oldCatSel = this.state.categorySelections;
// eslint-disable-next-line default-case
switch (name) {
case "text":
this.setState({
categorySelections: {
imageCat: oldCatSel.imageCat,
textCat: value,
audioCat: oldCatSel.audioCat
}
});
break;
case "image":
this.setState({
categorySelections: {
imageCat: value,
textCat: oldCatSel.textCat,
audioCat: oldCatSel.audioCat
}
});
break;
case "audio":
this.setState({
categorySelections: {
imageCat: oldCatSel.imageCat,
textCat: oldCatSel.textCat,
audioCat: value,
}
});
break;
}
console.log(this.state.categorySelections);
}
render() {
const categorySelections = this.state.categorySelections;
return (
<div className="App">
<header className="App-header">
<div className="title">
<Title title={this.getImageTitle()} />
</div>
<div className="cluster">
<div className="chooser">
<DisplayChooserComponent categorySelections={categorySelections} handler={this}/>
constructor(props) {
super(props);
this.handleArtworkChange = this.handleArtworkChange.bind(this);
this.getImageTitle = this.getImageTitle.bind(this);
this.handleCategoryChange = this.handleCategoryChange.bind(this);
this.checkForEmptyLocalStorage = this.checkForEmptyLocalStorage.bind(this);
this.saveAsFavorite = this.saveAsFavorite.bind(this);
this.openFavorite = this.openFavorite.bind(this);
this.updateSession = this.updateSession.bind(this);
this.sessionClicked = this.sessionClicked.bind(this);
if (this.checkForEmptyLocalStorage()) {
this.state = {
artwork: localStorage.getItem('artwork'),
categorySelections: {
textCat: parseInt(localStorage.getItem('Text')),
imageCat: parseInt(localStorage.getItem('Image')),
audioCat: parseInt(localStorage.getItem('Audio')),
},
sessionHistory: [],
sessionCounter: 0
};
} else {
this.state = {
artwork: 0,
categorySelections: {
textCat: 0,
imageCat: 0,
audioCat: 0,
},
sessionHistory: [],
sessionCounter: 0
};
}
}
checkForEmptyLocalStorage() {
return !(localStorage.getItem('Text') === null || localStorage.getItem('Image') === null ||
localStorage.getItem('Audio') === null || localStorage.getItem('artwork') === null);
}
saveAsFavorite = () => {
localStorage.setItem("favoriteCombination",
JSON.stringify({
"textCat": this.state.categorySelections.textCat,
"imageCat": this.state.categorySelections.imageCat,
"audioCat": this.state.categorySelections.audioCat,
"artwork": this.state.artwork,
}));
};
openFavorite = () => {
let favComb = JSON.parse(localStorage.getItem("favoriteCombination"));
if (favComb === null) {
return;
}
this.setState({
categorySelections: {
textCat: favComb.textCat,
imageCat: favComb.imageCat,
audioCat: favComb.audioCat,
},
artwork: favComb.artwork,
}, event => {
this.updateSession();
});
};
sessionClicked = data => {
let dataAsArray = data.split(";");
this.setState({
artwork: (parseInt(dataAsArray[0].split(":").pop()) - 1),
categorySelections: {
textCat: (parseInt(dataAsArray[1].split(":").pop()) - 1),
imageCat: (parseInt(dataAsArray[2].split(":").pop()) - 1),
audioCat: (parseInt(dataAsArray[3].split(":").pop()) - 1)
}
});
};
updateSession = () => {
let newCombination = JSON.parse(sessionStorage.getItem('combinationHistory'));
if (newCombination === null) {
newCombination = [];
}
newCombination.push(
this.state.sessionCounter + "/" +
"Artwork:" + (parseInt(this.state.artwork) + 1) + ";" +
"Text:" + (parseInt(this.state.categorySelections.textCat) + 1) + ";" +
"Image:" + (parseInt(this.state.categorySelections.imageCat) + 1) + ";" +
"Audio:" + (parseInt(this.state.categorySelections.audioCat) + 1)
);
sessionStorage.setItem('combinationHistory', JSON.stringify(newCombination));
this.setState({
sessionHistory: JSON.parse(sessionStorage.getItem('combinationHistory')),
sessionCounter: (this.state.sessionCounter + 1)
});
};
handleArtworkChange(artworkId) {
localStorage.setItem("artwork", artworkId);
this.setState({artwork: artworkId}, event => this.updateSession());
}
getImageTitle() {
let titles = ["Artwork 1", "Artwork 2", "Artwork 3", "Artwork 4"];
return titles[this.state.artwork] + JSON.stringify(this.state.categorySelections); // CategorySelection added for testing
}
handleCategoryChange(name, valueAsString) {
let value = parseInt(valueAsString);
const oldCatSel = this.state.categorySelections;
// eslint-disable-next-line default-case
switch (name) {
case "Text":
this.setState({
categorySelections: {
textCat: value,
imageCat: oldCatSel.imageCat,
audioCat: oldCatSel.audioCat
}
}, event => {
if (oldCatSel.textCat !== value) {
this.updateSession();
}
});
break;
case "Image":
this.setState({
categorySelections: {
textCat: oldCatSel.textCat,
imageCat: value,
audioCat: oldCatSel.audioCat
}
}, event => {
if (oldCatSel.imageCat !== value) {
this.updateSession();
}
});
break;
case "Audio":
this.setState({
categorySelections: {
textCat: oldCatSel.textCat,
imageCat: oldCatSel.imageCat,
audioCat: value,
}
}, event => {
if (oldCatSel.audioCat !== value) {
this.updateSession();
}
});
break;
}
}
render() {
const categorySelections = this.state.categorySelections;
const sessionHistory = this.state.sessionHistory;
return (
<div className="App">
<header className="App-header">
<div className="title">
<Title title={this.getImageTitle()}/>
</div>
<div className="cluster">
<div className="chooser">
<DisplayChooser categorySelections={categorySelections} handler={this}/>
</div>
<div className="artworkArea">
<Artwork artwork={this.state.artwork}
handler={this}
categorySelections={categorySelections}/>
</div>
</div>
<FavoriteSection handler={this}/>
<SessionElement sessionHistory={sessionHistory} handler={this}/>
</header>
</div>
<div className="artworkArea">
<Artwork artwork={this.state.artwork}
handler={this}
categorySelections = {categorySelections} />
</div>
</div>
</header>
</div>
);
}
);
}
}
export default App;
import React from 'react';
import '../style/CategoryComponent.css';
import $ from 'jquery';
export default class CategoryComponent extends React.Component {
componentDidMount() {
if (this.props.preChecked === this.props.value){
$('#'+this.props.selectionName).prop('checked', true);
}
export default class Categories extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="Category-component">
<input name={this.props.mediaType} type="radio" onChange={this.props.handleChange}
value={this.props.value} id={this.props.selectionName} />
<label htmlFor={this.props.selectionName}>{this.props.categoryName}</label>
<input name={this.props.mediaType} type="checkbox" onChange={this.props.handleChange}
value={this.props.value} id={this.props.selectionName} checked={this.props.checked}/>
<label htmlFor={this.props.selectionName}>{this.props.categoryName} {this.props.selectedIndex}</label>
</div>
);
}
......
import React from 'react';
import MediaComponent from "./MediaComponent";
import MediaContainer from "./MediaContainer";
import '../style/DisplayChooserComponent.css';
export default class DisplayChooserComponent extends React.Component {
export default class DisplayChooser extends React.Component {
constructor(props) {
super(props);
this.combineMediaCategories = this.combineMediaCategories.bind(this);
this.state = {
text: this.props.categorySelections.textCat,
image: this.props.categorySelections.imageCat,
audio: this.props.categorySelections.audioCat,
}
}
combineMediaCategories = event => {
this.props.handler.handleCategoryChange(event.target.name, event.target.value);
// eslint-disable-next-line default-case
localStorage.setItem(event.target.name, event.target.value);
};
......@@ -24,13 +18,12 @@ export default class DisplayChooserComponent extends React.Component {
const categoryNames = ["Category 1", "Category 2", "Category 3"];
return (
<div className="Display-chooser-component">
<MediaComponent preChecked={this.state.text} categoryNames={categoryNames} media="text"
receiveRadios={this.combineMediaCategories}/>
<MediaComponent preChecked={this.state.image} categoryNames={categoryNames} media="image"
receiveRadios={this.combineMediaCategories}/>
<MediaComponent preChecked={this.state.audio} categoryNames={categoryNames} media="audio"
receiveRadios={this.combineMediaCategories}/>
<MediaContainer checkedIndex={this.props.categorySelections.textCat} categoryNames={categoryNames}
media="Text" handler={this}/>
<MediaContainer checkedIndex={this.props.categorySelections.imageCat} categoryNames={categoryNames}
media="Image" handler={this}/>
<MediaContainer checkedIndex={this.props.categorySelections.audioCat} categoryNames={categoryNames}
media="Audio" handler={this}/>
</div>
);
}
......
import React from 'react';
import '../style/FavoriteButton.css';
export default class FavoriteSection extends React.Component {
render() {
return (
<div className="Button-container">
<button onClick={this.props.handler.saveAsFavorite}>Save as favorite</button>
<button onClick={this.props.handler.openFavorite}>Open favourite</button>
</div>
);
}
}
import React from 'react';
import CategoryComponent from './CategoryComponent';
import '../style/MediaComponent.css'
export default class MediaComponent extends React.Component {
constructor(props) {
super(props);
this.handleRadioChange = this.handleRadioChange.bind(this);
this.state = {
selectedCategory: '',
savedEvent: null,
savedTarget: null,
}
}
handleRadioChange = event => {
event.persist();
this.setState({
savedEvent: event,
savedTarget: event.target,
selectedCategory: this.props.media + event.target.value
}, event => {
this.props.receiveRadios(this.state.savedEvent);
});
};
render() {
const categories = [0, 1, 2];
return (
<div className="Media-component">
<h3>{this.props.media}</h3>
<CategoryComponent value={categories[0]} mediaType={this.props.media}
handleChange={this.handleRadioChange} categoryName={this.props.categoryNames[0]}
selectionName={this.props.media + categories[0]} preChecked={this.props.preChecked}/>
<CategoryComponent value={categories[1]} mediaType={this.props.media}
handleChange={this.handleRadioChange} categoryName={this.props.categoryNames[1]}
selectionName={this.props.media + categories[1]} preChecked={this.props.preChecked}/>
<CategoryComponent value={categories[2]} mediaType={this.props.media}
handleChange={this.handleRadioChange} categoryName={this.props.categoryNames[2]}
selectionName={this.props.media + categories[2]} preChecked={this.props.preChecked}/>
</div>
);
}
}
import React from 'react';
import Categories from './Categories';
import '../style/MediaComponent.css'
export default class MediaContainer extends React.Component {
constructor(props) {
super(props);
}
render() {
const categories = [0, 1, 2];
const checked = [false, false, false];
for (let i = 0; i < categories.length; i++) {
if (categories[i] === this.props.checkedIndex) {
checked[i] = true;
}
}
return (
<div className="Media-component">
<h3>{this.props.media}</h3>
<Categories value={categories[0]} mediaType={this.props.media}
handleChange={this.props.handler.combineMediaCategories}
categoryName={this.props.categoryNames[0]}
selectionName={this.props.media + categories[0]}
checked={checked[0]}/>
<Categories value={categories[1]} mediaType={this.props.media}
handleChange={this.props.handler.combineMediaCategories}
categoryName={this.props.categoryNames[1]}
selectionName={this.props.media + categories[1]}
checked={checked[1]}/>
<Categories value={categories[2]} mediaType={this.props.media}
handleChange={this.props.handler.combineMediaCategories}
categoryName={this.props.categoryNames[2]}
selectionName={this.props.media + categories[2]}
checked={checked[2]}/>
</div>
);
}
}
import React from 'react';
import '../style/SessionElement.css';
export default class SessionElement extends React.Component {
render() {
let sessionHistory = [];
if (this.props.sessionHistory !== null) {
sessionHistory = this.props.sessionHistory.map((items) =>
<p key={items} onClick={() => this.props.handler.sessionClicked(items.split("/").pop())}>{items.replace(/;/g, " - ").replace(/:/g, ": ").split("/").pop()}</p>
);
}
return (
<div className="sessionHolder">
<h4>Combination history</h4>
{sessionHistory}
</div>
);
}
}
......@@ -5,6 +5,9 @@
.Category-component > input {
margin: -1px 0 0 0;
vertical-align: middle;
-webkit-appearance: radio;
-moz-appearance: radio;
-ms-appearance: radio;
}
.Category-component > label {
......
.Button-container button {
padding: 5px;
border-radius: 5px;
background: greenyellow;
border: 1px solid #333333;
transition: 0.5s ease;
}
.Button-container button:hover {
cursor: pointer;
}
\ No newline at end of file
.sessionHolder {
max-height: 200px;
overflow-y: scroll;
}
.sessionHolder p:hover {
cursor: pointer;
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment