forked from ddrilling/AsbCloudServer
#nullable enable
This commit is contained in:
parent
312d653aec
commit
b8e5a8bf4c
@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Repository
|
namespace AsbCloudInfrastructure.Repository
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
public class QueryContainer<TEntity> where TEntity : class, IId
|
public class QueryContainer<TEntity> where TEntity : class, IId
|
||||||
{
|
{
|
||||||
protected readonly IAsbCloudDbContext dbContext;
|
protected readonly IAsbCloudDbContext dbContext;
|
||||||
@ -25,4 +26,5 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
GetQuery = () => makeQuery(dbSet);
|
GetQuery = () => makeQuery(dbSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
@ -11,6 +11,7 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Repository
|
namespace AsbCloudInfrastructure.Repository
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
public class SetpointsRequestRepository : CrudWellRelatedCacheRepositoryBase<SetpointsRequestDto, SetpointsRequest>
|
public class SetpointsRequestRepository : CrudWellRelatedCacheRepositoryBase<SetpointsRequestDto, SetpointsRequest>
|
||||||
{
|
{
|
||||||
private readonly IWellService wellService;
|
private readonly IWellService wellService;
|
||||||
@ -61,4 +62,5 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Repository
|
namespace AsbCloudInfrastructure.Repository
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
public class WitsRecordRepository<TDto, TEntity> : IWitsRecordRepository<TDto>
|
public class WitsRecordRepository<TDto, TEntity> : IWitsRecordRepository<TDto>
|
||||||
where TEntity : AsbCloudDb.Model.WITS.RecordBase, ITelemetryData
|
where TEntity : AsbCloudDb.Model.WITS.RecordBase, ITelemetryData
|
||||||
where TDto : AsbCloudApp.Data.ITelemetryData
|
where TDto : AsbCloudApp.Data.ITelemetryData
|
||||||
@ -53,7 +54,9 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
.Where(d => d.DateTime <= end)
|
.Where(d => d.DateTime <= end)
|
||||||
.AsNoTracking();
|
.AsNoTracking();
|
||||||
var data = await query.ToListAsync(token);
|
var data = await query.ToListAsync(token);
|
||||||
return data.Select(d => Convert(d, timezoneHours));
|
return data
|
||||||
|
.Where(d => d is not null)
|
||||||
|
.Select(d => Convert(d, timezoneHours));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<TDto>> GetLastAsync(int idTelemetry, CancellationToken token)
|
public async Task<IEnumerable<TDto>> GetLastAsync(int idTelemetry, CancellationToken token)
|
||||||
@ -64,7 +67,10 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
.OrderBy(d => d.DateTime)
|
.OrderBy(d => d.DateTime)
|
||||||
.AsNoTracking();
|
.AsNoTracking();
|
||||||
var data = await query.LastOrDefaultAsync(token);
|
var data = await query.LastOrDefaultAsync(token);
|
||||||
return new TDto[] { Convert(data, timezoneHours) };
|
if(data is not null)
|
||||||
|
return new TDto[] { Convert(data, timezoneHours) };
|
||||||
|
|
||||||
|
return new TDto[] { };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SaveDataAsync(int idTelemetry, IEnumerable<TDto> dtos, CancellationToken token)
|
public async Task SaveDataAsync(int idTelemetry, IEnumerable<TDto> dtos, CancellationToken token)
|
||||||
@ -75,6 +81,7 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours;
|
var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours;
|
||||||
var entities = dtos
|
var entities = dtos
|
||||||
.DistinctBy(d => d.DateTime)
|
.DistinctBy(d => d.DateTime)
|
||||||
|
.Where(dto => dto is not null)
|
||||||
.Select(dto => Convert(dto, idTelemetry, timezoneHours));
|
.Select(dto => Convert(dto, idTelemetry, timezoneHours));
|
||||||
|
|
||||||
var dateMin = entities.Min(e => e.DateTime);
|
var dateMin = entities.Min(e => e.DateTime);
|
||||||
@ -128,9 +135,6 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
|
|
||||||
private static TEntity Convert(TDto dto, int idTelemetry, double timezoneHours)
|
private static TEntity Convert(TDto dto, int idTelemetry, double timezoneHours)
|
||||||
{
|
{
|
||||||
if (dto is null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var entity = dto.Adapt<TEntity>();
|
var entity = dto.Adapt<TEntity>();
|
||||||
entity.Recid = GetRecId(dto);
|
entity.Recid = GetRecId(dto);
|
||||||
entity.IdTelemetry = idTelemetry;
|
entity.IdTelemetry = idTelemetry;
|
||||||
@ -140,13 +144,11 @@ namespace AsbCloudInfrastructure.Repository
|
|||||||
|
|
||||||
private static TDto Convert(TEntity entity, double timezoneHours)
|
private static TDto Convert(TEntity entity, double timezoneHours)
|
||||||
{
|
{
|
||||||
if (entity is null)
|
|
||||||
return default;
|
|
||||||
|
|
||||||
var data = entity.Adapt<TDto>();
|
var data = entity.Adapt<TDto>();
|
||||||
data.DateTime = entity.DateTime.ToRemoteDateTime(timezoneHours);
|
data.DateTime = entity.DateTime.ToRemoteDateTime(timezoneHours);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DailyReport
|
namespace AsbCloudInfrastructure.Services.DailyReport
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
abstract class BlockAbstract
|
abstract class BlockAbstract
|
||||||
{
|
{
|
||||||
public abstract CellAddress AddressBlockBegin { get; }
|
public abstract CellAddress AddressBlockBegin { get; }
|
||||||
public abstract CellAddress AddressBlockEnd { get; }
|
public abstract CellAddress AddressBlockEnd { get; }
|
||||||
public abstract void Draw(IXLWorksheet sheet);
|
public abstract void Draw(IXLWorksheet sheet);
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ using ClosedXML.Excel;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
class BhaBlock : BlockAbstract
|
class BhaBlock : BlockAbstract
|
||||||
{
|
{
|
||||||
private readonly BhaDto blockDto;
|
private readonly BhaDto blockDto;
|
||||||
@ -110,7 +111,8 @@ namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
|||||||
.SetFormulaA1($"{FormulaBhaBlock(AddressDurationDataStart[4], AddressDurationDataFinish[4])}").Style.SetAllBorders();
|
.SetFormulaA1($"{FormulaBhaBlock(AddressDurationDataStart[4], AddressDurationDataFinish[4])}").Style.SetAllBorders();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,12 +3,12 @@ using ClosedXML.Excel;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
internal class DimensionlessBlock : BlockAbstract
|
internal class DimensionlessBlock : BlockAbstract
|
||||||
{
|
{
|
||||||
private readonly NoDrillingDto blockDto;
|
private readonly NoDrillingDto blockDto;
|
||||||
|
|
||||||
public SaubBlock SaubBlock { get; set; }
|
public SaubBlock SaubBlock { get; set; } = null!;
|
||||||
|
|
||||||
public CellAddress AddressDimensionTitle { get; }
|
public CellAddress AddressDimensionTitle { get; }
|
||||||
public CellAddress AddressPreparationTitle { get; }
|
public CellAddress AddressPreparationTitle { get; }
|
||||||
@ -19,7 +19,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
|||||||
public CellAddress[] AddressPreparationValue { get; }
|
public CellAddress[] AddressPreparationValue { get; }
|
||||||
public CellAddress[] AddressExtensionHead { get; }
|
public CellAddress[] AddressExtensionHead { get; }
|
||||||
public CellAddress[] AddressExtensionValue { get; }
|
public CellAddress[] AddressExtensionValue { get; }
|
||||||
public CellAddress AddressBlockFormula { get; }
|
public CellAddress AddressBlockFormula { get; } = null!;
|
||||||
public override CellAddress AddressBlockBegin { get; }
|
public override CellAddress AddressBlockBegin { get; }
|
||||||
public override CellAddress AddressBlockEnd { get; }
|
public override CellAddress AddressBlockEnd { get; }
|
||||||
public DimensionlessBlock(CellAddress addressBlockBegin, NoDrillingDto blockDto)
|
public DimensionlessBlock(CellAddress addressBlockBegin, NoDrillingDto blockDto)
|
||||||
@ -114,6 +114,6 @@ namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
|||||||
._SetValue("Наращивание");
|
._SetValue("Наращивание");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ using ClosedXML.Excel;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
class HeadBlock : BlockAbstract
|
class HeadBlock : BlockAbstract
|
||||||
{
|
{
|
||||||
private readonly HeadDto blockDto;
|
private readonly HeadDto blockDto;
|
||||||
@ -175,6 +175,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
|||||||
._SetValue($"{blockDto.CountLaunchesMSE}");
|
._SetValue($"{blockDto.CountLaunchesMSE}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ using ClosedXML.Excel;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
internal class SaubBlock : BlockAbstract
|
internal class SaubBlock : BlockAbstract
|
||||||
{
|
{
|
||||||
private readonly SaubDto blockDto;
|
private readonly SaubDto blockDto;
|
||||||
@ -224,5 +225,6 @@ namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
|||||||
._SetValue($"Примечание: {blockDto.DeclinesReasonsROP}");
|
._SetValue($"Примечание: {blockDto.DeclinesReasonsROP}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ using ClosedXML.Excel;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
internal class SignBlock : BlockAbstract
|
internal class SignBlock : BlockAbstract
|
||||||
{
|
{
|
||||||
private readonly SignDto blockDto;
|
private readonly SignDto blockDto;
|
||||||
@ -10,7 +11,6 @@ namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
|||||||
public CellAddress AddressDrillMaster { get; }
|
public CellAddress AddressDrillMaster { get; }
|
||||||
public CellAddress AddressSupervisorHead { get; }
|
public CellAddress AddressSupervisorHead { get; }
|
||||||
public CellAddress AddressSupervisor { get; }
|
public CellAddress AddressSupervisor { get; }
|
||||||
public CellAddress[] AddressPeriodTableDataArray { get; }
|
|
||||||
public override CellAddress AddressBlockBegin { get; }
|
public override CellAddress AddressBlockBegin { get; }
|
||||||
public override CellAddress AddressBlockEnd { get; }
|
public override CellAddress AddressBlockEnd { get; }
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ namespace AsbCloudInfrastructure.Services.DailyReport.DailyReportBlocks
|
|||||||
.SetValue($"{blockDto.Supervisor}");
|
.SetValue($"{blockDto.Supervisor}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,9 +6,10 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
namespace AsbCloudInfrastructure.Services.DailyReport
|
namespace AsbCloudInfrastructure.Services.DailyReport
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
public class DailyReportMakerExcel
|
public class DailyReportMakerExcel
|
||||||
{
|
{
|
||||||
private IEnumerable<WellOperationCategoryDto> OperationCategories;
|
private IEnumerable<WellOperationCategoryDto> OperationCategories = null!;
|
||||||
|
|
||||||
public Stream MakeReportFromBlocks(DailyReportDto dto, IEnumerable<WellOperationCategoryDto> operationCategories)
|
public Stream MakeReportFromBlocks(DailyReportDto dto, IEnumerable<WellOperationCategoryDto> operationCategories)
|
||||||
{
|
{
|
||||||
@ -55,5 +56,6 @@ namespace AsbCloudInfrastructure.Services.DailyReport
|
|||||||
sheet.Rows().AdjustToContents();
|
sheet.Rows().AdjustToContents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ using System;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DailyReport
|
namespace AsbCloudInfrastructure.Services.DailyReport
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
internal static class XLExtentions
|
internal static class XLExtentions
|
||||||
{
|
{
|
||||||
public static IXLRange _SetValue(this IXLRange range, object value)
|
public static IXLRange _SetValue(this IXLRange range, object value)
|
||||||
@ -156,4 +157,5 @@ namespace AsbCloudInfrastructure.Services.DailyReport
|
|||||||
=> sheet.Range(begin.RowNumber, begin.ColumnNumber, end.RowNumber, end.ColumnNumber);
|
=> sheet.Range(begin.RowNumber, begin.ColumnNumber, end.RowNumber, end.ColumnNumber);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations
|
namespace AsbCloudInfrastructure.Services.DetectOperations
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
public class DetectableTelemetry
|
public class DetectableTelemetry
|
||||||
{
|
{
|
||||||
public DateTimeOffset DateTime { get; set; }
|
public DateTimeOffset DateTime { get; set; }
|
||||||
@ -13,4 +14,5 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
public float BitDepth { get; set; }
|
public float BitDepth { get; set; }
|
||||||
public float RotorSpeed { get; set; }
|
public float RotorSpeed { get; set; }
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations
|
namespace AsbCloudInfrastructure.Services.DetectOperations
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
internal class DetectedOperationExportService
|
internal class DetectedOperationExportService
|
||||||
{
|
{
|
||||||
private readonly IAsbCloudDbContext db;
|
private readonly IAsbCloudDbContext db;
|
||||||
@ -41,7 +42,8 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var wells = idsWells.Select(i => wellService.GetOrDefault(i))
|
var wells = idsWells.Select(i => wellService.GetOrDefault(i))
|
||||||
.Where(w => w is not null && w.IdTelemetry is not null);
|
.Where(w => w is not null && w.IdTelemetry is not null)
|
||||||
|
.Select(w => w!);
|
||||||
|
|
||||||
if (!wells.Any())
|
if (!wells.Any())
|
||||||
return;
|
return;
|
||||||
@ -114,4 +116,5 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
sheet.Cell(rowNumber, 6).Value = operation.Value;
|
sheet.Cell(rowNumber, 6).Value = operation.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable enable
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
class OperationDetectorResult
|
class OperationDetectorResult
|
||||||
{
|
{
|
||||||
public int TelemetryBegin { get; set; }
|
public int TelemetryBegin { get; set; }
|
||||||
public int TelemetryEnd { get; set; }
|
public int TelemetryEnd { get; set; }
|
||||||
public DetectedOperation Operation { get; set; }
|
public DetectedOperation Operation { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
#nullable enable
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DetectOperations
|
namespace AsbCloudInfrastructure.Services.DetectOperations
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
public class InterpolationLine
|
public class InterpolationLine
|
||||||
{
|
{
|
||||||
private readonly double xSum;
|
private readonly double xSum;
|
||||||
@ -52,4 +53,5 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
|||||||
public bool IsAverageYGreaterThan(double bound) =>
|
public bool IsAverageYGreaterThan(double bound) =>
|
||||||
(ySum / count) >= bound;
|
(ySum / count) >= bound;
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DrillingProgram
|
namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
internal class DrillingProgramMaker
|
internal class DrillingProgramMaker
|
||||||
{
|
{
|
||||||
private const int maxAllowedColumns = 256;
|
private const int maxAllowedColumns = 256;
|
||||||
@ -15,7 +16,9 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
|||||||
var resultExcelFile = new XLWorkbook(XLEventTracking.Disabled);
|
var resultExcelFile = new XLWorkbook(XLEventTracking.Disabled);
|
||||||
|
|
||||||
var titleSheet = resultExcelFile.AddWorksheet("Титульный лист");
|
var titleSheet = resultExcelFile.AddWorksheet("Титульный лист");
|
||||||
var marks = parts.SelectMany(p => p.File.FileMarks);
|
var marks = parts
|
||||||
|
.Where(p => p.File is not null)
|
||||||
|
.SelectMany(p => p.File!.FileMarks);
|
||||||
var titleSheetMaker = new TitleListSheet(marks, well);
|
var titleSheetMaker = new TitleListSheet(marks, well);
|
||||||
titleSheetMaker.Draw(titleSheet);
|
titleSheetMaker.Draw(titleSheet);
|
||||||
|
|
||||||
@ -128,4 +131,5 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
|||||||
return rngData;
|
return rngData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,16 @@
|
|||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.DrillingProgram
|
namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||||
{
|
{
|
||||||
|
#nullable enable
|
||||||
class ImageInfo
|
class ImageInfo
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public byte[] Data { get; set; }
|
public byte[] Data { get; set; } = null!;
|
||||||
public int Height { get; set; }
|
public int Height { get; set; }
|
||||||
public int Width { get; set; }
|
public int Width { get; set; }
|
||||||
public IXLAddress TopLeftCellAddress { get; set; }
|
public IXLAddress TopLeftCellAddress { get; set; } = null!;
|
||||||
public int Left { get; set; }
|
public int Left { get; set; }
|
||||||
public int Top { get; set; }
|
public int Top { get; set; }
|
||||||
}
|
}
|
||||||
|
#nullable disable
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user