Skip to content

Commit 5502abb

Browse files
committed
Add shared draft status on admin summary
1 parent 88bfb2a commit 5502abb

8 files changed

Lines changed: 106 additions & 41 deletions

File tree

src/OrchardCoreContrib.Contents/Drivers/ShareDraftContentDriver.cs renamed to src/OrchardCoreContrib.Contents/Drivers/SharedDraftContentDriver.cs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111

1212
namespace OrchardCoreContrib.Contents.Drivers;
1313

14-
public sealed class ShareDraftContentDriver(
14+
public sealed class SharedDraftContentDriver(
1515
IAuthorizationService authorizationService,
1616
IHttpContextAccessor httpContextAccessor,
1717
ISharedDraftLinkService linkService,
1818
INotifier notifier,
19-
IHtmlLocalizer<ShareDraftContentDriver> H) : ContentDisplayDriver
19+
IHtmlLocalizer<SharedDraftContentDriver> H) : ContentDisplayDriver
2020
{
21-
public override async Task<IDisplayResult> EditAsync(ContentItem contentItem, BuildEditorContext context)
21+
public override async Task<IDisplayResult> DisplayAsync(ContentItem contentItem, BuildDisplayContext context)
2222
{
2323
var user = httpContextAccessor.HttpContext.User;
2424

@@ -27,9 +27,40 @@ public override async Task<IDisplayResult> EditAsync(ContentItem contentItem, Bu
2727
return null;
2828
}
2929

30-
return Initialize<ShareDraftViewModel>("Content_ShareDraftButton", model => model.ContentItem = contentItem)
30+
var model = new SharedDraftLinkViewModel();
31+
32+
var link = await linkService.GetActiveLinkAsync(contentItem.ContentItemId);
33+
34+
if (link is not null)
35+
{
36+
model.Link = link;
37+
model.GeneratedLink = linkService.GetGeneratedLink(link.Token);
38+
}
39+
40+
return Shape("SharedDraftStatus_SummaryAdmin", model)
3141
.RenderWhen(() => Task.FromResult(!contentItem.Published))
32-
.Location("Actions:30");
42+
.Location("SummaryAdmin", "Meta:15");
43+
}
44+
45+
public override async Task<IDisplayResult> EditAsync(ContentItem contentItem, BuildEditorContext context)
46+
{
47+
var user = httpContextAccessor.HttpContext.User;
48+
49+
if (!await authorizationService.AuthorizeAsync(user, ContentsPermissions.ShareDraftContent))
50+
{
51+
return null;
52+
}
53+
54+
var generatedLink = await linkService.GenerateLinkAsync(contentItem.ContentItemId);
55+
56+
var link = await linkService.GetActiveLinkAsync(contentItem.ContentItemId);
57+
58+
return Initialize<SharedDraftLinkViewModel>("Content_ShareDraftButton", model =>
59+
{
60+
model.Link = link;
61+
model.GeneratedLink = generatedLink;
62+
}).RenderWhen(() => Task.FromResult(!contentItem.Published))
63+
.Location("Actions:30");
3364
}
3465

3566
public override async Task<IDisplayResult> UpdateAsync(ContentItem contentItem, UpdateEditorContext context)
@@ -41,7 +72,7 @@ public override async Task<IDisplayResult> UpdateAsync(ContentItem contentItem,
4172
return null;
4273
}
4374

44-
var model = new ShareDraftViewModel();
75+
var model = new SharedDraftLinkViewModel();
4576

4677
await context.Updater.TryUpdateModelAsync(model, Prefix);
4778

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
using OrchardCore.ContentManagement;
2+
using OrchardCoreContrib.Contents.Models;
23

34
namespace OrchardCoreContrib.Contents.Services;
45

56
public interface ISharedDraftLinkService
67
{
7-
Task<string> GenerateLinkAsync(ContentItem contentItem);
8+
Task<string> GenerateLinkAsync(string contentItemId);
9+
10+
string GetGeneratedLink(string token);
811

912
Task<ContentItem> GetDraftContentAsync(string token);
1013

1114
Task<int> CleanupExpiredLinksAsync();
1215

1316
Task<bool> RevokeLinkAsync(string contentItemId);
17+
18+
Task<SharedDraftLink> GetActiveLinkAsync(string contentItemId);
1419
}

src/OrchardCoreContrib.Contents/Services/SharedDraftLinkService.cs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,36 @@
11
using Microsoft.AspNetCore.Http;
22
using OrchardCore.ContentManagement;
3+
using OrchardCore.Environment.Shell;
34
using OrchardCoreContrib.Contents.Indexes;
45
using OrchardCoreContrib.Contents.Models;
6+
using Parlot.Fluent;
57
using YesSql;
68

79
namespace OrchardCoreContrib.Contents.Services;
810

911
public class SharedDraftLinkService(
1012
IContentManager contentManager,
1113
IHttpContextAccessor httpContextAccessor,
12-
YesSql.ISession session) : ISharedDraftLinkService
14+
YesSql.ISession session,
15+
ShellSettings shellSettings) : ISharedDraftLinkService
1316
{
14-
public async Task<string> GenerateLinkAsync(ContentItem contentItem)
17+
public async Task<string> GenerateLinkAsync(string contentItemId)
1518
{
16-
ArgumentNullException.ThrowIfNull(contentItem);
19+
ArgumentException.ThrowIfNullOrEmpty(contentItemId);
1720

1821
var existingLink = await session.Query<SharedDraftLink, SharedDraftLinkIndex>()
19-
.Where(l => l.ContentItemId == contentItem.ContentItemId && l.ExpirationUtc > DateTime.UtcNow)
22+
.Where(l => l.ContentItemId == contentItemId && l.ExpirationUtc > DateTime.UtcNow)
2023
.FirstOrDefaultAsync();
2124

2225
if (existingLink is not null)
2326
{
24-
return $"/share/{existingLink.Token}";
27+
return GetGeneratedLink(existingLink.Token);
2528
}
2629

2730
var token = Guid.NewGuid().ToString("N");
2831
var link = new SharedDraftLink
2932
{
30-
ContentItemId = contentItem.ContentItemId,
33+
ContentItemId = contentItemId,
3134
Token = token,
3235
ExpirationUtc = DateTime.UtcNow.AddDays(30),
3336
CreatedBy = httpContextAccessor.HttpContext.User.Identity.Name,
@@ -36,7 +39,19 @@ public async Task<string> GenerateLinkAsync(ContentItem contentItem)
3639

3740
await session.SaveAsync(link);
3841

39-
return $"/share/{token}";
42+
return GetGeneratedLink(token);
43+
}
44+
45+
public string GetGeneratedLink(string token)
46+
{
47+
ArgumentException.ThrowIfNullOrEmpty(token);
48+
49+
var tenant = shellSettings.RequestUrlPrefix;
50+
var baseUrl = $"{httpContextAccessor.HttpContext.Request.Scheme}://{httpContextAccessor.HttpContext.Request.Host}";
51+
52+
return string.IsNullOrEmpty(tenant)
53+
? $"{baseUrl}/share/{token}"
54+
: $"{baseUrl}/{tenant}/share/{token}";
4055
}
4156

4257
public async Task<ContentItem> GetDraftContentAsync(string token)
@@ -84,4 +99,13 @@ public async Task<bool> RevokeLinkAsync(string contentItemId)
8499

85100
return true;
86101
}
102+
103+
public async Task<SharedDraftLink> GetActiveLinkAsync(string contentItemId)
104+
{
105+
ArgumentException.ThrowIfNullOrEmpty(contentItemId);
106+
107+
return await session.Query<SharedDraftLink, SharedDraftLinkIndex>()
108+
.Where(l => l.ContentItemId == contentItemId && l.ExpirationUtc > DateTime.UtcNow)
109+
.FirstOrDefaultAsync();
110+
}
87111
}

