mirror of
git://f0xx.org/android_cast
synced 2026-07-29 08:19:00 +03:00
1
This commit is contained in:
@@ -8,19 +8,19 @@
|
|||||||
isolation: isolate;
|
isolation: isolate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 97% transparent watermark */
|
/* Debug watermark visibility */
|
||||||
.hub-page::before {
|
.hub-page::before {
|
||||||
content: "";
|
content: "";
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background: url("assets/hub-logo.svg") center center / min(92vmin, 960px) no-repeat;
|
background: url("assets/hub-logo.svg") center center / cover no-repeat;
|
||||||
opacity: 0.03;
|
opacity: 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="light"] .hub-page::before {
|
[data-theme="light"] .hub-page::before {
|
||||||
opacity: 0.035;
|
opacity: 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hub-shell {
|
.hub-shell {
|
||||||
|
|||||||
@@ -33,10 +33,12 @@ body {
|
|||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
a { color: var(--accent); text-decoration: none; }
|
a { color: var(--accent); text-decoration: none; }
|
||||||
a:hover { text-decoration: underline; }
|
a:hover { text-decoration: underline; }
|
||||||
.shell { display: flex; min-height: calc(100vh - 40px); }
|
.shell { display: flex; min-height: calc(100vh - 40px); flex: 1 0 auto; }
|
||||||
.shell.single .main-pane { max-width: 1100px; margin: 0 auto; padding: 24px; }
|
.shell.single .main-pane { max-width: 1100px; margin: 0 auto; padding: 24px; }
|
||||||
.nav-pane {
|
.nav-pane {
|
||||||
width: 56px;
|
width: 56px;
|
||||||
@@ -404,9 +406,14 @@ a:hover { text-decoration: underline; }
|
|||||||
border-top: 1px solid var(--border);
|
border-top: 1px solid var(--border);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0;
|
||||||
|
background: var(--surface);
|
||||||
|
z-index: 40;
|
||||||
}
|
}
|
||||||
.login-page {
|
.login-page {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ final class TicketRepository {
|
|||||||
'device_model',
|
'device_model',
|
||||||
'owner_username',
|
'owner_username',
|
||||||
];
|
];
|
||||||
|
private static ?array $ticketColumns = null;
|
||||||
|
|
||||||
public static function insert(array $payload): void {
|
public static function insert(array $payload): void {
|
||||||
$err = TicketTagCatalog::validate(is_array($payload['tags'] ?? null) ? $payload['tags'] : []);
|
$err = TicketTagCatalog::validate(is_array($payload['tags'] ?? null) ? $payload['tags'] : []);
|
||||||
@@ -88,9 +89,16 @@ final class TicketRepository {
|
|||||||
$countStmt = $pdo->prepare("SELECT COUNT(*) FROM tickets WHERE $whereSql");
|
$countStmt = $pdo->prepare("SELECT COUNT(*) FROM tickets WHERE $whereSql");
|
||||||
$countStmt->execute($params);
|
$countStmt->execute($params);
|
||||||
$total = (int) $countStmt->fetchColumn();
|
$total = (int) $countStmt->fetchColumn();
|
||||||
$sql = "SELECT id, ticket_id, title, brief, opened_at_ms, updated_at_ms, created_at_ms,
|
$select = 'id, ticket_id, title, brief, opened_at_ms, updated_at_ms, created_at_ms,
|
||||||
owner_username, verified_by_username, device_model, app_package, app_version,
|
owner_username, verified_by_username, device_model, app_package, app_version,
|
||||||
os_name, os_version, rating, tags_json, workflow_state, assignees_json
|
os_name, os_version, rating, tags_json';
|
||||||
|
if (self::hasTicketColumn('workflow_state')) {
|
||||||
|
$select .= ', workflow_state';
|
||||||
|
}
|
||||||
|
if (self::hasTicketColumn('assignees_json')) {
|
||||||
|
$select .= ', assignees_json';
|
||||||
|
}
|
||||||
|
$sql = "SELECT $select
|
||||||
FROM tickets WHERE $whereSql ORDER BY $sortCol $dir LIMIT $perPage OFFSET $offset";
|
FROM tickets WHERE $whereSql ORDER BY $sortCol $dir LIMIT $perPage OFFSET $offset";
|
||||||
$stmt = $pdo->prepare($sql);
|
$stmt = $pdo->prepare($sql);
|
||||||
$stmt->execute($params);
|
$stmt->execute($params);
|
||||||
@@ -181,7 +189,7 @@ final class TicketRepository {
|
|||||||
$sets[] = 'verified_by_username = ?';
|
$sets[] = 'verified_by_username = ?';
|
||||||
$params[] = $v !== '' ? mb_substr($v, 0, 64) : null;
|
$params[] = $v !== '' ? mb_substr($v, 0, 64) : null;
|
||||||
}
|
}
|
||||||
if (isset($fields['workflow_state'])) {
|
if (isset($fields['workflow_state']) && self::hasTicketColumn('workflow_state')) {
|
||||||
$state = TicketWorkflow::normalize((string) $fields['workflow_state']);
|
$state = TicketWorkflow::normalize((string) $fields['workflow_state']);
|
||||||
$sets[] = 'workflow_state = ?';
|
$sets[] = 'workflow_state = ?';
|
||||||
$params[] = $state;
|
$params[] = $state;
|
||||||
@@ -192,7 +200,7 @@ final class TicketRepository {
|
|||||||
$sets[] = 'tags_json = ?';
|
$sets[] = 'tags_json = ?';
|
||||||
$params[] = json_encode($tags, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
$params[] = json_encode($tags, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
}
|
}
|
||||||
if (array_key_exists('assignees', $fields)) {
|
if (array_key_exists('assignees', $fields) && self::hasTicketColumn('assignees_json')) {
|
||||||
$assignees = self::normalizeAssignees($fields['assignees']);
|
$assignees = self::normalizeAssignees($fields['assignees']);
|
||||||
$err = UserRepository::validateUsernames(
|
$err = UserRepository::validateUsernames(
|
||||||
array_map(static fn (array $a): string => $a['username'], $assignees)
|
array_map(static fn (array $a): string => $a['username'], $assignees)
|
||||||
@@ -239,6 +247,13 @@ final class TicketRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function hasTicketColumn(string $column): bool {
|
||||||
|
if (self::$ticketColumns === null) {
|
||||||
|
self::$ticketColumns = Database::columnNames(Database::pdo(), 'tickets');
|
||||||
|
}
|
||||||
|
return in_array($column, self::$ticketColumns, true);
|
||||||
|
}
|
||||||
|
|
||||||
/** @param array<string, mixed> $row */
|
/** @param array<string, mixed> $row */
|
||||||
private static function mapListRow(array $row): array {
|
private static function mapListRow(array $row): array {
|
||||||
$tags = parse_report_tags($row['tags_json'] ?? '[]');
|
$tags = parse_report_tags($row['tags_json'] ?? '[]');
|
||||||
|
|||||||
Reference in New Issue
Block a user