mirror of
https://github.com/astuto/astuto.git
synced 2025-12-15 19:27:52 +01:00
Add custom CSS (#264)
This commit is contained in:
committed by
GitHub
parent
653e139a9e
commit
d7e7db9f72
@@ -168,7 +168,7 @@ class NewPost extends React.Component<Props, State> {
|
||||
}
|
||||
</Button>
|
||||
:
|
||||
<a href="/users/sign_in" className="btn btn-dark">
|
||||
<a href="/users/sign_in" className="btn btnPrimary">
|
||||
{I18n.t('board.new_post.login_button')}
|
||||
</a>
|
||||
}
|
||||
|
||||
@@ -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<any>;
|
||||
}
|
||||
|
||||
const AppearanceSiteSettingsP = ({
|
||||
originForm,
|
||||
authenticityToken,
|
||||
|
||||
areUpdating,
|
||||
error,
|
||||
updateTenant,
|
||||
}: Props) => {
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { isDirty, isSubmitSuccessful },
|
||||
watch,
|
||||
} = useForm<ISiteSettingsAppearanceForm>({
|
||||
defaultValues: {
|
||||
customCss: originForm.customCss,
|
||||
},
|
||||
});
|
||||
|
||||
const customCss = watch('customCss');
|
||||
|
||||
const onSubmit: SubmitHandler<ISiteSettingsAppearanceForm> = 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 (
|
||||
<>
|
||||
<Box>
|
||||
<h2>{ I18n.t('site_settings.appearance.title') }</h2>
|
||||
|
||||
<p style={{textAlign: 'left'}}>
|
||||
<ActionLink
|
||||
onClick={() => window.open('https://docs.astuto.io/category/appearance-customization/', '_blank')}
|
||||
icon={<LearnMoreIcon />}
|
||||
>
|
||||
{I18n.t('site_settings.appearance.learn_more')}
|
||||
</ActionLink>
|
||||
</p>
|
||||
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="formRow">
|
||||
<div className="formGroup customCssForm col-12">
|
||||
<h4>{ getLabel('tenant_setting', 'custom_css') }</h4>
|
||||
|
||||
<textarea
|
||||
{...register('customCss')}
|
||||
maxLength={32000}
|
||||
id="customCss"
|
||||
className="formControl"
|
||||
onKeyDown={e => e.key === 'Tab' && e.preventDefault()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button onClick={() => null} disabled={!isDirty}>
|
||||
{I18n.t('common.buttons.update')}
|
||||
</Button>
|
||||
</form>
|
||||
</Box>
|
||||
|
||||
<SiteSettingsInfoBox
|
||||
areUpdating={areUpdating}
|
||||
error={error}
|
||||
areDirty={isDirty && !isSubmitSuccessful}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default AppearanceSiteSettingsP;
|
||||
36
app/javascript/components/SiteSettings/Appearance/index.tsx
Normal file
36
app/javascript/components/SiteSettings/Appearance/index.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import * as React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { Store } from 'redux';
|
||||
|
||||
import AppearanceSiteSettings from '../../../containers/AppearanceSiteSettings';
|
||||
import createStoreHelper from '../../../helpers/createStore';
|
||||
import { State } from '../../../reducers/rootReducer';
|
||||
import { ISiteSettingsAppearanceForm } from './AppearanceSiteSettingsP';
|
||||
|
||||
interface Props {
|
||||
originForm: ISiteSettingsAppearanceForm;
|
||||
authenticityToken: string;
|
||||
}
|
||||
|
||||
class AppearanceSiteSettingsRoot extends React.Component<Props> {
|
||||
store: Store<State, any>;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.store = createStoreHelper();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Provider store={this.store}>
|
||||
<AppearanceSiteSettings
|
||||
originForm={this.props.originForm}
|
||||
authenticityToken={this.props.authenticityToken}
|
||||
/>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AppearanceSiteSettingsRoot;
|
||||
@@ -6,6 +6,8 @@ import OAuthProvidersList from './OAuthProvidersList';
|
||||
import { AuthenticationPages } from './AuthenticationSiteSettingsP';
|
||||
import { OAuthsState } from '../../../reducers/oAuthsReducer';
|
||||
import SiteSettingsInfoBox from '../../common/SiteSettingsInfoBox';
|
||||
import ActionLink from '../../common/ActionLink';
|
||||
import { LearnMoreIcon } from '../../common/Icons';
|
||||
|
||||
interface Props {
|
||||
oAuths: OAuthsState;
|
||||
@@ -34,6 +36,15 @@ const AuthenticationIndexPage = ({
|
||||
<Box customClass="authenticationIndexPage">
|
||||
<h2>{ I18n.t('site_settings.authentication.title') }</h2>
|
||||
|
||||
<p style={{textAlign: 'left'}}>
|
||||
<ActionLink
|
||||
onClick={() => window.open('https://docs.astuto.io/category/oauth-configuration/', '_blank')}
|
||||
icon={<LearnMoreIcon />}
|
||||
>
|
||||
{I18n.t('site_settings.authentication.learn_more')}
|
||||
</ActionLink>
|
||||
</p>
|
||||
|
||||
<OAuthProvidersList
|
||||
oAuths={oAuths.items}
|
||||
handleToggleEnabledOAuth={handleToggleEnabledOAuth}
|
||||
|
||||
@@ -11,7 +11,7 @@ interface Props {
|
||||
const Button = ({ children, onClick, className = '', outline = false, disabled = false}: Props) => (
|
||||
<button
|
||||
onClick={onClick}
|
||||
className={`${className} btn btn-${outline ? 'outline-' : ''}dark`}
|
||||
className={`${className} btn${outline ? 'Outline' : ''}Primary`}
|
||||
disabled={disabled}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { ImCancelCircle } from 'react-icons/im';
|
||||
import { TbLock, TbLockOpen } from 'react-icons/tb';
|
||||
import { MdContentCopy, MdDone, MdOutlineArrowBack } from 'react-icons/md';
|
||||
import { GrTest } from 'react-icons/gr';
|
||||
import { MdOutlineLibraryBooks } from "react-icons/md";
|
||||
|
||||
export const EditIcon = () => <FiEdit />;
|
||||
|
||||
@@ -25,4 +26,6 @@ export const DoneIcon = () => <MdDone />;
|
||||
|
||||
export const BackIcon = () => <MdOutlineArrowBack />;
|
||||
|
||||
export const ReplyIcon = () => <BsReply />;
|
||||
export const ReplyIcon = () => <BsReply />;
|
||||
|
||||
export const LearnMoreIcon = () => <MdOutlineLibraryBooks />;
|
||||
Reference in New Issue
Block a user