mirror of https://github.com/abpframework/eventhub
committed by
GitHub
170 changed files with 14383 additions and 2546 deletions
@ -0,0 +1,33 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace EventHub.Events; |
||||
|
|
||||
|
public class AddSessionDto |
||||
|
{ |
||||
|
[Required] |
||||
|
[StringLength(SessionConsts.MaxTitleLength, MinimumLength = SessionConsts.MinTitleLength)] |
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DataType(DataType.DateTime)] |
||||
|
public DateTime StartTime { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DataType(DataType.DateTime)] |
||||
|
public DateTime EndTime { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[StringLength(SessionConsts.MaxDescriptionLength, MinimumLength = SessionConsts.MinDescriptionLength)] |
||||
|
public string Description { get; set; } |
||||
|
|
||||
|
public string Language { get; set; } |
||||
|
|
||||
|
public List<string> SpeakerUserNames { get; set; } |
||||
|
|
||||
|
public AddSessionDto() |
||||
|
{ |
||||
|
SpeakerUserNames = new List<string>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace EventHub.Events; |
||||
|
|
||||
|
public class AddTrackDto |
||||
|
{ |
||||
|
[Required] |
||||
|
[StringLength(TrackConsts.MaxNameLength)] |
||||
|
public string Name { get; set; } |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
namespace EventHub.Events; |
||||
|
|
||||
|
public class DeleteTractDto |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace EventHub.Events; |
||||
|
|
||||
|
public class SessionDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public Guid TrackId { get; set; } |
||||
|
|
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
public DateTime StartTime { get; set; } |
||||
|
|
||||
|
public DateTime EndTime { get; set; } |
||||
|
|
||||
|
public string Description { get; set; } |
||||
|
|
||||
|
public string Language { get; set; } |
||||
|
|
||||
|
public List<SpeakerDto> Speakers { get; set; } |
||||
|
|
||||
|
public SessionDto() |
||||
|
{ |
||||
|
Speakers = new List<SpeakerDto>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace EventHub.Events; |
||||
|
|
||||
|
public class SpeakerDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public Guid SessionId { get; set; } |
||||
|
|
||||
|
public Guid UserId { get; set; } |
||||
|
|
||||
|
public string UserName { get; set; } |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace EventHub.Events; |
||||
|
|
||||
|
public class TrackDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public List<SessionDto> Sessions { get; set; } |
||||
|
|
||||
|
public TrackDto() |
||||
|
{ |
||||
|
Sessions = new List<SessionDto>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace EventHub.Events; |
||||
|
|
||||
|
public class UpdateSessionDto |
||||
|
{ |
||||
|
[Required] |
||||
|
[StringLength(SessionConsts.MaxTitleLength, MinimumLength = SessionConsts.MinTitleLength)] |
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DataType(DataType.DateTime)] |
||||
|
public DateTime StartTime { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DataType(DataType.DateTime)] |
||||
|
public DateTime EndTime { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[StringLength(SessionConsts.MaxDescriptionLength, MinimumLength = SessionConsts.MinDescriptionLength)] |
||||
|
public string Description { get; set; } |
||||
|
|
||||
|
public string Language { get; set; } |
||||
|
|
||||
|
public List<string> SpeakerUserNames { get; set; } |
||||
|
|
||||
|
public UpdateSessionDto() |
||||
|
{ |
||||
|
SpeakerUserNames = new List<string>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace EventHub.Events; |
||||
|
|
||||
|
public class UpdateTrackDto |
||||
|
{ |
||||
|
[Required] |
||||
|
[StringLength(TrackConsts.MaxNameLength)] |
||||
|
public string Name { get; set; } |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
namespace EventHub.Users; |
||||
|
|
||||
|
public class UserInListDto |
||||
|
{ |
||||
|
public string UserName { get; set; } |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
namespace EventHub.Events |
||||
|
{ |
||||
|
public static class SessionConsts |
||||
|
{ |
||||
|
public const int MinTitleLength = 8; |
||||
|
public const int MaxTitleLength = 128; |
||||
|
|
||||
|
public const int MinDescriptionLength = 50; |
||||
|
public const int MaxDescriptionLength = 2000; |
||||
|
|
||||
|
public const int MinLanguageLength = 2; |
||||
|
public const int MaxLanguageLength = 16; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace EventHub.Events |
||||
|
{ |
||||
|
public static class TrackConsts |
||||
|
{ |
||||
|
public const int MaxNameLength = 64; |
||||
|
} |
||||
|
} |
||||
@ -1,30 +0,0 @@ |
|||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
using Volo.Abp.Domain.Repositories; |
|
||||
using Volo.Abp.EventBus; |
|
||||
|
|
||||
namespace EventHub.Events |
|
||||
{ |
|
||||
public class EventTimeChangeLocalEventHandler : ILocalEventHandler<EventTimeChangingEventData>, ITransientDependency |
|
||||
{ |
|
||||
private readonly IRepository<Event, Guid> _eventRepository; |
|
||||
|
|
||||
public EventTimeChangeLocalEventHandler(IRepository<Event, Guid> eventRepository) |
|
||||
{ |
|
||||
_eventRepository = eventRepository; |
|
||||
} |
|
||||
|
|
||||
public async Task HandleEventAsync(EventTimeChangingEventData eventData) |
|
||||
{ |
|
||||
await UpdateEventForTimingChangeAsync(eventData.Event); |
|
||||
} |
|
||||
|
|
||||
private async Task UpdateEventForTimingChangeAsync(Event @event) |
|
||||
{ |
|
||||
@event.IsTimingChangeEmailSent = false; |
|
||||
|
|
||||
await _eventRepository.UpdateAsync(@event, true); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
using System; |
|
||||
|
|
||||
namespace EventHub.Events |
|
||||
{ |
|
||||
public class EventTimeChangingEventData |
|
||||
{ |
|
||||
public Event Event { get; } |
|
||||
public DateTime OldStartTime { get; } |
|
||||
public DateTime OldEndTime { get; } |
|
||||
|
|
||||
public EventTimeChangingEventData(Event @event, DateTime oldStartTime, DateTime oldEndTime) |
|
||||
{ |
|
||||
Event = @event; |
|
||||
OldStartTime = oldStartTime; |
|
||||
OldEndTime = oldEndTime; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,122 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.ObjectModel; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
|
||||
|
namespace EventHub.Events |
||||
|
{ |
||||
|
public class Session : Entity<Guid> |
||||
|
{ |
||||
|
public Guid TrackId { get; private set; } |
||||
|
|
||||
|
public string Title { get; private set; } |
||||
|
|
||||
|
public DateTime StartTime { get; private set; } |
||||
|
|
||||
|
public DateTime EndTime { get; private set; } |
||||
|
|
||||
|
public string Description { get; private set; } |
||||
|
|
||||
|
public string Language { get; set; } |
||||
|
|
||||
|
public ICollection<Speaker> Speakers { get; private set; } |
||||
|
|
||||
|
private Session() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
internal Session( |
||||
|
Guid id, |
||||
|
Guid trackId, |
||||
|
string title, |
||||
|
DateTime startTime, |
||||
|
DateTime endTime, |
||||
|
string description, |
||||
|
string language, |
||||
|
ICollection<Guid> speakerUserIds) |
||||
|
: base(id) |
||||
|
{ |
||||
|
TrackId = trackId; |
||||
|
SetTitle(title); |
||||
|
SetDescription(description); |
||||
|
SetTime(startTime, endTime); |
||||
|
SetLanguage(language); |
||||
|
|
||||
|
Speakers = new Collection<Speaker>(); |
||||
|
AddSpeakers(speakerUserIds); |
||||
|
} |
||||
|
|
||||
|
public Session SetTitle(string title) |
||||
|
{ |
||||
|
Title = Check.NotNullOrWhiteSpace(title, nameof(title), SessionConsts.MaxTitleLength, SessionConsts.MinTitleLength); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public Session SetDescription(string description) |
||||
|
{ |
||||
|
Description = Check.NotNullOrWhiteSpace(description, nameof(description), SessionConsts.MaxDescriptionLength, SessionConsts.MinDescriptionLength); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
internal Session SetTime(DateTime startTime, DateTime endTime) |
||||
|
{ |
||||
|
if (startTime > endTime) |
||||
|
{ |
||||
|
throw new BusinessException(EventHubErrorCodes.SessionEndTimeCantBeEarlierThanStartTime); |
||||
|
} |
||||
|
|
||||
|
StartTime = startTime; |
||||
|
EndTime = endTime; |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
internal Session SetLanguage(string language) |
||||
|
{ |
||||
|
Language = Check.NotNullOrWhiteSpace(language, nameof(language), SessionConsts.MaxLanguageLength); |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
internal Session AddSpeakers(ICollection<Guid> userIds) |
||||
|
{ |
||||
|
foreach (var userId in userIds) |
||||
|
{ |
||||
|
AddSpeaker(userId); |
||||
|
} |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
internal Session AddSpeaker(Guid userId) |
||||
|
{ |
||||
|
if (Speakers.Any(x => x.UserId == userId)) |
||||
|
{ |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
Speakers.Add(new Speaker(Id, userId)); |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
internal Session RemoveSpeakers(ICollection<Guid> userIds) |
||||
|
{ |
||||
|
foreach (var userId in userIds) |
||||
|
{ |
||||
|
RemoveSpeaker(userId); |
||||
|
} |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
internal Session RemoveSpeaker(Guid userId) |
||||
|
{ |
||||
|
Speakers.RemoveAll(t => t.UserId == userId); |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
|
||||
|
namespace EventHub.Events |
||||
|
{ |
||||
|
public class Speaker : Entity |
||||
|
{ |
||||
|
public Guid SessionId { get; private set; } |
||||
|
|
||||
|
public Guid UserId { get; private set; } |
||||
|
|
||||
|
private Speaker() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public Speaker(Guid sessionId, Guid userId) |
||||
|
{ |
||||
|
SessionId = sessionId; |
||||
|
UserId = userId; |
||||
|
} |
||||
|
|
||||
|
public override object[] GetKeys() |
||||
|
{ |
||||
|
return new object[] {SessionId, UserId}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,140 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.ObjectModel; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
|
||||
|
namespace EventHub.Events |
||||
|
{ |
||||
|
public class Track : Entity<Guid> |
||||
|
{ |
||||
|
public Guid EventId { get; private set; } |
||||
|
|
||||
|
public string Name { get; private set; } |
||||
|
|
||||
|
public ICollection<Session> Sessions { get; private set; } |
||||
|
|
||||
|
private Track() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
internal Track( |
||||
|
Guid id, |
||||
|
Guid eventId, |
||||
|
string name) |
||||
|
: base(id) |
||||
|
{ |
||||
|
EventId = eventId; |
||||
|
SetName(name); |
||||
|
Sessions = new Collection<Session>(); |
||||
|
} |
||||
|
|
||||
|
public Track SetName(string name) |
||||
|
{ |
||||
|
Name = Check.NotNullOrWhiteSpace(name, nameof(name), TrackConsts.MaxNameLength); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
internal Track AddSession( |
||||
|
Guid sessionId, |
||||
|
string title, |
||||
|
string description, |
||||
|
DateTime startTime, |
||||
|
DateTime endTime, |
||||
|
string language, |
||||
|
ICollection<Guid> speakerUserIds) |
||||
|
{ |
||||
|
if (Sessions.Any(s => s.Title == title)) |
||||
|
{ |
||||
|
throw new BusinessException(EventHubErrorCodes.SessionTitleAlreadyExist) |
||||
|
.WithData("Title", title); |
||||
|
} |
||||
|
|
||||
|
if (startTime > endTime) |
||||
|
{ |
||||
|
throw new BusinessException(EventHubErrorCodes.SessionEndTimeCantBeEarlierThanStartTime); |
||||
|
} |
||||
|
|
||||
|
CheckIfValidSessionTime(startTime); |
||||
|
CheckIfValidSessionTime(endTime); |
||||
|
|
||||
|
Sessions.Add(new Session(sessionId, Id, title, startTime, endTime, description, language, speakerUserIds)); |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
internal Track UpdateSession( |
||||
|
Guid sessionId, |
||||
|
string title, |
||||
|
string description, |
||||
|
DateTime startTime, |
||||
|
DateTime endTime, |
||||
|
string language, |
||||
|
ICollection<Guid> speakerUserIds) |
||||
|
{ |
||||
|
if (startTime > endTime) |
||||
|
{ |
||||
|
throw new BusinessException(EventHubErrorCodes.SessionEndTimeCantBeEarlierThanStartTime); |
||||
|
} |
||||
|
|
||||
|
var session = Sessions.Single(x => x.Id == sessionId); |
||||
|
|
||||
|
if (session.StartTime != startTime) |
||||
|
{ |
||||
|
CheckIfValidSessionTime(endTime, sessionId); |
||||
|
} |
||||
|
|
||||
|
if (session.EndTime != endTime) |
||||
|
{ |
||||
|
CheckIfValidSessionTime(endTime, sessionId); |
||||
|
} |
||||
|
|
||||
|
session.SetTitle(title); |
||||
|
session.SetDescription(description); |
||||
|
session.SetTime(startTime, endTime); |
||||
|
session.SetLanguage(language); |
||||
|
|
||||
|
if (!speakerUserIds.Any()) |
||||
|
{ |
||||
|
session.RemoveSpeakers(session.Speakers.Select(x => x.UserId).ToList()); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
var speakersToBeRemoved = session.Speakers.Where(x => speakerUserIds.Any(s => s != x.UserId)).Select(x => x.UserId).ToList(); |
||||
|
session.RemoveSpeakers(speakersToBeRemoved); |
||||
|
session.AddSpeakers(speakerUserIds); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
internal Track RemoveSession(Guid sessionId) |
||||
|
{ |
||||
|
var session = Sessions.SingleOrDefault(x => x.Id == sessionId); |
||||
|
if (session is null) |
||||
|
{ |
||||
|
throw new BusinessException(EventHubErrorCodes.SessionNotFound); |
||||
|
} |
||||
|
|
||||
|
Sessions.Remove(session); |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
private void CheckIfValidSessionTime(DateTime date, Guid? sessionId = null) |
||||
|
{ |
||||
|
foreach (var session in Sessions) |
||||
|
{ |
||||
|
if (sessionId.HasValue && sessionId!.Value == session.Id) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if (date.IsBetween(session.StartTime, session.EndTime)) |
||||
|
{ |
||||
|
throw new BusinessException(EventHubErrorCodes.SessionTimeConflictsWithAnExistingSession); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace EventHub.Users; |
||||
|
|
||||
|
public class UserWithoutDetails |
||||
|
{ |
||||
|
public Guid Id { get; set; } |
||||
|
|
||||
|
public string UserName { get; set; } |
||||
|
} |
||||
File diff suppressed because it is too large
@ -0,0 +1,115 @@ |
|||||
|
using System; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
namespace EventHub.Migrations |
||||
|
{ |
||||
|
public partial class Added_Tracks_And_Sessions : Migration |
||||
|
{ |
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.AddColumn<bool>( |
||||
|
name: "IsDraft", |
||||
|
table: "EhEvents", |
||||
|
type: "boolean", |
||||
|
nullable: false, |
||||
|
defaultValue: false); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "EhEventTracks", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false), |
||||
|
EventId = table.Column<Guid>(type: "uuid", nullable: false), |
||||
|
Name = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_EhEventTracks", x => x.Id); |
||||
|
table.ForeignKey( |
||||
|
name: "FK_EhEventTracks_EhEvents_EventId", |
||||
|
column: x => x.EventId, |
||||
|
principalTable: "EhEvents", |
||||
|
principalColumn: "Id", |
||||
|
onDelete: ReferentialAction.Cascade); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "EhEventSessions", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false), |
||||
|
TrackId = table.Column<Guid>(type: "uuid", nullable: false), |
||||
|
Title = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false), |
||||
|
StartTime = table.Column<DateTime>(type: "timestamp without time zone", nullable: false), |
||||
|
EndTime = table.Column<DateTime>(type: "timestamp without time zone", nullable: false), |
||||
|
Description = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: false), |
||||
|
Language = table.Column<string>(type: "character varying(16)", maxLength: 16, nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_EhEventSessions", x => x.Id); |
||||
|
table.ForeignKey( |
||||
|
name: "FK_EhEventSessions_EhEventTracks_TrackId", |
||||
|
column: x => x.TrackId, |
||||
|
principalTable: "EhEventTracks", |
||||
|
principalColumn: "Id", |
||||
|
onDelete: ReferentialAction.Cascade); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "EhEventSpeakers", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
SessionId = table.Column<Guid>(type: "uuid", nullable: false), |
||||
|
UserId = table.Column<Guid>(type: "uuid", nullable: false) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_EhEventSpeakers", x => new { x.SessionId, x.UserId }); |
||||
|
table.ForeignKey( |
||||
|
name: "FK_EhEventSpeakers_AbpUsers_UserId", |
||||
|
column: x => x.UserId, |
||||
|
principalTable: "AbpUsers", |
||||
|
principalColumn: "Id", |
||||
|
onDelete: ReferentialAction.Cascade); |
||||
|
table.ForeignKey( |
||||
|
name: "FK_EhEventSpeakers_EhEventSessions_SessionId", |
||||
|
column: x => x.SessionId, |
||||
|
principalTable: "EhEventSessions", |
||||
|
principalColumn: "Id", |
||||
|
onDelete: ReferentialAction.Cascade); |
||||
|
}); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_EhEventSessions_TrackId", |
||||
|
table: "EhEventSessions", |
||||
|
column: "TrackId"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_EhEventSpeakers_UserId_SessionId", |
||||
|
table: "EhEventSpeakers", |
||||
|
columns: new[] { "UserId", "SessionId" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_EhEventTracks_EventId", |
||||
|
table: "EhEventTracks", |
||||
|
column: "EventId"); |
||||
|
} |
||||
|
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropTable( |
||||
|
name: "EhEventSpeakers"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "EhEventSessions"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "EhEventTracks"); |
||||
|
|
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "IsDraft", |
||||
|
table: "EhEvents"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
File diff suppressed because it is too large
@ -0,0 +1,104 @@ |
|||||
|
using System; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
#nullable disable |
||||
|
|
||||
|
namespace EventHub.Migrations |
||||
|
{ |
||||
|
public partial class Removed_Unnecessary_Index : Migration |
||||
|
{ |
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropIndex( |
||||
|
name: "IX_EhEventSpeakers_UserId_SessionId", |
||||
|
table: "EhEventSpeakers"); |
||||
|
|
||||
|
migrationBuilder.DropIndex( |
||||
|
name: "IX_AbpSettings_Name_ProviderName_ProviderKey", |
||||
|
table: "AbpSettings"); |
||||
|
|
||||
|
migrationBuilder.DropIndex( |
||||
|
name: "IX_AbpPermissionGrants_Name_ProviderName_ProviderKey", |
||||
|
table: "AbpPermissionGrants"); |
||||
|
|
||||
|
migrationBuilder.AlterColumn<DateTime>( |
||||
|
name: "StartTime", |
||||
|
table: "EhEventSessions", |
||||
|
type: "timestamp with time zone", |
||||
|
nullable: false, |
||||
|
oldClrType: typeof(DateTime), |
||||
|
oldType: "timestamp without time zone"); |
||||
|
|
||||
|
migrationBuilder.AlterColumn<DateTime>( |
||||
|
name: "EndTime", |
||||
|
table: "EhEventSessions", |
||||
|
type: "timestamp with time zone", |
||||
|
nullable: false, |
||||
|
oldClrType: typeof(DateTime), |
||||
|
oldType: "timestamp without time zone"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_EhEventSpeakers_UserId", |
||||
|
table: "EhEventSpeakers", |
||||
|
column: "UserId"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AbpSettings_Name_ProviderName_ProviderKey", |
||||
|
table: "AbpSettings", |
||||
|
columns: new[] { "Name", "ProviderName", "ProviderKey" }, |
||||
|
unique: true); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AbpPermissionGrants_TenantId_Name_ProviderName_ProviderKey", |
||||
|
table: "AbpPermissionGrants", |
||||
|
columns: new[] { "TenantId", "Name", "ProviderName", "ProviderKey" }, |
||||
|
unique: true); |
||||
|
} |
||||
|
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropIndex( |
||||
|
name: "IX_EhEventSpeakers_UserId", |
||||
|
table: "EhEventSpeakers"); |
||||
|
|
||||
|
migrationBuilder.DropIndex( |
||||
|
name: "IX_AbpSettings_Name_ProviderName_ProviderKey", |
||||
|
table: "AbpSettings"); |
||||
|
|
||||
|
migrationBuilder.DropIndex( |
||||
|
name: "IX_AbpPermissionGrants_TenantId_Name_ProviderName_ProviderKey", |
||||
|
table: "AbpPermissionGrants"); |
||||
|
|
||||
|
migrationBuilder.AlterColumn<DateTime>( |
||||
|
name: "StartTime", |
||||
|
table: "EhEventSessions", |
||||
|
type: "timestamp without time zone", |
||||
|
nullable: false, |
||||
|
oldClrType: typeof(DateTime), |
||||
|
oldType: "timestamp with time zone"); |
||||
|
|
||||
|
migrationBuilder.AlterColumn<DateTime>( |
||||
|
name: "EndTime", |
||||
|
table: "EhEventSessions", |
||||
|
type: "timestamp without time zone", |
||||
|
nullable: false, |
||||
|
oldClrType: typeof(DateTime), |
||||
|
oldType: "timestamp with time zone"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_EhEventSpeakers_UserId_SessionId", |
||||
|
table: "EhEventSpeakers", |
||||
|
columns: new[] { "UserId", "SessionId" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AbpSettings_Name_ProviderName_ProviderKey", |
||||
|
table: "AbpSettings", |
||||
|
columns: new[] { "Name", "ProviderName", "ProviderKey" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AbpPermissionGrants_Name_ProviderName_ProviderKey", |
||||
|
table: "AbpPermissionGrants", |
||||
|
columns: new[] { "Name", "ProviderName", "ProviderKey" }); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,97 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Threading.Tasks; |
|
||||
using EventHub.Events; |
|
||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using Volo.Abp; |
|
||||
using Volo.Abp.Application.Dtos; |
|
||||
using Volo.Abp.AspNetCore.Mvc; |
|
||||
using Volo.Abp.Content; |
|
||||
using Volo.Abp.VirtualFileSystem; |
|
||||
|
|
||||
namespace EventHub.Controllers.Events |
|
||||
{ |
|
||||
[RemoteService(Name = EventHubRemoteServiceConsts.RemoteServiceName)] |
|
||||
[Area("eventhub")] |
|
||||
[ControllerName("Event")] |
|
||||
[Route("api/eventhub/event")] |
|
||||
public class EventController : AbpController, IEventAppService |
|
||||
{ |
|
||||
private readonly IEventAppService _eventAppService; |
|
||||
private readonly IVirtualFileProvider _virtualFileProvider; |
|
||||
|
|
||||
public EventController( |
|
||||
IEventAppService eventAppService, |
|
||||
IVirtualFileProvider virtualFileProvider) |
|
||||
{ |
|
||||
_eventAppService = eventAppService; |
|
||||
_virtualFileProvider = virtualFileProvider; |
|
||||
} |
|
||||
|
|
||||
[HttpPost] |
|
||||
public async Task<EventDto> CreateAsync([FromForm] CreateEventDto input) |
|
||||
{ |
|
||||
return await _eventAppService.CreateAsync(input); |
|
||||
} |
|
||||
|
|
||||
[HttpGet] |
|
||||
public async Task<PagedResultDto<EventInListDto>> GetListAsync(EventListFilterDto input) |
|
||||
{ |
|
||||
return await _eventAppService.GetListAsync(input); |
|
||||
} |
|
||||
|
|
||||
[HttpGet] |
|
||||
[Route("by-url-code/{urlCode}")] |
|
||||
public async Task<EventDetailDto> GetByUrlCodeAsync(string urlCode) |
|
||||
{ |
|
||||
return await _eventAppService.GetByUrlCodeAsync(urlCode); |
|
||||
} |
|
||||
|
|
||||
[HttpGet] |
|
||||
[Route("location/{id}")] |
|
||||
public async Task<EventLocationDto> GetLocationAsync(Guid id) |
|
||||
{ |
|
||||
return await _eventAppService.GetLocationAsync(id); |
|
||||
} |
|
||||
|
|
||||
[HttpGet] |
|
||||
[Route("lookup/countries")] |
|
||||
public async Task<List<CountryLookupDto>> GetCountriesLookupAsync() |
|
||||
{ |
|
||||
return await _eventAppService.GetCountriesLookupAsync(); |
|
||||
} |
|
||||
|
|
||||
[HttpGet] |
|
||||
[Route("is-event-owner/{id}")] |
|
||||
public async Task<bool> IsEventOwnerAsync(Guid id) |
|
||||
{ |
|
||||
return await _eventAppService.IsEventOwnerAsync(id); |
|
||||
} |
|
||||
|
|
||||
[HttpPut] |
|
||||
[Route("{id}")] |
|
||||
public async Task UpdateAsync(Guid id, [FromForm] UpdateEventDto input) |
|
||||
{ |
|
||||
await _eventAppService.UpdateAsync(id, input); |
|
||||
} |
|
||||
|
|
||||
[HttpGet] |
|
||||
[Route("cover-image/{id}")] |
|
||||
public async Task<IRemoteStreamContent> GetCoverImageAsync(Guid id) |
|
||||
{ |
|
||||
var remoteStreamContent = await _eventAppService.GetCoverImageAsync(id); |
|
||||
|
|
||||
if (remoteStreamContent is null) |
|
||||
{ |
|
||||
var stream = _virtualFileProvider.GetFileInfo("/Images/eh-event.png").CreateReadStream(); |
|
||||
remoteStreamContent = new RemoteStreamContent(stream); |
|
||||
await stream.FlushAsync(); |
|
||||
} |
|
||||
|
|
||||
Response.Headers.Add("Accept-Ranges", "bytes"); |
|
||||
Response.ContentType = remoteStreamContent.ContentType; |
|
||||
|
|
||||
return remoteStreamContent; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,155 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using EventHub.Events; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Content; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace EventHub.Controllers.Events |
||||
|
{ |
||||
|
[RemoteService(Name = EventHubRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area("eventhub")] |
||||
|
[ControllerName("Event")] |
||||
|
[Route("api/eventhub/event")] |
||||
|
public class EventController : EventHubController, IEventAppService |
||||
|
{ |
||||
|
private readonly IEventAppService _eventAppService; |
||||
|
private readonly IVirtualFileProvider _virtualFileProvider; |
||||
|
|
||||
|
public EventController( |
||||
|
IEventAppService eventAppService, |
||||
|
IVirtualFileProvider virtualFileProvider) |
||||
|
{ |
||||
|
_eventAppService = eventAppService; |
||||
|
_virtualFileProvider = virtualFileProvider; |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
public async Task<EventDto> CreateAsync([FromForm] CreateEventDto input) |
||||
|
{ |
||||
|
return await _eventAppService.CreateAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public async Task<PagedResultDto<EventInListDto>> GetListAsync(EventListFilterDto input) |
||||
|
{ |
||||
|
return await _eventAppService.GetListAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("draft-events-by-user-id")] |
||||
|
public async Task<List<EventInListDto>> GetDraftEventsByCurrentUser() |
||||
|
{ |
||||
|
return await _eventAppService.GetDraftEventsByCurrentUser(); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("by-url-code/{urlCode}")] |
||||
|
public async Task<EventDetailDto> GetByUrlCodeAsync(string urlCode) |
||||
|
{ |
||||
|
return await _eventAppService.GetByUrlCodeAsync(urlCode); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("location/{id}")] |
||||
|
public async Task<EventLocationDto> GetLocationAsync(Guid id) |
||||
|
{ |
||||
|
return await _eventAppService.GetLocationAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("lookup/countries")] |
||||
|
public async Task<List<CountryLookupDto>> GetCountriesLookupAsync() |
||||
|
{ |
||||
|
return await _eventAppService.GetCountriesLookupAsync(); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("is-event-owner/{id}")] |
||||
|
public async Task<bool> IsEventOwnerAsync(Guid id) |
||||
|
{ |
||||
|
return await _eventAppService.IsEventOwnerAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Route("{id}")] |
||||
|
public async Task UpdateAsync(Guid id, [FromForm] UpdateEventDto input) |
||||
|
{ |
||||
|
await _eventAppService.UpdateAsync(id, input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Route("/publish/{id}")] |
||||
|
public async Task<string> PublishAsync(Guid id) |
||||
|
{ |
||||
|
return await _eventAppService.PublishAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Route("{id}/tracks")] |
||||
|
public async Task AddTrackAsync(Guid id, AddTrackDto input) |
||||
|
{ |
||||
|
await _eventAppService.AddTrackAsync(id, input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Route("{id}/tracks/{trackId}")] |
||||
|
public async Task UpdateTrackAsync(Guid id, Guid trackId, UpdateTrackDto input) |
||||
|
{ |
||||
|
await _eventAppService.UpdateTrackAsync(id, trackId, input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("{id}/tracks/{trackId}")] |
||||
|
public async Task DeleteTrackAsync(Guid id, Guid trackId) |
||||
|
{ |
||||
|
await _eventAppService.DeleteTrackAsync(id, trackId); |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Route("{id}/tracks/{trackId}/sessions")] |
||||
|
public async Task AddSessionAsync(Guid id, Guid trackId, AddSessionDto input) |
||||
|
{ |
||||
|
input.SpeakerUserNames = input.SpeakerUserNames.Where(x => !x.IsNullOrWhiteSpace()).ToList(); |
||||
|
await _eventAppService.AddSessionAsync(id, trackId, input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Route("{id}/tracks/{trackId}/sessions/{sessionId}")] |
||||
|
public async Task UpdateSessionAsync(Guid id, Guid trackId, Guid sessionId, UpdateSessionDto input) |
||||
|
{ |
||||
|
input.SpeakerUserNames = input.SpeakerUserNames.Where(x => !x.IsNullOrWhiteSpace()).ToList(); |
||||
|
await _eventAppService.UpdateSessionAsync(id, trackId, sessionId, input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("{id}/tracks/{trackId}/sessions/{sessionId}")] |
||||
|
public async Task DeleteSessionAsync(Guid id, Guid trackId, Guid sessionId) |
||||
|
{ |
||||
|
await _eventAppService.DeleteSessionAsync(id, trackId, sessionId); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("cover-image/{id}")] |
||||
|
public async Task<IRemoteStreamContent> GetCoverImageAsync(Guid id) |
||||
|
{ |
||||
|
var remoteStreamContent = await _eventAppService.GetCoverImageAsync(id); |
||||
|
|
||||
|
if (remoteStreamContent is null) |
||||
|
{ |
||||
|
var stream = _virtualFileProvider.GetFileInfo("/Images/eh-event.png").CreateReadStream(); |
||||
|
remoteStreamContent = new RemoteStreamContent(stream); |
||||
|
await stream.FlushAsync(); |
||||
|
} |
||||
|
|
||||
|
Response.Headers.Add("Accept-Ranges", "bytes"); |
||||
|
Response.ContentType = remoteStreamContent.ContentType; |
||||
|
|
||||
|
return remoteStreamContent; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,853 +0,0 @@ |
|||||
@page "/test" |
|
||||
@using EventHub.Web.Pages |
|
||||
@model EventHub.Web.Pages.Empty |
|
||||
|
|
||||
<main class="static-page container mt-5"> |
|
||||
<h1 class="text-center mb-3">Create an Event</h1> |
|
||||
<p class="text-center mb-5">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ut nulla consequat, tempus sapien in, |
|
||||
pellentesque nunc. Sed at nunc pellentesque, fermentum mi et, fermentum massa. </p> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="card"> |
|
||||
<div class="card-body px-4 py-5 text-center"> |
|
||||
<svg width="50" height="58" viewBox="0 0 50 58" fill="none" xmlns="http://www.w3.org/2000/svg"> |
|
||||
<path d="M33.0445 28.1094H9.31281C8.68249 28.1094 8.17188 28.6205 8.17188 29.2515C8.17188 29.8825 8.68249 30.394 9.31281 30.394H33.0445C33.6748 30.394 34.1854 29.8825 34.1854 29.2515C34.1854 28.6209 33.6748 28.1094 33.0445 28.1094Z" fill="#E8345D"/> |
|
||||
<path d="M33.0445 34.8032H9.31281C8.68249 34.8032 8.17188 35.3143 8.17188 35.9453C8.17188 36.5763 8.68249 37.0879 9.31281 37.0879H33.0445C33.6748 37.0879 34.1854 36.5763 34.1854 35.9453C34.1854 35.3143 33.6748 34.8032 33.0445 34.8032Z" fill="#E8345D"/> |
|
||||
<path d="M33.0445 41.4976H9.31281C8.68249 41.4976 8.17188 42.0087 8.17188 42.6397C8.17188 43.2707 8.68249 43.7822 9.31281 43.7822H33.0445C33.6748 43.7822 34.1854 43.2707 34.1854 42.6397C34.1854 42.0087 33.6748 41.4976 33.0445 41.4976Z" fill="#E8345D"/> |
|
||||
<path d="M48.0044 5.61362H44.3885V1.99791C44.3885 0.896072 43.4919 0 42.3894 0H37.5942C36.4935 0 35.5981 0.896072 35.5981 1.99791V5.61317H31.9827C31.1161 5.61317 30.3785 6.16896 30.1019 6.94246H12.6346C12.332 6.94246 12.0418 7.06282 11.8281 7.27699L0.333931 18.791C0.120145 19.0051 0 19.2959 0 19.599V54.9016C0 56.6101 1.38917 58 3.09637 58H39.7387C41.4459 58 42.8351 56.6101 42.8351 54.9016V39.4692C42.8351 38.8382 42.324 38.3267 41.6941 38.3267C41.0643 38.3267 40.5536 38.8382 40.5536 39.4692V54.9016C40.5536 55.3428 40.1804 55.7153 39.7387 55.7153H3.09637C2.65466 55.7153 2.28142 55.3428 2.28142 54.9016V20.7411H10.3103C12.2212 20.7411 13.7755 19.1857 13.7755 17.2736V9.22711H29.9831V12.4114C29.9831 13.5132 30.8802 14.4093 31.9827 14.4093H35.5981V18.0246C35.5981 19.1282 36.4935 20.026 37.5942 20.026H40.5532V29.1438C40.5532 29.7744 41.0643 30.2859 41.6941 30.2859C42.324 30.2859 42.8346 29.7744 42.8346 29.1438V19.9742C43.7233 19.7707 44.3885 18.9751 44.3885 18.025V14.4093H48.0039C49.1047 14.4093 50 13.5132 50 12.4114V7.61462C50 6.51102 49.1047 5.61362 48.0044 5.61362ZM10.3103 18.4564H3.8941L11.4937 10.8431V17.2736C11.4937 17.9259 10.9632 18.4564 10.3103 18.4564ZM47.7186 12.1246H43.2481C42.6177 12.1246 42.1071 12.6362 42.1071 13.2672V17.7413H37.8795V13.2672C37.8795 12.6362 37.3689 12.1246 36.739 12.1246H32.265V7.89827H36.739C37.3689 7.89827 37.8795 7.38673 37.8795 6.75572V2.28465H42.1071V6.75572C42.1071 7.38673 42.6177 7.89827 43.2481 7.89827H47.7186V12.1246Z" fill="#E8345D"/> |
|
||||
<path d="M41.6937 33.1411C41.0633 33.1411 40.5527 33.6526 40.5527 34.2837V34.3067C40.5527 34.9372 41.0638 35.4488 41.6937 35.4488C42.3235 35.4488 42.8342 34.9372 42.8342 34.3067V34.2837C42.8346 33.6526 42.3235 33.1411 41.6937 33.1411Z" fill="#E8345D"/> |
|
||||
</svg> |
|
||||
<h2 class="mt-4">Create a New Event</h2> |
|
||||
<p class="my-4">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam utnulla consequat, tempus sapien in.</p> |
|
||||
<a href="#" class="btn btn-primary">Create</a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="card"> |
|
||||
<div class="card-body px-4 py-5 text-center"> |
|
||||
<svg width="42" height="56" viewBox="0 0 42 56" fill="none" xmlns="http://www.w3.org/2000/svg"> |
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.9071 0H12.456C12.4436 0 12.4313 0.00128174 12.4193 0.00170898C12.4069 0.00213622 12.3946 0.00299073 12.3822 0.00384521C12.3361 0.00683594 12.29 0.0119629 12.2452 0.020935C12.2439 0.020935 12.2431 0.020935 12.2422 0.0213622C12.1965 0.0303345 12.1517 0.0435792 12.1074 0.0585327C12.0958 0.0623779 12.0839 0.0666504 12.0724 0.0709229C12.0314 0.0863037 11.9913 0.103821 11.952 0.123901C11.949 0.12561 11.9456 0.126892 11.9422 0.128601C11.9008 0.150818 11.8616 0.176453 11.8231 0.203369C11.8133 0.210632 11.8031 0.218323 11.7933 0.226013C11.7549 0.255066 11.7182 0.285828 11.6836 0.320435L0.320063 11.6971C0.285497 11.7318 0.254344 11.7693 0.225325 11.8074C0.217643 11.8172 0.210388 11.827 0.20356 11.8369C0.176248 11.8757 0.150216 11.9155 0.128025 11.9569C0.126745 11.9595 0.125892 11.9616 0.125038 11.9642C0.104127 12.0039 0.0862037 12.0453 0.0708408 12.0876C0.0665732 12.0988 0.0623056 12.1099 0.0584649 12.121C0.0435287 12.1658 0.0302994 12.2111 0.0209108 12.2573V12.2581C0.011949 12.3038 0.00682802 12.3508 0.00384076 12.3978C0.00298726 12.4098 0.00213375 12.4218 0.001707 12.4337C0.00128026 12.4461 0 12.4585 0 12.4709V54.9062C0 55.5104 0.489057 56 1.09248 56H40.9075C41.5105 56 42 55.5104 42 54.9062V1.09375C41.9996 0.489624 41.5105 0 40.9071 0ZM11.3635 3.73456V11.3771H3.72981L11.3635 3.73456ZM39.8146 53.8125H2.18497V13.5646H12.456C13.0594 13.5646 13.5485 13.0746 13.5485 12.4709V2.1875H39.815V53.8125H39.8146Z" fill="#E8345D"/> |
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.3835 20.3442C6.78007 20.3442 6.29102 20.8339 6.29102 21.438V37.2427C6.29102 37.8468 6.78007 38.3364 7.3835 38.3364C7.98693 38.3364 8.47598 37.8468 8.47598 37.2427V22.5317H26.4473V28.1146C26.1631 28.0936 25.8759 28.0825 25.5866 28.0825C19.2088 28.0825 14.0199 33.277 14.0199 39.6626C14.0199 39.9514 14.031 40.239 14.0523 40.5239H11.7534C11.15 40.5239 10.6609 41.0135 10.6609 41.6177C10.6609 42.2218 11.15 42.7114 11.7534 42.7114H14.4309C15.3313 46.0046 17.6605 48.8001 20.8654 50.2365C21.4164 50.4835 22.0625 50.2365 22.3091 49.6849C22.5558 49.1338 22.3091 48.4865 21.7582 48.24C18.3847 46.728 16.2049 43.3613 16.2049 39.6626C16.2049 34.4835 20.4135 30.27 25.5866 30.27C30.7596 30.27 34.9683 34.4835 34.9683 39.6626C34.9683 43.3613 32.7889 46.728 29.4154 48.24C28.8644 48.4865 28.6178 49.1338 28.8644 49.6849C29.0462 50.0912 29.4448 50.3322 29.8622 50.3322C30.0116 50.3322 30.1631 50.3015 30.3081 50.2365C34.4664 48.3729 37.1532 44.2222 37.1532 39.6626C37.1532 34.3323 33.5374 29.8325 28.6323 28.4905V21.438C28.6323 20.8339 28.1428 20.3442 27.5398 20.3442H7.3835Z" fill="#E8345D"/> |
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.5886 49.0552C24.9869 49.0552 24.4961 49.5461 24.4961 50.1489C24.4961 50.7513 24.9869 51.2427 25.5886 51.2427C26.1903 51.2427 26.6811 50.7513 26.6811 50.1489C26.6811 49.5461 26.1903 49.0552 25.5886 49.0552Z" fill="#E8345D"/> |
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.3835 40.5239C6.78178 40.5239 6.29102 41.0153 6.29102 41.6177C6.29102 42.2201 6.78178 42.7114 7.3835 42.7114C7.98522 42.7114 8.47598 42.2201 8.47598 41.6177C8.47598 41.0153 7.98522 40.5239 7.3835 40.5239Z" fill="#E8345D"/> |
|
||||
</svg> |
|
||||
<h2 class="my-4">Drafts</h2> |
|
||||
<div class="card card-body border-light mb-0 mt-3"> |
|
||||
<div class="row"> |
|
||||
<div class="col-7 text-start"> |
|
||||
<a href="#" class="text-info stretched-link text-decoration-none">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</a> |
|
||||
</div> |
|
||||
<div class="col-5 text-end"> |
|
||||
<span>Last edit: 01/01/2020</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="card card-body border-light mb-0 mt-3"> |
|
||||
<div class="row"> |
|
||||
<div class="col-7 text-start"> |
|
||||
<a href="#" class="text-info stretched-link text-decoration-none">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</a> |
|
||||
</div> |
|
||||
<div class="col-5 text-end"> |
|
||||
<span>Last edit: 01/01/2020</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="card card-body border-light mb-0 mt-3"> |
|
||||
<div class="row"> |
|
||||
<div class="col-7 text-start"> |
|
||||
<a href="#" class="text-info stretched-link text-decoration-none">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</a> |
|
||||
</div> |
|
||||
<div class="col-5 text-end"> |
|
||||
<span>Last edit: 01/01/2020</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="card card-body border-light mb-0 mt-3"> |
|
||||
<div class="row"> |
|
||||
<div class="col-7 text-start"> |
|
||||
<a href="#" class="text-info stretched-link text-decoration-none">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</a> |
|
||||
</div> |
|
||||
<div class="col-5 text-end"> |
|
||||
<span>Last edit: 01/01/2020</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Progress Steps --> |
|
||||
<div class="px-4 py-1"> |
|
||||
<div class="progresses py-4"> |
|
||||
<ul class="d-flex align-items-center justify-content-between"> |
|
||||
<li id="step-1" class="create-steps blue">1<span>New Event</span></li> |
|
||||
<li id="step-2" class="create-steps">2<span>Add Track</span></li> |
|
||||
<li id="step-3" class="create-steps">3<span>Add Session</span></li> |
|
||||
</ul> |
|
||||
<div class="progress"> |
|
||||
<div class="progress-bar" role="progressbar" style="width: 0%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Create a New Event --> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-10 mx-auto"> |
|
||||
<div class="card"> |
|
||||
<div class="card-body profile-content p-5"> |
|
||||
<h2 class="mb-4">Create a New Event</h2> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-floating mb-4"> |
|
||||
<input type="text" class="form-control" id="OrganizationName" placeholder=" "> |
|
||||
<label for="OrganizationName">Email address</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-floating mb-4"> |
|
||||
<input type="text" id="Title" placeholder=" " class="form-control"> |
|
||||
<label for="Title">Title</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-floating mb-4"> |
|
||||
<input type="text" id="StartDate" placeholder=" " class="form-control"> |
|
||||
<label for="StartDate">Start Date</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-floating mb-4"> |
|
||||
<input type="text" id="EndDate" placeholder=" " class="form-control"> |
|
||||
<label for="EndDate">End Date</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-12"> |
|
||||
<div class="form-floating mb-4"> |
|
||||
<textarea class="form-control" placeholder="Leave a comment here" id="EventsExplanation" style="height: 150px"></textarea> |
|
||||
<label for="EventsExplanation">Event’s Explanation</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row"> |
|
||||
<div class="col-md-12"> |
|
||||
<h3 class="mb-3">Cover Image</h3> |
|
||||
<div class="row"> |
|
||||
<div class="col-6"> |
|
||||
<div class="image-area"> |
|
||||
<img id="imageResult" src="#" alt="" class="img-fluid rounded shadow-sm mx-auto d-block"> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-6"> |
|
||||
<div> |
|
||||
<p class="mb-3">Photo size should be <span class="text-primary">1050x596</span> and <span class="text-primary">max 5 MB.</span></p> |
|
||||
<input type="file" id="Organization_ProfilePictureFile" class="form-control border-0" hidden="" name="Organization.ProfilePictureFile"> |
|
||||
<label id="upload-label" for="Organization_ProfilePictureFile" class="btn btn-primary btn-lg text-white">Upload</label> |
|
||||
<span class="Microsoft.AspNetCore.Mvc.TagHelpers.TagHelperOutputExtensions+ClassAttributeHtmlContent text-danger" data-valmsg-for="Organization.ProfilePictureFile" data-valmsg-replace="true"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row"> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-floating mb-4"> |
|
||||
<select class="form-select" id="Country"> |
|
||||
<option selected>Select Country</option> |
|
||||
<option value="1">One</option> |
|
||||
<option value="2">Two</option> |
|
||||
<option value="3">Three</option> |
|
||||
</select> |
|
||||
<label for="Country">Country</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-floating mb-4"> |
|
||||
<select class="form-select" id="City"> |
|
||||
<option selected>Select City</option> |
|
||||
<option value="1">One</option> |
|
||||
<option value="2">Two</option> |
|
||||
<option value="3">Three</option> |
|
||||
</select> |
|
||||
<label for="City">City</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-floating mb-4"> |
|
||||
<select class="form-select" id="Language"> |
|
||||
<option selected>Select Language</option> |
|
||||
<option value="1">One</option> |
|
||||
<option value="2">Two</option> |
|
||||
<option value="3">Three</option> |
|
||||
</select> |
|
||||
<label for="Language">Country</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-floating mb-4"> |
|
||||
<input type="text" id="Capacity" placeholder=" " class="form-control"> |
|
||||
<label for="Capacity">Capacity</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-floating mb-4"> |
|
||||
<select class="form-select" id="TypeOfEvent"> |
|
||||
<option selected>Select Type of Event</option> |
|
||||
<option value="1">One</option> |
|
||||
<option value="2">Two</option> |
|
||||
<option value="3">Three</option> |
|
||||
</select> |
|
||||
<label for="TypeOfEvent">Type of Event</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="row"> |
|
||||
<div class="col-6"></div> |
|
||||
<div class="col-6 text-end"> |
|
||||
<a href="#" class="btn btn-primary btn-lg">Next Step <i class="fa fa-arrow-right ms-2"></i></a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Progress Steps --> |
|
||||
<div class="px-4 py-1"> |
|
||||
<div class="progresses py-4"> |
|
||||
<ul class="d-flex align-items-center justify-content-between"> |
|
||||
<li id="step-1" class="create-steps blue">1<span>New Event</span></li> |
|
||||
<li id="step-2" class="create-steps blue">2<span>Add Track</span></li> |
|
||||
<li id="step-3" class="create-steps">3<span>Add Session</span></li> |
|
||||
</ul> |
|
||||
<div class="progress"> |
|
||||
<div class="progress-bar" role="progressbar" style="width: 50%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Add Track --> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-10 mx-auto"> |
|
||||
<div class="card"> |
|
||||
<div class="card-body profile-content p-5" style="min-height: 480px;"> |
|
||||
<h2 class="mb-4">Add Track</h2> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-3"> |
|
||||
<div class="track-item mb-4"> |
|
||||
<span class="track-name">There is a track name here</span> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#editTrackModal" class="mt-3 d-block text-info"><small><i class="fa fa-edit me-1"></i>Edit</small></a> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-3"> |
|
||||
<div class="track-item mb-4"> |
|
||||
<span class="track-name">There is a track name here</span> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#editTrackModal" class="mt-3 d-block text-info"><small><i class="fa fa-edit me-1"></i>Edit</small></a> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-3"> |
|
||||
<div class="track-item mb-4"> |
|
||||
<span class="track-name">There is a track name here</span> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#editTrackModal" class="mt-3 d-block text-info"><small><i class="fa fa-edit me-1"></i>Edit</small></a> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-3"> |
|
||||
<div class="big-square-btn mb-4 text-center"> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#addTrackModal" class="btn btn-outline-secondary d-block px-2 py-5"><i class="fa fa-plus mb-3"></i><br>Add New Track</a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="card-footer bg-white border-0 p-5 pt-1"> |
|
||||
<div class="row"> |
|
||||
<div class="col-6"> |
|
||||
<a href="#" class="btn btn-secondary"><i class="fa fa-arrow-left me-2"></i> Previous Step </a> |
|
||||
</div> |
|
||||
<div class="col-6 text-end"> |
|
||||
<a href="#" class="btn btn-link">Skip This Step</a> |
|
||||
<a href="#" class="btn btn-primary">Next Step <i class="fa fa-arrow-right ms-2"></i></a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Progress Steps --> |
|
||||
<div class="px-4 py-1"> |
|
||||
<div class="progresses py-4"> |
|
||||
<ul class="d-flex align-items-center justify-content-between"> |
|
||||
<li id="step-1" class="create-steps blue">1<span>New Event</span></li> |
|
||||
<li id="step-2" class="create-steps blue">2<span>Add Track</span></li> |
|
||||
<li id="step-3" class="create-steps blue">3<span>Add Session</span></li> |
|
||||
</ul> |
|
||||
<div class="progress"> |
|
||||
<div class="progress-bar" role="progressbar" style="width: 100%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Add Session --> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-10 mx-auto"> |
|
||||
<div class="card"> |
|
||||
<div class="card-body profile-content p-5" style="min-height: 480px;"> |
|
||||
<h2 class="mb-4">Add Session</h2> |
|
||||
<table class="table"> |
|
||||
<thead> |
|
||||
<tr> |
|
||||
<th class="text-center" width="25%">Track 1</th> |
|
||||
<th class="text-center" width="25%">Track 1</th> |
|
||||
<th class="text-center" width="25%">Track 1</th> |
|
||||
<th class="text-center" width="25%">Track 1</th> |
|
||||
</tr> |
|
||||
</thead> |
|
||||
<tbody> |
|
||||
<tr> |
|
||||
<td> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#editSessionModal" class="mt-3 d-block text-info"><small><i class="fa fa-edit me-1"></i>Edit</small></a> |
|
||||
</div> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#editSessionModal" class="mt-3 d-block text-info"><small><i class="fa fa-edit me-1"></i>Edit</small></a> |
|
||||
</div> |
|
||||
<div class="big-square-btn text-center"> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#addSessionModal" class="btn btn-outline-secondary d-block px-2 py-5"><i class="fa fa-plus mb-3"></i><br>Add New Session</a> |
|
||||
</div> |
|
||||
</td> |
|
||||
<td> |
|
||||
<div class="big-square-btn text-center"> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#addSessionModal" class="btn btn-outline-secondary d-block px-2 py-5"><i class="fa fa-plus mb-3"></i><br>Add New Session</a> |
|
||||
</div> |
|
||||
</td> |
|
||||
<td> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Berkan Şaşmaz</span> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#editSessionModal" class="mt-3 d-block text-info"><small><i class="fa fa-edit me-1"></i>Edit</small></a> |
|
||||
</div> |
|
||||
<div class="big-square-btn text-center"> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#addSessionModal" class="btn btn-outline-secondary d-block px-2 py-5"><i class="fa fa-plus mb-3"></i><br>Add New Session</a> |
|
||||
</div> |
|
||||
</td> |
|
||||
<td> |
|
||||
<div class="big-square-btn text-center"> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#addSessionModal" class="btn btn-outline-secondary d-block px-2 py-5"><i class="fa fa-plus mb-3"></i><br>Add New Session</a> |
|
||||
</div> |
|
||||
</td> |
|
||||
</tr> |
|
||||
|
|
||||
</tbody> |
|
||||
</table> |
|
||||
</div> |
|
||||
<div class="card-footer bg-white border-0 p-5 pt-1"> |
|
||||
<div class="row"> |
|
||||
<div class="col-6"> |
|
||||
<a href="#" class="btn btn-secondary"><i class="fa fa-arrow-left me-2"></i> Previous Step </a> |
|
||||
</div> |
|
||||
<div class="col-6 text-end"> |
|
||||
<a href="#" class="btn btn-outline-secondary me-2">Save as Draft</a> |
|
||||
<a href="#" class="btn btn-success">Publish <i class="fa fa-arrow-right ms-2"></i></a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Event Preview --> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-10 mx-auto"> |
|
||||
<div class="card"> |
|
||||
<div class="card-body profile-content p-5" style="min-height: 480px;"> |
|
||||
<h2 class="mb-5">Event Preview</h2> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>Organization Name:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<span class="preview-item">Volosoft</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>Title:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<span class="preview-item">My pretty cool event</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>Start Date:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<span class="preview-item">10/08/2025 - 09:00</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>End Date:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<span class="preview-item">10/08/2025 - 10:00</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>Event’s Explanation:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<p class="preview-item">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod |
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim |
|
||||
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea |
|
||||
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate |
|
||||
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat |
|
||||
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id |
|
||||
est laborum.</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>Cover Image:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<img src="https://api.openeventhub.com/api/eventhub/event/cover-image/3a003fb9-611a-db0c-82b2-7299ff8e8ce7" class="w-100 rounded-3"> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>Country:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<span class="preview-item">Turkey</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>City:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<span class="preview-item">Istanbul</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>Language:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<span class="preview-item">English</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>Capacity:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<span class="preview-item">100+</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>Event Type:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<span class="preview-item">Online</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>Tracks:</span> |
|
||||
</div> |
|
||||
<div class="col-md-8"> |
|
||||
<span class="preview-item">4</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="row mb-4"> |
|
||||
<div class="col-md-4"> |
|
||||
<span>Sessions:</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<table class="table"> |
|
||||
<thead> |
|
||||
<tr> |
|
||||
<th class="text-center" width="25%">Track 1</th> |
|
||||
<th class="text-center" width="25%">Track 1</th> |
|
||||
<th class="text-center" width="25%">Track 1</th> |
|
||||
<th class="text-center" width="25%">Track 1</th> |
|
||||
</tr> |
|
||||
</thead> |
|
||||
<tbody> |
|
||||
<tr> |
|
||||
<td> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
</td> |
|
||||
<td> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
</td> |
|
||||
<td> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
</td> |
|
||||
<td> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
<div class="track-item"> |
|
||||
<span class="track-name">Session Title</span> |
|
||||
<small class="text-primary d-block my-2">09:00 - 10:00 | English</small> |
|
||||
<span class="d-block mb-2">Halil İbrahim Kalkan</span> |
|
||||
</div> |
|
||||
</td> |
|
||||
</tr> |
|
||||
|
|
||||
</tbody> |
|
||||
</table> |
|
||||
</div> |
|
||||
<div class="card-footer bg-white border-0 p-5 pt-1"> |
|
||||
<div class="row"> |
|
||||
<div class="col-6"> |
|
||||
<a href="#" class="btn btn-secondary"><i class="fa fa-arrow-left me-2"></i> Previous Step </a> |
|
||||
</div> |
|
||||
<div class="col-6 text-end"> |
|
||||
<a href="#" class="btn btn-outline-secondary me-2">Save as Draft</a> |
|
||||
<a href="#" class="btn btn-success">Publish <i class="fa fa-arrow-right ms-2"></i></a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</main> |
|
||||
|
|
||||
<!-- Add Track Modal --> |
|
||||
<div class="modal fade" id="addTrackModal" tabindex="-1" aria-labelledby="addTrackModal" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-dialog-centered"> |
|
||||
<div class="modal-content"> |
|
||||
<div class="modal-header border-0 p-5 pb-2"> |
|
||||
<h5 class="modal-title">Add New Track</h5> |
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
|
||||
</div> |
|
||||
<div class="modal-body profile-content px-5"> |
|
||||
<div class="form-floating"> |
|
||||
<input type="text" class="form-control" id="TrackName" placeholder=" "> |
|
||||
<label for="TrackName">Track Name</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="modal-footer border-0 p-5 pt-2"> |
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> |
|
||||
<button type="button" class="btn btn-primary"><i class="fa fa-plus me-2"></i>Add</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Edit Track Modal --> |
|
||||
<div class="modal fade" id="editTrackModal" tabindex="-1" aria-labelledby="editTrackModal" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-dialog-centered"> |
|
||||
<div class="modal-content"> |
|
||||
<div class="modal-header border-0 p-5 pb-2"> |
|
||||
<h5 class="modal-title">Edit This Track</h5> |
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
|
||||
</div> |
|
||||
<div class="modal-body profile-content px-5"> |
|
||||
<div class="form"> |
|
||||
<label for="TrackName" class="mb-2">Edit Track Name</label> |
|
||||
<input type="text" class="form-control" id="TrackName" placeholder="There is a track name here"> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="modal-footer border-0 p-5 pt-2"> |
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> |
|
||||
<button type="button" class="btn btn-primary"><i class="fa fa-check-circle me-2"></i>Save</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Add Session Modal --> |
|
||||
<div class="modal fade" id="addSessionModal" tabindex="-1" aria-labelledby="addSessionModal" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-dialog-centered"> |
|
||||
<div class="modal-content"> |
|
||||
<div class="modal-header border-0 p-5 pb-2"> |
|
||||
<h5 class="modal-title">Add New Session</h5> |
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
|
||||
</div> |
|
||||
<div class="modal-body profile-content px-5"> |
|
||||
<div class="form-floating mb-3"> |
|
||||
<input type="text" class="form-control" id="Title2" placeholder=" "> |
|
||||
<label for="Title2">Title</label> |
|
||||
</div> |
|
||||
<div class="form-floating mb-3"> |
|
||||
<input type="text" class="form-control" id="StartTime2" placeholder=" "> |
|
||||
<label for="StartTime2">Start Time</label> |
|
||||
</div> |
|
||||
<div class="form-floating mb-3"> |
|
||||
<input type="text" class="form-control" id="EndTime2" placeholder=" "> |
|
||||
<label for="EndTime2">End Time</label> |
|
||||
</div> |
|
||||
<div class="form-floating mb-3"> |
|
||||
<input type="text" class="form-control" id="Language2" placeholder=" "> |
|
||||
<label for="Language2">Language</label> |
|
||||
</div> |
|
||||
<div class="form-floating mb-3"> |
|
||||
<input type="text" class="form-control" id="Speakers" placeholder=" "> |
|
||||
<label for="Speakers">Speakers</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="modal-footer border-0 p-5 pt-2"> |
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> |
|
||||
<button type="button" class="btn btn-primary"><i class="fa fa-plus me-2"></i>Add</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<!-- Edit Session Modal --> |
|
||||
<div class="modal fade" id="editSessionModal" tabindex="-1" aria-labelledby="editSessionModal" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-dialog-centered"> |
|
||||
<div class="modal-content"> |
|
||||
<div class="modal-header border-0 p-5 pb-2"> |
|
||||
<h5 class="modal-title">Edit This Session</h5> |
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
|
||||
</div> |
|
||||
<div class="modal-body profile-content px-5"> |
|
||||
<div class="form mb-3"> |
|
||||
<label for="Title2">Title</label> |
|
||||
<input type="text" class="form-control" id="Title2" placeholder="Lorem Upsym Title"> |
|
||||
</div> |
|
||||
<div class="form mb-3"> |
|
||||
<label for="StartTime2">Start Time</label> |
|
||||
<input type="text" class="form-control" id="StartTime2" placeholder="09:00"> |
|
||||
</div> |
|
||||
<div class="form mb-3"> |
|
||||
<label for="EndTime2">End Time</label> |
|
||||
<input type="text" class="form-control" id="EndTime2" placeholder="10:00"> |
|
||||
</div> |
|
||||
<div class="form mb-3"> |
|
||||
<label for="Language2">Language</label> |
|
||||
<input type="text" class="form-control" id="Language2" placeholder="English"> |
|
||||
</div> |
|
||||
<div class="form mb-3"> |
|
||||
<label for="Speakers">Speakers</label> |
|
||||
<input type="text" class="form-control" id="Speakers" placeholder="@@hikalkan"> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="modal-footer border-0 p-5 pt-2"> |
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> |
|
||||
<button type="button" class="btn btn-primary"><i class="fa fa-check-circle me-2"></i>Save</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
<!-- Pricing --> |
|
||||
<main class="static-page container mt-5"> |
|
||||
<h1 class="text-center mb-3">Eventhub Pricing List</h1> |
|
||||
<p class="text-center mb-5">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ut nulla consequat, tempus sapien in, |
|
||||
pellentesque nunc. Sed at nunc pellentesque, fermentum mi et, fermentum massa. </p> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="card"> |
|
||||
<div class="card-body px-4 py-4 text-center"> |
|
||||
<h2 class="mt-4">Normal Account</h2> |
|
||||
<p class="my-4">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam utnulla consequat, tempus sapien in.</p> |
|
||||
<div class="price mb-4"> |
|
||||
<small>$</small> |
|
||||
<span>0</span> |
|
||||
</div> |
|
||||
<ul class="list-check-icon mb-4 text-start"> |
|
||||
<li><i class="fa fa-check-circle"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit. </li> |
|
||||
<li><i class="fa fa-check-circle"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit. </li> |
|
||||
<li><i class="fa fa-check-circle"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit. </li> |
|
||||
</ul> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="card"> |
|
||||
<div class="card-body px-4 py-4 text-center"> |
|
||||
<h2 class="mt-4">Premium Account</h2> |
|
||||
<p class="my-4">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam utnulla consequat, tempus sapien in.</p> |
|
||||
<div class="price mb-4"> |
|
||||
<small>$</small> |
|
||||
<span>60</span> |
|
||||
</div> |
|
||||
<ul class="list-check-icon mb-4 text-start"> |
|
||||
<li><i class="fa fa-check-circle"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit. </li> |
|
||||
<li><i class="fa fa-check-circle"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit. </li> |
|
||||
<li><i class="fa fa-check-circle"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit adipiscing elit. </li> |
|
||||
<li><i class="fa fa-check-circle"></i> Lorem ipsum adipiscing elit dolor sit amet, consectetur adipiscing elit. </li> |
|
||||
<li><i class="fa fa-check-circle"></i> Lorem adipiscing elit adipiscing elitipsum dolor sit amet, consectetur adipiscing elit. </li> |
|
||||
<li><i class="fa fa-check-circle"></i> Lorem ipsum dolor sit amet, consectetur adipiscing elit. </li> |
|
||||
</ul> |
|
||||
<a href="#" class="btn btn-info my-4"><i class="fas fa-crown me-2"></i> Upgrade to Premium</a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<h2 class="text-center mb-3">Frequently Asked Questions</h2> |
|
||||
|
|
||||
<div id="accordion" class="mb-5 pb-5 faq-container"> |
|
||||
<div class="faq shown" data-anchor-id="accordion1"> |
|
||||
<div class="faq-header"> |
|
||||
<h5><button class="btn btn-faq" data-bs-toggle="collapse" data-bs-target="#accordion1" aria-expanded="false" aria-controls="accordion1">Lorem ipsum dolor sit amet, consectetur adipiscing elit?<i class="fas fa-chevron-up"></i> </button></h5> |
|
||||
</div> |
|
||||
<div id="accordion1" class="collapse show" data-bs-parent="#accordion" style=""> |
|
||||
<div class="faq-body"> |
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit. |
|
||||
</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="faq" data-anchor-id="accordion12"> |
|
||||
<div class="faq-header"> |
|
||||
<h5><button class="btn btn-faq collapsed" data-bs-toggle="collapse" data-bs-target="#accordion12" aria-expanded="false" aria-controls="accordion12">What onsectetur adipiscinglor sit amet?<i class="fas fa-chevron-up"></i> </button></h5> |
|
||||
</div> |
|
||||
<div id="accordion12" class="collapse" data-bs-parent="#accordion" style=""> |
|
||||
<div class="faq-body"> |
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit. |
|
||||
</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="faq" data-anchor-id="accordion123"> |
|
||||
<div class="faq-header"> |
|
||||
<h5><button class="btn btn-faq collapsed" data-bs-toggle="collapse" data-bs-target="#accordion123" aria-expanded="false" aria-controls="accordion123">What onsectetur adipiscing elit. Lorem ipsum dolor sit amet?<i class="fas fa-chevron-up"></i> </button></h5> |
|
||||
</div> |
|
||||
<div id="accordion123" class="collapse" data-bs-parent="#accordion" style=""> |
|
||||
<div class="faq-body"> |
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. |
|
||||
</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="faq" data-anchor-id="accordion124"> |
|
||||
<div class="faq-header"> |
|
||||
<h5><button class="btn btn-faq collapsed" data-bs-toggle="collapse" data-bs-target="#accordion124" aria-expanded="false" aria-controls="accordion124">Asectetur adipiscing elorem ipsum dolor sit amet?<i class="fas fa-chevron-up"></i> </button></h5> |
|
||||
</div> |
|
||||
<div id="accordion124" class="collapse" data-bs-parent="#accordion" style=""> |
|
||||
<div class="faq-body"> |
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit. |
|
||||
</p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</main> |
|
||||
|
|
||||
<!-- Cart --> |
|
||||
<main class="static-page container mt-5"> |
|
||||
<h1 class="text-center mb-3">Title Cart</h1> |
|
||||
<div class="row"> |
|
||||
<div class="col-md-7"> |
|
||||
<div class="card"> |
|
||||
<div class="card-body px-5 py-4"> |
|
||||
<h2 class="my-4">Product Detail</h2> |
|
||||
<h3 class="my-4">Premium Account: <span class="text-primary">Volosoft Company</span></h2> |
|
||||
<p>Start Date: <span class="text-dark">02/11/2020</span></p> |
|
||||
<p>End Date: <span class="text-dark">02/11/2020</span></p> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-5"> |
|
||||
<div class="card"> |
|
||||
<div class="card-body px-5 py-4"> |
|
||||
<h2 class="mt-4">Summary</h2> |
|
||||
<div class="cart-summary pt-3 pb-2"> |
|
||||
<p class="my-4">Premium Licence <span class="text-dark float-end">02/11/2020</span></p> |
|
||||
<hr> |
|
||||
<p class="my-4">TOTAL <span class="text-dark float-end">02/11/2020</span></p> |
|
||||
</div> |
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#cardModal" class="btn btn-info d-block my-4">Checkout</a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</main> |
|
||||
|
|
||||
<!-- Cart Modal --> |
|
||||
<div class="modal fade" id="cardModal" tabindex="-1" aria-labelledby="cardModal" aria-hidden="true"> |
|
||||
<div class="modal-dialog modal-dialog-centered"> |
|
||||
<div class="modal-content"> |
|
||||
<div class="modal-header border-0 p-5 pb-2"> |
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
|
||||
</div> |
|
||||
<div class="modal-body px-5"> |
|
||||
<i class="fa fa-check-circle modal-icon"></i> |
|
||||
<h5 class="modal-title text-center">Thank you for your perchase!</h5> |
|
||||
<p class="text-center">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam utnulla consequat.</p> |
|
||||
</div> |
|
||||
<div class="modal-footer border-0 p-5 pt-2"> |
|
||||
<button type="button" class="btn btn-info w-100" data-bs-dismiss="modal">Close</button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
@ -1,10 +0,0 @@ |
|||||
namespace EventHub.Web.Pages |
|
||||
{ |
|
||||
public class Empty : EventHubPageModel |
|
||||
{ |
|
||||
public void OnGet() |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,214 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Globalization; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using EventHub.Events; |
||||
|
using EventHub.Organizations; |
||||
|
using EventHub.Web.Helpers; |
||||
|
using JetBrains.Annotations; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.Rendering; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace EventHub.Web.Pages.Events.Components.CreateOrEditEventArea; |
||||
|
|
||||
|
[Widget( |
||||
|
AutoInitialize = true, |
||||
|
RefreshUrl = "/Widgets/CreateOrEditEventArea", |
||||
|
ScriptFiles = new[] { "/Pages/Events/Components/CreateOrEditEventArea/create-or-edit-event-area.js" }, |
||||
|
StyleFiles = new[] { "/Pages/Events/Components/CreateOrEditEventArea/create-or-edit-event-area.css" } |
||||
|
)] |
||||
|
public class CreateOrEditEventAreaViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
private readonly IEventAppService _eventAppService; |
||||
|
private readonly IOrganizationAppService _organizationAppService; |
||||
|
|
||||
|
private readonly ICurrentUser _currentUser; |
||||
|
|
||||
|
public CreateOrEditEventAreaViewComponent( |
||||
|
IEventAppService eventAppService, |
||||
|
IOrganizationAppService organizationAppService, |
||||
|
ICurrentUser currentUser) |
||||
|
{ |
||||
|
_eventAppService = eventAppService; |
||||
|
_organizationAppService = organizationAppService; |
||||
|
_currentUser = currentUser; |
||||
|
} |
||||
|
|
||||
|
public async Task<IViewComponentResult> InvokeAsync( |
||||
|
string eventUrlCode, |
||||
|
ProgressStepType stepType = ProgressStepType.Event) |
||||
|
{ |
||||
|
NewEventViewModel model = null; |
||||
|
if (!eventUrlCode.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
var @event = await _eventAppService.GetByUrlCodeAsync(eventUrlCode); |
||||
|
model = ObjectMapper.Map<EventDetailDto, NewEventViewModel>(@event); |
||||
|
ViewData["EventId"] = @event.Id; |
||||
|
ViewData["EventUrlCode"] = @event.UrlCode; |
||||
|
} |
||||
|
|
||||
|
model ??= new NewEventViewModel |
||||
|
{ |
||||
|
StartTime = DateTime.Now.ClearTime().AddDays(1).AddHours(19), |
||||
|
EndTime = DateTime.Now.ClearTime().AddDays(2).AddHours(21) |
||||
|
}; |
||||
|
|
||||
|
await FillViewDataAsync(stepType, model); |
||||
|
|
||||
|
return View("~/Pages/Events/Components/CreateOrEditEventArea/Default.cshtml", model); |
||||
|
} |
||||
|
|
||||
|
private async Task<string> GetOrganizationNameAsync(Guid organizationId) |
||||
|
{ |
||||
|
var organizationList = (await _organizationAppService.GetOrganizationsByUserIdAsync(_currentUser.GetId())).Items; |
||||
|
|
||||
|
return organizationList.Single(x => x.Id == organizationId).Name; |
||||
|
} |
||||
|
|
||||
|
private async Task<List<SelectListItem>> GetOrganizationsSelectItemAsync() |
||||
|
{ |
||||
|
var result = await _organizationAppService.GetOrganizationsByUserIdAsync(_currentUser.GetId()); |
||||
|
|
||||
|
return result.Items.Select( |
||||
|
organization => new SelectListItem |
||||
|
{ |
||||
|
Value = organization.Id.ToString(), |
||||
|
Text = organization.DisplayName |
||||
|
} |
||||
|
).ToList(); |
||||
|
} |
||||
|
|
||||
|
private async Task<string> GetCountryNameAsync(Guid countryId) |
||||
|
{ |
||||
|
var countries = await _eventAppService.GetCountriesLookupAsync(); |
||||
|
|
||||
|
return countries.Single(x => x.Id == countryId).Name; |
||||
|
} |
||||
|
|
||||
|
private async Task<List<SelectListItem>> GetCountriesSelectItemAsync() |
||||
|
{ |
||||
|
var result = await _eventAppService.GetCountriesLookupAsync(); |
||||
|
|
||||
|
return result.Select( |
||||
|
country => new SelectListItem |
||||
|
{ |
||||
|
Value = country.Id.ToString(), |
||||
|
Text = country.Name |
||||
|
} |
||||
|
).ToList(); |
||||
|
} |
||||
|
|
||||
|
private List<SelectListItem> GetLanguagesSelectItem() |
||||
|
{ |
||||
|
var result = CultureInfo.GetCultures(CultureTypes.NeutralCultures) |
||||
|
.DistinctBy(x => x.EnglishName) |
||||
|
.OrderBy(x => x.EnglishName) |
||||
|
.ToList(); |
||||
|
result.Remove(result.Single(x => x.TwoLetterISOLanguageName == "iv")); // Invariant Language
|
||||
|
|
||||
|
return result.Select( |
||||
|
cultureInfo => new SelectListItem |
||||
|
{ |
||||
|
Value = cultureInfo.TwoLetterISOLanguageName, |
||||
|
Text = cultureInfo.EnglishName |
||||
|
} |
||||
|
).ToList(); |
||||
|
} |
||||
|
|
||||
|
private async Task FillViewDataAsync(ProgressStepType stepType, NewEventViewModel model) |
||||
|
{ |
||||
|
ViewData["StepType"] = stepType.ToString(); |
||||
|
switch (stepType) |
||||
|
{ |
||||
|
case ProgressStepType.Event: |
||||
|
ViewData["Organizations"] = await GetOrganizationsSelectItemAsync(); |
||||
|
ViewData["Countries"] = await GetCountriesSelectItemAsync(); |
||||
|
ViewData["Languages"] = GetLanguagesSelectItem(); |
||||
|
break; |
||||
|
case ProgressStepType.Session: |
||||
|
ViewData["Languages"] = GetLanguagesSelectItem(); |
||||
|
break; |
||||
|
case ProgressStepType.Preview: |
||||
|
ViewData["OrganizationName"] = await GetOrganizationNameAsync(model.OrganizationId); |
||||
|
if (model.CountryId is not null) |
||||
|
{ |
||||
|
ViewData["CountryName"] = await GetCountryNameAsync(model.CountryId!.Value); |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class NewEventViewModel |
||||
|
{ |
||||
|
[SelectItems(nameof(Organizations))] |
||||
|
[DisplayName("Organization")] |
||||
|
public Guid OrganizationId { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[StringLength(EventConsts.MaxTitleLength, MinimumLength = EventConsts.MinTitleLength)] |
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DataType(DataType.DateTime)] |
||||
|
public DateTime StartTime { get; set; } = DateTime.Now; |
||||
|
|
||||
|
[Required] |
||||
|
[DataType(DataType.DateTime)] |
||||
|
public DateTime EndTime { get; set; } = DateTime.Now; |
||||
|
|
||||
|
[Required] |
||||
|
[StringLength(EventConsts.MaxDescriptionLength, MinimumLength = EventConsts.MinDescriptionLength)] |
||||
|
[TextArea] |
||||
|
public string Description { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
[Display(Name = "Cover Image")] |
||||
|
[DataType(DataType.Upload)] |
||||
|
[MaxFileSize(EventConsts.MaxCoverImageFileSize)] |
||||
|
[AllowedExtensions(new string[] { ".jpg", ".png", ".jpeg" })] |
||||
|
public IFormFile CoverImageFile { get; set; } |
||||
|
|
||||
|
[Required] public bool? IsOnline { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
[StringLength(EventConsts.MaxOnlineLinkLength, MinimumLength = EventConsts.MinOnlineLinkLength)] |
||||
|
public string OnlineLink { get; set; } |
||||
|
|
||||
|
[SelectItems(nameof(Countries))] |
||||
|
[DisplayName("Country")] |
||||
|
public Guid? CountryId { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
[StringLength(EventConsts.MaxCityLength, MinimumLength = EventConsts.MinCityLength)] |
||||
|
public string City { get; set; } |
||||
|
|
||||
|
[DisplayName("Language")] |
||||
|
public string Language { get; set; } |
||||
|
|
||||
|
[Range(1, int.MaxValue)] |
||||
|
public int? Capacity { get; set; } |
||||
|
|
||||
|
public List<TrackDto> Tracks { get; set; } |
||||
|
|
||||
|
public NewEventViewModel() |
||||
|
{ |
||||
|
Tracks = new List<TrackDto>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public enum ProgressStepType : byte |
||||
|
{ |
||||
|
Event = 0, |
||||
|
Track, |
||||
|
Session, |
||||
|
Preview |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea |
||||
|
@using Microsoft.AspNetCore.Http |
||||
|
@model EventHub.Web.Pages.Events.Components.CreateOrEditEventArea.CreateOrEditEventAreaViewComponent.NewEventViewModel |
||||
|
|
||||
|
@{ |
||||
|
if (Model is null) |
||||
|
{ |
||||
|
throw new BadHttpRequestException(""); |
||||
|
} |
||||
|
|
||||
|
var eventId = ViewData["EventId"] as Guid?; |
||||
|
var eventUrlCode = ViewData["EventUrlCode"]?.ToString(); |
||||
|
|
||||
|
var result = Enum.TryParse(ViewData["StepType"]!.ToString(), out CreateOrEditEventAreaViewComponent.ProgressStepType stepType); |
||||
|
if (!result) |
||||
|
{ |
||||
|
throw new BadHttpRequestException(""); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
<div id="EventContainer" style="@(stepType != CreateOrEditEventAreaViewComponent.ProgressStepType.Event ? "display: none" : "")"> |
||||
|
<partial name="_eventSection.cshtml" model="@Model"/> |
||||
|
</div> |
||||
|
<div id="TrackContainer" style="@(stepType != CreateOrEditEventAreaViewComponent.ProgressStepType.Track ? "display: none" : "")"> |
||||
|
<partial name="_trackSection.cshtml" model="@Model.Tracks"/> |
||||
|
</div> |
||||
|
<div id="SessionContainer" style="@(stepType != CreateOrEditEventAreaViewComponent.ProgressStepType.Session ? "display: none" : "")"> |
||||
|
<partial name="_sessionSection.cshtml" model="@Model.Tracks"/> |
||||
|
</div> |
||||
|
<div id="PreviewContainer" style="@(stepType != CreateOrEditEventAreaViewComponent.ProgressStepType.Preview ? "display: none" : "")"> |
||||
|
<partial name="_previewSection.cshtml" model="@Model"/> |
||||
|
</div> |
||||
|
|
||||
|
<input type="hidden" id="EventId" value="@eventId"/> |
||||
|
<input type="hidden" id="EventUrlCode" value="@eventUrlCode"/> |
||||
@ -0,0 +1,170 @@ |
|||||
|
@using EventHub.Web |
||||
|
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea |
||||
|
@using Microsoft.AspNetCore.Http |
||||
|
@using Microsoft.Extensions.Options |
||||
|
@model EventHub.Web.Pages.Events.Components.CreateOrEditEventArea.CreateOrEditEventAreaViewComponent.NewEventViewModel |
||||
|
@inject IOptions<EventHubUrlOptions> UrlOptions |
||||
|
|
||||
|
@{ |
||||
|
var organizations = new List<SelectListItem>(); |
||||
|
var countries = new List<SelectListItem>(); |
||||
|
var languages = new List<SelectListItem>(); |
||||
|
var eventId = ViewData["EventId"] as Guid?; |
||||
|
|
||||
|
@if (ViewData["StepType"]!.ToString() == CreateOrEditEventAreaViewComponent.ProgressStepType.Event.ToString()) |
||||
|
{ |
||||
|
organizations = ViewData["Organizations"] as List<SelectListItem>; |
||||
|
if (organizations is null || !organizations.Any()) |
||||
|
{ |
||||
|
throw new BadHttpRequestException("There is no organization"); |
||||
|
} |
||||
|
|
||||
|
countries = ViewData["Countries"] as List<SelectListItem>; |
||||
|
if (countries is null || !countries.Any()) |
||||
|
{ |
||||
|
throw new BadHttpRequestException("There is no country"); |
||||
|
} |
||||
|
|
||||
|
languages = ViewData["Languages"] as List<SelectListItem>; |
||||
|
if (languages is null || !languages.Any()) |
||||
|
{ |
||||
|
throw new BadHttpRequestException("There is no language"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
<partial name="_progressSection.cshtml" model="@CreateOrEditEventAreaViewComponent.ProgressStepType.Event" /> |
||||
|
@if (Model is not null) |
||||
|
{ |
||||
|
<form id="CreateEventForm" method="post" enctype="multipart/form-data"> |
||||
|
<div class="container pt-4"> |
||||
|
<div class="row py-4"> |
||||
|
<div class="col-md-9 mx-auto profile-content"> |
||||
|
<div class="card"> |
||||
|
<div class="card-body" style="min-height: 496px"> |
||||
|
<h3 class="mb-4">@(eventId.HasValue ? "Edit" : "Create New") Event</h3> |
||||
|
<div class="form"> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="form-label-group"> |
||||
|
<select asp-for="@Model.OrganizationId" asp-items="organizations" class="form-select"> |
||||
|
@if (organizations.Count > 1) |
||||
|
{ |
||||
|
<option selected value="">Pick an organization</option> |
||||
|
} |
||||
|
</select> |
||||
|
<span asp-validation-for="@Model.OrganizationId" class="text-danger"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="form-label-group"> |
||||
|
<input type="text" id="inputTitle" asp-for="@Model.Title" class="form-control" placeholder="Title"> |
||||
|
<label for="inputTitle">Title</label> |
||||
|
<span asp-validation-for="@Model.Title" class="text-danger"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="form-label-group"> |
||||
|
<input id="inputStartdate" asp-for="@Model.StartTime" class="form-control" placeholder="Start Date"> |
||||
|
<label for="inputStartdate">Start Date</label> |
||||
|
<span asp-validation-for="@Model.StartTime" class="text-danger"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="form-label-group"> |
||||
|
<input id="inputEnddate" asp-for="@Model.EndTime" class="form-control" placeholder="End Date"> |
||||
|
<label for="inputEnddate">End Date</label> |
||||
|
<span asp-validation-for="@Model.EndTime" class="text-danger"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-12"> |
||||
|
<div class="form-label-group"> |
||||
|
<textarea type="text" id="inputDescription" asp-for="@Model.Description" class="form-control" placeholder="Description"></textarea> |
||||
|
<span asp-validation-for="@Model.Description" class="text-danger"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-12"> |
||||
|
<h4 class="mb-4">Cover Image</h4> |
||||
|
<div class="row"> |
||||
|
<div class="col-6"> |
||||
|
@if (eventId.HasValue) |
||||
|
{ |
||||
|
<div class="image-area event-thumbnail img-fluid rounded shadow-sm mx-auto d-block" style="background-image: url(@(UrlOptions.Value.Api.EnsureEndsWith('/') + $"api/eventhub/event/cover-image/{eventId}")" alt="@Model.Title"></div> |
||||
|
<div class="image-area result-area" style="display: none"><img id="imageResult" src="#" alt="" class="img-fluid rounded shadow-sm mx-auto d-block"></div> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<div class="image-area"><img id="imageResult" src="#" alt="" class="img-fluid rounded shadow-sm mx-auto d-block"></div> |
||||
|
} |
||||
|
|
||||
|
</div> |
||||
|
<div class="col-6"> |
||||
|
<div> |
||||
|
<p class="mb-3">For horizontal format 600x400 sized upload images.</p> |
||||
|
<input type="file" id="Event_CoverImageFile" asp-for="@Model.CoverImageFile" class="form-control border-0" hidden> |
||||
|
<label id="upload-label" for="Event_CoverImageFile" class="btn btn-primary btn-lg text-white">Choose file</label> |
||||
|
<span asp-validation-for="@Model.CoverImageFile" class="text-danger"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<select class="form-select" asp-for="@Model.IsOnline"> |
||||
|
<option selected="selected" value="">Event Type</option> |
||||
|
<option value="@Boolean.TrueString">Online</option> |
||||
|
<option value="@Boolean.FalseString">In Person</option> |
||||
|
</select> |
||||
|
<span asp-validation-for="@Model.IsOnline" class="text-danger"></span> |
||||
|
</div> |
||||
|
<div class="col-md-6 event-link-group" style="display: none"> |
||||
|
<div class="form-label-group"> |
||||
|
<input type="text" id="inputOnlineLink" asp-for="@Model.OnlineLink" class="form-control" placeholder="Online Link"> |
||||
|
<label for="inputOnlineLink">Online Link</label> |
||||
|
<span asp-validation-for="@Model.OnlineLink" class="text-danger"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="form-label-group"> |
||||
|
<input type="number" id="inputCapacity" asp-for="@Model.Capacity" class="form-control" placeholder="Capacity"> |
||||
|
<label for="inputCapacity">Capacity</label> |
||||
|
<span asp-validation-for="@Model.Capacity" class="text-danger"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6 event-location-group"> |
||||
|
<select asp-for="@Model.CountryId" asp-items="countries" class="form-select"> |
||||
|
<option selected="" value="">Country</option> |
||||
|
</select> |
||||
|
<span asp-validation-for="@Model.CountryId" class="text-danger"></span> |
||||
|
</div> |
||||
|
<div class="col-md-6 event-location-group"> |
||||
|
<div class="form-label-group"> |
||||
|
<input type="text" id="inputCity" asp-for="@Model.City" class="form-control" placeholder="City"> |
||||
|
<label for="inputCity">City</label> |
||||
|
<span asp-validation-for="@Model.City" class="text-danger"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<select asp-for="@Model.Language" asp-items="languages" aria-label="en" class="form-select"> |
||||
|
<option selected value="">Language</option> |
||||
|
</select> |
||||
|
<span asp-validation-for="@Model.Language" class="text-danger"></span> |
||||
|
</div> |
||||
|
<div class="col-md-12 text-end"> |
||||
|
<button id="CreateEventButton" disabled type="submit" class="btn btn-primary btn-lg" |
||||
|
data-url="@(eventId.HasValue ? Url.ActionLink("Update", "Event", new {Area = "eventhub", id = eventId!.Value}, null) : Url.ActionLink("Create", "Event", new {Area = "eventhub"}, null))"> |
||||
|
Next Step <i class="fa fa-arrow-right ms-2"></i> |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</form> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<partial name="_modelNullErrorSection.cshtml" /> |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<div class="text-center mt-5"> |
||||
|
<h3><i class="fas fa-exclamation-circle"></i> An unknown error has occurred!</h3> |
||||
|
</div> |
||||
@ -0,0 +1,231 @@ |
|||||
|
@using EventHub.Web |
||||
|
@using EventHub.Web.Pages.Events |
||||
|
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea |
||||
|
@using Microsoft.AspNetCore.Http |
||||
|
@using Microsoft.Extensions.Options |
||||
|
@model EventHub.Web.Pages.Events.Components.CreateOrEditEventArea.CreateOrEditEventAreaViewComponent.NewEventViewModel |
||||
|
@inject IOptions<EventHubUrlOptions> UrlOptions |
||||
|
|
||||
|
@{ |
||||
|
var organizationName = ""; |
||||
|
var countryName = ""; |
||||
|
Guid? eventId = null; |
||||
|
@if (ViewData["StepType"]!.ToString() == CreateOrEditEventAreaViewComponent.ProgressStepType.Preview.ToString()) |
||||
|
{ |
||||
|
eventId = ViewData["EventId"] as Guid?; |
||||
|
|
||||
|
organizationName = ViewData["OrganizationName"] as string; |
||||
|
if (organizationName.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
throw new BadHttpRequestException("Organization name cannot be empty!"); |
||||
|
} |
||||
|
|
||||
|
countryName = ViewData["CountryName"] as string; |
||||
|
if (Model is {CountryId: { } } && countryName.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
throw new BadHttpRequestException("Country name cannot be empty when CountryId exists!"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@if (Model is not null) |
||||
|
{ |
||||
|
<div class="row"> |
||||
|
<div class="col-md-10 mx-auto"> |
||||
|
<div class="card"> |
||||
|
<div class="card-body profile-content p-5" style="min-height: 480px;"> |
||||
|
<h2 class="mb-5">Event Preview</h2> |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Organization Name:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<span class="preview-item">@organizationName</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Title:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<span class="preview-item">@Model.Title</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Start Date:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<span class="preview-item">@Model.StartTime.ToShortDateString() - @Model.StartTime.ToShortTimeString()</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>End Date:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<span class="preview-item">@Model.EndTime.ToShortDateString() - @Model.EndTime.ToShortTimeString()</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Event’s Explanation:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<p class="preview-item">@Model.Description</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Cover Image:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<div class="w-100 rounded-3 event-thumbnail" style="background-image: url(@(UrlOptions.Value.Api.EnsureEndsWith('/') + $"api/eventhub/event/cover-image/{eventId}")" alt="@Model.Title"></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
@if (Model.IsOnline != null && Model.IsOnline!.Value) |
||||
|
{ |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Event Type:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<span class="preview-item">Online</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
@if (!Model.OnlineLink.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Url:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<span class="preview-item">@Model.OnlineLink</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
} |
||||
|
else if (Model.CountryId.HasValue && !Model.City.IsNullOrEmpty()) |
||||
|
{ |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Country:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<span class="preview-item">@countryName</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>City:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<span class="preview-item">@Model.City</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
@if (!Model.Language.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Language:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<span class="preview-item">@Model.Language</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
@if (Model.Capacity.HasValue) |
||||
|
{ |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Capacity:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<span class="preview-item">@Model.Capacity</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
@if (Model.Tracks.Any()) |
||||
|
{ |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Tracks:</span> |
||||
|
</div> |
||||
|
<div class="col-md-8"> |
||||
|
<span class="preview-item">@Model.Tracks.Count</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row mb-4"> |
||||
|
<div class="col-md-4"> |
||||
|
<span>Sessions:</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<table class="table"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
@foreach (var track in Model.Tracks) |
||||
|
{ |
||||
|
<th class="text-center" width="25%">@track.Name</th> |
||||
|
} |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<tr> |
||||
|
@foreach (var track in Model.Tracks) |
||||
|
{ |
||||
|
<td> |
||||
|
@if (track.Sessions.Any()) |
||||
|
{ |
||||
|
@foreach (var session in track.Sessions) |
||||
|
{ |
||||
|
<div class="track-item"> |
||||
|
<span class="track-name">@session.Title.TruncateWithPostfix(55)</span> |
||||
|
<small class="text-primary d-block my-2">@EventDateHelper.GetTimeRangeText(TimeOnly.FromDateTime(session.StartTime), TimeOnly.FromDateTime(session.EndTime)) | @session.Language</small> |
||||
|
@foreach (var speaker in session.Speakers) |
||||
|
{ |
||||
|
<span class="d-block mb-2">@speaker.UserName</span> |
||||
|
} |
||||
|
</div> |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<div class="track-item text-center"> |
||||
|
<span class="track-name text-primary"><i class="fas fa-exclamation-circle"></i> There is no session!</span> |
||||
|
<span class="d-block mb-2 mt-3">Tracks without Session are not visible after the event is published.</span> |
||||
|
</div> |
||||
|
} |
||||
|
</td> |
||||
|
} |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
} |
||||
|
</div> |
||||
|
<div class="card-footer bg-white border-0 p-5 pt-1"> |
||||
|
<div class="row"> |
||||
|
<div class="col-6"> |
||||
|
@if (Model.Tracks.Any() && Model.Tracks.First().Sessions.Any()) |
||||
|
{ |
||||
|
<button id="PreviousStepButtonInPreviewSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Session" class="btn btn-secondary step-transition"><i class="fa fa-arrow-left me-2"></i> Previous Step </button> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<button id="PreviousStepButtonInPreviewSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Track" class="btn btn-secondary step-transition"><i class="fa fa-arrow-left me-2"></i> Previous Step </button> |
||||
|
} |
||||
|
</div> |
||||
|
<div class="col-6 text-end"> |
||||
|
<button id="PublishButton" class="btn btn-success">Publish <i class="fa fa-arrow-right ms-2"></i></button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<partial name="_modelNullErrorSection.cshtml" /> |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,20 @@ |
|||||
|
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea |
||||
|
@model EventHub.Web.Pages.Events.Components.CreateOrEditEventArea.CreateOrEditEventAreaViewComponent.ProgressStepType |
||||
|
|
||||
|
@{ |
||||
|
var eventId = ViewData["EventId"] as Guid?; |
||||
|
var prefixOfStep = eventId.HasValue ? "Edit" : "New"; |
||||
|
} |
||||
|
|
||||
|
<div class="px-4 py-1"> |
||||
|
<div class="progresses py-4"> |
||||
|
<ul class="d-flex align-items-center justify-content-between"> |
||||
|
<li id="step-1" class="create-steps @(Model == CreateOrEditEventAreaViewComponent.ProgressStepType.Event ? "blue" : "")">1<span>@prefixOfStep Event</span></li> |
||||
|
<li id="step-2" class="create-steps @(Model == CreateOrEditEventAreaViewComponent.ProgressStepType.Track ? "blue" : "")">2<span>@prefixOfStep Track</span></li> |
||||
|
<li id="step-3" class="create-steps @(Model == CreateOrEditEventAreaViewComponent.ProgressStepType.Session ? "blue" : "")">3<span>@prefixOfStep Session</span></li> |
||||
|
</ul> |
||||
|
<div class="progress"> |
||||
|
<div class="progress-bar" role="progressbar" style="width: 0%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
@ -0,0 +1,208 @@ |
|||||
|
@using EventHub.Web.Pages.Events |
||||
|
@using EventHub.Events |
||||
|
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea |
||||
|
@using Microsoft.AspNetCore.Http |
||||
|
@model List<EventHub.Events.TrackDto> |
||||
|
|
||||
|
@{ |
||||
|
var languages = new List<SelectListItem>(); |
||||
|
@if (ViewData["StepType"]!.ToString() == CreateOrEditEventAreaViewComponent.ProgressStepType.Session.ToString()) |
||||
|
{ |
||||
|
languages = ViewData["Languages"] as List<SelectListItem>; |
||||
|
if (languages is null || !languages.Any()) |
||||
|
{ |
||||
|
throw new BadHttpRequestException("There is no language"); |
||||
|
} |
||||
|
languages = languages.Select(l => |
||||
|
{ |
||||
|
if (l.Value == "en") |
||||
|
{ |
||||
|
l.Selected = true; |
||||
|
} |
||||
|
return l; |
||||
|
}).ToList(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
<partial name="_progressSection.cshtml" model="@CreateOrEditEventAreaViewComponent.ProgressStepType.Session" /> |
||||
|
|
||||
|
@if (Model is not null) |
||||
|
{ |
||||
|
<div class="row"> |
||||
|
<div class="col-md-10 mx-auto"> |
||||
|
<div class="card"> |
||||
|
<div class="card-body profile-content p-5" style="min-height: 480px;"> |
||||
|
<h2 class="mb-4">Add Session</h2> |
||||
|
<table class="table"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
@foreach (var track in Model) |
||||
|
{ |
||||
|
<th class="text-center" width="25%"> |
||||
|
@track.Name.TruncateWithPostfix(20) |
||||
|
</th> |
||||
|
} |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<tr> |
||||
|
@foreach (var track in Model) |
||||
|
{ |
||||
|
<td> |
||||
|
@foreach (var session in track.Sessions) |
||||
|
{ |
||||
|
<input type="hidden" id="TitleOfSession-@session.Id" value="@session.Title"/> |
||||
|
<input type="hidden" id="DescriptionOfSession-@session.Id" value="@session.Description"/> |
||||
|
<input type="datetime-local" id="StartTimeOfSession-@session.Id" value="@session.StartTime.ToString("s")" style="display: none"/> |
||||
|
<input type="datetime-local" id="EndTimeOfSession-@session.Id" value="@session.EndTime.ToString("s")" style="display: none"/> |
||||
|
<input type="hidden" id="LanguageOfSession-@session.Id" value="@session.Language"/> |
||||
|
<input type="hidden" id="SpeakersOfSession-@session.Id" value="@(session.Speakers.Any() ? string.Join(", ", session.Speakers.Select(x => x.UserName)).EnsureEndsWith(',').EnsureEndsWith(' ') : "")"/> |
||||
|
|
||||
|
<div class="track-item"> |
||||
|
<span class="track-name">@session.Title.TruncateWithPostfix(25)</span> |
||||
|
<small class="text-primary d-block my-2">@EventDateHelper.GetTimeRangeText(TimeOnly.FromDateTime(session.StartTime), TimeOnly.FromDateTime(session.EndTime)) | @session.Language</small> |
||||
|
@foreach (var speaker in session.Speakers) |
||||
|
{ |
||||
|
<span class="d-block mb-2">@speaker.UserName</span> |
||||
|
} |
||||
|
<abp-row> |
||||
|
<abp-column size="_5"> |
||||
|
<a id="@session.Id" data-track-id="@track.Id" href="javascript:;" data-bs-toggle="modal" data-bs-target="#EditSessionModal" class="mt-3 d-block text-info edit-session-button"> |
||||
|
<small><i class="fa fa-edit me-1"></i>Edit</small> |
||||
|
</a> |
||||
|
</abp-column> |
||||
|
<abp-column size="_6"> |
||||
|
<a id="@session.Id" data-track-id="@track.Id" href="javascript:;" class="mt-3 d-block text-info delete-session-button"> |
||||
|
<small><i class="fa fa-trash me-1"></i>Delete</small> |
||||
|
</a> |
||||
|
</abp-column> |
||||
|
</abp-row> |
||||
|
</div> |
||||
|
} |
||||
|
<div class="big-square-btn text-center"> |
||||
|
<a id="@track.Id-@track.Sessions.GetHashCode()" data-track-id="@track.Id" data-bs-toggle="modal" data-bs-target="#AddSessionModal" class="btn btn-outline-secondary d-block px-2 py-5 add-session-button"> |
||||
|
<i class="fa fa-plus mb-3"></i> |
||||
|
<br>Add New Session |
||||
|
</a> |
||||
|
</div> |
||||
|
</td> |
||||
|
} |
||||
|
</tr> |
||||
|
|
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
<div class="card-footer bg-white border-0 p-5 pt-1"> |
||||
|
<div class="row"> |
||||
|
<div class="col-6"> |
||||
|
<button id="PreviousStepButtonInSessionSection" |
||||
|
data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Track" |
||||
|
class="btn btn-secondary step-transition"><i class="fa fa-arrow-left me-2"></i> Previous |
||||
|
Step </button> |
||||
|
</div> |
||||
|
<div class="col-6 text-end"> |
||||
|
<button id="PreviewButtonInSessionSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Preview" class="btn btn-primary step-transition">Preview <i class="fa fa-arrow-right ms-2"></i></button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Add Session Modal --> |
||||
|
<div class="modal fade" id="AddSessionModal" tabindex="-1" aria-labelledby="AddSessionModal" aria-hidden="true"> |
||||
|
<div class="modal-dialog modal-dialog-centered"> |
||||
|
<div class="modal-content"> |
||||
|
<div class="modal-header border-0 p-5 pb-2"> |
||||
|
<h5 class="modal-title">Add New Session</h5> |
||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
||||
|
</div> |
||||
|
<form id="AddNewSessionForm"> |
||||
|
<input disabled type="hidden" id="TrackId" name="TrackId" value="TrackIdPlaceHolder" /> |
||||
|
<div class="modal-body profile-content px-5"> |
||||
|
<div class="form-floating mb-3"> |
||||
|
<input type="text" class="form-control" id="TitleInNewSessionModal" name="Title" placeholder=" " required minLength=@SessionConsts.MinTitleLength maxLength=@SessionConsts.MaxTitleLength /> |
||||
|
<label for="TitleInNewSessionModal">Title</label> |
||||
|
</div> |
||||
|
<div class="form-floating mb-3"> |
||||
|
<textarea type="text" class="form-control" id="DescriptionInNewSessionModal" name="Description" placeholder=" " required minLength=@SessionConsts.MinDescriptionLength maxLength=@SessionConsts.MaxDescriptionLength></textarea> |
||||
|
<label for="DescriptionInNewSessionModal">Description</label> |
||||
|
</div> |
||||
|
<div class="form-floating mb-3"> |
||||
|
<input type="datetime-local" class="form-control" id="StartTimeInNewSessionModal" name="StartTime" placeholder=" " required /> |
||||
|
<label for="StartTimeInNewSessionModal">Start Time</label> |
||||
|
</div> |
||||
|
<div class="form-floating mb-3"> |
||||
|
<input type="datetime-local" class="form-control" id="EndTimeInNewSessionModal" name="EndTime"placeholder=" " required /> |
||||
|
<label for="EndTimeInNewSessionModal">End Time</label> |
||||
|
</div> |
||||
|
<div class="form-floating mb-3"> |
||||
|
<select id="LanguageInNewSessionModal" name="Language" asp-items="languages" aria-label="en" class="form-select" required> |
||||
|
</select> |
||||
|
<label for="LanguageInNewSessionModal">Language</label> |
||||
|
</div> |
||||
|
<div class="form-floating mb-3"> |
||||
|
<input type="text" class="form-control" id="SpeakersInNewSessionModal" placeholder="Speakers" data-multiple /> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="modal-footer border-0 p-5 pt-2"> |
||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> |
||||
|
<button type="submit" class="btn btn-primary"><i class="fa fa-plus me-2"></i>Add</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Edit Session Modal --> |
||||
|
<div class="modal fade" id="EditSessionModal" tabindex="-1" aria-labelledby="EditSessionModal" aria-hidden="true"> |
||||
|
<div class="modal-dialog modal-dialog-centered"> |
||||
|
<div class="modal-content"> |
||||
|
<div class="modal-header border-0 p-5 pb-2"> |
||||
|
<h5 id="EditModalTitle" class="modal-title">Edit Session</h5> |
||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
||||
|
</div> |
||||
|
<form id="EditSessionForm"> |
||||
|
<input type="hidden" id="TrackId" value="TrackIdPlaceHolder"/> |
||||
|
<input type="hidden" id="SessionId" value="SessionIdPlaceHolder"/> |
||||
|
|
||||
|
<div class="modal-body profile-content px-5"> |
||||
|
<div class="form mb-3"> |
||||
|
<label for="TitleInEditSessionModal">Title</label> |
||||
|
<input type="text" class="form-control" id="TitleInEditSessionModal" name="Title" placeholder=" " required minLength=@SessionConsts.MinTitleLength maxLength=@SessionConsts.MaxTitleLength /> |
||||
|
</div> |
||||
|
<div class="form mb-3"> |
||||
|
<label for="DescriptionInEditSessionModal">Description</label> |
||||
|
<textarea type="text" class="form-control" id="DescriptionInEditSessionModal" name="Description" placeholder=" " required minLength=@SessionConsts.MinDescriptionLength maxLength=@SessionConsts.MaxDescriptionLength></textarea> |
||||
|
</div> |
||||
|
<div class="form mb-3"> |
||||
|
<label for="StartTimeInEditSessionModal">Start Time</label> |
||||
|
<input type="datetime-local" class="form-control" id="StartTimeInEditSessionModal" name="StartTime" placeholder=" " required /> |
||||
|
</div> |
||||
|
<div class="form mb-3"> |
||||
|
<label for="EndTimeInEditSessionModal">End Time</label> |
||||
|
<input type="datetime-local" class="form-control" id="EndTimeInEditSessionModal" name="EndTime" placeholder=" " required /> |
||||
|
</div> |
||||
|
<div class="form mb-3"> |
||||
|
<label for="LanguageInEditSessionModal">Language</label> |
||||
|
<select id="LanguageInEditSessionModal" name="Language" asp-items="languages" aria-label="en" class="form-select" required> |
||||
|
</select> |
||||
|
</div> |
||||
|
<div class="form mb-3"> |
||||
|
<label for="SpeakersInEditSessionModal">Speakers</label> |
||||
|
<input type="text" class="form-control" id="SpeakersInEditSessionModal" placeholder="Speakers" data-multiple /> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="modal-footer border-0 p-5 pt-2"> |
||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> |
||||
|
<button type="submit" class="btn btn-primary"><i class="fa fa-check-circle me-2"></i>Save</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<partial name="_modelNullErrorSection.cshtml" /> |
||||
|
} |
||||
@ -0,0 +1,105 @@ |
|||||
|
@using EventHub.Events |
||||
|
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea |
||||
|
@model List<EventHub.Events.TrackDto> |
||||
|
|
||||
|
<partial name="_progressSection.cshtml" model="@CreateOrEditEventAreaViewComponent.ProgressStepType.Track"/> |
||||
|
|
||||
|
@if (Model is not null) |
||||
|
{ |
||||
|
<div class="row"> |
||||
|
<div class="col-md-10 mx-auto"> |
||||
|
<div class="card"> |
||||
|
<div class="card-body profile-content p-5" style="min-height: 480px;"> |
||||
|
<h2 class="mb-4">Add Track</h2> |
||||
|
<div class="row"> |
||||
|
@foreach (var track in Model) |
||||
|
{ |
||||
|
<div class="col-md-3"> |
||||
|
<div class="track-item mb-4"> |
||||
|
<span class="track-name truncate">@track.Name</span> |
||||
|
<abp-row> |
||||
|
<abp-column> |
||||
|
<a id="@track.Id" data-track-name="@track.Name" href="javascript:;" data-bs-toggle="modal" data-bs-target="#EditTrackModal" class="mt-3 d-block text-info edit-track-button"><small><i class="fa fa-edit me-1"></i>Edit</small></a> |
||||
|
</abp-column> |
||||
|
<abp-column> |
||||
|
<a id="@track.Id" href="javascript:;" class="mt-3 d-block text-info delete-track-button"><small><i class="fa fa-trash me-1"></i>Delete</small></a> |
||||
|
</abp-column> |
||||
|
</abp-row> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
|
<div class="col-md-3"> |
||||
|
<div class="big-square-btn mb-4 text-center"> |
||||
|
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#AddTrackModal" class="btn btn-outline-secondary d-block px-2 py-5"><i class="fa fa-plus mb-3"></i><br>Add New Track</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card-footer bg-white border-0 p-5 pt-1"> |
||||
|
<div class="row"> |
||||
|
<div class="col-6"> |
||||
|
<button id="PreviousStepButtonInTrackSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Event" class="btn btn-secondary step-transition"><i class="fa fa-arrow-left me-2"></i> Previous Step </button> |
||||
|
</div> |
||||
|
<div class="col-6 text-end"> |
||||
|
<button id="SkipThisStepButtonInTrackSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Preview" class="btn btn-link step-transition text-decoration-none">Skip This Step</button> |
||||
|
<button id="NextStepButtonInTrackSection" data-target-step="@CreateOrEditEventAreaViewComponent.ProgressStepType.Session" class="btn btn-primary step-transition" @(Model.Any() ? "" : "disabled")>Next Step <i class="fa fa-arrow-right ms-2"></i></button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
@* Add Track Modal *@ |
||||
|
<div class="modal fade" id="AddTrackModal" tabindex="-1" aria-labelledby="AddTrackModal" aria-hidden="true"> |
||||
|
<div class="modal-dialog modal-dialog-centered"> |
||||
|
<div class="modal-content"> |
||||
|
<div class="modal-header border-0 p-5 pb-2"> |
||||
|
<h5 class="modal-title">Add New Track</h5> |
||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
||||
|
</div> |
||||
|
<form id="AddNewTrackForm" method="post"> |
||||
|
<div class="modal-body profile-content px-5"> |
||||
|
<div class="form-floating"> |
||||
|
<input type="text" class="form-control" id="TrackNameInput" placeholder=" " required data-val-length-max="@TrackConsts.MaxNameLength"> |
||||
|
<label for="TrackNameInput">Track Name</label> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="modal-footer border-0 p-5 pt-2"> |
||||
|
<button type="button" class="btn btn-secondary modal-close-button" data-bs-dismiss="modal">Close</button> |
||||
|
<button type="submit" class="btn btn-primary"> |
||||
|
<i class="fa fa-plus me-2"></i> Add |
||||
|
</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
@* Edit Track Modal *@ |
||||
|
<div class="modal fade" id="EditTrackModal" tabindex="-1" aria-labelledby="EditTrackModal" aria-hidden="true"> |
||||
|
<div class="modal-dialog modal-dialog-centered"> |
||||
|
<div class="modal-content"> |
||||
|
<div class="modal-header border-0 p-5 pb-2"> |
||||
|
<h5 class="modal-title">Edit This Track</h5> |
||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
||||
|
</div> |
||||
|
<form id="EditTrackForm"> |
||||
|
<div class="modal-body profile-content px-5"> |
||||
|
<input type="hidden" id="TrackId" value="TrackIdPlaceHolder"/> |
||||
|
<label for="TrackNameInput" class="mb-2">Edit Track Name</label> |
||||
|
<input type="text" class="form-control" id="TrackNameInput" placeholder="There is a track name here" required data-val-length-max="@TrackConsts.MaxNameLength"> |
||||
|
</div> |
||||
|
<div class="modal-footer border-0 p-5 pt-2"> |
||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> |
||||
|
<button type="submit" class="btn btn-primary"><i class="fa fa-check-circle me-2"></i>Save</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
}else |
||||
|
{ |
||||
|
<partial name="_modelNullErrorSection.cshtml"/> |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
.awesomplete { |
||||
|
display: inline!important; |
||||
|
} |
||||
@ -0,0 +1,512 @@ |
|||||
|
(function () { |
||||
|
abp.widgets.CreateOrEditEventArea = function ($wrapper) { |
||||
|
var l = abp.localization.getResource('EventHub'); |
||||
|
toastr.options.timeOut = 500; |
||||
|
toastr.options.preventDuplicates = true; |
||||
|
|
||||
|
var stepType = { |
||||
|
"Event": "Event", |
||||
|
"Track": "Track", |
||||
|
"Session": "Session", |
||||
|
"Preview": "Preview" |
||||
|
} |
||||
|
|
||||
|
var widgetManager = $wrapper.data('abp-widget-manager'); |
||||
|
var eventApiService = eventHub.controllers.events.event; |
||||
|
var eventIdInput = $('#EventId'); |
||||
|
var eventUrlCodeInput = $('#EventUrlCode'); |
||||
|
|
||||
|
var filter = { |
||||
|
eventUrlCode: "", |
||||
|
stepType: stepType.Event |
||||
|
} |
||||
|
|
||||
|
var getFilters = function () { |
||||
|
return filter; |
||||
|
} |
||||
|
|
||||
|
var init = function () { |
||||
|
$('#CreateEventButton').removeAttr('disabled') |
||||
|
FocusTrackNameInputInModalEventHandler("AddTrackModal") |
||||
|
FocusTrackNameInputInModalEventHandler("EditTrackModal") |
||||
|
NewEventFormInputAreaChangeHandler(); |
||||
|
FilFileInputChangeEventHandler(); |
||||
|
|
||||
|
if (eventIdInput.val().length === 36) { |
||||
|
$('#OrganizationId').prop("disabled", true); // Once the Organization is selected, it cannot be changed again.
|
||||
|
} |
||||
|
|
||||
|
$("#CreateEventForm").submit(function (e) { |
||||
|
e.preventDefault(); |
||||
|
if (!$(this).valid()) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
var formData = new FormData(); |
||||
|
formData = FillNewEventFormData(formData); |
||||
|
|
||||
|
var httpMetod = 'POST' |
||||
|
if (eventIdInput.val().length === 36) { |
||||
|
httpMetod = 'PUT' |
||||
|
} |
||||
|
|
||||
|
$.ajax({ |
||||
|
xhr: function() { |
||||
|
var xhr = new window.XMLHttpRequest(); |
||||
|
xhr.upload.addEventListener("progress", function(evt) { |
||||
|
if (evt.lengthComputable) { |
||||
|
var percentComplete = evt.loaded / evt.total; |
||||
|
percentComplete = parseInt(percentComplete * 100); |
||||
|
if(percentComplete !== 100){ |
||||
|
$('#CreateEventButton').prop( "disabled", true); |
||||
|
} |
||||
|
} |
||||
|
}, false); |
||||
|
|
||||
|
return xhr; |
||||
|
}, |
||||
|
url: $('#CreateEventButton').data('url'), |
||||
|
data: formData, |
||||
|
type: httpMetod, |
||||
|
contentType: false, |
||||
|
processData: false, |
||||
|
success: function(response){ |
||||
|
if (eventIdInput.val().length === 36) { |
||||
|
abp.notify.success('Updated event'); |
||||
|
}else{ |
||||
|
abp.notify.success('Created event as a draft' , '', toastr.options.timeOut = 2500); |
||||
|
eventIdInput.val(response.id); |
||||
|
eventUrlCodeInput.val(response.urlCode); |
||||
|
} |
||||
|
SwitchToTrackCreation() |
||||
|
}, |
||||
|
error: function (errorRaw) { |
||||
|
abp.notify.error(errorRaw.responseJSON.error.message, 'Error', |
||||
|
toastr.options = { |
||||
|
timeOut: 2500, |
||||
|
progressBar: true, |
||||
|
positionClass: "toast-bottom-right" |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
function SwitchToTrackCreation() { |
||||
|
$('#EventContainer').css('display', 'none'); |
||||
|
$('#TrackContainer').css('display', ''); |
||||
|
ScrollToWrapperBegin(); |
||||
|
} |
||||
|
|
||||
|
AddNewTrackSubmitFormEventHandler(); |
||||
|
OpenEditTrackModalClickEventHandler(); |
||||
|
EditTrackSubmitFormEventHandler(); |
||||
|
DeleteTrackButtonClickEventHandler(); |
||||
|
|
||||
|
OpenAddNewSessionModalClickEventHandler(); |
||||
|
AddNewSessionEventHandler(); |
||||
|
OpenEditSessionModalClickEventHandler(); |
||||
|
EditSessionEventHandler(); |
||||
|
DeleteSessionButtonClickEventHandler(); |
||||
|
|
||||
|
PublishEventButtonClickEventHandler(); |
||||
|
|
||||
|
PrevieousOrNextStepTransitionEventHandler() |
||||
|
}; |
||||
|
|
||||
|
function FillNewEventFormData(formData) { |
||||
|
var fileInput = document.getElementById('Event_CoverImageFile'); |
||||
|
formData.append("OrganizationId", $('#OrganizationId').val().trim()); |
||||
|
formData.append("Title", $('#inputTitle').val().trim()); |
||||
|
formData.append("StartTime", $('#inputStartdate').val().trim()); |
||||
|
formData.append("EndTime", $('#inputEnddate').val().trim()); |
||||
|
formData.append("Description", $('#inputDescription').val().trim()); |
||||
|
formData.append("CoverImageStreamContent", fileInput.files[0]); |
||||
|
formData.append("IsOnline", $('#IsOnline').val().trim()); |
||||
|
formData.append("OnlineLink", $('#inputOnlineLink').val().trim()); |
||||
|
formData.append("CountryId", $('#CountryId').val().trim()); |
||||
|
formData.append("City", $('#inputCity').val().trim()); |
||||
|
formData.append("Language", $('#Language').val().trim()); |
||||
|
formData.append("Capacity", $('#inputCapacity').val().trim()); |
||||
|
return formData; |
||||
|
} |
||||
|
|
||||
|
function AddNewTrackSubmitFormEventHandler() { |
||||
|
var addNewTrackForm = $('#AddNewTrackForm'); |
||||
|
addNewTrackForm.submit(function (e) { |
||||
|
e.preventDefault(); |
||||
|
if (!addNewTrackForm.valid()) { |
||||
|
return false; |
||||
|
} |
||||
|
var trackName = addNewTrackForm.find('#TrackNameInput').val().trim(); |
||||
|
eventApiService.addTrack(eventIdInput.val(), {name: trackName}).then(function () { |
||||
|
$('#AddTrackModal').modal('hide'); |
||||
|
abp.notify.success('Added the track'); |
||||
|
FillFilter(stepType.Track); |
||||
|
widgetManager.refresh(); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function FocusTrackNameInputInModalEventHandler(elementId) { |
||||
|
$('#' + elementId).on('shown.bs.modal', function () { |
||||
|
$(this).find('input[type=text]').trigger('focus') |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function OpenEditTrackModalClickEventHandler() { |
||||
|
$('.edit-track-button').click(function (e) { |
||||
|
var editTrackModal = $('#EditTrackModal'); |
||||
|
var clickedTrackId = this.id; |
||||
|
var trackName = $('#' + clickedTrackId).data('track-name'); |
||||
|
editTrackModal.find('#TrackNameInput').val(trackName); |
||||
|
editTrackModal.find('#TrackId').val(clickedTrackId); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function EditTrackSubmitFormEventHandler() { |
||||
|
var editTrackForm = $('#EditTrackForm'); |
||||
|
editTrackForm.submit(function (e) { |
||||
|
e.preventDefault(); |
||||
|
if (!editTrackForm.valid()) { |
||||
|
return false; |
||||
|
} |
||||
|
var trackId = editTrackForm.find('#TrackId').val(); |
||||
|
var oldTrackName = $('#' + trackId).data('track-name'); |
||||
|
var trackName = editTrackForm.find('#TrackNameInput').val().trim(); |
||||
|
if (trackName === oldTrackName) { |
||||
|
abp.notify.error('Track name must be different from the previous name.'); |
||||
|
return; |
||||
|
} |
||||
|
eventApiService.updateTrack(eventIdInput.val(), trackId, {name: trackName}).then(function () { |
||||
|
$('#EditTrackModal').modal('hide'); |
||||
|
abp.notify.success('Updated the track'); |
||||
|
FillFilter(stepType.Track) |
||||
|
widgetManager.refresh(); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function DeleteTrackButtonClickEventHandler() { |
||||
|
$('.delete-track-button').click(function (e) { |
||||
|
e.preventDefault(); |
||||
|
eventApiService.deleteTrack(eventIdInput.val(), this.id).then(function () { |
||||
|
abp.notify.success('Successfully deleted'); |
||||
|
FillFilter(stepType.Track) |
||||
|
widgetManager.refresh(); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function OpenAddNewSessionModalClickEventHandler() { |
||||
|
$('.add-session-button').click(function (e) { |
||||
|
var addSessionModal = $('#AddSessionModal'); |
||||
|
var clickedSessionId = this.id; |
||||
|
var trackId = $('#' + clickedSessionId).data('track-id'); |
||||
|
addSessionModal.find('#TrackId').val(trackId); |
||||
|
$('#StartTimeInNewSessionModal').val($('#inputStartdate').val()); |
||||
|
$('#EndTimeInNewSessionModal').val($('#inputEnddate').val()); |
||||
|
|
||||
|
CreateAutoCompleteByElement("SpeakersInNewSessionModal"); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function AddNewSessionEventHandler() { |
||||
|
var addNewSessionForm = $('#AddNewSessionForm'); |
||||
|
addNewSessionForm.submit(function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
if (!addNewSessionForm.valid()) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
var addSessionModal = $('#AddSessionModal'); |
||||
|
var trackId = addSessionModal.find('#TrackId').val(); |
||||
|
|
||||
|
var userNameList = $('#SpeakersInNewSessionModal').val().split(/[ , ]+/); |
||||
|
userNameList = userNameList.filter(v => v !== ''); |
||||
|
var input = $(this).serializeFormToObject(); |
||||
|
input.speakerUserNames = userNameList; |
||||
|
eventApiService.addSession(eventIdInput.val(), trackId, input).then(function () { |
||||
|
$('#AddSessionModal').modal('hide'); |
||||
|
abp.notify.success('Added the session'); |
||||
|
FillFilter(stepType.Session); |
||||
|
widgetManager.refresh(); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function OpenEditSessionModalClickEventHandler() { |
||||
|
$('.edit-session-button').click(function (e) { |
||||
|
e.preventDefault(); |
||||
|
var editSessionModal = $('#EditSessionModal'); |
||||
|
|
||||
|
var clickedSessionId = this.id; |
||||
|
var trackId = $('#' + clickedSessionId).data('track-id'); |
||||
|
|
||||
|
editSessionModal.find('#TrackId').val(trackId); |
||||
|
editSessionModal.find('#SessionId').val(clickedSessionId); |
||||
|
|
||||
|
var titleOfSession = $('#TitleOfSession-' + clickedSessionId).val(); |
||||
|
$('#EditModalTitle').html('Edit ' + abp.utils.truncateStringWithPostfix(titleOfSession, 10) + ' Session'); |
||||
|
editSessionModal.find('#TitleInEditSessionModal').val(titleOfSession); |
||||
|
editSessionModal.find('#DescriptionInEditSessionModal').val($('#DescriptionOfSession-' + clickedSessionId).val()); |
||||
|
editSessionModal.find('#StartTimeInEditSessionModal').val($('#StartTimeOfSession-' + clickedSessionId).val()); |
||||
|
editSessionModal.find('#EndTimeInEditSessionModal').val($('#EndTimeOfSession-' + clickedSessionId).val()); |
||||
|
editSessionModal.find('#LanguageInEditSessionModal').val($('#LanguageOfSession-' + clickedSessionId).val()); |
||||
|
editSessionModal.find('#SpeakersInEditSessionModal').val($('#SpeakersOfSession-' + clickedSessionId).val()); |
||||
|
|
||||
|
CreateAutoCompleteByElement("SpeakersInEditSessionModal"); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function EditSessionEventHandler() { |
||||
|
var editSessionForm = $('#EditSessionForm'); |
||||
|
editSessionForm.submit(function (e) { |
||||
|
e.preventDefault(); |
||||
|
|
||||
|
if (!editSessionForm.valid()) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
var userNameList = $('#SpeakersInEditSessionModal').val().split(/[ , ]+/); |
||||
|
userNameList = userNameList.filter(v => v !== ''); |
||||
|
var input = editSessionForm.serializeFormToObject(); |
||||
|
input.speakerUserNames = userNameList; |
||||
|
eventApiService.updateSession(eventIdInput.val(), editSessionForm.find('#TrackId').val(), editSessionForm.find('#SessionId').val(), input).then(function () { |
||||
|
$('#EditSessionModal').modal('hide'); |
||||
|
abp.notify.success('Updated the session'); |
||||
|
FillFilter(stepType.Session); |
||||
|
widgetManager.refresh(); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function DeleteSessionButtonClickEventHandler() { |
||||
|
$('.delete-session-button').click(function (e) { |
||||
|
e.preventDefault(); |
||||
|
var clickedSessionId = this.id; |
||||
|
var trackId = $('#' + clickedSessionId).data('track-id'); |
||||
|
|
||||
|
eventApiService.deleteSession(eventIdInput.val(), trackId, clickedSessionId).then(function () { |
||||
|
abp.notify.success('Successfully deleted'); |
||||
|
FillFilter(stepType.Session) |
||||
|
widgetManager.refresh(); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function PublishEventButtonClickEventHandler() { |
||||
|
$('#PublishButton').click(function (e) { |
||||
|
e.preventDefault(); |
||||
|
eventApiService.publish(eventIdInput.val()).then(function (res) { |
||||
|
e.prefe |
||||
|
abp.notify.success('Event Published'); |
||||
|
window.location.replace('https://' + window.location.host + '/events/' + res); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function PrevieousOrNextStepTransitionEventHandler() { |
||||
|
$('.step-transition').click(function (e) { |
||||
|
var clickedButtonId = this.id; |
||||
|
var targetStep = $('#' + clickedButtonId).data('target-step'); |
||||
|
FillFilter(targetStep); |
||||
|
widgetManager.refresh(); |
||||
|
ScrollToWrapperBegin(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function CreateAutoCompleteByElement(id) { |
||||
|
var element = document.getElementById(id); |
||||
|
var awesomplete = new Awesomplete(element, { |
||||
|
filter: function (text, input) { |
||||
|
return Awesomplete.FILTER_CONTAINS(text, input.match(/[^,]*$/)[0]); |
||||
|
}, |
||||
|
|
||||
|
item: function (text, input) { |
||||
|
return Awesomplete.ITEM(text, input.match(/[^,]*$/)[0]); |
||||
|
}, |
||||
|
|
||||
|
replace: function (text) { |
||||
|
var before = this.input.value.match(/^.+,\s*|/)[0]; |
||||
|
this.input.value = before + text + " , "; |
||||
|
}, |
||||
|
list: [] |
||||
|
}); |
||||
|
|
||||
|
function delay(callback, ms) { |
||||
|
var timer = 0; |
||||
|
return function () { |
||||
|
var context = this, args = arguments; |
||||
|
clearTimeout(timer); |
||||
|
timer = setTimeout(function () { |
||||
|
callback.apply(context, args); |
||||
|
}, ms || 0); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
$('#' + id).keyup(delay(function (e) { |
||||
|
var filterText = $(this).val().split(/[ ,]+/); |
||||
|
eventHub.controllers.users.user.getListByUserName(filterText[filterText.length-1]).then(function (res) { |
||||
|
var userNames = [] |
||||
|
$.each(res, function (i, v) { |
||||
|
if (!$('#' + id).val().includes(v.userName)){ |
||||
|
userNames.push(v.userName); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
awesomplete.list = userNames |
||||
|
awesomplete.evaluate(); |
||||
|
}); |
||||
|
}, 500)); |
||||
|
} |
||||
|
|
||||
|
function FillFilter(stepType) { |
||||
|
filter.stepType = stepType; |
||||
|
filter.eventUrlCode = eventUrlCodeInput.val(); |
||||
|
} |
||||
|
|
||||
|
function ScrollToWrapperBegin() { |
||||
|
$([document.documentElement, document.body]).animate({ |
||||
|
scrollTop: $wrapper.offset().top |
||||
|
}, 100); |
||||
|
} |
||||
|
|
||||
|
$(document).ajaxSend(function (event, jqxhr, settings, exception) { |
||||
|
ButtonsBusy(true) |
||||
|
}); |
||||
|
|
||||
|
$(document).ajaxComplete(function (event, jqxhr, settings, exception) { |
||||
|
ButtonsBusy(false) |
||||
|
}); |
||||
|
|
||||
|
abp.ajax.showError = function (error) { |
||||
|
abp.notify.error( |
||||
|
error.message, |
||||
|
'Error', |
||||
|
toastr.options = { |
||||
|
timeOut: 2500, |
||||
|
progressBar: true, |
||||
|
positionClass: "toast-bottom-right" |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
function ButtonsBusy(isBusy) { |
||||
|
if (isBusy) { |
||||
|
$('button[type=submit]').attr('disabled', 'disabled') |
||||
|
} else { |
||||
|
$('button[type=submit]').removeAttr('disabled') |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function NewEventFormInputAreaChangeHandler() { |
||||
|
var isOnline = $("#IsOnline option:selected").val() |
||||
|
if (isOnline === "True") { |
||||
|
$("#CountryId").attr("required", false); |
||||
|
$("#inputCity").attr("required", false); |
||||
|
$(".event-link-group").show(); |
||||
|
$(".event-location-group").hide(); |
||||
|
} else { |
||||
|
$("#CountryId").attr("required", true); |
||||
|
$("#inputCity").attr("required", true); |
||||
|
$(".event-link-group").hide(); |
||||
|
$(".event-location-group").show(); |
||||
|
} |
||||
|
|
||||
|
$('#IsOnline').on('change', '', function () { |
||||
|
var isOnline = $("#IsOnline option:selected").val() |
||||
|
if (isOnline === "True") { |
||||
|
$("#CountryId").attr("required", false); |
||||
|
$("#inputCity").attr("required", false); |
||||
|
$(".event-link-group").show(); |
||||
|
$(".event-location-group").hide(); |
||||
|
} else { |
||||
|
$("#CountryId").attr("required", true); |
||||
|
$("#inputCity").attr("required", true); |
||||
|
$(".event-link-group").hide(); |
||||
|
$(".event-location-group").show(); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function FilFileInputChangeEventHandler() { |
||||
|
var file; |
||||
|
var infoArea = document.getElementById('upload-label'); |
||||
|
var fileInput = document.getElementById('Event_CoverImageFile'); |
||||
|
|
||||
|
if (fileInput !== null) { |
||||
|
fileInput.addEventListener('change', function () { |
||||
|
var showFile = true; |
||||
|
|
||||
|
file = fileInput.files[0]; |
||||
|
|
||||
|
if (file === undefined) { |
||||
|
$('#Event_CoverImageFile').val(''); |
||||
|
$('#imageResult').attr('src', '#'); |
||||
|
infoArea.textContent = 'Choose file' |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var permittedExtensions = ["jpg", "jpeg", "png"] |
||||
|
var fileExtension = $(this).val().split('.').pop(); |
||||
|
if (permittedExtensions.indexOf(fileExtension) === -1) { |
||||
|
showFile = false; |
||||
|
abp.message.error(l('EventCoverImageExtensionNotAllowed')) |
||||
|
.then(() => { |
||||
|
$('#Event_CoverImageFile').val(''); |
||||
|
file = null; |
||||
|
}); |
||||
|
} else if (file.size > 1024 * 1024) { |
||||
|
showFile = false; |
||||
|
abp.message.error(l('EventCoverImageSizeExceedMessage')) |
||||
|
.then(() => { |
||||
|
$('#Event_CoverImageFile').val(''); |
||||
|
file = null; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
var img = new Image(); |
||||
|
img.onload = function () { |
||||
|
var imageError = true; |
||||
|
var sizes = { |
||||
|
width: this.width, |
||||
|
height: this.height |
||||
|
}; |
||||
|
URL.revokeObjectURL(this.src); |
||||
|
|
||||
|
if (showFile && imageError) { |
||||
|
readURL(file); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var objectURL = URL.createObjectURL(file); |
||||
|
img.src = objectURL; |
||||
|
}); |
||||
|
|
||||
|
function readURL(input) { |
||||
|
if (input) { |
||||
|
var reader = new FileReader(); |
||||
|
|
||||
|
reader.onload = function (e) { |
||||
|
if (eventIdInput.val().length === 36){ |
||||
|
$('.image-area').css('display', 'none').removeClass('d-block'); |
||||
|
$('.result-area').css('display', ''); |
||||
|
} |
||||
|
$('#imageResult').attr('src', e.target.result); |
||||
|
infoArea.textContent = 'File name: ' + input.name; |
||||
|
} |
||||
|
|
||||
|
reader.readAsDataURL(input); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
getFilters: getFilters, |
||||
|
init: init, |
||||
|
}; |
||||
|
} |
||||
|
})(); |
||||
@ -1,135 +1,19 @@ |
|||||
@page "/event/edit/{url}" |
@page "/event/edit/{url}" |
||||
@inject IHtmlLocalizer<EventHubResource> L |
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea |
||||
@using EventHub.Localization |
|
||||
@using EventHub.Web |
|
||||
@using Microsoft.AspNetCore.Mvc.Localization |
|
||||
@using Microsoft.Extensions.Options |
|
||||
@model EventHub.Web.Pages.Events.EditPageModel |
@model EventHub.Web.Pages.Events.EditPageModel |
||||
@inject IOptions<EventHubUrlOptions> UrlOptions |
|
||||
|
|
||||
@section scripts { |
@section scripts { |
||||
<abp-script src="/Pages/Events/Edit.js"/> |
<abp-script src="/libs/awesomplete/awesomplete.min.js" /> |
||||
} |
} |
||||
|
|
||||
<form method="post" enctype="multipart/form-data"> |
@section styles { |
||||
<div class="container pt-4"> |
<abp-style src="/libs/awesomplete/awesomplete.css" /> |
||||
<div class="row py-4"> |
} |
||||
<div class="col-md-9 mx-auto profile-content"> |
|
||||
|
|
||||
<div class="card"> |
|
||||
<div class="card-body" style="min-height: 496px"> |
|
||||
<h3 class="mb-4">Edit Event</h3> |
|
||||
<div class="form"> |
|
||||
<div class="row"> |
|
||||
<input type="hidden" value="@Model.Url" id="event-detail-url"/> |
|
||||
<abp-input asp-for="Event.Id"/> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-label-group"> |
|
||||
<select asp-for="Event.OrganizationId" asp-items="Model.Organizations" class="form-select"> |
|
||||
<option selected value="">Organization</option> |
|
||||
</select> |
|
||||
<span asp-validation-for="Event.OrganizationId" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-label-group"> |
|
||||
<input type="text" id="inputTitle" asp-for="Event.Title" class="form-control" placeholder="Title"> |
|
||||
<label for="inputTitle">Title</label> |
|
||||
<span asp-validation-for="Event.Title" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-label-group"> |
|
||||
<input id="inputStartdate" asp-for="Event.StartTime" class="form-control" placeholder="Start Date"> |
|
||||
<label for="inputStartdate">Start Date</label> |
|
||||
<span asp-validation-for="Event.StartTime" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-label-group"> |
|
||||
<input id="inputEnddate" asp-for="Event.EndTime" class="form-control" placeholder="End Date"> |
|
||||
<label for="inputEnddate">End Date</label> |
|
||||
<span asp-validation-for="Event.EndTime" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-12"> |
|
||||
<div class="form-label-group form-floating"> |
|
||||
<textarea rows="5" type="text" id="inputDescription" asp-for="Event.Description" class="form-control" placeholder="Description"></textarea> |
|
||||
<span asp-validation-for="Event.Description" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<div class="col-md-12"> |
|
||||
<h4 class="mb-4">Cover Image</h4> |
|
||||
<div class="row"> |
|
||||
<div class="col-5"> |
|
||||
<div class="image-area"> |
|
||||
<img id="imageResult" src="@(UrlOptions.Value.Api.EnsureEndsWith('/') + $"api/eventhub/event/cover-image/{Model.Event.Id}")" alt="" class="img-fluid rounded shadow-sm mx-auto d-block"> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-7"> |
|
||||
<div> |
|
||||
<p class="mb-3">For horizontal format 600x300 sized upload images.</p> |
|
||||
<input type="file" id="Event_CoverImageFile" asp-for="Event.CoverImageFile" class="form-control border-0" hidden> |
|
||||
<label id="upload-label" for="Event_CoverImageFile" class="btn btn-primary btn-lg text-white">Choose file</label> |
|
||||
<span asp-validation-for="Event.CoverImageFile" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<select class="form-select" asp-for="Event.IsOnline"> |
|
||||
<option selected="selected" value="">Event Type</option> |
|
||||
<option value="@Boolean.TrueString">Online</option> |
|
||||
<option value="@Boolean.FalseString">In Person</option> |
|
||||
</select> |
|
||||
<span asp-validation-for="Event.IsOnline" class="text-danger"></span> |
|
||||
</div> |
|
||||
<div class="col-md-6 event-link-group" style="display: none"> |
|
||||
<div class="form-label-group"> |
|
||||
<input type="text" id="inputOnlineLink" asp-for="Event.OnlineLink" class="form-control" placeholder="Online Link"> |
|
||||
<label for="inputOnlineLink">Online Link</label> |
|
||||
<span asp-validation-for="Event.OnlineLink" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-label-group"> |
|
||||
<input type="number" id="inputCapacity" asp-for="Event.Capacity" class="form-control" placeholder="Capacity"> |
|
||||
<label for="inputCapacity">Capacity</label> |
|
||||
<span asp-validation-for="Event.Capacity" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6 event-location-group"> |
|
||||
<select asp-for="Event.CountryId" asp-items="Model.Countries" class="form-select"> |
|
||||
<option selected="" value="">Country</option> |
|
||||
</select> |
|
||||
<span asp-validation-for="Event.CountryId" class="text-danger"></span> |
|
||||
</div> |
|
||||
<div class="col-md-6 event-location-group"> |
|
||||
<div class="form-label-group"> |
|
||||
<input type="text" id="inputCity" asp-for="Event.City" class="form-control" placeholder="City"> |
|
||||
<label for="inputCity">City</label> |
|
||||
<span asp-validation-for="Event.City" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<select asp-for="Event.Language" asp-items="Model.Languages" aria-label="en" class="form-select"> |
|
||||
<option selected value="">Language</option> |
|
||||
</select> |
|
||||
<span asp-validation-for="Event.Language" class="text-danger"></span> |
|
||||
</div> |
|
||||
|
|
||||
|
|
||||
<div class="col-md-12 text-end"> |
<div class="container mt-5"> |
||||
<button type="submit" class="btn btn-primary btn-lg"> |
@await Component.InvokeAsync(typeof(CreateOrEditEventAreaViewComponent), new |
||||
@L["Submit"] |
{ |
||||
</button> |
eventUrlCode = Model.UrlCode, |
||||
</div> |
stepType = CreateOrEditEventAreaViewComponent.ProgressStepType.Event |
||||
</div> |
}) |
||||
</div> |
</div> |
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</form> |
|
||||
|
|||||
@ -1,202 +1,19 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.ComponentModel; |
|
||||
using System.ComponentModel.DataAnnotations; |
|
||||
using System.Globalization; |
|
||||
using System.IO; |
|
||||
using System.Linq; |
|
||||
using System.Threading.Tasks; |
|
||||
using EventHub.Events; |
using EventHub.Events; |
||||
using EventHub.Organizations; |
|
||||
using EventHub.Web.Helpers; |
|
||||
using JetBrains.Annotations; |
|
||||
using Microsoft.AspNetCore.Http; |
|
||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using Microsoft.AspNetCore.Mvc.Rendering; |
|
||||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; |
|
||||
using Volo.Abp.Content; |
|
||||
using Volo.Abp.Users; |
|
||||
|
|
||||
namespace EventHub.Web.Pages.Events |
namespace EventHub.Web.Pages.Events |
||||
{ |
{ |
||||
public class EditPageModel : EventHubPageModel |
public class EditPageModel : EventHubPageModel |
||||
{ |
{ |
||||
[BindProperty(SupportsGet = true)] |
public string UrlCode { get; set; } |
||||
public new string Url { get; set; } |
|
||||
|
|
||||
[BindProperty] |
public EditPageModel() |
||||
public EditEventViewModel Event { get; set; } |
|
||||
|
|
||||
public List<SelectListItem> Organizations { get; private set; } |
|
||||
public List<SelectListItem> Countries { get; private set; } |
|
||||
public List<SelectListItem> Languages { get; private set; } |
|
||||
|
|
||||
private readonly IEventAppService _eventAppService; |
|
||||
private readonly IOrganizationAppService _organizationAppService; |
|
||||
|
|
||||
public EditPageModel( |
|
||||
IEventAppService eventAppService, |
|
||||
IOrganizationAppService organizationAppService) |
|
||||
{ |
|
||||
_eventAppService = eventAppService; |
|
||||
_organizationAppService = organizationAppService; |
|
||||
} |
|
||||
|
|
||||
public async Task OnGetAsync() |
|
||||
{ |
{ |
||||
var urlCode = EventUrlCodeHelper.GetCodeFromUrl(Url); |
|
||||
var eventDetailDto = await _eventAppService.GetByUrlCodeAsync(urlCode); |
|
||||
|
|
||||
Event = ObjectMapper.Map<EventDetailDto, EditEventViewModel>(eventDetailDto); |
|
||||
|
|
||||
await FillOrganizationsAsync(); |
|
||||
await FillCountriesAsync(); |
|
||||
FillLanguages(); |
|
||||
} |
} |
||||
|
|
||||
public async Task<IActionResult> OnPostAsync() |
public void OnGet(string url) |
||||
{ |
{ |
||||
try |
UrlCode = EventUrlCodeHelper.GetCodeFromUrl(url); |
||||
{ |
|
||||
ValidateModel(); |
|
||||
|
|
||||
var updateEventDto = ObjectMapper.Map<EditEventViewModel, UpdateEventDto>(Event); |
|
||||
|
|
||||
await using var memoryStream = new MemoryStream(); |
|
||||
if (Event.CoverImageFile != null && Event.CoverImageFile.Length > 0) |
|
||||
{ |
|
||||
await Event.CoverImageFile.CopyToAsync(memoryStream); |
|
||||
memoryStream.Position = 0; |
|
||||
|
|
||||
updateEventDto.CoverImageStreamContent = new RemoteStreamContent(memoryStream, fileName: Event.CoverImageFile.FileName, contentType: Event.CoverImageFile.ContentType); |
|
||||
} |
|
||||
|
|
||||
await _eventAppService.UpdateAsync(Event.Id, updateEventDto); |
|
||||
await memoryStream.DisposeAsync(); |
|
||||
|
|
||||
return RedirectToPage("./Detail", new { url = Url }); |
|
||||
} |
|
||||
catch (Exception exception) |
|
||||
{ |
|
||||
ShowAlert(exception); |
|
||||
await FillOrganizationsAsync(); |
|
||||
await FillCountriesAsync(); |
|
||||
FillLanguages(); |
|
||||
return Page(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private async Task FillOrganizationsAsync() |
|
||||
{ |
|
||||
var result = await _organizationAppService.GetOrganizationsByUserIdAsync(CurrentUser.GetId()); |
|
||||
Organizations = result.Items.Select( |
|
||||
organization => new SelectListItem |
|
||||
{ |
|
||||
Value = organization.Id.ToString(), |
|
||||
Text = organization.DisplayName |
|
||||
} |
|
||||
).ToList(); |
|
||||
|
|
||||
if (Event.OrganizationId != Guid.Empty) |
|
||||
{ |
|
||||
Organizations.Single(x => x.Value == Event.OrganizationId.ToString()).Selected = true; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private async Task FillCountriesAsync() |
|
||||
{ |
|
||||
var result = await _eventAppService.GetCountriesLookupAsync(); |
|
||||
|
|
||||
Countries = result.Select( |
|
||||
country => new SelectListItem |
|
||||
{ |
|
||||
Value = country.Id.ToString(), |
|
||||
Text = country.Name |
|
||||
} |
|
||||
).ToList(); |
|
||||
|
|
||||
if (Event.CountryId.HasValue) |
|
||||
{ |
|
||||
Countries.Single(x => x.Value == Event.CountryId.ToString()).Selected = true; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private void FillLanguages() |
|
||||
{ |
|
||||
var result = CultureInfo.GetCultures(CultureTypes.NeutralCultures) |
|
||||
.DistinctBy(x => x.EnglishName) |
|
||||
.OrderBy(x => x.EnglishName) |
|
||||
.ToList(); |
|
||||
result.Remove(result.Single(x => x.TwoLetterISOLanguageName == "iv")); // Invariant Language
|
|
||||
|
|
||||
Languages = result.Select( |
|
||||
cultureInfo => new SelectListItem |
|
||||
{ |
|
||||
Value = cultureInfo.TwoLetterISOLanguageName, |
|
||||
Text = cultureInfo.EnglishName |
|
||||
} |
|
||||
).ToList(); |
|
||||
|
|
||||
if (!string.IsNullOrWhiteSpace(Event.Language)) |
|
||||
{ |
|
||||
Languages.Single(x => x.Value == Event.Language).Selected = true; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public class EditEventViewModel |
|
||||
{ |
|
||||
[HiddenInput] |
|
||||
public Guid Id { get; set; } |
|
||||
|
|
||||
[SelectItems(nameof(Organizations))] |
|
||||
[DisplayName("Organization")] |
|
||||
public Guid OrganizationId { get; set; } |
|
||||
|
|
||||
[Required] |
|
||||
[StringLength(EventConsts.MaxTitleLength, MinimumLength = EventConsts.MinTitleLength)] |
|
||||
public string Title { get; set; } |
|
||||
|
|
||||
[Required] |
|
||||
[DataType(DataType.DateTime)] |
|
||||
public DateTime StartTime { get; set; } = DateTime.Now; |
|
||||
|
|
||||
[Required] |
|
||||
[DataType(DataType.DateTime)] |
|
||||
public DateTime EndTime { get; set; } = DateTime.Now; |
|
||||
|
|
||||
[Required] |
|
||||
[StringLength(EventConsts.MaxDescriptionLength, MinimumLength = EventConsts.MinDescriptionLength)] |
|
||||
[TextArea] |
|
||||
public string Description { get; set; } |
|
||||
|
|
||||
[CanBeNull] |
|
||||
[Display(Name = "Cover Image")] |
|
||||
[DataType(DataType.Upload)] |
|
||||
[MaxFileSize(EventConsts.MaxCoverImageFileSize)] |
|
||||
[AllowedExtensions(new string[] { ".jpg", ".png", ".jpeg" })] |
|
||||
public IFormFile CoverImageFile { get; set; } |
|
||||
|
|
||||
[Required] |
|
||||
public bool IsOnline { get; set; } |
|
||||
|
|
||||
[CanBeNull] |
|
||||
[StringLength(EventConsts.MaxOnlineLinkLength, MinimumLength = EventConsts.MinOnlineLinkLength)] |
|
||||
public string OnlineLink { get; set; } |
|
||||
|
|
||||
[SelectItems(nameof(Countries))] |
|
||||
[DisplayName("Country")] |
|
||||
public Guid? CountryId { get; set; } |
|
||||
|
|
||||
[CanBeNull] |
|
||||
[StringLength(EventConsts.MaxCityLength, MinimumLength = EventConsts.MinCityLength)] |
|
||||
public string City { get; set; } |
|
||||
|
|
||||
[SelectItems(nameof(Languages))] |
|
||||
[DisplayName("Language")] |
|
||||
public string Language { get; set; } |
|
||||
|
|
||||
[Range(1, int.MaxValue)] |
|
||||
public int? Capacity { get; set; } |
|
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,94 +0,0 @@ |
|||||
$(function () { |
|
||||
var l = abp.localization.getResource('EventHub'); |
|
||||
|
|
||||
var isOnline = $("#Event_IsOnline option:selected").val() |
|
||||
if (isOnline === "True") { |
|
||||
$(".event-link-group").show(); |
|
||||
$(".event-location-group").hide(); |
|
||||
} else { |
|
||||
$(".event-link-group").hide(); |
|
||||
$(".event-location-group").show(); |
|
||||
} |
|
||||
|
|
||||
$('#Event_IsOnline').on('change', '', function () { |
|
||||
var isOnline = $("#Event_IsOnline option:selected").val() |
|
||||
if (isOnline === "True") { |
|
||||
$("#Event_CountryId").attr("required", false); |
|
||||
$("#inputCity").attr("required", false); |
|
||||
$(".event-link-group").show(); |
|
||||
$(".event-location-group").hide(); |
|
||||
} else { |
|
||||
$("#Event_CountryId").attr("required", true); |
|
||||
$("#inputCity").attr("required", true); |
|
||||
$(".event-link-group").hide(); |
|
||||
$(".event-location-group").show(); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
var infoArea = document.getElementById('upload-label'); |
|
||||
var fileInput = document.getElementById('Event_CoverImageFile'); |
|
||||
var file; |
|
||||
|
|
||||
if (fileInput !== null) { |
|
||||
fileInput.addEventListener('change', function () { |
|
||||
var showFile = true; |
|
||||
|
|
||||
file = fileInput.files[0]; |
|
||||
|
|
||||
if (file === undefined) { |
|
||||
$('#Event_CoverImageFile').val(''); |
|
||||
$('#imageResult').attr('src', '#'); |
|
||||
infoArea.textContent = 'Choose file' |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var permittedExtensions = ["jpg", "jpeg", "png"] |
|
||||
var fileExtension = $(this).val().split('.').pop(); |
|
||||
if (permittedExtensions.indexOf(fileExtension) === -1) { |
|
||||
showFile = false; |
|
||||
abp.message.error(l('EventCoverImageExtensionNotAllowed')) |
|
||||
.then(() => { |
|
||||
$('#Event_CoverImageFile').val(''); |
|
||||
file = null; |
|
||||
}); |
|
||||
} else if (file.size > 1024 * 1024) { |
|
||||
showFile = false; |
|
||||
abp.message.error(l('EventCoverImageSizeExceedMessage')) |
|
||||
.then(() => { |
|
||||
$('#Event_CoverImageFile').val(''); |
|
||||
file = null; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
var img = new Image(); |
|
||||
img.onload = function () { |
|
||||
var imageError = true; |
|
||||
var sizes = { |
|
||||
width: this.width, |
|
||||
height: this.height |
|
||||
}; |
|
||||
URL.revokeObjectURL(this.src); |
|
||||
|
|
||||
if (showFile && imageError) { |
|
||||
readURL(file); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
var objectURL = URL.createObjectURL(file); |
|
||||
img.src = objectURL; |
|
||||
}); |
|
||||
|
|
||||
function readURL(input) { |
|
||||
if (input) { |
|
||||
var reader = new FileReader(); |
|
||||
|
|
||||
reader.onload = function (e) { |
|
||||
$('#imageResult').attr('src', e.target.result); |
|
||||
infoArea.textContent = 'File name: ' + input.name; |
|
||||
} |
|
||||
|
|
||||
reader.readAsDataURL(input); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
@ -1,145 +1,99 @@ |
|||||
@page "/events/new" |
@page "/events/new/{eventUrlCode?}" |
||||
@inject IHtmlLocalizer<EventHubResource> L |
@inject IHtmlLocalizer<EventHubResource> L |
||||
@using EventHub.Localization |
@using EventHub.Localization |
||||
|
@using EventHub.Web.Pages.Events.Components.CreateOrEditEventArea |
||||
@using Microsoft.AspNetCore.Mvc.Localization |
@using Microsoft.AspNetCore.Mvc.Localization |
||||
@model EventHub.Web.Pages.Events.NewPageModel |
@model EventHub.Web.Pages.Events.NewPageModel |
||||
|
|
||||
@section scripts { |
@section scripts { |
||||
<abp-script src="/Pages/Events/New.js"/> |
<abp-script src="/libs/awesomplete/awesomplete.min.js" /> |
||||
} |
} |
||||
|
|
||||
@if (!Model.Organizations.Any()) |
@section styles { |
||||
{ |
<abp-style src="/libs/awesomplete/awesomplete.css" /> |
||||
<div class="container mt-5"> |
} |
||||
<div class="row"> |
|
||||
<div class="col-lg-8 col-md-10 mx-auto "> |
<div class="container mt-5"> |
||||
<div class="card" > |
@if (!Model.IsHasOrganizations) |
||||
<div class="card-body text-center p-lg-5"> |
{ |
||||
<h4 class="mb-4">@L["NewEventYouHaveNoOrganizationYetMessage"]</h4> |
<div class="row"> |
||||
<a abp-button="Primary" href="@Url.Page("/Organizations/New")">@L["CreateAnOrganization"]</a> |
<div class="col-lg-8 col-md-10 mx-auto "> |
||||
|
<div class="card"> |
||||
|
<div class="card-body text-center p-lg-5"> |
||||
|
<h4 class="mb-4">@L["NewEventYouHaveNoOrganizationYetMessage"]</h4> |
||||
|
<a abp-button="Primary" href="@Url.Page("/Organizations/New")">@L["CreateAnOrganization"]</a> |
||||
|
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
} |
||||
</div> |
else if (Model.DraftEventList.Any()) |
||||
} |
{ |
||||
else |
<h1 class="text-center mb-3">Create an Event</h1> |
||||
{ |
<p class="text-center mb-5"> |
||||
<form method="post" enctype="multipart/form-data"> |
You can create a new event or proceed through the draft events you have created before. |
||||
<div class="container pt-4"> |
</p> |
||||
<div class="row py-4"> |
<div class="row"> |
||||
<div class="col-md-9 mx-auto profile-content"> |
<div class="col-md-6"> |
||||
<div class="card"> |
<div class="card"> |
||||
<div class="card-body" style="min-height: 496px"> |
<div class="card-body px-4 py-5 text-center"> |
||||
<h3 class="mb-4">Create New Event</h3> |
<svg width="50" height="58" viewBox="0 0 50 58" fill="none" xmlns="http://www.w3.org/2000/svg"> |
||||
<div class="form"> |
<path d="M33.0445 28.1094H9.31281C8.68249 28.1094 8.17188 28.6205 8.17188 29.2515C8.17188 29.8825 8.68249 30.394 9.31281 30.394H33.0445C33.6748 30.394 34.1854 29.8825 34.1854 29.2515C34.1854 28.6209 33.6748 28.1094 33.0445 28.1094Z" fill="#E8345D"/> |
||||
<div class="row"> |
<path d="M33.0445 34.8032H9.31281C8.68249 34.8032 8.17188 35.3143 8.17188 35.9453C8.17188 36.5763 8.68249 37.0879 9.31281 37.0879H33.0445C33.6748 37.0879 34.1854 36.5763 34.1854 35.9453C34.1854 35.3143 33.6748 34.8032 33.0445 34.8032Z" fill="#E8345D"/> |
||||
<div class="col-md-6"> |
<path d="M33.0445 41.4976H9.31281C8.68249 41.4976 8.17188 42.0087 8.17188 42.6397C8.17188 43.2707 8.68249 43.7822 9.31281 43.7822H33.0445C33.6748 43.7822 34.1854 43.2707 34.1854 42.6397C34.1854 42.0087 33.6748 41.4976 33.0445 41.4976Z" fill="#E8345D"/> |
||||
<div class="form-label-group"> |
<path d="M48.0044 5.61362H44.3885V1.99791C44.3885 0.896072 43.4919 0 42.3894 0H37.5942C36.4935 0 35.5981 0.896072 35.5981 1.99791V5.61317H31.9827C31.1161 5.61317 30.3785 6.16896 30.1019 6.94246H12.6346C12.332 6.94246 12.0418 7.06282 11.8281 7.27699L0.333931 18.791C0.120145 19.0051 0 19.2959 0 19.599V54.9016C0 56.6101 1.38917 58 3.09637 58H39.7387C41.4459 58 42.8351 56.6101 42.8351 54.9016V39.4692C42.8351 38.8382 42.324 38.3267 41.6941 38.3267C41.0643 38.3267 40.5536 38.8382 40.5536 39.4692V54.9016C40.5536 55.3428 40.1804 55.7153 39.7387 55.7153H3.09637C2.65466 55.7153 2.28142 55.3428 2.28142 54.9016V20.7411H10.3103C12.2212 20.7411 13.7755 19.1857 13.7755 17.2736V9.22711H29.9831V12.4114C29.9831 13.5132 30.8802 14.4093 31.9827 14.4093H35.5981V18.0246C35.5981 19.1282 36.4935 20.026 37.5942 20.026H40.5532V29.1438C40.5532 29.7744 41.0643 30.2859 41.6941 30.2859C42.324 30.2859 42.8346 29.7744 42.8346 29.1438V19.9742C43.7233 19.7707 44.3885 18.9751 44.3885 18.025V14.4093H48.0039C49.1047 14.4093 50 13.5132 50 12.4114V7.61462C50 6.51102 49.1047 5.61362 48.0044 5.61362ZM10.3103 18.4564H3.8941L11.4937 10.8431V17.2736C11.4937 17.9259 10.9632 18.4564 10.3103 18.4564ZM47.7186 12.1246H43.2481C42.6177 12.1246 42.1071 12.6362 42.1071 13.2672V17.7413H37.8795V13.2672C37.8795 12.6362 37.3689 12.1246 36.739 12.1246H32.265V7.89827H36.739C37.3689 7.89827 37.8795 7.38673 37.8795 6.75572V2.28465H42.1071V6.75572C42.1071 7.38673 42.6177 7.89827 43.2481 7.89827H47.7186V12.1246Z" fill="#E8345D"/> |
||||
<select asp-for="Event.OrganizationId" asp-items="Model.Organizations" class="form-select"> |
<path d="M41.6937 33.1411C41.0633 33.1411 40.5527 33.6526 40.5527 34.2837V34.3067C40.5527 34.9372 41.0638 35.4488 41.6937 35.4488C42.3235 35.4488 42.8342 34.9372 42.8342 34.3067V34.2837C42.8346 33.6526 42.3235 33.1411 41.6937 33.1411Z" fill="#E8345D"/> |
||||
@if (Model.Organizations.Count > 1) |
</svg> |
||||
|
<h2 class="mt-4">Create a New Event</h2> |
||||
|
<p class="my-4">Create your own Eventhub group and benefit from a community of millions.</p> |
||||
|
<a href="@Url.Page("/events/new", new {isCreateNew = true})" class="btn btn-primary">Create</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<div class="card"> |
||||
|
<div class="card-body px-4 py-5 text-center"> |
||||
|
<svg width="42" height="56" viewBox="0 0 42 56" fill="none" xmlns="http://www.w3.org/2000/svg"> |
||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.9071 0H12.456C12.4436 0 12.4313 0.00128174 12.4193 0.00170898C12.4069 0.00213622 12.3946 0.00299073 12.3822 0.00384521C12.3361 0.00683594 12.29 0.0119629 12.2452 0.020935C12.2439 0.020935 12.2431 0.020935 12.2422 0.0213622C12.1965 0.0303345 12.1517 0.0435792 12.1074 0.0585327C12.0958 0.0623779 12.0839 0.0666504 12.0724 0.0709229C12.0314 0.0863037 11.9913 0.103821 11.952 0.123901C11.949 0.12561 11.9456 0.126892 11.9422 0.128601C11.9008 0.150818 11.8616 0.176453 11.8231 0.203369C11.8133 0.210632 11.8031 0.218323 11.7933 0.226013C11.7549 0.255066 11.7182 0.285828 11.6836 0.320435L0.320063 11.6971C0.285497 11.7318 0.254344 11.7693 0.225325 11.8074C0.217643 11.8172 0.210388 11.827 0.20356 11.8369C0.176248 11.8757 0.150216 11.9155 0.128025 11.9569C0.126745 11.9595 0.125892 11.9616 0.125038 11.9642C0.104127 12.0039 0.0862037 12.0453 0.0708408 12.0876C0.0665732 12.0988 0.0623056 12.1099 0.0584649 12.121C0.0435287 12.1658 0.0302994 12.2111 0.0209108 12.2573V12.2581C0.011949 12.3038 0.00682802 12.3508 0.00384076 12.3978C0.00298726 12.4098 0.00213375 12.4218 0.001707 12.4337C0.00128026 12.4461 0 12.4585 0 12.4709V54.9062C0 55.5104 0.489057 56 1.09248 56H40.9075C41.5105 56 42 55.5104 42 54.9062V1.09375C41.9996 0.489624 41.5105 0 40.9071 0ZM11.3635 3.73456V11.3771H3.72981L11.3635 3.73456ZM39.8146 53.8125H2.18497V13.5646H12.456C13.0594 13.5646 13.5485 13.0746 13.5485 12.4709V2.1875H39.815V53.8125H39.8146Z" fill="#E8345D"/> |
||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.3835 20.3442C6.78007 20.3442 6.29102 20.8339 6.29102 21.438V37.2427C6.29102 37.8468 6.78007 38.3364 7.3835 38.3364C7.98693 38.3364 8.47598 37.8468 8.47598 37.2427V22.5317H26.4473V28.1146C26.1631 28.0936 25.8759 28.0825 25.5866 28.0825C19.2088 28.0825 14.0199 33.277 14.0199 39.6626C14.0199 39.9514 14.031 40.239 14.0523 40.5239H11.7534C11.15 40.5239 10.6609 41.0135 10.6609 41.6177C10.6609 42.2218 11.15 42.7114 11.7534 42.7114H14.4309C15.3313 46.0046 17.6605 48.8001 20.8654 50.2365C21.4164 50.4835 22.0625 50.2365 22.3091 49.6849C22.5558 49.1338 22.3091 48.4865 21.7582 48.24C18.3847 46.728 16.2049 43.3613 16.2049 39.6626C16.2049 34.4835 20.4135 30.27 25.5866 30.27C30.7596 30.27 34.9683 34.4835 34.9683 39.6626C34.9683 43.3613 32.7889 46.728 29.4154 48.24C28.8644 48.4865 28.6178 49.1338 28.8644 49.6849C29.0462 50.0912 29.4448 50.3322 29.8622 50.3322C30.0116 50.3322 30.1631 50.3015 30.3081 50.2365C34.4664 48.3729 37.1532 44.2222 37.1532 39.6626C37.1532 34.3323 33.5374 29.8325 28.6323 28.4905V21.438C28.6323 20.8339 28.1428 20.3442 27.5398 20.3442H7.3835Z" fill="#E8345D"/> |
||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.5886 49.0552C24.9869 49.0552 24.4961 49.5461 24.4961 50.1489C24.4961 50.7513 24.9869 51.2427 25.5886 51.2427C26.1903 51.2427 26.6811 50.7513 26.6811 50.1489C26.6811 49.5461 26.1903 49.0552 25.5886 49.0552Z" fill="#E8345D"/> |
||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.3835 40.5239C6.78178 40.5239 6.29102 41.0153 6.29102 41.6177C6.29102 42.2201 6.78178 42.7114 7.3835 42.7114C7.98522 42.7114 8.47598 42.2201 8.47598 41.6177C8.47598 41.0153 7.98522 40.5239 7.3835 40.5239Z" fill="#E8345D"/> |
||||
|
</svg> |
||||
|
<h2 class="my-4">Drafts</h2> |
||||
|
@foreach (var draftEvent in Model.DraftEventList) |
||||
{ |
{ |
||||
<option selected value="">Pick an organization</option> |
<div class="card card-body border-light mb-0 mt-3"> |
||||
|
<div class="row"> |
||||
|
<div class="col-7 text-start"> |
||||
|
<a href="@Url.Page("/events/new", new {eventUrlCode = draftEvent.UrlCode})" class="text-info stretched-link text-decoration-none">@draftEvent.Title</a> |
||||
|
</div> |
||||
|
<div class="col-5 text-end"> |
||||
|
<span> |
||||
|
Last edit: |
||||
|
@if (!draftEvent.LastModificationTime.HasValue) |
||||
|
{ |
||||
|
<span>@draftEvent.CreationTime.ToShortDateString()</span> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<span>@draftEvent.LastModificationTime!.Value.ToShortDateString()</span> |
||||
|
} |
||||
|
</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
} |
} |
||||
</select> |
|
||||
<span asp-validation-for="Event.OrganizationId" class="text-danger"></span> |
|
||||
</div> |
</div> |
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-label-group"> |
|
||||
<input type="text" id="inputTitle" asp-for="Event.Title" class="form-control" placeholder="Title"> |
|
||||
<label for="inputTitle">Title</label> |
|
||||
<span asp-validation-for="Event.Title" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-label-group"> |
|
||||
<input id="inputStartdate" asp-for="Event.StartTime" class="form-control" placeholder="Start Date"> |
|
||||
<label for="inputStartdate">Start Date</label> |
|
||||
<span asp-validation-for="Event.StartTime" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-label-group"> |
|
||||
<input id="inputEnddate" asp-for="Event.EndTime" class="form-control" placeholder="End Date"> |
|
||||
<label for="inputEnddate">End Date</label> |
|
||||
<span asp-validation-for="Event.EndTime" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-12"> |
|
||||
<div class="form-label-group"> |
|
||||
<textarea rows="5" type="text" id="inputDescription" asp-for="Event.Description" class="form-control" placeholder="Description"></textarea> |
|
||||
<span asp-validation-for="Event.Description" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-12"> |
|
||||
<h4 class="mb-4">Cover Image</h4> |
|
||||
<div class="row"> |
|
||||
<div class="col-6"> |
|
||||
<div class="image-area"><img id="imageResult" src="#" alt="" class="img-fluid rounded shadow-sm mx-auto d-block"></div> |
|
||||
</div> |
|
||||
<div class="col-6"> |
|
||||
<div> |
|
||||
<p class="mb-3">For horizontal format 600x400 sized upload images.</p> |
|
||||
<input type="file" id="Event_CoverImageFile" asp-for="Event.CoverImageFile" class="form-control border-0" hidden> |
|
||||
<label id="upload-label" for="Event_CoverImageFile" class="btn btn-primary btn-lg text-white">Choose file</label> |
|
||||
<span asp-validation-for="Event.CoverImageFile" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<select class="form-select" asp-for="Event.IsOnline"> |
|
||||
<option selected="selected" value="">Event Type</option> |
|
||||
<option value="@Boolean.TrueString">Online</option> |
|
||||
<option value="@Boolean.FalseString">In Person</option> |
|
||||
</select> |
|
||||
<span asp-validation-for="Event.IsOnline" class="text-danger"></span> |
|
||||
</div> |
|
||||
<div class="col-md-6 event-link-group" style="display: none"> |
|
||||
<div class="form-label-group"> |
|
||||
<input type="text" id="inputOnlineLink" asp-for="Event.OnlineLink" class="form-control" placeholder="Online Link"> |
|
||||
<label for="inputOnlineLink">Online Link</label> |
|
||||
<span asp-validation-for="Event.OnlineLink" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<div class="form-label-group"> |
|
||||
<input type="number" id="inputCapacity" asp-for="Event.Capacity" class="form-control" placeholder="Capacity"> |
|
||||
<label for="inputCapacity">Capacity</label> |
|
||||
<span asp-validation-for="Event.Capacity" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6 event-location-group"> |
|
||||
<select asp-for="Event.CountryId" asp-items="Model.Countries" class="form-select"> |
|
||||
<option selected="" value="">Country</option> |
|
||||
</select> |
|
||||
<span asp-validation-for="Event.CountryId" class="text-danger"></span> |
|
||||
</div> |
|
||||
<div class="col-md-6 event-location-group"> |
|
||||
<div class="form-label-group"> |
|
||||
<input type="text" id="inputCity" asp-for="Event.City" class="form-control" placeholder="City"> |
|
||||
<label for="inputCity">City</label> |
|
||||
<span asp-validation-for="Event.City" class="text-danger"></span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="col-md-6"> |
|
||||
<select asp-for="Event.Language" asp-items="Model.Languages" aria-label="en" class="form-select"> |
|
||||
<option selected value="">Language</option> |
|
||||
</select> |
|
||||
<span asp-validation-for="Event.Language" class="text-danger"></span> |
|
||||
</div> |
|
||||
<div class="col-md-12 text-end"> |
|
||||
<button type="submit" class="btn btn-primary btn-lg"> |
|
||||
Publish New Event |
|
||||
</button> |
|
||||
</div> |
|
||||
</div> |
</div> |
||||
</div> |
|
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
} |
||||
</div> |
else |
||||
</div> |
{ |
||||
</form> |
@await Component.InvokeAsync(typeof(CreateOrEditEventAreaViewComponent), new |
||||
} |
{ |
||||
|
eventUrlCode = Model.EventUrlCode, |
||||
|
stepType = CreateOrEditEventAreaViewComponent.ProgressStepType.Event |
||||
|
}) |
||||
|
} |
||||
|
</div> |
||||
|
|||||
@ -1,180 +1,52 @@ |
|||||
using System; |
using System; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
using System.ComponentModel; |
|
||||
using System.ComponentModel.DataAnnotations; |
|
||||
using System.Globalization; |
|
||||
using System.IO; |
|
||||
using System.Linq; |
using System.Linq; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
using EventHub.Events; |
using EventHub.Events; |
||||
using EventHub.Organizations; |
using EventHub.Organizations; |
||||
using EventHub.Web.Helpers; |
|
||||
using JetBrains.Annotations; |
|
||||
using Microsoft.AspNetCore.Http; |
|
||||
using Microsoft.AspNetCore.Mvc; |
using Microsoft.AspNetCore.Mvc; |
||||
using Microsoft.AspNetCore.Mvc.Rendering; |
|
||||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; |
|
||||
using Volo.Abp.Content; |
|
||||
using Volo.Abp.Users; |
using Volo.Abp.Users; |
||||
|
|
||||
namespace EventHub.Web.Pages.Events |
namespace EventHub.Web.Pages.Events |
||||
{ |
{ |
||||
public class NewPageModel : EventHubPageModel |
public class NewPageModel : EventHubPageModel |
||||
{ |
{ |
||||
[BindProperty] |
[BindProperty(SupportsGet = true)] |
||||
public NewEventViewModel Event { get; set; } |
public string EventUrlCode { get; set; } |
||||
|
|
||||
public List<SelectListItem> Organizations { get; private set; } |
[BindProperty(SupportsGet = true)] |
||||
public List<SelectListItem> Countries { get; private set; } |
public bool IsCreateNew { get; set; } |
||||
public List<SelectListItem> Languages { get; private set; } |
|
||||
|
public bool IsHasOrganizations { get; set; } |
||||
|
|
||||
|
public List<EventInListDto> DraftEventList { get; set; } |
||||
|
|
||||
private readonly IEventAppService _eventAppService; |
private readonly IEventAppService _eventAppService; |
||||
private readonly IOrganizationAppService _organizationAppService; |
private readonly IOrganizationAppService _organizationAppService; |
||||
|
|
||||
public NewPageModel( |
public NewPageModel( |
||||
IEventAppService eventAppService, |
IEventAppService eventAppService, |
||||
IOrganizationAppService organizationAppService) |
IOrganizationAppService organizationAppService) |
||||
{ |
{ |
||||
_eventAppService = eventAppService; |
_eventAppService = eventAppService; |
||||
_organizationAppService = organizationAppService; |
_organizationAppService = organizationAppService; |
||||
|
|
||||
|
DraftEventList = new List<EventInListDto>(); |
||||
} |
} |
||||
|
|
||||
public async Task OnGetAsync() |
public async Task OnGetAsync() |
||||
{ |
{ |
||||
Event = new NewEventViewModel |
IsHasOrganizations = (await _organizationAppService.GetOrganizationsByUserIdAsync(CurrentUser.GetId())).Items.Any(); |
||||
{ |
|
||||
StartTime = DateTime.Now.ClearTime().AddDays(1).AddHours(19), |
|
||||
EndTime = DateTime.Now.ClearTime().AddDays(1).AddHours(21) |
|
||||
}; |
|
||||
|
|
||||
await FillOrganizationsAsync(); |
if (!EventUrlCode.IsNullOrWhiteSpace()) |
||||
await FillCountriesAsync(); |
|
||||
FillLanguages(); |
|
||||
} |
|
||||
|
|
||||
public async Task<IActionResult> OnPostAsync() |
|
||||
{ |
|
||||
try |
|
||||
{ |
{ |
||||
ValidateModel(); |
return; |
||||
|
|
||||
var createEventDto = ObjectMapper.Map<NewEventViewModel, CreateEventDto>(Event); |
|
||||
|
|
||||
await using var memoryStream = new MemoryStream(); |
|
||||
if (Event.CoverImageFile != null && Event.CoverImageFile.Length > 0) |
|
||||
{ |
|
||||
await Event.CoverImageFile.CopyToAsync(memoryStream); |
|
||||
memoryStream.Position = 0; |
|
||||
|
|
||||
createEventDto.CoverImageStreamContent = new RemoteStreamContent(memoryStream, fileName: Event.CoverImageFile.FileName, contentType: Event.CoverImageFile.ContentType); |
|
||||
} |
|
||||
|
|
||||
var eventDto = await _eventAppService.CreateAsync(createEventDto); |
|
||||
await memoryStream.DisposeAsync(); |
|
||||
|
|
||||
return RedirectToPage("/Events/Detail", new {url = eventDto.UrlCode}); |
|
||||
} |
} |
||||
catch (Exception exception) |
|
||||
|
if (IsHasOrganizations && !IsCreateNew) |
||||
{ |
{ |
||||
ShowAlert(exception); |
DraftEventList = await _eventAppService.GetDraftEventsByCurrentUser(); |
||||
await FillOrganizationsAsync(); |
|
||||
await FillCountriesAsync(); |
|
||||
FillLanguages(); |
|
||||
return Page(); |
|
||||
} |
} |
||||
} |
} |
||||
|
|
||||
private async Task FillOrganizationsAsync() |
|
||||
{ |
|
||||
var result = await _organizationAppService.GetOrganizationsByUserIdAsync(CurrentUser.GetId()); |
|
||||
Organizations = result.Items.Select( |
|
||||
organization => new SelectListItem |
|
||||
{ |
|
||||
Value = organization.Id.ToString(), |
|
||||
Text = organization.DisplayName |
|
||||
} |
|
||||
).ToList(); |
|
||||
} |
|
||||
|
|
||||
private async Task FillCountriesAsync() |
|
||||
{ |
|
||||
var result = await _eventAppService.GetCountriesLookupAsync(); |
|
||||
|
|
||||
Countries = result.Select( |
|
||||
country => new SelectListItem |
|
||||
{ |
|
||||
Value = country.Id.ToString(), |
|
||||
Text = country.Name |
|
||||
} |
|
||||
).ToList(); |
|
||||
} |
|
||||
|
|
||||
private void FillLanguages() |
|
||||
{ |
|
||||
var result = CultureInfo.GetCultures(CultureTypes.NeutralCultures) |
|
||||
.DistinctBy(x => x.EnglishName) |
|
||||
.OrderBy(x => x.EnglishName) |
|
||||
.ToList(); |
|
||||
result.Remove(result.Single(x => x.TwoLetterISOLanguageName == "iv")); // Invariant Language
|
|
||||
|
|
||||
Languages = result.Select( |
|
||||
cultureInfo => new SelectListItem |
|
||||
{ |
|
||||
Value = cultureInfo.TwoLetterISOLanguageName, |
|
||||
Text = cultureInfo.EnglishName |
|
||||
} |
|
||||
).ToList(); |
|
||||
} |
|
||||
|
|
||||
public class NewEventViewModel |
|
||||
{ |
|
||||
[SelectItems(nameof(Organizations))] |
|
||||
[DisplayName("Organization")] |
|
||||
public Guid OrganizationId { get; set; } |
|
||||
|
|
||||
[Required] |
|
||||
[StringLength(EventConsts.MaxTitleLength, MinimumLength = EventConsts.MinTitleLength)] |
|
||||
public string Title { get; set; } |
|
||||
|
|
||||
[Required] |
|
||||
[DataType(DataType.DateTime)] |
|
||||
public DateTime StartTime { get; set; } = DateTime.Now; |
|
||||
|
|
||||
[Required] |
|
||||
[DataType(DataType.DateTime)] |
|
||||
public DateTime EndTime { get; set; } = DateTime.Now; |
|
||||
|
|
||||
[Required] |
|
||||
[StringLength(EventConsts.MaxDescriptionLength, MinimumLength = EventConsts.MinDescriptionLength)] |
|
||||
[TextArea] |
|
||||
public string Description { get; set; } |
|
||||
|
|
||||
[CanBeNull] |
|
||||
[Display(Name = "Cover Image")] |
|
||||
[DataType(DataType.Upload)] |
|
||||
[MaxFileSize(EventConsts.MaxCoverImageFileSize)] |
|
||||
[AllowedExtensions(new string[] {".jpg", ".png", ".jpeg"})] |
|
||||
public IFormFile CoverImageFile { get; set; } |
|
||||
|
|
||||
[Required] public bool? IsOnline { get; set; } |
|
||||
|
|
||||
[CanBeNull] |
|
||||
[StringLength(EventConsts.MaxOnlineLinkLength, MinimumLength = EventConsts.MinOnlineLinkLength)] |
|
||||
public string OnlineLink { get; set; } |
|
||||
|
|
||||
[SelectItems(nameof(Countries))] |
|
||||
[DisplayName("Country")] |
|
||||
public Guid? CountryId { get; set; } |
|
||||
|
|
||||
[CanBeNull] |
|
||||
[StringLength(EventConsts.MaxCityLength, MinimumLength = EventConsts.MinCityLength)] |
|
||||
public string City { get; set; } |
|
||||
|
|
||||
[SelectItems(nameof(Languages))] |
|
||||
[DisplayName("Language")] |
|
||||
public string Language { get; set; } |
|
||||
|
|
||||
[Range(1, int.MaxValue)] public int? Capacity { get; set; } |
|
||||
} |
|
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,94 +0,0 @@ |
|||||
$(function () { |
|
||||
var l = abp.localization.getResource('EventHub'); |
|
||||
|
|
||||
var isOnline = $("#Event_IsOnline option:selected").val() |
|
||||
if (isOnline === "True") { |
|
||||
$(".event-link-group").show(); |
|
||||
$(".event-location-group").hide(); |
|
||||
} else { |
|
||||
$(".event-link-group").hide(); |
|
||||
$(".event-location-group").show(); |
|
||||
} |
|
||||
|
|
||||
$('#Event_IsOnline').on('change', '', function () { |
|
||||
var isOnline = $("#Event_IsOnline option:selected").val() |
|
||||
if (isOnline === "True") { |
|
||||
$("#Event_CountryId").attr("required", false); |
|
||||
$("#inputCity").attr("required", false); |
|
||||
$(".event-link-group").show(); |
|
||||
$(".event-location-group").hide(); |
|
||||
} else { |
|
||||
$("#Event_CountryId").attr("required", true); |
|
||||
$("#inputCity").attr("required", true); |
|
||||
$(".event-link-group").hide(); |
|
||||
$(".event-location-group").show(); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
var infoArea = document.getElementById('upload-label'); |
|
||||
var fileInput = document.getElementById('Event_CoverImageFile'); |
|
||||
var file; |
|
||||
|
|
||||
if (fileInput !== null) { |
|
||||
fileInput.addEventListener('change', function () { |
|
||||
var showFile = true; |
|
||||
|
|
||||
file = fileInput.files[0]; |
|
||||
|
|
||||
if (file === undefined) { |
|
||||
$('#Event_CoverImageFile').val(''); |
|
||||
$('#imageResult').attr('src', '#'); |
|
||||
infoArea.textContent = 'Choose file' |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var permittedExtensions = ["jpg", "jpeg", "png"] |
|
||||
var fileExtension = $(this).val().split('.').pop(); |
|
||||
if (permittedExtensions.indexOf(fileExtension) === -1) { |
|
||||
showFile = false; |
|
||||
abp.message.error(l('EventCoverImageExtensionNotAllowed')) |
|
||||
.then(() => { |
|
||||
$('#Event_CoverImageFile').val(''); |
|
||||
file = null; |
|
||||
}); |
|
||||
} else if (file.size > 1024 * 1024) { |
|
||||
showFile = false; |
|
||||
abp.message.error(l('EventCoverImageSizeExceedMessage')) |
|
||||
.then(() => { |
|
||||
$('#Event_CoverImageFile').val(''); |
|
||||
file = null; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
var img = new Image(); |
|
||||
img.onload = function () { |
|
||||
var imageError = true; |
|
||||
var sizes = { |
|
||||
width: this.width, |
|
||||
height: this.height |
|
||||
}; |
|
||||
URL.revokeObjectURL(this.src); |
|
||||
|
|
||||
if (showFile && imageError) { |
|
||||
readURL(file); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
var objectURL = URL.createObjectURL(file); |
|
||||
img.src = objectURL; |
|
||||
}); |
|
||||
|
|
||||
function readURL(input) { |
|
||||
if (input) { |
|
||||
var reader = new FileReader(); |
|
||||
|
|
||||
reader.onload = function (e) { |
|
||||
$('#imageResult').attr('src', e.target.result); |
|
||||
infoArea.textContent = 'File name: ' + input.name; |
|
||||
} |
|
||||
|
|
||||
reader.readAsDataURL(input); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
@ -0,0 +1,56 @@ |
|||||
|
@using EventHub.Web.PaymentRequests |
||||
|
@using Microsoft.Extensions.Options |
||||
|
@model EventHub.Organizations.OrganizationProfileDto |
||||
|
@inject IOptionsSnapshot<PremiumPlanInfoOptions> PremiumPlanInfoOptionsSnapshot |
||||
|
|
||||
|
<abp-container class="mt-4"> |
||||
|
<abp-row> |
||||
|
@if (Model.IsPremium && PremiumPlanInfoOptionsSnapshot.Value.IsActive && PremiumPlanInfoOptionsSnapshot.Value.IsExtendable && Model.PremiumEndDate!.Value.IsBetween(DateTime.Now, DateTime.Now.AddMonths(PremiumPlanInfoOptionsSnapshot.Value.OnePremiumPeriodAsMonth - PremiumPlanInfoOptionsSnapshot.Value.CanBeExtendedAfterHowManyMonths))) |
||||
|
{ |
||||
|
<span class="mb-2 ms-5 text-center strong">Premium end date: @Model.PremiumEndDate!.Value.ToShortDateString()</span> |
||||
|
} |
||||
|
<abp-column> |
||||
|
<a href="/organization/edit/@Model.Name" class="btn btn-success text-white">Edit</a> |
||||
|
</abp-column> |
||||
|
<abp-column size="_9"> |
||||
|
@if (PremiumPlanInfoOptionsSnapshot.Value.IsActive) |
||||
|
{ |
||||
|
@if (Model.IsPremium) |
||||
|
{ |
||||
|
@if (PremiumPlanInfoOptionsSnapshot.Value.IsExtendable && Model.PremiumEndDate!.Value.IsBetween(DateTime.Now, DateTime.Now.AddMonths(PremiumPlanInfoOptionsSnapshot.Value.OnePremiumPeriodAsMonth - PremiumPlanInfoOptionsSnapshot.Value.CanBeExtendedAfterHowManyMonths))) |
||||
|
{ |
||||
|
<div class="d-grid gap-2"> |
||||
|
<a href="@Url.Page("/Pricing", new { organizationName = Model.Name })" class="btn btn-info"> |
||||
|
<i class="fas fa-crown me-2"></i> Extend Now |
||||
|
</a> |
||||
|
</div> |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<div class="d-grid gap-2"> |
||||
|
<button class="btn btn-info"> |
||||
|
<span class="mt-2">Premium end date: @Model.PremiumEndDate!.Value.ToShortDateString()</span> |
||||
|
</button> |
||||
|
</div> |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<div class="d-grid gap-2"> |
||||
|
<a href="@Url.Page("/Pricing", new { organizationName = Model.Name })" class="btn btn-info"> |
||||
|
<i class="fas fa-crown me-2"></i> Upgrade To @PremiumPlanInfoOptionsSnapshot.Value.PlanType |
||||
|
</a> |
||||
|
</div> |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
<abp-card class="text-center"> |
||||
|
<abp-card-body> |
||||
|
<span>Premium end date: @Model.PremiumEndDate!.Value.ToShortDateString()</span> |
||||
|
</abp-card-body> |
||||
|
</abp-card> |
||||
|
} |
||||
|
</abp-column> |
||||
|
</abp-row> |
||||
|
</abp-container> |
||||
@ -1,13 +1,36 @@ |
|||||
$(function () { |
$(function () { |
||||
$('.events > .nav-item > a[data-toggle="tab"]').on('shown.bs.tab', function (e) { |
$('.events > .nav-item > a[data-toggle="tab"]').on('shown.bs.tab', function (e) { |
||||
var target = $(e.target).attr("href") |
var target = $(e.target).attr("href") |
||||
if (target === "#UpcomingEvent"){ |
if (target === "#UpcomingEvent") { |
||||
$("a[href='#PastEvent']").removeClass('selected'); |
$("a[href='#PastEvent']").removeClass('selected'); |
||||
$("a[href='#UpcomingEvent']").addClass('selected'); |
$("a[href='#UpcomingEvent']").addClass('selected'); |
||||
|
|
||||
}else{ |
} else { |
||||
$("a[href='#UpcomingEvent']").removeClass('selected'); |
$("a[href='#UpcomingEvent']").removeClass('selected'); |
||||
$("a[href='#PastEvent']").addClass('selected'); |
$("a[href='#PastEvent']").addClass('selected'); |
||||
} |
} |
||||
}); |
}); |
||||
}); |
|
||||
|
var searchParams = new URLSearchParams(window.location.search); |
||||
|
var paymentRequestId = searchParams.get('paymentRequestId'); |
||||
|
if (paymentRequestId.length === 36) { |
||||
|
payment.paymentRequests.paymentRequest |
||||
|
.get(paymentRequestId) |
||||
|
.then(function (r) { |
||||
|
if (r.extraProperties.Status === "COMPLETED") { |
||||
|
Swal.fire({ |
||||
|
title: 'Thank you for your purchase!', |
||||
|
text: 'Your Organization has been upgraded to Premium.', |
||||
|
imageUrl: '/assets/success.svg', |
||||
|
imageHeight: "70", |
||||
|
imageWidth: "70", |
||||
|
showCloseButton: true, |
||||
|
confirmButtonText: 'Close' |
||||
|
}).then(() => { |
||||
|
window.location.replace(window.location.pathname) |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|||||
@ -0,0 +1,77 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using EventHub.Organizations; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Newtonsoft.Json; |
||||
|
using Payment.PaymentRequests; |
||||
|
using Payment.Web; |
||||
|
using Payment.Web.Pages.Payment; |
||||
|
using Payment.Web.PaymentRequest; |
||||
|
|
||||
|
namespace EventHub.Web.Pages.Payment; |
||||
|
|
||||
|
public class CustomPostCheckoutPageModel : PostCheckoutPageModel |
||||
|
{ |
||||
|
public string OrganizationName { get; set; } |
||||
|
|
||||
|
public CustomPostCheckoutPageModel( |
||||
|
IPaymentRequestAppService appService, |
||||
|
IOptions<PaymentWebOptions> paymentWebOptions, |
||||
|
IPaymentUrlBuilder paymentUrlBuilder) |
||||
|
: base( |
||||
|
appService, |
||||
|
paymentWebOptions, |
||||
|
paymentUrlBuilder) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public override async Task<IActionResult> OnGetAsync() |
||||
|
{ |
||||
|
if (Token.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
return BadRequest(); |
||||
|
} |
||||
|
|
||||
|
PaymentRequest = await PaymentRequestAppService.CompleteAsync(Token); |
||||
|
|
||||
|
FillOrganizationName(); |
||||
|
PaymentWebOptions.PaymentSuccessfulCallbackUrl = Url.Page("/Organizations/Profile", new { name = OrganizationName }); |
||||
|
|
||||
|
GoBackLink = PaymentUrlBuilder.BuildCheckoutUrl(PaymentRequest.Id).AbsoluteUri; |
||||
|
|
||||
|
if (PaymentRequest.State == PaymentRequestState.Completed |
||||
|
&& !PaymentWebOptions.PaymentSuccessfulCallbackUrl.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
var callbackUrl = PaymentWebOptions.PaymentSuccessfulCallbackUrl + "?paymentRequestId=" + PaymentRequest.Id; |
||||
|
Response.Redirect(callbackUrl); |
||||
|
} |
||||
|
|
||||
|
if (PaymentRequest.State == PaymentRequestState.Failed |
||||
|
&& !PaymentWebOptions.PaymentFailureCallbackUrl.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
var callbackUrl = PaymentWebOptions.PaymentFailureCallbackUrl + "?paymentRequestId=" + PaymentRequest.Id; |
||||
|
Response.Redirect(callbackUrl); |
||||
|
} |
||||
|
|
||||
|
return Page(); |
||||
|
} |
||||
|
|
||||
|
private void FillOrganizationName() |
||||
|
{ |
||||
|
var isExistExtraProperties = PaymentRequest.ExtraProperties.TryGetValue(nameof(OrganizationPaymentRequestExtraParameterConfiguration), out var ExtraProperties); |
||||
|
if (!isExistExtraProperties) |
||||
|
{ |
||||
|
throw new BadHttpRequestException(""); |
||||
|
} |
||||
|
|
||||
|
var organizationPaymentExtraParameterConfiguration = JsonConvert.DeserializeObject<OrganizationPaymentRequestExtraParameterConfiguration>(ExtraProperties.ToString()); |
||||
|
if (organizationPaymentExtraParameterConfiguration is null) |
||||
|
{ |
||||
|
throw new BadHttpRequestException(""); |
||||
|
} |
||||
|
|
||||
|
OrganizationName = organizationPaymentExtraParameterConfiguration.OrganizationName; |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue