Add Opportunities tab with calendar, event list, and Conference Scout
- New sidebar tab: side-by-side Events list and month calendar, with multi-day event bars spanning their date range (title + location) - Events: SPIE Optics + Photonics 2026, SEMICON Europa 2026 - New Conference Scout drill-view, hero button, and dedicated page wired to a scheduled cloud routine that sweeps the web weekly for conferences/seminars/networking events relevant to TXproducts (semiconductors, power electronics GaN/SiC, X-ray optics, photon/nanoscience, synchrotron/beamline science, and defense/ aerospace prospecting), syncing results in for manual review Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2ac38607c7
commit
6afaefc251
1 file changed
+467
-5
+467
-5
@@ -728,6 +728,86 @@
|
||||
background: #f0f4f8; border: 1px solid #e0e7ef; border-radius: 6px; padding: 4px 9px;
|
||||
}
|
||||
.links a:hover { border-color: #2d6a9f; }
|
||||
|
||||
/* ---------- Opportunities (calendar) ---------- */
|
||||
.opp-toolbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
|
||||
.opp-month-label { font-size: 1.15rem; font-weight: 800; color: #1b3a5c; }
|
||||
.opp-nav-btn {
|
||||
font-family: inherit; font-size: 0.85rem; font-weight: 700; color: #2d6a9f;
|
||||
background: #fff; border: 1px solid #e0e7ef; border-radius: 6px; padding: 6px 12px; cursor: pointer;
|
||||
}
|
||||
.opp-nav-btn:hover { background: #e8f0fe; }
|
||||
.opp-today-btn { margin-left: 8px; }
|
||||
.opp-cal-grid {
|
||||
border-top: 1px solid #e0e7ef; border-left: 1px solid #e0e7ef;
|
||||
}
|
||||
.opp-cal-weekdays, .opp-cal-week {
|
||||
display: grid; grid-template-columns: repeat(7, 1fr);
|
||||
}
|
||||
.opp-cal-week { position: relative; }
|
||||
.opp-cal-weekday {
|
||||
text-align: center; font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
|
||||
letter-spacing: 0.04em; color: #6b7a8d; padding: 8px 0;
|
||||
border-right: 1px solid #e0e7ef; border-bottom: 1px solid #e0e7ef; background: #f7f9fc;
|
||||
}
|
||||
.opp-cal-cell {
|
||||
min-height: 96px; border-right: 1px solid #e0e7ef; border-bottom: 1px solid #e0e7ef;
|
||||
padding: 8px;
|
||||
}
|
||||
.opp-cal-cell.outside { background: #fafbfc; }
|
||||
.opp-cal-cell.outside .opp-cal-daynum { color: #c3cdd8; }
|
||||
.opp-cal-daynum { font-size: 0.82rem; font-weight: 700; color: #1a2533; }
|
||||
.opp-cal-cell.today .opp-cal-daynum {
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
width: 22px; height: 22px; border-radius: 50%; background: #2d6a9f; color: #fff;
|
||||
}
|
||||
.opp-cal-event-bar {
|
||||
position: absolute; height: 20px; line-height: 20px; border-radius: 4px;
|
||||
background: #2d6a9f; color: #fff; font-size: 0.72rem; font-weight: 700;
|
||||
padding: 0 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||||
cursor: default;
|
||||
}
|
||||
.opp-cal-event-bar .opp-cal-event-title { color: #ffd43b; font-weight: 800; text-decoration: none; }
|
||||
a.opp-cal-event-title:hover { text-decoration: underline; }
|
||||
.opp-cal-event-bar .opp-cal-event-loc { color: #fff; font-weight: 600; opacity: 0.82; margin-left: 6px; }
|
||||
.opp-cal-event-bar.continues-left { border-top-left-radius: 0; border-bottom-left-radius: 0; }
|
||||
.opp-cal-event-bar.continues-right { border-top-right-radius: 0; border-bottom-right-radius: 0; }
|
||||
|
||||
#tab-opportunities .drill-view { padding: 0; }
|
||||
.opp-layout { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
|
||||
@media (max-width: 900px) { .opp-layout { grid-template-columns: 1fr; } }
|
||||
.opp-list-card { padding: 24px; }
|
||||
.opp-list-heading { margin: 0 0 16px; font-size: 1.05rem; font-weight: 800; color: #1b3a5c; }
|
||||
.opp-list { display: flex; flex-direction: column; gap: 10px; }
|
||||
.opp-list-empty { color: #6b7a8d; font-size: 0.9rem; }
|
||||
.opp-list-row {
|
||||
display: flex; align-items: flex-start; gap: 12px; padding: 12px;
|
||||
border: 1px solid #e0e7ef; border-radius: 8px; cursor: pointer;
|
||||
transition: border-color 0.15s, background 0.15s;
|
||||
}
|
||||
.opp-list-row:hover { border-color: #2d6a9f; background: #f7f9fc; }
|
||||
.opp-list-meta {
|
||||
flex: 0 0 128px; display: flex; flex-direction: column; gap: 3px;
|
||||
font-size: 0.82rem; line-height: 1.5;
|
||||
}
|
||||
.opp-list-dates { font-weight: 700; color: #1a2533; }
|
||||
.opp-list-loc, .opp-list-attendee { color: #6b7a8d; }
|
||||
.opp-list-link {
|
||||
display: inline-block; margin-top: 3px; font-size: 0.78rem; font-weight: 700;
|
||||
color: #2d6a9f; text-decoration: underline;
|
||||
}
|
||||
.opp-list-about { flex: 1; border-left: 1px solid #eef1f5; padding-left: 16px; }
|
||||
.opp-scout-note {
|
||||
background: #fbf0df; border: 1px solid #f3ddb8; border-radius: 8px;
|
||||
padding: 12px 14px; margin-bottom: 16px; font-size: 0.82rem; line-height: 1.55; color: #7a4a06;
|
||||
}
|
||||
.opp-scout-note strong { color: #b45f06; }
|
||||
.opp-list-badge {
|
||||
display: inline-block; background: #fbf0df; color: #b45f06; font-weight: 800;
|
||||
font-size: 0.78rem; border-radius: 20px; padding: 5px 12px; text-decoration: none; white-space: nowrap;
|
||||
}
|
||||
a.opp-list-badge:hover { text-decoration: underline; }
|
||||
.opp-list-abstract { margin: 8px 0 0; font-size: 0.82rem; line-height: 1.55; color: #3d4c5c; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -742,7 +822,7 @@
|
||||
|
||||
<div class="status-pill">
|
||||
<div class="label">Last Updated</div>
|
||||
<div class="value" id="sidebar-last-updated">Aug 12, 2026</div>
|
||||
<div class="value" id="sidebar-last-updated">Aug 17, 2026</div>
|
||||
</div>
|
||||
|
||||
<div class="nav-group">
|
||||
@@ -750,6 +830,7 @@
|
||||
<button class="sidebar-nav-btn" data-tab="address-book">Directory</button>
|
||||
<button class="sidebar-nav-btn" data-tab="marketing">Marketing</button>
|
||||
<button class="sidebar-nav-btn" data-tab="sales">Sales</button>
|
||||
<button class="sidebar-nav-btn" data-tab="opportunities">Opportunities</button>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
@@ -772,6 +853,9 @@
|
||||
<div class="hero-nav" id="hero-nav-conferences" style="display:none;">
|
||||
<button class="hero-nav-btn" id="hero-nav-conferences-btn">Conferences</button>
|
||||
</div>
|
||||
<div class="hero-nav" id="hero-nav-scout" style="display:none;">
|
||||
<button class="hero-nav-btn" id="hero-nav-scout-btn">Conference Scout</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4476,6 +4560,46 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tab-opportunities" class="tab-content">
|
||||
<div class="drill-crumbs" id="opp-crumbs" style="margin-bottom: 14px;"></div>
|
||||
|
||||
<div class="drill-view active" data-view="opportunities-root">
|
||||
<div class="opp-layout">
|
||||
<div class="card opp-list-card">
|
||||
<h3 class="opp-list-heading">Events</h3>
|
||||
<p class="narrative" style="max-width: none;">Conferences, events, and potential opportunities for TXproducts.</p>
|
||||
<div class="opp-list" id="opp-event-list"></div>
|
||||
</div>
|
||||
<div class="card opp-cal-card" style="padding: 0;">
|
||||
<div style="padding: 24px 32px 28px;">
|
||||
<div class="opp-toolbar">
|
||||
<div class="opp-month-label" id="opp-month-label"></div>
|
||||
<div>
|
||||
<button class="opp-nav-btn" id="opp-prev-btn">← Prev</button>
|
||||
<button class="opp-nav-btn opp-today-btn" id="opp-today-btn">Today</button>
|
||||
<button class="opp-nav-btn" id="opp-next-btn">Next →</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="opp-cal-grid" id="opp-cal-grid"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="drill-view" data-view="scout">
|
||||
<div class="card">
|
||||
<h2>Conference Scout</h2>
|
||||
<p class="narrative" style="max-width: none;">A scheduled research agent that sweeps the web every Monday morning for conferences, trade shows, seminars, and networking events relevant to TXproducts — semiconductors, power electronics (GaN/SiC), X-ray optics, photon/nanoscience, and defense/aerospace expansion prospecting. Review the candidates below, then add anything worth tracking to the Events list yourself — nothing here is added automatically.</p>
|
||||
<div class="opp-scout-note"><strong>Verification note:</strong> this run's sandbox blocked direct fetches to every official event site (even neutral test domains), so dates and locations below are cross-referenced across multiple independent search sources rather than confirmed on the primary page — double-check the official site before committing budget or travel. This is a fresh worldwide sweep (12 candidates, replacing the previous Europe-only list) spanning Asia, the Americas, Africa, and Europe, tagged "Existing focus area" or "Potential new business (defense)" per TXproducts' corrected scope: semiconductors/power electronics (GaN/SiC), X-ray optics, photon/nanoscience, synchrotron/beamline science, and defense/aerospace prospecting.</div>
|
||||
<div class="opp-list" id="opp-scout-list"></div>
|
||||
<div class="drill-actions" style="margin-top: 18px;">
|
||||
<button class="drill-back" data-target="opportunities-root">← Opportunities</button>
|
||||
<a class="open-link" href="https://claude.ai/code/routines/trig_01XRb81y9pAWDube5kjRUvGT" target="_blank" rel="noopener">Open Conference Scout ↗</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -4483,7 +4607,8 @@
|
||||
"team": ["Team", "Who's on marketing/sales and their roles."],
|
||||
"address-book": ["Directory", "One outreach board, fed by every branch — Marketing Intelligence, LinkedIn, and the boss's Outreach targets."],
|
||||
"marketing": ["Marketing", ""],
|
||||
"sales": ["Sales", ""]
|
||||
"sales": ["Sales", ""],
|
||||
"opportunities": ["Opportunities", ""]
|
||||
};
|
||||
var btns = document.querySelectorAll(".sidebar-nav-btn");
|
||||
btns.forEach(function (btn) {
|
||||
@@ -4504,8 +4629,8 @@
|
||||
|
||||
/* ---- Drill-downs: Marketing -> Social Media (dropdown) -> LinkedIn -> Dash
|
||||
Sales -> Market Intelligence -> site (goes there directly, one child today) ---- */
|
||||
var HERO_NAV_BY_TAB = { marketing: ["hero-nav-social", "hero-nav-conferences"] };
|
||||
var DRILL_DEFAULT_VIEW = { marketing: "marketing-root", sales: "market-intelligence" };
|
||||
var HERO_NAV_BY_TAB = { marketing: ["hero-nav-social", "hero-nav-conferences"], opportunities: ["hero-nav-scout"] };
|
||||
var DRILL_DEFAULT_VIEW = { marketing: "marketing-root", sales: "market-intelligence", opportunities: "opportunities-root" };
|
||||
var DRILL_CONFIG = {
|
||||
marketing: {
|
||||
crumbsEl: "mkt-crumbs",
|
||||
@@ -4521,6 +4646,13 @@
|
||||
"sales-root": [["Sales", "sales-root"]],
|
||||
"market-intelligence": [["Sales", "sales-root"], ["Intelligence Board", "market-intelligence"], ["Market Intelligence", "market-intelligence"]]
|
||||
}
|
||||
},
|
||||
opportunities: {
|
||||
crumbsEl: "opp-crumbs",
|
||||
crumbs: {
|
||||
"opportunities-root": [["Opportunities", "opportunities-root"]],
|
||||
"scout": [["Opportunities", "opportunities-root"], ["Conference Scout", "scout"]]
|
||||
}
|
||||
}
|
||||
};
|
||||
function setDrillView(scope, view) {
|
||||
@@ -4548,7 +4680,7 @@
|
||||
crumbsEl.appendChild(el);
|
||||
});
|
||||
}
|
||||
["marketing", "sales"].forEach(function (scope) {
|
||||
["marketing", "sales", "opportunities"].forEach(function (scope) {
|
||||
document.querySelectorAll("#tab-" + scope + " .drill-back, #tab-" + scope + " .drill-next").forEach(function (b) {
|
||||
b.addEventListener("click", function () { setDrillView(scope, b.getAttribute("data-target")); });
|
||||
});
|
||||
@@ -4576,6 +4708,9 @@
|
||||
document.getElementById("hero-nav-conferences-btn").addEventListener("click", function () {
|
||||
setDrillView("marketing", "conferences");
|
||||
});
|
||||
document.getElementById("hero-nav-scout-btn").addEventListener("click", function () {
|
||||
setDrillView("opportunities", "scout");
|
||||
});
|
||||
|
||||
/* ---- Conferences (Directory pattern: conference cards on the left, drill into
|
||||
its own presentation sub-directory on the right) ---- */
|
||||
@@ -5870,6 +6005,333 @@
|
||||
// Starting point: focus on the Outreach Board, filtered to Outreach, one contact selected.
|
||||
document.getElementById("ab-view-board-btn").click();
|
||||
document.querySelector(".ab-filter-chip[data-source=\"Outreach\"]").click();
|
||||
|
||||
/* ---------- Opportunities calendar ----------
|
||||
Each entry: { start: "YYYY-MM-DD", end: "YYYY-MM-DD" (defaults to start),
|
||||
title, location, attendee (optional) }.
|
||||
Multi-day entries render as one bar spanning their full date range;
|
||||
bars continuing past a week boundary lose the rounded corner on that side. */
|
||||
var OPPORTUNITIES = [
|
||||
{ start: "2026-08-23", end: "2026-08-27", title: "SPIE", location: "San Diego, CA", attendee: "Peter", url: "https://spie.org/conferences-and-exhibitions/optics-and-photonics",
|
||||
abstract: "SPIE's flagship annual optics and photonics conference and exhibition, held every August in San Diego since the 1960s. Brings together 10,000+ scientists, engineers, and industry professionals across optical engineering, nanoscience, quantum science, and organic photonics." },
|
||||
{ start: "2026-11-10", end: "2026-11-13", title: "SEMICON Europa", location: "Munich, Germany", url: "https://www.semiconeuropa.org/",
|
||||
abstract: "Semiconductor and electronics manufacturing trade show co-located with electronica in Munich. Covers fab management, advanced packaging, and smart manufacturing across the chip supply chain, drawing 8,000+ visitors from equipment vendors, fabs, and OSATs." }
|
||||
];
|
||||
var MONTH_NAMES = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
var MONTH_ABBR = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||||
var oppCursor = new Date();
|
||||
oppCursor.setDate(1);
|
||||
function oppKey(d) {
|
||||
return d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
|
||||
}
|
||||
function parseOppDate(s) {
|
||||
var parts = s.split("-").map(Number);
|
||||
return new Date(parts[0], parts[1] - 1, parts[2]);
|
||||
}
|
||||
function addOppDays(d, n) {
|
||||
var r = new Date(d);
|
||||
r.setDate(r.getDate() + n);
|
||||
return r;
|
||||
}
|
||||
function buildOppEvents() {
|
||||
return OPPORTUNITIES.map(function (o) {
|
||||
return {
|
||||
title: o.title, location: o.location, attendee: o.attendee, url: o.url, abstract: o.abstract,
|
||||
start: parseOppDate(o.start), end: parseOppDate(o.end || o.start)
|
||||
};
|
||||
}).sort(function (a, b) { return a.start - b.start; });
|
||||
}
|
||||
function formatOppDateRange(start, end) {
|
||||
if (start.getTime() === end.getTime()) {
|
||||
return MONTH_ABBR[start.getMonth()] + " " + start.getDate() + ", " + start.getFullYear();
|
||||
}
|
||||
if (start.getFullYear() === end.getFullYear()) {
|
||||
if (start.getMonth() === end.getMonth()) {
|
||||
return MONTH_ABBR[start.getMonth()] + " " + start.getDate() + "–" + end.getDate() + ", " + start.getFullYear();
|
||||
}
|
||||
return MONTH_ABBR[start.getMonth()] + " " + start.getDate() + " – " + MONTH_ABBR[end.getMonth()] + " " + end.getDate() + ", " + start.getFullYear();
|
||||
}
|
||||
return MONTH_ABBR[start.getMonth()] + " " + start.getDate() + ", " + start.getFullYear() + " – " + MONTH_ABBR[end.getMonth()] + " " + end.getDate() + ", " + end.getFullYear();
|
||||
}
|
||||
function renderOppEventList() {
|
||||
var listEl = document.getElementById("opp-event-list");
|
||||
if (!listEl) return;
|
||||
listEl.innerHTML = "";
|
||||
var events = buildOppEvents();
|
||||
if (!events.length) {
|
||||
var empty = document.createElement("div");
|
||||
empty.className = "opp-list-empty";
|
||||
empty.textContent = "No events yet.";
|
||||
listEl.appendChild(empty);
|
||||
return;
|
||||
}
|
||||
events.forEach(function (e) {
|
||||
var row = document.createElement("div");
|
||||
row.className = "opp-list-row";
|
||||
|
||||
var meta = document.createElement("div");
|
||||
meta.className = "opp-list-meta";
|
||||
var datesEl = document.createElement("div");
|
||||
datesEl.className = "opp-list-dates";
|
||||
datesEl.textContent = formatOppDateRange(e.start, e.end);
|
||||
meta.appendChild(datesEl);
|
||||
if (e.location) {
|
||||
var locEl = document.createElement("div");
|
||||
locEl.className = "opp-list-loc";
|
||||
locEl.textContent = e.location;
|
||||
meta.appendChild(locEl);
|
||||
}
|
||||
if (e.attendee) {
|
||||
var attEl = document.createElement("div");
|
||||
attEl.className = "opp-list-attendee";
|
||||
attEl.textContent = "Attending: " + e.attendee;
|
||||
meta.appendChild(attEl);
|
||||
}
|
||||
if (e.url) {
|
||||
var linkEl = document.createElement("a");
|
||||
linkEl.className = "opp-list-link";
|
||||
linkEl.href = e.url;
|
||||
linkEl.target = "_blank";
|
||||
linkEl.rel = "noopener";
|
||||
linkEl.textContent = "Website";
|
||||
meta.appendChild(linkEl);
|
||||
}
|
||||
row.appendChild(meta);
|
||||
|
||||
var about = document.createElement("div");
|
||||
about.className = "opp-list-about";
|
||||
var badge = document.createElement(e.url ? "a" : "span");
|
||||
badge.className = "opp-list-badge";
|
||||
badge.textContent = e.title;
|
||||
if (e.url) {
|
||||
badge.href = e.url;
|
||||
badge.target = "_blank";
|
||||
badge.rel = "noopener";
|
||||
}
|
||||
about.appendChild(badge);
|
||||
if (e.abstract) {
|
||||
var abstractEl = document.createElement("p");
|
||||
abstractEl.className = "opp-list-abstract";
|
||||
abstractEl.textContent = e.abstract;
|
||||
about.appendChild(abstractEl);
|
||||
}
|
||||
row.appendChild(about);
|
||||
|
||||
row.addEventListener("click", function () {
|
||||
oppCursor = new Date(e.start.getFullYear(), e.start.getMonth(), 1);
|
||||
renderOppCalendar();
|
||||
});
|
||||
listEl.appendChild(row);
|
||||
});
|
||||
}
|
||||
function renderOppCalendar() {
|
||||
var label = document.getElementById("opp-month-label");
|
||||
var grid = document.getElementById("opp-cal-grid");
|
||||
if (!label || !grid) return;
|
||||
label.textContent = MONTH_NAMES[oppCursor.getMonth()] + " " + oppCursor.getFullYear();
|
||||
grid.innerHTML = "";
|
||||
|
||||
var weekdayRow = document.createElement("div");
|
||||
weekdayRow.className = "opp-cal-weekdays";
|
||||
["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].forEach(function (wd) {
|
||||
var wdEl = document.createElement("div");
|
||||
wdEl.className = "opp-cal-weekday";
|
||||
wdEl.textContent = wd;
|
||||
weekdayRow.appendChild(wdEl);
|
||||
});
|
||||
grid.appendChild(weekdayRow);
|
||||
|
||||
var year = oppCursor.getFullYear(), month = oppCursor.getMonth();
|
||||
var firstDow = new Date(year, month, 1).getDay();
|
||||
var daysInMonth = new Date(year, month + 1, 0).getDate();
|
||||
var totalCells = Math.ceil((firstDow + daysInMonth) / 7) * 7;
|
||||
var gridStart = new Date(year, month, 1 - firstDow);
|
||||
var todayKey = oppKey(new Date());
|
||||
|
||||
var events = buildOppEvents();
|
||||
|
||||
for (var w = 0; w < totalCells / 7; w++) {
|
||||
var weekStart = addOppDays(gridStart, w * 7);
|
||||
var weekEnd = addOppDays(weekStart, 6);
|
||||
var weekEl = document.createElement("div");
|
||||
weekEl.className = "opp-cal-week";
|
||||
|
||||
var weekEvents = events
|
||||
.filter(function (e) { return e.start <= weekEnd && e.end >= weekStart; })
|
||||
.sort(function (a, b) { return a.start - b.start; });
|
||||
var lanes = [];
|
||||
weekEvents.forEach(function (e) {
|
||||
var colStart = Math.max(0, Math.round((Math.max(e.start, weekStart) - weekStart) / 86400000));
|
||||
var colEnd = Math.min(6, Math.round((Math.min(e.end, weekEnd) - weekStart) / 86400000));
|
||||
var lane = 0;
|
||||
while (lanes[lane] && lanes[lane].some(function (r) { return !(colEnd < r[0] || colStart > r[1]); })) lane++;
|
||||
if (!lanes[lane]) lanes[lane] = [];
|
||||
lanes[lane].push([colStart, colEnd]);
|
||||
e._col = [colStart, colEnd];
|
||||
e._lane = lane;
|
||||
});
|
||||
var cellMinHeight = Math.max(96, 34 + lanes.length * 24 + 10);
|
||||
|
||||
for (var d = 0; d < 7; d++) {
|
||||
var cellDate = addOppDays(weekStart, d);
|
||||
var outside = cellDate.getMonth() !== month;
|
||||
var key = oppKey(cellDate);
|
||||
var cell = document.createElement("div");
|
||||
cell.className = "opp-cal-cell" + (outside ? " outside" : "") + (key === todayKey ? " today" : "");
|
||||
cell.style.minHeight = cellMinHeight + "px";
|
||||
var numEl = document.createElement("div");
|
||||
numEl.className = "opp-cal-daynum";
|
||||
numEl.textContent = cellDate.getDate();
|
||||
cell.appendChild(numEl);
|
||||
weekEl.appendChild(cell);
|
||||
}
|
||||
|
||||
weekEvents.forEach(function (e) {
|
||||
var bar = document.createElement("div");
|
||||
bar.className = "opp-cal-event-bar";
|
||||
if (e.start < weekStart) bar.classList.add("continues-left");
|
||||
if (e.end > weekEnd) bar.classList.add("continues-right");
|
||||
bar.style.left = "calc(" + (e._col[0] / 7 * 100) + "% + 4px)";
|
||||
bar.style.width = "calc(" + ((e._col[1] - e._col[0] + 1) / 7 * 100) + "% - 8px)";
|
||||
bar.style.top = (34 + e._lane * 24) + "px";
|
||||
var titleEl = document.createElement(e.url ? "a" : "span");
|
||||
titleEl.className = "opp-cal-event-title";
|
||||
titleEl.textContent = e.title;
|
||||
if (e.url) {
|
||||
titleEl.href = e.url;
|
||||
titleEl.target = "_blank";
|
||||
titleEl.rel = "noopener";
|
||||
}
|
||||
bar.appendChild(titleEl);
|
||||
if (e.location) {
|
||||
var locEl = document.createElement("span");
|
||||
locEl.className = "opp-cal-event-loc";
|
||||
locEl.textContent = e.location;
|
||||
bar.appendChild(locEl);
|
||||
}
|
||||
bar.title = e.title + (e.location ? " — " + e.location : "") + (e.attendee ? " (" + e.attendee + ")" : "");
|
||||
weekEl.appendChild(bar);
|
||||
});
|
||||
|
||||
grid.appendChild(weekEl);
|
||||
}
|
||||
}
|
||||
/* ---------- Conference Scout results ----------
|
||||
Snapshot of the weekly research agent's report, hand-reviewed and pasted in here.
|
||||
Each entry: { title, dates (display text), location, url, reason }. */
|
||||
var SCOUT_RESULTS = [
|
||||
{ title: "PCIM Asia 2026", dates: "Aug 26–28, 2026", location: "Shenzhen, China",
|
||||
reason: "Asia's leading power electronics / wide-bandgap semiconductor trade show — direct GaN/SiC device and materials audience. Existing focus area." },
|
||||
{ title: "IMAPS Onshoring Workshop 2026", dates: "Aug 31–Sept 2, 2026", location: "Arlington, VA, USA",
|
||||
url: "https://imaps.org/page/Onshoring",
|
||||
reason: "Workshop on the US Defense Industrial Base's microelectronics packaging/assembly onshoring — a direct entry point for X-ray/semiconductor characterization into defense supply chains. Potential new business (defense)." },
|
||||
{ title: "SEMICON Taiwan 2026", dates: "Sept 2–4, 2026", location: "Taipei, Taiwan",
|
||||
url: "https://www.semicontaiwan.org/",
|
||||
reason: "Major semiconductor equipment/materials/metrology trade show in a top compound-semiconductor manufacturing hub. Existing focus area." },
|
||||
{ title: "WiPDA-Europe 2026", dates: "Sept 20–22, 2026", location: "Aalborg, Denmark",
|
||||
url: "https://www.energy.aau.dk/wipda-europe-2026-e156452",
|
||||
reason: "IEEE workshop on wide-bandgap (GaN/SiC) power devices — niche but highly targeted technical audience. Existing focus area." },
|
||||
{ title: "XTOP 2026", dates: "Sept 21–25, 2026", location: "Karlsruhe, Germany",
|
||||
url: "https://xtop2026.kit.edu",
|
||||
reason: "16th Biennial Conference on High-Resolution X-Ray Diffraction and Imaging — direct X-ray diffraction/imaging overlap. Existing focus area." },
|
||||
{ title: "NOBUGS 2026", dates: "Sept 21–25, 2026 (core Sept 22–24)", location: "Schenefeld Campus (European XFEL), near Hamburg, Germany",
|
||||
url: "https://nobugs2026.xfel.eu/",
|
||||
reason: "Explicitly covers metadata/data formats and FAIR data management for beamline software; co-hosted by DESY/European XFEL on TXproducts' home campus — the single best topical fit found. Existing focus area." },
|
||||
{ title: "ICSCRM 2026", dates: "Sept 27–Oct 2, 2026", location: "Yokohama, Japan",
|
||||
reason: "Premier international conference on silicon carbide and related materials — direct match for the SiC/X-ray metrology work. Existing focus area." },
|
||||
{ title: "RDA 27th Plenary Meeting (P27)", dates: "Oct 6–8, 2026", location: "London, UK",
|
||||
url: "https://www.rd-alliance.org/plenaries/p27/",
|
||||
reason: "Research Data Alliance plenary — strong FAIR/research-data-infrastructure networking, though less domain-specific than NOBUGS. Existing focus area." },
|
||||
{ title: "AFLS2026", dates: "Nov 16–20, 2026", location: "Harare, Zimbabwe",
|
||||
url: "https://events.saip.org.za/event/255",
|
||||
reason: "African Light Source / African Physical Society joint meeting — the Africa-based synchrotron-development community, with materials/X-ray characterization topics. Existing focus area." },
|
||||
{ title: "MRS Fall Meeting & Exhibit 2026", dates: "Nov 29–Dec 4, 2026", location: "Boston, MA, USA",
|
||||
url: "https://www.mrs.org/",
|
||||
reason: "Broad materials-science conference with strong X-ray characterization tracks. Existing focus area." },
|
||||
{ title: "GOMACTech 2027", dates: "March 22–25, 2027", location: "Pasadena, CA, USA",
|
||||
url: "https://www.gomactech.net/",
|
||||
reason: "The premier US DoD microelectronics conference — covers GaN/SiC power devices and X-ray characterization/reliability for defense microelectronics. Potential new business (defense)." },
|
||||
{ title: "IEEE RadarConf'27", dates: "May 1–6, 2027", location: "Bangalore, India",
|
||||
url: "https://radarconf2027.org/",
|
||||
reason: "Radar hardware relies heavily on GaN/SiC RF power amplifiers — a defense-radar audience in a growing Indian defense-electronics market. Potential new business (defense)." }
|
||||
];
|
||||
function renderOppScoutList() {
|
||||
var listEl = document.getElementById("opp-scout-list");
|
||||
if (!listEl) return;
|
||||
listEl.innerHTML = "";
|
||||
if (!SCOUT_RESULTS.length) {
|
||||
var empty = document.createElement("div");
|
||||
empty.className = "opp-list-empty";
|
||||
empty.textContent = "No results yet.";
|
||||
listEl.appendChild(empty);
|
||||
return;
|
||||
}
|
||||
SCOUT_RESULTS.forEach(function (s) {
|
||||
var row = document.createElement("div");
|
||||
row.className = "opp-list-row";
|
||||
row.style.cursor = "default";
|
||||
|
||||
var meta = document.createElement("div");
|
||||
meta.className = "opp-list-meta";
|
||||
var datesEl = document.createElement("div");
|
||||
datesEl.className = "opp-list-dates";
|
||||
datesEl.textContent = s.dates;
|
||||
meta.appendChild(datesEl);
|
||||
if (s.location) {
|
||||
var locEl = document.createElement("div");
|
||||
locEl.className = "opp-list-loc";
|
||||
locEl.textContent = s.location;
|
||||
meta.appendChild(locEl);
|
||||
}
|
||||
if (s.url) {
|
||||
var linkEl = document.createElement("a");
|
||||
linkEl.className = "opp-list-link";
|
||||
linkEl.href = s.url;
|
||||
linkEl.target = "_blank";
|
||||
linkEl.rel = "noopener";
|
||||
linkEl.textContent = "Website";
|
||||
meta.appendChild(linkEl);
|
||||
}
|
||||
row.appendChild(meta);
|
||||
|
||||
var about = document.createElement("div");
|
||||
about.className = "opp-list-about";
|
||||
var badge = document.createElement(s.url ? "a" : "span");
|
||||
badge.className = "opp-list-badge";
|
||||
badge.textContent = s.title;
|
||||
if (s.url) {
|
||||
badge.href = s.url;
|
||||
badge.target = "_blank";
|
||||
badge.rel = "noopener";
|
||||
}
|
||||
about.appendChild(badge);
|
||||
if (s.reason) {
|
||||
var reasonEl = document.createElement("p");
|
||||
reasonEl.className = "opp-list-abstract";
|
||||
reasonEl.textContent = s.reason;
|
||||
about.appendChild(reasonEl);
|
||||
}
|
||||
row.appendChild(about);
|
||||
|
||||
listEl.appendChild(row);
|
||||
});
|
||||
}
|
||||
document.getElementById("opp-prev-btn").addEventListener("click", function () {
|
||||
oppCursor.setMonth(oppCursor.getMonth() - 1);
|
||||
renderOppCalendar();
|
||||
});
|
||||
document.getElementById("opp-next-btn").addEventListener("click", function () {
|
||||
oppCursor.setMonth(oppCursor.getMonth() + 1);
|
||||
renderOppCalendar();
|
||||
});
|
||||
document.getElementById("opp-today-btn").addEventListener("click", function () {
|
||||
oppCursor = new Date();
|
||||
oppCursor.setDate(1);
|
||||
renderOppCalendar();
|
||||
});
|
||||
renderOppEventList();
|
||||
renderOppCalendar();
|
||||
renderOppScoutList();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user