mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 01:25:37 -05:00
Another code layering (#4037)
* working on formatting * fixed basic lint errors; starting moving things to their appropriate location * formatting * update tslint to match the version of vscode we have * remove unused code * work in progress fixing layering * formatting * moved connection management service to platform * formatting * add missing file * moving more servies * formatting * moving more services * formatting * wip * moving more services * formatting * move css file * add missing svgs * moved the rest of services * formatting * changing around some references * formatting * revert tslint * revert some changes that brake things * formatting * fix tests * fix testzx * fix tests * fix tests * fix compile issue
This commit is contained in:
24
src/sql/platform/theme/common/colors.ts
Normal file
24
src/sql/platform/theme/common/colors.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { registerColor, foreground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
import * as nls from 'vs/nls';
|
||||
|
||||
export const tableHeaderBackground = registerColor('table.headerBackground', { dark: new Color(new RGBA(51, 51, 52)), light: new Color(new RGBA(245, 245, 245)), hc: '#333334' }, nls.localize('tableHeaderBackground', 'Table header background color'));
|
||||
export const tableHeaderForeground = registerColor('table.headerForeground', { dark: new Color(new RGBA(229, 229, 229)), light: new Color(new RGBA(16, 16, 16)), hc: '#e5e5e5' }, nls.localize('tableHeaderForeground', 'Table header foreground color'));
|
||||
export const disabledInputBackground = registerColor('input.disabled.background', { dark: '#444444', light: '#dcdcdc', hc: Color.black }, nls.localize('disabledInputBoxBackground', "Disabled Input box background."));
|
||||
export const disabledInputForeground = registerColor('input.disabled.foreground', { dark: '#888888', light: '#888888', hc: foreground }, nls.localize('disabledInputBoxForeground', "Disabled Input box foreground."));
|
||||
export const buttonFocusOutline = registerColor('button.focusOutline', { dark: '#eaeaea', light: '#666666', hc: null }, nls.localize('buttonFocusOutline', "Button outline color when focused."));
|
||||
export const disabledCheckboxForeground = registerColor('checkbox.disabled.foreground', { dark: '#888888', light: '#888888', hc: Color.black }, nls.localize('disabledCheckboxforeground', "Disabled checkbox foreground."));
|
||||
|
||||
export const listFocusAndSelectionBackground = registerColor('list.focusAndSelectionBackground', { dark: '#2c3295', light: '#2c3295', hc: null }, nls.localize('listFocusAndSelectionBackground', "List/Table background color for the selected and focus item when the list/table is active"));
|
||||
|
||||
// SQL Agent Colors
|
||||
export const tableBackground = registerColor('agent.tableBackground', { light: '#fffffe', dark: '#333333', hc: Color.black }, nls.localize('agentTableBackground', "SQL Agent Table background color."));
|
||||
export const cellBackground = registerColor('agent.cellBackground', { light: '#faf5f8', dark: Color.black, hc: Color.black }, nls.localize('agentCellBackground', "SQL Agent table cell background color."));
|
||||
export const tableHoverBackground = registerColor('agent.tableHoverColor', { light: '#dcdcdc', dark: '#444444', hc: null }, nls.localize('agentTableHoverBackground', "SQL Agent table hover background color."));
|
||||
export const jobsHeadingBackground = registerColor('agent.jobsHeadingColor', { light: '#f4f4f4', dark: '#444444', hc: '#2b56f2' }, nls.localize('agentJobsHeadingColor', "SQL Agent heading background color."));
|
||||
export const cellBorderColor = registerColor('agent.cellBorderColor', { light: null, dark: null, hc: '#2b56f2' }, nls.localize('agentCellBorderColor', "SQL Agent table cell border color."));
|
||||
274
src/sql/platform/theme/common/styler.ts
Normal file
274
src/sql/platform/theme/common/styler.ts
Normal file
@@ -0,0 +1,274 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as sqlcolors from './colors';
|
||||
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import * as cr from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IThemable, attachStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { SIDE_BAR_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { IPanelColors } from 'vs/workbench/browser/parts/views/panelViewlet';
|
||||
|
||||
export function attachModalDialogStyler(widget: IThemable, themeService: IThemeService, style?:
|
||||
{
|
||||
dialogForeground?: cr.ColorIdentifier,
|
||||
dialogHeaderAndFooterBackground?: cr.ColorIdentifier,
|
||||
dialogBodyBackground?: cr.ColorIdentifier,
|
||||
}): IDisposable {
|
||||
return attachStyler(themeService, {
|
||||
dialogForeground: (style && style.dialogForeground) || cr.foreground,
|
||||
dialogBorder: cr.contrastBorder,
|
||||
dialogHeaderAndFooterBackground: (style && style.dialogHeaderAndFooterBackground) || SIDE_BAR_BACKGROUND,
|
||||
dialogBodyBackground: (style && style.dialogBodyBackground) || cr.editorBackground
|
||||
}, widget);
|
||||
}
|
||||
|
||||
export function attachDropdownStyler(widget: IThemable, themeService: IThemeService, style?:
|
||||
{
|
||||
backgroundColor?: cr.ColorIdentifier,
|
||||
foregroundColor?: cr.ColorIdentifier,
|
||||
borderColor?: cr.ColorIdentifier,
|
||||
}): IDisposable {
|
||||
return attachStyler(themeService, {
|
||||
foregroundColor: (style && style.foregroundColor) || cr.inputForeground,
|
||||
borderColor: (style && style.borderColor) || cr.inputBorder,
|
||||
backgroundColor: (style && style.backgroundColor) || cr.editorBackground
|
||||
}, widget);
|
||||
}
|
||||
|
||||
export function attachInputBoxStyler(widget: IThemable, themeService: IThemeService, style?:
|
||||
{
|
||||
inputBackground?: cr.ColorIdentifier,
|
||||
inputForeground?: cr.ColorIdentifier,
|
||||
disabledInputBackground?: cr.ColorIdentifier,
|
||||
disabledInputForeground?: cr.ColorIdentifier,
|
||||
inputBorder?: cr.ColorIdentifier,
|
||||
inputValidationInfoBorder?: cr.ColorIdentifier,
|
||||
inputValidationInfoBackground?: cr.ColorIdentifier,
|
||||
inputValidationWarningBorder?: cr.ColorIdentifier,
|
||||
inputValidationWarningBackground?: cr.ColorIdentifier,
|
||||
inputValidationErrorBorder?: cr.ColorIdentifier,
|
||||
inputValidationErrorBackground?: cr.ColorIdentifier
|
||||
}): IDisposable {
|
||||
return attachStyler(themeService, {
|
||||
inputBackground: (style && style.inputBackground) || cr.inputBackground,
|
||||
inputForeground: (style && style.inputForeground) || cr.inputForeground,
|
||||
disabledInputBackground: (style && style.disabledInputBackground) || sqlcolors.disabledInputBackground,
|
||||
disabledInputForeground: (style && style.disabledInputForeground) || sqlcolors.disabledInputForeground,
|
||||
inputBorder: (style && style.inputBorder) || cr.inputBorder,
|
||||
inputValidationInfoBorder: (style && style.inputValidationInfoBorder) || cr.inputValidationInfoBorder,
|
||||
inputValidationInfoBackground: (style && style.inputValidationInfoBackground) || cr.inputValidationInfoBackground,
|
||||
inputValidationWarningBorder: (style && style.inputValidationWarningBorder) || cr.inputValidationWarningBorder,
|
||||
inputValidationWarningBackground: (style && style.inputValidationWarningBackground) || cr.inputValidationWarningBackground,
|
||||
inputValidationErrorBorder: (style && style.inputValidationErrorBorder) || cr.inputValidationErrorBorder,
|
||||
inputValidationErrorBackground: (style && style.inputValidationErrorBackground) || cr.inputValidationErrorBackground
|
||||
}, widget);
|
||||
}
|
||||
|
||||
export function attachSelectBoxStyler(widget: IThemable, themeService: IThemeService, style?:
|
||||
{
|
||||
selectBackground?: cr.ColorIdentifier,
|
||||
selectListBackground?: cr.ColorIdentifier,
|
||||
selectForeground?: cr.ColorIdentifier,
|
||||
selectBorder?: cr.ColorIdentifier,
|
||||
disabledSelectBackground?: cr.ColorIdentifier,
|
||||
disabledSelectForeground?: cr.ColorIdentifier,
|
||||
inputValidationInfoBorder?: cr.ColorIdentifier,
|
||||
inputValidationInfoBackground?: cr.ColorIdentifier,
|
||||
inputValidationWarningBorder?: cr.ColorIdentifier,
|
||||
inputValidationWarningBackground?: cr.ColorIdentifier,
|
||||
inputValidationErrorBorder?: cr.ColorIdentifier,
|
||||
inputValidationErrorBackground?: cr.ColorIdentifier,
|
||||
focusBorder?: cr.ColorIdentifier,
|
||||
listFocusBackground?: cr.ColorIdentifier,
|
||||
listFocusForeground?: cr.ColorIdentifier,
|
||||
listFocusOutline?: cr.ColorIdentifier,
|
||||
listHoverBackground?: cr.ColorIdentifier,
|
||||
listHoverForeground?: cr.ColorIdentifier
|
||||
}): IDisposable {
|
||||
return attachStyler(themeService, {
|
||||
selectBackground: (style && style.selectBackground) || cr.selectBackground,
|
||||
selectListBackground: (style && style.selectListBackground) || cr.selectListBackground,
|
||||
selectForeground: (style && style.selectForeground) || cr.selectForeground,
|
||||
selectBorder: (style && style.selectBorder) || cr.selectBorder,
|
||||
disabledSelectBackground: (style && style.disabledSelectBackground) || sqlcolors.disabledInputBackground,
|
||||
disabledSelectForeground: (style && style.disabledSelectForeground) || sqlcolors.disabledInputForeground,
|
||||
inputValidationInfoBorder: (style && style.inputValidationInfoBorder) || cr.inputValidationInfoBorder,
|
||||
inputValidationInfoBackground: (style && style.inputValidationInfoBackground) || cr.inputValidationInfoBackground,
|
||||
inputValidationWarningBorder: (style && style.inputValidationWarningBorder) || cr.inputValidationWarningBorder,
|
||||
inputValidationWarningBackground: (style && style.inputValidationWarningBackground) || cr.inputValidationWarningBackground,
|
||||
inputValidationErrorBorder: (style && style.inputValidationErrorBorder) || cr.inputValidationErrorBorder,
|
||||
inputValidationErrorBackground: (style && style.inputValidationErrorBackground) || cr.inputValidationErrorBackground,
|
||||
focusBorder: (style && style.focusBorder) || cr.focusBorder,
|
||||
listFocusBackground: (style && style.listFocusBackground) || cr.listFocusBackground,
|
||||
listFocusForeground: (style && style.listFocusForeground) || cr.listFocusForeground,
|
||||
listFocusOutline: (style && style.listFocusOutline) || cr.activeContrastBorder,
|
||||
listHoverBackground: (style && style.listHoverBackground) || cr.listHoverBackground,
|
||||
listHoverForeground: (style && style.listHoverForeground) || cr.listHoverForeground,
|
||||
listHoverOutline: (style && style.listFocusOutline) || cr.activeContrastBorder
|
||||
}, widget);
|
||||
}
|
||||
|
||||
export function attachListBoxStyler(widget: IThemable, themeService: IThemeService, style?:
|
||||
{
|
||||
selectBackground?: cr.ColorIdentifier,
|
||||
selectForeground?: cr.ColorIdentifier,
|
||||
selectBorder?: cr.ColorIdentifier,
|
||||
inputValidationInfoBorder?: cr.ColorIdentifier,
|
||||
inputValidationInfoBackground?: cr.ColorIdentifier,
|
||||
inputValidationWarningBorder?: cr.ColorIdentifier,
|
||||
inputValidationWarningBackground?: cr.ColorIdentifier,
|
||||
inputValidationErrorBorder?: cr.ColorIdentifier,
|
||||
inputValidationErrorBackground?: cr.ColorIdentifier
|
||||
}): IDisposable {
|
||||
return attachStyler(themeService, {
|
||||
selectBackground: (style && style.selectBackground) || cr.selectBackground,
|
||||
selectForeground: (style && style.selectForeground) || cr.selectForeground,
|
||||
selectBorder: (style && style.selectBorder) || cr.selectBorder,
|
||||
inputValidationInfoBorder: (style && style.inputValidationInfoBorder) || cr.inputValidationInfoBorder,
|
||||
inputValidationInfoBackground: (style && style.inputValidationInfoBackground) || cr.inputValidationInfoBackground,
|
||||
inputValidationWarningBorder: (style && style.inputValidationWarningBorder) || cr.inputValidationWarningBorder,
|
||||
inputValidationWarningBackground: (style && style.inputValidationWarningBackground) || cr.inputValidationWarningBackground,
|
||||
inputValidationErrorBorder: (style && style.inputValidationErrorBorder) || cr.inputValidationErrorBorder,
|
||||
inputValidationErrorBackground: (style && style.inputValidationErrorBackground) || cr.inputValidationErrorBackground
|
||||
}, widget);
|
||||
}
|
||||
|
||||
export function attachTableStyler(widget: IThemable, themeService: IThemeService, style?: {
|
||||
listFocusBackground?: cr.ColorIdentifier,
|
||||
listFocusForeground?: cr.ColorIdentifier,
|
||||
listActiveSelectionBackground?: cr.ColorIdentifier,
|
||||
listActiveSelectionForeground?: cr.ColorIdentifier,
|
||||
listFocusAndSelectionBackground?: cr.ColorIdentifier,
|
||||
listFocusAndSelectionForeground?: cr.ColorIdentifier,
|
||||
listInactiveFocusBackground?: cr.ColorIdentifier,
|
||||
listInactiveSelectionBackground?: cr.ColorIdentifier,
|
||||
listInactiveSelectionForeground?: cr.ColorIdentifier,
|
||||
listHoverBackground?: cr.ColorIdentifier,
|
||||
listHoverForeground?: cr.ColorIdentifier,
|
||||
listDropBackground?: cr.ColorIdentifier,
|
||||
listFocusOutline?: cr.ColorIdentifier,
|
||||
listInactiveFocusOutline?: cr.ColorIdentifier,
|
||||
listSelectionOutline?: cr.ColorIdentifier,
|
||||
listHoverOutline?: cr.ColorIdentifier,
|
||||
tableHeaderBackground?: cr.ColorIdentifier,
|
||||
tableHeaderForeground?: cr.ColorIdentifier
|
||||
}): IDisposable {
|
||||
return attachStyler(themeService, {
|
||||
listFocusBackground: (style && style.listFocusBackground) || cr.listFocusBackground,
|
||||
listFocusForeground: (style && style.listFocusForeground) || cr.listFocusForeground,
|
||||
listActiveSelectionBackground: (style && style.listActiveSelectionBackground) || cr.listActiveSelectionBackground,
|
||||
listActiveSelectionForeground: (style && style.listActiveSelectionForeground) || cr.listActiveSelectionForeground,
|
||||
listFocusAndSelectionBackground: style && style.listFocusAndSelectionBackground || sqlcolors.listFocusAndSelectionBackground,
|
||||
listFocusAndSelectionForeground: (style && style.listFocusAndSelectionForeground) || cr.listActiveSelectionForeground,
|
||||
listInactiveFocusBackground: (style && style.listInactiveFocusBackground),
|
||||
listInactiveSelectionBackground: (style && style.listInactiveSelectionBackground) || cr.listInactiveSelectionBackground,
|
||||
listInactiveSelectionForeground: (style && style.listInactiveSelectionForeground) || cr.listInactiveSelectionForeground,
|
||||
listHoverBackground: (style && style.listHoverBackground) || cr.listHoverBackground,
|
||||
listHoverForeground: (style && style.listHoverForeground) || cr.listHoverForeground,
|
||||
listDropBackground: (style && style.listDropBackground) || cr.listDropBackground,
|
||||
listFocusOutline: (style && style.listFocusOutline) || cr.activeContrastBorder,
|
||||
listSelectionOutline: (style && style.listSelectionOutline) || cr.activeContrastBorder,
|
||||
listHoverOutline: (style && style.listHoverOutline) || cr.activeContrastBorder,
|
||||
listInactiveFocusOutline: style && style.listInactiveFocusOutline,
|
||||
tableHeaderBackground: (style && style.tableHeaderBackground) || sqlcolors.tableHeaderBackground,
|
||||
tableHeaderForeground: (style && style.tableHeaderForeground) || sqlcolors.tableHeaderForeground
|
||||
}, widget);
|
||||
}
|
||||
|
||||
export function attachEditableDropdownStyler(widget: IThemable, themeService: IThemeService, style?: {
|
||||
listFocusBackground?: cr.ColorIdentifier,
|
||||
listFocusForeground?: cr.ColorIdentifier,
|
||||
listActiveSelectionBackground?: cr.ColorIdentifier,
|
||||
listActiveSelectionForeground?: cr.ColorIdentifier,
|
||||
listFocusAndSelectionBackground?: cr.ColorIdentifier,
|
||||
listFocusAndSelectionForeground?: cr.ColorIdentifier,
|
||||
listInactiveFocusBackground?: cr.ColorIdentifier,
|
||||
listInactiveSelectionBackground?: cr.ColorIdentifier,
|
||||
listInactiveSelectionForeground?: cr.ColorIdentifier,
|
||||
listHoverBackground?: cr.ColorIdentifier,
|
||||
listHoverForeground?: cr.ColorIdentifier,
|
||||
listDropBackground?: cr.ColorIdentifier,
|
||||
listFocusOutline?: cr.ColorIdentifier,
|
||||
listInactiveFocusOutline?: cr.ColorIdentifier,
|
||||
listSelectionOutline?: cr.ColorIdentifier,
|
||||
listHoverOutline?: cr.ColorIdentifier,
|
||||
|
||||
inputBackground?: cr.ColorIdentifier,
|
||||
inputForeground?: cr.ColorIdentifier,
|
||||
inputBorder?: cr.ColorIdentifier,
|
||||
inputValidationInfoBorder?: cr.ColorIdentifier,
|
||||
inputValidationInfoBackground?: cr.ColorIdentifier,
|
||||
inputValidationWarningBorder?: cr.ColorIdentifier,
|
||||
inputValidationWarningBackground?: cr.ColorIdentifier,
|
||||
inputValidationErrorBorder?: cr.ColorIdentifier,
|
||||
inputValidationErrorBackground?: cr.ColorIdentifier,
|
||||
contextBackground?: cr.ColorIdentifier,
|
||||
contextBorder?: cr.ColorIdentifier
|
||||
}): IDisposable {
|
||||
return attachStyler(themeService, {
|
||||
listFocusBackground: (style && style.listFocusBackground) || cr.listFocusBackground,
|
||||
listFocusForeground: (style && style.listFocusForeground) || cr.listFocusForeground,
|
||||
listActiveSelectionBackground: (style && style.listActiveSelectionBackground) || cr.lighten(cr.listActiveSelectionBackground, 0.1),
|
||||
listActiveSelectionForeground: (style && style.listActiveSelectionForeground) || cr.listActiveSelectionForeground,
|
||||
listFocusAndSelectionBackground: style && style.listFocusAndSelectionBackground || cr.listActiveSelectionBackground,
|
||||
listFocusAndSelectionForeground: (style && style.listFocusAndSelectionForeground) || cr.listActiveSelectionForeground,
|
||||
listInactiveFocusBackground: (style && style.listInactiveFocusBackground),
|
||||
listInactiveSelectionBackground: (style && style.listInactiveSelectionBackground) || cr.listInactiveSelectionBackground,
|
||||
listInactiveSelectionForeground: (style && style.listInactiveSelectionForeground) || cr.listInactiveSelectionForeground,
|
||||
listHoverBackground: (style && style.listHoverBackground) || cr.listHoverBackground,
|
||||
listHoverForeground: (style && style.listHoverForeground) || cr.listHoverForeground,
|
||||
listDropBackground: (style && style.listDropBackground) || cr.listDropBackground,
|
||||
listFocusOutline: (style && style.listFocusOutline) || cr.activeContrastBorder,
|
||||
listSelectionOutline: (style && style.listSelectionOutline) || cr.activeContrastBorder,
|
||||
listHoverOutline: (style && style.listHoverOutline) || cr.activeContrastBorder,
|
||||
listInactiveFocusOutline: style && style.listInactiveFocusOutline,
|
||||
inputBackground: (style && style.inputBackground) || cr.inputBackground,
|
||||
inputForeground: (style && style.inputForeground) || cr.inputForeground,
|
||||
inputBorder: (style && style.inputBorder) || cr.inputBorder,
|
||||
inputValidationInfoBorder: (style && style.inputValidationInfoBorder) || cr.inputValidationInfoBorder,
|
||||
inputValidationInfoBackground: (style && style.inputValidationInfoBackground) || cr.inputValidationInfoBackground,
|
||||
inputValidationWarningBorder: (style && style.inputValidationWarningBorder) || cr.inputValidationWarningBorder,
|
||||
inputValidationWarningBackground: (style && style.inputValidationWarningBackground) || cr.inputValidationWarningBackground,
|
||||
inputValidationErrorBorder: (style && style.inputValidationErrorBorder) || cr.inputValidationErrorBorder,
|
||||
inputValidationErrorBackground: (style && style.inputValidationErrorBackground) || cr.inputValidationErrorBackground,
|
||||
contextBackground: (style && style.contextBackground) || cr.editorBackground,
|
||||
contextBorder: (style && style.contextBorder) || cr.inputBorder
|
||||
}, widget);
|
||||
}
|
||||
|
||||
export function attachButtonStyler(widget: IThemable, themeService: IThemeService, style?: {
|
||||
buttonForeground?: cr.ColorIdentifier,
|
||||
buttonBackground?: cr.ColorIdentifier,
|
||||
buttonHoverBackground?: cr.ColorIdentifier,
|
||||
buttonFocusOutline?: cr.ColorIdentifier
|
||||
}): IDisposable {
|
||||
return attachStyler(themeService, {
|
||||
buttonForeground: (style && style.buttonForeground) || cr.buttonForeground,
|
||||
buttonBackground: (style && style.buttonBackground) || cr.buttonBackground,
|
||||
buttonHoverBackground: (style && style.buttonHoverBackground) || cr.buttonHoverBackground,
|
||||
buttonBorder: cr.contrastBorder,
|
||||
buttonFocusOutline: (style && style.buttonFocusOutline) || sqlcolors.buttonFocusOutline
|
||||
}, widget);
|
||||
}
|
||||
|
||||
export function attachCheckboxStyler(widget: IThemable, themeService: IThemeService, style?: { disabledCheckboxForeground?: cr.ColorIdentifier })
|
||||
: IDisposable {
|
||||
return attachStyler(themeService, {
|
||||
disabledCheckboxForeground: (style && style.disabledCheckboxForeground) || sqlcolors.disabledCheckboxForeground
|
||||
}, widget);
|
||||
}
|
||||
|
||||
export function attachPanelStyler(widget: IThemable, themeService: IThemeService) {
|
||||
return attachStyler<IPanelColors>(themeService, {
|
||||
headerForeground: SIDE_BAR_SECTION_HEADER_FOREGROUND,
|
||||
headerBackground: SIDE_BAR_SECTION_HEADER_BACKGROUND,
|
||||
// headerHighContrastBorder: index === 0 ? null : contrastBorder,
|
||||
dropBackground: SIDE_BAR_DRAG_AND_DROP_BACKGROUND
|
||||
}, widget);
|
||||
}
|
||||
Reference in New Issue
Block a user