canvas option팝업 추가
This commit is contained in:
parent
8a45143d50
commit
1bba9bde8a
3
public/static/images/canvas/arr_btn_ico.svg
Normal file
3
public/static/images/canvas/arr_btn_ico.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="5" height="8" viewBox="0 0 5 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 6.5L3.5 4L1 1.5" stroke="#898989" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 166 B |
3
public/static/images/canvas/arr_btn_ico_black.svg
Normal file
3
public/static/images/canvas/arr_btn_ico_black.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="5" height="8" viewBox="0 0 5 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 6.5L3.5 4L1 1.5" stroke="#101010" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 166 B |
3
public/static/images/canvas/check-black.svg
Normal file
3
public/static/images/canvas/check-black.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="11" height="9" viewBox="0 0 11 9" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 3.18182L4.5 7L10 1" stroke="#101010" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 171 B |
3
public/static/images/canvas/check-grey.svg
Normal file
3
public/static/images/canvas/check-grey.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="11" height="9" viewBox="0 0 11 9" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 3.18182L4.5 7L10 1" stroke="#898989" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 171 B |
10
public/static/images/canvas/modal_close.svg
Normal file
10
public/static/images/canvas/modal_close.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_55_91)">
|
||||
<path d="M8.99915 9L1 1M1.00085 9L9 1" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_55_91">
|
||||
<rect width="10" height="10" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 361 B |
@ -1,18 +1,24 @@
|
||||
'use client'
|
||||
|
||||
import CanvasLayout from '@/components/canvas/CanvasLayout'
|
||||
import CanvasMenu from '@/components/canvas/CanvasMenu'
|
||||
import SettingModal01 from '@/components/canvas/modal/settoing01/SettingModal01'
|
||||
import Header from '@/components/header/Header'
|
||||
import '@/styles/style.scss'
|
||||
import { useState } from 'react'
|
||||
|
||||
export default function CanvasPage() {
|
||||
const [modalOpen, setModalOpen] = useState('option');
|
||||
return(
|
||||
<div className="wrap">
|
||||
<Header/>
|
||||
<div className="content">
|
||||
<div className="canvas-wrap">
|
||||
<CanvasMenu/>
|
||||
<CanvasMenu modalOpen={modalOpen} setModalOpen={setModalOpen}/>
|
||||
<div className="canvas-content">
|
||||
<CanvasLayout/>
|
||||
</div>
|
||||
{modalOpen === 'option' && <SettingModal01 modalOpen={modalOpen} setModalOpen={setModalOpen}/>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -15,6 +15,8 @@ export default function InputWrapPage (){
|
||||
<div className="form-btn">
|
||||
<button className="btn-frame deepgray">屋根面の割り当て</button>
|
||||
<button className="btn-frame gray">屋根面の割り当て</button>
|
||||
<button className="btn-frame modal">屋根面の割り当て</button>
|
||||
<button className="btn-frame modal act">屋根面の割り当て</button>
|
||||
<button className="btn-frame small dark">移動</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -47,6 +49,33 @@ export default function InputWrapPage (){
|
||||
<ColorPicker/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="input-wrap">
|
||||
<h1>Check-Btn</h1>
|
||||
<div className="form-Check-btn">
|
||||
<button className="check-btn">
|
||||
<span className="check-area"></span>
|
||||
<span className="title-area">ü割り当て表示</span>
|
||||
</button>
|
||||
<button className="check-btn act">
|
||||
<span className="check-area"></span>
|
||||
<span className="title-area">ü割り当て表示</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="input-wrap">
|
||||
<h1>Arrow-Btn</h1>
|
||||
<div className="form-Arrow-btn">
|
||||
<button className="arr-btn">
|
||||
<span>文字フォントの変更</span>
|
||||
</button>
|
||||
<button className="arr-btn act">
|
||||
<span>文字フォントの変更</span>
|
||||
</button>
|
||||
<button className="arr-btn act">
|
||||
<span>文字フォントの変更</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
import RecoilRootWrapper from './RecoilWrapper'
|
||||
import QModal from '@/components/common/modal/QModal'
|
||||
import '@/styles/common.scss'
|
||||
// import '@/styles/style.scss'
|
||||
|
||||
@ -14,7 +13,6 @@ export default function RootLayout({ children }) {
|
||||
<body>
|
||||
<RecoilRootWrapper>
|
||||
{children}
|
||||
<QModal />
|
||||
</RecoilRootWrapper>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { modalContent, modalState } from '@/store/modalAtom'
|
||||
|
||||
export default function ModalPage() {
|
||||
const [open, setOpen] = useRecoilState(modalState)
|
||||
const [contents, setContent] = useRecoilState(modalContent)
|
||||
|
||||
const ipsum = (
|
||||
<>
|
||||
<p>title</p>
|
||||
<p>
|
||||
저작자·발명가·과학기술자와 예술가의 권리는 법률로써 보호한다. 이 헌법은 1988년 2월 25일부터 시행한다. 다만, 이 헌법을 시행하기 위하여 필요한
|
||||
법률의 제정·개정과 이 헌법에 의한 대통령 및 국회의원의 선거 기타 이 헌법시행에 관한 준비는 이 헌법시행 전에 할 수 있다.
|
||||
</p>
|
||||
<p>
|
||||
국가는 주택개발정책등을 통하여 모든 국민이 쾌적한 주거생활을 할 수 있도록 노력하여야 한다. 통신·방송의 시설기준과 신문의 기능을 보장하기
|
||||
위하여 필요한 사항은 법률로 정한다.
|
||||
</p>
|
||||
<p>
|
||||
국회에서 의결된 법률안은 정부에 이송되어 15일 이내에 대통령이 공포한다. 선거에 관한 경비는 법률이 정하는 경우를 제외하고는 정당 또는
|
||||
후보자에게 부담시킬 수 없다.
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<button
|
||||
onClick={() => {
|
||||
setContent(ipsum)
|
||||
setOpen(true)
|
||||
}}
|
||||
>
|
||||
OPEN MODAL
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
|
||||
export default function CanvasFrame () {
|
||||
return(
|
||||
<div className="canvas-frame">
|
||||
|
||||
@ -3,7 +3,7 @@ import { useState } from "react";
|
||||
import Qselect from "../common/select/Qselect";
|
||||
import MenuDepth01 from "./MenuDepth01";
|
||||
|
||||
export default function CanvasMenu() {
|
||||
export default function CanvasMenu({setModalOpen}) {
|
||||
const [menuNumber, setMenuNumber] = useState(null);
|
||||
const SelectOption = [
|
||||
{name: '瓦53A',}, {name: '瓦53A'}
|
||||
@ -45,7 +45,7 @@ export default function CanvasMenu() {
|
||||
<button className="btn01 "></button>
|
||||
<button className="btn02 active"></button>
|
||||
<button className="btn03"></button>
|
||||
<button className="btn04"></button>
|
||||
<button className="btn04" onClick={() => setModalOpen('option')}></button>
|
||||
<button className="btn05"></button>
|
||||
<button className="btn06"></button>
|
||||
</div>
|
||||
|
||||
49
src/components/canvas/modal/settoing01/FirstOption.jsx
Normal file
49
src/components/canvas/modal/settoing01/FirstOption.jsx
Normal file
@ -0,0 +1,49 @@
|
||||
import { HandleBtnClick } from "./SettingModal01"
|
||||
|
||||
const buttonList01 = [
|
||||
{id: 1, name: '割り当て表示'},
|
||||
{id: 2, name: '実寸表示'},
|
||||
{id: 3, name: '図面表示'},
|
||||
{id: 4, name: '寸法表示なし'},
|
||||
{id: 5, name: 'グリッド表示'},
|
||||
{id: 6, name: '架台表示'},
|
||||
{id: 7, name: '文字表示'},
|
||||
{id: 8, name: '座標表示'},
|
||||
{id: 9, name: '流れ方向表示'},
|
||||
{id: 10, name: '図面切替表示'},
|
||||
{id: 11, name: 'ü廊下寸法表示'},
|
||||
]
|
||||
const buttonList02 = [
|
||||
{id: 1, name: 'ボーダーのみ'},
|
||||
{id: 2, name: 'ラインハッチ'},
|
||||
{id: 3, name: 'All painted'},
|
||||
]
|
||||
|
||||
export default function FirstOption (){
|
||||
return(
|
||||
<>
|
||||
<div className="modal-check-btn-wrap">
|
||||
<h3 className="check-wrap-title light">※図面に表示する項目をクリックすると適用されます。</h3>
|
||||
<div className="flex-check-box for2">
|
||||
{buttonList01.map((item)=>(
|
||||
<button key={item.id} className="check-btn" onClick={(e) => HandleBtnClick(e)}>
|
||||
<span className="check-area"></span>
|
||||
<span className="title-area">{item.name}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-check-btn-wrap">
|
||||
<h3 className="check-wrap-title">画面表示</h3>
|
||||
<div className="flex-check-box for-line">
|
||||
{buttonList02.map((item)=>(
|
||||
<button key={item.id} className="check-btn" onClick={(e) => HandleBtnClick(e)}>
|
||||
<span className="check-area"></span>
|
||||
<span className="title-area">{item.name}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
50
src/components/canvas/modal/settoing01/SecondOption.jsx
Normal file
50
src/components/canvas/modal/settoing01/SecondOption.jsx
Normal file
@ -0,0 +1,50 @@
|
||||
import { HandleBtnClick } from "./SettingModal01"
|
||||
|
||||
const buttonList01 = [
|
||||
{id: 1, name: '文字フォントの変更'},
|
||||
{id: 2, name: 'フロー方向フォントの変更'},
|
||||
{id: 3, name: '寸法フォントの変更'},
|
||||
{id: 4, name: '回路番号フォントの変更'},
|
||||
]
|
||||
const buttonList02 = [
|
||||
{id: 1, name: '極小'},
|
||||
{id: 2, name: '牛'},
|
||||
{id: 3, name: '中'},
|
||||
{id: 4, name: 'ティーン'},
|
||||
]
|
||||
|
||||
export default function SecondOption (){
|
||||
return(
|
||||
<>
|
||||
<div className="modal-check-btn-wrap">
|
||||
<h3 className="check-wrap-title">フォントとサイズの変更</h3>
|
||||
<div className="flex-check-box for2">
|
||||
{buttonList01.map((item)=>(
|
||||
<button className="arr-btn">
|
||||
<span>{item.name}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-check-btn-wrap">
|
||||
<h3 className="check-wrap-title">吸着範囲の設定</h3>
|
||||
<div className="flex-check-box for-line">
|
||||
{buttonList02.map((item)=>(
|
||||
<button key={item.id} className="check-btn" onClick={(e) => HandleBtnClick(e)}>
|
||||
<span className="check-area"></span>
|
||||
<span className="title-area">{item.name}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex-check-box for-line">
|
||||
<button className="arr-btn">
|
||||
<span>寸法線の設定</span>
|
||||
</button>
|
||||
<button className="arr-btn">
|
||||
<span>図面サイズの設定</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
56
src/components/canvas/modal/settoing01/SettingModal01.jsx
Normal file
56
src/components/canvas/modal/settoing01/SettingModal01.jsx
Normal file
@ -0,0 +1,56 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from "react";
|
||||
import FirstOption from "./FirstOption";
|
||||
import SecondOption from "./SecondOption";
|
||||
import WithDraggable from "@/components/common/draggable/withDraggable";
|
||||
|
||||
export const HandleBtnClick = (e) => {
|
||||
const button = e.target.closest('button');
|
||||
if(!button.classList.contains('act')){
|
||||
button.classList.add('act');
|
||||
}else{
|
||||
button.classList.remove('act');
|
||||
}
|
||||
}
|
||||
|
||||
export default function SettingModal01 ({modalOpen, setModalOpen}){
|
||||
const [buttonAct, setButtonAct] = useState(1);
|
||||
const [close, setClose] = useState(false)
|
||||
const HandleClickClose = () => {
|
||||
setClose(true)
|
||||
setTimeout(() => {
|
||||
setModalOpen('');
|
||||
setClose(false);
|
||||
}, 180)
|
||||
}
|
||||
return(
|
||||
<WithDraggable isShow={true}>
|
||||
<div className={`modal-pop-wrap sm ${modalOpen === 'option' && close === false ? 'mount' : ''}${close ? 'unmount' : ''} `}>
|
||||
<div className="modal-head">
|
||||
<h1 className="title">Canvas設定</h1>
|
||||
<button className="modal-close" onClick={HandleClickClose}>닫기</button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<div className="modal-btn-wrap">
|
||||
<button
|
||||
className={`btn-frame modal ${buttonAct === 1 ? 'act' : ''}`}
|
||||
onClick={() => setButtonAct(1)}
|
||||
>
|
||||
ディスプレイ設定
|
||||
</button>
|
||||
|
||||
<button
|
||||
className={`btn-frame modal ${buttonAct === 2 ? 'act' : ''}`}
|
||||
onClick={() => setButtonAct(2)}
|
||||
>
|
||||
フォントと図面サイズの設定
|
||||
</button>
|
||||
</div>
|
||||
{buttonAct === 1 && <FirstOption/>}
|
||||
{buttonAct === 2 && <SecondOption/>}
|
||||
</div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
|
||||
import { Modal } from 'react-responsive-modal'
|
||||
|
||||
import { modalContent, modalState } from '@/store/modalAtom'
|
||||
|
||||
import 'react-responsive-modal/styles.css'
|
||||
|
||||
export default function QModal() {
|
||||
const [open, setOpen] = useRecoilState(modalState)
|
||||
const children = useRecoilValue(modalContent)
|
||||
|
||||
return (
|
||||
<Modal open={open} onClose={() => setOpen(false)} center>
|
||||
{children}
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
.input-content{
|
||||
max-width: 1600px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 100px;
|
||||
.input-wrap{
|
||||
padding: 50px 50px 0;
|
||||
h1{
|
||||
@ -22,5 +23,13 @@
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
.form-Arrow-btn,
|
||||
.form-Check-btn{
|
||||
padding: 10px;
|
||||
background-color: #272727;
|
||||
> button{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
91
src/styles/_modal.scss
Normal file
91
src/styles/_modal.scss
Normal file
@ -0,0 +1,91 @@
|
||||
@keyframes mountpop{
|
||||
from{opacity: 0; scale: 0.95;}
|
||||
to{opacity: 1; scale: 1;}
|
||||
}
|
||||
@keyframes unmountpop{
|
||||
from{opacity: 1; scale: 1;}
|
||||
to{opacity: 0; scale: 0.95;}
|
||||
}
|
||||
|
||||
.modal-pop-wrap{
|
||||
position: fixed;
|
||||
top: 200px;
|
||||
right: 100px;
|
||||
width: 100%;
|
||||
min-width: 380px;
|
||||
max-width: fit-content;
|
||||
height: -webkit-fit-content;
|
||||
height: -moz-fit-content;
|
||||
height: fit-content;
|
||||
border: 1px solid #000;
|
||||
border-radius: 4px;
|
||||
background-color: #272727;
|
||||
z-index: 9999999;
|
||||
&.sm{
|
||||
max-width: 450px;
|
||||
}
|
||||
&.mount{
|
||||
animation: mountpop .17s ease-in-out forwards;
|
||||
}
|
||||
&.unmount{
|
||||
animation: unmountpop .17s ease-in-out forwards;
|
||||
}
|
||||
}
|
||||
.modal-head{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 24px;
|
||||
background-color: #000;
|
||||
cursor: pointer;
|
||||
h1.title{
|
||||
font-size: 13px;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
.modal-close{
|
||||
margin-left: auto;
|
||||
color: #fff;
|
||||
text-indent: -999999999px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: url(../../public/static/images/canvas/modal_close.svg)no-repeat center;
|
||||
}
|
||||
}
|
||||
.modal-body{
|
||||
padding: 15px;
|
||||
.modal-btn-wrap{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
button{
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
.modal-check-btn-wrap{
|
||||
margin-top: 15px;
|
||||
.check-wrap-title{
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
&.light{
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
.flex-check-box{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-top: 15px;
|
||||
&.for2{
|
||||
button{
|
||||
width: calc(50% - 5px);
|
||||
}
|
||||
}
|
||||
&.for-line{
|
||||
button{
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,7 +137,7 @@ button{
|
||||
border: 1px solid #000;
|
||||
text-align: center;
|
||||
font-family: 'Pretendard', sans-serif;
|
||||
transition: color .12s ease-in-out;
|
||||
transition: all .17s ease-in-out;
|
||||
cursor: pointer;
|
||||
&.block{
|
||||
width: 100%;
|
||||
@ -161,6 +161,27 @@ button{
|
||||
background-color: #1C1C1C;
|
||||
border: 1px solid #484848;
|
||||
}
|
||||
&.modal{
|
||||
background-color: #272727;
|
||||
border: 1px solid #484848;
|
||||
color: #aaa;
|
||||
&:hover{
|
||||
background-color: #1083E3;
|
||||
border: 1px solid #1083E3;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
&.act{
|
||||
background-color: #1083E3;
|
||||
border: 1px solid #1083E3;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
}
|
||||
&.block{
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// select
|
||||
@ -278,3 +299,81 @@ input[type=text]{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check-btn
|
||||
.check-btn{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
background-color: #3A3A3A;
|
||||
border-radius: 3px;
|
||||
transition: all .17s ease-in-out;
|
||||
.check-area{
|
||||
flex: none;
|
||||
width: 30px;
|
||||
height: 100%;
|
||||
border-right: 1px solid #272727;
|
||||
background: url(../../public/static/images/canvas/check-grey.svg)no-repeat center;
|
||||
background-size: 11px 9px;
|
||||
}
|
||||
.title-area{
|
||||
padding: 0 10px;
|
||||
font-size: 12px;
|
||||
color: #898989;
|
||||
font-weight: 400;
|
||||
}
|
||||
&.block{
|
||||
width: 100%;
|
||||
}
|
||||
&:hover,
|
||||
&.act{
|
||||
background-color: #fff;
|
||||
.check-area{
|
||||
border-right: 1px solid #101010;
|
||||
background: url(../../public/static/images/canvas/check-black.svg)no-repeat center;
|
||||
}
|
||||
.title-area{
|
||||
color: #101010;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// arr-btn
|
||||
.arr-btn{
|
||||
display: block;
|
||||
height: 30px;
|
||||
border-radius: 3px;
|
||||
background-color: #3A3A3A;
|
||||
padding: 0 11px;
|
||||
text-align: left;
|
||||
transition: all .17s ease-in-out;
|
||||
span{
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
color: #898989;
|
||||
font-weight: 400;
|
||||
padding-right: 15px;
|
||||
&:after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
transform: translateY(-50%);
|
||||
width: 5px;
|
||||
height: 8px;
|
||||
background: url(../../public/static/images/canvas/arr_btn_ico.svg)no-repeat center;
|
||||
}
|
||||
}
|
||||
&:hover,
|
||||
&.act{
|
||||
background-color: #fff;
|
||||
span{
|
||||
color: #101010;
|
||||
font-weight: 500;
|
||||
&:after{
|
||||
background: url(../../public/static/images/canvas/arr_btn_ico_black.svg)no-repeat center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,2 +1,3 @@
|
||||
@import '_layout.scss';
|
||||
@import '_contents.scss';
|
||||
@import '_modal.scss';
|
||||
Loading…
x
Reference in New Issue
Block a user