Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions editor-app/components/ActivityDiagram.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface Props {
rightClickActivity: (a: Activity) => void;
rightClickParticipation: (a: Activity, p: Participation) => void;
svgRef: MutableRefObject<any>;
hideNonParticipating?: boolean;
}

const ActivityDiagram = (props: Props) => {
Expand All @@ -34,6 +35,7 @@ const ActivityDiagram = (props: Props) => {
rightClickActivity,
rightClickParticipation,
svgRef,
hideNonParticipating = false,
} = props;

const [plot, setPlot] = useState({
Expand All @@ -53,7 +55,8 @@ const ActivityDiagram = (props: Props) => {
clickParticipation,
rightClickIndividual,
rightClickActivity,
rightClickParticipation
rightClickParticipation,
hideNonParticipating
)
);
}, [
Expand All @@ -67,6 +70,7 @@ const ActivityDiagram = (props: Props) => {
rightClickIndividual,
rightClickActivity,
rightClickParticipation,
hideNonParticipating,
]);

const buildCrumbs = () => {
Expand All @@ -78,12 +82,14 @@ const ActivityDiagram = (props: Props) => {
const text = act ? act.name : <i>{dataset.name ?? "Top"}</i>;
context.push(
<Breadcrumb.Item
active={ id == activityContext }
active={id == activityContext}
linkProps={{ onClick: () => setActivityContext(link) }}
key={id ?? "."}
>{text}</Breadcrumb.Item>);
if (id == undefined)
break;
>
{text}
</Breadcrumb.Item>
);
if (id == undefined) break;
id = act!.partOf;
}
return context.reverse();
Expand Down
96 changes: 77 additions & 19 deletions editor-app/components/ActivityDiagramWrap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ import { Model } from "@/lib/Model";
import { Activity, Id, Individual, Maybe, Participation } from "@/lib/Schema";
import ExportJson from "./ExportJson";
import ExportSvg from "./ExportSvg";
import { Button } from "react-bootstrap";
import HideIndividuals from "./HideIndividuals";
import React from "react";
import Card from "react-bootstrap/Card";
import DiagramLegend from "./DiagramLegend";

const beforeUnloadHandler = (ev: BeforeUnloadEvent) => {
ev.returnValue = "";
Expand All @@ -25,6 +30,8 @@ const beforeUnloadHandler = (ev: BeforeUnloadEvent) => {
/* XXX Most of this component needs refactoring into a Controller class,
* leaving the react component as just the View. */
export default function ActivityDiagramWrap() {
// compactMode hides individuals that participate in zero activities
const [compactMode, setCompactMode] = useState(false);
const model = new Model();
const [dataset, setDataset] = useState(model);
const [dirty, setDirty] = useState(false);
Expand All @@ -47,10 +54,8 @@ export default function ActivityDiagramWrap() {
const [showSortIndividuals, setShowSortIndividuals] = useState(false);

useEffect(() => {
if (dirty)
window.addEventListener("beforeunload", beforeUnloadHandler);
else
window.removeEventListener("beforeunload", beforeUnloadHandler);
if (dirty) window.addEventListener("beforeunload", beforeUnloadHandler);
else window.removeEventListener("beforeunload", beforeUnloadHandler);
}, [dirty]);

const updateDataset = (updater: Dispatch<Model>) => {
Expand Down Expand Up @@ -120,22 +125,45 @@ export default function ActivityDiagramWrap() {
const activitiesArray: Activity[] = [];
dataset.activities.forEach((a: Activity) => activitiesArray.push(a));

// Filter activities for the current context
let activitiesInView: Activity[] = [];
if (activityContext) {
// Only include activities that are part of the current context
activitiesInView = activitiesArray.filter(
(a) => a.partOf === activityContext
);
} else {
// Top-level activities (no parent)
activitiesInView = activitiesArray.filter((a) => !a.partOf);
}

return (
<>
<Container fluid>
<ActivityDiagram
dataset={dataset}
configData={configData}
activityContext={activityContext}
setActivityContext={setActivityContext}
clickIndividual={clickIndividual}
clickActivity={clickActivity}
clickParticipation={clickParticipation}
rightClickIndividual={rightClickIndividual}
rightClickActivity={rightClickActivity}
rightClickParticipation={rightClickParticipation}
svgRef={svgRef}
/>
<Row>
<Col xs="auto">
<DiagramLegend
activities={activitiesInView}
activityColors={config.presentation.activity.fill}
/>
</Col>
<Col>
<ActivityDiagram
dataset={dataset}
configData={configData}
activityContext={activityContext}
setActivityContext={setActivityContext}
clickIndividual={clickIndividual}
clickActivity={clickActivity}
clickParticipation={clickParticipation}
rightClickIndividual={rightClickIndividual}
rightClickActivity={rightClickActivity}
rightClickParticipation={rightClickParticipation}
svgRef={svgRef}
hideNonParticipating={compactMode}
/>
</Col>
</Row>
<Row className="mt-3 justify-content-between">
<Col className="d-flex justify-content-start">
<SetIndividual
Expand Down Expand Up @@ -176,12 +204,19 @@ export default function ActivityDiagramWrap() {
showSortIndividuals={showSortIndividuals}
setShowSortIndividuals={setShowSortIndividuals}
/>
<HideIndividuals
compactMode={compactMode}
setCompactMode={setCompactMode}
dataset={dataset}
activitiesInView={activitiesInView}
/>
</Col>
<Col className="d-flex justify-content-end">
<Undo
<Undo
hasUndo={undoHistory.length > 0}
undo={undo}
clearDiagram={clearDiagram}/>
clearDiagram={clearDiagram}
/>
<SetConfig
configData={configData}
setConfigData={setConfigData}
Expand All @@ -206,3 +241,26 @@ export default function ActivityDiagramWrap() {
</>
);
}

// Pass compactMode down to ActivityDiagram (already rendered above)
// Update ActivityDiagram invocation near top of file:

/*
Replace the existing ActivityDiagram invocation with:
<ActivityDiagram
dataset={dataset}
configData={configData}
activityContext={activityContext}
setActivityContext={setActivityContext}
clickIndividual={clickIndividual}
clickActivity={clickActivity}
clickParticipation={clickParticipation}
rightClickIndividual={rightClickIndividual}
rightClickActivity={rightClickActivity}
rightClickParticipation={rightClickParticipation}
svgRef={svgRef}
hideNonParticipating={compactMode}
/>

(The earlier invocation should be replaced so ActivityDiagram receives the prop.)
*/
48 changes: 48 additions & 0 deletions editor-app/components/DiagramLegend.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from "react";
import Card from "react-bootstrap/Card";
import { Activity } from "@/lib/Schema";

interface Props {
activities: Activity[];
activityColors: string[];
}

const DiagramLegend = ({ activities, activityColors }: Props) => (
<Card className="ms-3 mb-2" style={{ minWidth: 220 }}>
<Card.Body>
<Card.Title>Legend</Card.Title>
{activities.map((activity, idx) => (
<div key={activity.id} className="mb-1 d-flex align-items-center">
<span
style={{
display: "inline-block",
width: 16,
height: 16,
background: activityColors[idx % activityColors.length],
borderRadius: 3,
marginRight: 8,
border: "1px solid #888",
}}
/>
<span>{activity.name}</span>
</div>
))}
<div className="mt-2">
<span
style={{
display: "inline-block",
width: 16,
height: 16,
background: "#ccc",
borderRadius: 3,
marginRight: 8,
border: "1px solid #888",
}}
/>
<span>Not Participating</span>
</div>
</Card.Body>
</Card>
);

export default DiagramLegend;
118 changes: 75 additions & 43 deletions editor-app/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,55 +1,87 @@
import Link from "next/link";
import pkg from "../package.json";

function Footer() {
const style = {};
const year = new Date().getFullYear();

return (
<>
<div className="container">
<footer className="py-3 my-4">
<p className="border-bottom pb-3 mb-3">
</p>
<footer className="py-3 my-4">
<p className="border-bottom pb-3 mb-3"></p>

<div className="container">
<div className="row">
<div className="col-sm">
<h5>More</h5>
<ul className="list-unstyled text-small">
<li><Link className="text-muted" href="https://digitaltwinhub.co.uk/networks/29-the-apollo-protocol">Get in touch</Link></li>
<li><Link className="text-muted" href="https://github.com/Apollo-Protocol/4d-activity-editor/discussions">Give feedback</Link></li>
</ul>

</div>
<div className="col-sm">
<p className="text-center text-muted"><p className="text-center text-muted">2023 Apollo Protocol Activity Diagram Editor</p> <p className="text-center text-muted">Created by AMRC in collaboration with CIS</p>
<p className="text-center text-muted"> </p></p>
</div>
<div className="col-sm">

<div className="row mb-3">
<div className="col-sm text-center align-self-center">
<Link href="https://www.amrc.co.uk/">
<picture><img src="Logo_AMRC.png" className="rounded mw-100" alt="..."></img></picture>
</Link>

</div>
<div className="col-5">
<picture><img src="Logo_CIS.png" className="mw-100 float-right" alt="..."></img></picture>
</div>

</div>
<div className="container">
<div className="row">
<div className="col-sm">
<h5>More</h5>
<ul className="list-unstyled text-small">
<li>
<Link
className="text-muted"
href="https://digitaltwinhub.co.uk/networks/29-the-apollo-protocol"
>
Get in touch
</Link>
</li>
<li>
<Link
className="text-muted"
href="https://github.com/Apollo-Protocol/4d-activity-editor/discussions"
>
Give feedback
</Link>
</li>
</ul>
</div>
<div className="col-sm">
<div className="text-center text-muted">
<div>{year} Apollo Protocol Activity Diagram Editor</div>
<div>Created by AMRC in collaboration with CIS</div>
<div>Version: v{pkg.version}</div>
</div>
</div>
<div className="col-sm">
<div className="row mb-3">
<div className="col-sm text-center align-self-center">
<Link href="https://www.amrc.co.uk/">
<picture>
<img
src="Logo_AMRC.png"
className="rounded mw-100"
alt="..."
></img>
</picture>
</Link>
</div>
<div className="col-5">
<picture>
<img
src="Logo_CIS.png"
className="mw-100 float-right"
alt="..."
></img>
</picture>
</div>
</div>

<div className="row">
<div className="col-sm text-center align-self-center">
Funded by <picture><img src="Logo_InnovateUK.png" className="rounded w-25" alt="..."></img></picture>
</div>
</div>

</div>
</div>
</div>

</footer>
</div>
<div className="row">
<div className="col-sm text-center align-self-center">
Funded by{" "}
<picture>
<img
src="Logo_InnovateUK.png"
className="rounded w-25"
alt="..."
></img>
</picture>
</div>
</div>
</div>
</div>
</div>
</footer>
</div>
</>
);
}
Expand Down
Loading