Update VPN client and gateway behavior
This commit is contained in:
@@ -4,13 +4,14 @@ import {
|
||||
useState,
|
||||
type FormEvent,
|
||||
type ReactNode,
|
||||
type RefObject,
|
||||
} from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { canAppendRouteRule } from '../../../shared/routingRules.js';
|
||||
import type { RouteRule } from '../../../shared/contracts/state.js';
|
||||
import { operationBlocked } from '../../state/operations.js';
|
||||
import { ConfirmationDialog } from '../../ui/ConfirmationDialog.js';
|
||||
import { Drawer } from '../../ui/Drawer.js';
|
||||
import { RailAction } from '../../ui/RailAction.js';
|
||||
|
||||
const ROUTE_RULE_OPTIONS: Array<[RouteRule['type'], string]> = [
|
||||
['domain', 'Точный домен'],
|
||||
@@ -393,18 +394,22 @@ export function RoutingToggle({
|
||||
}) {
|
||||
const disabled = gatewayDirect || (isGateway && !hasSubscription);
|
||||
return (
|
||||
<button
|
||||
ref={feature.toggleRef}
|
||||
className={`client-local-rules-toggle${feature.isOpen ? ' is-open' : ''}${feature.pendingRestart ? ' has-pending' : ''}`}
|
||||
type="button"
|
||||
<RailAction
|
||||
buttonRef={feature.toggleRef}
|
||||
className={`client-local-rules-toggle${feature.pendingRestart ? ' has-pending' : ''}`}
|
||||
open={feature.isOpen}
|
||||
controls="client-local-rules"
|
||||
disabled={disabled}
|
||||
aria-expanded={feature.isOpen}
|
||||
aria-controls="client-local-rules"
|
||||
aria-label={disabled
|
||||
ariaLabel={disabled
|
||||
? hasSubscription
|
||||
? 'Локальные правила недоступны: сейчас работают правила Harbor Gateway'
|
||||
: 'Локальные правила недоступны: сначала добавьте подписку'
|
||||
: feature.isOpen ? 'Закрыть локальные правила' : 'Настроить локальные правила'}
|
||||
label={disabled
|
||||
? hasSubscription
|
||||
? 'Локальные правила недоступны: сейчас работают правила Gateway'
|
||||
: 'Сначала добавьте подписку'
|
||||
: feature.pendingRestart ? 'Правила ждут перезапуска' : 'Локальные правила'}
|
||||
onClick={() => feature.isOpen ? feature.requestClose() : onOpen()}
|
||||
>
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
@@ -412,12 +417,7 @@ export function RoutingToggle({
|
||||
<circle className="client-rail-rule-knob is-top" cx="15" cy="7" r="2" />
|
||||
<circle className="client-rail-rule-knob is-bottom" cx="9" cy="17" r="2" />
|
||||
</svg>
|
||||
<span>{disabled
|
||||
? hasSubscription
|
||||
? 'Локальные правила недоступны: сейчас работают правила Gateway'
|
||||
: 'Сначала добавьте подписку'
|
||||
: feature.pendingRestart ? 'Правила ждут перезапуска' : 'Локальные правила'}</span>
|
||||
</button>
|
||||
</RailAction>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -446,22 +446,17 @@ export function RoutingPanel({ feature, statusSlot }: { feature: RoutingFeature;
|
||||
const incomplete = draftRules.some((rule) => !String(rule.value || '').trim());
|
||||
|
||||
return (
|
||||
<aside
|
||||
ref={feature.panelRef as RefObject<HTMLElement>}
|
||||
<Drawer
|
||||
panelRef={feature.panelRef}
|
||||
closeRef={feature.closeRef}
|
||||
id="client-local-rules"
|
||||
className={`client-drawer client-local-rules${feature.isOpen ? ' is-open' : ''}`}
|
||||
aria-labelledby="local-rules-title"
|
||||
aria-hidden={!feature.isOpen}
|
||||
inert={!feature.isOpen ? true : undefined}
|
||||
className="client-local-rules"
|
||||
sheetClassName="client-local-rules-sheet"
|
||||
open={feature.isOpen}
|
||||
labelledBy="local-rules-title"
|
||||
closeLabel="Закрыть локальные правила"
|
||||
onClose={feature.requestClose}
|
||||
>
|
||||
<div className="client-drawer-sheet client-local-rules-sheet">
|
||||
<button
|
||||
ref={feature.closeRef}
|
||||
className="client-drawer-close"
|
||||
type="button"
|
||||
aria-label="Закрыть локальные правила"
|
||||
onClick={feature.requestClose}
|
||||
>×</button>
|
||||
<header className="client-local-rules-header">
|
||||
<span>Маршрутизация</span>
|
||||
<button
|
||||
@@ -532,7 +527,7 @@ export function RoutingPanel({ feature, statusSlot }: { feature: RoutingFeature;
|
||||
/>
|
||||
<span className="client-local-rule-status" role="status">{statusLabel}</span>
|
||||
<button
|
||||
className="client-local-rule-delete"
|
||||
className="client-row-delete"
|
||||
type="button"
|
||||
aria-label={`Удалить правило ${index + 1}`}
|
||||
onClick={() => feature.remove(rule._key)}
|
||||
@@ -549,8 +544,8 @@ export function RoutingPanel({ feature, statusSlot }: { feature: RoutingFeature;
|
||||
})}
|
||||
{!feature.rules.length && <p className="client-local-rules-empty">Правил пока нет. Весь трафик идёт через VPN.</p>}
|
||||
</div>
|
||||
<div className="client-local-rule-add-slot">
|
||||
<button className="client-local-rule-add" type="button" disabled={!canAdd} onClick={feature.add}>
|
||||
<div className="client-row-add-slot">
|
||||
<button className="client-row-add" type="button" disabled={!canAdd} onClick={feature.add}>
|
||||
+ Добавить правило
|
||||
</button>
|
||||
<span className={incomplete ? 'is-visible' : ''}>Сначала заполните текущее правило</span>
|
||||
@@ -565,8 +560,7 @@ export function RoutingPanel({ feature, statusSlot }: { feature: RoutingFeature;
|
||||
<button type="button" onClick={feature.requestClose}>Отмена</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</aside>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user