diff --git a/httpdocs/theme/react/all.js b/httpdocs/theme/react/all.js index d7b38e9a2..258843588 100644 --- a/httpdocs/theme/react/all.js +++ b/httpdocs/theme/react/all.js @@ -1,4302 +1,4302 @@ window.appHelpers = function () { function getEnv(domain) { let env; if (this.splitByLastDot(domain) === 'com' || this.splitByLastDot(domain) === 'org') { env = 'live'; } else { env = 'test'; } return env; } function getDeviceWidth(width) { let device; if (width > 1720) { device = "very-huge"; } else if (width < 1720 && width > 1500) { device = "huge"; } else if (width < 1500 && width > 1250) { device = "full"; } else if (width < 1250 && width >= 1000) { device = "large"; } else if (width < 1000 && width >= 661) { device = "mid"; } else if (width < 661 && width >= 400) { device = "tablet"; } else if (width < 400) { device = "phone"; } return device; } function splitByLastDot(text) { var index = text.lastIndexOf('.'); return text.slice(index + 1); } function getTimeAgo(datetime) { const a = timeago().format(datetime); return a; } function getFileSize(size) { if (isNaN(size)) size = 0; if (size < 1024) return size + ' Bytes'; size /= 1024; if (size < 1024) return size.toFixed(2) + ' Kb'; size /= 1024; if (size < 1024) return size.toFixed(2) + ' Mb'; size /= 1024; if (size < 1024) return size.toFixed(2) + ' Gb'; size /= 1024; return size.toFixed(2) + ' Tb'; } function generateFilterUrl(location, currentCat) { let link = {}; if (currentCat && currentCat !== 0) { link.base = "/browse/cat/" + currentCat + "/ord/"; } else { link.base = "/browse/ord/"; } if (location.search) link.search = location.search; return link; } function generateFileDownloadHash(file, env) { let salt; if (env === "test") { salt = "vBHnf7bbdhz120bhNsd530LsA2mkMvh6sDsCm4jKlm23D186Fj"; } else { salt = "Kcn6cv7&dmvkS40Hna§4ffcvl=021nfMs2sdlPs123MChf4s0K"; } const timestamp = Math.floor(new Date().getTime() / 1000 + 3600); const hash = md5(salt + file.collection_id + timestamp); return hash; } return { getEnv, getDeviceWidth, splitByLastDot, getTimeAgo, getFileSize, generateFilterUrl, generateFileDownloadHash }; }(); window.categoryHelpers = function () { function findCurrentCategories(categories, catId) { let currentCategories = {}; categories.forEach(function (mc, index) { if (parseInt(mc.id) === catId) { currentCategories.category = mc; } else { const cArray = categoryHelpers.convertCatChildrenObjectToArray(mc.children); cArray.forEach(function (sc, index) { if (parseInt(sc.id) === catId) { currentCategories.category = mc; currentCategories.subcategory = sc; } else { const scArray = categoryHelpers.convertCatChildrenObjectToArray(sc.children); scArray.forEach(function (ssc, index) { if (parseInt(ssc.id) === catId) { currentCategories.category = mc; currentCategories.subcategory = sc; currentCategories.secondSubCategory = ssc; } }); } }); } }); return currentCategories; } function convertCatChildrenObjectToArray(children) { let cArray = []; for (var i in children) { cArray.push(children[i]); } return cArray; } return { findCurrentCategories, convertCatChildrenObjectToArray }; }(); window.productHelpers = function () { function getNumberOfProducts(device, numRows) { let num; if (device === "very-huge") { num = 7; } else if (device === "huge") { num = 6; } else if (device === "full") { num = 5; } else if (device === "large") { num = 4; } else if (device === "mid") { num = 3; } else if (device === "tablet") { num = 2; } else if (device === "phone") { num = 1; } if (numRows) num = num * numRows; return num; } function generatePaginationObject(numPages, pathname, currentCategoy, order, page) { let pagination = []; let baseHref = "/browse"; if (pathname.indexOf('cat') > -1) { baseHref += "/cat/" + currentCategoy; } if (page > 1) { const prev = { number: 'previous', link: baseHref + "/page/" + parseInt(page - 1) + "/ord/" + order }; pagination.push(prev); } for (var i = 0; i < numPages; i++) { const p = { number: parseInt(i + 1), link: baseHref + "/page/" + parseInt(i + 1) + "/ord/" + order }; pagination.push(p); } if (page < numPages) { const next = { number: 'next', link: baseHref + "/page/" + parseInt(page + 1) + "/ord/" + order }; pagination.push(next); } return pagination; } function calculateProductRatings(ratings) { let pRating; let totalUp = 0, totalDown = 0; ratings.forEach(function (r, index) { if (r.rating_active === "1") { if (r.user_like === "1") { totalUp += 1; } else if (r.user_dislike === "1") { totalDown += 1; } } }); pRating = 100 / ratings.length * (totalUp - totalDown); return pRating; } function getActiveRatingsNumber(ratings) { let activeRatingsNumber = 0; ratings.forEach(function (r, index) { if (r.rating_active === "1") { activeRatingsNumber += 1; } }); return activeRatingsNumber; } function getFilesSummary(files) { let summery = { downloads: 0, archived: 0, fileSize: 0, total: 0 }; files.forEach(function (file, index) { summery.total += 1; summery.fileSize += parseInt(file.size); summery.downloads += parseInt(file.downloaded_count); }); return summery; } function checkIfLikedByUser(user, likes) { let likedByUser = false; likes.forEach(function (like, index) { if (user.member_id === like.member_id) { likedByUser = true; } }); return likedByUser; } function getLoggedUserRatingOnProduct(user, ratings) { let userRating = -1; ratings.forEach(function (r, index) { if (r.member_id === user.member_id) { if (r.user_like === "1") { userRating = 1; } else { userRating = 0; } } }); return userRating; } function calculateProductLaplaceScore(ratings) { let laplace_score = 0; let upvotes = 0; let downvotes = 0; ratings.forEach(function (rating, index) { if (rating.rating_active === "1") { if (rating.user_like === "1") { upvotes += 1; } else if (rating.user_like === "0") { downvotes += 1; } } }); laplace_score = Math.round((upvotes + 6) / (upvotes + downvotes + 12), 2) * 100; return laplace_score; } return { getNumberOfProducts, generatePaginationObject, calculateProductRatings, getActiveRatingsNumber, getFilesSummary, checkIfLikedByUser, getLoggedUserRatingOnProduct, calculateProductLaplaceScore }; }(); class ProductGroupScrollWrapper extends React.Component { constructor(props) { super(props); this.state = { products: [], offset: 0 }; this.onProductGroupScroll = this.onProductGroupScroll.bind(this); this.loadMoreProducts = this.loadMoreProducts.bind(this); } componentWillMount() { window.addEventListener("scroll", this.onProductGroupScroll); } componentDidMount() { this.loadMoreProducts(); } onProductGroupScroll() { const end = $("footer").offset().top; const viewEnd = $(window).scrollTop() + $(window).height(); const distance = end - viewEnd; if (distance < 0 && this.state.loadingMoreProducts !== true) { this.setState({ loadingMoreProducts: true }, function () { this.loadMoreProducts(); }); } } loadMoreProducts() { const itemsPerScroll = 50; const moreProducts = store.getState().products.slice(this.state.offset, this.state.offset + itemsPerScroll); const products = this.state.products.concat(moreProducts); const offset = this.state.offset + itemsPerScroll; this.setState({ products: products, offset: offset, loadingMoreProducts: false }); } render() { let loadingMoreProductsDisplay; if (this.state.loadingMoreProducts) { loadingMoreProductsDisplay = React.createElement( "div", { className: "product-group-scroll-loading-container" }, React.createElement( "div", { className: "icon-wrapper" }, React.createElement("span", { className: "glyphicon glyphicon-refresh spinning" }) ) ); } return React.createElement( "div", { className: "product-group-scroll-wrapper" }, React.createElement(ProductGroup, { products: this.state.products, device: this.props.device }), loadingMoreProductsDisplay ); } } class ProductGroup extends React.Component { render() { let products; if (this.props.products) { let productsArray = this.props.products; if (this.props.numRows) { const limit = productHelpers.getNumberOfProducts(this.props.device, this.props.numRows); productsArray = productsArray.slice(0, limit); } products = productsArray.map((product, index) => React.createElement(ProductGroupItem, { key: index, product: product })); } let sectionHeader; if (this.props.title) { sectionHeader = React.createElement( "div", { className: "section-header" }, React.createElement( "h3", { className: "mdl-color-text--primary" }, this.props.title ), React.createElement( "div", { className: "actions" }, React.createElement( "a", { href: this.props.link, className: "mdl-button mdl-js-button mdl-button--colored mdl-button--raised mdl-js-ripple-effect mdl-color--primary" }, "see more" ) ) ); } return React.createElement( "div", { className: "products-showcase" }, sectionHeader, React.createElement( "div", { className: "products-container row" }, products ) ); } } class ProductGroupItem extends React.Component { render() { let imageBaseUrl; if (store.getState().env === 'live') { imageBaseUrl = 'cn.opendesktop.org'; } else { imageBaseUrl = 'cn.pling.it'; } return React.createElement( "div", { className: "product square" }, React.createElement( "div", { className: "content" }, React.createElement( "div", { className: "product-wrapper mdl-shadow--2dp" }, React.createElement( "a", - { href: window.baseUrl + "/p/" + this.props.product.project_id }, + { href: "/p/" + this.props.product.project_id }, React.createElement( "div", { className: "product-image-container" }, React.createElement( "figure", null, React.createElement("img", { className: "very-rounded-corners", src: 'https://' + imageBaseUrl + '/cache/200x171/img/' + this.props.product.image_small }), React.createElement( "span", { className: "product-info-title" }, this.props.product.title ) ) ), React.createElement( "div", { className: "product-info" }, React.createElement( "span", { className: "product-info-description" }, this.props.product.description ) ) ) ) ) ); } } const reducer = Redux.combineReducers({ products: productsReducer, product: productReducer, lightboxGallery: lightboxGalleryReducer, pagination: paginationReducer, topProducts: topProductsReducer, categories: categoriesReducer, comments: commentsReducer, users: usersReducer, user: userReducer, supporters: supportersReducer, domain: domainReducer, env: envReducer, device: deviceReducer, view: viewReducer, filters: filtersReducer }); /* reducers */ function productsReducer(state = {}, action) { if (action.type === 'SET_PRODUCTS') { return action.products; } else { return state; } } function productReducer(state = {}, action) { if (action.type === 'SET_PRODUCT') { return action.product; } else if (action.type === 'SET_PRODUCT_FILES') { const s = Object.assign({}, state, { r_files: action.files }); return s; } else if (action.type === 'SET_PRODUCT_UPDATES') { const s = Object.assign({}, state, { r_updates: action.updates }); return s; } else if (action.type === 'SET_PRODUCT_RATINGS') { const s = Object.assign({}, state, { r_ratings: action.ratings }); return s; } else if (action.type === 'SET_PRODUCT_LIKES') { const s = Object.assign({}, state, { r_likes: action.likes }); return s; } else if (action.type === 'SET_PRODUCT_PLINGS') { const s = Object.assign({}, state, { r_plings: action.plings }); return s; } else if (action.type === 'SET_PRODUCT_USER_RATINGS') { const s = Object.assign({}, state, { r_userRatings: action.userRatings }); return s; } else if (action.type === 'SET_PRODUCT_GALLERY') { const s = Object.assign({}, state, { r_gallery: action.gallery }); return s; } else if (action.type === 'SET_PRODUCT_COMMENTS') { const s = Object.assign({}, state, { r_comments: action.comments }); return s; } else if (action.type === 'SET_PRODUCT_ORIGINS') { const s = Object.assign({}, state, { r_origins: action.origins }); return s; } else if (action.type === 'SET_PRODUCT_RELATED') { const s = Object.assign({}, state, { r_related: action.related }); return s; } else if (action.type === 'SET_PRODUCT_MORE_PRODUCTS') { const s = Object.assign({}, state, { r_more_products: action.products }); return s; } else if (action.type === 'SET_PRODUCT_MORE_PRODUCTS_OTHER_USERS') { const s = Object.assign({}, state, { r_more_products_other_users: action.products }); return s; } else if (action.type === 'SET_PRODUCT_TAGS') { const s = Object.assign({}, state, { r_tags_user: action.userTags, r_tags_system: action.systemTags }); return s; } else { return state; } } function lightboxGalleryReducer(state = {}, action) { if (action.type === 'SHOW_LIGHTBOX') { const s = Object.assign({}, state, { show: true, currentItem: action.item }); return s; } else if (action.type === 'HIDE_LIGHTBOX') { const s = Object.assign({}, state, { show: false }); return s; } else { return state; } } function paginationReducer(state = {}, action) { if (action.type === 'SET_PAGINATION') { return action.pagination; } else { return state; } } function topProductsReducer(state = {}, action) { if (action.type === 'SET_TOP_PRODUCTS') { return action.products; } else { return state; } } function categoriesReducer(state = {}, action) { if (action.type === 'SET_CATEGORIES') { const s = Object.assign({}, state, { items: categories }); return s; } else if (action.type === 'SET_CURRENT_CAT') { const s = Object.assign({}, state, { current: action.cat }); return s; } else if (action.type === 'SET_CURRENT_SUBCAT') { const s = Object.assign({}, state, { currentSub: action.cat }); return s; } else if (action.type === 'SET_CURRENT_SECONDSUBCAT') { const s = Object.assign({}, state, { currentSecondSub: action.cat }); return s; } else { return state; } } function commentsReducer(state = {}, action) { if (action.type === 'SET_COMMENTS') { return action.comments; } else { return state; } } function usersReducer(state = {}, action) { if (action.type === 'SET_USERS') { return action.users; } else { return state; } } function userReducer(state = {}, action) { if (action.type === 'SET_USER') { return action.user; } else { return state; } } function supportersReducer(state = {}, action) { if (action.type === 'SET_SUPPORTERS') { return action.supporters; } else { return state; } } function domainReducer(state = {}, action) { if (action.type === 'SET_DOMAIN') { return action.domain; } else { return state; } } function envReducer(state = {}, action) { if (action.type === 'SET_ENV') { return action.env; } else { return state; } } function deviceReducer(state = {}, action) { if (action.type === 'SET_DEVICE') { return action.device; } else { return state; } } function viewReducer(state = {}, action) { if (action.type === 'SET_VIEW') { return action.view; } else { return state; } } function filtersReducer(state = {}, action) { if (action.type === 'SET_FILTERS') { return action.filters; } else { return state; } } /* /reducers */ /* dispatch */ function setProducts(products) { return { type: 'SET_PRODUCTS', products: products }; } function setProduct(product) { return { type: 'SET_PRODUCT', product: product }; } function setProductFiles(files) { return { type: 'SET_PRODUCT_FILES', files: files }; } function setProductUpdates(updates) { return { type: 'SET_PRODUCT_UPDATES', updates: updates }; } function setProductRatings(ratings) { return { type: 'SET_PRODUCT_RATINGS', ratings: ratings }; } function setProductLikes(likes) { return { type: 'SET_PRODUCT_LIKES', likes: likes }; } function setProductPlings(plings) { return { type: 'SET_PRODUCT_PLINGS', plings: plings }; } function setProductUserRatings(userRatings) { return { type: 'SET_PRODUCT_USER_RATINGS', userRatings: userRatings }; } function setProductGallery(gallery) { return { type: 'SET_PRODUCT_GALLERY', gallery: gallery }; } function setProductComments(comments) { return { type: 'SET_PRODUCT_COMMENTS', comments: comments }; } function setProductOrigins(origins) { return { type: 'SET_PRODUCT_ORIGINS', origins: origins }; } function setProductRelated(related) { return { type: 'SET_PRODUCT_RELATED', related: related }; } function setProductMoreProducts(products) { return { type: 'SET_PRODUCT_MORE_PRODUCTS', products: products }; } function setProductMoreProductsOtherUsers(products) { return { type: 'SET_PRODUCT_MORE_PRODUCTS_OTHER_USERS', products: products }; } function setProductTags(userTags, systemTags) { return { type: 'SET_PRODUCT_TAGS', userTags: userTags, systemTags: systemTags }; } function showLightboxGallery(num) { return { type: 'SHOW_LIGHTBOX', item: num }; } function hideLightboxGallery() { return { type: 'HIDE_LIGHTBOX' }; } function setPagination(pagination) { return { type: 'SET_PAGINATION', pagination: pagination }; } function setTopProducts(topProducts) { return { type: 'SET_TOP_PRODUCTS', products: topProducts }; } function setCategories(categories) { return { type: 'SET_CATEGORIES', categories: categories }; } function setCurrentCategory(cat) { return { type: 'SET_CURRENT_CAT', cat: cat }; } function setCurrentSubCategory(cat) { return { type: 'SET_CURRENT_SUBCAT', cat: cat }; } function setCurrentSecondSubCategory(cat) { return { type: 'SET_CURRENT_SECONDSUBCAT', cat: cat }; } function setComments(comments) { return { type: 'SET_COMMENTS', comments: comments }; } function setUsers(users) { return { type: 'SET_USERS', users: users }; } function setUser(user) { return { type: 'SET_USER', user: user }; } function setSupporters(supporters) { return { type: 'SET_SUPPORTERS', supporters: supporters }; } function setDomain(domain) { return { type: 'SET_DOMAIN', domain: domain }; } function setEnv(env) { return { type: 'SET_ENV', env: env }; } function setDevice(device) { return { type: 'SET_DEVICE', device: device }; } function setView(view) { return { type: 'SET_VIEW', view: view }; } function setFilters(filters) { return { type: 'SET_FILTERS', filters: filters }; } /* /dispatch */ class ExplorePage extends React.Component { constructor(props) { super(props); this.state = { device: store.getState().device, minHeight: 'auto' }; this.updateContainerHeight = this.updateContainerHeight.bind(this); } componentWillReceiveProps(nextProps) { if (nextProps.device) { this.setState({ device: nextProps.device }); } if (nextProps.products) { this.setState({ products: nextProps.products }); } if (nextProps.filters) { this.setState({ filters: filters }); } } updateContainerHeight(sideBarHeight) { this.setState({ minHeight: sideBarHeight + 100 }); } render() { let titleDisplay; if (this.props.categories) { let title = ""; if (this.props.categories.currentSecondSub) { title = this.props.categories.currentSecondSub.title; } else { if (this.props.categories.currentSub) { title = this.props.categories.currentSub.title; } else { if (this.props.categories.current) { title = this.props.categories.current.title; } } } if (title.length > 0) { titleDisplay = React.createElement( "div", { className: "explore-page-category-title" }, React.createElement( "h2", null, title ), React.createElement( "small", null, store.getState().pagination.totalcount, " results" ) ); } } return React.createElement( "div", { id: "explore-page" }, React.createElement( "div", { className: "wrapper" }, React.createElement( "div", { className: "main-content-container", style: { "minHeight": this.state.minHeight } }, React.createElement( "div", { className: "left-sidebar-container" }, React.createElement(ExploreLeftSideBarWrapper, { updateContainerHeight: this.updateContainerHeight }) ), React.createElement( "div", { className: "main-content" }, titleDisplay, React.createElement( "div", { className: "top-bar" }, React.createElement(ExploreTopBarWrapper, null) ), React.createElement( "div", { className: "explore-products-container" }, React.createElement(ProductGroupScrollWrapper, { device: this.state.device }), React.createElement(PaginationWrapper, null) ) ) ), React.createElement( "div", { className: "right-sidebar-container" }, React.createElement(ExploreRightSideBarWrapper, null) ) ) ); } } const mapStateToExploreProps = state => { const device = state.device; const products = state.products; const categories = state.categories; return { device, products, categories }; }; const mapDispatchToExploreProps = dispatch => { return { dispatch }; }; const ExplorePageWrapper = ReactRedux.connect(mapStateToExploreProps, mapDispatchToExploreProps)(ExplorePage); class ExploreTopBar extends React.Component { constructor(props) { super(props); this.state = {}; } render() { const categories = this.props.categories; let currentId; if (categories.current) { currentId = categories.current.id; } if (categories.currentSub) { currentId = categories.currentSub.id; } if (categories.currentSecondSub) { currentId = categories.currentSecondSub.id; } const link = appHelpers.generateFilterUrl(window.location, currentId); let linkSearch = ""; if (link.search) { linkSearch = link.search; } return React.createElement( "div", { className: "explore-top-bar" }, React.createElement( "a", { href: link.base + "latest" + linkSearch, className: this.props.filters.order === "latest" ? "item active" : "item" }, "Latest" ), React.createElement( "a", { href: link.base + "top" + linkSearch, className: this.props.filters.order === "top" ? "item active" : "item" }, "Top" ) ); } } const mapStateToExploreTopBarProps = state => { const filters = state.filters; const categories = state.categories; return { filters, categories }; }; const mapDispatchToExploreTopBarProps = dispatch => { return { dispatch }; }; const ExploreTopBarWrapper = ReactRedux.connect(mapStateToExploreTopBarProps, mapDispatchToExploreTopBarProps)(ExploreTopBar); class ExploreLeftSideBar extends React.Component { constructor(props) { super(props); this.state = {}; } componentDidMount() { const sideBarHeight = $('#left-sidebar').height(); this.props.updateContainerHeight(sideBarHeight); } render() { let categoryTree; if (this.props.categories) { categoryTree = this.props.categories.items.map((cat, index) => React.createElement(ExploreSideBarItem, { key: index, category: cat })); } return React.createElement( "aside", { className: "explore-left-sidebar", id: "left-sidebar" }, React.createElement( "ul", null, React.createElement( "li", { className: "category-item" }, React.createElement( "a", { className: this.props.categories.current === 0 ? "active" : "", href: "/browse/ord/" + filters.order }, React.createElement( "span", { className: "title" }, "All" ) ) ), categoryTree ) ); } } const mapStateToExploreLeftSideBarProps = state => { const categories = state.categories; const filters = state.filters; return { categories }; }; const mapDispatchToExploreLeftSideBarProps = dispatch => { return { dispatch }; }; const ExploreLeftSideBarWrapper = ReactRedux.connect(mapStateToExploreLeftSideBarProps, mapDispatchToExploreLeftSideBarProps)(ExploreLeftSideBar); class ExploreSideBarItem extends React.Component { render() { const order = store.getState().filters.order; const categories = store.getState().categories; let currentId, currentSubId, currentSecondSubId; if (categories.current) { currentId = categories.current.id; } if (categories.currentSub) { currentSubId = categories.currentSub.id; } if (categories.currentSecondSub) { currentSecondSubId = categories.currentSecondSub.id; } let active; if (currentId === this.props.category.id || currentSubId === this.props.category.id || currentSecondSubId === this.props.category.id) { active = true; } let subcatMenu; if (this.props.category.has_children === true && active) { const cArray = categoryHelpers.convertCatChildrenObjectToArray(this.props.category.children); const subcategories = cArray.map((cat, index) => React.createElement(ExploreSideBarItem, { key: index, category: cat })); subcatMenu = React.createElement( "ul", null, subcategories ); } return React.createElement( "li", { className: "category-item" }, React.createElement( "a", { className: active === true ? "active" : "", href: "/browse/cat/" + this.props.category.id + "/ord/" + order + window.location.search }, React.createElement( "span", { className: "title" }, this.props.category.title ), React.createElement( "span", { className: "product-counter" }, this.props.category.product_count ) ), subcatMenu ); } } class Pagination extends React.Component { constructor(props) { super(props); this.state = {}; } componentDidMount() { const itemsPerPage = 50; const numPages = Math.ceil(this.props.pagination.totalcount / itemsPerPage); const pagination = productHelpers.generatePaginationObject(numPages, window.location.pathname, this.props.currentCategoy, this.props.filters.order, this.props.pagination.page); this.setState({ pagination: pagination }, function () {}); } render() { let paginationDisplay; if (this.state.pagination && this.props.pagination.totalcount > 50) { const pagination = this.state.pagination.map((pi, index) => { let numberDisplay; if (pi.number === 'previous') { numberDisplay = React.createElement( "span", { className: "num-wrap" }, React.createElement( "i", { className: "material-icons" }, "arrow_back_ios" ), React.createElement( "span", null, pi.number ) ); } else if (pi.number === 'next') { numberDisplay = React.createElement( "span", { className: "num-wrap" }, React.createElement( "span", null, pi.number ), React.createElement( "i", { className: "material-icons" }, "arrow_forward_ios" ) ); } else { numberDisplay = pi.number; } let cssClass; if (pi.number === this.props.pagination.page) { cssClass = "active"; } return React.createElement( "li", { key: index }, React.createElement( "a", { href: pi.link, className: cssClass }, numberDisplay ) ); }); paginationDisplay = React.createElement( "ul", null, pagination ); } return React.createElement( "div", { id: "pagination-container" }, React.createElement( "div", { className: "wrapper" }, paginationDisplay ) ); } } const mapStateToPaginationProps = state => { const pagination = state.pagination; const filters = state.filters; const currentCategoy = state.categories.current; return { pagination, filters, currentCategoy }; }; const mapDispatchToPaginationProps = dispatch => { return { dispatch }; }; const PaginationWrapper = ReactRedux.connect(mapStateToPaginationProps, mapDispatchToPaginationProps)(Pagination); class ExploreRightSideBar extends React.Component { constructor(props) { super(props); this.state = {}; } render() { return React.createElement( "aside", { className: "explore-right-sidebar" }, React.createElement( "div", { className: "ers-section" }, React.createElement( "a", { href: "https://www.opendesktop.org/p/1175480/", target: "_blank" }, React.createElement("img", { id: "download-app", src: "/images/system/download-app.png" }) ) ), React.createElement( "div", { className: "ers-section" }, React.createElement( "a", { href: "/support", id: "become-a-supporter", className: "mdl-button mdl-js-button mdl-button--colored mdl-button--raised mdl-js-ripple-effect mdl-color--primary" }, "Become a supporter" ) ), React.createElement( "div", { className: "ers-section" }, React.createElement(ExploreSupportersContainerWrapper, null) ), React.createElement( "div", { className: "ers-section" }, React.createElement(RssNewsContainer, null) ), React.createElement( "div", { className: "ers-section" }, React.createElement(BlogFeedContainer, null) ), React.createElement( "div", { className: "ers-section" }, React.createElement(ExploreCommentsContainerWrapper, null) ), React.createElement( "div", { className: "ers-section" }, React.createElement(ExploreTopProductsWrapper, null) ) ); } } const mapStateToExploreRightSideBarProps = state => { const categories = state.categories; const filters = state.filters; return { categories }; }; const mapDispatchToExploreRightSideBarProps = dispatch => { return { dispatch }; }; const ExploreRightSideBarWrapper = ReactRedux.connect(mapStateToExploreRightSideBarProps, mapDispatchToExploreRightSideBarProps)(ExploreRightSideBar); class ExploreSupportersContainer extends React.Component { constructor(props) { super(props); this.state = {}; } render() { let supportersContainer; if (this.props.supporters) { const cArray = categoryHelpers.convertCatChildrenObjectToArray(this.props.supporters); const supporters = cArray.map((sp, index) => React.createElement( "div", { className: "supporter-item", key: index }, React.createElement( "a", { href: "/member/" + sp.member_id, className: "item" }, React.createElement("img", { src: sp.profile_image_url }) ) )); supportersContainer = React.createElement( "div", { className: "supporter-list-wrapper" }, supporters ); } return React.createElement( "div", { id: "supporters-container", className: "sidebar-feed-container" }, React.createElement( "h3", null, this.props.supporters.length, " people support those who create freedom" ), supportersContainer ); } } const mapStateToExploreSupportersContainerProps = state => { const supporters = state.supporters; return { supporters }; }; const mapDispatchToExploreSupportersContainerProps = dispatch => { return { dispatch }; }; const ExploreSupportersContainerWrapper = ReactRedux.connect(mapStateToExploreSupportersContainerProps, mapDispatchToExploreSupportersContainerProps)(ExploreSupportersContainer); class RssNewsContainer extends React.Component { constructor(props) { super(props); this.state = {}; } componentDidMount() { const self = this; $.getJSON("https://blog.opendesktop.org/?json=1&callback=?", function (res) { self.setState({ items: res.posts }); }); } render() { let feedItemsContainer; if (this.state.items) { const feedItems = this.state.items.slice(0, 3).map((fi, index) => React.createElement( "li", { key: index }, React.createElement( "a", { className: "title", href: fi.url }, React.createElement( "span", null, fi.title ) ), React.createElement( "span", { className: "info-row" }, React.createElement( "span", { className: "date" }, appHelpers.getTimeAgo(fi.date) ), React.createElement( "span", { className: "comment-counter" }, fi.comment_count, " comments" ) ) )); feedItemsContainer = React.createElement( "ul", null, feedItems ); } return React.createElement( "div", { id: "rss-new-container", className: "sidebar-feed-container" }, React.createElement( "h3", null, "News" ), feedItemsContainer ); } } class BlogFeedContainer extends React.Component { constructor(props) { super(props); this.state = {}; } componentDidMount() { const self = this; $.ajax("https://forum.opendesktop.org/latest.json").then(function (result) { let topics = result.topic_list.topics; topics.sort(function (a, b) { return new Date(b.last_posted_at) - new Date(a.last_posted_at); }); topics = topics.slice(0, 3); self.setState({ items: topics }); }); } render() { let feedItemsContainer; if (this.state.items) { const feedItems = this.state.items.map((fi, index) => React.createElement( "li", { key: index }, React.createElement( "a", { className: "title", href: "https://forum.opendesktop.org//t/" + fi.id }, React.createElement( "span", null, fi.title ) ), React.createElement( "span", { className: "info-row" }, React.createElement( "span", { className: "date" }, appHelpers.getTimeAgo(fi.created_at) ), React.createElement( "span", { className: "comment-counter" }, fi.reply_count, " replies" ) ) )); feedItemsContainer = React.createElement( "ul", null, feedItems ); } return React.createElement( "div", { id: "blog-feed-container", className: "sidebar-feed-container" }, React.createElement( "h3", null, "Forum" ), feedItemsContainer ); } } class ExploreCommentsContainer extends React.Component { constructor(props) { super(props); this.state = {}; } render() { let commentsContainer; if (this.props.comments) { const comments = this.props.comments.map((cm, index) => React.createElement( "li", { key: index }, React.createElement( "div", { className: "cm-content" }, React.createElement( "span", { className: "cm-userinfo" }, React.createElement("img", { src: cm.profile_image_url }), React.createElement( "span", { className: "username" }, React.createElement( "a", { href: "/p/" + cm.comment_target_id }, cm.username ) ) ), React.createElement( "a", { className: "title", href: "/member/" + cm.member_id }, React.createElement( "span", null, cm.title ) ), React.createElement( "span", { className: "content" }, cm.comment_text ), React.createElement( "span", { className: "info-row" }, React.createElement( "span", { className: "date" }, appHelpers.getTimeAgo(cm.comment_created_at) ) ) ) )); commentsContainer = React.createElement( "ul", null, comments ); } return React.createElement( "div", { id: "blog-feed-container", className: "sidebar-feed-container" }, React.createElement( "h3", null, "Forum" ), commentsContainer ); } } const mapStateToExploreCommentsContainerProps = state => { const comments = state.comments; return { comments }; }; const mapDispatchToExploreCommentsContainerProps = dispatch => { return { dispatch }; }; const ExploreCommentsContainerWrapper = ReactRedux.connect(mapStateToExploreCommentsContainerProps, mapDispatchToExploreCommentsContainerProps)(ExploreCommentsContainer); class ExploreTopProducts extends React.Component { constructor(props) { super(props); this.state = {}; } render() { let topProductsContainer; if (this.props.topProducts) { let imageBaseUrl; if (store.getState().env === 'live') { imageBaseUrl = 'cn.opendesktop.org'; } else { imageBaseUrl = 'cn.pling.it'; } const topProducts = this.props.topProducts.map((tp, index) => React.createElement( "li", { key: index }, React.createElement("img", { src: "https://" + imageBaseUrl + "/cache/40x40/img/" + tp.image_small }), React.createElement( "a", { href: "/p/" + tp.project_id }, tp.title ), React.createElement( "span", { className: "cat-name" }, tp.cat_title ) )); topProductsContainer = React.createElement( "ol", null, topProducts ); } return React.createElement( "div", { id: "top-products-container", className: "sidebar-feed-container" }, React.createElement( "h3", null, "3 Months Ranking" ), React.createElement( "small", null, "(based on downloads)" ), topProductsContainer ); } } const mapStateToExploreTopProductsProps = state => { const topProducts = state.topProducts; return { topProducts }; }; const mapDispatchToExploreTopProductsProps = dispatch => { return { dispatch }; }; const ExploreTopProductsWrapper = ReactRedux.connect(mapStateToExploreTopProductsProps, mapDispatchToExploreTopProductsProps)(ExploreTopProducts); class HomePage extends React.Component { constructor(props) { super(props); this.state = { device: store.getState().device, products: store.getState().products }; } componentWillReceiveProps(nextProps) { if (nextProps.device) { this.setState({ device: nextProps.device }); } if (nextProps.products) { this.setState({ products: nextProps.products }); } } render() { return React.createElement( "div", { id: "homepage" }, React.createElement( "div", { className: "hp-wrapper" }, React.createElement(Introduction, { device: this.state.device, count: window.totalProjects }) ) ); } } const mapStateToHomePageProps = state => { const device = state.device; const products = state.products; return { device, products }; }; const mapDispatchToHomePageProps = dispatch => { return { dispatch }; }; const HomePageWrapper = ReactRedux.connect(mapStateToHomePageProps, mapDispatchToHomePageProps)(HomePage); class Introduction extends React.Component { render() { let introductionText, siteTitle, buttonsContainer; if (window.page === "appimages") { siteTitle = "AppImageHub"; introductionText = React.createElement( "p", null, "This catalog has AppImages and counting.", React.createElement("br", null), "AppImages are self-contained apps which can simply be downloaded & run on any Linux distribution. For easy integration, download AppImageLauncher:" ); buttonsContainer = React.createElement( "div", { className: "actions" }, React.createElement( "a", { href: "/p/1228228", className: "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored mdl-color--primary" }, React.createElement("img", { src: "/theme/react/assets/img/icon-download_white.png" }), " AppImageLauncher" ), React.createElement( "a", { href: "/browse", className: "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored mdl-color--primary" }, "Browse all apps" ) ); } else if (window.page === "libreoffice") { siteTitle = "LibreOffice"; introductionText = React.createElement( "p", null, "Extensions add new features to your LibreOffice or make the use of already existing ones easier. Currently there are ", this.props.count, " project(s) available." ); buttonsContainer = React.createElement( "div", { className: "actions green" }, React.createElement( "a", { href: window.baseUrl + "product/add", className: "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored mdl-color--primary" }, "Add Extension" ), React.createElement( "a", { href: window.baseUrl + "browse", className: "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored mdl-color--primary" }, "Browse all Extensions" ) ); } return React.createElement( "div", { id: "introduction", className: "section" }, React.createElement( "div", { className: "container" }, React.createElement( "article", null, React.createElement( "h2", { className: "mdl-color-text--primary" }, "Welcome to ", siteTitle ), introductionText, buttonsContainer ) ) ); } } class HpIntroSection extends React.Component { constructor(props) { super(props); this.state = {}; } render() { return React.createElement( "div", { id: "homepage-search-container", className: "section intro" }, React.createElement( "div", { className: "container" }, React.createElement( "article", null, React.createElement( "p", null, "Search thousands of snaps used by millions of people across 50 Linux distributions" ) ), React.createElement( "div", { id: "hp-search-form-container" }, React.createElement( "select", { className: "mdl-selectfield__select" }, React.createElement( "option", null, "categories" ) ), React.createElement("input", { type: "text" }), React.createElement( "button", null, "search" ) ) ) ); } } const mapStateToHpIntroSectionProps = state => { const categories = state.categories; return { categories }; }; const mapDispatchToHpIntroSectionProps = dispatch => { return { dispatch }; }; const HpIntroSectionWrapper = ReactRedux.connect(mapStateToHpIntroSectionProps, mapDispatchToHpIntroSectionProps)(HpIntroSection); class ProductCarousel extends React.Component { constructor(props) { super(props); this.state = { showRightArrow: true, showLeftArrow: false }; this.updateDimensions = this.updateDimensions.bind(this); this.animateProductCarousel = this.animateProductCarousel.bind(this); } componentWillMount() { window.addEventListener("resize", this.updateDimensions); } componentDidMount() { this.updateDimensions(); } updateDimensions() { const containerWidth = $('#introduction').find('.container').width(); const sliderWidth = containerWidth * 3; const itemWidth = containerWidth / 5; this.setState({ sliderPosition: 0, containerWidth: containerWidth, sliderWidth: sliderWidth, itemWidth: itemWidth }); } animateProductCarousel(dir) { let newSliderPosition = this.state.sliderPosition; if (dir === 'left') { newSliderPosition = this.state.sliderPosition - this.state.containerWidth; } else { newSliderPosition = this.state.sliderPosition + this.state.containerWidth; } this.setState({ sliderPosition: newSliderPosition }, function () { let showLeftArrow = true, showRightArrow = true; const endPoint = this.state.sliderWidth - this.state.containerWidth; if (this.state.sliderPosition <= 0) { showLeftArrow = false; } if (this.state.sliderPosition >= endPoint) { showRightArrow = false; } this.setState({ showLeftArrow: showLeftArrow, showRightArrow: showRightArrow }); }); } render() { let carouselItemsDisplay; if (this.props.products && this.props.products.length > 0) { carouselItemsDisplay = this.props.products.map((product, index) => React.createElement(ProductCarouselItem, { key: index, product: product, itemWidth: this.state.itemWidth, baseUrl: this.props.baseUrl })); } let rightArrowDisplay, leftArrowDisplay; if (this.state.showLeftArrow) { leftArrowDisplay = React.createElement( "div", { className: "product-carousel-left" }, React.createElement( "a", { onClick: () => this.animateProductCarousel('left'), className: "carousel-arrow arrow-left" }, React.createElement( "i", { className: "material-icons" }, "chevron_left" ) ) ); } if (this.state.showRightArrow) { rightArrowDisplay = React.createElement( "div", { className: "product-carousel-right" }, React.createElement( "a", { onClick: () => this.animateProductCarousel('right'), className: "carousel-arrow arrow-right" }, React.createElement( "i", { className: "material-icons" }, "chevron_right" ) ) ); } return React.createElement( "div", { className: "product-carousel" }, React.createElement( "div", { className: "product-carousel-header" }, React.createElement( "h2", null, React.createElement( "a", { href: this.props.link }, this.props.title, React.createElement( "i", { className: "material-icons" }, "chevron_right" ) ) ) ), React.createElement( "div", { className: "product-carousel-wrapper" }, leftArrowDisplay, React.createElement( "div", { className: "product-carousel-container" }, React.createElement( "div", { className: "product-carousel-slider", style: { "width": this.state.sliderWidth, "left": "-" + this.state.sliderPosition + "px" } }, carouselItemsDisplay ) ), rightArrowDisplay ) ); } } class ProductCarouselItem extends React.Component { constructor(props) { super(props); this.state = {}; } render() { let imageBaseUrl; if (store.getState().env === 'live') { imageBaseUrl = 'cn.opendesktop.org'; } else { imageBaseUrl = 'cn.pling.it'; } return React.createElement( "div", { className: "product-carousel-item", style: { "width": this.props.itemWidth } }, React.createElement( "a", - { href: window.baseUrl + "p/" + this.props.product.project_id }, + { href: "p/" + this.props.product.project_id }, React.createElement( "figure", null, React.createElement("img", { className: "very-rounded-corners", src: 'https://' + imageBaseUrl + '/cache/200x171/img/' + this.props.product.image_small }) ), React.createElement( "div", { className: "product-info" }, React.createElement( "span", { className: "product-info-title" }, this.props.product.title ), React.createElement( "span", { className: "product-info-user" }, this.props.product.username ) ) ) ); } } class ProductView extends React.Component { constructor(props) { super(props); this.state = { tab: 'comments', showDownloadSection: false }; this.toggleTab = this.toggleTab.bind(this); this.toggleDownloadSection = this.toggleDownloadSection.bind(this); } componentDidMount() { let downloadTableHeight = $('#product-download-section').find('#files-tab').height(); downloadTableHeight += 80; this.setState({ downloadTableHeight: downloadTableHeight }); } componentWillReceiveProps(nextProps) { if (nextProps.product !== this.props.product) { this.forceUpdate(); } if (nextProps.lightboxGallery !== this.props.lightboxGallery) { this.forceUpdate(); } } toggleTab(tab) { this.setState({ tab: tab }); } toggleDownloadSection() { let showDownloadSection = this.state.showDownloadSection === true ? false : true; this.setState({ showDownloadSection: showDownloadSection }); } render() { let productGalleryDisplay; if (this.props.product.r_gallery.length > 0) { productGalleryDisplay = React.createElement(ProductViewGallery, { product: this.props.product }); } let productGalleryLightboxDisplay; if (this.props.lightboxGallery.show === true) { productGalleryLightboxDisplay = React.createElement(ProductGalleryLightbox, { product: this.props.product }); } let downloadSectionDisplayHeight; if (this.state.showDownloadSection === true) { downloadSectionDisplayHeight = this.state.downloadTableHeight; } return React.createElement( 'div', { id: 'product-page' }, React.createElement( 'div', { id: 'product-download-section', style: { "height": downloadSectionDisplayHeight } }, React.createElement(ProductViewFilesTab, { product: this.props.product, files: this.props.product.r_files }) ), React.createElement(ProductViewHeader, { product: this.props.product, user: this.props.user, onDownloadBtnClick: this.toggleDownloadSection }), productGalleryDisplay, React.createElement(ProductDescription, { product: this.props.product }), React.createElement(ProductNavBar, { onTabToggle: this.toggleTab, tab: this.state.tab, product: this.props.product }), React.createElement(ProductViewContent, { product: this.props.product, user: this.props.user, tab: this.state.tab }), productGalleryLightboxDisplay ); } } const mapStateToProductPageProps = state => { const product = state.product; const user = state.user; const lightboxGallery = state.lightboxGallery; return { product, user, lightboxGallery }; }; const mapDispatchToProductPageProps = dispatch => { return { dispatch }; }; const ProductViewWrapper = ReactRedux.connect(mapStateToProductPageProps, mapDispatchToProductPageProps)(ProductView); class ProductViewHeader extends React.Component { constructor(props) { super(props); this.state = {}; } render() { let imageBaseUrl; if (store.getState().env === 'live') { imageBaseUrl = 'cn.opendesktop.org'; } else { imageBaseUrl = 'cn.pling.it'; } let productTagsDisplay; if (this.props.product.r_tags_user) { const tagsArray = this.props.product.r_tags_user.split(','); const tags = tagsArray.map((tag, index) => React.createElement( 'span', { className: 'mdl-chip', key: index }, React.createElement( 'span', { className: 'mdl-chip__text' }, React.createElement('span', { className: 'glyphicon glyphicon-tag' }), React.createElement( 'a', { href: "search/projectSearchText/" + tag + "/f/tags" }, tag ) ) )); productTagsDisplay = React.createElement( 'div', { className: 'product-tags' }, tags ); } return React.createElement( 'div', { className: 'wrapper', id: 'product-view-header' }, React.createElement( 'div', { className: 'container' }, React.createElement( 'div', { className: 'section mdl-grid' }, React.createElement( 'div', { className: 'product-view-header-left' }, React.createElement( 'figure', { className: 'image-container' }, React.createElement('img', { src: 'https://' + imageBaseUrl + '/cache/140x140/img/' + this.props.product.image_small }) ), React.createElement( 'div', { className: 'product-info' }, React.createElement( 'h1', null, this.props.product.title ), React.createElement( 'div', { className: 'info-row' }, React.createElement( 'a', { className: 'user', href: "/member/" + this.props.product.member_id }, React.createElement( 'span', { className: 'avatar' }, React.createElement('img', { src: this.props.product.profile_image_url }) ), React.createElement( 'span', { className: 'username' }, this.props.product.username ) ), React.createElement( 'a', { href: "/browse/cat/" + this.props.product.project_category_id + "/order/latest?new=1" }, React.createElement( 'span', null, this.props.product.cat_title ) ), productTagsDisplay ) ) ), React.createElement( 'div', { className: 'product-view-header-right' }, React.createElement( 'div', { className: 'details-container' }, React.createElement( 'a', { onClick: this.props.onDownloadBtnClick, href: '#', className: 'mdl-button mdl-js-button mdl-button--colored mdl-button--raised mdl-js-ripple-effect mdl-color--primary' }, 'Download' ), React.createElement(ProductViewHeaderLikes, { product: this.props.product, user: this.props.user }), React.createElement( 'div', { id: 'product-view-header-right-side' }, React.createElement(ProductViewHeaderRatings, { product: this.props.product, user: this.props.user }) ) ) ) ) ) ); } } class ProductViewHeaderLikes extends React.Component { constructor(props) { super(props); this.state = {}; this.onUserLike = this.onUserLike.bind(this); } componentDidMount() { const user = store.getState().user; const likedByUser = productHelpers.checkIfLikedByUser(user, this.props.product.r_likes); this.setState({ likesTotal: this.props.product.r_likes.length, likedByUser: likedByUser }); } onUserLike() { if (this.props.user.username) { const url = "/p/" + this.props.product.project_id + "/followproject/"; const self = this; $.ajax({ url: url, cache: false }).done(function (response) { // error if (response.status === "error") { self.setState({ msg: response.msg }); } else { // delete if (response.action === "delete") { const likesTotal = self.state.likesTotal - 1; self.setState({ likesTotal: likesTotal, likedByUser: false }); } // insert else { const likesTotal = self.state.likesTotal + 1; self.setState({ likesTotal: likesTotal, likedByUser: true }); } } }); } else { this.setState({ msg: 'please login to like' }); } } render() { let cssContainerClass, cssHeartClass; if (this.state.likedByUser === true) { cssContainerClass = "liked-by-user"; cssHeartClass = "plingheart fa heartproject fa-heart"; } else { cssHeartClass = "plingheart fa fa-heart-o heartgrey"; } return React.createElement( 'div', { className: cssContainerClass, id: 'likes-container' }, React.createElement( 'div', { className: 'likes' }, React.createElement('i', { className: cssHeartClass }), React.createElement( 'span', { onClick: this.onUserLike }, this.state.likesTotal ) ), React.createElement( 'div', { className: 'likes-label-container' }, this.state.msg ) ); } } class ProductViewHeaderRatings extends React.Component { constructor(props) { super(props); this.state = { userIsOwner: '', action: '', laplace_score: this.props.product.laplace_score }; this.onRatingFormResponse = this.onRatingFormResponse.bind(this); } componentDidMount() { let userIsOwner = false; if (this.props.user && this.props.user.member_id === this.props.product.member_id) { userIsOwner = true; } let userRating = -1; if (userIsOwner === false) { userRating = productHelpers.getLoggedUserRatingOnProduct(this.props.user, this.props.product.r_ratings); } this.setState({ userIsOwner: userIsOwner, userRating: userRating }); } onRatingBtnClick(action) { this.setState({ showModal: false }, function () { this.setState({ action: action, showModal: true }, function () { $('#ratings-form-modal').modal('show'); }); }); } onRatingFormResponse(modalResponse, val) { const self = this; this.setState({ errorMsg: '' }, function () { jQuery.ajax({ data: {}, url: '/p/' + this.props.product.project_id + '/loadratings/', method: 'get', error: function (jqXHR, textStatus, errorThrown) { self.setState({ errorMsg: textStatus + " " + errorThrown }); $('#ratings-form-modal').modal('hide'); }, success: function (response) { // const laplace_score = productHelpers.calculateProductLaplaceScore(response); store.dispatch(setProductRatings(response)); if (modalResponse.status !== "ok") self.setState({ errorMsg: modalResponse.status + " - " + modalResponse.message }); self.setState({ laplace_score: modalResponse.laplace_score }, function () {}); $('#ratings-form-modal').modal('hide'); } }); }); } render() { let ratingsFormModalDisplay; if (this.state.showModal === true) { if (this.props.user.username) { ratingsFormModalDisplay = React.createElement(RatingsFormModal, { user: this.props.user, userIsOwner: this.state.userIsOwner, userRating: this.state.userRating, action: this.state.action, product: this.props.product, onRatingFormResponse: this.onRatingFormResponse }); } else { ratingsFormModalDisplay = React.createElement( 'div', { className: 'modal please-login', id: 'ratings-form-modal', tabIndex: '-1', role: 'dialog' }, React.createElement( 'div', { className: 'modal-dialog', role: 'document' }, React.createElement( 'div', { className: 'modal-content' }, React.createElement( 'div', { className: 'modal-header' }, React.createElement( 'h4', { className: 'modal-title' }, 'Please Login' ), React.createElement( 'button', { type: 'button', id: 'review-modal-close', className: 'close', 'data-dismiss': 'modal', 'aria-label': 'Close' }, React.createElement( 'span', { 'aria-hidden': 'true' }, '\xD7' ) ) ), React.createElement( 'div', { className: 'modal-body' }, React.createElement( 'a', { href: '/login/' }, 'Login' ) ) ) ) ); } } return React.createElement( 'div', { className: 'ratings-bar-container' }, React.createElement( 'div', { className: 'ratings-bar-left', onClick: () => this.onRatingBtnClick('minus') }, React.createElement( 'i', { className: 'material-icons' }, 'remove' ) ), React.createElement( 'div', { className: 'ratings-bar-holder' }, React.createElement('div', { className: 'green ratings-bar', style: { "width": this.state.laplace_score + "%" } }), React.createElement('div', { className: 'ratings-bar-empty', style: { "width": 100 - this.state.laplace_score + "%" } }) ), React.createElement( 'div', { className: 'ratings-bar-right', onClick: () => this.onRatingBtnClick('plus') }, React.createElement( 'i', { className: 'material-icons' }, 'add' ) ), ratingsFormModalDisplay, React.createElement( 'p', { className: 'ratings-bar-error-msg-container' }, this.state.errorMsg ) ); } } class RatingsFormModal extends React.Component { constructor(props) { super(props); this.state = { action: this.props.action }; this.submitRatingForm = this.submitRatingForm.bind(this); this.onTextAreaInputChange = this.onTextAreaInputChange.bind(this); } componentDidMount() { let actionIcon; if (this.props.action === 'plus') { actionIcon = '+'; } else if (this.props.action === 'minus') { actionIcon = '-'; } this.setState({ action: this.props.action, actionIcon: actionIcon, text: actionIcon }, function () { this.forceUpdate(); }); } onTextAreaInputChange(e) { this.setState({ text: e.target.value }); } submitRatingForm() { this.setState({ loading: true }, function () { const self = this; let v; if (this.state.action === 'plus') { v = '1'; } else { v = '2'; } jQuery.ajax({ data: { p: this.props.product.project_id, m: this.props.user.member_id, v: v, pm: this.props.product.member_id, otxt: this.state.text, userrate: this.props.userRating, msg: this.state.text }, url: '/productcomment/addreplyreview/', method: 'post', error: function () { const msg = "Service is temporarily unavailable. Our engineers are working quickly to resolve this issue.
Find out why you may have encountered this error."; self.setState({ msg: msg }); }, success: function (response) { self.props.onRatingFormResponse(response, v); } }); }); } render() { let textAreaDisplay, modalBtnDisplay; if (!this.props.user) { textAreaDisplay = React.createElement( 'p', null, 'Please login to comment' ); modalBtnDisplay = React.createElement( 'button', { type: 'button', className: 'btn btn-secondary', 'data-dismiss': 'modal' }, 'Close' ); } else { if (this.props.userIsOwner) { textAreaDisplay = React.createElement( 'p', null, 'Project owner not allowed' ); modalBtnDisplay = React.createElement( 'button', { type: 'button', className: 'btn btn-secondary', 'data-dismiss': 'modal' }, 'Close' ); } else if (this.state.text) { textAreaDisplay = React.createElement('textarea', { onChange: this.onTextAreaInputChange, defaultValue: this.state.text, className: 'form-control' }); if (this.state.loading !== true) { if (this.state.msg) { modalBtnDisplay = React.createElement( 'p', null, this.state.msg ); } else { modalBtnDisplay = React.createElement( 'button', { onClick: this.submitRatingForm, type: 'button', className: 'btn btn-primary' }, 'Rate Now' ); } } else { modalBtnDisplay = React.createElement('span', { className: 'glyphicon glyphicon-refresh spinning' }); } } } return React.createElement( 'div', { className: 'modal', id: 'ratings-form-modal', tabIndex: '-1', role: 'dialog' }, React.createElement( 'div', { className: 'modal-dialog', role: 'document' }, React.createElement( 'div', { className: 'modal-content' }, React.createElement( 'div', { className: 'modal-header' }, React.createElement( 'div', { className: this.props.action + " action-icon-container" }, this.state.actionIcon ), React.createElement( 'h5', { className: 'modal-title' }, 'Add Comment (min. 1 char):' ), React.createElement( 'button', { type: 'button', id: 'review-modal-close', className: 'close', 'data-dismiss': 'modal', 'aria-label': 'Close' }, React.createElement( 'span', { 'aria-hidden': 'true' }, '\xD7' ) ) ), React.createElement( 'div', { className: 'modal-body' }, textAreaDisplay ), React.createElement( 'div', { className: 'modal-footer' }, modalBtnDisplay ) ) ) ); } } class ProductViewGallery extends React.Component { constructor(props) { super(props); this.state = { loading: true, currentItem: 1, galleryWrapperMarginLeft: 0 }; this.updateDimensions = this.updateDimensions.bind(this); this.onLeftArrowClick = this.onLeftArrowClick.bind(this); this.onRightArrowClick = this.onRightArrowClick.bind(this); this.animateGallerySlider = this.animateGallerySlider.bind(this); } componentDidMount() { window.addEventListener("resize", this.updateDimensions); this.updateDimensions(); } componentWillUnmount() { window.removeEventListener("resize", this.updateDimensions); } updateDimensions() { const productGallery = document.getElementById('product-gallery'); const itemsWidth = 300; const itemsTotal = this.props.product.r_gallery.length + 1; this.setState({ itemsWidth: itemsWidth, itemsTotal: itemsTotal, loading: false }); } onLeftArrowClick() { let nextItem; if (this.state.currentItem <= 1) { nextItem = this.state.itemsTotal; } else { nextItem = this.state.currentItem - 1; } const marginLeft = this.state.itemsWidth * (nextItem - 1); this.animateGallerySlider(nextItem, marginLeft); } onRightArrowClick() { let nextItem; if (this.state.currentItem === this.state.itemsTotal) { nextItem = 1; } else { nextItem = this.state.currentItem + 1; } const marginLeft = this.state.itemsWidth * (nextItem - 1); this.animateGallerySlider(nextItem, marginLeft); } animateGallerySlider(nextItem, marginLeft) { this.setState({ currentItem: nextItem, galleryWrapperMarginLeft: "-" + marginLeft + "px" }); } onGalleryItemClick(num) { store.dispatch(showLightboxGallery(num)); } render() { let galleryDisplay; if (this.props.product.embed_code && this.props.product.embed_code.length > 0) { let imageBaseUrl; if (store.getState().env === 'live') { imageBaseUrl = 'http://cn.opendesktop.org'; } else { imageBaseUrl = 'http://cn.pling.it'; } if (this.props.product.r_gallery.length > 0) { const itemsWidth = this.state.itemsWidth; const currentItem = this.state.currentItem; const self = this; const moreItems = this.props.product.r_gallery.map((gi, index) => React.createElement( 'div', { key: index, onClick: () => this.onGalleryItemClick(index + 2), className: currentItem === index + 2 ? "active-gallery-item gallery-item" : "gallery-item" }, React.createElement('img', { className: 'media-item', src: imageBaseUrl + "/img/" + gi }) )); galleryDisplay = React.createElement( 'div', { id: 'product-gallery' }, React.createElement( 'a', { className: 'gallery-arrow arrow-left', onClick: this.onLeftArrowClick }, React.createElement( 'i', { className: 'material-icons' }, 'chevron_left' ) ), React.createElement( 'div', { className: 'section' }, React.createElement( 'div', { style: { "width": this.state.itemsWidth * this.state.itemsTotal + "px", "marginLeft": this.state.galleryWrapperMarginLeft }, className: 'gallery-items-wrapper' }, React.createElement('div', { onClick: () => this.onGalleryItemClick(1), dangerouslySetInnerHTML: { __html: this.props.product.embed_code }, className: this.state.currentItem === 1 ? "active-gallery-item gallery-item" : "gallery-item" }), moreItems ) ), React.createElement( 'a', { className: 'gallery-arrow arrow-right', onClick: this.onRightArrowClick }, React.createElement( 'i', { className: 'material-icons' }, 'chevron_right' ) ) ); } } return React.createElement( 'div', { className: 'section', id: 'product-view-gallery-container' }, React.createElement( 'div', { className: 'container' }, React.createElement( 'div', { className: 'section' }, galleryDisplay ) ) ); } } class ProductGalleryLightbox extends React.Component { constructor(props) { super(props); let currentItem; if (store.getState().lightboxGallery) { currentItem = store.getState().lightboxGallery.currentItem; } else { currentItem = 1; } this.state = { currentItem: currentItem, loading: true }; this.updateDimensions = this.updateDimensions.bind(this); this.toggleNextGalleryItem = this.toggleNextGalleryItem.bind(this); this.togglePrevGalleryItem = this.togglePrevGalleryItem.bind(this); this.animateGallerySlider = this.animateGallerySlider.bind(this); this.onThumbnailClick = this.onThumbnailClick.bind(this); } componentDidMount() { window.addEventListener("resize", this.updateDimensions); this.updateDimensions(); } componentWillUnmount() { window.removeEventListener("resize", this.updateDimensions); } updateDimensions() { const thumbnailsSectionWidth = document.getElementById('thumbnails-section').offsetWidth; const itemsWidth = 300; const itemsTotal = this.props.product.r_gallery.length + 1; let thumbnailsMarginLeft = 0; if (this.state.currentItem * itemsWidth > thumbnailsSectionWidth) { thumbnailsMarginLeft = thumbnailsSectionWidth - this.state.currentItem * itemsWidth; } this.setState({ itemsWidth: itemsWidth, itemsTotal: itemsTotal, thumbnailsSectionWidth: thumbnailsSectionWidth, thumbnailsMarginLeft: thumbnailsMarginLeft, loading: false }); } togglePrevGalleryItem() { let nextItem; if (this.state.currentItem <= 1) { nextItem = this.state.itemsTotal; } else { nextItem = this.state.currentItem - 1; } this.animateGallerySlider(nextItem); } toggleNextGalleryItem() { let nextItem; if (this.state.currentItem === this.state.itemsTotal) { nextItem = 1; } else { nextItem = this.state.currentItem + 1; } this.animateGallerySlider(nextItem); } animateGallerySlider(currentItem) { this.setState({ currentItem: currentItem }, function () { this.updateDimensions(); }); } onThumbnailClick(num) { this.animateGallerySlider(num); } hideLightbox() { store.dispatch(hideLightboxGallery()); } render() { let imageBaseUrl; if (store.getState().env === 'live') { imageBaseUrl = 'http://cn.opendesktop.org'; } else { imageBaseUrl = 'http://cn.pling.it'; } const currentItem = this.state.currentItem; const self = this; const thumbnails = this.props.product.r_gallery.map((gi, index) => React.createElement( 'div', { key: index, onClick: () => self.onThumbnailClick(index + 2), className: self.state.currentItem === index + 2 ? "active thumbnail-item" : "thumbnail-item" }, React.createElement('img', { className: 'media-item', src: imageBaseUrl + "/img/" + gi }) )); let mainItemDisplay; if (currentItem === 1) { mainItemDisplay = React.createElement('div', { dangerouslySetInnerHTML: { __html: this.props.product.embed_code } }); } else { const mainItem = this.props.product.r_gallery[currentItem - 2]; mainItemDisplay = React.createElement('img', { className: 'media-item', src: imageBaseUrl + "/img/" + mainItem }); } return React.createElement( 'div', { id: 'product-gallery-lightbox' }, React.createElement( 'a', { id: 'close-lightbox', onClick: this.hideLightbox }, React.createElement( 'i', { className: 'material-icons' }, 'cancel' ) ), React.createElement( 'div', { id: 'lightbox-gallery-main-view' }, React.createElement( 'a', { className: 'gallery-arrow', onClick: this.togglePrevGalleryItem, id: 'arrow-left' }, React.createElement( 'i', { className: 'material-icons' }, 'chevron_left' ) ), React.createElement( 'div', { className: 'current-gallery-item' }, mainItemDisplay ), React.createElement( 'a', { className: 'gallery-arrow', onClick: this.toggleNextGalleryItem, id: 'arrow-right' }, React.createElement( 'i', { className: 'material-icons' }, 'chevron_right' ) ) ), React.createElement( 'div', { id: 'lightbox-gallery-thumbnails' }, React.createElement( 'div', { className: 'section', id: 'thumbnails-section' }, React.createElement( 'div', { id: 'gallery-items-wrapper', style: { "width": this.state.itemsTotal * this.state.itemsWidth + "px", "marginLeft": this.state.thumbnailsMarginLeft + "px" } }, React.createElement('div', { onClick: () => this.onThumbnailClick(1), dangerouslySetInnerHTML: { __html: this.props.product.embed_code }, className: this.state.currentItem === 1 ? "active thumbnail-item" : "thumbnail-item" }), thumbnails ) ) ) ); } } class ProductDescription extends React.Component { constructor(props) { super(props); this.state = {}; } render() { return React.createElement( 'div', { id: 'product-description', className: 'section' }, React.createElement( 'div', { className: 'container' }, React.createElement( 'div', { className: 'main-content' }, React.createElement( 'article', null, React.createElement('p', { dangerouslySetInnerHTML: { __html: this.props.product.description } }) ), React.createElement( 'aside', null, React.createElement( 'ul', null, React.createElement( 'li', null, React.createElement( 'span', { className: 'key' }, 'License' ), React.createElement( 'span', { className: 'val' }, this.props.product.project_license_title ) ), React.createElement( 'li', null, React.createElement( 'span', { className: 'key' }, 'Last Update' ), React.createElement( 'span', { className: 'val' }, this.props.product.changed_at.split(' ')[0] ) ) ) ) ) ) ); } } class ProductNavBar extends React.Component { render() { let productNavBarDisplay; let filesMenuItem, ratingsMenuItem, favsMenuItem, plingsMenuItem; if (this.props.product.r_files.length > 0) { filesMenuItem = React.createElement( 'a', { className: this.props.tab === "files" ? "item active" : "item", onClick: () => this.props.onTabToggle('files') }, 'Files (', this.props.product.r_files.length, ')' ); } if (this.props.product.r_ratings.length > 0) { const activeRatingsNumber = productHelpers.getActiveRatingsNumber(this.props.product.r_ratings); ratingsMenuItem = React.createElement( 'a', { className: this.props.tab === "ratings" ? "item active" : "item", onClick: () => this.props.onTabToggle('ratings') }, 'Ratings & Reviews (', activeRatingsNumber, ')' ); } if (this.props.product.r_likes.length > 0) { favsMenuItem = React.createElement( 'a', { className: this.props.tab === "favs" ? "item active" : "item", onClick: () => this.props.onTabToggle('favs') }, 'Favs (', this.props.product.r_likes.length, ')' ); } if (this.props.product.r_plings.length > 0) { plingsMenuItem = React.createElement( 'a', { className: this.props.tab === "plings" ? "item active" : "item", onClick: () => this.props.onTabToggle('plings') }, 'Plings (', this.props.product.r_plings.length, ')' ); } return React.createElement( 'div', { className: 'wrapper' }, React.createElement( 'div', { className: 'container' }, React.createElement( 'div', { className: 'explore-top-bar' }, React.createElement( 'a', { className: this.props.tab === "comments" ? "item active" : "item", onClick: () => this.props.onTabToggle('comments') }, 'Comments (', this.props.product.r_comments.length, ')' ), filesMenuItem, ratingsMenuItem, favsMenuItem, plingsMenuItem ) ) ); } } class ProductViewContent extends React.Component { render() { let currentTabDisplay; if (this.props.tab === 'comments') { currentTabDisplay = React.createElement( 'div', { className: 'product-tab', id: 'comments-tab' }, React.createElement(ProductCommentsContainer, { product: this.props.product, user: this.props.user }) ); } else if (this.props.tab === 'files') { currentTabDisplay = React.createElement(ProductViewFilesTab, { product: this.props.product, files: this.props.product.r_files }); } else if (this.props.tab === 'ratings') { currentTabDisplay = React.createElement(ProductViewRatingsTabWrapper, { ratings: this.props.product.r_ratings }); } else if (this.props.tab === 'favs') { currentTabDisplay = React.createElement(ProductViewFavTab, { likes: this.props.product.r_likes }); } else if (this.props.tab === 'plings') { currentTabDisplay = React.createElement(ProductViewPlingsTab, { plings: this.props.product.r_plings }); } return React.createElement( 'div', { className: 'wrapper' }, React.createElement( 'div', { className: 'container' }, React.createElement( 'div', { className: 'section', id: 'product-view-content-container' }, currentTabDisplay ) ) ); } } class ProductCommentsContainer extends React.Component { constructor(props) { super(props); this.state = {}; } render() { let commentsDisplay; const cArray = categoryHelpers.convertCatChildrenObjectToArray(this.props.product.r_comments); if (cArray.length > 0) { const product = this.props.product; const comments = cArray.map((c, index) => { if (c.level === 1) { return React.createElement(CommentItem, { user: this.props.user, product: product, comment: c.comment, key: index, level: 1 }); } }); commentsDisplay = React.createElement( 'div', { className: 'comment-list' }, comments ); } return React.createElement( 'div', { className: 'product-view-section', id: 'product-comments-container' }, React.createElement(CommentForm, { user: this.props.user, product: this.props.product }), commentsDisplay ); } } class CommentForm extends React.Component { constructor(props) { super(props); this.state = { text: '', errorMsg: '', errorTitle: '', loading: false }; this.updateCommentText = this.updateCommentText.bind(this); this.submitComment = this.submitComment.bind(this); this.updateComments = this.updateComments.bind(this); } updateCommentText(e) { this.setState({ text: e.target.value }); } submitComment() { this.setState({ loading: true }, function () { const msg = this.state.text; const self = this; let data = { p: this.props.product.project_id, m: this.props.user.member_id, msg: this.state.text }; if (this.props.comment) { data.i = this.props.comment.comment_id; } jQuery.ajax({ data: data, url: '/productcomment/addreply/', type: 'post', dataType: 'json', error: function (jqXHR, textStatus, errorThrown) { const results = JSON && JSON.parse(jqXHR.responseText) || $.parseJSON(jqXHR.responseText); self.setState({ errorMsg: results.message, errorTitle: results.title, login_url: results.login_url, status: 'error' }); }, success: function (results) { let baseUrl; if (store.getState().env === 'live') { baseUrl = 'cn.opendesktop.org'; } else { baseUrl = 'cn.pling.it'; } $.ajax({ url: '/productcomment?p=' + self.props.product.project_id, cache: false }).done(function (response) { self.updateComments(response); }); } }); }); } updateComments(response) { store.dispatch(setProductComments(response)); this.setState({ text: '', loading: false }, function () { if (this.props.hideReplyForm) { this.props.hideReplyForm(); } }); } render() { let commentFormDisplay; if (this.props.user.username) { if (this.state.loading) { commentFormDisplay = React.createElement( 'div', { className: 'comment-form-container' }, React.createElement( 'p', null, React.createElement('span', { className: 'glyphicon glyphicon-refresh spinning' }), ' posting comment' ) ); } else { let submitBtnDisplay; if (this.state.text.length === 0) { submitBtnDisplay = React.createElement( 'button', { disabled: 'disabled', type: 'button', className: 'mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored mdl-color--primary' }, 'send' ); } else { submitBtnDisplay = React.createElement( 'button', { onClick: this.submitComment, type: 'button', className: 'mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored mdl-color--primary' }, React.createElement('span', { className: 'glyphicon glyphicon-send' }), 'send' ); } let errorDisplay; if (this.state.status === 'error') { errorDisplay = React.createElement( 'div', { className: 'comment-form-error-display-container' }, React.createElement('div', { dangerouslySetInnerHTML: { __html: this.state.errorTitle } }), React.createElement('div', { dangerouslySetInnerHTML: { __html: this.state.errorMsg } }) ); } commentFormDisplay = React.createElement( 'div', { className: 'comment-form-container' }, React.createElement( 'span', null, 'Add Comment' ), React.createElement('textarea', { className: 'form-control', onChange: this.updateCommentText, value: this.state.text }), errorDisplay, submitBtnDisplay ); } } else { commentFormDisplay = React.createElement( 'p', null, 'Please ', React.createElement( 'a', { href: '/login?redirect=ohWn43n4SbmJZWlKUZNl2i1_s5gggiCE' }, 'login' ), ' or ', React.createElement( 'a', { href: '/register' }, 'register' ), ' to add a comment' ); } return React.createElement( 'div', { id: 'product-page-comment-form-container' }, commentFormDisplay ); } } class CommentItem extends React.Component { constructor(props) { super(props); this.state = { showCommentReplyForm: false }; this.filterByCommentLevel = this.filterByCommentLevel.bind(this); this.onToggleReplyForm = this.onToggleReplyForm.bind(this); this.onReportComment = this.onReportComment.bind(this); this.onConfirmReportClick = this.onConfirmReportClick.bind(this); } filterByCommentLevel(val) { if (val.level > this.props.level && this.props.comment.comment_id === val.comment.comment_parent_id) { return val; } } onToggleReplyForm() { const showCommentReplyForm = this.state.showCommentReplyForm === true ? false : true; this.setState({ showCommentReplyForm: showCommentReplyForm }); } onReportComment() { $('#report-' + this.props.comment.comment_id).modal('show'); } onConfirmReportClick(commentId, productId) { jQuery.ajax({ data: { i: commentId, p: productId }, url: "/report/comment/", type: "POST", dataType: "json", error: function (jqXHR, textStatus, errorThrown) { var results = JSON && JSON.parse(jqXHR.responseText) || $.parseJSON(jqXHR.responseText); $("#report-" + commentId).find('.modal-header-text').empty().append(results.title); $("#report-" + commentId).find('.modal-body').empty().append(results.message); setTimeout(function () { $("#report-" + commentId).modal('hide'); }, 2000); }, success: function (results) { if (results.status == 'ok') { $("#report-" + commentId).find(".comment-report-p").empty().html(results.message.split('

')[0].split('

')[1]); } if (results.status == 'error') { if (results.message != '') { $("#report-" + commentId).find(".comment-report-p").empty().html(results.message); } else { $("#report-" + commentId).find(".comment-report-p").empty().html('Service is temporarily unavailable.'); } } setTimeout(function () { $("#report-" + commentId).modal('hide'); }, 2000); } }); } render() { let commentRepliesContainer; const filteredComments = categoryHelpers.convertCatChildrenObjectToArray(this.props.product.r_comments).filter(this.filterByCommentLevel); if (filteredComments.length > 0) { const product = this.props.product; const user = this.props.user; const comments = filteredComments.map((c, index) => React.createElement(CommentItem, { user: user, product: product, comment: c.comment, key: index, level: c.level })); commentRepliesContainer = React.createElement( 'div', { className: 'comment-item-replies-container' }, comments ); } let displayIsSupporter; if (this.props.comment.issupporter === "1") { displayIsSupporter = React.createElement( 'li', null, React.createElement( 'span', { className: 'is-supporter-display uc-icon' }, 'S' ) ); } let displayIsCreater; if (this.props.comment.member_id === this.props.product.member_id) { displayIsCreater = React.createElement( 'li', null, React.createElement( 'span', { className: 'is-creater-display uc-icon' }, 'C' ) ); } let commentReplyFormDisplay; if (this.state.showCommentReplyForm) { commentReplyFormDisplay = React.createElement(CommentForm, { comment: this.props.comment, user: this.props.user, product: this.props.product, hideReplyForm: this.onToggleReplyForm }); } return React.createElement( 'div', { className: 'comment-item' }, React.createElement( 'div', { className: 'comment-user-avatar' }, React.createElement('img', { src: this.props.comment.profile_image_url }) ), React.createElement( 'div', { className: 'comment-item-content' }, React.createElement( 'div', { className: 'comment-item-header' }, React.createElement( 'ul', null, React.createElement( 'li', null, React.createElement( 'a', { className: 'comment-username', href: "/member/" + this.props.comment.member_id }, this.props.comment.username ) ), displayIsSupporter, displayIsCreater, React.createElement( 'li', null, React.createElement( 'span', { className: 'comment-created-at' }, appHelpers.getTimeAgo(this.props.comment.comment_created_at) ) ) ) ), React.createElement( 'div', { className: 'comment-item-text' }, this.props.comment.comment_text ), React.createElement( 'div', { className: 'comment-item-actions' }, React.createElement( 'a', { onClick: this.onToggleReplyForm }, React.createElement( 'i', { className: 'material-icons reverse' }, 'reply' ), React.createElement( 'span', null, 'Reply' ) ), React.createElement( 'a', { onClick: this.onReportComment }, React.createElement( 'i', { className: 'material-icons' }, 'warning' ), React.createElement( 'span', null, 'Report' ) ), React.createElement(ReportCommentModal, { comment: this.props.comment, product: this.props.product, user: this.props.user, onConfirmReportClick: this.onConfirmReportClick }) ) ), commentReplyFormDisplay, commentRepliesContainer ); } } class ReportCommentModal extends React.Component { constructor(props) { super(props); this.state = { status: "ready" }; } onConfirmReportClick(commmentId, productId) { this.setState({ status: "loading" }, function () { this.props.onConfirmReportClick(commmentId, productId); }); } render() { let confirmActionButtonIconDisplay; if (this.state.status === "ready") { confirmActionButtonIconDisplay = React.createElement( 'i', { className: 'material-icons reverse' }, 'reply' ); } else if (this.state.status === "loading") { confirmActionButtonIconDisplay = React.createElement('span', { className: 'glyphicon glyphicon-refresh spinning' }); } return React.createElement( 'div', { className: 'modal report-comment-modal', id: "report-" + this.props.comment.comment_id, tabIndex: '-1', role: 'dialog' }, React.createElement( 'div', { className: 'modal-dialog', role: 'document' }, React.createElement( 'div', { className: 'modal-content' }, React.createElement( 'div', { className: 'modal-header' }, React.createElement( 'h4', { className: 'modal-title' }, 'Report Comment' ), React.createElement( 'button', { type: 'button', id: 'review-modal-close', className: 'close', 'data-dismiss': 'modal', 'aria-label': 'Close' }, React.createElement( 'span', { 'aria-hidden': 'true' }, '\xD7' ) ) ), React.createElement( 'div', { className: 'modal-body' }, React.createElement( 'p', { className: 'comment-report-p' }, 'Do you really want to report this comment?' ) ), React.createElement( 'div', { className: 'modal-footer' }, React.createElement( 'a', { onClick: () => this.onConfirmReportClick(this.props.comment.comment_id, this.props.product.project_id) }, confirmActionButtonIconDisplay, ' yes' ) ) ) ) ); } } class ProductViewFilesTab extends React.Component { render() { let filesDisplay; const files = this.props.files.map((f, index) => React.createElement(ProductViewFilesTabItem, { product: this.props.product, key: index, file: f })); const summeryRow = productHelpers.getFilesSummary(this.props.files); filesDisplay = React.createElement( 'tbody', null, files, React.createElement( 'tr', null, React.createElement( 'td', null, summeryRow.total, ' files (0 archived)' ), React.createElement('td', null), React.createElement('td', null), React.createElement('td', null), React.createElement('td', null), React.createElement( 'td', null, summeryRow.downloads ), React.createElement('td', null), React.createElement( 'td', null, appHelpers.getFileSize(summeryRow.fileSize) ), React.createElement('td', null), React.createElement('td', null) ) ); return React.createElement( 'div', { id: 'files-tab', className: 'product-tab' }, React.createElement( 'table', { className: 'mdl-data-table mdl-js-data-table mdl-shadow--2dp' }, React.createElement( 'thead', null, React.createElement( 'tr', null, React.createElement( 'th', { className: 'mdl-data-table__cell--non-numericm' }, 'File' ), React.createElement( 'th', { className: 'mdl-data-table__cell--non-numericm' }, 'Version' ), React.createElement( 'th', { className: 'mdl-data-table__cell--non-numericm' }, 'Description' ), React.createElement( 'th', { className: 'mdl-data-table__cell--non-numericm' }, 'Packagetype' ), React.createElement( 'th', { className: 'mdl-data-table__cell--non-numericm' }, 'Architecture' ), React.createElement( 'th', { className: 'mdl-data-table__cell--non-numericm' }, 'Downloads' ), React.createElement( 'th', { className: 'mdl-data-table__cell--non-numericm' }, 'Date' ), React.createElement( 'th', { className: 'mdl-data-table__cell--non-numericm' }, 'Filesize' ), React.createElement( 'th', { className: 'mdl-data-table__cell--non-numericm' }, 'DL' ), React.createElement( 'th', { className: 'mdl-data-table__cell--non-numericm' }, 'OCS-Install' ) ) ), filesDisplay ) ); } } class ProductViewFilesTabItem extends React.Component { constructor(props) { super(props); this.state = { downloadLink: "" }; } componentDidMount() { let baseUrl, downloadLinkUrlAttr; if (store.getState().env === 'live') { baseUrl = 'opendesktop.org'; downloadLinkUrlAttr = "https%3A%2F%dl.opendesktop.org%2Fapi%2F"; } else { baseUrl = 'pling.cc'; downloadLinkUrlAttr = "https%3A%2F%2Fcc.ppload.com%2Fapi%2F"; } const f = this.props.file; const timestamp = Math.floor(new Date().getTime() / 1000 + 3600); const fileDownloadHash = appHelpers.generateFileDownloadHash(f, store.getState().env); let downloadLink = "https://" + baseUrl + "/p/" + this.props.product.project_id + "/startdownload?file_id=" + f.id + "&file_name=" + f.title + "&file_type=" + f.type + "&file_size=" + f.size + "&url=" + downloadLinkUrlAttr + "files%2Fdownload%2Fid%2F" + f.id + "%2Fs%2F" + fileDownloadHash + "%2Ft%2F" + timestamp + "%2Fu%2F" + this.props.product.member_id + "%2F" + f.title; this.setState({ downloadLink: downloadLink }); } render() { const f = this.props.file; return React.createElement( 'tr', null, React.createElement( 'td', { className: 'mdl-data-table__cell--non-numericm' }, React.createElement( 'a', { href: this.state.downloadLink }, f.title ) ), React.createElement( 'td', null, f.version ), React.createElement( 'td', { className: 'mdl-data-table__cell--non-numericm' }, f.description ), React.createElement( 'td', { className: 'mdl-data-table__cell--non-numericm' }, f.packagename ), React.createElement( 'td', { className: 'mdl-data-table__cell--non-numericm' }, f.archname ), React.createElement( 'td', null, f.downloaded_count ), React.createElement( 'td', { className: 'mdl-data-table__cell--non-numericm' }, appHelpers.getTimeAgo(f.created_timestamp) ), React.createElement( 'td', { className: 'mdl-data-table__cell--non-numericm' }, appHelpers.getFileSize(f.size) ), React.createElement( 'td', null, React.createElement( 'a', { href: this.state.downloadLink }, React.createElement( 'i', { className: 'material-icons' }, 'cloud_download' ) ) ), React.createElement( 'td', null, f.ocs_compatible ) ); } } class ProductViewRatingsTab extends React.Component { constructor(props) { super(props); this.state = { filter: 'active' }; this.filterLikes = this.filterLikes.bind(this); this.filterDislikes = this.filterDislikes.bind(this); this.filterActive = this.filterActive.bind(this); this.setFilter = this.setFilter.bind(this); } filterLikes(rating) { if (rating.user_like === "1") { return rating; } } filterDislikes(rating) { if (rating.user_dislike === "1") { return rating; } } filterActive(rating) { if (rating.rating_active === "1") { return rating; } } setFilter(filter) { this.setState({ filter: filter }); } render() { const ratingsLikes = this.props.ratings.filter(this.filterLikes); const ratingsDislikes = this.props.ratings.filter(this.filterDislikes); const ratingsActive = this.props.ratings.filter(this.filterActive); let ratingsDisplay; if (this.props.ratings.length > 0) { let ratings; if (this.state.filter === "all") { ratings = this.props.ratings; } else if (this.state.filter === "active") { ratings = ratingsActive; } else if (this.state.filter === "dislikes") { ratings = ratingsDislikes; } else if (this.state.filter === "likes") { ratings = ratingsLikes; } const ratingsItems = ratings.map((r, index) => React.createElement(RatingItem, { key: index, rating: r })); ratingsDisplay = React.createElement( 'div', { className: 'product-ratings-list comment-list' }, ratingsItems ); } const subMenuItemClassName = " mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect"; const subMenuActiveItemClassName = "active mdl-button--colored mdl-color--primary item"; return React.createElement( 'div', { id: 'ratings-tab', className: 'product-tab' }, React.createElement( 'div', { className: 'ratings-filters-menu' }, React.createElement( 'span', { className: 'btn-container', onClick: () => this.setFilter("dislikes") }, React.createElement( 'a', { className: this.state.filter === "dislikes" ? subMenuActiveItemClassName + subMenuItemClassName : subMenuItemClassName, onClick: this.showDislikes }, 'show dislikes (', ratingsDislikes.length, ')' ) ), React.createElement( 'span', { className: 'btn-container', onClick: () => this.setFilter("likes") }, React.createElement( 'a', { onClick: this.setDislikesFilter, className: this.state.filter === "likes" ? subMenuActiveItemClassName + subMenuItemClassName : subMenuItemClassName, onClick: this.showLikes }, 'show likes (', ratingsLikes.length, ')' ) ), React.createElement( 'span', { className: 'btn-container', onClick: () => this.setFilter("active") }, React.createElement( 'a', { onClick: this.setDislikesFilter, className: this.state.filter === "active" ? subMenuActiveItemClassName + subMenuItemClassName : subMenuItemClassName, onClick: this.showActive }, 'show active reviews (', ratingsActive.length, ')' ) ), React.createElement( 'span', { className: 'btn-container', onClick: () => this.setFilter("all") }, React.createElement( 'a', { onClick: this.setDislikesFilter, className: this.state.filter === "all" ? subMenuActiveItemClassName + subMenuItemClassName : subMenuItemClassName, onClick: this.showAll }, 'show all (', this.props.ratings.length, ')' ) ) ), ratingsDisplay ); } } const mapStateToProductViewRatingsTabProps = state => { const ratings = state.product.r_ratings; return { ratings }; }; const mapDispatchToProductViewRatingsTabProps = dispatch => { return { dispatch }; }; const ProductViewRatingsTabWrapper = ReactRedux.connect(mapStateToProductViewRatingsTabProps, mapDispatchToProductViewRatingsTabProps)(ProductViewRatingsTab); class RatingItem extends React.Component { constructor(props) { super(props); this.state = {}; } render() { return React.createElement( 'div', { className: 'product-rating-item comment-item' }, React.createElement( 'div', { className: 'rating-user-avatar comment-user-avatar' }, React.createElement('img', { src: this.props.rating.profile_image_url }) ), React.createElement( 'div', { className: 'rating-item-content comment-item-content' }, React.createElement( 'div', { className: 'rating-item-header comment-item-header' }, React.createElement( 'a', { href: "/member/" + this.props.rating.member_id }, this.props.rating.username ), React.createElement( 'span', { className: 'comment-created-at' }, appHelpers.getTimeAgo(this.props.rating.created_at) ) ), React.createElement( 'div', { className: 'rating-item-text comment-item-text' }, this.props.rating.comment_text ) ) ); } } class ProductViewFavTab extends React.Component { constructor(props) { super(props); this.state = {}; } render() { let favsDisplay; if (this.props.likes) { const favs = this.props.likes.map((like, index) => React.createElement(UserCardItem, { key: index, like: like })); favsDisplay = React.createElement( 'div', { className: 'favs-list supporter-list' }, favs ); } return React.createElement( 'div', { className: 'product-tab', id: 'fav-tab' }, favsDisplay ); } } class ProductViewPlingsTab extends React.Component { constructor(props) { super(props); this.state = {}; } render() { let plingsDisplay; if (this.props.plings) { const plings = this.props.plings.map((pling, index) => React.createElement(UserCardItem, { key: index, pling: pling })); plingsDisplay = React.createElement( 'div', { className: 'plings-list supporter-list' }, plings ); } return React.createElement( 'div', { className: 'product-tab', id: 'plings-tab' }, plingsDisplay ); } } class UserCardItem extends React.Component { constructor(props) { super(props); this.state = {}; } render() { let item; if (this.props.like) { item = this.props.like; } else if (this.props.pling) { item = this.props.pling; } let cardTypeDisplay; if (this.props.like) { cardTypeDisplay = React.createElement('i', { className: 'fa fa-heart myfav', 'aria-hidden': 'true' }); } else if (this.props.pling) { cardTypeDisplay = React.createElement('img', { src: '/images/system/pling-btn-active.png' }); } return React.createElement( 'div', { className: 'supporter-list-item' }, React.createElement( 'div', { className: 'item-content' }, React.createElement( 'div', { className: 'user-avatar' }, React.createElement('img', { src: item.profile_image_url }) ), React.createElement( 'span', { className: 'username' }, React.createElement( 'a', { href: "/member/" + item.member_id }, item.username ) ), React.createElement( 'span', { className: 'card-type-holder' }, cardTypeDisplay ), React.createElement( 'span', { className: 'created-at' }, appHelpers.getTimeAgo(item.created_at) ) ) ); } } const { Provider, connect } = ReactRedux; const store = Redux.createStore(reducer); class App extends React.Component { constructor(props) { super(props); this.state = { loading: true, version: 1 }; this.updateDimensions = this.updateDimensions.bind(this); } componentWillMount() { // device this.updateDimensions(); } componentDidMount() { // domain store.dispatch(setDomain(window.location.hostname)); // env const env = appHelpers.getEnv(window.location.hostname); store.dispatch(setEnv(env)); // device window.addEventListener("resize", this.updateDimensions); // view if (window.view) store.dispatch(setView(view)); // products if (window.products) { store.dispatch(setProducts(products)); } // product (single) if (window.product) { store.dispatch(setProduct(product)); store.dispatch(setProductFiles(filesJson)); store.dispatch(setProductUpdates(updatesJson)); store.dispatch(setProductRatings(ratingsJson)); store.dispatch(setProductLikes(likeJson)); store.dispatch(setProductPlings(projectplingsJson)); store.dispatch(setProductUserRatings(ratingOfUserJson)); store.dispatch(setProductGallery(galleryPicturesJson)); store.dispatch(setProductComments(commentsJson)); store.dispatch(setProductOrigins(originsJson)); store.dispatch(setProductRelated(relatedJson)); store.dispatch(setProductMoreProducts(moreProductsJson)); store.dispatch(setProductMoreProductsOtherUsers(moreProductsOfOtherUsrJson)); store.dispatch(setProductTags(tagsuserJson, tagssystemJson)); } // pagination if (window.pagination) { store.dispatch(setPagination(pagination)); } // filters if (window.filters) { store.dispatch(setFilters(filters)); } // top products if (window.topProducts) { store.dispatch(setTopProducts(topProducts)); } // categories if (window.categories) { // set categories store.dispatch(setCategories(categories)); if (window.catId) { // current categories const currentCategories = categoryHelpers.findCurrentCategories(categories, catId); store.dispatch(setCurrentCategory(currentCategories.category)); store.dispatch(setCurrentSubCategory(currentCategories.subcategory)); store.dispatch(setCurrentSecondSubCategory(currentCategories.secondSubCategory)); } } // supporters if (window.supporters) { store.dispatch(setSupporters(supporters)); } // comments if (window.comments) { store.dispatch(setComments(comments)); } // user if (window.user) { store.dispatch(setUser(user)); } // finish loading this.setState({ loading: false }); } componentWillUnmount() { // device window.removeEventListener("resize", this.updateDimensions); } updateDimensions() { const device = appHelpers.getDeviceWidth(window.innerWidth); store.dispatch(setDevice(device)); } render() { let displayView = React.createElement(HomePageWrapper, null); if (store.getState().view === 'explore') { displayView = React.createElement(ExplorePageWrapper, null); } else if (store.getState().view === 'product') { displayView = React.createElement(ProductViewWrapper, null); } return React.createElement( "div", { id: "app-root" }, displayView ); } } class AppWrapper extends React.Component { render() { return React.createElement( Provider, { store: store }, React.createElement(App, null) ); } } ReactDOM.render(React.createElement(AppWrapper, null), document.getElementById('explore-content'));