Discord bot
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

374 lines
7.1 KiB

  1. import Head from 'next/head';
  2. import Link from 'next/link';
  3. import styled, {createGlobalStyle} from 'styled-components';
  4. import {Folder, Settings, Trash2} from 'react-feather';
  5. import Button from '../../molecules/Button';
  6. import TopBar from '../../organisms/widgets/TopBar';
  7. import FolderItem from '../../organisms/tree/FolderItem';
  8. import FolderViewMode from '../../../models/FolderViewMode';
  9. import TextInput from '../../molecules/TextInput';
  10. import {forClientSideState, Form} from '../../../utilities/handler';
  11. import Method from '../../../utilities/handler/Method';
  12. import {useRouter} from 'next/router';
  13. const Variables = createGlobalStyle({
  14. ':root': {
  15. '--size-sidebar': '360px',
  16. },
  17. })
  18. const Container = styled('div')({
  19. maxWidth: 720,
  20. padding: '0 1rem',
  21. boxSizing: 'border-box',
  22. })
  23. const SideBar = styled('div')({
  24. width: 'calc(50% - var(--size-sidebar) * 0.5)',
  25. backgroundColor: 'var(--color-bg, white)',
  26. position: 'fixed',
  27. top: 0,
  28. left: 0,
  29. height: '100%',
  30. })
  31. const SideBarContainer = styled('div')({
  32. marginLeft: 'auto',
  33. width: 'var(--size-sidebar)',
  34. })
  35. const Main = styled('div')({
  36. paddingLeft: 'calc(50% - var(--size-sidebar) * 0.5)',
  37. })
  38. const FolderInfoContainer = styled(Container)({
  39. display: 'flex',
  40. justifyContent: 'space-between',
  41. height: '4rem',
  42. alignItems: 'center',
  43. })
  44. const SidebarLink = styled('a')({
  45. display: 'flex',
  46. height: '4rem',
  47. alignItems: 'center',
  48. })
  49. const InnerSidebar = styled('div')({
  50. width: 'calc(var(--size-sidebar) - 4rem)',
  51. height: '100%',
  52. position: 'absolute',
  53. top: 0,
  54. right: 0,
  55. backgroundColor: 'var(--color-bg, white)',
  56. })
  57. const SideBarIcon = styled('div')({
  58. width: '4rem',
  59. height: '4rem',
  60. display: 'grid',
  61. placeContent: 'center',
  62. })
  63. const SidebarContents = styled('div')({
  64. width: '100%',
  65. height: '100%',
  66. position: 'relative',
  67. })
  68. const FolderListWrapper = styled('div')({
  69. width: '100%',
  70. height: '100%',
  71. overflow: 'auto',
  72. })
  73. const FolderList = styled('ul')({
  74. margin: 0,
  75. padding: 0,
  76. })
  77. const FolderListItem = styled('li')({
  78. display: 'block',
  79. })
  80. const FolderActions = styled('div')({
  81. position: 'sticky',
  82. display: 'flex',
  83. justifyContent: 'flex-end',
  84. alignItems: 'center',
  85. top: 0,
  86. left: 0,
  87. width: '100%',
  88. height: '4rem',
  89. backgroundColor: 'var(--color-bg, white)',
  90. padding: '0 1rem',
  91. boxSizing: 'border-box',
  92. })
  93. const FolderLink = styled('a')({
  94. display: 'inline-flex',
  95. minWidth: '100%',
  96. verticalAlign: 'top',
  97. height: '3rem',
  98. alignItems: 'center',
  99. whiteSpace: 'nowrap',
  100. padding: '0 1rem',
  101. boxSizing: 'border-box',
  102. })
  103. const FolderGrid = styled('div')({
  104. display: 'grid',
  105. gridTemplateColumns: 'repeat(3, 1fr)',
  106. gap: '0.5rem',
  107. margin: '2rem 0 4rem',
  108. })
  109. const FolderGridCell = styled('div')({
  110. paddingBottom: '100%',
  111. position: 'relative',
  112. })
  113. const FolderGridContents = styled('div')({
  114. position: 'absolute',
  115. top: 0,
  116. left: 0,
  117. width: '100%',
  118. height: '100%',
  119. })
  120. const Header = styled('div')({
  121. position: 'sticky',
  122. top: 'var(--size-topbar)',
  123. left: 0,
  124. width: '100%',
  125. zIndex: 2,
  126. backgroundColor: 'var(--color-bg, white)',
  127. })
  128. const FolderIdInput = styled('input')({
  129. fontFamily: 'monospace',
  130. fontSize: '0.875rem',
  131. display: 'block',
  132. width: '20em',
  133. border: 0,
  134. backgroundColor: 'transparent',
  135. color: 'inherit',
  136. padding: 0,
  137. margin: 0,
  138. outline: 0,
  139. })
  140. const FolderIdBox = styled('span')({
  141. display: 'inline-block',
  142. verticalAlign: 'middle',
  143. })
  144. const FolderTemplate = ({
  145. query,
  146. children,
  147. items = [],
  148. mode,
  149. hierarchy,
  150. }) => {
  151. const router = useRouter()
  152. const [currentFolder] = hierarchy.slice(-1)
  153. return (
  154. <>
  155. <Head>
  156. <title>
  157. {currentFolder.name} | Bruhbot
  158. </title>
  159. <link rel="icon" href="/favicon.ico" />
  160. </Head>
  161. <Variables />
  162. <TopBar
  163. query={query}
  164. />
  165. <SideBar>
  166. <SidebarContents>
  167. <Link
  168. href={{
  169. pathname: '/my/folders',
  170. }}
  171. passHref
  172. >
  173. <SidebarLink>
  174. <SideBarContainer>
  175. <SideBarIcon>
  176. <Folder />
  177. </SideBarIcon>
  178. </SideBarContainer>
  179. </SidebarLink>
  180. </Link>
  181. <Link
  182. href={{
  183. pathname: '/my/bin',
  184. }}
  185. passHref
  186. >
  187. <SidebarLink>
  188. <SideBarContainer>
  189. <SideBarIcon>
  190. <Trash2 />
  191. </SideBarIcon>
  192. </SideBarContainer>
  193. </SidebarLink>
  194. </Link>
  195. <Link
  196. href={{
  197. pathname: '/my/settings',
  198. }}
  199. passHref
  200. >
  201. <SidebarLink>
  202. <SideBarContainer>
  203. <SideBarIcon>
  204. <Settings />
  205. </SideBarIcon>
  206. </SideBarContainer>
  207. </SidebarLink>
  208. </Link>
  209. <InnerSidebar>
  210. <FolderListWrapper>
  211. <FolderActions>
  212. <form
  213. action="/api/a/folders/new"
  214. method={Method.GET}
  215. onSubmit={forClientSideState({ router, })(() => {
  216. })}
  217. >
  218. {(
  219. <Button
  220. type="submit"
  221. >
  222. New Folder
  223. </Button>
  224. )}
  225. </form>
  226. </FolderActions>
  227. {
  228. mode === FolderViewMode.NEW_FOLDER
  229. && (
  230. <FolderList>
  231. <form
  232. action="/api/a/folders/create"
  233. method={Method.POST}
  234. >
  235. <input
  236. type="hidden"
  237. name="parent_id"
  238. value={currentFolder.id}
  239. />
  240. <TextInput
  241. name="name"
  242. />
  243. <Button>
  244. Create
  245. </Button>
  246. </form>
  247. </FolderList>
  248. )
  249. }
  250. <FolderList>
  251. {children.map(c => (
  252. <FolderListItem
  253. key={c.id}
  254. >
  255. <Link
  256. href={{
  257. pathname: '/my/folders/[id]',
  258. query: {
  259. id: c.id,
  260. },
  261. }}
  262. passHref
  263. >
  264. <FolderLink>
  265. {c.name}
  266. </FolderLink>
  267. </Link>
  268. </FolderListItem>
  269. ))}
  270. </FolderList>
  271. </FolderListWrapper>
  272. </InnerSidebar>
  273. </SidebarContents>
  274. </SideBar>
  275. <Main>
  276. <Header>
  277. <FolderInfoContainer>
  278. <div>
  279. {hierarchy.map(h => (
  280. <>
  281. {'/ '}
  282. <Link
  283. href={{
  284. pathname: '/my/folders/[id]',
  285. query: {
  286. id: h.id,
  287. },
  288. }}
  289. >
  290. <a>
  291. {h.name}
  292. </a>
  293. </Link>
  294. {' '}
  295. </>
  296. ))}
  297. </div>
  298. <div>
  299. <FolderIdBox>
  300. Folder ID
  301. <FolderIdInput
  302. readOnly
  303. value={currentFolder.id}
  304. />
  305. </FolderIdBox>
  306. <Button>
  307. Delete
  308. </Button>
  309. </div>
  310. </FolderInfoContainer>
  311. </Header>
  312. <Container>
  313. {
  314. Array.isArray(items)
  315. && items.length < 1
  316. && (
  317. <>
  318. This folder is empty.
  319. </>
  320. )
  321. }
  322. {
  323. Array.isArray(items)
  324. && items.length > 0
  325. && (
  326. <FolderGrid>
  327. {
  328. items.map(i => (
  329. <FolderGridCell
  330. key={i.id}
  331. >
  332. <FolderGridContents>
  333. <FolderItem
  334. name={i.name}
  335. url={i.url}
  336. />
  337. </FolderGridContents>
  338. </FolderGridCell>
  339. ))
  340. }
  341. </FolderGrid>
  342. )
  343. }
  344. </Container>
  345. </Main>
  346. </>
  347. )
  348. }
  349. export default FolderTemplate