diff --git a/app/assets/stylesheets/application.sass.scss b/app/assets/stylesheets/application.sass.scss index b404fc2b..9e719d9b 100644 --- a/app/assets/stylesheets/application.sass.scss +++ b/app/assets/stylesheets/application.sass.scss @@ -27,4 +27,5 @@ @import 'components/SiteSettings/PostStatuses'; @import 'components/SiteSettings/Roadmap'; @import 'components/SiteSettings/Users'; - @import 'components/SiteSettings/Authentication'; \ No newline at end of file + @import 'components/SiteSettings/Authentication'; + @import 'components/SiteSettings/Appearance/'; \ No newline at end of file diff --git a/app/assets/stylesheets/common/_custom_texts.scss b/app/assets/stylesheets/common/_custom_texts.scss index 14155bea..c65d3796 100644 --- a/app/assets/stylesheets/common/_custom_texts.scss +++ b/app/assets/stylesheets/common/_custom_texts.scss @@ -24,7 +24,7 @@ } .mutedText { - color: $astuto-grey; + color: var(--astuto-grey); } .smallMutedText { diff --git a/app/assets/stylesheets/common/_form.scss b/app/assets/stylesheets/common/_form.scss index 14a0d082..34ef687d 100644 --- a/app/assets/stylesheets/common/_form.scss +++ b/app/assets/stylesheets/common/_form.scss @@ -9,8 +9,8 @@ } .form-control:focus { - border-color: $astuto-light-grey; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 4px rgba(0, 0, 0, 0.6); + border-color: var(--primary-color); + box-shadow: 0 0 0 0.25rem var(--primary-color-light); } .new_user, .edit_user { @@ -33,7 +33,7 @@ margin-top: 24px; - a { color: $primary-color; } + a { color: var(--astuto-black); } } .formRow { diff --git a/app/assets/stylesheets/common/_header.scss b/app/assets/stylesheets/common/_header.scss index 8c715351..308a9428 100644 --- a/app/assets/stylesheets/common/_header.scss +++ b/app/assets/stylesheets/common/_header.scss @@ -54,11 +54,16 @@ font-size: 14px; text-align: left; + + a:hover { color: var(--primary-color); } + + &.active { + @extend .badgeLight; + + a { color: var(--primary-color) !important }; + } } - .nav-item.active { - @extend .badgeLight; - } } .profileNav { @@ -75,12 +80,12 @@ } .fullname { - color: $astuto-black; + color: var(--astuto-black); vertical-align: middle; } } .dropdown-item:active { - background-color: $primary-color; + background-color: var(--primary-color); } } \ No newline at end of file diff --git a/app/assets/stylesheets/common/_index.scss b/app/assets/stylesheets/common/_index.scss index 4face863..e7654fb1 100644 --- a/app/assets/stylesheets/common/_index.scss +++ b/app/assets/stylesheets/common/_index.scss @@ -1,17 +1,50 @@ +::selection { + background-color: var(--primary-color-light); +} + +body { + background-color: var(--background-color); +} + +.btnPrimary { + @extend .btn; + + color: white; + background-color: var(--primary-color); + border-color: var(--primary-color-dark); + + &:hover { color: white; } + &:focus { box-shadow: 0 0 0 0.25rem var(--primary-color-light); } +} + +.btnOutlinePrimary { + @extend .btn; + + background-color: transparent; + color: var(--primary-color); + border-color: var(--primary-color); + + &:hover { + color: white; + background-color: var(--primary-color); + } + + &:focus { box-shadow: 0 0 0 0.25rem var(--primary-color-light); } +} + .card { @extend .card; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.04),0 2px 4px -1px rgba(0, 0, 0, 0.03); transition: all 0.3s cubic-bezier(.25,.8,.25,1); - color: $primary-color; + color: var(--astuto-black); padding: 8px; } .card3D { - @extend - .card; + @extend .card; transition: all 0.3s cubic-bezier(.25,.8,.25,1); @@ -89,17 +122,17 @@ .align-self-stretch; a { - color: $astuto-grey; + color: var(--astuto-grey); font-weight: 500; &:hover { - color: $astuto-black; + color: var(--primary-color); } } .nav-link.active { - color: $astuto-black; - background-color: $astuto-light-grey; + color: var(--primary-color); + background-color: var(--astuto-grey-light); } } @@ -134,7 +167,7 @@ .badgeLight { @extend .badge-light; - background-color: $astuto-light-grey; + background-color: var(--astuto-grey-light); } .container { @@ -147,7 +180,7 @@ } .turbolinks-progress-bar { - background-color: $primary-color; + background-color: var(--primary-color); height: 2px; } @@ -162,6 +195,14 @@ & > input[type="checkbox"] { @extend .custom-control-input; + + &:focus ~ label::before { + box-shadow: 0 0 0 0.25rem var(--primary-color-light); + } + + &:active ~ label::before { + background-color: var(--primary-color); + } } & > label { @@ -173,14 +214,23 @@ } & > input:checked ~ label::before { - background-color: $primary-color !important; - border-color: $primary-color !important; + background-color: var(--primary-color) !important; + border-color: var(--primary-color-dark) !important; + } + + & > input:focus ~ label::before { + border-color: var(--primary-color-dark) !important; } } .selectPicker { @extend .custom-select; + + &:focus { + box-shadow: 0 0 0 0.25rem var(--primary-color-light); + border-color: var(--primary-color-dark); + } } .link { @@ -189,13 +239,16 @@ } .actionLink { - color: $astuto-black; + color: var(--astuto-black); display: flex; cursor: pointer; align-self: center; margin-right: 12px; - &:hover { text-decoration: underline !important; } + &:hover { + color: var(--primary-color); + text-decoration: underline !important; + } svg { margin-right: 4px; @@ -203,7 +256,7 @@ } &.actionLinkDisabled { - color: $astuto-grey !important; + color: var(--astuto-grey) !important; text-decoration: none !important; cursor: not-allowed; diff --git a/app/assets/stylesheets/components/Board.scss b/app/assets/stylesheets/components/Board.scss index 77fa3b32..28d1af9d 100644 --- a/app/assets/stylesheets/components/Board.scss +++ b/app/assets/stylesheets/components/Board.scss @@ -11,7 +11,7 @@ } .newPostContainer { - background-color: $astuto-light-grey; + background-color: var(--astuto-grey-light); text-align: center; .boardTitle { @@ -37,6 +37,8 @@ .postStatusListItemLink { @extend .flex-grow-1; + + &:hover { text-decoration: none; } } .postStatusListItem { @@ -84,7 +86,7 @@ .p-3; height: 140px; - color: $primary-color; + color: var(--astuto-black); @include media-breakpoint-down(sm) { height: auto; diff --git a/app/assets/stylesheets/components/LikeButton.scss b/app/assets/stylesheets/components/LikeButton.scss index 458d9ccd..b09e434e 100644 --- a/app/assets/stylesheets/components/LikeButton.scss +++ b/app/assets/stylesheets/components/LikeButton.scss @@ -14,13 +14,13 @@ border-bottom: $like_button_size solid rgba(35,35,35,.2); &:hover { - border-bottom-color: $primary-color; + border-bottom-color: var(--primary-color); cursor: pointer; } } .likeButton.liked { - border-bottom-color: $primary-color; + border-bottom-color: var(--primary-color); } .likeCountLabel { diff --git a/app/assets/stylesheets/components/Post.scss b/app/assets/stylesheets/components/Post.scss index f40bde7e..a3b7bad2 100644 --- a/app/assets/stylesheets/components/Post.scss +++ b/app/assets/stylesheets/components/Post.scss @@ -125,7 +125,7 @@ @extend .my-4; - color: $primary-color; + color: var(--astuto-black); p:last-child { @extend .mb-0; diff --git a/app/assets/stylesheets/components/Roadmap.scss b/app/assets/stylesheets/components/Roadmap.scss index 0d7297d0..d7ed3774 100644 --- a/app/assets/stylesheets/components/Roadmap.scss +++ b/app/assets/stylesheets/components/Roadmap.scss @@ -11,7 +11,7 @@ .p-0; width: 32%; - background-color: $astuto-light-grey; + background-color: var(--astuto-grey-light); @include media-breakpoint-down(sm) { width: 100%; @@ -35,8 +35,7 @@ } .postLink { - @extend - .my-2; + @extend .my-2; &:hover { text-decoration: none; } } diff --git a/app/assets/stylesheets/components/SiteSettings/Appearance/index.scss b/app/assets/stylesheets/components/SiteSettings/Appearance/index.scss new file mode 100644 index 00000000..001def94 --- /dev/null +++ b/app/assets/stylesheets/components/SiteSettings/Appearance/index.scss @@ -0,0 +1,4 @@ +#customCss { + width: 100%; + height: 300px; +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/SiteSettings/Roadmap/index.scss b/app/assets/stylesheets/components/SiteSettings/Roadmap/index.scss index 5725e949..a90b1a31 100644 --- a/app/assets/stylesheets/components/SiteSettings/Roadmap/index.scss +++ b/app/assets/stylesheets/components/SiteSettings/Roadmap/index.scss @@ -29,7 +29,7 @@ box-sizing: border-box; flex: 0 0 28%; - background-color: $astuto-light-grey; + background-color: var(--astuto-grey-light); overflow: hidden; height: 150px; @@ -47,7 +47,9 @@ padding: 8px 4px; text-transform: uppercase; - .titleText { @extend .align-self-center; } + .titleText { + @extend .align-self-center; + } } } } \ No newline at end of file diff --git a/app/assets/stylesheets/constants/_colors.scss b/app/assets/stylesheets/constants/_colors.scss index e0cdc3b2..f7f1602f 100644 --- a/app/assets/stylesheets/constants/_colors.scss +++ b/app/assets/stylesheets/constants/_colors.scss @@ -1,5 +1,14 @@ -$primary-color: #333; +:root { + // Theme palette (supposed to be customized) + --primary-color: rgb(51, 51, 51); + --background-color: rgb(255, 255, 255); -$astuto-black: #333; -$astuto-grey: rgba(0, 0, 0, 0.5); -$astuto-light-grey: rgba(178, 178, 178, 0.2); \ No newline at end of file + // Theme palette shades (supposed to be computed from theme palette) + --primary-color-light: color-mix(in srgb,var(--primary-color), #fff 85%); + --primary-color-dark: color-mix(in srgb,var(--primary-color), #000 20%); + + // Astuto colors (supposed to be fixed) + --astuto-black: rgb(51, 51, 51); + --astuto-grey: rgba(0, 0, 0, 0.5); + --astuto-grey-light: rgba(178, 178, 178, 0.2); +} diff --git a/app/controllers/site_settings_controller.rb b/app/controllers/site_settings_controller.rb index 662cbb71..a68f1418 100644 --- a/app/controllers/site_settings_controller.rb +++ b/app/controllers/site_settings_controller.rb @@ -2,7 +2,7 @@ class SiteSettingsController < ApplicationController include ApplicationHelper before_action :authenticate_admin, - only: [:general, :boards, :post_statuses, :roadmap, :authentication] + only: [:general, :authentication, :boards, :post_statuses, :roadmap, :appearance] before_action :authenticate_moderator, only: [:users] @@ -10,6 +10,9 @@ class SiteSettingsController < ApplicationController def general end + def authentication + end + def boards end @@ -19,9 +22,9 @@ class SiteSettingsController < ApplicationController def roadmap end - def users + def appearance end - def authentication + def users end end \ No newline at end of file diff --git a/app/javascript/components/Board/NewPost.tsx b/app/javascript/components/Board/NewPost.tsx index 76fb2479..5f8434de 100644 --- a/app/javascript/components/Board/NewPost.tsx +++ b/app/javascript/components/Board/NewPost.tsx @@ -168,7 +168,7 @@ class NewPost extends React.Component { } : - + {I18n.t('board.new_post.login_button')} } diff --git a/app/javascript/components/SiteSettings/Appearance/AppearanceSiteSettingsP.tsx b/app/javascript/components/SiteSettings/Appearance/AppearanceSiteSettingsP.tsx new file mode 100644 index 00000000..c2d3b5d7 --- /dev/null +++ b/app/javascript/components/SiteSettings/Appearance/AppearanceSiteSettingsP.tsx @@ -0,0 +1,118 @@ +import * as React from 'react'; +import { useEffect } from 'react'; +import I18n from 'i18n-js'; + +import Box from '../../common/Box'; +import SiteSettingsInfoBox from '../../common/SiteSettingsInfoBox'; +import Button from '../../common/Button'; +import HttpStatus from '../../../constants/http_status'; +import { getLabel } from '../../../helpers/formUtils'; +import { SubmitHandler, useForm } from 'react-hook-form'; +import ActionLink from '../../common/ActionLink'; +import { LearnMoreIcon } from '../../common/Icons'; + + +export interface ISiteSettingsAppearanceForm { + customCss: string; +} + +interface Props { + originForm: ISiteSettingsAppearanceForm; + authenticityToken: string; + + areUpdating: boolean; + error: string; + + updateTenant( + customCss: string, + authenticityToken: string + ): Promise; +} + +const AppearanceSiteSettingsP = ({ + originForm, + authenticityToken, + + areUpdating, + error, + updateTenant, +}: Props) => { + const { + register, + handleSubmit, + formState: { isDirty, isSubmitSuccessful }, + watch, + } = useForm({ + defaultValues: { + customCss: originForm.customCss, + }, + }); + + const customCss = watch('customCss'); + + const onSubmit: SubmitHandler = data => { + updateTenant( + data.customCss, + authenticityToken + ).then(res => { + if (res?.status !== HttpStatus.OK) return; + window.location.reload(); + }); + }; + + useEffect(() => { + const style = document.createElement('style'); + style.innerHTML = customCss; + document.body.appendChild(style); + + // Clean up function + return () => { + document.body.removeChild(style); + }; + }, [customCss]); + + return ( + <> + +

{ I18n.t('site_settings.appearance.title') }

+ +

+ window.open('https://docs.astuto.io/category/appearance-customization/', '_blank')} + icon={} + > + {I18n.t('site_settings.appearance.learn_more')} + +

+ +
+
+
+

{ getLabel('tenant_setting', 'custom_css') }

+ +