Restore Scene Inspector V2 help integration.
This commit is contained in:
parent
fece540d14
commit
e02802ed5c
28
PlotLine/Help/Articles/SceneInspector/Suggestions.md
Normal file
28
PlotLine/Help/Articles/SceneInspector/Suggestions.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
title: Word Companion Suggestions
|
||||||
|
category: Scene Inspector
|
||||||
|
tags: scene inspector, word companion, suggestions, characters, assets, locations
|
||||||
|
contextKey: sceneInspector.suggestions
|
||||||
|
micro: Review suggested characters, assets and locations found by Word Companion.
|
||||||
|
quickTitle: Word Companion suggestions
|
||||||
|
quickSummary: Suggestions are proposed scene links from Word Companion that you can accept into the scene or reject when they are not useful.
|
||||||
|
screenshot:
|
||||||
|
---
|
||||||
|
|
||||||
|
# Overview
|
||||||
|
|
||||||
|
Word Companion suggestions are proposed connections between the current scene and story records such as characters, assets and locations.
|
||||||
|
|
||||||
|
Review each suggestion before accepting it. Accepting adds the suggested link to the scene. Rejecting clears the suggestion when it is not relevant or not useful.
|
||||||
|
|
||||||
|
# How To Use It
|
||||||
|
|
||||||
|
Use suggestions as a review queue, not as automatic truth. They are most helpful after drafting or importing text, when Word Companion has noticed names or places that may need to be connected to the scene.
|
||||||
|
|
||||||
|
If a suggestion is correct, accept it so the Scene Inspector and Timeline can use that evidence. If it is a false match, reject it so it no longer distracts you.
|
||||||
|
|
||||||
|
# Related Guides
|
||||||
|
|
||||||
|
- [Characters](/Help/Article/sceneInspector.characters)
|
||||||
|
- [Assets](/Help/Article/sceneInspector.assets)
|
||||||
|
- [Locations](/Help/Article/sceneInspector.locations)
|
||||||
@ -17,7 +17,10 @@
|
|||||||
<div class="scene-inspector-v2-card-header">
|
<div class="scene-inspector-v2-card-header">
|
||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">Continuity</p>
|
<p class="eyebrow">Continuity</p>
|
||||||
<h3>Scene health</h3>
|
<div class="scene-inspector-v2-heading">
|
||||||
|
<h3>Scene health</h3>
|
||||||
|
<help-icon key="sceneInspector.warnings" mode="inline" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary" data-scene-editor="warnings" data-scene-id="@Model.SceneID" data-scene-editor-url="@Url.Action("SceneContinuityEditor", "Warnings", new { sceneId = Model.SceneID })">Review warnings</button>
|
<button type="button" class="btn btn-sm btn-outline-primary" data-scene-editor="warnings" data-scene-id="@Model.SceneID" data-scene-editor-url="@Url.Action("SceneContinuityEditor", "Warnings", new { sceneId = Model.SceneID })">Review warnings</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,7 +2,15 @@
|
|||||||
<div class="scene-inspector-editor-shell">
|
<div class="scene-inspector-editor-shell">
|
||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">Focused editor</p>
|
<p class="eyebrow">Focused editor</p>
|
||||||
<h3 data-scene-editor-title>Focused editor</h3>
|
<div class="scene-inspector-editor-title-row">
|
||||||
|
<h3 data-scene-editor-title>Focused editor</h3>
|
||||||
|
<button type="button"
|
||||||
|
class="plotline-help-icon scene-inspector-editor-help"
|
||||||
|
data-scene-editor-help
|
||||||
|
data-help-open="sceneInspector.overview"
|
||||||
|
title="Open help for this editor"
|
||||||
|
aria-label="Open help for this editor">?</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary" data-scene-editor-close>Cancel</button>
|
<button type="button" class="btn btn-sm btn-outline-secondary" data-scene-editor-close>Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -20,7 +20,10 @@
|
|||||||
<div class="scene-inspector-v2-card-header scene-overview-v2-header">
|
<div class="scene-inspector-v2-card-header scene-overview-v2-header">
|
||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">Overview</p>
|
<p class="eyebrow">Overview</p>
|
||||||
<h3>@(string.IsNullOrWhiteSpace(Model.SceneTitle) ? "Untitled scene" : Model.SceneTitle)</h3>
|
<div class="scene-inspector-v2-heading">
|
||||||
|
<h3>@(string.IsNullOrWhiteSpace(Model.SceneTitle) ? "Untitled scene" : Model.SceneTitle)</h3>
|
||||||
|
<help-icon key="sceneInspector.overview" mode="inline" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="scene-overview-v2-controls">
|
<div class="scene-overview-v2-controls">
|
||||||
<span class="status-pill">@status</span>
|
<span class="status-pill">@status</span>
|
||||||
|
|||||||
@ -10,7 +10,10 @@
|
|||||||
<div class="scene-inspector-v2-card-header">
|
<div class="scene-inspector-v2-card-header">
|
||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">People</p>
|
<p class="eyebrow">People</p>
|
||||||
<h3>Characters and relationships</h3>
|
<div class="scene-inspector-v2-heading">
|
||||||
|
<h3>Characters and relationships</h3>
|
||||||
|
<help-icon key="sceneInspector.characters" mode="inline" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="scene-inspector-v2-actions">
|
<div class="scene-inspector-v2-actions">
|
||||||
<div class="btn-group scene-inspector-v2-action-menu">
|
<div class="btn-group scene-inspector-v2-action-menu">
|
||||||
|
|||||||
@ -12,7 +12,10 @@
|
|||||||
<div class="scene-inspector-v2-card-header">
|
<div class="scene-inspector-v2-card-header">
|
||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">Story</p>
|
<p class="eyebrow">Story</p>
|
||||||
<h3>Purpose and structure</h3>
|
<div class="scene-inspector-v2-heading">
|
||||||
|
<h3>Purpose and structure</h3>
|
||||||
|
<help-icon key="sceneInspector.purpose" mode="inline" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="scene-inspector-v2-actions">
|
<div class="scene-inspector-v2-actions">
|
||||||
<div class="btn-group scene-inspector-v2-action-menu">
|
<div class="btn-group scene-inspector-v2-action-menu">
|
||||||
|
|||||||
@ -14,7 +14,10 @@
|
|||||||
<div class="scene-inspector-v2-card-header">
|
<div class="scene-inspector-v2-card-header">
|
||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">World</p>
|
<p class="eyebrow">World</p>
|
||||||
<h3>Locations and assets</h3>
|
<div class="scene-inspector-v2-heading">
|
||||||
|
<h3>Locations and assets</h3>
|
||||||
|
<help-icon key="sceneInspector.locations" mode="inline" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="scene-inspector-v2-actions">
|
<div class="scene-inspector-v2-actions">
|
||||||
<div class="btn-group scene-inspector-v2-action-menu">
|
<div class="btn-group scene-inspector-v2-action-menu">
|
||||||
|
|||||||
@ -26,7 +26,10 @@
|
|||||||
<div class="scene-inspector-v2-card-header">
|
<div class="scene-inspector-v2-card-header">
|
||||||
<div>
|
<div>
|
||||||
<p class="eyebrow">Writer</p>
|
<p class="eyebrow">Writer</p>
|
||||||
<h3>Drafting support</h3>
|
<div class="scene-inspector-v2-heading">
|
||||||
|
<h3>Drafting support</h3>
|
||||||
|
<help-icon key="sceneInspector.writer" mode="inline" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="scene-inspector-v2-actions">
|
<div class="scene-inspector-v2-actions">
|
||||||
<div class="btn-group scene-inspector-v2-action-menu">
|
<div class="btn-group scene-inspector-v2-action-menu">
|
||||||
|
|||||||
@ -4627,6 +4627,23 @@ body.dragging-location [data-drag-type="location"] {
|
|||||||
line-height: 1.25;
|
line-height: 1.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scene-inspector-v2-heading,
|
||||||
|
.scene-inspector-editor-title-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene-inspector-v2-heading h3,
|
||||||
|
.scene-inspector-editor-title-row h3 {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene-inspector-v2-heading .plotline-help-icon-wrapper {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
.scene-inspector-v2-edit .scene-inspector-v2-card-header {
|
.scene-inspector-v2-edit .scene-inspector-v2-card-header {
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
@ -5100,6 +5117,10 @@ body.scene-inspector-editor-resizing {
|
|||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scene-inspector-editor-help {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
.scene-inspector-editor-empty {
|
.scene-inspector-editor-empty {
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|||||||
2
PlotLine/wwwroot/css/site.min.css
vendored
2
PlotLine/wwwroot/css/site.min.css
vendored
File diff suppressed because one or more lines are too long
@ -20,11 +20,41 @@
|
|||||||
warnings: "Review warnings"
|
warnings: "Review warnings"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const helpKeys = {
|
||||||
|
"scene-details": "sceneInspector.overview",
|
||||||
|
purpose: "sceneInspector.purpose",
|
||||||
|
metrics: "sceneMetrics.overview",
|
||||||
|
threads: "sceneInspector.threads",
|
||||||
|
dependencies: "sceneInspector.dependencies",
|
||||||
|
characters: "sceneInspector.characters",
|
||||||
|
attributes: "sceneInspector.characterAttributes",
|
||||||
|
suggestions: "sceneInspector.suggestions",
|
||||||
|
knowledge: "sceneInspector.knowledge",
|
||||||
|
relationships: "sceneInspector.relationships",
|
||||||
|
locations: "sceneInspector.locations",
|
||||||
|
assets: "sceneInspector.assets",
|
||||||
|
custody: "sceneInspector.custody",
|
||||||
|
notes: "sceneInspector.notes",
|
||||||
|
checklist: "sceneInspector.checklist",
|
||||||
|
workflow: "sceneInspector.writer",
|
||||||
|
attachments: "sceneInspector.attachments",
|
||||||
|
warnings: "sceneInspector.warnings"
|
||||||
|
};
|
||||||
|
|
||||||
function openOverlay(root, overlay, key) {
|
function openOverlay(root, overlay, key) {
|
||||||
const title = overlay.querySelector("[data-scene-editor-title]");
|
const title = overlay.querySelector("[data-scene-editor-title]");
|
||||||
if (title) {
|
if (title) {
|
||||||
title.textContent = titles[key] || "Focused editor";
|
title.textContent = titles[key] || "Focused editor";
|
||||||
}
|
}
|
||||||
|
const helpButton = overlay.querySelector("[data-scene-editor-help]");
|
||||||
|
if (helpButton) {
|
||||||
|
const helpKey = helpKeys[key] || "sceneInspector.overview";
|
||||||
|
const helpTitle = titles[key] || "this editor";
|
||||||
|
helpButton.dataset.helpOpen = helpKey;
|
||||||
|
helpButton.hidden = false;
|
||||||
|
helpButton.title = `Open help for ${helpTitle}`;
|
||||||
|
helpButton.setAttribute("aria-label", `Open help for ${helpTitle}`);
|
||||||
|
}
|
||||||
overlay.hidden = false;
|
overlay.hidden = false;
|
||||||
overlay.setAttribute("aria-hidden", "false");
|
overlay.setAttribute("aria-hidden", "false");
|
||||||
root.classList.add("editor-overlay-open");
|
root.classList.add("editor-overlay-open");
|
||||||
@ -43,6 +73,7 @@
|
|||||||
const body = overlay.querySelector("[data-scene-editor-body]");
|
const body = overlay.querySelector("[data-scene-editor-body]");
|
||||||
if (body) {
|
if (body) {
|
||||||
body.innerHTML = html;
|
body.innerHTML = html;
|
||||||
|
window.PlotLineHelpIcons?.init(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +106,7 @@
|
|||||||
const replacement = template.content.firstElementChild;
|
const replacement = template.content.firstElementChild;
|
||||||
if (replacement) {
|
if (replacement) {
|
||||||
current.replaceWith(replacement);
|
current.replaceWith(replacement);
|
||||||
|
window.PlotLineHelpIcons?.init(replacement);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -306,13 +306,13 @@
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
const icons = document.querySelectorAll("[data-help-icon]");
|
if (!window.bootstrap) {
|
||||||
if (!icons.length || !window.bootstrap) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const popovers = new Map();
|
const popovers = new Map();
|
||||||
let activeIcon = null;
|
let activeIcon = null;
|
||||||
|
const initializedIcons = new WeakSet();
|
||||||
|
|
||||||
const tooltipElement = (icon) => icon.querySelector("[data-help-tooltip]") || icon;
|
const tooltipElement = (icon) => icon.querySelector("[data-help-tooltip]") || icon;
|
||||||
const hideTooltip = (icon) => bootstrap.Tooltip.getInstance(tooltipElement(icon))?.hide();
|
const hideTooltip = (icon) => bootstrap.Tooltip.getInstance(tooltipElement(icon))?.hide();
|
||||||
@ -321,85 +321,104 @@
|
|||||||
bootstrap.Popover.getInstance(activeIcon)?.hide();
|
bootstrap.Popover.getInstance(activeIcon)?.hide();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const hideAllHelpTooltips = () => icons.forEach((icon) => hideTooltip(icon));
|
const allHelpIcons = () => document.querySelectorAll("[data-help-icon]");
|
||||||
|
const hideAllHelpTooltips = () => allHelpIcons().forEach((icon) => hideTooltip(icon));
|
||||||
|
const helpIconsIn = (scope) => {
|
||||||
|
if (!scope) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const icons = [];
|
||||||
|
if (scope.matches?.("[data-help-icon]")) {
|
||||||
|
icons.push(scope);
|
||||||
|
}
|
||||||
|
scope.querySelectorAll?.("[data-help-icon]").forEach((icon) => icons.push(icon));
|
||||||
|
return icons;
|
||||||
|
};
|
||||||
|
|
||||||
icons.forEach((icon) => {
|
const initHelpIcons = (scope = document) => {
|
||||||
const tooltipTarget = tooltipElement(icon);
|
helpIconsIn(scope).forEach((icon) => {
|
||||||
const micro = tooltipTarget.dataset.helpMicro || "Help article not found.";
|
if (initializedIcons.has(icon)) {
|
||||||
const title = icon.dataset.helpTitle || "Help unavailable";
|
|
||||||
const summary = icon.dataset.helpSummary || "Help content has not yet been written for this feature.";
|
|
||||||
|
|
||||||
bootstrap.Tooltip.getOrCreateInstance(tooltipTarget, {
|
|
||||||
title: micro,
|
|
||||||
trigger: "hover focus",
|
|
||||||
placement: "top",
|
|
||||||
container: "body"
|
|
||||||
});
|
|
||||||
|
|
||||||
const popover = bootstrap.Popover.getOrCreateInstance(icon, {
|
|
||||||
title,
|
|
||||||
trigger: "click",
|
|
||||||
placement: "auto",
|
|
||||||
container: "body",
|
|
||||||
html: true,
|
|
||||||
customClass: "plotline-help-popover",
|
|
||||||
content() {
|
|
||||||
const wrapper = document.createElement("div");
|
|
||||||
const summaryText = document.createElement("p");
|
|
||||||
summaryText.className = "mb-2";
|
|
||||||
summaryText.textContent = summary;
|
|
||||||
|
|
||||||
const moreLink = document.createElement("a");
|
|
||||||
moreLink.href = icon.dataset.helpUrl || "#";
|
|
||||||
moreLink.textContent = "More...";
|
|
||||||
moreLink.className = "plotline-help-more";
|
|
||||||
moreLink.addEventListener("click", (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
hideActivePopover();
|
|
||||||
hideAllHelpTooltips();
|
|
||||||
icon.dispatchEvent(new CustomEvent("plotline:help-more", {
|
|
||||||
bubbles: true,
|
|
||||||
detail: { key: icon.dataset.helpKey || "" }
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
wrapper.append(summaryText, moreLink);
|
|
||||||
return wrapper;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
popovers.set(icon, popover);
|
|
||||||
|
|
||||||
icon.addEventListener("click", (event) => {
|
|
||||||
if (!window.PlotLineHelpDrawer?.isActive?.()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
initializedIcons.add(icon);
|
||||||
|
|
||||||
|
const tooltipTarget = tooltipElement(icon);
|
||||||
|
const micro = tooltipTarget.dataset.helpMicro || "Help article not found.";
|
||||||
|
const title = icon.dataset.helpTitle || "Help unavailable";
|
||||||
|
const summary = icon.dataset.helpSummary || "Help content has not yet been written for this feature.";
|
||||||
|
|
||||||
|
bootstrap.Tooltip.getOrCreateInstance(tooltipTarget, {
|
||||||
|
title: micro,
|
||||||
|
trigger: "hover focus",
|
||||||
|
placement: "top",
|
||||||
|
container: "body"
|
||||||
|
});
|
||||||
|
|
||||||
|
const popover = bootstrap.Popover.getOrCreateInstance(icon, {
|
||||||
|
title,
|
||||||
|
trigger: "click",
|
||||||
|
placement: "auto",
|
||||||
|
container: "body",
|
||||||
|
html: true,
|
||||||
|
customClass: "plotline-help-popover",
|
||||||
|
content() {
|
||||||
|
const wrapper = document.createElement("div");
|
||||||
|
const summaryText = document.createElement("p");
|
||||||
|
summaryText.className = "mb-2";
|
||||||
|
summaryText.textContent = summary;
|
||||||
|
|
||||||
|
const moreLink = document.createElement("a");
|
||||||
|
moreLink.href = icon.dataset.helpUrl || "#";
|
||||||
|
moreLink.textContent = "More...";
|
||||||
|
moreLink.className = "plotline-help-more";
|
||||||
|
moreLink.addEventListener("click", (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
hideActivePopover();
|
||||||
|
hideAllHelpTooltips();
|
||||||
|
icon.dispatchEvent(new CustomEvent("plotline:help-more", {
|
||||||
|
bubbles: true,
|
||||||
|
detail: { key: icon.dataset.helpKey || "" }
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.append(summaryText, moreLink);
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
popovers.set(icon, popover);
|
||||||
|
|
||||||
|
icon.addEventListener("click", (event) => {
|
||||||
|
if (!window.PlotLineHelpDrawer?.isActive?.()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
hideActivePopover();
|
|
||||||
hideTooltip(icon);
|
|
||||||
window.PlotLineHelpPopovers?.hideAll();
|
|
||||||
window.PlotLineHelpDrawer.open(icon.dataset.helpKey || "");
|
|
||||||
});
|
|
||||||
icon.addEventListener("show.bs.popover", (event) => {
|
|
||||||
if (window.PlotLineHelpDrawer?.isActive?.()) {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return;
|
event.stopPropagation();
|
||||||
}
|
hideActivePopover();
|
||||||
|
hideTooltip(icon);
|
||||||
|
window.PlotLineHelpPopovers?.hideAll();
|
||||||
|
window.PlotLineHelpDrawer.open(icon.dataset.helpKey || "");
|
||||||
|
});
|
||||||
|
icon.addEventListener("show.bs.popover", (event) => {
|
||||||
|
if (window.PlotLineHelpDrawer?.isActive?.()) {
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
hideActivePopover(icon);
|
hideActivePopover(icon);
|
||||||
hideTooltip(icon);
|
hideTooltip(icon);
|
||||||
|
});
|
||||||
|
icon.addEventListener("shown.bs.popover", () => {
|
||||||
|
activeIcon = icon;
|
||||||
|
hideTooltip(icon);
|
||||||
|
});
|
||||||
|
icon.addEventListener("hidden.bs.popover", () => {
|
||||||
|
if (activeIcon === icon) {
|
||||||
|
activeIcon = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
icon.addEventListener("shown.bs.popover", () => {
|
};
|
||||||
activeIcon = icon;
|
|
||||||
hideTooltip(icon);
|
|
||||||
});
|
|
||||||
icon.addEventListener("hidden.bs.popover", () => {
|
|
||||||
if (activeIcon === icon) {
|
|
||||||
activeIcon = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener("click", (event) => {
|
document.addEventListener("click", (event) => {
|
||||||
const target = event.target instanceof Element ? event.target : null;
|
const target = event.target instanceof Element ? event.target : null;
|
||||||
@ -432,6 +451,10 @@
|
|||||||
activeIcon = null;
|
activeIcon = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
window.PlotLineHelpIcons = {
|
||||||
|
init: initHelpIcons
|
||||||
|
};
|
||||||
|
initHelpIcons();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
|
|||||||
2
PlotLine/wwwroot/js/site.min.js
vendored
2
PlotLine/wwwroot/js/site.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user