18 |
{
19 | setExtended(!extended);
20 | if (props.onExtended) {
21 | props.onExtended();
22 | }
23 | }}>
24 | {props.button}
25 |
26 |
27 | {
28 | should_expand
29 | ? <>
30 | {props.hide_triangle ? null :
}
31 |
{props.body}
32 | >
33 | : null
34 | }
35 |
36 |
;
37 | }
--------------------------------------------------------------------------------
/frontend/app/web/src/css/layout.css:
--------------------------------------------------------------------------------
1 | .app {
2 | }
3 | .appMobile {
4 | & .other {
5 | padding-bottom: var(--footer-height);
6 | & .mainBody {
7 | overflow-y: hidden;
8 | }
9 | }
10 | }
11 | .header {
12 | position: fixed;
13 | z-index: 300;
14 | }
15 | .mobileFullContent {
16 | width: 100%;
17 | height: calc(100vh - var(--header-height) - var(--footer-height));
18 | position: fixed;
19 | top: var(--header-height);
20 | }
21 |
22 | .content {
23 | width: 100%;
24 | display: flex;
25 | justify-content: center;
26 | }
27 |
28 | .other {
29 | background-color: var(--gray-1);
30 | top: var(--header-height);
31 | min-height: calc(100vh - var(--header-height));
32 | display: flex;
33 | flex-direction: row;
34 | position: relative;
35 | & .mainBody {
36 | height: 100%;
37 | flex: 1;
38 | & .forumBody {
39 | width: 100%;
40 | height: 100%;
41 | }
42 | }
43 | }
44 |
45 | .mainContent {
46 | max-width: 600px;
47 | width: 100%;
48 | }
49 | .rightSideBar {
50 | padding: 10px 20px;
51 | width: 335px;
52 | }
--------------------------------------------------------------------------------
/frontend/app/web/src/css/board_list.module.css:
--------------------------------------------------------------------------------
1 | .boardList {
2 | margin-top: 20px;
3 | display: flex;
4 | align-items: center;
5 | justify-content: center;
6 | & > div {
7 | width: 100%;
8 | background-color: var(--background-color);
9 | & .boardBlock:not(:first-child) {
10 | border-top: 0px;
11 | }
12 | & .boardBlock:hover {
13 | background: var(--hover-background-color)
14 | }
15 | & .boardBlock {
16 | border: 1px var(--border-color) solid;
17 | width: 100%;
18 | padding: 5px;
19 | & .info {
20 | display: flex;
21 | flex-direction: row;
22 | & .name {
23 | color: black;
24 | font-size: 16px;
25 | }
26 | & .type {
27 | flex: 1px;
28 | color: var(--green);
29 | margin-left: 5px;
30 | }
31 | }
32 | & .title {
33 | color: black;
34 | font-size: 12px;
35 | }
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/frontend/app/web/deploy/nginx.conf:
--------------------------------------------------------------------------------
1 | map $http_user_agent $index {
2 | default /index.html;
3 | ~*iPad /index.html;
4 | ~*Mobile|Android|webOS|iPhone|iPod|BlackBerry /index.mobile.html;
5 | }
6 | server {
7 | listen 80;
8 | server_name 0.0.0.0;
9 | access_log /var/log/nginx/access_log;
10 | error_log /var/log/nginx/error_log;
11 | charset utf-8;
12 | gzip on;
13 | gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript image/svg+xml image/png image/jpeg;
14 | gzip_min_length 1000;
15 | gzip_proxied any;
16 |
17 | location ~ ^/(api|avatar) {
18 | proxy_pass http://api-service:8080;
19 | }
20 |
21 | location /chat {
22 | proxy_pass http://api-service:8080;
23 | proxy_http_version 1.1;
24 | proxy_set_header Upgrade $http_upgrade;
25 | proxy_set_header Connection "Upgrade";
26 | proxy_set_header Host $host;
27 | }
28 |
29 | location ~ \.(js|css)$ {
30 | root /usr/share/nginx/html;
31 | expires 365d;
32 | }
33 |
34 | location / {
35 | root /usr/share/nginx/html;
36 | try_files $uri /$uri $index;
37 | }
38 | }
--------------------------------------------------------------------------------
/api-service/src/email/smtp.rs:
--------------------------------------------------------------------------------
1 | use crate::custom_error::{Error, Fallible};
2 | use lettre::{
3 | message::header::ContentType, transport::smtp::authentication::Credentials, AsyncSmtpTransport,
4 | AsyncTransport, Message, Tokio1Executor,
5 | };
6 |
7 | pub async fn send_via_smtp(
8 | sender: &str,
9 | receiver: &str,
10 | subject: &str,
11 | html_content: String,
12 | smtp_server: &str,
13 | smtp_username: &str,
14 | smtp_password: &str,
15 | ) -> Fallible<()> {
16 | let email = Message::builder()
17 | .from(sender.parse().unwrap())
18 | .to(receiver.parse().unwrap())
19 | .subject(subject)
20 | .header(ContentType::TEXT_HTML)
21 | .body(html_content)
22 | .unwrap();
23 |
24 | let creds = Credentials::new(smtp_username.to_owned(), smtp_password.to_owned());
25 |
26 | let mailer: AsyncSmtpTransport