From 1467c3d003d4e5967a4e9818222e03d4a6f6d2b1 Mon Sep 17 00:00:00 2001 From: deranjer Date: Fri, 19 Jan 2018 19:59:23 -0500 Subject: [PATCH] Closing a file that was left open, working on profiling app for memory leak on Windows --- engine/doneTorrentActions.go | 21 +- engine/engine.go | 1 + .../lib/BackendComm/backendWebsocket.js | 334 ++++++++++++++++++ goTorrentWebUI/lib/BottomMenu/Tabs/fileTab.js | 193 ++++++++++ .../lib/BottomMenu/Tabs/generalTab.js | 325 +++++++++++++++++ goTorrentWebUI/lib/BottomMenu/Tabs/peerTab.js | 96 +++++ goTorrentWebUI/lib/BottomMenu/bottomMenu.js | 183 ++++++++++ .../lib/CustomCells/progressBarCell.js | 80 +++++ .../TopMenu/Modals/RSSModal/RSSFeedList.js | 215 +++++++++++ .../TopMenu/Modals/RSSModal/RSSModalLayout.js | 272 ++++++++++++++ .../TopMenu/Modals/RSSModal/RSSTorrentList.js | 149 ++++++++ .../TopMenu/Modals/RSSModal/addRSSModal.js | 177 ++++++++++ .../lib/TopMenu/Modals/addTorrentFileModal.js | 198 +++++++++++ .../lib/TopMenu/Modals/addTorrentLinkModal.js | 179 ++++++++++ .../lib/TopMenu/Modals/deleteTorrentModal.js | 216 +++++++++++ goTorrentWebUI/lib/TopMenu/topMenu.js | 226 ++++++++++++ goTorrentWebUI/lib/app.js | 159 +++++++++ goTorrentWebUI/lib/leftMenu/leftMenu.js | 257 ++++++++++++++ goTorrentWebUI/lib/store/actions.js | 18 + goTorrentWebUI/lib/store/reducer.js | 159 +++++++++ goTorrentWebUI/lib/torrentlist.js | 212 +++++++++++ main.go | 12 +- 22 files changed, 3667 insertions(+), 15 deletions(-) create mode 100644 goTorrentWebUI/lib/BackendComm/backendWebsocket.js create mode 100644 goTorrentWebUI/lib/BottomMenu/Tabs/fileTab.js create mode 100644 goTorrentWebUI/lib/BottomMenu/Tabs/generalTab.js create mode 100644 goTorrentWebUI/lib/BottomMenu/Tabs/peerTab.js create mode 100644 goTorrentWebUI/lib/BottomMenu/bottomMenu.js create mode 100644 goTorrentWebUI/lib/CustomCells/progressBarCell.js create mode 100644 goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSFeedList.js create mode 100644 goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSModalLayout.js create mode 100644 goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSTorrentList.js create mode 100644 goTorrentWebUI/lib/TopMenu/Modals/RSSModal/addRSSModal.js create mode 100644 goTorrentWebUI/lib/TopMenu/Modals/addTorrentFileModal.js create mode 100644 goTorrentWebUI/lib/TopMenu/Modals/addTorrentLinkModal.js create mode 100644 goTorrentWebUI/lib/TopMenu/Modals/deleteTorrentModal.js create mode 100644 goTorrentWebUI/lib/TopMenu/topMenu.js create mode 100644 goTorrentWebUI/lib/app.js create mode 100644 goTorrentWebUI/lib/leftMenu/leftMenu.js create mode 100644 goTorrentWebUI/lib/store/actions.js create mode 100644 goTorrentWebUI/lib/store/reducer.js create mode 100644 goTorrentWebUI/lib/torrentlist.js diff --git a/engine/doneTorrentActions.go b/engine/doneTorrentActions.go index 26cbddd4..9e49c881 100644 --- a/engine/doneTorrentActions.go +++ b/engine/doneTorrentActions.go @@ -1,7 +1,6 @@ package engine import ( - "fmt" "io" "os" "path/filepath" @@ -40,22 +39,22 @@ func MoveAndLeaveSymlink(config FullClientSettings, singleTorrent *torrent.Torre if oldFileInfo.IsDir() { os.Mkdir(newFilePath, 0644) folderCopy.Copy(oldFilePath, newFilePath) //copy the folder to the new location - notifyUser(tStorage, config, singleTorrent) + notifyUser(tStorage, config, singleTorrent, db) return } - srcFile, err := os.Open(oldFilePath) + defer srcFile.Close() if err != nil { Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "error": err}).Error("Windows: Cannot open old file for copy") return } - defer srcFile.Close() destFile, err := os.Create(newFilePath) + defer destFile.Close() if err != nil { Logger.WithFields(logrus.Fields{"New File Path": newFilePath, "error": err}).Error("Windows: Cannot open new file for copying into") return } - defer destFile.Close() + bytesWritten, err := io.Copy(destFile, srcFile) if err != nil { Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "error": err}).Error("Windows: Cannot copy old file into new") @@ -66,23 +65,23 @@ func MoveAndLeaveSymlink(config FullClientSettings, singleTorrent *torrent.Torre Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "error": err}).Error("Windows: Error syncing new file to disk") } Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "bytesWritten": bytesWritten}).Info("Windows Torrent Copy Completed") - notifyUser(tStorage, config, singleTorrent) + notifyUser(tStorage, config, singleTorrent, db) } else { err := os.Symlink(oldFilePath, newFilePath) //For all other OS's create a symlink if err != nil { Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "error": err}).Error("Error creating symlink") return } - notifyUser(tStorage, config, singleTorrent) + notifyUser(tStorage, config, singleTorrent, db) Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath}).Info("Moving completed torrent") } } - tStorage.TorrentMoved = true - Storage.AddTorrentLocalStorage(db, tStorage) //Updating the fact that we moved the torrent + } -func notifyUser(tStorage Storage.TorrentLocal, config FullClientSettings, singleTorrent *torrent.Torrent) { - fmt.Println("Pushbullet token", config.PushBulletToken) +func notifyUser(tStorage Storage.TorrentLocal, config FullClientSettings, singleTorrent *torrent.Torrent, db *storm.DB) { + tStorage.TorrentMoved = true + Storage.AddTorrentLocalStorage(db, tStorage) //Updating the fact that we moved the torrent if config.PushBulletToken != "" { pb := pushbullet.New(config.PushBulletToken) n := requests.NewNote() diff --git a/engine/engine.go b/engine/engine.go index 1c20b474..78a62d35 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -85,6 +85,7 @@ func readTorrentFileFromDB(element *Storage.TorrentLocal, tclient *torrent.Clien if err != nil { Logger.WithFields(logrus.Fields{"tempfile": tempFile, "err": err}).Error("Unable to create tempfile") } + defer tempFile.Close() //Todo.. if we remove this do we need to close it? defer os.Remove(tempFile.Name()) if _, err := tempFile.Write(element.TorrentFile); err != nil { //writing out out the entire file back into the temp dir from boltdb Logger.WithFields(logrus.Fields{"tempfile": tempFile, "err": err}).Error("Unable to write to tempfile") diff --git a/goTorrentWebUI/lib/BackendComm/backendWebsocket.js b/goTorrentWebUI/lib/BackendComm/backendWebsocket.js new file mode 100644 index 00000000..e2d3169d --- /dev/null +++ b/goTorrentWebUI/lib/BackendComm/backendWebsocket.js @@ -0,0 +1,334 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _reactTooltip = require('react-tooltip'); + +var _reactTooltip2 = _interopRequireDefault(_reactTooltip); + +var _InfoOutline = require('material-ui-icons/InfoOutline'); + +var _InfoOutline2 = _interopRequireDefault(_InfoOutline); + +var _reactRedux = require('react-redux'); + +var _actions = require('../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +var _Select = require('material-ui/Select/Select'); + +var _Select2 = _interopRequireDefault(_Select); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var title = document.title; //Set the number of active torrents in the title +var torrents = []; +var peerList = []; +var fileList = []; +var RSSList = []; +var RSSTorrentList = []; + +var torrentListRequest = { + messageType: "torrentListRequest" + + //websocket is started in kickwebsocket.js and is picked up here so "ws" is already defined 22 +};ws.onmessage = function (evt) { + //When we recieve a message from the websocket + var serverMessage = JSON.parse(evt.data); + //console.log("message", serverMessage.MessageType) + switch (serverMessage.MessageType) { + + case "torrentList": + //console.log("Recieved Client Update...", serverMessage) + //var serverMessage = JSON.parse(evt.data); + + torrents = []; //clearing out the torrent array to make room for new (so that it does keep adding) + for (var i = 0; i < serverMessage.total; i++) { + var _torrents$push; + + torrents.push((_torrents$push = { + TorrentHashString: serverMessage.data[i].TorrentHashString, + TorrentName: serverMessage.data[i].TorrentName, + DownloadedSize: serverMessage.data[i].DownloadedSize, + Size: serverMessage.data[i].Size, + DownloadSpeed: serverMessage.data[i].DownloadSpeed, + UploadSpeed: serverMessage.data[i].UploadSpeed, + PercentDone: serverMessage.data[i].PercentDone, + StoragePath: serverMessage.data[i].StoragePath, + DateAdded: serverMessage.data[i].DateAdded, + SourceType: serverMessage.data[i].SourceType, + Status: serverMessage.data[i].Status, + BytesCompleted: serverMessage.data[i].BytesCompleted, + ActivePeers: serverMessage.data[i].ActivePeers, + ETA: serverMessage.data[i].ETA, + TotalUploadedSize: serverMessage.data[i].TotalUploadedSize, + Ratio: serverMessage.data[i].UploadRatio + }, _defineProperty(_torrents$push, 'DateAdded', serverMessage.data[i].DateAdded), _defineProperty(_torrents$push, 'FileNumber', serverMessage.data[i].NumberofFiles), _defineProperty(_torrents$push, 'PieceNumber', serverMessage.data[i].NumberofPieces), _defineProperty(_torrents$push, 'MaxConnections', serverMessage.data[i].MaxConnections), _torrents$push)); + } + var newTitle = '(' + serverMessage.total + ')' + title; //updating the title + document.title = newTitle; + break; + + case "torrentPeerList": + peerList = []; //clearing out the peerlist array to make room for new (so that it does keep adding) + + for (var i = 0; i < serverMessage.TotalPeers; i++) { + peerList.push({ + PeerID: serverMessage.PeerList[i].Id.toString(), + IP: serverMessage.PeerList[i].IP, + Port: serverMessage.PeerList[i].Port, + Source: serverMessage.PeerList[i].Source, + SupportsEncryption: serverMessage.PeerList[i].SupportsEncryption.toString() + }); + } + break; + + case "torrentFileList": + fileList = []; + for (var i = 0; i < serverMessage.TotalFiles; i++) { + fileList.push({ + FileName: serverMessage.FileList[i].FileName, + FilePath: serverMessage.FileList[i].FilePath, + FileSize: serverMessage.FileList[i].FileSize, + FilePercent: serverMessage.FileList[i].FilePercent, + FilePriority: serverMessage.FileList[i].FilePriority + }); + } + console.log("filelist", fileList); + break; + + case "speedTab": + console.log("Speedtab data requested"); + break; + + case "loggerData": + console.log("Logger data requested"); + break; + + case "rssListRequest": + console.log("RSSListRequest recieved", evt.data); + RSSList = []; + for (var i = 0; i < serverMessage.TotalRSSFeeds; i++) { + RSSList.push({ + RSSURL: serverMessage.RSSFeeds[i].RSSFeedURL, + RSSName: serverMessage.RSSFeeds[i].RSSName + }); + } + console.log("RSSURLS", RSSList); + console.log("FIRSTURL", RSSList[1]); + console.log("FULLURL", RSSList[1].RSSURL); + break; + + case "rssTorrentList": + //console.log("RSSTorrentList recieved", evt.data) + RSSTorrentList = []; + for (var i = 0; i < serverMessage.TotalTorrents; i++) { + RSSTorrentList.push({ + TorrentName: serverMessage.Torrents[i].Title, + TorrentLink: serverMessage.Torrents[i].Link, + PublishDate: serverMessage.Torrents[i].PubDate + }); + } + } +}; + +ws.onclose = function () { + console.log('Closing connection'); +}; + +var divStyle = { + display: 'inline-block', + paddingTop: '10px', + paddingLeft: '10px' +}; + +var buttonStyle = { + fontSize: '60px' +}; + +var BackendSocket = function (_React$Component) { + _inherits(BackendSocket, _React$Component); + + function BackendSocket() { + var _ref; + + var _temp, _this, _ret; + + _classCallCheck(this, BackendSocket); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = BackendSocket.__proto__ || Object.getPrototypeOf(BackendSocket)).call.apply(_ref, [this].concat(args))), _this), _this.selectionHandler = function (selectionHashes, selectedTab) { + switch (selectedTab) { + case 0: + console.log("general tab information requested"); + break; + case 1: + var peerListHashes = { + MessageType: "torrentPeerListRequest", + Payload: selectionHashes + }; + console.log("Peers tab information requested", peerListHashes); + ws.send(JSON.stringify(peerListHashes)); + break; + case 2: + var fileListHashes = { + MessageType: "torrentFileListRequest", + Payload: selectionHashes + }; + console.log("Files tab information requested", fileListHashes); + ws.send(JSON.stringify(fileListHashes)); + break; + case 3: + console.log("Speed tab information requested"); + break; + case 4: + console.log("Logger tab information requested"); + break; + default: + console.log("default tab"); + break; + } + }, _this.testSelectionLength = function (selection) { + if (nextProps.selectionHashes.length > 1) { + return true; + } + return false; + }, _temp), _possibleConstructorReturn(_this, _ret); + } + + _createClass(BackendSocket, [{ + key: 'componentDidMount', + value: function componentDidMount() { + var _this2 = this; + + this.timerID = setInterval(function () { + return _this2.tick(); + }, 2000); + } + }, { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + clearInterval(this.timerID); + } + }, { + key: 'tick', + value: function tick() { + // this tick is the main tick that updates ALL of the components that update on tick... which is a lot + if (this.props.RSSList != RSSList & this.props.RSSModalOpen == true) { + this.props.newRSSFeedStore(RSSList); //pushing the new RSSList to Redux + } + if (this.props.RSSTorrentList != RSSTorrentList & this.props.RSSModalOpen == true) { + this.props.RSSTorrentList(RSSTorrentList); //pushing the new RSSTorrentList to Redux + } + + ws.send(JSON.stringify(torrentListRequest)); //talking to the server to get the torrent list + //console.log("Torrentlist", torrents) + this.props.setButtonState(this.props.selection); //forcing an update to the buttons + this.props.newTorrentList(torrents); //sending the list of torrents to torrentlist.js + if (this.props.selectionHashes.length === 1) { + switch (this.props.selectedTab) { + case 1: + var peerListHashes = { + MessageType: "torrentPeerListRequest", + Payload: this.props.selectionHashes + }; + ws.send(JSON.stringify(peerListHashes)); + this.props.newPeerList(peerList); + break; + case 2: + var fileListHashes = { + MessageType: "torrentFileListRequest", + Payload: this.props.selectionHashes + }; + ws.send(JSON.stringify(fileListHashes)); + this.props.newFileList(fileList); + break; + + } + } + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + console.log("Lenght", nextProps.selectionHashes.length, "value", nextProps.selectionHashes); + if (nextProps.selectionHashes.length === 1) { + //if we have a selection pass it on for the tabs to verify + this.selectionHandler(nextProps.selectionHashes, nextProps.selectedTab); + } + } + }, { + key: 'render', + value: function render() { + return _react2.default.createElement( + 'div', + { style: divStyle }, + _react2.default.createElement(_InfoOutline2.default, { styles: buttonStyle, color: 'primary', 'data-tip': 'BackendStatus: Green=Good', 'aria-label': 'Settings' }) + ); + } + }]); + + return BackendSocket; +}(_react2.default.Component); + +var mapStateToProps = function mapStateToProps(state) { + return { + selectionHashes: state.selectionHashes, + selectedTab: state.selectedTab, + selection: state.selection, + RSSModalOpen: state.RSSModalOpen, + RSSTorrentList: state.RSSTorrentList + }; +}; + +var mapDispatchToProps = function mapDispatchToProps(dispatch) { + return { + newTorrentList: function newTorrentList(torrentList) { + return dispatch({ type: actionTypes.TORRENT_LIST, torrentList: torrentList }); + }, + newPeerList: function newPeerList(peerList) { + return dispatch({ type: actionTypes.PEER_LIST, peerList: peerList }); + }, + newFileList: function newFileList(fileList) { + return dispatch({ type: actionTypes.FILE_LIST, fileList: fileList }); + }, + setButtonState: function setButtonState(buttonState) { + return dispatch({ type: actionTypes.SET_BUTTON_STATE, buttonState: buttonState }); + }, + newRSSFeedStore: function newRSSFeedStore(RSSList) { + return dispatch({ type: actionTypes.NEW_RSS_FEED_STORE, RSSList: RSSList }); + }, + RSSTorrentList: function RSSTorrentList(_RSSTorrentList) { + return dispatch({ type: actionTypes.RSS_TORRENT_LIST, RSSTorrentList: _RSSTorrentList }); + } + //changeSelection: (selection) => dispatch({type: actionTypes.CHANGE_SELECTION, selection}),//forcing an update to the buttons + + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(BackendSocket); \ No newline at end of file diff --git a/goTorrentWebUI/lib/BottomMenu/Tabs/fileTab.js b/goTorrentWebUI/lib/BottomMenu/Tabs/fileTab.js new file mode 100644 index 00000000..b68f194d --- /dev/null +++ b/goTorrentWebUI/lib/BottomMenu/Tabs/fileTab.js @@ -0,0 +1,193 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _Button = require('material-ui/Button'); + +var _Button2 = _interopRequireDefault(_Button); + +var _progressBarCell = require('../../CustomCells/progressBarCell'); + +var _dxReactGrid = require('@devexpress/dx-react-grid'); + +var _dxReactGridMaterialUi = require('@devexpress/dx-react-grid-material-ui'); + +var _reactRedux = require('react-redux'); + +var _actions = require('../../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var FileTab = function (_React$Component) { + _inherits(FileTab, _React$Component); + + function FileTab(props) { + _classCallCheck(this, FileTab); + + var _this = _possibleConstructorReturn(this, (FileTab.__proto__ || Object.getPrototypeOf(FileTab)).call(this, props)); + + _this.changeSelection = function (selection) { + console.log("Filelist is changing selection now", selection); + _this.setState({ selected: selection }); + if (selection.length > 0) { + //if selection is empty buttons will be default and selectionHashes will be blanked out and pushed to redux + console.log("Getting the selected Rows"); + var selectedRows = []; //array of all the selected Rows + selection.forEach(function (element) { + selectedRows.push(_this.props.fileList[element]); //pushing the selected rows out of torrentlist + }); + _this.setState({ fileSelection: selectedRows }); + } + }; + + _this.sendPriorityRequest = function (priority, sendfileNames) { + _this.state.fileSelection.forEach(function (element) { + console.log("element", element); + sendFileNames.push(element.FilePath); + }); + var setFilePriority = { + MessageType: "setFilePriority", + Payload: sendFileNames + }; + console.log(JSON.stringify(setFilePriority)); + ws.send(JSON.stringify(setFilePriority)); + }; + + _this.setHighPriority = function () { + var priorty = "High"; + var selectionHash = _this.props.selectionHashes[0]; //getting the first element (should be the only one) + var sendFileNames = [selectionHash, "High"]; // adding the selection hash as the first element will be stripped out by the server, second element is the prioty request + }; + + _this.setNormalPriority = function () { + var priorty = "Normal"; + var selectionHash = _this.props.selectionHashes[0]; //getting the first element (should be the only one) + var sendFileNames = [selectionHash, "Normal"]; // adding the selection hash as the first element will be stripped out by the server, second element is the prioty request + }; + + _this.setCancelPriority = function () { + var priorty = "Cancel"; + var selectionHash = _this.props.selectionHashes[0]; //getting the first element (should be the only one) + var sendFileNames = [selectionHash, "Cancel"]; // adding the selection hash as the first element will be stripped out by the server, second element is the prioty request + }; + + _this.state = { //rows are stored in redux they are sent over from the server + columns: [{ name: 'FileName', title: 'File Name' }, { name: 'FilePath', title: 'File Path' }, { name: 'FileSize', title: 'File Size' }, { name: 'FilePercent', title: 'File Percent' }, { name: 'FilePriority', title: 'File Priority' }], + sorting: [], + columnOrder: ['FileName', 'FilePath', 'FileSize', 'FilePercent', 'FilePriority'], + columnWidths: { FileName: 450, FilePath: 650, FileSize: 100, FilePercent: 100, FilePriority: 75 }, + fileSelection: [], + selected: [] + + }; + + _this.changeColumnOrder = function (columnOrder) { + return _this.setState({ columnOrder: columnOrder }); + }; + _this.changeColumnWidths = function (columnWidths) { + return _this.setState({ columnWidths: columnWidths }); + }; + _this.changeSorting = function (sorting) { + return _this.setState({ sorting: sorting }); + }; + + return _this; + } + + _createClass(FileTab, [{ + key: 'render', + value: function render() { + return ( + //Buttons here + _react2.default.createElement( + 'div', + null, + 'Set File Priority:', + _react2.default.createElement( + _Button2.default, + { raised: true, color: 'primary', onClick: this.setHighPriority }, + 'High' + ), + _react2.default.createElement( + _Button2.default, + { raised: true, color: 'primary', onClick: this.setNormalPriority }, + 'Normal' + ), + _react2.default.createElement( + _Button2.default, + { raised: true, color: 'accent', onClick: this.setCancelPriority }, + 'Do Not Download' + ), + _react2.default.createElement( + _dxReactGridMaterialUi.Grid, + { rows: this.props.fileList, columns: this.state.columns }, + _react2.default.createElement(_dxReactGrid.SortingState, { sorting: this.state.sorting, onSortingChange: this.changeSorting }), + _react2.default.createElement(_dxReactGrid.LocalSorting, null), + _react2.default.createElement(_dxReactGridMaterialUi.DragDropContext, null), + _react2.default.createElement(_dxReactGrid.SelectionState, { onSelectionChange: this.changeSelection, selection: this.state.selection }), + _react2.default.createElement(_dxReactGridMaterialUi.VirtualTableView, { height: 300, tableCellTemplate: function tableCellTemplate(_ref) { + var row = _ref.row, + column = _ref.column, + style = _ref.style; + + if (column.name === 'FilePercent') { + return _react2.default.createElement(_progressBarCell.ProgressBarCell, { value: row.FilePercent * 100, style: style }); + } + return undefined; + } }), + '/>', + _react2.default.createElement(_dxReactGridMaterialUi.TableColumnResizing, { columnWidths: this.state.columnWidths, onColumnWidthsChange: this.changeColumnWidths }), + _react2.default.createElement(_dxReactGridMaterialUi.TableColumnReordering, { order: this.state.columnOrder, onOrderChange: this.changeColumnOrder }), + _react2.default.createElement(_dxReactGridMaterialUi.TableSelection, { selectByRowClick: true, highlightSelected: true }), + _react2.default.createElement(_dxReactGridMaterialUi.TableHeaderRow, { allowSorting: true, allowResizing: true, allowDragging: true }) + ) + ) + ); + } + }]); + + return FileTab; +}(_react2.default.Component); + +var mapStateToProps = function mapStateToProps(state) { + return { + selectionHashes: state.selectionHashes, + fileList: state.fileList + //fileSelectionNames: state.fileSelectionNames, + }; +}; + +var mapDispatchToProps = function mapDispatchToProps(dispatch) { + return { + + //changeFileSelection: (fileSelection) => dispatch({type: actionTypes.CHANGE_FILE_SELECTION, fileSelection}), + + sendSelectionHashes: function sendSelectionHashes(selectionHashes) { + return dispatch({ type: actionTypes.SELECTION_HASHES, selectionHashes: selectionHashes }); + } + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(FileTab); \ No newline at end of file diff --git a/goTorrentWebUI/lib/BottomMenu/Tabs/generalTab.js b/goTorrentWebUI/lib/BottomMenu/Tabs/generalTab.js new file mode 100644 index 00000000..d2a8950e --- /dev/null +++ b/goTorrentWebUI/lib/BottomMenu/Tabs/generalTab.js @@ -0,0 +1,325 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _styles = require('material-ui/styles'); + +var _Paper = require('material-ui/Paper'); + +var _Paper2 = _interopRequireDefault(_Paper); + +var _Grid = require('material-ui/Grid'); + +var _Grid2 = _interopRequireDefault(_Grid); + +var _reactRedux = require('react-redux'); + +var _actions = require('../../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var styles = function styles(theme) { + return { + root: { + flexGrow: 1, + marginTop: 0 + }, + paper: { + padding: 16, + textAlign: 'left', + color: theme.palette.text.primary + }, + floatRight: { + float: 'right' + } + }; +}; + +var GeneralTab = function (_React$Component) { + _inherits(GeneralTab, _React$Component); + + function GeneralTab(props) { + _classCallCheck(this, GeneralTab); + + var _this = _possibleConstructorReturn(this, (GeneralTab.__proto__ || Object.getPrototypeOf(GeneralTab)).call(this, props)); + + _this.componentWillReceiveProps = function () { + //console.log("recieving props in generaltab", "TYPE", this.props.selectionHashes[Object.keys(this.props.selectionHashes)[0]]) + if (_this.props.selectionHashes.length === 1) { + //if one torrent is selected + var selectionHashTemp = _this.props.selectionHashes[Object.keys(_this.props.selectionHashes)[0]]; // extract out the hash of the single selection + var selectedTorrentTemp = []; + _this.props.torrentList.forEach(function (singleTorrent) { + if (singleTorrent.TorrentHashString === selectionHashTemp) { + selectedTorrentTemp = singleTorrent; + } + }); + //selectedTorrentTemp = this.props.torrentList.filter(torrent => torrent.TorrentHashString === this.props.selectionHashes) + //console.log("SelectedTorrentTemp", selectedTorrentTemp) + _this.setState({ selectedTorrent: selectedTorrentTemp }); + } else { + _this.setState({ selectedTorrent: [] }); + } + }; + + _this.state = { + selectedTorrent: [] + }; + + return _this; + } + + _createClass(GeneralTab, [{ + key: 'render', + value: function render() { + var classes = this.props.classes; + + return _react2.default.createElement( + 'div', + { className: classes.root }, + _react2.default.createElement( + _Grid2.default, + { container: true, spacing: 8 }, + _react2.default.createElement( + _Grid2.default, + { item: true, xs: 12, sm: 4 }, + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Torrent Name: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["TorrentName"], + ' ' + ) + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Torrent Size: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["Size"], + ' ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Storage Path: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["StoragePath"], + ' ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Date Added: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + ' ', + this.state.selectedTorrent["DateAdded"], + ' ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Source Type: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + ' ', + this.state.selectedTorrent["SourceType"], + ' ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Label: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + ' None ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Torrent Hash: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + ' ', + this.state.selectedTorrent["TorrentHashString"], + ' ' + ), + ' ' + ) + ), + _react2.default.createElement( + _Grid2.default, + { item: true, xs: 12, sm: 4 }, + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Status: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["Status"], + ' ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Percent Done: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["PercentDone"], + ' ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Torrent DL Amount: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["DownloadedSize"], + ' ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Total Upload Amount: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["TotalUploadedSize"], + ' ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Seeding Ratio: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["Ratio"], + ' ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'ETA: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["ETA"], + ' ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Max Connections: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["MaxConnections"], + ' ' + ), + ' ' + ) + ), + _react2.default.createElement( + _Grid2.default, + { item: true, xs: 12, sm: 4 }, + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Number of Files: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["FileNumber"], + ' ' + ), + ' ' + ), + _react2.default.createElement( + _Paper2.default, + { className: classes.paper }, + 'Number of Pieces: ', + _react2.default.createElement( + 'span', + { className: classes.floatRight }, + this.state.selectedTorrent["PieceNumber"], + ' ' + ), + ' ' + ) + ) + ) + ); + } + }]); + + return GeneralTab; +}(_react2.default.Component); + +var mapStateToProps = function mapStateToProps(state) { + return { + selectionHashes: state.selectionHashes, + torrentList: state.torrentList + }; +}; + +exports.default = (0, _styles.withStyles)(styles)((0, _reactRedux.connect)(mapStateToProps)(GeneralTab)); \ No newline at end of file diff --git a/goTorrentWebUI/lib/BottomMenu/Tabs/peerTab.js b/goTorrentWebUI/lib/BottomMenu/Tabs/peerTab.js new file mode 100644 index 00000000..dd3b8dee --- /dev/null +++ b/goTorrentWebUI/lib/BottomMenu/Tabs/peerTab.js @@ -0,0 +1,96 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _reactBootstrapTable = require('react-bootstrap-table'); + +var _dxReactGrid = require('@devexpress/dx-react-grid'); + +var _dxReactGridMaterialUi = require('@devexpress/dx-react-grid-material-ui'); + +var _reactRedux = require('react-redux'); + +var _actions = require('../../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var PeerTab = function (_React$Component) { + _inherits(PeerTab, _React$Component); + + function PeerTab(props) { + _classCallCheck(this, PeerTab); + + var _this = _possibleConstructorReturn(this, (PeerTab.__proto__ || Object.getPrototypeOf(PeerTab)).call(this, props)); + + _this.state = { //rows are stored in redux they are sent over from the server + columns: [{ name: 'PeerID', title: 'Peer ID' }, { name: 'IP', title: 'IP Address' }, + //{ name: 'Country', title: 'Country of Origin'}, //TODO map IP to country + { name: 'Port', title: 'Port' }, { name: 'Source', title: 'Source' }, //T=Tracker, I=Incoming, Hg=DHTGetPeers, Ha=DHTAnnouncePeer, X=PEX + { name: 'SupportsEncryption', title: 'Supports Encryption' }], + sorting: [], + columnOrder: ['PeerID', 'IP', 'Port', 'Source', 'SupportsEncryption'], + columnWidths: { PeerID: 250, IP: 150, Port: 100, Source: 150, SupportsEncryption: 150 } + }; + + _this.changeColumnOrder = function (columnOrder) { + return _this.setState({ columnOrder: columnOrder }); + }; + _this.changeColumnWidths = function (columnWidths) { + return _this.setState({ columnWidths: columnWidths }); + }; + _this.changeSorting = function (sorting) { + return _this.setState({ sorting: sorting }); + }; + return _this; + } + + _createClass(PeerTab, [{ + key: 'render', + value: function render() { + return _react2.default.createElement( + _dxReactGridMaterialUi.Grid, + { rows: this.props.peerList, columns: this.state.columns }, + _react2.default.createElement(_dxReactGrid.SortingState, { sorting: this.state.sorting, onSortingChange: this.changeSorting }), + _react2.default.createElement(_dxReactGrid.LocalSorting, null), + _react2.default.createElement(_dxReactGridMaterialUi.DragDropContext, null), + _react2.default.createElement(_dxReactGridMaterialUi.VirtualTableView, { height: 350 }), + _react2.default.createElement(_dxReactGridMaterialUi.TableColumnResizing, { columnWidths: this.state.columnWidths, onColumnWidthsChange: this.changeColumnWidths }), + _react2.default.createElement(_dxReactGridMaterialUi.TableColumnReordering, { order: this.state.columnOrder, onOrderChange: this.changeColumnOrder }), + _react2.default.createElement(_dxReactGridMaterialUi.TableHeaderRow, { allowSorting: true, allowResizing: true, allowDragging: true }) + ); + } + }]); + + return PeerTab; +}(_react2.default.Component); + +var mapStateToProps = function mapStateToProps(state) { + return { + selectionHashes: state.selectionHashes, + peerList: state.peerList + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps)(PeerTab); \ No newline at end of file diff --git a/goTorrentWebUI/lib/BottomMenu/bottomMenu.js b/goTorrentWebUI/lib/BottomMenu/bottomMenu.js new file mode 100644 index 00000000..6d04f9f3 --- /dev/null +++ b/goTorrentWebUI/lib/BottomMenu/bottomMenu.js @@ -0,0 +1,183 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +require('typeface-roboto'); + +var _styles = require('material-ui/styles'); + +var _AppBar = require('material-ui/AppBar'); + +var _AppBar2 = _interopRequireDefault(_AppBar); + +var _Tabs = require('material-ui/Tabs'); + +var _Tabs2 = _interopRequireDefault(_Tabs); + +var _generalTab = require('./Tabs/generalTab'); + +var _generalTab2 = _interopRequireDefault(_generalTab); + +var _peerTab = require('./Tabs/peerTab'); + +var _peerTab2 = _interopRequireDefault(_peerTab); + +var _fileTab = require('./Tabs/fileTab'); + +var _fileTab2 = _interopRequireDefault(_fileTab); + +var _reactRedux = require('react-redux'); + +var _actions = require('../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // contains the font for material UI + + +//Redux + + +function TabContainer(props) { + return _react2.default.createElement( + 'div', + { style: { padding: 8 * 3 } }, + props.children + ); +} + +TabContainer.propTypes = { + children: _propTypes2.default.node.isRequired +}; + +var styles = function styles(theme) { + return { + root: { + // flexGrow: 1, + // marginTop: theme.spacing.unit * 3, + //backgroundColor: theme.palette.background.paper, + backgroundColor: '#e5e5e5', + height: '100%', + boxShadow: '0 0 20px #000' + } + }; +}; + +var BasicTabs = function (_React$Component) { + _inherits(BasicTabs, _React$Component); + + function BasicTabs() { + var _ref; + + var _temp, _this, _ret; + + _classCallCheck(this, BasicTabs); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = BasicTabs.__proto__ || Object.getPrototypeOf(BasicTabs)).call.apply(_ref, [this].concat(args))), _this), _this.handleChange = function (event, value) { + //this.setState({ value }); + _this.props.changeTab(value); + }, _temp), _possibleConstructorReturn(_this, _ret); + } + + _createClass(BasicTabs, [{ + key: 'render', + value: function render() { + var classes = this.props.classes; + + + return _react2.default.createElement( + 'div', + { className: classes.root }, + _react2.default.createElement( + 'div', + { className: 'DragHandle' }, + ' ', + _react2.default.createElement( + _AppBar2.default, + { position: 'static' }, + _react2.default.createElement( + _Tabs2.default, + { value: this.props.selectedTab, onChange: this.handleChange }, + _react2.default.createElement(_Tabs.Tab, { label: 'General' }), + _react2.default.createElement(_Tabs.Tab, { label: 'Peers' }), + _react2.default.createElement(_Tabs.Tab, { label: 'Files' }), + _react2.default.createElement(_Tabs.Tab, { label: 'Speed' }), + _react2.default.createElement(_Tabs.Tab, { label: 'Logger', href: '#basic-tabs' }) + ) + ) + ), + this.props.selectedTab === 0 && _react2.default.createElement( + TabContainer, + null, + _react2.default.createElement(_generalTab2.default, null) + ), + this.props.selectedTab === 1 && _react2.default.createElement( + TabContainer, + null, + _react2.default.createElement(_peerTab2.default, null) + ), + this.props.selectedTab === 2 && _react2.default.createElement( + TabContainer, + null, + _react2.default.createElement(_fileTab2.default, null) + ), + this.props.selectedTab === 3 && _react2.default.createElement( + TabContainer, + null, + 'Speed' + ), + this.props.selectedTab === 4 && _react2.default.createElement( + TabContainer, + null, + 'Logger' + ) + ); + } + }]); + + return BasicTabs; +}(_react2.default.Component); + +BasicTabs.propTypes = { + classes: _propTypes2.default.object.isRequired +}; + +var mapStateToProps = function mapStateToProps(state) { + return { + selectedTab: state.selectedTab + }; +}; + +var mapDispatchToProps = function mapDispatchToProps(dispatch) { + return { + changeTab: function changeTab(selectedTab) { + return dispatch({ type: actionTypes.SELECTED_TAB, selectedTab: selectedTab }); + } + }; +}; + +exports.default = (0, _styles.withStyles)(styles)((0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(BasicTabs)); \ No newline at end of file diff --git a/goTorrentWebUI/lib/CustomCells/progressBarCell.js b/goTorrentWebUI/lib/CustomCells/progressBarCell.js new file mode 100644 index 00000000..6f5addbc --- /dev/null +++ b/goTorrentWebUI/lib/CustomCells/progressBarCell.js @@ -0,0 +1,80 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ProgressBarCell = exports.ProgressBarCellBase = undefined; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _materialUi = require('material-ui'); + +var _styles = require('material-ui/styles'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var styles = function styles(theme) { + var _progressText; + + return { + progressBarCell: { + paddingLeft: theme.spacing.unit, + paddingRight: theme.spacing.unit, + borderBottom: '1px solid ' + theme.palette.text.lightDivider + }, + progressBar: { + backgroundColor: theme.palette.primary[300], + float: 'left', + height: theme.spacing.unit, + whiteSpace: 'nowrap' + }, + progressText: (_progressText = { + display: 'inline-block', + fontSize: '1em', + textAlign: 'right', + verticalAlign: 'text-top' + }, _defineProperty(_progressText, 'fontSize', '12px'), _defineProperty(_progressText, 'fontWeight', 'bold'), _defineProperty(_progressText, 'margin', '5px'), _defineProperty(_progressText, 'whiteSpace', 'nowrap'), _progressText) + }; +}; + +var ProgressBarCellBase = exports.ProgressBarCellBase = function ProgressBarCellBase(_ref) { + var value = _ref.value, + classes = _ref.classes, + style = _ref.style; + return _react2.default.createElement( + _materialUi.TableCell, + { + className: classes.progressBarCell, + style: style + + }, + _react2.default.createElement('div', { + className: classes.progressBar, + style: { width: value + '%' }, + title: value.toFixed(1) + '%' + }), + _react2.default.createElement( + 'div', + { className: classes.progressText }, + value + ) + ); +}; +ProgressBarCellBase.propTypes = { + value: _propTypes2.default.number.isRequired, + classes: _propTypes2.default.object.isRequired, + style: _propTypes2.default.object +}; +ProgressBarCellBase.defaultProps = { + style: {} +}; + +var ProgressBarCell = exports.ProgressBarCell = (0, _styles.withStyles)(styles, { name: 'ProgressBarCell' })(ProgressBarCellBase); \ No newline at end of file diff --git a/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSFeedList.js b/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSFeedList.js new file mode 100644 index 00000000..5aecf493 --- /dev/null +++ b/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSFeedList.js @@ -0,0 +1,215 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _Button = require('material-ui/Button'); + +var _Button2 = _interopRequireDefault(_Button); + +var _TextField = require('material-ui/TextField'); + +var _TextField2 = _interopRequireDefault(_TextField); + +var _styles = require('material-ui/styles'); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _List = require('material-ui/List'); + +var _List2 = _interopRequireDefault(_List); + +var _Dialog = require('material-ui/Dialog'); + +var _Dialog2 = _interopRequireDefault(_Dialog); + +var _Link = require('material-ui-icons/Link'); + +var _Link2 = _interopRequireDefault(_Link); + +var _reactTooltip = require('react-tooltip'); + +var _reactTooltip2 = _interopRequireDefault(_reactTooltip); + +var _Icon = require('material-ui/Icon'); + +var _Icon2 = _interopRequireDefault(_Icon); + +var _IconButton = require('material-ui/IconButton'); + +var _IconButton2 = _interopRequireDefault(_IconButton); + +var _RssFeed = require('material-ui-icons/RssFeed'); + +var _RssFeed2 = _interopRequireDefault(_RssFeed); + +var _AddCircle = require('material-ui-icons/AddCircle'); + +var _AddCircle2 = _interopRequireDefault(_AddCircle); + +var _Delete = require('material-ui-icons/Delete'); + +var _Delete2 = _interopRequireDefault(_Delete); + +var _reactRedux = require('react-redux'); + +var _actions = require('../../../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +//Redux + + +var button = { + fontSize: '60px', + paddingRight: '20px', + paddingLeft: '20px' +}; + +var smallButton = { + width: '36px', + height: '36px', + padding: '5px' +}; + +var rssInput = { + width: '90%', + paddingRight: '10px' +}; + +var inlineStyle = { + display: 'inline-block', + backdrop: 'static' +}; + +var RSSFeedList = function (_React$Component) { + _inherits(RSSFeedList, _React$Component); + + function RSSFeedList() { + var _ref; + + var _temp, _this, _ret; + + _classCallCheck(this, RSSFeedList); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = RSSFeedList.__proto__ || Object.getPrototypeOf(RSSFeedList)).call.apply(_ref, [this].concat(args))), _this), _this.state = { + testRSSFeeds: [], + showList: false, + selectedIndex: 0 + }, _this.showRSSFiles = function (key) { + var RSSTorrentsRequest = { + messageType: "rssTorrentsRequest", + Payload: [_this.props.RSSList[key].RSSURL] + }; + ws.send(JSON.stringify(RSSTorrentsRequest)); + + _this.setState({ selectedIndex: key }); //setting our selected index for styling + console.log("RSSFEED", key, "sending message", JSON.stringify(RSSTorrentsRequest)); + }, _this.getStyle = function (index) { + console.log("SettingStye", selectedIndex, index); + if (selectedIndex == index) { + console.log("Returning activestyle"); + style = "{{backgroundColor: '#80b3ff'}}"; + return style; + } + style = "{{backgroundColor: '#f44295'}}"; + return style; + }, _this.deleteRSSFeed = function (key) { + var RSSURLDelete = { + messageType: "deleteRSSFeed", + Payload: [_this.props.RSSList[key]] + }; + console.log("Deleting THIS", _this.props.RSSList[key]); + //ws.send(JSON.stringify(RSSURLDelete)); + }, _temp), _possibleConstructorReturn(_this, _ret); + } + + _createClass(RSSFeedList, [{ + key: 'render', + value: function render() { + var _this2 = this; + + //const { classes, onRequestClose, handleRequestClose, handleSubmit } = this.props; + if (this.props.RSSList.length > 0 && this.state.showList == false) { + console.log("Setting list to show...."); + this.setState({ showList: true }); + } + + return _react2.default.createElement( + 'div', + { style: inlineStyle }, + this.state.showList == true && //if we have any rss torrent feeds then display them in list } + _react2.default.createElement( + _List2.default, + { dense: true }, + this.props.RSSList.map(function (RSSFeed, index) { + return _react2.default.createElement( + _List.ListItem, + { button: true, onClick: function onClick() { + return _this2.showRSSFiles(index); + }, key: index }, + _react2.default.createElement(_List.ListItemText, { primary: RSSFeed.RSSName }), + _react2.default.createElement( + _List.ListItemSecondaryAction, + null, + _react2.default.createElement( + _IconButton2.default, + { key: index, onClick: function onClick() { + return _this2.deleteRSSFeed(index); + }, 'aria-label': 'Delete' }, + _react2.default.createElement(_Delete2.default, null) + ) + ) + ); + }) + ) + ); + } + }]); + + return RSSFeedList; +}(_react2.default.Component); + +; + +var mapStateToProps = function mapStateToProps(state) { + return { + RSSList: state.RSSList + }; +}; + +var mapDispatchToProps = function mapDispatchToProps(dispatch) { + return { + rssModalOpenState: function rssModalOpenState(RSSModalOpen) { + return dispatch({ type: actionTypes.RSS_MODAL_OPEN_STATE, RSSModalOpen: RSSModalOpen }); + } //sending modal state to backendwebsocket so we can update RSS lists + }; +}; +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(RSSFeedList); \ No newline at end of file diff --git a/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSModalLayout.js b/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSModalLayout.js new file mode 100644 index 00000000..b3946177 --- /dev/null +++ b/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSModalLayout.js @@ -0,0 +1,272 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +require('../../../../node_modules/react-grid-layout/css/styles.css'); + +require('../../../../node_modules/react-resizable/css/styles.css'); + +var _reactGridLayout = require('react-grid-layout'); + +var _reactGridLayout2 = _interopRequireDefault(_reactGridLayout); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _reactRedux = require('react-redux'); + +var _actions = require('../../../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +var _TextField = require('material-ui/TextField'); + +var _TextField2 = _interopRequireDefault(_TextField); + +var _styles = require('material-ui/styles'); + +var _Dialog = require('material-ui/Dialog'); + +var _Dialog2 = _interopRequireDefault(_Dialog); + +var _reactTooltip = require('react-tooltip'); + +var _reactTooltip2 = _interopRequireDefault(_reactTooltip); + +var _Icon = require('material-ui/Icon'); + +var _Icon2 = _interopRequireDefault(_Icon); + +var _RssFeed = require('material-ui-icons/RssFeed'); + +var _RssFeed2 = _interopRequireDefault(_RssFeed); + +var _AddCircle = require('material-ui-icons/AddCircle'); + +var _AddCircle2 = _interopRequireDefault(_AddCircle); + +var _RSSFeedList = require('./RSSFeedList'); + +var _RSSFeedList2 = _interopRequireDefault(_RSSFeedList); + +var _RSSTorrentList = require('./RSSTorrentList'); + +var _RSSTorrentList2 = _interopRequireDefault(_RSSTorrentList); + +var _IconButton = require('material-ui/IconButton'); + +var _IconButton2 = _interopRequireDefault(_IconButton); + +var _Button = require('material-ui/Button'); + +var _Button2 = _interopRequireDefault(_Button); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +//css for react grid + +//react-grid for layout + +//Redux + +//interior items + +var ReactGridLayout = (0, _reactGridLayout.WidthProvider)(_reactGridLayout2.default); + +var background = { + backgroundColor: '#e5e5e5', + boxShadow: '0 0 20px #000' +}; + +var button = { + fontSize: '60px', + paddingRight: '20px', + paddingLeft: '20px' +}; + +var smallButton = { + width: '36px', + height: '36px', + padding: '5px' +}; + +var rssInput = { + width: '90%', + paddingRight: '10px' +}; + +var inlineStyle = { + display: 'inline-block', + backdrop: 'static' +}; + +var RSSModalLayout = function (_React$Component) { + _inherits(RSSModalLayout, _React$Component); + + function RSSModalLayout(props) { + _classCallCheck(this, RSSModalLayout); + + var _this = _possibleConstructorReturn(this, (RSSModalLayout.__proto__ || Object.getPrototypeOf(RSSModalLayout)).call(this, props)); + + _this.handleRSSModalClose = function () { + var closeState = false; + _this.props.rssModalOpenState(closeState); + }; + + _this.handleAddRSSFeed = function () { + _this.setState({ textValue: "Clear" }); //clearing out the text submitted + var RSSURLSubmit = { + messageType: "addRSSFeed", + Payload: [_this.state.textValue] + }; + ws.send(JSON.stringify(RSSURLSubmit)); + var RSSRequest = { + messageType: "rssFeedRequest" + }; + ws.send(JSON.stringify(RSSRequest)); //Immediatly request an update of the feed when you add a new URL + }; + + _this.setTextValue = function (event) { + _this.setState({ textValue: event.target.value }); + }; + + var layout = [{ i: 'a', x: 0, y: 0, w: 6, h: 1, static: true }, { i: 'b', x: 0, y: 1, w: 1, h: 5, static: true }, { i: 'c', x: 1, y: 1, w: 5, h: 5, minW: 5, minH: 3, static: true }]; + _this.state = { layout: layout }; + + return _this; + } + + _createClass(RSSModalLayout, [{ + key: 'onLayoutChange', + value: function onLayoutChange(layout) { + this.props.onLayoutChange(layout); + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + console.log("nextprops", nextProps, "Modal", nextProps.RSSModalOpen); + } + }, { + key: 'componentWillMount', + value: function componentWillMount() { + console.log("Mounting grid"); + } + }, { + key: 'render', + value: function render() { + return _react2.default.createElement( + 'div', + { style: inlineStyle }, + _react2.default.createElement( + _Dialog.DialogContent, + null, + _react2.default.createElement( + ReactGridLayout, + _extends({ layout: this.state.layout, onLayoutChange: this.onLayoutChange + }, this.props), + _react2.default.createElement( + 'div', + { key: 'a', sytle: background, className: 'DragHandle' }, + _react2.default.createElement(_TextField2.default, { + style: rssInput, + autoFocus: true, + margin: 'dense', + id: 'name', + label: 'Add New RSS URL', + type: 'text', + placeholder: 'Enter RSS URL Here..', + onChange: this.setTextValue + }), + _react2.default.createElement( + _IconButton2.default, + { onClick: this.handleAddRSSFeed, color: 'primary', 'data-tip': 'Add RSS Feed', style: smallButton, 'aria-label': 'Add RSS Feeds' }, + _react2.default.createElement(_reactTooltip2.default, { place: 'top', type: 'light', effect: 'float' }), + _react2.default.createElement(_AddCircle2.default, null) + ) + ), + _react2.default.createElement( + 'div', + { key: 'b', style: background, className: 'DragHandle' }, + _react2.default.createElement(_RSSFeedList2.default, null) + ), + _react2.default.createElement( + 'div', + { key: 'c', style: background, className: 'DragHandle' }, + _react2.default.createElement(_RSSTorrentList2.default, null) + ) + ) + ), + _react2.default.createElement( + _Dialog.DialogActions, + null, + _react2.default.createElement( + _Button2.default, + { onClick: this.handleRSSModalClose, color: 'primary' }, + 'Close' + ) + ) + ); + } + }]); + + return RSSModalLayout; +}(_react2.default.Component); + +RSSModalLayout.propTypes = { + onLayoutChange: _propTypes2.default.func.isRequired +}; +RSSModalLayout.defaultProps = { + className: "layout", + items: 4, + rowHeight: 100, + onLayoutChange: function onLayoutChange() {}, + cols: 6, + draggableCancel: '.NoDrag', + draggableHandle: '.DragHandle' +}; +; + +//module.exports = RSSModalLayout; + +var mapStateToProps = function mapStateToProps(state) { + return { + RSSList: state.RSSList, + RSSModalOpen: state.RSSModalOpen + }; +}; + +var mapDispatchToProps = function mapDispatchToProps(dispatch) { + return { + rssModalOpenState: function rssModalOpenState(RSSModalOpen) { + return dispatch({ type: actionTypes.RSS_MODAL_OPEN_STATE, RSSModalOpen: RSSModalOpen }); + } + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(RSSModalLayout); \ No newline at end of file diff --git a/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSTorrentList.js b/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSTorrentList.js new file mode 100644 index 00000000..0b6b354a --- /dev/null +++ b/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/RSSTorrentList.js @@ -0,0 +1,149 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _Button = require('material-ui/Button'); + +var _Button2 = _interopRequireDefault(_Button); + +var _dxReactGrid = require('@devexpress/dx-react-grid'); + +var _dxReactGridMaterialUi = require('@devexpress/dx-react-grid-material-ui'); + +var _reactRedux = require('react-redux'); + +var _actions = require('../../../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var tableStyle = {}; + +var RSSTorrentList = function (_React$Component) { + _inherits(RSSTorrentList, _React$Component); + + function RSSTorrentList(props) { + _classCallCheck(this, RSSTorrentList); + + var _this = _possibleConstructorReturn(this, (RSSTorrentList.__proto__ || Object.getPrototypeOf(RSSTorrentList)).call(this, props)); + + _this.changeSelection = function (selection) { + console.log("TorrentList is changing selection now", selection); + _this.setState({ selected: selection }); + if (selection.length > 0) { + //if selection is empty buttons will be default and selectionHashes will be blanked out and pushed to redux + console.log("Getting the selected Rows"); + var selectedRows = []; //array of all the selected Rows + selection.forEach(function (element) { + selectedRows.push(_this.props.RSSTorrentList[element]); //pushing the selected rows out of torrentlist + }); + _this.setState({ fileSelection: selectedRows }); + } + }; + + _this.sendMagnetLinks = function () { + var sendMagnetLinks = []; + _this.state.fileSelection.forEach(function (element) { + //fileselection contains the currently selected rows + console.log("element", element); + sendMagnetLinks.push(element.TorrentLink); + }); + var magnetLinkSubmit = { + MessageType: "magnetLinkSubmit", + Payload: sendMagnetLinks + }; + console.log(JSON.stringify(magnetLinkSubmit)); + ws.send(JSON.stringify(magnetLinkSubmit)); + }; + + _this.state = { //rows are stored in redux they are sent over from the server + columns: [{ name: 'TorrentName', title: 'Title' }, { name: 'TorrentLink', title: 'Magnet Link' }, { name: 'PublishDate', title: 'Date Published' }], + sorting: [], + columnOrder: ['TorrentName', 'TorrentLink', 'PublishDate'], + columnWidths: { TorrentName: 450, TorrentLink: 650, PublishDate: 200 }, + fileSelection: [], + selected: [] + + }; + + _this.changeColumnOrder = function (columnOrder) { + return _this.setState({ columnOrder: columnOrder }); + }; + _this.changeColumnWidths = function (columnWidths) { + return _this.setState({ columnWidths: columnWidths }); + }; + _this.changeSorting = function (sorting) { + return _this.setState({ sorting: sorting }); + }; + + return _this; + } + + _createClass(RSSTorrentList, [{ + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps() { + console.log("New torrentlist", this.props.RSSTorrentList); + } + }, { + key: 'render', + value: function render() { + return ( + //Buttons here + _react2.default.createElement( + 'div', + null, + _react2.default.createElement( + _Button2.default, + { raised: true, color: 'primary', onClick: this.sendMagnetLinks }, + 'Download Torrents' + ), + _react2.default.createElement( + _dxReactGridMaterialUi.Grid, + { rows: this.props.RSSTorrentList, columns: this.state.columns }, + _react2.default.createElement(_dxReactGrid.SortingState, { sorting: this.state.sorting, onSortingChange: this.changeSorting }), + _react2.default.createElement(_dxReactGrid.LocalSorting, null), + _react2.default.createElement(_dxReactGridMaterialUi.DragDropContext, null), + _react2.default.createElement(_dxReactGrid.SelectionState, { onSelectionChange: this.changeSelection, selection: this.state.selection }), + _react2.default.createElement(_dxReactGridMaterialUi.VirtualTableView, { height: 500 }), + _react2.default.createElement(_dxReactGridMaterialUi.TableColumnResizing, { columnWidths: this.state.columnWidths, onColumnWidthsChange: this.changeColumnWidths }), + _react2.default.createElement(_dxReactGridMaterialUi.TableColumnReordering, { order: this.state.columnOrder, onOrderChange: this.changeColumnOrder }), + _react2.default.createElement(_dxReactGridMaterialUi.TableSelection, { selectByRowClick: true, highlightSelected: true }), + _react2.default.createElement(_dxReactGridMaterialUi.TableHeaderRow, { allowSorting: true, allowResizing: true, allowDragging: true }) + ) + ) + ); + } + }]); + + return RSSTorrentList; +}(_react2.default.Component); + +var mapStateToProps = function mapStateToProps(state) { + return { + selectionHashes: state.selectionHashes, + RSSTorrentList: state.RSSTorrentList + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps)(RSSTorrentList); \ No newline at end of file diff --git a/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/addRSSModal.js b/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/addRSSModal.js new file mode 100644 index 00000000..8ca2d722 --- /dev/null +++ b/goTorrentWebUI/lib/TopMenu/Modals/RSSModal/addRSSModal.js @@ -0,0 +1,177 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _Button = require('material-ui/Button'); + +var _Button2 = _interopRequireDefault(_Button); + +var _TextField = require('material-ui/TextField'); + +var _TextField2 = _interopRequireDefault(_TextField); + +var _styles = require('material-ui/styles'); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _List = require('material-ui/List'); + +var _List2 = _interopRequireDefault(_List); + +var _Dialog = require('material-ui/Dialog'); + +var _Dialog2 = _interopRequireDefault(_Dialog); + +var _Link = require('material-ui-icons/Link'); + +var _Link2 = _interopRequireDefault(_Link); + +var _reactTooltip = require('react-tooltip'); + +var _reactTooltip2 = _interopRequireDefault(_reactTooltip); + +var _Icon = require('material-ui/Icon'); + +var _Icon2 = _interopRequireDefault(_Icon); + +var _IconButton = require('material-ui/IconButton'); + +var _IconButton2 = _interopRequireDefault(_IconButton); + +var _RssFeed = require('material-ui-icons/RssFeed'); + +var _RssFeed2 = _interopRequireDefault(_RssFeed); + +var _AddCircle = require('material-ui-icons/AddCircle'); + +var _AddCircle2 = _interopRequireDefault(_AddCircle); + +var _RSSModalLayout = require('./RSSModalLayout'); + +var _RSSModalLayout2 = _interopRequireDefault(_RSSModalLayout); + +var _reactRedux = require('react-redux'); + +var _actions = require('../../../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +//Redux + + +var button = { + fontSize: '60px', + paddingRight: '20px', + paddingLeft: '20px' +}; + +var inlineStyle = { + display: 'inline-block', + backdrop: 'static' +}; + +var AddRSSModal = function (_React$Component) { + _inherits(AddRSSModal, _React$Component); + + function AddRSSModal() { + var _ref; + + var _temp, _this, _ret; + + _classCallCheck(this, AddRSSModal); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = AddRSSModal.__proto__ || Object.getPrototypeOf(AddRSSModal)).call.apply(_ref, [this].concat(args))), _this), _this.rssModalOpenState = function () { + console.log("Opening RSS Modal"); + _this.props.rssModalOpenState(true); + }, _temp), _possibleConstructorReturn(_this, _ret); + } + + _createClass(AddRSSModal, [{ + key: 'componentDidMount', + value: function componentDidMount() { + //Immediatly request an update of the feed when loading app + var RSSRequest = { + messageType: "rssFeedRequest" + }; + ws.send(JSON.stringify(RSSRequest)); + } + }, { + key: 'render', + value: function render() { + var _props = this.props, + classes = _props.classes, + onRequestClose = _props.onRequestClose, + handleRequestClose = _props.handleRequestClose, + handleSubmit = _props.handleSubmit; + + return _react2.default.createElement( + 'div', + { style: inlineStyle }, + _react2.default.createElement( + _IconButton2.default, + { onClick: this.rssModalOpenState, color: 'primary', 'data-tip': 'Add RSS URL', style: button, 'aria-label': 'RSS Feeds' }, + _react2.default.createElement(_reactTooltip2.default, { place: 'top', type: 'light', effect: 'float' }), + _react2.default.createElement(_RssFeed2.default, null) + ), + _react2.default.createElement( + _Dialog2.default, + { fullScreen: true, open: this.props.RSSModalOpen, onRequestClose: this.handleRequestClose }, + _react2.default.createElement( + _Dialog.DialogTitle, + null, + 'Manage RSS Feeds' + ), + _react2.default.createElement(_RSSModalLayout2.default, null) + ) + ); + } + }]); + + return AddRSSModal; +}(_react2.default.Component); + +; + +var mapStateToProps = function mapStateToProps(state) { + return { + RSSModalOpen: state.RSSModalOpen + }; +}; + +var mapDispatchToProps = function mapDispatchToProps(dispatch) { + return { + rssModalOpenState: function rssModalOpenState(RSSModalOpen) { + return dispatch({ type: actionTypes.RSS_MODAL_OPEN_STATE, RSSModalOpen: RSSModalOpen }); + } + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(AddRSSModal); \ No newline at end of file diff --git a/goTorrentWebUI/lib/TopMenu/Modals/addTorrentFileModal.js b/goTorrentWebUI/lib/TopMenu/Modals/addTorrentFileModal.js new file mode 100644 index 00000000..13e0c6f0 --- /dev/null +++ b/goTorrentWebUI/lib/TopMenu/Modals/addTorrentFileModal.js @@ -0,0 +1,198 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _Button = require('material-ui/Button'); + +var _Button2 = _interopRequireDefault(_Button); + +var _TextField = require('material-ui/TextField'); + +var _TextField2 = _interopRequireDefault(_TextField); + +var _styles = require('material-ui/styles'); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _Dialog = require('material-ui/Dialog'); + +var _Dialog2 = _interopRequireDefault(_Dialog); + +var _reactTooltip = require('react-tooltip'); + +var _reactTooltip2 = _interopRequireDefault(_reactTooltip); + +var _AddBox = require('material-ui-icons/AddBox'); + +var _AddBox2 = _interopRequireDefault(_AddBox); + +var _IconButton = require('material-ui/IconButton'); + +var _IconButton2 = _interopRequireDefault(_IconButton); + +var _reactDropzone = require('react-dropzone'); + +var _reactDropzone2 = _interopRequireDefault(_reactDropzone); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +//import InsertLinkIcon from 'material-ui-icons/Link'; + +//import Icon from 'material-ui/Icon'; + + +var button = { + fontSize: '60px', + paddingRight: '20px', + paddingLeft: '20px' +}; + +var uploadButton = { + fontSize: '35px', + paddingLeft: '0px' +}; + +var inlineStyle = { + display: 'inline-block' +}; + +var input = { + display: 'none' +}; + +var addTorrentFilePopup = function (_React$Component) { + _inherits(addTorrentFilePopup, _React$Component); + + function addTorrentFilePopup() { + var _ref; + + var _temp, _this, _ret; + + _classCallCheck(this, addTorrentFilePopup); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = addTorrentFilePopup.__proto__ || Object.getPrototypeOf(addTorrentFilePopup)).call.apply(_ref, [this].concat(args))), _this), _this.state = { + open: false, + torrentFileName: "", + torrentFileValue: [], + storageValue: "", + showDrop: true + }, _this.handleClickOpen = function () { + _this.setState({ open: true }); + }, _this.handleRequestClose = function () { + _this.setState({ open: false }); + }, _this.handleSubmit = function () { + _this.setState({ open: false }); + //let magnetLinkSubmit = this.state.textValue; + console.log("File", _this.state.torrentFileValue); + var reader = new FileReader(); + var torrentFileBlob = new Blob(_this.state.torrentFileValue); + console.log("Blob", torrentFileBlob); + reader.readAsDataURL(torrentFileBlob); + reader.onloadend = function () { + var base64data = reader.result; + console.log("Base64", base64data); + + var torrentFileMessage = { + messageType: "torrentFileSubmit", + messageDetail: _this.state.torrentFileName, + messageDetailTwo: _this.state.storageValue, + Payload: [base64data] + }; + console.log("Sending magnet link: ", torrentFileMessage); + ws.send(JSON.stringify(torrentFileMessage)); + }; + }, _this.onFileLoad = function (file) { + _this.setState({ torrentFileName: file[0].name }); + _this.setState({ showDrop: false }); + _this.setState({ torrentFileValue: file }); + console.log("File Name", file[0].name); + }, _this.setStorageValue = function (event) { + _this.setState({ storageValue: event.target.value }); + }, _temp), _possibleConstructorReturn(_this, _ret); + } + + _createClass(addTorrentFilePopup, [{ + key: 'render', + value: function render() { + var _props = this.props, + classes = _props.classes, + onRequestClose = _props.onRequestClose, + handleRequestClose = _props.handleRequestClose, + handleSubmit = _props.handleSubmit; + + return _react2.default.createElement( + 'div', + { style: inlineStyle }, + _react2.default.createElement( + _IconButton2.default, + { onClick: this.handleClickOpen, color: 'primary', 'data-tip': 'Add Torrent File', style: button, centerRipple: true, 'aria-label': 'Add Torrent File' }, + _react2.default.createElement(_reactTooltip2.default, { place: 'top', type: 'light', effect: 'float' }), + _react2.default.createElement(_AddBox2.default, null) + ), + _react2.default.createElement( + _Dialog2.default, + { open: this.state.open, onRequestClose: this.handleRequestClose, onEscapeKeyUp: this.handleRequestClose, maxWidth: 'md' }, + _react2.default.createElement( + _Dialog.DialogTitle, + null, + 'Add Torrent File' + ), + _react2.default.createElement( + _Dialog.DialogContent, + null, + _react2.default.createElement(_Dialog.DialogContentText, null), + this.state.showDrop && _react2.default.createElement( + _reactDropzone2.default, + { disablePreview: true, multiple: false, onDrop: this.onFileLoad }, + 'Upload Torrent Here and Add Storage Path' + ), + this.state.torrentFileName != "" && this.state.torrentFileName, + _react2.default.createElement(_TextField2.default, { id: 'storagePath', type: 'text', label: 'Storage Path', placeholder: 'Empty will be default torrent storage path', fullWidth: true, onChange: this.setStorageValue }) + ), + _react2.default.createElement( + _Dialog.DialogActions, + null, + _react2.default.createElement( + _Button2.default, + { onClick: this.handleRequestClose, color: 'primary' }, + 'Cancel' + ), + _react2.default.createElement( + _Button2.default, + { onClick: this.handleSubmit, color: 'primary' }, + 'Submit' + ) + ) + ) + ); + } + }]); + + return addTorrentFilePopup; +}(_react2.default.Component); + +exports.default = addTorrentFilePopup; +; \ No newline at end of file diff --git a/goTorrentWebUI/lib/TopMenu/Modals/addTorrentLinkModal.js b/goTorrentWebUI/lib/TopMenu/Modals/addTorrentLinkModal.js new file mode 100644 index 00000000..9b90e4ae --- /dev/null +++ b/goTorrentWebUI/lib/TopMenu/Modals/addTorrentLinkModal.js @@ -0,0 +1,179 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _Button = require('material-ui/Button'); + +var _Button2 = _interopRequireDefault(_Button); + +var _TextField = require('material-ui/TextField'); + +var _TextField2 = _interopRequireDefault(_TextField); + +var _styles = require('material-ui/styles'); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _Dialog = require('material-ui/Dialog'); + +var _Dialog2 = _interopRequireDefault(_Dialog); + +var _Link = require('material-ui-icons/Link'); + +var _Link2 = _interopRequireDefault(_Link); + +var _reactTooltip = require('react-tooltip'); + +var _reactTooltip2 = _interopRequireDefault(_reactTooltip); + +var _Icon = require('material-ui/Icon'); + +var _Icon2 = _interopRequireDefault(_Icon); + +var _IconButton = require('material-ui/IconButton'); + +var _IconButton2 = _interopRequireDefault(_IconButton); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var button = { + fontSize: '60px', + paddingRight: '20px', + paddingLeft: '20px' +}; + +var inlineStyle = { + display: 'inline-block', + backdrop: 'static' +}; + +var addTorrentPopup = function (_React$Component) { + _inherits(addTorrentPopup, _React$Component); + + function addTorrentPopup() { + var _ref; + + var _temp, _this, _ret; + + _classCallCheck(this, addTorrentPopup); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = addTorrentPopup.__proto__ || Object.getPrototypeOf(addTorrentPopup)).call.apply(_ref, [this].concat(args))), _this), _this.state = { + open: false, + magnetLinkValue: "", + storageValue: "" + + }, _this.handleClickOpen = function () { + _this.setState({ open: true }); + }, _this.handleRequestClose = function () { + _this.setState({ open: false }); + }, _this.handleSubmit = function () { + _this.setState({ open: false }); + //let magnetLinkSubmit = this.state.textValue; + var magnetLinkMessage = { + messageType: "magnetLinkSubmit", + messageDetail: _this.state.storageValue, + Payload: [_this.state.magnetLinkValue] + }; + console.log("Sending magnet link: ", magnetLinkMessage); + ws.send(JSON.stringify(magnetLinkMessage)); + }, _this.setMagnetLinkValue = function (event) { + _this.setState({ magnetLinkValue: event.target.value }); + }, _this.setStorageValue = function (event) { + _this.setState({ storageValue: event.target.value }); + }, _temp), _possibleConstructorReturn(_this, _ret); + } + + _createClass(addTorrentPopup, [{ + key: 'render', + value: function render() { + var _props = this.props, + classes = _props.classes, + onRequestClose = _props.onRequestClose, + handleRequestClose = _props.handleRequestClose, + handleSubmit = _props.handleSubmit; + + return _react2.default.createElement( + 'div', + { style: inlineStyle }, + _react2.default.createElement( + _IconButton2.default, + { onClick: this.handleClickOpen, color: 'primary', 'data-tip': 'Add Magnet Link', style: button, centerRipple: true, 'aria-label': 'Add Magnet Link' }, + _react2.default.createElement(_reactTooltip2.default, { place: 'top', type: 'light', effect: 'float' }), + _react2.default.createElement(_Link2.default, null) + ), + _react2.default.createElement( + _Dialog2.default, + { open: this.state.open, onRequestClose: this.handleRequestClose }, + _react2.default.createElement( + _Dialog.DialogTitle, + null, + 'Add Magnet Link' + ), + _react2.default.createElement( + _Dialog.DialogContent, + null, + _react2.default.createElement( + _Dialog.DialogContentText, + null, + 'Add a Magnet Link here and hit submit to add torrent...' + ), + _react2.default.createElement(_TextField2.default, { + autoFocus: true, + margin: 'dense', + id: 'name', + label: 'Magnet Link', + type: 'text', + placeholder: 'Enter Magnet Link Here', + fullWidth: true, + onChange: this.setMagnetLinkValue + }), + _react2.default.createElement(_TextField2.default, { id: 'storagePath', type: 'text', label: 'Storage Path', placeholder: 'Empty will be default torrent storage path', fullWidth: true, onChange: this.setStorageValue }) + ), + _react2.default.createElement( + _Dialog.DialogActions, + null, + _react2.default.createElement( + _Button2.default, + { onClick: this.handleRequestClose, color: 'primary' }, + 'Cancel' + ), + _react2.default.createElement( + _Button2.default, + { onClick: this.handleSubmit, color: 'primary' }, + 'Submit' + ) + ) + ) + ); + } + }]); + + return addTorrentPopup; +}(_react2.default.Component); + +exports.default = addTorrentPopup; +; \ No newline at end of file diff --git a/goTorrentWebUI/lib/TopMenu/Modals/deleteTorrentModal.js b/goTorrentWebUI/lib/TopMenu/Modals/deleteTorrentModal.js new file mode 100644 index 00000000..51d846cd --- /dev/null +++ b/goTorrentWebUI/lib/TopMenu/Modals/deleteTorrentModal.js @@ -0,0 +1,216 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _Button = require('material-ui/Button'); + +var _Button2 = _interopRequireDefault(_Button); + +var _TextField = require('material-ui/TextField'); + +var _TextField2 = _interopRequireDefault(_TextField); + +var _styles = require('material-ui/styles'); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _Dialog = require('material-ui/Dialog'); + +var _Dialog2 = _interopRequireDefault(_Dialog); + +var _reactTooltip = require('react-tooltip'); + +var _reactTooltip2 = _interopRequireDefault(_reactTooltip); + +var _AddBox = require('material-ui-icons/AddBox'); + +var _AddBox2 = _interopRequireDefault(_AddBox); + +var _IconButton = require('material-ui/IconButton'); + +var _IconButton2 = _interopRequireDefault(_IconButton); + +var _Delete = require('material-ui-icons/Delete'); + +var _Delete2 = _interopRequireDefault(_Delete); + +var _reactRedux = require('react-redux'); + +var _actions = require('../../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +//import InsertLinkIcon from 'material-ui-icons/Link'; + +//import Icon from 'material-ui/Icon'; + + +//Redux + + +var button = { + fontSize: '60px', + paddingRight: '20px', + paddingLeft: '20px' +}; + +var inlineStyle = { + display: 'inline-block' +}; + +var DeleteTorrentModal = function (_React$Component) { + _inherits(DeleteTorrentModal, _React$Component); + + function DeleteTorrentModal() { + var _ref; + + var _temp, _this, _ret; + + _classCallCheck(this, DeleteTorrentModal); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = DeleteTorrentModal.__proto__ || Object.getPrototypeOf(DeleteTorrentModal)).call.apply(_ref, [this].concat(args))), _this), _this.state = { + open: false + }, _this.handleDeleteTorrent = function () { + var selection = []; + var deleteTorrentHashes = { + MessageType: "deleteTorrents", + MessageDetail: "true", + Payload: _this.props.selectionHashes + }; + console.log("Deleting Torrents", deleteTorrentHashes); + ws.send(JSON.stringify(deleteTorrentHashes)); + _this.props.setButtonState(_this.props.selection); //TODO this currently just forces a button refresh, should be a better way to do this + _this.props.changeSelection(selection); //purging out our selection after deleting a torent + _this.setState({ open: false }); + }, _this.handleDeleteData = function () { + var selection = []; + + var deleteTorrentHashes = { + MessageType: "deleteTorrents", + MessageDetail: "true", + Payload: _this.props.selectionHashes + }; + console.log("Deleting Torrents and Data", deleteTorrentHashes); + ws.send(JSON.stringify(deleteTorrentHashes)); + _this.props.setButtonState(_this.props.selection); //TODO this currently just forces a button refresh, should be a better way to do this + _this.props.changeSelection(selection); //purging out our selection after deleting a torent + _this.setState({ open: false }); + }, _this.handleClickOpen = function () { + if (_this.props.selection.length > 0) { + _this.setState({ open: true }); + } else { + console.log("Select a torrent to delete.."); + } + }, _this.handleRequestClose = function () { + _this.setState({ open: false }); + }, _this.setTextValue = function (event) { + _this.setState({ textValue: event.target.value }); + }, _temp), _possibleConstructorReturn(_this, _ret); + } + + _createClass(DeleteTorrentModal, [{ + key: 'render', + value: function render() { + var _props = this.props, + onRequestClose = _props.onRequestClose, + handleRequestClose = _props.handleRequestClose, + handleSubmit = _props.handleSubmit; + + return _react2.default.createElement( + 'div', + { style: inlineStyle }, + _react2.default.createElement( + _IconButton2.default, + { color: this.props.buttonState[0].deleteButton, 'data-tip': 'Delete Torrent', style: button, onClick: this.handleClickOpen, 'aria-label': 'Delete Torrent' }, + _react2.default.createElement(_reactTooltip2.default, { place: 'top', type: 'error', effect: 'float' }), + _react2.default.createElement(_Delete2.default, null) + ), + _react2.default.createElement( + _Dialog2.default, + { open: this.state.open, onRequestClose: this.handleRequestClose, onEscapeKeyUp: this.handleRequestClose, maxWidth: 'md' }, + _react2.default.createElement( + _Dialog.DialogTitle, + null, + 'Delete Torrent' + ), + _react2.default.createElement( + _Dialog.DialogContent, + null, + 'Are you sure you want to delete Torrent?' + ), + _react2.default.createElement( + _Dialog.DialogActions, + null, + _react2.default.createElement( + _Button2.default, + { onClick: this.handleRequestClose, color: 'primary' }, + 'Cancel' + ), + _react2.default.createElement( + _Button2.default, + { onClick: this.handleDeleteData, color: 'primary' }, + 'Delete with Data' + ), + _react2.default.createElement( + _Button2.default, + { onClick: this.handleDeleteTorrent, color: 'primary' }, + 'Delete just Torrent' + ) + ) + ) + ); + } + }]); + + return DeleteTorrentModal; +}(_react2.default.Component); + +; + +var mapStateToProps = function mapStateToProps(state) { + return { + buttonState: state.buttonState, + selection: state.selection, + selectionHashes: state.selectionHashes + }; +}; + +var mapDispatchToProps = function mapDispatchToProps(dispatch) { + return { + setButtonState: function setButtonState(buttonState) { + return dispatch({ type: actionTypes.SET_BUTTON_STATE, buttonState: buttonState }); + }, + changeSelection: function changeSelection(selection) { + return dispatch({ type: actionTypes.CHANGE_SELECTION, selection: selection }); + } //used to force a selection empty after deleting torrent + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(DeleteTorrentModal); \ No newline at end of file diff --git a/goTorrentWebUI/lib/TopMenu/topMenu.js b/goTorrentWebUI/lib/TopMenu/topMenu.js new file mode 100644 index 00000000..0a869147 --- /dev/null +++ b/goTorrentWebUI/lib/TopMenu/topMenu.js @@ -0,0 +1,226 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +require('typeface-roboto'); + +var _styles = require('material-ui/styles'); + +var _Icon = require('material-ui/Icon'); + +var _Icon2 = _interopRequireDefault(_Icon); + +var _IconButton = require('material-ui/IconButton'); + +var _IconButton2 = _interopRequireDefault(_IconButton); + +var _addTorrentLinkModal = require('./Modals/addTorrentLinkModal'); + +var _addTorrentLinkModal2 = _interopRequireDefault(_addTorrentLinkModal); + +var _addTorrentFileModal = require('./Modals/addTorrentFileModal'); + +var _addTorrentFileModal2 = _interopRequireDefault(_addTorrentFileModal); + +var _addRSSModal = require('./Modals/RSSModal/addRSSModal'); + +var _addRSSModal2 = _interopRequireDefault(_addRSSModal); + +var _deleteTorrentModal = require('./Modals/deleteTorrentModal'); + +var _deleteTorrentModal2 = _interopRequireDefault(_deleteTorrentModal); + +var _PlayArrow = require('material-ui-icons/PlayArrow'); + +var _PlayArrow2 = _interopRequireDefault(_PlayArrow); + +var _Stop = require('material-ui-icons/Stop'); + +var _Stop2 = _interopRequireDefault(_Stop); + +var _RssFeed = require('material-ui-icons/RssFeed'); + +var _RssFeed2 = _interopRequireDefault(_RssFeed); + +var _Settings = require('material-ui-icons/Settings'); + +var _Settings2 = _interopRequireDefault(_Settings); + +var _reactTooltip = require('react-tooltip'); + +var _reactTooltip2 = _interopRequireDefault(_reactTooltip); + +var _Delete = require('material-ui-icons/Delete'); + +var _Delete2 = _interopRequireDefault(_Delete); + +var _AddShoppingCart = require('material-ui-icons/AddShoppingCart'); + +var _AddShoppingCart2 = _interopRequireDefault(_AddShoppingCart); + +var _backendWebsocket = require('../BackendComm/backendWebsocket'); + +var _backendWebsocket2 = _interopRequireDefault(_backendWebsocket); + +var _reactRedux = require('react-redux'); + +var _actions = require('../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // contains the font for material UI + +//import PauseTorrentIcon from 'material-ui-icons/Pause'; + + +//Redux + + +var styles = function styles(theme) { + return { + button: { + margin: theme.spacing.unit, + fontSize: '60px' + }, + input: { + display: 'none' + }, + paddingTest: { + display: 'inline-block' + }, + padding: { + paddingTop: '10px', + paddingLeft: '10px' + }, + verticalDivider: { + borderLeft: '2px solid grey', + padding: '20px', + height: '40px', + position: 'absolute', + display: 'inline-block', + paddingRight: '30px', + paddingLeft: '30px' + }, + background: { + backgroundColor: theme.palette.background.paper + + } + }; +}; + +var IconButtons = function (_React$Component) { + _inherits(IconButtons, _React$Component); + + function IconButtons(props) { + _classCallCheck(this, IconButtons); + + var _this = _possibleConstructorReturn(this, (IconButtons.__proto__ || Object.getPrototypeOf(IconButtons)).call(this, props)); + + _this.startTorrent = function () { + console.log("Starting Torrents", _this.props.selectionHashes); + var startTorrentHashes = { + MessageType: "startTorrents", + Payload: _this.props.selectionHashes + //console.log("Peers tab information requested", peerListHashes) + };ws.send(JSON.stringify(startTorrentHashes)); + _this.props.setButtonState(_this.props.selection); //TODO this currently just forces a button refresh, should be a better way to do this + }; + + _this.stopTorrent = function () { + var stopTorrentHashes = { + MessageType: "stopTorrents", + Payload: _this.props.selectionHashes + }; + console.log("Stopping Torrents", stopTorrentHashes); + ws.send(JSON.stringify(stopTorrentHashes)); + _this.props.setButtonState(_this.props.selection); //TODO this currently just forces a button refresh, should be a better way to do this + }; + + return _this; + } + + _createClass(IconButtons, [{ + key: 'render', + value: function render() { + var classes = this.props.classes; + + return _react2.default.createElement( + 'div', + { className: classes.padding }, + _react2.default.createElement(_addTorrentFileModal2.default, null), + _react2.default.createElement(_addTorrentLinkModal2.default, null), + _react2.default.createElement('div', { className: classes.verticalDivider }), + _react2.default.createElement( + _IconButton2.default, + { color: this.props.buttonState[0].startButton, 'data-tip': 'Start Torrent', className: classes.button, 'aria-label': 'Start Torrent', onClick: this.startTorrent }, + _react2.default.createElement(_reactTooltip2.default, { place: 'top', type: 'light', effect: 'float' }), + _react2.default.createElement(_PlayArrow2.default, null) + ), + _react2.default.createElement( + _IconButton2.default, + { color: this.props.buttonState[0].stopButton, 'data-tip': 'Stop Torrent', className: classes.button, onClick: this.stopTorrent, 'aria-label': 'Stop Torrent' }, + _react2.default.createElement(_reactTooltip2.default, { place: 'top', type: 'light', effect: 'float' }), + _react2.default.createElement(_Stop2.default, null) + ), + _react2.default.createElement(_deleteTorrentModal2.default, null), + _react2.default.createElement('div', { className: classes.verticalDivider }), + _react2.default.createElement(_addRSSModal2.default, null), + _react2.default.createElement( + _IconButton2.default, + { color: 'primary', 'data-tip': 'Settings', className: classes.button, 'aria-label': 'Settings' }, + _react2.default.createElement(_reactTooltip2.default, { place: 'top', type: 'light', effect: 'float' }), + _react2.default.createElement(_Settings2.default, null) + ), + _react2.default.createElement('div', { className: classes.verticalDivider }), + _react2.default.createElement(_backendWebsocket2.default, null) + ); + } + }]); + + return IconButtons; +}(_react2.default.Component); + +IconButtons.propTypes = { + classes: _propTypes2.default.object.isRequired +}; + +var mapStateToProps = function mapStateToProps(state) { + return { + buttonState: state.buttonState, + selection: state.selection, + selectionHashes: state.selectionHashes + }; +}; + +var mapDispatchToProps = function mapDispatchToProps(dispatch) { + return { + setButtonState: function setButtonState(buttonState) { + return dispatch({ type: actionTypes.SET_BUTTON_STATE, buttonState: buttonState }); + }, + changeSelection: function changeSelection(selection) { + return dispatch({ type: actionTypes.CHANGE_SELECTION, selection: selection }); + } //used to force a selection empty after deleting torrent + }; +}; + +exports.default = (0, _styles.withStyles)(styles)((0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(IconButtons)); \ No newline at end of file diff --git a/goTorrentWebUI/lib/app.js b/goTorrentWebUI/lib/app.js new file mode 100644 index 00000000..c8b25ecb --- /dev/null +++ b/goTorrentWebUI/lib/app.js @@ -0,0 +1,159 @@ +'use strict'; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +require('../node_modules/react-grid-layout/css/styles.css'); + +require('../node_modules/react-resizable/css/styles.css'); + +var _reactGridLayout = require('react-grid-layout'); + +var _reactGridLayout2 = _interopRequireDefault(_reactGridLayout); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _redux = require('redux'); + +var _reactRedux = require('react-redux'); + +var _reducer = require('./store/reducer'); + +var _reducer2 = _interopRequireDefault(_reducer); + +var _topMenu = require('./TopMenu/topMenu'); + +var _topMenu2 = _interopRequireDefault(_topMenu); + +var _bottomMenu = require('./BottomMenu/bottomMenu'); + +var _bottomMenu2 = _interopRequireDefault(_bottomMenu); + +var _leftMenu = require('./leftMenu/leftMenu'); + +var _leftMenu2 = _interopRequireDefault(_leftMenu); + +var _torrentlist = require('./torrentlist'); + +var _torrentlist2 = _interopRequireDefault(_torrentlist); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +//css for react grid + +//react-grid for layout + +//Redux + +//Menu and torrentlist imports + + +var reduxStore = (0, _redux.createStore)(_reducer2.default); + +var ReactGridLayout = (0, _reactGridLayout.WidthProvider)(_reactGridLayout2.default); + +var background = { + backgroundColor: '#e5e5e5', + boxShadow: '0 0 20px #000' +}; + +var BasicLayout = function (_React$PureComponent) { + _inherits(BasicLayout, _React$PureComponent); + + function BasicLayout(props) { + _classCallCheck(this, BasicLayout); + + var _this = _possibleConstructorReturn(this, (BasicLayout.__proto__ || Object.getPrototypeOf(BasicLayout)).call(this, props)); + + var layout = [{ i: 'a', x: 0, y: 0, w: 6, h: 1, static: true }, { i: 'b', x: 0, y: 1, w: 1, h: 9, static: true }, { i: 'c', x: 1, y: 1, w: 5, h: 5, minW: 5, minH: 3, static: true }, { i: 'd', x: 1, y: 6, w: 5, h: 4, minW: 5, minH: 1, static: true }]; + _this.state = { layout: layout }; + return _this; + } + + _createClass(BasicLayout, [{ + key: 'onLayoutChange', + value: function onLayoutChange(layout) { + this.props.onLayoutChange(layout); + } + }, { + key: 'render', + value: function render() { + return _react2.default.createElement( + ReactGridLayout, + _extends({ layout: this.state.layout, onLayoutChange: this.onLayoutChange + }, this.props), + _react2.default.createElement( + 'div', + { key: 'a', style: background, className: 'DragHandle' }, + _react2.default.createElement(_topMenu2.default, null) + ), + _react2.default.createElement( + 'div', + { key: 'b', style: background, className: 'DragHandle' }, + _react2.default.createElement(_leftMenu2.default, null) + ), + _react2.default.createElement( + 'div', + { key: 'c', style: background, className: 'DragHandle' }, + _react2.default.createElement(_torrentlist2.default, null) + ), + _react2.default.createElement( + 'div', + { key: 'd' }, + _react2.default.createElement(_bottomMenu2.default, null) + ) + ) //returning our 4 grids + + ; + } + }]); + + return BasicLayout; +}(_react2.default.PureComponent); + +BasicLayout.propTypes = { + onLayoutChange: _propTypes2.default.func.isRequired +}; +BasicLayout.defaultProps = { + className: "layout", + items: 4, + rowHeight: 100, + onLayoutChange: function onLayoutChange() {}, + cols: 6, + draggableCancel: '.NoDrag', + draggableHandle: '.DragHandle' +}; +; + +module.exports = BasicLayout; + +//if (require.main === module) { +// require('../test-hook.jsx')(module.exports); +//} + +_reactDom2.default.render(_react2.default.createElement( + _reactRedux.Provider, + { store: reduxStore }, + _react2.default.createElement(BasicLayout, null) +), //wrapping redux around our app +document.getElementById('app')); \ No newline at end of file diff --git a/goTorrentWebUI/lib/leftMenu/leftMenu.js b/goTorrentWebUI/lib/leftMenu/leftMenu.js new file mode 100644 index 00000000..43b08cb9 --- /dev/null +++ b/goTorrentWebUI/lib/leftMenu/leftMenu.js @@ -0,0 +1,257 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _propTypes = require('prop-types'); + +var _propTypes2 = _interopRequireDefault(_propTypes); + +require('typeface-roboto'); + +var _styles = require('material-ui/styles'); + +var _List = require('material-ui/List'); + +var _List2 = _interopRequireDefault(_List); + +var _Divider = require('material-ui/Divider'); + +var _Divider2 = _interopRequireDefault(_Divider); + +var _FileDownload = require('material-ui-icons/FileDownload'); + +var _FileDownload2 = _interopRequireDefault(_FileDownload); + +var _FileUpload = require('material-ui-icons/FileUpload'); + +var _FileUpload2 = _interopRequireDefault(_FileUpload); + +var _SwapVert = require('material-ui-icons/SwapVert'); + +var _SwapVert2 = _interopRequireDefault(_SwapVert); + +var _AllInclusive = require('material-ui-icons/AllInclusive'); + +var _AllInclusive2 = _interopRequireDefault(_AllInclusive); + +var _reactRedux = require('react-redux'); + +var _actions = require('../store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // contains the font for material UI + + +//react redux + + +//TODO, clean up the goddamn variable names you are all over the place +var styles = function styles(theme) { + return { + root: { + width: '100%', + maxWidth: 360, + backgroundColor: '#e5e5e5' + }, + icons: { + width: '40px', + height: '40px' + }, + inactiveIcon: { + width: '40px', + height: '40px', + color: 'red' + }, + active: { + backgroundColor: '#80b3ff' + } + }; +}; + +var SimpleList = function (_React$Component) { + _inherits(SimpleList, _React$Component); + + function SimpleList(props) { + _classCallCheck(this, SimpleList); + + var _this = _possibleConstructorReturn(this, (SimpleList.__proto__ || Object.getPrototypeOf(SimpleList)).call(this, props)); + + _initialiseProps.call(_this); + + var classes = _this.props.classes; + + _this.state = { + allTorrentsClass: classes.active, + downloadingClass: '', + seedingClass: '', + activeTorrentsClass: '', + completedTorrentsClass: '', + allID: "All", + downloadingID: "Downloading", + seedingID: "Seeding", + activeID: "Active", + completedID: "Completed" + + }; + return _this; + } + + _createClass(SimpleList, [{ + key: 'render', + value: function render() { + var _this2 = this; + + var classes = this.props.classes; + + return _react2.default.createElement( + 'div', + { className: classes.root }, + _react2.default.createElement( + _List2.default, + { dense: true }, + _react2.default.createElement( + _List.ListItem, + { dense: true, className: this.state.allTorrentsClass, button: true, onClick: function onClick() { + return _this2.setFilter('', _this2.state.allID); + } }, + _react2.default.createElement( + _List.ListItemIcon, + { className: classes.icons }, + _react2.default.createElement(_AllInclusive2.default, null) + ), + _react2.default.createElement(_List.ListItemText, { primary: 'All Torrents' }) + ), + _react2.default.createElement( + _List.ListItem, + { className: this.state.downloadingClass, button: true, onClick: function onClick() { + return _this2.setFilter('Downloading', _this2.state.downloadingID); + } }, + _react2.default.createElement( + _List.ListItemIcon, + { className: classes.icons }, + _react2.default.createElement(_FileDownload2.default, null) + ), + _react2.default.createElement(_List.ListItemText, { primary: 'Downloading Torrents' }) + ), + _react2.default.createElement( + _List.ListItem, + { className: this.state.seedingClass, button: true, onClick: function onClick() { + return _this2.setFilter('Seeding', _this2.state.seedingID); + } }, + _react2.default.createElement( + _List.ListItemIcon, + { className: classes.icons }, + _react2.default.createElement(_FileUpload2.default, null) + ), + _react2.default.createElement(_List.ListItemText, { primary: 'Seeding Torrents' }) + ), + _react2.default.createElement( + _List.ListItem, + { className: this.state.completedTorrentsClass, button: true, onClick: function onClick() { + return _this2.setFilter('Completed', _this2.state.completedID); + } }, + _react2.default.createElement( + _List.ListItemIcon, + { className: classes.inactiveIcon }, + _react2.default.createElement(_SwapVert2.default, null) + ), + _react2.default.createElement(_List.ListItemText, { primary: 'Completed Torrents' }) + ) + ), + _react2.default.createElement(_Divider2.default, null) + ); + } + }]); + + return SimpleList; +}(_react2.default.Component); + +var _initialiseProps = function _initialiseProps() { + var _this3 = this; + + this.setActiveElement = function (listItem) {}; + + this.setFilter = function (filterState, id) { + var classes = _this3.props.classes; + + filterState = [{ columnName: 'Status', value: filterState }]; + _this3.props.changeFilter(filterState); //dispatch to redux + console.log("Switching filters classes", id); + switch (id) {//TODO.. there has to be a better fucking way to do this + case "All": + _this3.state.allTorrentsClass = classes.active; + _this3.state.downloadingClass = ''; + _this3.state.seedingClass = ''; + _this3.state.activeTorrentsClass = ''; + _this3.state.completedTorrentsClass = ''; + break; + case "Downloading": + console.log("Downloading..."); + _this3.state.downloadingClass = classes.active; + _this3.state.allTorrentsClass = ''; + _this3.state.seedingClass = ''; + _this3.state.activeTorrentsClass = ''; + _this3.state.completedTorrentsClass = ''; + break; + case "Seeding": + _this3.state.seedingClass = classes.active; + _this3.state.allTorrentsClass = ''; + _this3.state.downloadingClass = ''; + _this3.state.activeTorrentsClass = ''; + _this3.state.completedTorrentsClass = ''; + break; + case "Active": + _this3.state.activeTorrentsClass = classes.active; + _this3.state.allTorrentsClass = ''; + _this3.state.downloadingClass = ''; + _this3.state.seedingClass = ''; + _this3.state.completedTorrentsClass = ''; + break; + case "Completed": + _this3.state.completedTorrentsClass = classes.active; + _this3.state.allTorrentsClass = ''; + _this3.state.downloadingClass = ''; + _this3.state.seedingClass = ''; + _this3.state.activeTorrentsClass = ''; + break; + + } + }; +}; + +SimpleList.propTypes = { + classes: _propTypes2.default.object.isRequired +}; + +var mapStateToProps = function mapStateToProps(state) { + return { + filter: state.filter + }; +}; + +var mapDispatchToProps = function mapDispatchToProps(dispatch) { + return { + changeFilter: function changeFilter(filter) { + return dispatch({ type: actionTypes.CHANGE_FILTER, filter: filter }); + } + }; +}; + +exports.default = (0, _styles.withStyles)(styles)((0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(SimpleList)); \ No newline at end of file diff --git a/goTorrentWebUI/lib/store/actions.js b/goTorrentWebUI/lib/store/actions.js new file mode 100644 index 00000000..1b4acdee --- /dev/null +++ b/goTorrentWebUI/lib/store/actions.js @@ -0,0 +1,18 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var SORTLIST = exports.SORTLIST = 'SORTLIST'; +var CHANGE_SELECTION = exports.CHANGE_SELECTION = 'CHANGE_SELECTION'; +var CHANGE_FILTER = exports.CHANGE_FILTER = 'CHANGE_FILTER'; +var TORRENT_LIST = exports.TORRENT_LIST = 'TORRENT_LIST'; +var SET_BUTTON_STATE = exports.SET_BUTTON_STATE = 'BUTTON_STATE'; +var SELECTION_HASHES = exports.SELECTION_HASHES = 'SELECTION_HASHES'; +var SELECTED_TAB = exports.SELECTED_TAB = 'SELECTED_TAB'; +var PEER_LIST = exports.PEER_LIST = 'PEER_LIST'; +var FILE_LIST = exports.FILE_LIST = 'FILE_LIST'; +var CHANGE_FILE_SELECTION = exports.CHANGE_FILE_SELECTION = 'CHANGE_FILE_SELECTION'; +var NEW_RSS_FEED_STORE = exports.NEW_RSS_FEED_STORE = 'NEW_RSS_FEED_STORE'; +var RSS_MODAL_OPEN_STATE = exports.RSS_MODAL_OPEN_STATE = 'RSS_MODAL_OPEN_STATE'; +var RSS_TORRENT_LIST = exports.RSS_TORRENT_LIST = 'RSS_TORRENT_LIST'; \ No newline at end of file diff --git a/goTorrentWebUI/lib/store/reducer.js b/goTorrentWebUI/lib/store/reducer.js new file mode 100644 index 00000000..9924c909 --- /dev/null +++ b/goTorrentWebUI/lib/store/reducer.js @@ -0,0 +1,159 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _actions = require("./actions"); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var initialState = { + buttonStateDefault: [{ startButton: "default", stopButton: "default", deleteButton: "default", fSeedButton: "default", fRecheckButton: "default" }], + buttonState: [{ startButton: "default", stopButton: "default", deleteButton: "default", fSeedButton: "default", fRecheckButton: "default" }], + sorting: [], + selection: [], + selectionHashes: [], + filter: ["Status", ""], + columnName: "Status", + torrentList: [], + peerList: [], + fileList: [], + torrentDetailInfo: [], + selectedTab: 0, + RSSList: [], + RSSTorrentList: [], + RSSModalOpen: false +}; + +var reducer = function reducer() { + var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState; + var action = arguments[1]; + + switch (action.type) { + + case actionTypes.CHANGE_SELECTION: + console.log("Change Selection", action.selection); + return _extends({}, state, { + peerList: [], //changing selection will purge out all of the old data + fileList: [], + selectionHashes: [], + selection: action.selection + }); + + case actionTypes.NEW_RSS_FEED_STORE: + console.log("New RSS Feed Store", action.RSSList); + return _extends({}, state, { + RSSList: action.RSSList + }); + + case actionTypes.RSS_TORRENT_LIST: + console.log("New RSS Torrent List IN REDUCER", action.RSSTorrentList); + return _extends({}, state, { + RSSTorrentList: action.RSSTorrentList + }); + + case actionTypes.SELECTION_HASHES: + console.log("Selection hashes REDUX", action.selectionHashes); + return _extends({}, state, { + selectionHashes: action.selectionHashes + }); + + case actionTypes.SORTLIST: + //TODO do I even need this in redux? + console.log("List Sort", action.sorting); + return state; + + case actionTypes.CHANGE_FILTER: + return _extends({}, state, { + filter: action.filter + }); + + case actionTypes.TORRENT_LIST: + return _extends({}, state, { + torrentList: action.torrentList + }); + + case actionTypes.PEER_LIST: + return _extends({}, state, { + peerList: action.peerList + }); + + case actionTypes.FILE_LIST: + return _extends({}, state, { + fileList: action.fileList + }); + + case actionTypes.SELECTED_TAB: + return _extends({}, state, { + selectedTab: action.selectedTab + }); + + case actionTypes.RSS_MODAL_OPEN_STATE: + console.log("Setting RSS Modal State...", action.RSSModalOpen); + return _extends({}, state, { + RSSModalOpen: action.RSSModalOpen + }); + + case actionTypes.SET_BUTTON_STATE: + if (action.buttonState.length === 0) { + //if selection is empty buttons will be default and selectionHashes will be blanked out and pushed to redux + var _buttonStateFinal = state.buttonStateDefault; //if no selection dispatch that to redux + return _extends({}, state, { + buttonState: _buttonStateFinal + }); + } else { + // if we have selection continue on with logic to determine button state + var selectedRows = []; //array of all the selected Rows + action.buttonState.forEach(function (element) { + selectedRows.push(state.torrentList[element]); //pushing the selected rows out of torrentlist + }); + + var buttonStateTest = selectedRows.filter(function (element) { + //TODO fix this bad mess... we literally just need to filter for stopped and go from there + var result = []; + if (element.Status === "Downloading" || element.Status === "Awaiting Peers" || element.Status === "Seeding" || element.Status === "Completed") { + result.push(element.Status); + return result; + } + }); + var buttonStateTest2 = selectedRows.filter(function (element) { + return element.Status === "Stopped"; + }); + + if (buttonStateTest.length > 0 && buttonStateTest2.length === 0) { + + var _buttonStateFinal2 = [{ startButton: "default", stopButton: "primary", deleteButton: "accent", fSeedButton: "default", fRecheckButton: "primary" }]; + return _extends({}, state, { + buttonState: _buttonStateFinal2 + }); + } + if (buttonStateTest.length === 0 && buttonStateTest2.length > 0) { + var _buttonStateFinal3 = [{ startButton: "primary", stopButton: "default", deleteButton: "accent", fSeedButton: "default", fRecheckButton: "primary" }]; + return _extends({}, state, { + buttonState: _buttonStateFinal3 + }); + } + if (buttonStateTest.length > 0 && buttonStateTest2.length > 0) { + var _buttonStateFinal4 = [{ startButton: "primary", stopButton: "primary", deleteButton: "accent", fSeedButton: "default", fRecheckButton: "primary" }]; + return _extends({}, state, { + buttonState: _buttonStateFinal4 + }); + } + } + return _extends({}, state, { + buttonState: buttonStateFinal + }); + + default: + return state; + }; + + console.log("no actiontypes found", action); + return state; +}; +exports.default = reducer; \ No newline at end of file diff --git a/goTorrentWebUI/lib/torrentlist.js b/goTorrentWebUI/lib/torrentlist.js new file mode 100644 index 00000000..e412c28f --- /dev/null +++ b/goTorrentWebUI/lib/torrentlist.js @@ -0,0 +1,212 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _reactBootstrapTableAllMin = require('../node_modules/react-bootstrap-table/dist/react-bootstrap-table-all.min.css'); + +var _reactBootstrapTableAllMin2 = _interopRequireDefault(_reactBootstrapTableAllMin); + +var _reactBootstrapTable = require('react-bootstrap-table'); + +var _Paper = require('material-ui/Paper'); + +var _Paper2 = _interopRequireDefault(_Paper); + +var _dxReactGrid = require('@devexpress/dx-react-grid'); + +var _dxReactGridMaterialUi = require('@devexpress/dx-react-grid-material-ui'); + +var _progressBarCell = require('./CustomCells/progressBarCell'); + +var _reactRedux = require('react-redux'); + +var _actions = require('./store/actions'); + +var actionTypes = _interopRequireWildcard(_actions); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +//react redux + + +/* var torrentLinkSubmit = document.getElementById('torrentLinkSubmit'); +var magnetLink = document.getElementById('magnetLink'); +var myTextArea = document.getElementById("loggerData"); +var torrentHash = document.getElementById("hash"); +initialize an empty torrents field before update. + var torrentLinkSubmit = document.getElementById('torrentLinkSubmit'); +var magnetLink = document.getElementById('magnetLink'); +var myTextArea = document.getElementById("loggerData"); +var torrentHash = document.getElementById("hash"); +var torrentLinkSubmit = document.getElementById('torrentLinkSubmit'); +var torrentLinkModal = document.getElementById('addTorrentLinkModal'); +var btnTorrentLink = document.getElementById("addTorrentLink"); +*/ + +function sendEvent(message) { + ws.send(message); + console.log('Sending message... ', message); +} + +var TorrentListTable = function (_React$Component) { + _inherits(TorrentListTable, _React$Component); + + function TorrentListTable(props) { + _classCallCheck(this, TorrentListTable); + + var _this = _possibleConstructorReturn(this, (TorrentListTable.__proto__ || Object.getPrototypeOf(TorrentListTable)).call(this, props)); + + _this.determineSelectionHashes = function (selectedRows) { + //console.log("CurrentSelectionHashes", this.props.selectionHashes) + var selectionHashes = []; //rebuilding our selection hashes from our currently selected rows + selectedRows.forEach(function (element) { + selectionHashes.push(element.TorrentHashString); //push the selection hash to the temp array + }); + _this.props.sendSelectionHashes(selectionHashes); //push the result to redux + }; + + _this.changeSelection = function (selection) { + //console.log("TOrrentlist is changing selection now", selection) + _this.props.changeSelection(selection); //dispatch selection to redux, also clear out anything tied to the old selection (peerlists, filelists, etc) + + if (selection.length === 0) { + //if selection is empty buttons will be default and selectionHashes will be blanked out and pushed to redux + _this.props.setButtonState(selection); //if no selection dispatch that to redux + } else { + // if we have selection continue on with logic to determine button state + var selectedRows = []; //array of all the selected Rows + selection.forEach(function (element) { + selectedRows.push(_this.props.torrentList[element]); //pushing the selected rows out of torrentlist + }); + //console.log("Determining selection hashses") + _this.determineSelectionHashes(selectedRows); //pulling the torrent hashes for the selcted rows + _this.props.setButtonState(selection); + } + }; + + _this.filterHandler = function (filter) { + //TODO, figure out how to do multiple filter + //console.log("Changing FIlter", filter) + if (filter.value === "Active") { + console.log("This filter doesn't fucking work"); + } + }; + + _this.state = { //rows are stored in redux they are sent over from the server + columns: [{ name: 'TorrentName', title: 'Torrent Name' }, { name: 'DownloadedSize', title: 'Dl Size' }, { name: 'Size', title: 'Size' }, { name: 'PercentDone', title: 'Percent Done' }, { name: 'Status', title: 'Status' }, { name: 'DownloadSpeed', title: 'DL Speed' }, { name: 'UploadSpeed', title: 'UL Speed' }, { name: 'ActivePeers', title: 'Active Peers' }, { name: 'ETA', title: 'ETA' }, { name: 'Ratio', title: 'Ratio' }, { name: 'DateAdded', title: 'Date Added' }, { name: 'Availability', title: 'Availability' }], + columnOrder: ['TorrentName', 'DownloadedSize', 'Size', 'PercentDone', 'Status', 'DownloadSpeed', 'UploadSpeed', 'ActivePeers', 'ETA', 'Ratio', 'DateAdded', 'Availability'], + columnWidths: { TorrentName: 250, DownloadedSize: 100, Size: 100, PercentDone: 175, Status: 150, DownloadSpeed: 100, UploadSpeed: 100, ActivePeers: 100, ETA: 100, Ratio: 75, DateAdded: 100, Availability: 75 }, + prevSelection: [], //just used to pull data from cell (temp Prevcell holder), real selection is in Redux + pageSizes: [5, 10, 15, 0], + currentPage: 0 + }; + + _this.changeColumnOrder = function (columnOrder) { + return _this.setState({ columnOrder: columnOrder }); + }; + _this.changeColumnWidths = function (columnWidths) { + return _this.setState({ columnWidths: columnWidths }); + }; + _this.changePageSize = function (pageSize) { + return _this.setState({ pageSize: pageSize }); + }; + _this.changeCurrentPage = function (currentPage) { + return _this.setState({ currentPage: currentPage }); + }; + return _this; + } + + _createClass(TorrentListTable, [{ + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + //this is for setting the filter when the left menu activates a new filter + if (this.props.filter != nextProps.filter) { + this.filterHandler(nextProps.filter); + } + //console.log("Recieving new props", nextProps.selection) + } + }, { + key: 'render', + value: function render() { + return _react2.default.createElement( + _Paper2.default, + null, + _react2.default.createElement( + _dxReactGridMaterialUi.Grid, + { rows: this.props.torrentList, columns: this.state.columns }, + _react2.default.createElement(_dxReactGrid.FilteringState, { filters: this.props.filter }), + _react2.default.createElement(_dxReactGrid.SortingState, { sorting: this.props.sorting, onSortingChange: this.props.changeSorting }), + _react2.default.createElement(_dxReactGrid.SelectionState, { onSelectionChange: this.changeSelection, selection: this.props.selection }), + _react2.default.createElement(_dxReactGrid.LocalFiltering, null), + _react2.default.createElement(_dxReactGrid.LocalSorting, null), + _react2.default.createElement(_dxReactGridMaterialUi.VirtualTableView, { height: 530, tableCellTemplate: function tableCellTemplate(_ref) { + var row = _ref.row, + column = _ref.column, + style = _ref.style; + + if (column.name === 'PercentDone') { + return _react2.default.createElement(_progressBarCell.ProgressBarCell, { value: row.PercentDone * 100, style: style }); + } + return undefined; + } }), + _react2.default.createElement(_dxReactGridMaterialUi.DragDropContext, null), + _react2.default.createElement(_dxReactGridMaterialUi.TableColumnResizing, { columnWidths: this.state.columnWidths, onColumnWidthsChange: this.changeColumnWidths }), + _react2.default.createElement(_dxReactGridMaterialUi.TableColumnReordering, { order: this.state.columnOrder, onOrderChange: this.changeColumnOrder }), + _react2.default.createElement(_dxReactGridMaterialUi.TableSelection, { selectByRowClick: true, highlightSelected: true }), + _react2.default.createElement(_dxReactGridMaterialUi.TableHeaderRow, { allowSorting: true, allowResizing: true, allowDragging: true }) + ) + ); + } + }]); + + return TorrentListTable; +}(_react2.default.Component); + +var mapStateToProps = function mapStateToProps(state) { + return { + filter: state.filter, + torrentList: state.torrentList, + buttonState: state.buttonState, + buttonStateDefault: state.buttonStateDefault, //all default + selectionHashes: state.selectionHashes, + selection: state.selection + }; +}; + +var mapDispatchToProps = function mapDispatchToProps(dispatch) { + return { + changeSorting: function changeSorting(sorting) { + return dispatch({ type: actionTypes.SORTLIST, sorting: sorting }); + }, + changeSelection: function changeSelection(selection) { + return dispatch({ type: actionTypes.CHANGE_SELECTION, selection: selection }); + }, + setButtonState: function setButtonState(buttonState) { + return dispatch({ type: actionTypes.SET_BUTTON_STATE, buttonState: buttonState }); + }, + sendSelectionHashes: function sendSelectionHashes(selectionHashes) { + return dispatch({ type: actionTypes.SELECTION_HASHES, selectionHashes: selectionHashes }); + } + }; +}; + +exports.default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(TorrentListTable); \ No newline at end of file diff --git a/main.go b/main.go index d17f6006..fe91cb3d 100644 --- a/main.go +++ b/main.go @@ -6,11 +6,14 @@ import ( "fmt" "html/template" "io/ioutil" + "net/http" "os" "path/filepath" "strings" + _ "net/http/pprof" + "github.com/anacrolix/torrent" "github.com/asdine/storm" Engine "github.com/deranjer/goTorrent/engine" @@ -59,6 +62,7 @@ func main() { if Config.LoggingOutput == "file" { os.Remove("logs/server.log") //cleanup the old log on every restart file, err := os.OpenFile("logs/server.log", os.O_CREATE|os.O_WRONLY, 0666) //creating the log file + defer file.Close() //TODO.. since we write to this constantly how does close work? if err != nil { fmt.Println("Unable to create file for logging.... please check permissions.. forcing output to stdout") Logger.Out = os.Stdout @@ -95,9 +99,9 @@ func main() { TorrentLocalArray = Storage.FetchAllStoredTorrents(db) //pulling in all the already added torrents if TorrentLocalArray != nil { //the first creation of the running torrent array //since we are adding all of them in we use a coroutine... just allows the web ui to load then it will load in the torrents - go func() { //TODO instead of running all torrent fetches in coroutine see if possible to run each single one in a routine so we don't wait for ALL of them to be verified - RunningTorrentArray = Engine.CreateRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) - }() + //go func() { //TODO instead of running all torrent fetches in coroutine see if possible to run each single one in a routine so we don't wait for ALL of them to be verified + RunningTorrentArray = Engine.CreateRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) + //}() } else { Logger.Info("Database is empty, no torrents loaded") } @@ -122,7 +126,7 @@ func main() { }) http.HandleFunc("/websocket", func(w http.ResponseWriter, r *http.Request) { //websocket is the main data pipe to the frontend conn, err := upgrader.Upgrade(w, r, nil) - + defer conn.Close() //defer closing the websocket until done. if err != nil { Logger.WithFields(logrus.Fields{"error": err}).Fatal("Unable to create websocket!") return