From 28f3d6db70bc47860d4cdf81e7c46c33535d8e09 Mon Sep 17 00:00:00 2001 From: Lukas Heiligenbrunner Date: Mon, 19 Oct 2020 21:12:07 +0000 Subject: [PATCH] use flexbox to wrap settings tiles correctly new icon for different tags ignore test files in codeclimate test --- .codeclimate.yml | 39 ++++++++++ .gitlab-ci.yml | 1 + api/src/handlers/Settings.php | 29 +++++++- package.json | 16 ++-- src/App.module.css | 3 +- src/elements/AddTagPopup/AddTagPopup.test.js | 4 +- src/elements/InfoHeaderItem/InfoHeaderItem.js | 34 +++++++++ .../InfoHeaderItem/InfoHeaderItem.module.css | 58 +++++++++++++++ .../InfoHeaderItem/InfoHeaderItem.test.js | 43 +++++++++++ src/elements/NewTagPopup/NewTagPopup.js | 10 +-- src/elements/Preview/Preview.js | 2 +- src/elements/Tag/Tag.js | 2 +- src/pages/CategoryPage/CategoryPage.js | 2 +- src/pages/CategoryPage/CategoryPage.test.js | 4 +- src/pages/HomePage/HomePage.js | 6 +- src/pages/Player/Player.js | 8 +- src/pages/Player/Player.module.css | 1 - src/pages/RandomPage/RandomPage.js | 5 +- src/pages/SettingsPage/GeneralSettings.js | 73 +++++++++++++------ .../SettingsPage/GeneralSettings.module.css | 14 ++++ .../SettingsPage/GeneralSettings.test.js | 5 ++ .../SettingsPage/SettingsPage.module.css | 3 +- 22 files changed, 307 insertions(+), 55 deletions(-) create mode 100644 src/elements/InfoHeaderItem/InfoHeaderItem.js create mode 100644 src/elements/InfoHeaderItem/InfoHeaderItem.module.css create mode 100644 src/elements/InfoHeaderItem/InfoHeaderItem.test.js diff --git a/.codeclimate.yml b/.codeclimate.yml index 0870063..9a947e2 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,4 +1,43 @@ version: "2" +plugins: + csslint: + enabled: true + coffeelint: + enabled: true + duplication: + enabled: true + config: + languages: + - ruby + - javascript + - python + - php + eslint: + enabled: true + channel: __ESLINT_CHANNEL__ + fixme: + enabled: true + rubocop: + enabled: true +exclude_patterns: + - config/ + - db/ + - dist/ + - features/ + - "**/node_modules/" + - script/ + - "**/spec/" + - "**/test/" + - "**/tests/" + - Tests/ + - "**/vendor/" + - "**/*_test.go" + - "**/*.d.ts" + - "**/*.min.js" + - "**/*.min.css" + - "**/__tests__/" + - "**/__mocks__/" + - "**/*.test.js" checks: argument-count: config: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2c95f53..15ece61 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,6 +21,7 @@ prepare: stage: prepare script: - npm install --progress=false + - npm update --progress=false build: stage: build diff --git a/api/src/handlers/Settings.php b/api/src/handlers/Settings.php index 7ef4412..21f3ef8 100644 --- a/api/src/handlers/Settings.php +++ b/api/src/handlers/Settings.php @@ -14,12 +14,35 @@ class Settings extends RequestBase { /** * handle settings stuff to load from db */ - private function getFromDB(){ + private function getFromDB() { /** * load currently set settings form db for init of settings page */ $this->addActionHandler("loadGeneralSettings", function () { - $query = "SELECT * from settings"; + // query settings and infotile values + $query = " + SELECT ( + SELECT COUNT(*) + FROM videos + ) AS videonr, + ( + SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS Size + FROM information_schema.TABLES + WHERE TABLE_SCHEMA = '" . Database::getInstance()->getDatabaseName() . "' + GROUP BY table_schema + ) AS dbsize, + ( + SELECT COUNT(*) + FROM tags + ) AS difftagnr, + ( + SELECT COUNT(*) + FROM video_tags + ) AS tagsadded, + settings.* + FROM settings + LIMIT 1 + "; $result = $this->conn->query($query); @@ -51,7 +74,7 @@ class Settings extends RequestBase { /** * handle setting stuff to save to db */ - private function saveToDB(){ + private function saveToDB() { /** * save changed settings to db */ diff --git a/package.json b/package.json index c13873a..8dc0e34 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,16 @@ "version": "0.1.0", "private": true, "dependencies": { - "bootstrap": "^4.5.0", + "@fortawesome/fontawesome-svg-core": "^1.2.30", + "@fortawesome/free-regular-svg-icons": "^5.15.1", + "@fortawesome/free-solid-svg-icons": "^5.15.1", + "@fortawesome/react-fontawesome": "^0.1.11", + "bootstrap": "^4.5.3", "plyr-react": "^2.2.0", - "react": "^16.13.1", - "react-bootstrap": "^1.0.1", - "react-dom": "^16.13.1", - "react-scripts": "^3.4.1" + "react": "^16.14.0", + "react-bootstrap": "^1.3.0", + "react-dom": "^16.14.0", + "react-scripts": "^3.4.3" }, "scripts": { "start": "react-scripts start", @@ -49,7 +53,7 @@ "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", "enzyme": "^3.11.0", - "enzyme-adapter-react-16": "^1.15.2", + "enzyme-adapter-react-16": "^1.15.5", "jest-junit": "^10.0.0" } } diff --git a/src/App.module.css b/src/App.module.css index b3e63ec..10a8a7e 100644 --- a/src/App.module.css +++ b/src/App.module.css @@ -37,9 +37,8 @@ } .navcontainer { - border-bottom-width: 2px; + border-width: 0 0 2px 0; border-style: dotted; - border-width: 0; padding-bottom: 40px; padding-top: 20px; diff --git a/src/elements/AddTagPopup/AddTagPopup.test.js b/src/elements/AddTagPopup/AddTagPopup.test.js index 9728dbd..5adb711 100644 --- a/src/elements/AddTagPopup/AddTagPopup.test.js +++ b/src/elements/AddTagPopup/AddTagPopup.test.js @@ -39,7 +39,7 @@ describe('', function () { global.fetch = prepareFetchApi({result: "success"}); wrapper.setProps({ - submit: jest.fn((arg1, arg2) => {}), + submit: jest.fn(() => {}), onHide: jest.fn() }, () => { wrapper.instance().addTag(1, "test"); @@ -62,7 +62,7 @@ describe('', function () { global.fetch = prepareFetchApi({result: "fail"}); wrapper.setProps({ - submit: jest.fn((arg1, arg2) => {}), + submit: jest.fn(() => {}), onHide: jest.fn() }, () => { wrapper.instance().addTag(1, "test"); diff --git a/src/elements/InfoHeaderItem/InfoHeaderItem.js b/src/elements/InfoHeaderItem/InfoHeaderItem.js new file mode 100644 index 0000000..00a95db --- /dev/null +++ b/src/elements/InfoHeaderItem/InfoHeaderItem.js @@ -0,0 +1,34 @@ +import React from "react"; +import style from './InfoHeaderItem.module.css'; +import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; +import {Spinner} from "react-bootstrap"; + +/** + * a component to display one of the short quickinfo tiles on dashboard + */ +class InfoHeaderItem extends React.Component { + render() { + return ( +
{ + // call clicklistener if defined + if (this.props.onClick != null) this.props.onClick(); + }} className={style.infoheaderitem} style={{backgroundColor: this.props.backColor}}> +
+ +
+ {this.props.text !== null && this.props.text !== undefined ? + <> +
{this.props.text}
+
{this.props.subtext}
+ + : + } +
+ ); + } +} + +export default InfoHeaderItem; diff --git a/src/elements/InfoHeaderItem/InfoHeaderItem.module.css b/src/elements/InfoHeaderItem/InfoHeaderItem.module.css new file mode 100644 index 0000000..d67f20b --- /dev/null +++ b/src/elements/InfoHeaderItem/InfoHeaderItem.module.css @@ -0,0 +1,58 @@ +/* styling for tile */ +.infoheaderitem { + background-color: lightblue; + border-radius: 5px; + flex: calc(25% - 10px); + margin: 5px; +} + +/* On screens that are 1317px wide or less, go from four columns to two columns */ +@media screen and (max-width: 1317px) { + .infoheaderitem { + flex: calc(50% - 10px); + } +} + +/* change opacity of icon when hovering whole tile */ +.infoheaderitem:hover .icon { + opacity: 0.75; + transition: opacity linear 0.4s; +} + +/* change cursor on hover */ +.infoheaderitem:hover { + cursor: pointer; +} + +.icon { + float: left; + height: 130px; + margin-left: 5px; + margin-right: 17px; + margin-top: 20px; + opacity: 0.5; + text-align: center; + + width: 30%; +} + +/* big main text in tile */ +.maintext { + font-size: x-large; + font-weight: bold; + margin-top: 30px; +} + +/* small subtext in tile */ +.subtext { + font-size: large; + margin-top: 5px; + opacity: 0.7; +} + +.loadAnimation { + display: inline-block; + line-height: 145px; + margin-left: calc(25% - 15px); + vertical-align: middle; +} diff --git a/src/elements/InfoHeaderItem/InfoHeaderItem.test.js b/src/elements/InfoHeaderItem/InfoHeaderItem.test.js new file mode 100644 index 0000000..e20a581 --- /dev/null +++ b/src/elements/InfoHeaderItem/InfoHeaderItem.test.js @@ -0,0 +1,43 @@ +import {shallow} from "enzyme"; +import React from "react"; +import InfoHeaderItem from "./InfoHeaderItem"; + +describe('', function () { + it('renders without crashing ', function () { + const wrapper = shallow(); + wrapper.unmount(); + }); + + it('renders correct text', function () { + const wrapper = shallow(); + expect(wrapper.find(".maintext").text()).toBe("mytext"); + }); + + it('renders correct subtext', function () { + const wrapper = shallow(); + expect(wrapper.find(".subtext").text()).toBe("testtext"); + }); + + it('test no subtext if no text defined', function () { + const wrapper = shallow(); + expect(wrapper.find(".subtext")).toHaveLength(0); + }); + + it('test custom click handler', function () { + const func = jest.fn(); + const wrapper = shallow( func()}/>); + expect(func).toBeCalledTimes(0); + wrapper.simulate("click"); + expect(func).toBeCalledTimes(1); + }); + + it('test insertion of loading spinner', function () { + const wrapper = shallow(); + expect(wrapper.find("Spinner").length).toBe(1); + }); + + it('test loading spinner if undefined', function () { + const wrapper = shallow(); + expect(wrapper.find("Spinner").length).toBe(1); + }); +}); diff --git a/src/elements/NewTagPopup/NewTagPopup.js b/src/elements/NewTagPopup/NewTagPopup.js index bbe6a04..481cfe1 100644 --- a/src/elements/NewTagPopup/NewTagPopup.js +++ b/src/elements/NewTagPopup/NewTagPopup.js @@ -18,21 +18,21 @@ class NewTagPopup extends React.Component { - + Create a new Tag! Tag Name: - { + { this.value = v.target.value }}/> - + This Tag will automatically show up on category page. diff --git a/src/elements/Preview/Preview.js b/src/elements/Preview/Preview.js index ff3aa8b..066d819 100644 --- a/src/elements/Preview/Preview.js +++ b/src/elements/Preview/Preview.js @@ -48,7 +48,7 @@ class Preview extends React.Component { Pic loading. : - } + }
diff --git a/src/elements/Tag/Tag.js b/src/elements/Tag/Tag.js index 21c73ce..330b981 100644 --- a/src/elements/Tag/Tag.js +++ b/src/elements/Tag/Tag.js @@ -10,7 +10,7 @@ class Tag extends React.Component { render() { return ( + data-testid='Test-Tag'>{this.props.children} ); } diff --git a/src/pages/CategoryPage/CategoryPage.js b/src/pages/CategoryPage/CategoryPage.js index d10b834..b89b143 100644 --- a/src/pages/CategoryPage/CategoryPage.js +++ b/src/pages/CategoryPage/CategoryPage.js @@ -84,7 +84,7 @@ class CategoryPage extends React.Component { : null} - : diff --git a/src/pages/CategoryPage/CategoryPage.test.js b/src/pages/CategoryPage/CategoryPage.test.js index 5f806d7..fdafef3 100644 --- a/src/pages/CategoryPage/CategoryPage.test.js +++ b/src/pages/CategoryPage/CategoryPage.test.js @@ -98,7 +98,7 @@ describe('', function () { const func = jest.fn(); CategoryPage.prototype.fetchVideoData = func; - shallow(); + shallow(); expect(func).toBeCalledTimes(1); }); @@ -106,7 +106,7 @@ describe('', function () { it('test sidebar tag clicks', function () { const func = jest.fn(); - const wrapper = mount(); + const wrapper = mount(); wrapper.instance().loadTag = func; console.log(wrapper.debug()); diff --git a/src/pages/HomePage/HomePage.js b/src/pages/HomePage/HomePage.js index cd05329..4192613 100644 --- a/src/pages/HomePage/HomePage.js +++ b/src/pages/HomePage/HomePage.js @@ -131,12 +131,12 @@ class HomePage extends React.Component { e.preventDefault(); this.searchVideos(this.keyword); }}> - { this.keyword = e.target.value }}/> - + diff --git a/src/pages/Player/Player.js b/src/pages/Player/Player.js index faaa564..d8186a3 100644 --- a/src/pages/Player/Player.js +++ b/src/pages/Player/Player.js @@ -126,7 +126,7 @@ class Player extends React.Component { {this.state.quality}p Quality! : null} {this.state.length !== 0 ? {Math.round(this.state.length / 60)} Minutes of - length! : null} + length! : null} Tags: {this.state.tags.map((m) => ( @@ -167,8 +167,10 @@ class Player extends React.Component {
not loaded yet
}
- - + +
diff --git a/src/pages/Player/Player.module.css b/src/pages/Player/Player.module.css index 6a21fec..cd686b3 100644 --- a/src/pages/Player/Player.module.css +++ b/src/pages/Player/Player.module.css @@ -12,7 +12,6 @@ display: block; float: left; margin-left: 20px; - margin-top: 25px; margin-top: 20px; width: 60%; } diff --git a/src/pages/RandomPage/RandomPage.js b/src/pages/RandomPage/RandomPage.js index e360889..8613629 100644 --- a/src/pages/RandomPage/RandomPage.js +++ b/src/pages/RandomPage/RandomPage.js @@ -25,9 +25,8 @@ class RandomPage extends React.Component { render() { return (
- + Visible Tags: diff --git a/src/pages/SettingsPage/GeneralSettings.js b/src/pages/SettingsPage/GeneralSettings.js index d2443de..a3d8e90 100644 --- a/src/pages/SettingsPage/GeneralSettings.js +++ b/src/pages/SettingsPage/GeneralSettings.js @@ -2,6 +2,9 @@ import React from "react"; import {Button, Col, Form} from "react-bootstrap"; import style from "./GeneralSettings.module.css" import GlobalInfos from "../../GlobalInfos"; +import InfoHeaderItem from "../../elements/InfoHeaderItem/InfoHeaderItem"; +import {faArchive, faBalanceScaleLeft, faRulerVertical} from "@fortawesome/free-solid-svg-icons"; +import {faAddressCard} from "@fortawesome/free-regular-svg-icons"; /** * Component for Generalsettings tag on Settingspage @@ -18,7 +21,12 @@ class GeneralSettings extends React.Component { videopath: "", tvshowpath: "", mediacentername: "", - password: "" + password: "", + + videonr: null, + dbsize: null, + difftagnr: null, + tagsadded: null }; } @@ -30,31 +38,49 @@ class GeneralSettings extends React.Component { const themeStyle = GlobalInfos.getThemeStyle(); return ( <> +
+ + + + +
{ e.preventDefault(); this.saveSettings(); }}> - + Video Path - this.setState({videopath: ee.target.value})}/> - + TV Show Path - this.setState({tvshowpath: e.target.value})}/> { this.setState({passwordsupport: !this.state.passwordsupport}) @@ -62,18 +88,18 @@ class GeneralSettings extends React.Component { /> {this.state.passwordsupport ? - + Password - this.setState({password: e.target.value})}/> : null } { this.setState({tmdbsupport: !this.state.tmdbsupport}) @@ -81,10 +107,10 @@ class GeneralSettings extends React.Component { /> { GlobalInfos.enableDarkTheme(!GlobalInfos.isDarkTheme()); @@ -93,13 +119,13 @@ class GeneralSettings extends React.Component { }} /> - + The name of the Mediacenter - this.setState({mediacentername: e.target.value})}/> - @@ -125,7 +151,12 @@ class GeneralSettings extends React.Component { mediacentername: result.mediacenter_name, password: result.password, passwordsupport: result.passwordEnabled, - tmdbsupport: result.TMDB_grabbing + tmdbsupport: result.TMDB_grabbing, + + videonr: result.videonr, + dbsize: result.dbsize, + difftagnr: result.difftagnr, + tagsadded: result.tagsadded }); })); } @@ -142,7 +173,7 @@ class GeneralSettings extends React.Component { updateRequest.append('tvshowpath', this.state.tvshowpath); updateRequest.append('mediacentername', this.state.mediacentername); updateRequest.append("tmdbsupport", this.state.tmdbsupport); - updateRequest.append("darkmodeenabled", GlobalInfos.isDarkTheme()); + updateRequest.append("darkmodeenabled", GlobalInfos.isDarkTheme().toString()); fetch('/api/settings.php', {method: 'POST', body: updateRequest}) .then((response) => response.json() diff --git a/src/pages/SettingsPage/GeneralSettings.module.css b/src/pages/SettingsPage/GeneralSettings.module.css index 2f9cb81..c750cf8 100644 --- a/src/pages/SettingsPage/GeneralSettings.module.css +++ b/src/pages/SettingsPage/GeneralSettings.module.css @@ -1,4 +1,5 @@ .GeneralForm { + margin-top: 55px; width: 60%; } @@ -6,3 +7,16 @@ margin-top: 25px; width: 40%; } + +.infoheader { + display: flex; + flex-wrap: wrap; +} + +/* On screens that are 722px wide or less, make the columns stack on top of each other instead of next to each other */ +@media screen and (max-width: 722px) { + .infoheader { + flex-direction: column; + } +} + diff --git a/src/pages/SettingsPage/GeneralSettings.test.js b/src/pages/SettingsPage/GeneralSettings.test.js index fd675c9..1a66177 100644 --- a/src/pages/SettingsPage/GeneralSettings.test.js +++ b/src/pages/SettingsPage/GeneralSettings.test.js @@ -109,4 +109,9 @@ describe('', function () { wrapper.find("[data-testid='tmdb-switch']").simulate("change"); expect(wrapper.state().tmdbsupport).toBe(false); }); + + it('test insertion of 4 infoheaderitems', function () { + const wrapper = shallow(); + expect(wrapper.find("InfoHeaderItem").length).toBe(4); + }); }); diff --git a/src/pages/SettingsPage/SettingsPage.module.css b/src/pages/SettingsPage/SettingsPage.module.css index 965d459..27af260 100644 --- a/src/pages/SettingsPage/SettingsPage.module.css +++ b/src/pages/SettingsPage/SettingsPage.module.css @@ -2,7 +2,8 @@ border-bottom-right-radius: 10px; border-top-right-radius: 10px; float: left; - min-height: calc(100vh - 62px); + margin-top: 10px; + min-height: calc(100vh - 70px); min-width: 110px; padding-top: 20px; width: 10%;