Temp image fix

This commit is contained in:
Fergal Moran
2018-04-27 02:22:05 +01:00
parent 4d400d7d21
commit faa8a87c59
14 changed files with 413 additions and 41 deletions

View File

@@ -1,5 +1,4 @@
import { GlobalsService } from './services/globals.service';
import { CallbackComponent } from './components/callback/callback.component';
import { PodcastUploadFormComponent } from './components/podcast/podcast-upload-form/podcast-upload-form.component';
import { PodcastAddUrlFormComponent } from './components/podcast/podcast-add-url-form/podcast-add-url-form.component';
import { PodcastAddFormComponent } from './components/podcast/podcast-add-form/podcast-add-form.component';
@@ -70,7 +69,7 @@ import { PodNomsApiInterceptor } from './interceptors/podnoms-api.interceptor';
import { SideOverlayComponent } from './components/side-overlay/side-overlay.component';
import { UiStateService } from './services/ui-state.service';
let config = new AuthServiceConfig([
const config = new AuthServiceConfig([
{
id: GoogleLoginProvider.PROVIDER_ID,
provider: new GoogleLoginProvider('357461672895-2mevm3b10b4bd3gjdvugl00up8ba2n4m.apps.googleusercontent.com')
@@ -101,7 +100,6 @@ export function provideConfig() {
PodcastAddUrlFormComponent,
DebugComponent,
SidebarComponent,
CallbackComponent,
RegisterComponent,
ResetComponent,
ProfileComponent,

View File

@@ -1,7 +1,6 @@
import { ProfileComponent } from 'app/components/profile/profile.component';
import { ResetComponent } from 'app/components/reset/reset.component';
import { RegisterComponent } from 'app/components/register/register.component';
import { CallbackComponent } from 'app/components/callback/callback.component';
import { LoginComponent } from 'app/components/login/login.component';
import { DebugComponent } from 'app/components/debug/debug.component';
import { NgModule } from '@angular/core';
@@ -18,7 +17,6 @@ const routes: Routes = [
{ path: 'about', component: AboutComponent },
{ path: 'register', component: RegisterComponent },
{ path: 'reset', component: ResetComponent, pathMatch: 'full' },
{ path: 'callback', component: CallbackComponent },
{ path: 'debug', component: DebugComponent, canActivate: [AuthGuard] },
{ path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
{ path: 'podcasts', component: PodcastComponent, canActivate: [AuthGuard] },

View File

@@ -1,3 +0,0 @@
<div class="loading">
Loading......
</div>

View File

@@ -1,17 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { PodnomsAuthService } from 'app/services/podnoms-auth.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-callback',
templateUrl: './callback.component.html',
styleUrls: ['./callback.component.css']
})
export class CallbackComponent implements OnInit {
constructor(private _authService: PodnomsAuthService, private _router: Router) {}
ngOnInit() {
debugger;
this._router.navigate(['/podcasts']);
}
}

View File

@@ -33,8 +33,8 @@ export class EntriesEffects {
add$ = this.actions$
.ofType(entries.ADD)
.switchMap((action: entries.AddAction) =>
//this is probably (definitely) superfluous as we've now moved
//the addEntry into the component
// this is probably (definitely) superfluous as we've now moved
// the addEntry into the component
this._service.updateEntry(action.payload)
.map(res => {
console.log('EntriesEffects', 'add$', res);

View File

@@ -8,6 +8,7 @@ using Hangfire;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using PodNoms.Api.Models;
@@ -25,6 +26,9 @@ namespace PodNoms.Api.Controllers {
public class EntryController : BaseAuthController {
private readonly IPodcastRepository _podcastRepository;
private readonly IEntryRepository _repository;
public IConfiguration _options { get; }
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
private readonly IUrlProcessService _processor;
@@ -36,12 +40,14 @@ namespace PodNoms.Api.Controllers {
IPodcastRepository podcastRepository,
IUnitOfWork unitOfWork, IMapper mapper, IOptions<StorageSettings> storageSettings,
IOptions<AudioFileStorageSettings> audioFileStorageSettings,
IConfiguration options,
IUrlProcessService processor, ILoggerFactory logger,
UserManager<ApplicationUser> userManager,
IHttpContextAccessor contextAccessor) : base(contextAccessor, userManager) {
this._logger = logger.CreateLogger<EntryController>();
this._podcastRepository = podcastRepository;
this._repository = repository;
this._options = options;
this._storageSettings = storageSettings.Value;
this._unitOfWork = unitOfWork;
this._audioFileStorageSettings = audioFileStorageSettings.Value;
@@ -57,7 +63,10 @@ namespace PodNoms.Api.Controllers {
extractJobId, service => service.UploadAudio(entry.Id, entry.AudioUrl));
var notify = BackgroundJob.ContinueWith<INotifyJobCompleteService>(
uploadJobId, service => service.NotifyUser(entry.Podcast.AppUser.Id, "PodNoms", $"{entry.Title} has finished processing",
entry.Podcast.ImageUrl));
entry.Podcast.GetThumbnailUrl(
this._options.GetSection("Storage")["CdnUrl"],
this._options.GetSection("ImageFileStorageSettings")["ContainerName"])
));
} catch (InvalidOperationException ex) {
_logger.LogError($"Failed submitting job to processor\n{ex.Message}");
entry.ProcessingStatus = ProcessingStatus.Failed;

View File

@@ -63,7 +63,6 @@ namespace PodNoms.Api.Controllers {
var destinationFile = $"{podcast.Uid}.{extension}";
var destinationFileThumbnail = $"{podcast.Uid}-32x32.{extension}";
podcast.ImageUrl = destinationFile;
await _fileUploader.UploadFile(finishedFile, _imageFileStorageSettings.ContainerName,
destinationFile, "image/png", (p, t) => _logger.LogDebug($"Uploading image: {p} - {t}"));
@@ -72,7 +71,7 @@ namespace PodNoms.Api.Controllers {
destinationFileThumbnail, "image/png", (p, t) => _logger.LogDebug($"Uploading image: {p} - {t}"));
await _repository.AddOrUpdateAsync(podcast);
podcast.TemporaryImageUrl = string.Empty;
await this._unitOfWork.CompleteAsync();
return new OkObjectResult(_mapper.Map<Podcast, PodcastViewModel>(podcast));

View File

@@ -0,0 +1,365 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Migrations;
using PodNoms.Api.Persistence;
namespace PodNoms.Api.Migrations
{
[DbContext(typeof(PodnomsDbContext))]
[Migration("20180427010607_ImageUrlUpdates")]
partial class ImageUrlUpdates
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.0-preview2-30571")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider");
b.Property<string>("ProviderKey");
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider");
b.Property<string>("Name");
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreateDate");
b.Property<int>("PodcastId");
b.Property<string>("SourceUrl");
b.Property<DateTime>("UpdateDate");
b.HasKey("Id");
b.HasIndex("PodcastId");
b.ToTable("Playlists");
});
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("AppUserId");
b.Property<DateTime>("CreateDate")
.ValueGeneratedOnAdd()
.HasDefaultValueSql("getdate()");
b.Property<string>("Description");
b.Property<string>("Slug")
.IsUnicode(true);
b.Property<string>("TemporaryImageUrl");
b.Property<string>("Title");
b.Property<string>("Uid");
b.Property<DateTime>("UpdateDate");
b.HasKey("Id");
b.HasIndex("AppUserId");
b.ToTable("Podcasts");
});
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<long>("AudioFileSize");
b.Property<float>("AudioLength");
b.Property<string>("AudioUrl");
b.Property<string>("Author");
b.Property<DateTime>("CreateDate")
.ValueGeneratedOnAdd()
.HasDefaultValueSql("getdate()");
b.Property<string>("Description");
b.Property<string>("ImageUrl");
b.Property<int?>("PlaylistId");
b.Property<int>("PodcastId");
b.Property<bool>("Processed");
b.Property<string>("ProcessingPayload");
b.Property<int>("ProcessingStatus");
b.Property<string>("SourceUrl");
b.Property<string>("Title");
b.Property<string>("Uid");
b.Property<DateTime>("UpdateDate");
b.HasKey("Id");
b.HasIndex("PlaylistId");
b.HasIndex("PodcastId");
b.ToTable("PodcastEntries");
});
modelBuilder.Entity("PodNoms.Api.Services.Auth.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<long?>("FacebookId");
b.Property<string>("FirstName");
b.Property<string>("LastName");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("PictureUrl");
b.Property<string>("SecurityStamp");
b.Property<string>("Slug");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("PodNoms.Api.Models.Playlist", b =>
{
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
.WithMany()
.HasForeignKey("PodcastId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("PodNoms.Api.Models.Podcast", b =>
{
b.HasOne("PodNoms.Api.Services.Auth.ApplicationUser", "AppUser")
.WithMany()
.HasForeignKey("AppUserId");
});
modelBuilder.Entity("PodNoms.Api.Models.PodcastEntry", b =>
{
b.HasOne("PodNoms.Api.Models.Playlist")
.WithMany("PodcastEntries")
.HasForeignKey("PlaylistId");
b.HasOne("PodNoms.Api.Models.Podcast", "Podcast")
.WithMany("PodcastEntries")
.HasForeignKey("PodcastId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace PodNoms.Api.Migrations
{
public partial class ImageUrlUpdates : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "ImageUrl",
table: "Podcasts",
newName: "TemporaryImageUrl");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "TemporaryImageUrl",
table: "Podcasts",
newName: "ImageUrl");
}
}
}

View File

@@ -160,11 +160,11 @@ namespace PodNoms.Api.Migrations
b.Property<string>("Description");
b.Property<string>("ImageUrl");
b.Property<string>("Slug")
.IsUnicode(true);
b.Property<string>("TemporaryImageUrl");
b.Property<string>("Title");
b.Property<string>("Uid");

View File

@@ -11,17 +11,17 @@ namespace PodNoms.Api.Models {
public string Title { get; set; }
public string Description { get; set; }
public string Slug { get; set; }
public string ImageUrl { get; set; }
public string TemporaryImageUrl { get; set; }
public List<PodcastEntry> PodcastEntries { get; set; }
public Podcast() {
PodcastEntries = new List<PodcastEntry>();
}
public string GetImageUrl(string cdnUrl, string containerName) {
return $"{cdnUrl}{containerName}/{this.ImageUrl}";
return string.IsNullOrEmpty(TemporaryImageUrl) ? $"{cdnUrl}{containerName}/{this.Uid}.png" : TemporaryImageUrl;
}
public string GetThumnnailUrl(string cdnUrl, string containerName) {
return $"{cdnUrl}{containerName}/{this.Uid}-32x32.png";
public string GetThumbnailUrl(string cdnUrl, string containerName) {
return string.IsNullOrEmpty(TemporaryImageUrl) ? $"{cdnUrl}{containerName}/{this.Uid}-32x32.png" : TemporaryImageUrl;
}
}
}

View File

@@ -54,7 +54,7 @@ namespace PodNoms.Api.Persistence {
from p in _context.Podcasts
select p.Slug);
}
item.ImageUrl = $"standard/podcast-image-{Randomisers.RandomInteger(1, 16)}.png";
item.TemporaryImageUrl = $"standard/podcast-image-{Randomisers.RandomInteger(1, 16)}.png";
_context.Podcasts.Add(item);
}

View File

@@ -24,7 +24,7 @@ namespace PodNoms.Api.Providers {
this._options.GetSection("ImageFileStorageSettings")["ContainerName"])))
.ForMember(
v => v.ThumbnailUrl,
e => e.MapFrom(m => m.GetThumnnailUrl(
e => e.MapFrom(m => m.GetThumbnailUrl(
this._options.GetSection("Storage")["CdnUrl"],
this._options.GetSection("ImageFileStorageSettings")["ContainerName"])));
@@ -42,9 +42,7 @@ namespace PodNoms.Api.Providers {
map => map.MapFrom(s => s.PictureUrl));
//API Resource to Domain
CreateMap<PodcastViewModel, Podcast>()
.ForMember(v => v.ImageUrl, map => map.Ignore())
;
CreateMap<PodcastViewModel, Podcast>();
CreateMap<PodcastEntryViewModel, PodcastEntry>()
.ForMember(
e => e.ImageUrl,