Add Community Formula Library feature
Companies can now share their custom formula templates to a platform-wide community library. Other tenants can browse, preview, and import formulas as independent local copies. Includes attribution (source company name), "Inspired by" lineage for re-contributed formulas, import counts, own-formula badge, cascade diagram nullification, and AI assistant + help docs updates. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,7 @@ public class CompanySettingsController : Controller
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly IAzureBlobStorageService _blobStorage;
|
||||
private readonly ICustomFormulaAiService _formulaAiService;
|
||||
private readonly IFormulaLibraryService _formulaLibraryService;
|
||||
|
||||
public CompanySettingsController(
|
||||
IUnitOfWork unitOfWork,
|
||||
@@ -49,7 +50,8 @@ public class CompanySettingsController : Controller
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager,
|
||||
IAzureBlobStorageService blobStorage,
|
||||
ICustomFormulaAiService formulaAiService)
|
||||
ICustomFormulaAiService formulaAiService,
|
||||
IFormulaLibraryService formulaLibraryService)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_mapper = mapper;
|
||||
@@ -64,6 +66,7 @@ public class CompanySettingsController : Controller
|
||||
_signInManager = signInManager;
|
||||
_blobStorage = blobStorage;
|
||||
_formulaAiService = formulaAiService;
|
||||
_formulaLibraryService = formulaLibraryService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3080,6 +3083,11 @@ public class CompanySettingsController : Controller
|
||||
|
||||
_mapper.Map(dto, entity);
|
||||
entity.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
// If this was imported from the library, mark it as modified so the share button appears
|
||||
if (entity.SourceFormulaLibraryItemId.HasValue)
|
||||
entity.IsModifiedFromSource = true;
|
||||
|
||||
await _unitOfWork.CompleteAsync();
|
||||
|
||||
return Json(new { success = true });
|
||||
@@ -3100,6 +3108,52 @@ public class CompanySettingsController : Controller
|
||||
return Json(new { success = true });
|
||||
}
|
||||
|
||||
// ── Community Library: share / unshare / status ───────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// Returns the community library status for a given template: whether it is published,
|
||||
/// eligible to share, and where it was originally imported from if applicable.
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> FormulaLibraryStatus(int templateId)
|
||||
{
|
||||
if (!AllowCustomFormulas()) return Json(new { canShare = false });
|
||||
var companyId = _tenantContext.GetCurrentCompanyId()!.Value;
|
||||
var status = await _formulaLibraryService.GetTemplateLibraryStatusAsync(templateId, companyId);
|
||||
return Json(status);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Publishes a company template to the community library (or re-publishes after unshare).
|
||||
/// Only templates that are original creations or modified imports may be shared.
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> ShareFormula([FromBody] PowderCoating.Application.DTOs.Company.ShareFormulaRequest request)
|
||||
{
|
||||
if (!AllowCustomFormulas()) return Json(new { success = false, message = "Custom Formulas are not available on your current plan." });
|
||||
var companyId = _tenantContext.GetCurrentCompanyId()!.Value;
|
||||
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value ?? "";
|
||||
|
||||
try
|
||||
{
|
||||
var libraryItemId = await _formulaLibraryService.ShareAsync(companyId, userId, request);
|
||||
return Json(new { success = true, libraryItemId });
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Removes a template from the community library. Existing company imports are unaffected.</summary>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> UnshareFormula(int libraryItemId)
|
||||
{
|
||||
var companyId = _tenantContext.GetCurrentCompanyId()!.Value;
|
||||
await _formulaLibraryService.UnshareAsync(libraryItemId, companyId);
|
||||
return Json(new { success = true });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uploads a diagram image for a template to blob storage container
|
||||
/// <c>formulatemplate-diagrams/{companyId}/{templateId}/diagram.{ext}</c>.
|
||||
|
||||
Reference in New Issue
Block a user