mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Converting Orchard.Themes
--HG-- branch : dev
This commit is contained in:
@@ -18,7 +18,7 @@ namespace Orchard.Themes.Controllers {
|
||||
public AdminController(
|
||||
IOrchardServices services,
|
||||
IThemeService themeService,
|
||||
PreviewTheme previewTheme,
|
||||
IPreviewTheme previewTheme,
|
||||
IAuthorizer authorizer,
|
||||
INotifier notifier,
|
||||
IShapeHelperFactory shapeHelperFactory) {
|
||||
@@ -37,11 +37,11 @@ namespace Orchard.Themes.Controllers {
|
||||
var themes = _themeService.GetInstalledThemes();
|
||||
var currentTheme = _themeService.GetSiteTheme();
|
||||
var model = new ThemesIndexViewModel { CurrentTheme = currentTheme, Themes = themes };
|
||||
return View(Shape.Model(model));
|
||||
return View(model);
|
||||
}
|
||||
catch (Exception exception) {
|
||||
Services.Notifier.Error(T("Listing themes failed: " + exception.Message));
|
||||
return View(Shape.Model(new ThemesIndexViewModel()));
|
||||
return View(new ThemesIndexViewModel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +102,10 @@ namespace Orchard.Themes.Controllers {
|
||||
}
|
||||
}
|
||||
|
||||
public ActionResult Install() {
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Install(FormCollection input) {
|
||||
try {
|
||||
|
@@ -78,20 +78,20 @@
|
||||
<Compile Include="Preview\IPreviewTheme.cs" />
|
||||
<Compile Include="Preview\PreviewTheme.cs" />
|
||||
<Compile Include="Preview\PreviewThemeFilter.cs" />
|
||||
<Compile Include="Preview\PreviewThemeSelector.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\SafeModeThemeSelector.cs" />
|
||||
<Compile Include="Services\SiteThemeSelector.cs" />
|
||||
<Compile Include="Services\ThemeService.cs" />
|
||||
<Compile Include="Services\ThemeZoneManagerEvents.cs" />
|
||||
<Compile Include="ViewModels\PreviewViewModel.cs" />
|
||||
<Compile Include="ViewModels\ThemesIndexViewModel.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Content\orchard.ico" />
|
||||
<Content Include="Styles\admin.css" />
|
||||
<Content Include="Views\Admin\Index.aspx" />
|
||||
<None Include="Views\Admin\Index.cshtml" />
|
||||
<Content Include="Views\Admin\Install.aspx" />
|
||||
<Content Include="Views\Admin\ThemePreview.ascx" />
|
||||
<None Include="Views\ThemePreview.cshtml" />
|
||||
<Content Include="Web.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@@ -1,36 +1,29 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using Orchard.Mvc;
|
||||
|
||||
namespace Orchard.Themes.Preview {
|
||||
public class PreviewTheme : IPreviewTheme, IThemeSelector {
|
||||
public class PreviewTheme : IPreviewTheme {
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private static readonly string PreviewThemeKey = typeof(PreviewTheme).FullName;
|
||||
private readonly HttpContextBase _httpContext;
|
||||
|
||||
public PreviewTheme(HttpContextBase httpContext) {
|
||||
_httpContext = httpContext;
|
||||
public PreviewTheme(IHttpContextAccessor httpContextAccessor) {
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
public string GetPreviewTheme() {
|
||||
return Convert.ToString(_httpContext.Session[PreviewThemeKey]);
|
||||
var httpContext = _httpContextAccessor.Current();
|
||||
return Convert.ToString(httpContext.Session[PreviewThemeKey]);
|
||||
}
|
||||
|
||||
public void SetPreviewTheme(string themeName) {
|
||||
var httpContext = _httpContextAccessor.Current();
|
||||
if (string.IsNullOrEmpty(themeName)) {
|
||||
_httpContext.Session.Remove(PreviewThemeKey);
|
||||
httpContext.Session.Remove(PreviewThemeKey);
|
||||
}
|
||||
else {
|
||||
_httpContext.Session[PreviewThemeKey] = themeName;
|
||||
httpContext.Session[PreviewThemeKey] = themeName;
|
||||
}
|
||||
}
|
||||
|
||||
public ThemeSelectorResult GetTheme(RequestContext context) {
|
||||
var previewThemeName = GetPreviewTheme();
|
||||
if (string.IsNullOrEmpty(previewThemeName))
|
||||
return null;
|
||||
|
||||
return new ThemeSelectorResult { Priority = 90, ThemeName = previewThemeName };
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -23,19 +23,20 @@ namespace Orchard.Themes.Preview {
|
||||
if (string.IsNullOrEmpty(previewThemeName))
|
||||
return;
|
||||
|
||||
var themes = _themeService.GetInstalledThemes();
|
||||
var model = new PreviewViewModel {
|
||||
Themes = themes.Select(theme => new SelectListItem {
|
||||
Text = theme.DisplayName,
|
||||
Value = theme.ThemeName,
|
||||
Selected = theme.ThemeName == previewThemeName
|
||||
})
|
||||
};
|
||||
var installedThemes = _themeService.GetInstalledThemes();
|
||||
var themeListItems = installedThemes
|
||||
.Select(theme => new SelectListItem {
|
||||
Text = theme.DisplayName,
|
||||
Value = theme.ThemeName,
|
||||
Selected = theme.ThemeName == previewThemeName
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
||||
var shape = _shapeHelperFactory.CreateHelper();
|
||||
_workContextAccessor.GetContext(filterContext).Page.Zones["Body"].Add(shape.ThemePreview(model), ":before");
|
||||
_workContextAccessor.GetContext(filterContext).Page.Zones["Body"].Add(shape.ThemePreview(Themes: themeListItems), ":before");
|
||||
}
|
||||
|
||||
public void OnResultExecuted(ResultExecutedContext filterContext) {}
|
||||
public void OnResultExecuted(ResultExecutedContext filterContext) { }
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
using System.Web.Routing;
|
||||
|
||||
namespace Orchard.Themes.Preview {
|
||||
public class PreviewThemeSelector : IThemeSelector {
|
||||
private readonly IPreviewTheme _previewTheme;
|
||||
|
||||
public PreviewThemeSelector(IPreviewTheme previewTheme) {
|
||||
_previewTheme = previewTheme;
|
||||
}
|
||||
|
||||
public ThemeSelectorResult GetTheme(RequestContext context) {
|
||||
var previewThemeName = _previewTheme.GetPreviewTheme();
|
||||
if (string.IsNullOrEmpty(previewThemeName))
|
||||
return null;
|
||||
|
||||
return new ThemeSelectorResult { Priority = 90, ThemeName = previewThemeName };
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Orchard.Themes.ViewModels {
|
||||
public class PreviewViewModel {
|
||||
public IEnumerable<SelectListItem> Themes { get; set; }
|
||||
}
|
||||
}
|
@@ -1,53 +0,0 @@
|
||||
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<ThemesIndexViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Mvc.Html"%>
|
||||
<%@ Import Namespace="Orchard.Themes.ViewModels"%><%
|
||||
Html.RegisterStyle("admin.css"); %>
|
||||
<h1><%: Html.TitleForPage(T("Manage Themes").ToString()) %></h1>
|
||||
<% if (Model.CurrentTheme == null) {
|
||||
%><p><%: T("There is no current theme in the application. The built-in theme will be used.")
|
||||
%><br /><%: Html.ActionLink(T("Install a new Theme").ToString(), "Install") %></p><%
|
||||
} else {
|
||||
%><h3><%: T("Current Theme")%> - <%: Model.CurrentTheme.DisplayName %></h3>
|
||||
|
||||
<%: Html.Image(Html.ThemePath(Model.CurrentTheme, "/Theme.png"), Html.Encode(Model.CurrentTheme.DisplayName), new { @class = "themePreviewImage" })%>
|
||||
<h5><%: T("By") %> <%: Model.CurrentTheme.Author %></h5>
|
||||
|
||||
<p>
|
||||
<%: T("Version:") %> <%: Model.CurrentTheme.Version %><br />
|
||||
<%: Model.CurrentTheme.Description %><br />
|
||||
<%: Model.CurrentTheme.HomePage %>
|
||||
</p>
|
||||
<%: Html.ActionLink(T("Install a new Theme").ToString(), "Install", null, new { @class = "button primaryAction" })%>
|
||||
|
||||
<% } %>
|
||||
<h2><%: T("Available Themes")%></h2>
|
||||
<ul class="templates">
|
||||
<% foreach (var theme in Model.Themes) {
|
||||
if (Model.CurrentTheme == null || theme.ThemeName != Model.CurrentTheme.ThemeName) {
|
||||
%> <li>
|
||||
<div>
|
||||
<h3><%: theme.DisplayName %></h3>
|
||||
<%: Html.Image(Html.ThemePath(theme, "/Theme.png"), Html.Encode(theme.DisplayName), null)%>
|
||||
<% using (Html.BeginFormAntiForgeryPost(Url.Action("Activate"), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<%: Html.Hidden("themeName", theme.ThemeName)%>
|
||||
<button type="submit" title="<%: T("Activate") %>"><%: T("Activate") %></button>
|
||||
<% } %>
|
||||
<% using (Html.BeginFormAntiForgeryPost(Url.Action("Preview"), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<%: Html.Hidden("themeName", theme.ThemeName)%>
|
||||
<button type="submit" title="<%: T("Preview") %>"><%: T("Preview") %></button>
|
||||
<% } %>
|
||||
<h5><%: T("By") %> <%: theme.Author %></h5>
|
||||
<p>
|
||||
<%: T("Version:") %> <%: theme.Version %><br />
|
||||
<%: theme.Description %><br />
|
||||
<%: theme.HomePage %>
|
||||
</p>
|
||||
<% using (Html.BeginFormAntiForgeryPost(Url.Action("Uninstall"), FormMethod.Post, new { @class = "inline link" })) { %>
|
||||
<%: Html.Hidden("themeName", theme.ThemeName)%>
|
||||
<button type="submit" class="uninstall" title="<%: T("Uninstall") %>"><%: T("Uninstall")%></button>
|
||||
<% } %>
|
||||
</div>
|
||||
</li>
|
||||
<% }
|
||||
} %>
|
||||
</ul>
|
@@ -0,0 +1,57 @@
|
||||
@model Orchard.Themes.ViewModels.ThemesIndexViewModel
|
||||
@{
|
||||
Html.RegisterStyle("admin.css");
|
||||
}
|
||||
|
||||
<h1>@Html.TitleForPage(T("Manage Themes").ToString())</h1>
|
||||
@if (Model.CurrentTheme == null) {
|
||||
<p>
|
||||
@T("There is no current theme in the application. The built-in theme will be used.")<br />
|
||||
@Html.ActionLink(T("Install a new Theme").ToString(), "Install")
|
||||
</p>
|
||||
} else {
|
||||
<h3>@T("Current Theme") - @Model.CurrentTheme.DisplayName</h3>
|
||||
|
||||
@Html.Image(Href(Html.ThemePath(Model.CurrentTheme, "/Theme.png")), Html.Encode(Model.CurrentTheme.DisplayName), new { @class = "themePreviewImage" })
|
||||
<h5>@T("By") @Model.CurrentTheme.Author</h5>
|
||||
|
||||
<p>
|
||||
@T("Version:") @Model.CurrentTheme.Version<br />
|
||||
@Model.CurrentTheme.Description<br />
|
||||
@Model.CurrentTheme.HomePage
|
||||
</p>
|
||||
|
||||
@Html.ActionLink(T("Install a new Theme").ToString(), "Install", null, new { @class = "button primaryAction" })
|
||||
}
|
||||
|
||||
<h2>@T("Available Themes")</h2>
|
||||
<ul class="templates">
|
||||
@foreach (var theme in Model.Themes) {
|
||||
if (Model.CurrentTheme == null || theme.ThemeName != Model.CurrentTheme.ThemeName) {
|
||||
<li>
|
||||
<div>
|
||||
<h3>@theme.DisplayName</h3>
|
||||
@Html.Image(Href(Html.ThemePath(theme, "/Theme.png")), Html.Encode(theme.DisplayName), null)
|
||||
@using (Html.BeginFormAntiForgeryPost(Url.Action("Activate"), FormMethod.Post, new { @class = "inline" })) {
|
||||
@Html.Hidden("themeName", theme.ThemeName)
|
||||
<button type="submit" title="@T("Activate")">@T("Activate")</button>
|
||||
}
|
||||
@using (Html.BeginFormAntiForgeryPost(Url.Action("Preview"), FormMethod.Post, new { @class = "inline" })) {
|
||||
@Html.Hidden("themeName", theme.ThemeName)
|
||||
<button type="submit" title="@T("Preview")">@T("Preview")</button>
|
||||
}
|
||||
<h5>@T("By") @theme.Author</h5>
|
||||
<p>
|
||||
@T("Version:") @theme.Version<br />
|
||||
@theme.Description<br />
|
||||
@theme.HomePage
|
||||
</p>
|
||||
@using (Html.BeginFormAntiForgeryPost(Url.Action("Uninstall"), FormMethod.Post, new { @class = "inline link" })) {
|
||||
@Html.Hidden("themeName", theme.ThemeName)
|
||||
<button type="submit" class="uninstall" title="@T("Uninstall")">@T("Uninstall")</button>
|
||||
}
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
@@ -1,12 +0,0 @@
|
||||
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<object>" %>
|
||||
<%@ Import Namespace="Orchard.Mvc.Html"%>
|
||||
<h1><%: Html.TitleForPage(T("Install Theme").ToString()) %></h1>
|
||||
<% using (Html.BeginForm("Install", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" })) {%>
|
||||
<%: Html.ValidationSummary() %>
|
||||
<fieldset>
|
||||
<label for="ThemeZipPath"><%: T("File Path to the zip file:")%></label>
|
||||
<input id="ThemeZipPath" name="ThemeZipPath" type="file" class="text" value="<%: T("Browse") %>" size="64" /><br />
|
||||
<input type="submit" class="button" value="<%: T("Install") %>" />
|
||||
<%: Html.AntiForgeryTokenOrchard() %>
|
||||
</fieldset>
|
||||
<% } %>
|
@@ -0,0 +1,10 @@
|
||||
<h1>@Html.TitleForPage(T("Install Theme").ToString())</h1>
|
||||
@using (Html.BeginForm("Install", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" })) {
|
||||
@Html.ValidationSummary()
|
||||
<fieldset>
|
||||
<label for="ThemeZipPath">@T("File Path to the zip file:")</label>
|
||||
<input id="ThemeZipPath" name="ThemeZipPath" type="file" class="text" value="@T("Browse")" size="64" /><br />
|
||||
<input type="submit" class="button" value="@T("Install")" />
|
||||
@Html.AntiForgeryTokenOrchard()
|
||||
</fieldset>
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<PreviewViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Mvc.Html"%>
|
||||
<%@ Import Namespace="Orchard.Themes.ViewModels"%>
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin-top:40px;
|
||||
}
|
||||
#themepreview {
|
||||
background:#2D2F25 url('<%=ResolveUrl("../../Styles/Images/toolBarBackground.gif") %>') repeat-x left top;
|
||||
border-bottom:1px solid #494d4d;
|
||||
font-size:15px;
|
||||
left:0;
|
||||
height:30px;
|
||||
margin:0;
|
||||
position:absolute;
|
||||
overflow:hidden;
|
||||
padding:5px 0;
|
||||
top:0;
|
||||
width:100%;
|
||||
}
|
||||
#themepreview fieldset,
|
||||
#themepreview span, #themepreview input,
|
||||
#themepreview select, #themepreview button {
|
||||
border:none;
|
||||
color:#000;
|
||||
font:1em/1em Frutiger,"Frutiger Linotype",Univers,Calibri,"Gill Sans","Gill Sans MT","Myriad Pro",Myriad,"DejaVu Sans Condensed","Liberation Sans","Nimbus Sans L",Tahoma,Geneva,"Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
margin:0;
|
||||
padding:0;
|
||||
width:auto;
|
||||
}
|
||||
#themepreview span { color: #ccc; padding-right:5px; }
|
||||
#themepreview fieldset { padding:3px 8px; }
|
||||
html.dyn #themepreview button.preview { display:none; }
|
||||
#themepreview fieldset * { float:left; }
|
||||
#themepreview fieldset span { line-height:1.6em; }
|
||||
#themepreview button.cancel { float:right; }
|
||||
/* Button styles */
|
||||
#themepreview button {
|
||||
background:#2a2626 url('<%=ResolveUrl("../../Styles/Images/toolBarActiveButtonBackground.gif") %>') repeat-x left center;
|
||||
border:1px solid;
|
||||
border-top-color:#191d1d;
|
||||
border-right-color:#494d4d;
|
||||
border-bottom-color:#494d4d;
|
||||
border-left-color:#202626;
|
||||
color:#f1f1f1;
|
||||
line-height:1.22em;
|
||||
margin: 0 0 0 10px;
|
||||
padding:0 4px 1px;
|
||||
text-align:center;
|
||||
}
|
||||
#themepreview button:hover {
|
||||
background:#2a2626 url('<%=ResolveUrl("../../Styles/Images/toolBarHoverButtonBackground.gif") %>') repeat-x left center;
|
||||
border-color:#545959;
|
||||
color:#fdcc64;
|
||||
cursor:pointer;
|
||||
}
|
||||
</style>
|
||||
<div id="themepreview">
|
||||
<% using(Html.BeginFormAntiForgeryPost(Url.Action("Preview", new{Controller="Admin", Area="Orchard.Themes"}), FormMethod.Post, new { @class = "inline" })) { %>
|
||||
<fieldset>
|
||||
<span><%: T("You are previewing: ")%></span>
|
||||
<%: Html.Hidden("ReturnUrl", Context.Request.RawUrl)%>
|
||||
<%: Html.DropDownList("ThemeName", Model.Themes, new {onChange = "this.form.submit();"})%>
|
||||
<button type="submit" class="preview" title="<%: T("Preview")%>" name="submit.Preview" value="<%: T("Preview")%>"><%: T("Preview")%></button>
|
||||
<button type="submit" title="<%: T("Apply")%>" name="submit.Apply" value="<%: T("Apply")%>"><%: T("Apply this theme") %></button>
|
||||
<button type="submit" class="cancel" title="<%: T("Cancel")%>" name="submit.Cancel" value="<%: T("Cancel")%>"><%: T("Cancel")%></button>
|
||||
</fieldset>
|
||||
<% } %>
|
||||
</div>
|
||||
|
@@ -0,0 +1,71 @@
|
||||
@{
|
||||
var themes = (IEnumerable<SelectListItem>)Model.Themes;
|
||||
}
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin-top:40px;
|
||||
}
|
||||
#themepreview {
|
||||
background:#2D2F25 url('@Href("../Styles/Images/toolBarBackground.gif")') repeat-x left top;
|
||||
border-bottom:1px solid #494d4d;
|
||||
font-size:15px;
|
||||
left:0;
|
||||
height:30px;
|
||||
margin:0;
|
||||
position:absolute;
|
||||
overflow:hidden;
|
||||
padding:5px 0;
|
||||
top:0;
|
||||
width:100%;
|
||||
}
|
||||
#themepreview fieldset,
|
||||
#themepreview span, #themepreview input,
|
||||
#themepreview select, #themepreview button {
|
||||
border:none;
|
||||
color:#000;
|
||||
font:1em/1em Frutiger,"Frutiger Linotype",Univers,Calibri,"Gill Sans","Gill Sans MT","Myriad Pro",Myriad,"DejaVu Sans Condensed","Liberation Sans","Nimbus Sans L",Tahoma,Geneva,"Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
margin:0;
|
||||
padding:0;
|
||||
width:auto;
|
||||
}
|
||||
#themepreview span { color: #ccc; padding-right:5px; }
|
||||
#themepreview fieldset { padding:3px 8px; }
|
||||
html.dyn #themepreview button.preview { display:none; }
|
||||
#themepreview fieldset * { float:left; }
|
||||
#themepreview fieldset span { line-height:1.6em; }
|
||||
#themepreview button.cancel { float:right; }
|
||||
/* Button styles */
|
||||
#themepreview button {
|
||||
background:#2a2626 url('@Href("../Styles/Images/toolBarBackground.gif")') repeat-x left center;
|
||||
border:1px solid;
|
||||
border-top-color:#191d1d;
|
||||
border-right-color:#494d4d;
|
||||
border-bottom-color:#494d4d;
|
||||
border-left-color:#202626;
|
||||
color:#f1f1f1;
|
||||
line-height:1.22em;
|
||||
margin: 0 0 0 10px;
|
||||
padding:0 4px 1px;
|
||||
text-align:center;
|
||||
}
|
||||
#themepreview button:hover {
|
||||
background:#2a2626 url('@Href("../../Styles/Images/toolBarHoverButtonBackground.gif")') repeat-x left center;
|
||||
border-color:#545959;
|
||||
color:#fdcc64;
|
||||
cursor:pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="themepreview">
|
||||
@using(Html.BeginFormAntiForgeryPost(Url.Action("Preview", new{Controller="Admin", Area="Orchard.Themes"}), FormMethod.Post, new { @class = "inline" })) {
|
||||
<fieldset>
|
||||
<span>@T("You are previewing: ")</span>
|
||||
@Html.DropDownList("ThemeName", themes, new {onChange = "this.form.submit();"})
|
||||
@Html.Hidden("ReturnUrl", Context.Request.RawUrl)
|
||||
<button type="submit" class="preview" title="@T("Preview")" name="submit.Preview" value="@T("Preview")">@T("Preview")</button>
|
||||
<button type="submit" title="@T("Apply")" name="submit.Apply" value="@T("Apply")">@T("Apply this theme")</button>
|
||||
<button type="submit" class="cancel" title="@T("Cancel")" name="submit.Cancel" value="@T("Cancel")">@T("Cancel")</button>
|
||||
</fieldset>
|
||||
}
|
||||
</div>
|
||||
|
@@ -20,11 +20,7 @@ namespace Orchard.Mvc.Html {
|
||||
}
|
||||
|
||||
public static string ThemePath(this HtmlHelper helper, ITheme theme, string path) {
|
||||
Control parent = helper.ViewDataContainer as Control;
|
||||
|
||||
Argument.ThrowIfNull(parent, "helper.ViewDataContainer");
|
||||
|
||||
return parent.ResolveUrl(helper.Resolve<IExtensionManager>().GetThemeLocation(theme) + path);
|
||||
return helper.Resolve<IExtensionManager>().GetThemeLocation(theme) + path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user