Skip to content

Commit fa1712d

Browse files
committed
feat(ui): add TTL support and expiration management
Updated CreateTunnelRequest and Tunnel interfaces to include ttl and expires_in fields. Extended backend APIs (listTunnels, createTunnel) to handle pagination (page, perPage) and TTL functionality. Added UI support in TunnelCreate.vue for selecting a timeout (ttl) via a combobox. Displayed expiration date in TunnelList.vue, highlighting expired tunnels. Implemented validation and formatting logic for TTL and expiration date handling using moment. Updated tests for TunnelCreate and TunnelList components to verify TTL-related functionality and new expiration fields. Adjusted snapshot for TunnelList to reflect the new table header and rows.
1 parent b49efc6 commit fa1712d

File tree

9 files changed

+237
-28
lines changed

9 files changed

+237
-28
lines changed

ui/src/api/client/api.ts

Lines changed: 127 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ui/src/components/Tunnels/TunnelCreate.vue

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@
4949
/>
5050
</v-col>
5151
</v-row>
52+
<v-row>
53+
<v-col>
54+
<v-combobox
55+
v-model.number="timeout"
56+
:items="predefinedTimeouts"
57+
item-title="text"
58+
item-value="value"
59+
:rules="[validateTimeout]"
60+
label="Timeout (in seconds)"
61+
variant="outlined"
62+
data-test="timeout-combobox"
63+
@update:model-value="onTimeoutChange"
64+
/>
65+
66+
</v-col>
67+
</v-row>
5268
</v-card-text>
5369
</v-container>
5470
<v-card-actions>
@@ -117,6 +133,48 @@ const {
117133
},
118134
);
119135
136+
interface Timeout {
137+
value: number,
138+
text: string,
139+
}
140+
141+
const predefinedTimeouts = ref<Array<Timeout>>([
142+
{ value: -1, text: "Unlimited Timeout" },
143+
{ value: 60, text: "1 minute" },
144+
{ value: 300, text: "5 minutes" },
145+
{ value: 900, text: "15 minutes" },
146+
{ value: 3600, text: "1 hour" },
147+
{ value: 86400, text: "1 day" },
148+
{ value: 604800, text: "1 week" },
149+
{ value: 2624016, text: "1 month" },
150+
]);
151+
152+
const {
153+
value: timeout,
154+
} = useField<number>(
155+
"timeout",
156+
yup
157+
.number()
158+
.integer()
159+
.min(1, "Value must be 1 or greater")
160+
.max(2624016, "Value cannot exceed 1 month in seconds")
161+
.required("Timeout is required"),
162+
{ initialValue: -1 },
163+
);
164+
165+
const onTimeoutChange = (newValue: Timeout | number) => {
166+
switch (typeof newValue) {
167+
case "object": timeout.value = newValue.value; break;
168+
case "number": timeout.value = newValue; break;
169+
default: timeout.value = predefinedTimeouts.value[0].value; break;
170+
}
171+
};
172+
173+
const validateTimeout = (value: number) => {
174+
if (Number.isNaN(value)) return "Value must be a number";
175+
return true;
176+
};
177+
120178
const hasAuthorizationCreateTunnel = () => {
121179
const role = store.getters["auth/role"];
122180
if (role !== "") {
@@ -135,6 +193,8 @@ const hasErrors = () => !!(
135193
|| hostError.value
136194
|| !port.value
137195
|| !host.value
196+
|| !timeout.value
197+
|| !validateTimeout
138198
);
139199
140200
const resetFields = () => {
@@ -159,6 +219,7 @@ const addTunnel = async () => {
159219
uid: props.uid,
160220
host: host.value,
161221
port: port.value,
222+
ttl: timeout.value,
162223
});
163224
164225
store.dispatch(

0 commit comments

Comments
 (0)