165 lines
8.1 KiB
Plaintext

@model StoryAssetEditViewModel
@{
ViewData["Title"] = Model.StoryAssetID == 0 ? "New Story Asset" : "Edit Story Asset";
}
<div class="page-heading compact">
<div>
<p class="eyebrow">Story asset</p>
<h1>@ViewData["Title"] <help-icon key="storyAssets.edit" /></h1>
</div>
</div>
@if (TempData["ImageError"] is string imageError)
{
<div class="alert alert-warning">@imageError</div>
}
<form asp-action="Save" method="post" class="edit-panel" enctype="multipart/form-data">
<input asp-for="StoryAssetID" type="hidden" />
<input asp-for="ProjectID" type="hidden" />
<input asp-for="ImagePath" type="hidden" />
<input asp-for="ThumbnailPath" type="hidden" />
<div class="row g-3">
<div class="col-md-8">
<label asp-for="AssetName" class="form-label"></label>
<input asp-for="AssetName" class="form-control" />
<span asp-validation-for="AssetName" class="text-danger"></span>
</div>
<div class="col-12">
<label class="form-label">Aliases</label>
<div class="d-flex flex-wrap gap-2 mb-2" data-alias-list>
@for (var i = 0; i < Model.Aliases.Count; i++)
{
<span class="badge rounded-pill text-bg-light border d-inline-flex align-items-center gap-2">
<span>@Model.Aliases[i]</span>
<button class="btn-close btn-close-sm" type="button" aria-label="Remove @Model.Aliases[i]" data-remove-alias></button>
<input type="hidden" name="Aliases" value="@Model.Aliases[i]" />
</span>
}
</div>
<div class="input-group">
<input class="form-control" type="text" maxlength="200" placeholder="Add an alias" data-alias-input />
<button class="btn btn-outline-secondary" type="button" data-add-alias>Add</button>
</div>
</div>
<div class="col-md-4">
<label asp-for="AssetKindID" class="form-label">Kind <help-icon key="storyAssets.fields.kind" mode="inline" /></label>
<select asp-for="AssetKindID" asp-items="Model.AssetKindOptions" class="form-select"></select>
</div>
<div class="col-md-4">
<div class="metric-slider">
<div class="metric-slider-label">
<label asp-for="Importance">Importance <help-icon key="storyAssets.fields.importance" mode="inline" /></label>
<output>@Model.Importance</output>
</div>
<input asp-for="Importance" type="range" class="form-range" min="1" max="10" oninput="this.previousElementSibling.querySelector('output').value = this.value" />
</div>
<span asp-validation-for="Importance" class="text-danger"></span>
</div>
<div class="col-md-4">
<label asp-for="CurrentStateID" class="form-label">Current state <help-icon key="storyAssets.fields.currentState" mode="inline" /></label>
<select asp-for="CurrentStateID" asp-items="Model.AssetStateOptions" class="form-select">
<option value="">No state</option>
</select>
</div>
<div class="col-md-4">
<label asp-for="CurrentLocationID" class="form-label">Current location <help-icon key="storyAssets.fields.currentLocation" mode="inline" /></label>
<select asp-for="CurrentLocationID" asp-items="Model.LocationOptions" class="form-select">
<option value="">No location</option>
</select>
</div>
<div class="col-md-4">
<div class="form-check story-asset-checkbox-field">
<input asp-for="IsResolved" class="form-check-input" />
<label asp-for="IsResolved" class="form-check-label">Resolved <help-icon key="storyAssets.fields.resolved" mode="inline" /></label>
</div>
</div>
<div class="col-md-4">
<div class="form-check story-asset-checkbox-field">
<input asp-for="ShowInQuickAddBar" class="form-check-input" />
<label asp-for="ShowInQuickAddBar" class="form-check-label">Show in Quick Add Bar <help-icon key="storyAssets.fields.quickAdd" mode="inline" /></label>
<div class="form-text">Makes this item available as a draggable shortcut on the Timeline page.</div>
</div>
</div>
<div class="col-12">
<label asp-for="Description" class="form-label"></label>
<textarea asp-for="Description" class="form-control" rows="5"></textarea>
</div>
<div class="col-12">
<div class="visual-image-editor">
<div>
<p class="eyebrow">Asset Image</p>
<partial name="_Avatar" model="@(new AvatarViewModel { DisplayName = Model.AssetName, ImagePath = Model.ImagePath, ThumbnailPath = Model.ThumbnailPath, Size = "lg", Lazy = false })" />
</div>
<div class="visual-image-editor__controls">
<label asp-for="ImageUpload" class="form-label"></label>
<input asp-for="ImageUpload" class="form-control" type="file" accept=".jpg,.jpeg,.png,.webp,image/jpeg,image/png,image/webp" />
<div class="form-text">JPG, PNG or WebP. A 128 x 128 thumbnail is generated automatically.</div>
@if (!string.IsNullOrWhiteSpace(Model.ImagePath) || !string.IsNullOrWhiteSpace(Model.ThumbnailPath))
{
<label class="form-check mt-2">
<input asp-for="RemoveImage" class="form-check-input" />
<span class="form-check-label">Remove image</span>
</label>
}
</div>
</div>
</div>
</div>
<div class="button-row mt-3">
<button class="btn btn-primary" type="submit">Save asset</button>
<a class="btn btn-outline-secondary" asp-action="Index" asp-route-projectId="@Model.ProjectID">Cancel</a>
</div>
</form>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
<script>
(() => {
const list = document.querySelector("[data-alias-list]");
const input = document.querySelector("[data-alias-input]");
const add = document.querySelector("[data-add-alias]");
if (!list || !input || !add) return;
const aliases = () => [...list.querySelectorAll("input[name='Aliases']")].map(x => x.value.toLowerCase());
const appendAlias = (value) => {
const alias = value.trim();
if (!alias || aliases().includes(alias.toLowerCase())) return;
const chip = document.createElement("span");
chip.className = "badge rounded-pill text-bg-light border d-inline-flex align-items-center gap-2";
const text = document.createElement("span");
text.textContent = alias;
const remove = document.createElement("button");
remove.className = "btn-close btn-close-sm";
remove.type = "button";
remove.setAttribute("aria-label", `Remove ${alias}`);
remove.dataset.removeAlias = "";
const hidden = document.createElement("input");
hidden.type = "hidden";
hidden.name = "Aliases";
hidden.value = alias;
chip.append(text, remove, hidden);
list.append(chip);
input.value = "";
};
add.addEventListener("click", () => appendAlias(input.value));
input.addEventListener("keydown", event => {
if (event.key === "Enter") {
event.preventDefault();
appendAlias(input.value);
}
});
list.addEventListener("click", event => {
if (event.target instanceof HTMLElement && event.target.matches("[data-remove-alias]")) {
event.target.closest(".badge")?.remove();
}
});
})();
</script>
}