| @@ -6,6 +6,7 @@ public sealed class MessageDto : BaseDto | |||
| { | |||
| public string Text { get; set; } | |||
| public bool IsValid { get; set; } = true; | |||
| public bool AllowEditing { get; set; } = false; | |||
| public Guid Code { get; set; } = Guid.NewGuid(); | |||
| public List<FileModel> FileNames { get; set; } = new(); | |||
| public DateTime? ExpiryDate { get; set; } | |||
| @@ -112,8 +112,12 @@ public sealed class MessageService : IMessageService | |||
| public async Task Update(MessageDto messageDto) | |||
| { | |||
| var message = await GetById(messageDto.Id); | |||
| message.Text = messageDto.Text; | |||
| message.FileNames = messageDto.FileNames; | |||
| var a = _dbContext.Messages | |||
| .Update(_mapper.Map<Message>(messageDto)); | |||
| .Update(_mapper.Map<Message>(message)); | |||
| await _dbContext.SaveChangesAsync(); | |||
| } | |||
| @@ -6,6 +6,7 @@ public sealed class Message : BaseEntity | |||
| public string Code { get; set; } | |||
| public List<FileModel> FileNames { get; } = new(); | |||
| public bool IsValid { get; set; } | |||
| public bool AllowEditing { get; set; } | |||
| public DateTime? ExpiryDate { get; set; } | |||
| public bool Anonymous { get; set; } = false; | |||
| } | |||
| @@ -0,0 +1,348 @@ | |||
| // <auto-generated /> | |||
| using System; | |||
| using Microsoft.EntityFrameworkCore; | |||
| using Microsoft.EntityFrameworkCore.Infrastructure; | |||
| using Microsoft.EntityFrameworkCore.Metadata; | |||
| using Microsoft.EntityFrameworkCore.Migrations; | |||
| using Microsoft.EntityFrameworkCore.Storage.ValueConversion; | |||
| using SecureSharing.Data.DbContexts; | |||
| #nullable disable | |||
| namespace SecureSharing.Data.Migrations | |||
| { | |||
| [DbContext(typeof(AppDbContext))] | |||
| [Migration("20221024122405_Adding message editing")] | |||
| partial class Addingmessageediting | |||
| { | |||
| protected override void BuildTargetModel(ModelBuilder modelBuilder) | |||
| { | |||
| #pragma warning disable 612, 618 | |||
| modelBuilder | |||
| .HasAnnotation("ProductVersion", "6.0.9") | |||
| .HasAnnotation("Relational:MaxIdentifierLength", 128); | |||
| SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => | |||
| { | |||
| b.Property<string>("Id") | |||
| .HasColumnType("nvarchar(450)"); | |||
| b.Property<string>("ConcurrencyStamp") | |||
| .IsConcurrencyToken() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("Name") | |||
| .HasMaxLength(256) | |||
| .HasColumnType("nvarchar(256)"); | |||
| b.Property<string>("NormalizedName") | |||
| .HasMaxLength(256) | |||
| .HasColumnType("nvarchar(256)"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("NormalizedName") | |||
| .IsUnique() | |||
| .HasDatabaseName("RoleNameIndex") | |||
| .HasFilter("[NormalizedName] IS NOT NULL"); | |||
| b.ToTable("AspNetRoles", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => | |||
| { | |||
| b.Property<int>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("int"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1); | |||
| b.Property<string>("ClaimType") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("ClaimValue") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("RoleId") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(450)"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("RoleId"); | |||
| b.ToTable("AspNetRoleClaims", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => | |||
| { | |||
| b.Property<string>("Id") | |||
| .HasColumnType("nvarchar(450)"); | |||
| b.Property<int>("AccessFailedCount") | |||
| .HasColumnType("int"); | |||
| b.Property<string>("ConcurrencyStamp") | |||
| .IsConcurrencyToken() | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("Email") | |||
| .HasMaxLength(256) | |||
| .HasColumnType("nvarchar(256)"); | |||
| b.Property<bool>("EmailConfirmed") | |||
| .HasColumnType("bit"); | |||
| b.Property<bool>("LockoutEnabled") | |||
| .HasColumnType("bit"); | |||
| b.Property<DateTimeOffset?>("LockoutEnd") | |||
| .HasColumnType("datetimeoffset"); | |||
| b.Property<string>("NormalizedEmail") | |||
| .HasMaxLength(256) | |||
| .HasColumnType("nvarchar(256)"); | |||
| b.Property<string>("NormalizedUserName") | |||
| .HasMaxLength(256) | |||
| .HasColumnType("nvarchar(256)"); | |||
| b.Property<string>("PasswordHash") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("PhoneNumber") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<bool>("PhoneNumberConfirmed") | |||
| .HasColumnType("bit"); | |||
| b.Property<string>("SecurityStamp") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<bool>("TwoFactorEnabled") | |||
| .HasColumnType("bit"); | |||
| b.Property<string>("UserName") | |||
| .HasMaxLength(256) | |||
| .HasColumnType("nvarchar(256)"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("NormalizedEmail") | |||
| .HasDatabaseName("EmailIndex"); | |||
| b.HasIndex("NormalizedUserName") | |||
| .IsUnique() | |||
| .HasDatabaseName("UserNameIndex") | |||
| .HasFilter("[NormalizedUserName] IS NOT NULL"); | |||
| b.ToTable("AspNetUsers", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => | |||
| { | |||
| b.Property<int>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("int"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1); | |||
| b.Property<string>("ClaimType") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("ClaimValue") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("UserId") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(450)"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("UserId"); | |||
| b.ToTable("AspNetUserClaims", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => | |||
| { | |||
| b.Property<string>("LoginProvider") | |||
| .HasMaxLength(128) | |||
| .HasColumnType("nvarchar(128)"); | |||
| b.Property<string>("ProviderKey") | |||
| .HasMaxLength(128) | |||
| .HasColumnType("nvarchar(128)"); | |||
| b.Property<string>("ProviderDisplayName") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<string>("UserId") | |||
| .IsRequired() | |||
| .HasColumnType("nvarchar(450)"); | |||
| b.HasKey("LoginProvider", "ProviderKey"); | |||
| b.HasIndex("UserId"); | |||
| b.ToTable("AspNetUserLogins", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => | |||
| { | |||
| b.Property<string>("UserId") | |||
| .HasColumnType("nvarchar(450)"); | |||
| b.Property<string>("RoleId") | |||
| .HasColumnType("nvarchar(450)"); | |||
| b.HasKey("UserId", "RoleId"); | |||
| b.HasIndex("RoleId"); | |||
| b.ToTable("AspNetUserRoles", (string)null); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => | |||
| { | |||
| b.Property<string>("UserId") | |||
| .HasColumnType("nvarchar(450)"); | |||
| b.Property<string>("LoginProvider") | |||
| .HasMaxLength(128) | |||
| .HasColumnType("nvarchar(128)"); | |||
| b.Property<string>("Name") | |||
| .HasMaxLength(128) | |||
| .HasColumnType("nvarchar(128)"); | |||
| b.Property<string>("Value") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.HasKey("UserId", "LoginProvider", "Name"); | |||
| b.ToTable("AspNetUserTokens", (string)null); | |||
| }); | |||
| modelBuilder.Entity("SecureSharing.Data.Data.FileModel", b => | |||
| { | |||
| b.Property<int>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("int"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1); | |||
| b.Property<int>("MessageId") | |||
| .HasColumnType("int"); | |||
| b.Property<string>("Name") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.HasKey("Id"); | |||
| b.HasIndex("MessageId"); | |||
| b.ToTable("FileModel"); | |||
| }); | |||
| modelBuilder.Entity("SecureSharing.Data.Data.Message", b => | |||
| { | |||
| b.Property<int>("Id") | |||
| .ValueGeneratedOnAdd() | |||
| .HasColumnType("int"); | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1); | |||
| b.Property<bool>("AllowEditing") | |||
| .HasColumnType("bit"); | |||
| b.Property<bool>("Anonymous") | |||
| .HasColumnType("bit"); | |||
| b.Property<string>("Code") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.Property<DateTime?>("ExpiryDate") | |||
| .HasColumnType("datetime2"); | |||
| b.Property<bool>("IsValid") | |||
| .HasColumnType("bit"); | |||
| b.Property<string>("Text") | |||
| .HasColumnType("nvarchar(max)"); | |||
| b.HasKey("Id"); | |||
| b.ToTable("Messages"); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b => | |||
| { | |||
| b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) | |||
| .WithMany() | |||
| .HasForeignKey("RoleId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b => | |||
| { | |||
| b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) | |||
| .WithMany() | |||
| .HasForeignKey("UserId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b => | |||
| { | |||
| b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) | |||
| .WithMany() | |||
| .HasForeignKey("UserId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b => | |||
| { | |||
| b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) | |||
| .WithMany() | |||
| .HasForeignKey("RoleId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) | |||
| .WithMany() | |||
| .HasForeignKey("UserId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| }); | |||
| modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b => | |||
| { | |||
| b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) | |||
| .WithMany() | |||
| .HasForeignKey("UserId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| }); | |||
| modelBuilder.Entity("SecureSharing.Data.Data.FileModel", b => | |||
| { | |||
| b.HasOne("SecureSharing.Data.Data.Message", null) | |||
| .WithMany("FileNames") | |||
| .HasForeignKey("MessageId") | |||
| .OnDelete(DeleteBehavior.Cascade) | |||
| .IsRequired(); | |||
| }); | |||
| modelBuilder.Entity("SecureSharing.Data.Data.Message", b => | |||
| { | |||
| b.Navigation("FileNames"); | |||
| }); | |||
| #pragma warning restore 612, 618 | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,26 @@ | |||
| using Microsoft.EntityFrameworkCore.Migrations; | |||
| #nullable disable | |||
| namespace SecureSharing.Data.Migrations | |||
| { | |||
| public partial class Addingmessageediting : Migration | |||
| { | |||
| protected override void Up(MigrationBuilder migrationBuilder) | |||
| { | |||
| migrationBuilder.AddColumn<bool>( | |||
| name: "AllowEditing", | |||
| table: "Messages", | |||
| type: "bit", | |||
| nullable: false, | |||
| defaultValue: false); | |||
| } | |||
| protected override void Down(MigrationBuilder migrationBuilder) | |||
| { | |||
| migrationBuilder.DropColumn( | |||
| name: "AllowEditing", | |||
| table: "Messages"); | |||
| } | |||
| } | |||
| } | |||
| @@ -253,6 +253,9 @@ namespace SecureSharing.Data.Migrations | |||
| SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1); | |||
| b.Property<bool>("AllowEditing") | |||
| .HasColumnType("bit"); | |||
| b.Property<bool>("Anonymous") | |||
| .HasColumnType("bit"); | |||
| @@ -1,4 +1,5 @@ | |||
| using Microsoft.AspNetCore.Authorization; | |||
| using AutoMapper; | |||
| using Microsoft.AspNetCore.Authorization; | |||
| using Microsoft.AspNetCore.Mvc; | |||
| using Microsoft.AspNetCore.StaticFiles; | |||
| using SecureSharing.Business.Dtos; | |||
| @@ -18,14 +19,16 @@ public sealed class HomeController : Controller | |||
| private readonly IMessageService _messageService; | |||
| private readonly IModelFactory _modelFactory; | |||
| private readonly IWebHostEnvironment _webHostEnvironment; | |||
| private readonly IMapper _mapper; | |||
| public HomeController(ILogger<HomeController> logger, IMessageService messageService, IModelFactory modelFactory, | |||
| IWebHostEnvironment webHostEnvironment) | |||
| IWebHostEnvironment webHostEnvironment, IMapper mapper) | |||
| { | |||
| _logger = logger; | |||
| _messageService = messageService; | |||
| _modelFactory = modelFactory; | |||
| _webHostEnvironment = webHostEnvironment; | |||
| _mapper = mapper; | |||
| } | |||
| public IActionResult Index() | |||
| @@ -33,6 +36,7 @@ public sealed class HomeController : Controller | |||
| return View(); | |||
| } | |||
| [AllowAnonymous] | |||
| public async Task<string> UploadTemporaryFile() | |||
| { | |||
| var code = Guid.NewGuid().ToString(); | |||
| @@ -56,15 +60,19 @@ public sealed class HomeController : Controller | |||
| [HttpPost] | |||
| public async Task<IActionResult> CreateMessage(MessageModel model) | |||
| { | |||
| if (string.IsNullOrWhiteSpace(model.Text) && model.Files.Count == 0 && | |||
| model.FilesAsText == "978682e8-3ce7-4258-b731-d027b5b213aa") | |||
| if (!model.AllowEditing | |||
| && string.IsNullOrWhiteSpace(model.Text) | |||
| && model.Files.Count == 0 | |||
| && model.FilesAsText == "978682e8-3ce7-4258-b731-d027b5b213aa") | |||
| { | |||
| return Redirect("/"); | |||
| } | |||
| model.FilesAsText = model.FilesAsText != "978682e8-3ce7-4258-b731-d027b5b213aa" | |||
| ? model.FilesAsText.Split("978682e8-3ce7-4258-b731-d027b5b213aa")[1] | |||
| : ""; | |||
| var message = new MessageDto { Text = model.Text, Anonymous = model.Anonymous }; | |||
| var message = new MessageDto { Text = model.Text, Anonymous = model.AllowEditing || model.Anonymous, AllowEditing = model.AllowEditing}; | |||
| await UploadFiles(model, message); | |||
| @@ -73,6 +81,32 @@ public sealed class HomeController : Controller | |||
| return RedirectToAction("Link", "Home", new { code, share = true }); | |||
| } | |||
| [HttpPost] | |||
| [AllowAnonymous] | |||
| public async Task<IActionResult> UpdateMessage(MessageModel model) | |||
| { | |||
| if (string.IsNullOrWhiteSpace(model.Text) && model.Files.Count == 0 && | |||
| model.FilesAsText == "978682e8-3ce7-4258-b731-d027b5b213aa") | |||
| { | |||
| return Redirect("/"); | |||
| } | |||
| model.FilesAsText = model.FilesAsText != "978682e8-3ce7-4258-b731-d027b5b213aa" | |||
| ? model.FilesAsText.Split("978682e8-3ce7-4258-b731-d027b5b213aa")[1] | |||
| : ""; | |||
| var message = new MessageDto { Text = model.Text, Anonymous = model.Anonymous, Id = model.Id, Code = model.Code}; | |||
| // var messageDto = _mapper.Map<MessageDto>(model); | |||
| await UploadFiles(model, message); | |||
| await _messageService.Update(message); | |||
| return RedirectToAction("LinkAnonymous", "Home", new { model.Code, share = true, edit = true }); | |||
| } | |||
| [AllowAnonymous] | |||
| private async Task UploadFiles(MessageModel model, MessageDto message) | |||
| { | |||
| var basePath = Path.Combine(_webHostEnvironment.WebRootPath.Split('/')[0], DefaultPath, | |||
| @@ -138,20 +172,28 @@ public sealed class HomeController : Controller | |||
| } | |||
| [HttpGet] | |||
| public async Task<IActionResult> Link(Guid code, bool? share) | |||
| public async Task<IActionResult> Link(Guid code, bool? share, bool? edit) | |||
| { | |||
| var model = await _modelFactory.PrepareLinkVM(code, share); | |||
| var model = await _modelFactory.PrepareLinkVM(code, share, edit); | |||
| return View(model); | |||
| } | |||
| [AllowAnonymous] | |||
| [HttpGet] | |||
| public async Task<IActionResult> LinkAnonymous(Guid code, bool? share) | |||
| public async Task<IActionResult> LinkAnonymous(Guid code, bool? edit) | |||
| { | |||
| var model = await _modelFactory.PrepareLinkAnonymous(code, share); | |||
| var model = await _modelFactory.PrepareLinkAnonymous(code, edit); | |||
| return View(model); | |||
| } | |||
| [AllowAnonymous] | |||
| [HttpGet] | |||
| public async Task<IActionResult> LinkEdit(Guid code, bool? edit) | |||
| { | |||
| var model = await _modelFactory.PrepareLinkEdit(code, edit); | |||
| return View(model.MessageModel); | |||
| } | |||
| public IActionResult Privacy() | |||
| { | |||
| return View(); | |||
| @@ -5,6 +5,7 @@ namespace SecureSharing.Infrastructure; | |||
| public interface IModelFactory | |||
| { | |||
| //public MessageModel PrepareMessageVM(MessageDto message); | |||
| public Task<LinkModel> PrepareLinkVM(Guid code, bool? share); | |||
| public Task<LinkModel> PrepareLinkAnonymous(Guid code, bool? share); | |||
| public Task<LinkModel> PrepareLinkVM(Guid code, bool? share, bool? edit); | |||
| public Task<LinkModel> PrepareLinkAnonymous(Guid code, bool? edit); | |||
| public Task<LinkModel> PrepareLinkEdit(Guid code, bool? edit); | |||
| } | |||
| @@ -14,7 +14,7 @@ public sealed class ModelFactory : IModelFactory | |||
| _messageService = messageService; | |||
| } | |||
| public async Task<LinkModel> PrepareLinkVM(Guid code, bool? share) | |||
| public async Task<LinkModel> PrepareLinkVM(Guid code, bool? share, bool? edit) | |||
| { | |||
| //share is true when the link is created | |||
| @@ -27,10 +27,12 @@ public sealed class ModelFactory : IModelFactory | |||
| { | |||
| MessageModel = new MessageModel | |||
| { | |||
| Id = message.Id, | |||
| Code = code, | |||
| Text = message.Text, | |||
| FileNames = message.FileNames.Select(x => x.Name).ToList(), | |||
| Anonymous = message.Anonymous | |||
| Anonymous = message.Anonymous, | |||
| AllowEditing = message.AllowEditing | |||
| }, | |||
| Share = share, | |||
| IsValid = message.IsValid | |||
| @@ -50,7 +52,7 @@ public sealed class ModelFactory : IModelFactory | |||
| else | |||
| { | |||
| //ONE_TIME sharing: make the message invalid now so that it can't be accessed next time | |||
| if (share is null or false) await _messageService.InvalidateMessage(message.Id); | |||
| if (share is null or false && edit is null or false) await _messageService.InvalidateMessage(message.Id); | |||
| } | |||
| } | |||
| else | |||
| @@ -67,13 +69,20 @@ public sealed class ModelFactory : IModelFactory | |||
| return model; | |||
| } | |||
| public async Task<LinkModel> PrepareLinkAnonymous(Guid code, bool? share) | |||
| public async Task<LinkModel> PrepareLinkAnonymous(Guid code, bool? edit) | |||
| { | |||
| var model = await PrepareLinkVM(code, share); | |||
| var model = await PrepareLinkVM(code, false, edit); | |||
| return model.MessageModel.Anonymous ? model : new LinkModel { IsValid = false }; | |||
| } | |||
| public async Task<LinkModel> PrepareLinkEdit(Guid code, bool? edit) | |||
| { | |||
| var model = await PrepareLinkVM(code, false, edit); | |||
| return model.MessageModel.Anonymous && model.MessageModel.AllowEditing ? model : new LinkModel { IsValid = false }; | |||
| } | |||
| //public MessageModel PrepareMessageVM(MessageDto message) | |||
| //{ | |||
| // throw new System.NotImplementedException(); | |||
| @@ -14,5 +14,7 @@ public sealed class MessageModel | |||
| public string FilesAsText { get; set; } = default!; | |||
| public bool Anonymous { get; set; } = false; | |||
| public bool AllowEditing { get; set; } = false; | |||
| // public Dictionary<int, string> AvailablePeriods { get; set; } | |||
| } | |||
| @@ -41,7 +41,7 @@ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="mb-3"> | |||
| <div class="label-text"> | |||
| Your files | |||
| @@ -50,16 +50,27 @@ | |||
| </div> | |||
| </div> | |||
| <div class="mb-3"> | |||
| <label class="label-text">Should link be visible outside diligent network?</label> | |||
| <div class="button-box row"> | |||
| <div class="single-button-input col-4"> | |||
| <input id="Anonymous" class="radio-input" type="checkbox" asp-for="Anonymous" value="true"> | |||
| <label for="Anonymous" class="label-available">Anonymous share</label> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @* TODO: https://www.w3schools.com/howto/howto_css_switch.asp *@ | |||
| <div class="mb-3"> | |||
| <label class="label-text">Should link be visible outside diligent network?</label> | |||
| <div class="button-box row"> | |||
| <div class="single-button-input col-4"> | |||
| <input id="Anonymous" class="radio-input" type="checkbox" asp-for="Anonymous" value="true"> | |||
| <label for="Anonymous" class="label-available">Anonymous share</label> | |||
| </div> | |||
| <label class="label-text">Should content be edited after posting?</label> | |||
| <div class="button-box row"> | |||
| <div class="single-button-input col-4"> | |||
| <input id="AllowEditing" class="radio-input" type="checkbox" asp-for="AllowEditing" value="true"> | |||
| <label for="AllowEditing" class="label-available">Allow editing</label> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <button class=" btn btn-light share-button" type="submit">Share</button> | |||
| </form> | |||
| @@ -20,7 +20,19 @@ else | |||
| </div> | |||
| <div id="div-link" class="label-text link-show"> | |||
| @{ | |||
| var link = Url.Action(Model.MessageModel.Anonymous ? "LinkAnonymous" : "Link", "Home", new { code = Model.MessageModel.Code }, "https"); | |||
| string link = ""; | |||
| if (Model.MessageModel.AllowEditing) | |||
| { | |||
| link = Url.Action("LinkEdit", "Home", new { code = Model.MessageModel.Code, edit = true }, "https"); | |||
| } | |||
| else if (Model.MessageModel.Anonymous) | |||
| { | |||
| link = Url.Action("LinkAnonymous", "Home", new { code = Model.MessageModel.Code }, "https"); | |||
| } | |||
| else | |||
| { | |||
| link = Url.Action("Link", "Home", new { code = Model.MessageModel.Code }, "https"); | |||
| } | |||
| } | |||
| <a id="a-link" href="@link">@link</a> | |||
| </div> | |||
| @@ -12,8 +12,7 @@ else | |||
| { | |||
| <h1>Document is ready!</h1> | |||
| <a href="/" class="share-more-files-button">Share more files</a> | |||
| <div> | |||
| @if (Model.TimeLeft != null) | |||
| { | |||
| @@ -33,9 +32,12 @@ else | |||
| } | |||
| else | |||
| { | |||
| <div class="label-text-lower"> | |||
| This message will expire when you leave this page | |||
| </div> | |||
| if (!Model.MessageModel.AllowEditing) | |||
| { | |||
| <div class="label-text-lower"> | |||
| This message will expire when you leave this page | |||
| </div> | |||
| } | |||
| } | |||
| </div> | |||
| @@ -0,0 +1,100 @@ | |||
| @{ | |||
| Layout = "~/Views/Shared/_Layout.cshtml"; | |||
| } | |||
| @model MessageModel | |||
| <h1>@Model.Id</h1> | |||
| <h1>@Model.Code</h1> | |||
| <h1>Share files</h1> | |||
| <form method="post" enctype="multipart/form-data" asp-controller="Home" asp-action="UpdateMessage" class="share-files-form"> | |||
| <input type="hidden" asp-for="Id" value="@Model.Id"> | |||
| <input type="hidden" asp-for="Code" value="@Model.Code"> | |||
| <div class="mb-3"> | |||
| <label class="label-text">Message (optional)</label> | |||
| <textarea asp-for="Text" class="input-message"></textarea> | |||
| </div> | |||
| <div class="mb-3"> | |||
| <label class="label-text">Upload files</label> | |||
| <div id="dropContainer" class="drop-here"> | |||
| <img class="image-file-upload" src="~/img/file-upload-image.png" alt=""/> | |||
| <div class="default-text text-files-upload"> | |||
| <label for="fileInput" class="btn browse-button"> | |||
| <span style="color:#0D1C52">Drag and drop files here or</span> browse | |||
| </label> | |||
| <input asp-for="Files" id="fileInput" type="file" multiple style="display: none"/> | |||
| <input asp-for="FilesAsText" id="fileInputAsText" type="text" style="display:none" value="978682e8-3ce7-4258-b731-d027b5b213aa"/> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="mb-3"> | |||
| <div class="label-text"> | |||
| Your files | |||
| </div> | |||
| <div id="filesUploaded"> | |||
| </div> | |||
| </div> | |||
| <button class="btn btn-light share-button" type="submit">Save</button> | |||
| </form> | |||
| <script src="~/plugins/jquery/jquery.js" type="text/javascript"></script> | |||
| <script type="text/javascript"> | |||
| var filesUploaded = document.getElementById("filesUploaded"); | |||
| $('#fileInput').change(function() { | |||
| var files = $('#fileInput')[0].files | |||
| for (var i = 0; i < files.length; i++){ | |||
| filesUploaded.innerHTML +='<p>' + files[i].name + '</p>'; | |||
| } | |||
| }); | |||
| var selectedFiles; | |||
| $(document).ready(() => { | |||
| var box; | |||
| box = document.getElementById("dropContainer"); | |||
| box.addEventListener("dragenter", OnDragEnter, false); | |||
| box.addEventListener("dragover", OnDragOver, false); | |||
| box.addEventListener("drop", OnDrop, false); | |||
| }) | |||
| function OnDragEnter(e) { | |||
| e.stopPropagation(); | |||
| e.preventDefault(); | |||
| } | |||
| function OnDragOver(e) { | |||
| e.stopPropagation(); | |||
| e.preventDefault(); | |||
| } | |||
| function OnDrop(e) { | |||
| e.stopPropagation(); | |||
| e.preventDefault(); | |||
| var selectedFiles = e.dataTransfer.files; | |||
| var formData = new FormData(); | |||
| var fileInput = document.getElementById("fileInputAsText"); | |||
| for (var i = 0; i < selectedFiles.length; i++){ | |||
| formData.append(selectedFiles[i].name, selectedFiles[i]); | |||
| } | |||
| $.ajax({ | |||
| url: '/Home/UploadTemporaryFile', | |||
| type: "POST", | |||
| contentType: false, | |||
| processData: false, | |||
| data: formData, | |||
| success: function (result) { | |||
| for (var i = 0; i < selectedFiles.length; i++){ | |||
| fileInput.value += result + ':' + selectedFiles[i].name + ';'; | |||
| filesUploaded.innerHTML += '<p>' + selectedFiles[i].name + '</p>'; | |||
| } | |||
| }, | |||
| error: function (err) { | |||
| console.log(err) | |||
| } | |||
| }); | |||
| } | |||
| </script> | |||