index.jsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import React, { Component } from "react";
  2. import { NavLink } from "react-router-dom";
  3. import CustomInput from "components/CustomInput.jsx";
  4. import CustomMessages from "components/CustomMessages.jsx";
  5. import PropTypes from "prop-types";
  6. import { translate, Trans } from "react-i18next";
  7. import { connect } from "react-redux";
  8. import io from "io";
  9. import config from "config";
  10. @connect(state => ({
  11. user: {
  12. userId: state.user.get("userId"),
  13. role: state.user.get("role"),
  14. },
  15. loggedIn: state.user.get("loggedIn"),
  16. }))
  17. @translate(["home", "createCommunityStation"], { wait: true })
  18. export default class Homepage extends Component {
  19. static propTypes = {
  20. t: PropTypes.func,
  21. };
  22. static defaultProps = {
  23. t: () => {},
  24. };
  25. constructor() {
  26. super();
  27. CustomInput.initialize(this);
  28. this.state = {
  29. stations: {
  30. official: [],
  31. community: [],
  32. },
  33. createStation: {
  34. private: false,
  35. }
  36. };
  37. io.getSocket(socket => {
  38. socket.emit("stations.index", data => {
  39. if (data.status === "success") {
  40. let community = [];
  41. let official = [];
  42. data.stations.forEach(station => {
  43. if (!station.currentSong) station.currentSong = { thumbnail: '/assets/images/notes-transparent.png' };
  44. if (station.currentSong && !station.currentSong.thumbnail) station.currentSong.thumbnail = "/assets/images/notes-transparent.png";
  45. if (station.type === 'official') official.push(station);
  46. else community.push(station);
  47. });
  48. this.setState({
  49. stations: {
  50. official,
  51. community,
  52. }
  53. });
  54. }
  55. });
  56. });
  57. }
  58. isOwner = (ownerId) => {
  59. if (this.props.loggedIn) {
  60. if (this.props.user.role === "admin") return true;
  61. if (this.props.user.userId === ownerId) return true;
  62. }
  63. return false;
  64. };
  65. listStations = (type) => {
  66. let stations = [];
  67. this.state.stations[type].forEach((station) => {
  68. let icon = null;
  69. if (station.type === "official") {
  70. if (station.privacy !== "public") icon =
  71. <i className="material-icons" title={ this.props.t("home:thisStationIsNotVisible") }>lock</i>;
  72. } else {
  73. // TODO Add isOwner function globally
  74. if (this.isOwner(station.ownerId)) icon =
  75. <i className="material-icons" title={ this.props.t("home:thisIsYourStation") }>home</i>;
  76. if (station.privacy !== "public") icon =
  77. <i className="material-icons" title={ this.props.t("home:thisStationIsNotVisible") }>lock</i>;
  78. }
  79. stations.push(
  80. (
  81. <div key={station._id} className="station-card">
  82. <div className="station-media">
  83. <img src={station.currentSong.thumbnail}/>
  84. </div>
  85. <div className="station-body">
  86. <h3 className="displayName">{station.displayName}</h3>
  87. <p className="description">{station.description}</p>
  88. </div>
  89. <div className="station-footer">
  90. <div className="user-count" title={ this.props.t("home:howManyOtherUsers") }>
  91. <i className="material-icons">people</i>
  92. <span>{station.userCount}</span>
  93. </div>
  94. { icon }
  95. </div>
  96. <a href={station.type + "/" + station.name}/>
  97. </div>
  98. )
  99. );
  100. });
  101. return stations;
  102. };
  103. togglePrivate = () => {
  104. this.setState({
  105. createStation: {
  106. private: !this.state.createStation.private,
  107. },
  108. });
  109. };
  110. createCommunity = () => {
  111. this.messages.clearErrorSuccess();
  112. if (CustomInput.hasInvalidInput(this.input)) {
  113. this.messages.clearAddError(this.props.t("general:someFieldsAreIncorrectError"));
  114. } else {
  115. io.getSocket(socket => {
  116. //TODO Add private value
  117. socket.emit("stations.create", {
  118. name: this.input.stationName.getValue(),
  119. type: "community",
  120. displayName: this.input.stationDisplayName.getValue(),
  121. description: this.input.stationDescription.getValue(),
  122. }, res => {
  123. if (res.status === "success") {
  124. location.href = "/community/" + this.input.stationName.getValue();//TODO Remove
  125. } else {
  126. this.messages.addError(res.message);
  127. }
  128. });
  129. });
  130. }
  131. };
  132. render() {
  133. const { t } = this.props;
  134. //TODO Make this not re-render a lot
  135. return (
  136. <main id="homepage">
  137. <h1>{ t("home:title") }</h1>
  138. <CustomMessages onRef={ ref => (this.messages = ref) } />
  139. <h2>{ t("home:officialStations") }</h2>
  140. <div className="official-stations stations">
  141. { this.listStations("official") }
  142. </div>
  143. <h2>{ t("home:communityStations") }</h2>
  144. <div className="community-stations stations">
  145. { (this.props.loggedIn) ? (
  146. <div className="station-card">
  147. <div className="station-media station-media-icon">
  148. <div className="create-station-header">
  149. <h3>Create community station</h3>
  150. </div>
  151. <i className="material-icons" title={ this.props.t("createCommunityStation:addCommunityStation") } onClick={ this.createCommunity }>add</i>
  152. </div>
  153. <div className="station-body">
  154. <CustomInput key="stationDisplayName" type="stationDisplayName" name="stationDisplayName" showLabel={ false } placeholder={ this.props.t("createCommunityStation:displayNameHere") } onRef={ ref => (this.input.stationDisplayName = ref) } />
  155. <CustomInput key="stationDescription" type="stationDescription" name="stationDescription" showLabel={ false } placeholder={ this.props.t("createCommunityStation:descriptionHere") } onRef={ ref => (this.input.stationDescription = ref) } />
  156. </div>
  157. <div className="station-footer">
  158. <div className="nameContainer">
  159. <span>musare.com/c/</span>
  160. <CustomInput key="stationName" type="stationName" name="stationName" showLabel={ false } placeholder={ this.props.t("createCommunityStation:nameHere") } onRef={ ref => (this.input.stationName = ref) } />
  161. </div>
  162. {(this.state.createStation.private) ? <i className="material-icons" title={ this.props.t("createCommunityStation:makeThisStationPublic") } onClick={ this.togglePrivate }>lock</i> : <i className="material-icons active" title={ this.props.t("createCommunityStation:makeThisStationPrivate") } onClick={ this.togglePrivate }>lock</i>}
  163. </div>
  164. </div>
  165. ) : null }
  166. { this.listStations("community") }
  167. </div>
  168. </main>
  169. );
  170. }
  171. }