src/OrchardCoreContrib.Contents/Startup.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public override void ConfigureServices(IServiceCollection services)
2222

2323
services.AddIndexProvider<SharedDraftLinkIndexProvider>();
2424

25-
services.AddScoped<IContentDisplayDriver, ShareDraftContentDriver>();
25+
services.AddScoped<IContentDisplayDriver, SharedDraftContentDriver>();
2626
services.AddScoped<ISharedDraftLinkService, SharedDraftLinkService>();
2727

2828
services.AddPermissionProvider<Permissions>();

src/OrchardCoreContrib.Contents/ViewModels/ShareDraftViewModel.cs

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Microsoft.AspNetCore.Mvc.ModelBinding;
2+
using OrchardCore.DisplayManagement.Views;
3+
using OrchardCoreContrib.Contents.Models;
4+
5+
namespace OrchardCoreContrib.Contents.ViewModels;
6+
7+
public class SharedDraftLinkViewModel : ShapeViewModel
8+
{
9+
[BindNever]
10+
public SharedDraftLink Link { get; set; }
11+
12+
[BindNever]
13+
public string GeneratedLink { get; set; }
14+
}

src/OrchardCoreContrib.Contents/Views/Content_ShareDraftButton.cshtml

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,9 @@
11
@using Microsoft.AspNetCore.Authorization
2-
@using OrchardCore.ContentManagement
3-
@using OrchardCore.Environment.Shell
42
@using OrchardCoreContrib.Contents
5-
@using OrchardCoreContrib.Contents.Models
6-
@using OrchardCoreContrib.Contents.Services
73
@using OrchardCoreContrib.Contents.ViewModels
8-
@model ShareDraftViewModel
9-
@inject ISharedDraftLinkService LinkService
10-
@inject ShellSettings ShellSettings
4+
@model SharedDraftLinkViewModel
115
@inject IAuthorizationService AuthorizationService
126

