wsj-filenaming/index.php
Vadym Samoilenko 523be058aa Add Azure AD / MSAL SSO authentication
- config.php: Azure tenant/client constants, SSO_ENABLED = true
- auth.php: requireAuth() middleware, getSafeUser(), getUserDataFile()
- auth_gate.php: MSAL.js PKCE login flow, stores return URL in sessionStorage
- logout.php: destroys PHP session + calls msalInstance.logoutRedirect()
- api.php: public create_session endpoint (JWT validation), 401 guard on all other actions, per-user data files (data_{safeUser}.json)
- sheet_helpers.php: fix dot sanitisation '_' → '_dot_' to match getSafeUser()
- index/builder/help.php: requireAuth() at top, user email + Sign Out in header

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 21:43:32 +00:00

121 lines
6 KiB
PHP

<?php require_once __DIR__ . '/auth.php'; requireAuth(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dow Jones Job Naming Tool</title>
<link rel="stylesheet" href="style.css">
<!-- Jspreadsheet & Jsuites -->
<script src="https://jsuites.net/v4/jsuites.js"></script>
<script src="https://bossanova.uk/jspreadsheet/v4/jexcel.js"></script>
<link rel="stylesheet" href="https://jsuites.net/v4/jsuites.css" type="text/css" />
<link rel="stylesheet" href="https://bossanova.uk/jspreadsheet/v4/jexcel.css" type="text/css" />
</head>
<body>
<div class="container">
<header style="display: flex; justify-content: space-between; align-items: center;">
<div>
<h1>DOW JONES JOB NAMING TOOL</h1>
<p style="color: var(--text-secondary);">Generate job names using the Dow Jones naming convention</p>
</div>
<div style="display: flex; gap: 10px; align-items: center;">
<span style="font-size: 0.8rem; color: var(--text-secondary);"><?php echo htmlspecialchars($CURRENT_USER); ?></span>
<a href="builder.php" class="btn btn-primary" style="text-decoration: none;">Builder / Decoder</a>
<a href="help.php" class="btn btn-secondary" style="text-decoration: none;">Help</a>
<a href="logout.php" class="btn btn-secondary" style="text-decoration: none;">Sign Out</a>
</div>
</header>
<div class="command-bar-container">
<div class="input-group">
<input type="text" id="commandInput" placeholder='Try: "Create 5 jobs for PMKT ACQ WSJ, initiative BIC, year 26"' autocomplete="off">
<button id="micBtn" class="btn btn-icon" title="Speak">🎤</button>
<button id="sendBtn" class="btn btn-primary">Send</button>
</div>
<div style="display: flex; align-items: center; gap: 10px; margin-top: 10px;">
<label class="switch">
<input type="checkbox" id="yoloToggle">
<span class="slider round"></span>
</label>
<span style="font-weight: bold; color: var(--text-color);">YOLO Mode</span>
<span style="font-size: 0.8em; color: #888;">(Skip clarifying questions)</span>
</div>
</div>
<!-- Quick Starters -->
<div class="quick-starters">
<span style="color: var(--text-secondary); font-size: 0.85rem; margin-right: 10px;">Try:</span>
<button class="starter-chip" onclick="fillCommand('Create 3 jobs for PMKT ACQ WSJ, initiative BIC, year 26')">PMKT Acquisition</button>
<button class="starter-chip" onclick="fillCommand('Create 2 event jobs for Global Food Forum, year 26')">Event - GFF</button>
<button class="starter-chip" onclick="fillCommand('Create 4 B2B Enterprise jobs for Factiva, initiative demo, year 26')">B2B Enterprise</button>
</div>
<div class="toolbar">
<div style="display: flex; gap: 15px; align-items: center;">
<label style="font-weight: 600;">Campaign:</label>
<input type="text" id="campaignName" placeholder="e.g., q1-2026" style="padding: 8px; width: 150px; border: 1px solid var(--border-color); border-radius: 4px;">
</div>
<div style="display: flex; gap: 10px;">
<button id="loadCampaignBtn" class="btn btn-secondary">Load Campaign</button>
<button id="saveCampaignBtn" class="btn btn-primary">Save Campaign</button>
<button id="exportBtn" class="btn btn-secondary">Export CSV</button>
<button id="copyFilenamesBtn" class="btn btn-secondary">Copy Filenames</button>
<button id="clearSheetBtn" class="btn btn-danger">Clear All</button>
</div>
</div>
<div class="table-container">
<div id="spreadsheet"></div>
</div>
<!-- AI Activity Log -->
<div class="ai-log">
<div class="ai-log-header" style="cursor: pointer;" onclick="document.getElementById('aiOutput').classList.toggle('collapsed'); this.querySelector('.collapse-icon').textContent = document.getElementById('aiOutput').classList.contains('collapsed') ? '>' : 'v';">
<h3><span class="collapse-icon">v</span> AI ACTIVITY LOG</h3>
<button id="clearLogBtn" class="btn btn-secondary" style="padding: 6px 12px; font-size: 0.85rem;" onclick="event.stopPropagation();">Clear Log</button>
</div>
<div id="aiOutput" class="ai-output">Waiting for command...</div>
</div>
</div>
<script>
function fillCommand(text) {
const input = document.getElementById('commandInput');
input.value = text;
input.focus();
}
</script>
<div id="loadingOverlay">
<div class="spinner"></div>
</div>
<!-- AI Question Modal -->
<div id="aiQuestionModal" class="modal-overlay">
<div class="modal-content">
<div class="modal-header">
<h3>AI Needs Clarification</h3>
<button class="close-modal-btn" onclick="closeAiModal()">x</button>
</div>
<div class="modal-body">
<p id="aiQuestionText" class="ai-question-text"></p>
<div class="modal-input-group">
<input type="text" id="aiModalInput" placeholder="Type your answer..." autocomplete="off">
<button id="aiModalMicBtn" class="btn btn-icon" title="Speak">🎤</button>
</div>
<div class="modal-actions">
<button id="aiModalSendBtn" class="btn btn-primary">Send Answer</button>
<button id="aiModalYoloBtn" class="btn btn-secondary">Do what you think (YOLO)</button>
</div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>