|
| 1 | +import React from "react"; |
| 2 | +import styled, { ThemeProvider } from "styled-components"; |
| 3 | + |
| 4 | +import { HEADER_TYPES, MOBILE_WIDTH, theme } from "../../config"; |
| 5 | +import Footer from "../shared/footer"; |
| 6 | +import Header from "../shared/header"; |
| 7 | + |
| 8 | +const ICON_GITHUB = require("../../assets/images/github.png"); |
| 9 | + |
| 10 | +const ICON_OCELOT = require("../../assets/images/OcelotLogo_ACT.png"); |
| 11 | +const ICON_IMGOPCT = require("../../assets/images/imgopct.png"); |
| 12 | +const ICON_OPACITYSTORA_GE = require("../../assets/images/opacitystora-ge.svg"); |
| 13 | +const ICON_OPACITYDEFAULT = require("../../assets/images/default_profile_picture.png"); |
| 14 | + |
| 15 | +type App = { |
| 16 | + span?: number |
| 17 | + title: string |
| 18 | + icon: string |
| 19 | + role: string |
| 20 | + links: { [key: string]: string } |
| 21 | + bio: string |
| 22 | +} |
| 23 | + |
| 24 | +const apps: App[] = [ |
| 25 | + { |
| 26 | + title: "Ocelot", |
| 27 | + icon: ICON_OCELOT, |
| 28 | + role: "Advanced File Management", |
| 29 | + links: { |
| 30 | + github: "https://github.com/act-opacity/ocelot/", |
| 31 | + }, |
| 32 | + bio: |
| 33 | + "Ocelot is a cross-platform, containerized web application client for the Opacity Storage service run from your local machine. Ocelot can be used to store and manage multiple Opacity accounts; sync files and folders between Opacity and one or more of your devices; provide sync status per file; search and filter your files easily; perform file and folder management actions; review file version history and access previous file versions; and quickly open a file share link to share or review its contents." |
| 34 | + }, |
| 35 | + { |
| 36 | + title: "imgOPCT", |
| 37 | + icon: ICON_IMGOPCT, |
| 38 | + role: "Image Sharing", |
| 39 | + links: { |
| 40 | + website: "https://imgopct.com/", |
| 41 | + }, |
| 42 | + bio: |
| 43 | + "imgOPCT is a public imageboard platform to share your images uploaded on Opacity. It's hosted for the community by the community. You can upload images and share them with the public on the front page." |
| 44 | + }, |
| 45 | + { |
| 46 | + title: "Opacity Handle Shortener", |
| 47 | + icon: ICON_OPACITYSTORA_GE, |
| 48 | + role: "Link Shortener", |
| 49 | + links: { |
| 50 | + website: "https://opacitystora.ge/", |
| 51 | + }, |
| 52 | + bio: |
| 53 | + "Opacitystora.ge allows you to easily shorten shared links (aka handles) from the Opacity Storage web services." |
| 54 | + }, |
| 55 | + { |
| 56 | + title: "Opacity Desktop Application", |
| 57 | + icon: ICON_OPACITYDEFAULT, |
| 58 | + role: "Desktop File Management", |
| 59 | + links: { |
| 60 | + github: "https://github.com/Mavahu/opacity-electron", |
| 61 | + }, |
| 62 | + bio: |
| 63 | + "This Windows desktop application allows you to interact with your Opacity account. It supports all features and even offers you the possibility to rename folders or move files/folders around." |
| 64 | + }, |
| 65 | + { |
| 66 | + span: 2, |
| 67 | + title: "Opacity API for Developers", |
| 68 | + icon: ICON_OPACITYDEFAULT, |
| 69 | + role: "API", |
| 70 | + links: { |
| 71 | + website: "https://api.opacity.io:3000/swagger/index.html", |
| 72 | + }, |
| 73 | + bio: |
| 74 | + "The Opacity API is provided for developers to build and integrate solutions with the Opacity Storage platform. Opacity’s developer platform is a core part of our mission to empower developers to grow and monetize their services using the OPCT token. Our APIs are designed to enable teams of any shape or size to build robust integrations that help them customize and get the most value out of Opacity. The Opacity API is built using REST conventions and designed to have a predictable URL structure. It uses standard HTTP features, including methods (POST, GET, PUT, DELETE) and error response codes." |
| 75 | + }, |
| 76 | +]; |
| 77 | + |
| 78 | +const ContainerWrapper = styled.div` |
| 79 | + width: 100%; |
| 80 | +`; |
| 81 | + |
| 82 | +const Container = styled.div` |
| 83 | + max-width: 950px; |
| 84 | + margin: auto; |
| 85 | + background-color: ${props => props.theme.background}; |
| 86 | + padding-bottom: 100px; |
| 87 | +`; |
| 88 | + |
| 89 | +const HeaderContainer = styled.div` |
| 90 | + width: auto; |
| 91 | + padding: 70px 0 0 0; |
| 92 | +`; |
| 93 | + |
| 94 | +const AppsContainer = styled.div` |
| 95 | + display: grid; |
| 96 | + grid-gap: 60px; |
| 97 | + grid-template-rows: repeat(2, 0.5fr); |
| 98 | + grid-template-columns: repeat(2, 1fr); |
| 99 | + @media only screen and (max-width: 1020px) { |
| 100 | + grid-gap: 40px; |
| 101 | + } |
| 102 | + @media only screen and (max-width: 750px) { |
| 103 | + grid-template-rows: repeat(5, 0.5fr); |
| 104 | + grid-template-columns: repeat(1, 1fr); |
| 105 | + } |
| 106 | +`; |
| 107 | + |
| 108 | +const AppWrapper = styled.div<{ span?: number }>` |
| 109 | + border: solid 0.5px #acb3bf; |
| 110 | + padding: 50px 20px; |
| 111 | + position: relative; |
| 112 | + align-self: stretch; |
| 113 | + grid-column: span ${props => props.span || 1}; |
| 114 | +`; |
| 115 | + |
| 116 | +const Wrapper = styled.div` |
| 117 | + text-align: center; |
| 118 | +`; |
| 119 | + |
| 120 | +const ContentWrapper = styled.div` |
| 121 | + width: 470px; |
| 122 | + margin: auto; |
| 123 | + @media only screen and (max-width: ${MOBILE_WIDTH}px) { |
| 124 | + width: auto; |
| 125 | + } |
| 126 | +`; |
| 127 | + |
| 128 | +const AppIcon = styled.img` |
| 129 | + height: 150px; |
| 130 | +`; |
| 131 | + |
| 132 | +const Icon = styled.img` |
| 133 | + width: 28px; |
| 134 | + height: 28px; |
| 135 | + margin: 5px; |
| 136 | +`; |
| 137 | + |
| 138 | +const Title = styled.h1` |
| 139 | + font-size: 32px; |
| 140 | + text-align: center; |
| 141 | + font-weight: bold; |
| 142 | + font-style: normal; |
| 143 | + font-stretch: normal; |
| 144 | + line-height: normal; |
| 145 | + letter-spacing: normal; |
| 146 | + color: #2e6dde; |
| 147 | +`; |
| 148 | + |
| 149 | +const AppTitle = styled.h2` |
| 150 | + font-size: 20px; |
| 151 | + font-style: normal; |
| 152 | + font-stretch: normal; |
| 153 | + line-height: normal; |
| 154 | + letter-spacing: normal; |
| 155 | + color: #4f5e78; |
| 156 | + text-align: center; |
| 157 | + color: ${props => props.theme.title.color}; |
| 158 | + font-weight: bold; |
| 159 | + text-transform: uppercase; |
| 160 | +`; |
| 161 | + |
| 162 | +const Parapraph = styled.p` |
| 163 | + font-weight: 500; |
| 164 | + font-weight: ${props => props.theme.fontWeight}; |
| 165 | + font-style: ${props => props.theme.fontStyle}; |
| 166 | + font-stretch: ${props => props.theme.fontStretch}; |
| 167 | + line-height: ${props => props.theme.lineHeight}; |
| 168 | + letter-spacing: 0.7px; |
| 169 | + color: #4f5e78; |
| 170 | + text-align: center; |
| 171 | + font-size: 12px; |
| 172 | +`; |
| 173 | + |
| 174 | +const AppRole = styled(Parapraph)` |
| 175 | + width: calc(100% - 16px); |
| 176 | + margin: auto; |
| 177 | + font-size: 16px; |
| 178 | + font-weight: bold; |
| 179 | + font-style: normal; |
| 180 | + font-stretch: normal; |
| 181 | + line-height: normal; |
| 182 | + letter-spacing: 0.3px; |
| 183 | + color: #4f5e78; |
| 184 | +`; |
| 185 | + |
| 186 | +const AppBio = styled(Parapraph)` |
| 187 | + margin: 10px auto 0 auto; |
| 188 | + font-size: 14px; |
| 189 | + text-align: left; |
| 190 | + max-width: 600px; |
| 191 | + padding: 0 12px; |
| 192 | +`; |
| 193 | + |
| 194 | +const Content = styled(Parapraph)` |
| 195 | + font-size: 16px; |
| 196 | + letter-spacing: ${props => props.theme.letterSpacing}; |
| 197 | + padding-bottom: 40px; |
| 198 | +`; |
| 199 | + |
| 200 | +const AppLinkContainer = styled.div` |
| 201 | + position: absolute; |
| 202 | + left: 10px; |
| 203 | + bottom: 0; |
| 204 | +`; |
| 205 | + |
| 206 | +const AppLink = styled.a` |
| 207 | + display: inline-block; |
| 208 | +`; |
| 209 | + |
| 210 | +const linkIcon = (name: string) => { |
| 211 | + switch (name) { |
| 212 | + case "github": |
| 213 | + return <Icon src={ICON_GITHUB} />; |
| 214 | + default: |
| 215 | + return <div style={{ height: 28, margin: 5, color: "#000000" }}>Website ↗</div>; |
| 216 | + }; |
| 217 | +}; |
| 218 | + |
| 219 | +const CommunityPageSlide = ({ isLoggedIn }) => ( |
| 220 | + <ThemeProvider theme={theme}> |
| 221 | + <ContainerWrapper> |
| 222 | + <Header type={HEADER_TYPES.COMMUNITY_PAGE} isLoggedIn={isLoggedIn} /> |
| 223 | + <HeaderContainer> |
| 224 | + <Title>Community Apps</Title> |
| 225 | + <ContentWrapper> |
| 226 | + <Content>Take a look at the great apps made by members of the Opacity community.</Content> |
| 227 | + </ContentWrapper> |
| 228 | + </HeaderContainer> |
| 229 | + <Container> |
| 230 | + <AppsContainer> |
| 231 | + {apps.map(app => ( |
| 232 | + <AppWrapper key={app.title} span={app.span}> |
| 233 | + <Wrapper> |
| 234 | + <AppIcon src={app.icon} /> |
| 235 | + </Wrapper> |
| 236 | + <AppTitle>{app.title}</AppTitle> |
| 237 | + <AppRole>{app.role}</AppRole> |
| 238 | + <AppBio>{app.bio}</AppBio> |
| 239 | + <AppLinkContainer> |
| 240 | + {Object.keys(app.links).map(linkName => ( |
| 241 | + <AppLink key={app.links[linkName]} href={app.links[linkName]} target="_blank"> |
| 242 | + {linkIcon(linkName)} |
| 243 | + </AppLink> |
| 244 | + ))} |
| 245 | + </AppLinkContainer> |
| 246 | + </AppWrapper> |
| 247 | + ))} |
| 248 | + </AppsContainer> |
| 249 | + </Container> |
| 250 | + <Footer /> |
| 251 | + </ContainerWrapper> |
| 252 | + </ThemeProvider> |
| 253 | +); |
| 254 | + |
| 255 | +export default CommunityPageSlide; |
0 commit comments