220 lines
11 KiB
PHP
220 lines
11 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
style('qortal_integration', 'qapps');
|
||
script('qortal_integration', 'qapps');
|
||
|
||
$qapps = $_['qappsList'] ?? [];
|
||
?>
|
||
|
||
<div
|
||
id="qortal-qapps-root"
|
||
class="section"
|
||
data-qapps="<?php p(json_encode($qapps, JSON_UNESCAPED_SLASHES)); ?>"
|
||
data-qapps-enabled="<?php p(!empty($_['qappsEnabled']) ? '1' : '0'); ?>"
|
||
data-qapps-browser-enabled="<?php p(!empty($_['qappsFullBrowserEnabled']) ? '1' : '0'); ?>"
|
||
data-qapps-browser-address="<?php p((string)($_['qappsFullBrowserAddress'] ?? '')); ?>"
|
||
data-qapps-debug-enabled="<?php p(!empty($_['qappsDebugEnabled']) ? '1' : '0'); ?>"
|
||
data-qortal-node-url="<?php p((string)($_['qortalNodeUrl'] ?? '')); ?>"
|
||
data-qortal-gateway-url="<?php p((string)($_['qortalGatewayUrl'] ?? '')); ?>"
|
||
data-gateway-proxy-url="<?php p((string)($_['gatewayProxyUrl'] ?? '')); ?>"
|
||
data-qapps-request-url="<?php p((string)($_['qappsRequestUrl'] ?? '')); ?>"
|
||
data-qapps-approve-url="<?php p((string)($_['qappsApproveUrl'] ?? '')); ?>"
|
||
data-qapps-permissions-url="<?php p((string)($_['qappsPermissionsUrl'] ?? '')); ?>"
|
||
data-qapps-unlock-url="<?php p((string)($_['qappsUnlockUrl'] ?? '')); ?>"
|
||
data-qapps-unlock-status-url="<?php p((string)($_['qappsUnlockStatusUrl'] ?? '')); ?>"
|
||
data-qapps-default-approval-mode="<?php p((string)($_['qappsDefaultApprovalMode'] ?? 'once')); ?>"
|
||
data-qapps-default-approval-temp-minutes="<?php p((string)($_['qappsDefaultApprovalTempMinutes'] ?? 10)); ?>"
|
||
data-qapps-default-approval-unlock-10-min="<?php p(!empty($_['qappsDefaultApprovalUnlock10Min']) ? '1' : '0'); ?>"
|
||
data-qapps-default-unlock-session-20-min="<?php p(!empty($_['qappsDefaultUnlockSession20Min']) ? '1' : '0'); ?>"
|
||
data-nextcloud-public-url="<?php p((string)($_['nextcloudPublicUrl'] ?? '')); ?>"
|
||
data-user-mappings-url="<?php p((string)($_['userMappingsUrl'] ?? '')); ?>"
|
||
data-settings-path="<?php p((string)($_['settingsPath'] ?? '')); ?>"
|
||
>
|
||
<div class="qortal-page-header">
|
||
<div>
|
||
<h2><?php p((string)($_['title'] ?? 'Q-Apps')); ?></h2>
|
||
<p class="qortal-help">Launch approved Q-Apps from inside Nextcloud.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="qortal-qapps-empty" class="qortal-card">
|
||
<p class="qortal-note">Q-Apps access is not enabled yet. Ask an admin to enable it.</p>
|
||
</div>
|
||
|
||
<div id="qortal-qapps-browser" class="qortal-card">
|
||
<h3>Full Qortal Browser</h3>
|
||
<p class="qortal-note">
|
||
Open the full Qortal browser for unrestricted Q-App access.
|
||
</p>
|
||
<p class="qortal-note">
|
||
Address: <code id="qortal-qapps-browser-address"></code>
|
||
</p>
|
||
<button id="qortal-qapps-open-browser" class="button button-primary">Open Full Browser</button>
|
||
</div>
|
||
|
||
<div id="qortal-qapps-warning" class="qortal-card qortal-hidden">
|
||
<h3>View-only mode</h3>
|
||
<p class="qortal-note">
|
||
No Qortal account is linked to your Nextcloud user yet. You can browse Q-Apps, but authentication-required
|
||
actions will not work until you create or attach a Qortal account.
|
||
</p>
|
||
<p class="qortal-note">
|
||
<a id="qortal-qapps-settings-link" class="button" href="#">Open Qortal Settings</a>
|
||
</p>
|
||
</div>
|
||
|
||
<div id="qortal-qapps-name-required" class="qortal-modal qortal-hidden">
|
||
<div class="qortal-modal__backdrop"></div>
|
||
<div class="qortal-modal__card qortal-modal__card--danger">
|
||
<h3>Registered Name Needed</h3>
|
||
<p class="qortal-note">
|
||
You do not have a registered Qortal name.
|
||
</p>
|
||
<p class="qortal-note">
|
||
In order to publish data or messages within Q-Apps to Qortal's distributed data network, you must register a name first.
|
||
</p>
|
||
<div class="qortal-approval-actions qortal-name-required-actions">
|
||
<a id="qortal-qapps-name-required-dashboard" class="button button-primary" href="#">Open Dashboard</a>
|
||
<button id="qortal-qapps-name-required-continue" class="button" type="button">Continue Anyway</button>
|
||
<button id="qortal-qapps-name-required-cancel" class="button" type="button">Cancel</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="qortal-qapps-list" class="qortal-card">
|
||
<h3>Available Q-Apps</h3>
|
||
<p class="qortal-note">Launch approved Q-Apps from this list, or use Full Browser mode for unrestricted navigation.</p>
|
||
<div class="qortal-table-wrap">
|
||
<table class="qortal-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Name</th>
|
||
<th>Address</th>
|
||
<th>Description</th>
|
||
<th>Action</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="qortal-qapps-body">
|
||
<tr>
|
||
<td colspan="4">Loading…</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="qortal-qapps-viewer" class="qortal-card qortal-hidden">
|
||
<div class="qortal-viewer-toolbar">
|
||
<div class="qortal-viewer-nav-actions">
|
||
<button id="qortal-qapps-back" class="button">Back</button>
|
||
<button id="qortal-qapps-reload" class="button">Reload</button>
|
||
</div>
|
||
<div class="qortal-viewer-address">
|
||
<code id="qortal-qapps-viewer-address" class="qortal-viewer-address-text"></code>
|
||
<div class="qortal-viewer-address-input">
|
||
<input id="qortal-qapps-viewer-address-input" class="qortal-input" type="text" placeholder="qortal://APP/Q-Tube">
|
||
<button id="qortal-qapps-viewer-address-go" class="button">Go</button>
|
||
</div>
|
||
<span id="qortal-qapps-loading-progress" class="qortal-qdn-progress qortal-hidden" aria-live="polite"></span>
|
||
</div>
|
||
<div class="qortal-viewer-actions">
|
||
<button id="qortal-qapps-menu" class="button qortal-mobile-only" type="button" aria-controls="qortal-qapps-root" aria-expanded="false">Menu</button>
|
||
<button id="qortal-qapps-open-external" class="button" type="button">Copy link</button>
|
||
<button id="qortal-qapps-close" class="button" type="button" aria-label="Close Q-App viewer">×</button>
|
||
</div>
|
||
</div>
|
||
<div id="qortal-qapps-frame-wrap" class="qortal-viewer-frame-wrap">
|
||
<div id="qortal-qapps-loading-overlay" class="qortal-loading-overlay qortal-hidden" aria-live="polite" aria-atomic="true">
|
||
<div class="qortal-loading-card">
|
||
<div class="qortal-loading-title">Loading from QDN</div>
|
||
<div id="qortal-qapps-loading-status" class="qortal-loading-status">Preparing resource...</div>
|
||
<div class="qortal-loading-progress-track">
|
||
<div id="qortal-qapps-loading-progress-bar" class="qortal-loading-progress-bar"></div>
|
||
</div>
|
||
<div id="qortal-qapps-loading-meta" class="qortal-loading-meta"></div>
|
||
</div>
|
||
</div>
|
||
<iframe id="qortal-qapps-frame" title="Q-App Viewer" loading="lazy" scrolling="yes"></iframe>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="qortal-qapps-debug" class="qortal-card qortal-hidden">
|
||
<div class="qortal-debug-header">
|
||
<h3>Q-Apps Debug</h3>
|
||
<div class="qortal-debug-actions">
|
||
<button id="qortal-qapps-debug-minimize" class="button">Minimize</button>
|
||
<button id="qortal-qapps-debug-float" class="button">Float Panel</button>
|
||
<button id="qortal-qapps-debug-copy" class="button">Copy Logs</button>
|
||
<button id="qortal-qapps-debug-clear" class="button">Clear</button>
|
||
</div>
|
||
</div>
|
||
<pre id="qortal-qapps-debug-body" class="qortal-status qortal-compact-status">Debug panel enabled.</pre>
|
||
</div>
|
||
|
||
<div id="qortal-qapps-approval" class="qortal-modal qortal-hidden">
|
||
<div class="qortal-modal__backdrop"></div>
|
||
<div class="qortal-modal__card">
|
||
<h3>Authorize Qortal Request</h3>
|
||
<p class="qortal-note">Choose how this Qortal request should be handled. Broker/API session auth is automatic while you are logged into Nextcloud.</p>
|
||
<div class="qortal-approval-details">
|
||
<div><span class="qortal-label">App</span> <span id="qortal-approval-app" class="qortal-value">—</span></div>
|
||
<div><span class="qortal-label">Action</span> <span id="qortal-approval-action" class="qortal-value">—</span></div>
|
||
</div>
|
||
<div class="qortal-approval-options">
|
||
<label><input type="radio" name="qortal-approval-mode" value="once" checked> Allow only this request</label>
|
||
<label><input type="radio" name="qortal-approval-mode" value="type_minutes"> Allow this request type for X minutes</label>
|
||
<label><input type="radio" name="qortal-approval-mode" value="type_always"> Always allow this request type</label>
|
||
<label><input type="radio" name="qortal-approval-mode" value="app_always"> Always allow all request types for this Q-App</label>
|
||
</div>
|
||
<div class="qortal-unlock-field">
|
||
<label class="qortal-label" for="qortal-approval-temp-minutes">X Minutes (for temporary type approval)</label>
|
||
<input id="qortal-approval-temp-minutes" class="qortal-input" type="number" min="1" max="1440" step="1" value="10">
|
||
</div>
|
||
<p id="qortal-approval-policy-status" class="qortal-note qortal-approval-help"></p>
|
||
<p class="qortal-note qortal-approval-help">Persistent approval rules are stored in External Auth permissions. Temporary type approval is kept in this browser tab for the selected duration.</p>
|
||
<p id="qortal-approval-wallet-status" class="qortal-note qortal-approval-wallet-status qortal-wallet-status-unknown">Wallet lock: unknown (password may be required)</p>
|
||
<div id="qortal-approval-unlock-fields" class="qortal-approval-unlock qortal-hidden">
|
||
<label class="qortal-label" for="qortal-approval-password">Wallet password</label>
|
||
<input id="qortal-approval-password" class="qortal-input" type="password" placeholder="Needed only if wallet is currently locked" autocomplete="current-password">
|
||
<label class="qortal-unlock-option">
|
||
<input id="qortal-approval-ttl" type="checkbox">
|
||
Also unlock wallet for 10 min (password required)
|
||
</label>
|
||
<p class="qortal-note qortal-approval-help">Wallet password is only needed when the wallet is locked.</p>
|
||
</div>
|
||
<div class="qortal-approval-actions">
|
||
<button id="qortal-approval-confirm" class="button button-primary">Approve</button>
|
||
<button id="qortal-approval-cancel" class="button">Cancel</button>
|
||
</div>
|
||
<p id="qortal-approval-error" class="qortal-note qortal-approval-error qortal-hidden"></p>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="qortal-qapps-unlock" class="qortal-modal qortal-hidden">
|
||
<div class="qortal-modal__backdrop"></div>
|
||
<div class="qortal-modal__card">
|
||
<h3>Unlock Qortal Wallet</h3>
|
||
<p class="qortal-note">Your wallet is locked. Enter your wallet password to continue.</p>
|
||
<div class="qortal-approval-details">
|
||
<div><span class="qortal-label">App</span> <span id="qortal-unlock-app" class="qortal-value">—</span></div>
|
||
<div><span class="qortal-label">Action</span> <span id="qortal-unlock-action" class="qortal-value">—</span></div>
|
||
</div>
|
||
<div class="qortal-unlock-field">
|
||
<label class="qortal-label" for="qortal-unlock-password">Wallet password</label>
|
||
<input id="qortal-unlock-password" class="qortal-input" type="password" placeholder="Enter wallet password" autocomplete="current-password">
|
||
</div>
|
||
<label class="qortal-unlock-option">
|
||
<input id="qortal-unlock-session" type="checkbox">
|
||
Keep wallet unlocked for 20 minutes
|
||
</label>
|
||
<div class="qortal-approval-actions">
|
||
<button id="qortal-unlock-confirm" class="button button-primary">Unlock</button>
|
||
<button id="qortal-unlock-cancel" class="button">Cancel</button>
|
||
</div>
|
||
<p id="qortal-unlock-error" class="qortal-note qortal-approval-error qortal-hidden"></p>
|
||
</div>
|
||
</div>
|
||
</div>
|