diff --git a/front/src/common/index.ts b/front/src/common/index.ts index 45bc727..78b9bdc 100644 --- a/front/src/common/index.ts +++ b/front/src/common/index.ts @@ -1,2 +1,3 @@ export * from './hooks'; export * from './global-window'; +export * from './log-download' diff --git a/front/src/common/log-download.ts b/front/src/common/log-download.ts new file mode 100644 index 0000000..751cb96 --- /dev/null +++ b/front/src/common/log-download.ts @@ -0,0 +1,17 @@ +export const handleDownloadSessionContent = (sessionContent: string): void => + generateFile(sessionContent); + +const generateFile = (txt: string): void => { + const file: Blob = new Blob([txt], { + type: 'text/plain;charset=utf-8', + }); + const element: HTMLAnchorElement = document.createElement('a'); + element.href = URL.createObjectURL(file); + element.download = generateCodePasterFileName(); + element.click(); +}; + +const generateCodePasterFileName = (): string => { + const dateToday = new Date(Date.now()).toLocaleDateString(); + return `Codepaster_Session_${dateToday}.txt`; +}; diff --git a/front/src/core/theme/theme.ts b/front/src/core/theme/theme.ts index 220eefd..ea87279 100644 --- a/front/src/core/theme/theme.ts +++ b/front/src/core/theme/theme.ts @@ -17,6 +17,8 @@ export const theme: Theme = merge(defaultTheme, { successDark: '#0f834c', alertLight: 'rgb(255, 87, 51)', alertDark: 'rgb(207, 70, 41)', + blueLight: '#2196f3', + blueDark: '#1565c0', greyLight: '#eee', greyMedium: '#ccc', }, diff --git a/front/src/core/theme/theme.vm.ts b/front/src/core/theme/theme.vm.ts index ccd2b89..9eacb6a 100644 --- a/front/src/core/theme/theme.vm.ts +++ b/front/src/core/theme/theme.vm.ts @@ -10,6 +10,8 @@ interface Palette extends DefaultPalette { successDark: string; alertLight: string; alertDark: string; + blueLight: string; + blueDark: string; greyLight: string; greyMedium: string; }; diff --git a/front/src/pods/student/student.component.tsx b/front/src/pods/student/student.component.tsx index 9736b0e..d3e50d2 100644 --- a/front/src/pods/student/student.component.tsx +++ b/front/src/pods/student/student.component.tsx @@ -8,6 +8,10 @@ import FormControlLabel from '@material-ui/core/FormControlLabel'; import * as innerClasses from './student.styles'; import { useAutoScroll } from 'common/hooks/auto-scroll.hook'; +import { handleDownloadSessionContent } from 'common'; +import GetAppIcon from '@material-ui/icons/GetApp'; +import Button from '@material-ui/core/Button'; + interface Props { room: string; log: string; @@ -16,17 +20,25 @@ interface Props { export const StudentComponent: React.FC = props => { const { room, log } = props; - const {isAutoScrollEnabled, setIsAutoScrollEnabled, textAreaRef, doAutoScroll} = useAutoScroll(); + const { + isAutoScrollEnabled, + setIsAutoScrollEnabled, + textAreaRef, + doAutoScroll, + } = useAutoScroll(); React.useEffect(() => { doAutoScroll(); }, [log]); return ( - <>
- + Session name: {room ?? ''}
); diff --git a/front/src/pods/student/student.styles.ts b/front/src/pods/student/student.styles.ts index 3ef5c61..4da9536 100644 --- a/front/src/pods/student/student.styles.ts +++ b/front/src/pods/student/student.styles.ts @@ -53,3 +53,45 @@ export const textarea = css` outline: none; } `; + +export const downloadButton = css` + display: flex; + align-items: left; + width: 100%; + padding: ${spacing(1.25)} ${spacing(1.875)}; + flex: 1; + font-size: 1.188rem; + font-weight: 400; + text-transform: capitalize; + border-radius: 0; + color: ${color.blueDark}; + background-color: white; + border: 2px solid ${color.blueDark}; + transition: all 0.2s; + &:hover, + &:active { + color: white; + background-color: ${color.blueDark}; + border: 2px solid ${color.blueDark}; + outline: none; + } + @media (min-width: ${breakpoints.values.xs}px) { + max-width: ${spacing(20)}; + } +`; + +export const downloadIcon = css` + margin-right: ${spacing(1.25)}; + font-size: 1.25rem; + display: none; + @media (min-width: ${breakpoints.values.xs}px) { + display: initial; + } +`; + +export const buttonScroll = css` + @media (min-width: ${breakpoints.values.xs}px) { + display: flex; + justify-content: space-between; + } +`; diff --git a/front/src/pods/trainer/components/session.component.tsx b/front/src/pods/trainer/components/session.component.tsx index c5fbf4b..8efc768 100644 --- a/front/src/pods/trainer/components/session.component.tsx +++ b/front/src/pods/trainer/components/session.component.tsx @@ -3,7 +3,9 @@ import { cx } from 'emotion'; import TextareaAutosize from '@material-ui/core/TextareaAutosize'; import ArrowForwardRoundedIcon from '@material-ui/icons/ArrowForwardRounded'; import UndoIcon from '@material-ui/icons/Undo'; +import GetAppIcon from '@material-ui/icons/GetApp'; import Button from '@material-ui/core/Button'; +import { handleDownloadSessionContent } from 'common'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import Checkbox from '@material-ui/core/Checkbox'; @@ -34,7 +36,12 @@ const getFullContent = (currenSessionContent: string) => { export const SessionComponent: React.FC = props => { const { log, handleSendFullContentLog, className } = props; - const {isAutoScrollEnabled, setIsAutoScrollEnabled, textAreaRef, doAutoScroll} = useAutoScroll(); + const { + isAutoScrollEnabled, + setIsAutoScrollEnabled, + textAreaRef, + doAutoScroll, + } = useAutoScroll(); React.useEffect(() => { handleSetSessionContent(log); @@ -46,7 +53,16 @@ export const SessionComponent: React.FC = props => { - + = props => { className={innerClasses.textarea} />