13-
@{
14-
var tenant = ShellSettings.RequestUrlPrefix;
15-
var link = await LinkService.GenerateLinkAsync(Model.ContentItem);
16-
var fullLink = string.IsNullOrEmpty(ShellSettings.RequestUrlPrefix)
17-
? $"{Context.Request.Scheme}://{Context.Request.Host}{link}"
18-
: $"{Context.Request.Scheme}://{Context.Request.Host}/{tenant}{link}";
19-
}
20-
217
<div class="btn-group mb-1">
228
<button type="button" class="btn btn-secondary" data-bs-toggle="modal" data-bs-target="#shareDraftModal">
239
@T["Share Draft"]
@@ -40,7 +26,7 @@
4026
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
4127
</div>
4228
<div class="modal-body">
43-
<input id="linkInput" type="text" class="form-control" readonly value="@fullLink" />
29+
<input id="linkInput" type="text" class="form-control" readonly value="@Model.GeneratedLink" />
4430
<button id="copyButton" type="button" class="btn btn-outline-secondary mt-2" onclick="copyUrl()">
4531
Copy to Clipboard
4632
</button>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
@using OrchardCoreContrib.Contents.ViewModels
2+
@model SharedDraftLinkViewModel
3+
4+
<span class="badge ta-badge font-weight-normal" data-bs-toggle="tooltip" title="@T["Shared Draft Status"]">
5+
@if (Model.Link is null)
6+
{
7+
<i class="fa-solid fa-link text-secondary" aria-hidden="true"></i>
8+
@T["Not Shared"]
9+
}
10+
else
11+
{
12+
<i class="fa-solid fa-link text-primary" aria-hidden="true"></i>
13+
<a class="text-primary" href="@Model.GeneratedLink" target="_blank">@T["Shared"]</a>
14+
}
15+
</span>

0 commit comments

Comments
 (0)