mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 07:41:27 +00:00
feat(mobile): env editing, domains, scaling, notifications (#61)
Companion app was read-mostly — quick fixes still needed a workstation. - service/variables: full env editor — add/edit/delete rows, secret toggle, masked-secret preservation (untouched secrets resubmit the "********" placeholder so stored ciphertext survives the PUT). - service/domains: list with default/TLS status, add, remove, set-default. - service/settings: replicas stepper (0–16), container port, scale-to- zero toggle + idle minutes — saves via PUT /services/:id. - (tabs)/notifications: alerts tab with unread badge on the tab bar, mark-read per item and mark-all. - Service detail gains a Manage section linking all three screens. State initializes at mount inside a child component rather than an effect — post-save refetches no longer clobber in-flight edits, and the react-hooks/set-state-in-effect lint stays clean. Verified: tsc --noEmit, expo lint, expo export (android bundle, 1378 modules — router graph compiles). Authored By: TDvorak <[email protected]>
This commit is contained in:
1 parent
3cc84553f4
commit
604319ee06
8 files changed
+758
No files matched your search
@@ -68,6 +68,36 @@ export interface Template {
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
export interface Variable {
|
||||
id?: string;
|
||||
key: string;
|
||||
value: string;
|
||||
is_secret: boolean;
|
||||
}
|
||||
|
||||
export interface ServiceDomain {
|
||||
id: string;
|
||||
domain: string;
|
||||
is_default: boolean;
|
||||
cert_type?: string;
|
||||
cert_status?: string;
|
||||
}
|
||||
|
||||
export interface AppNotification {
|
||||
id: string;
|
||||
kind: string;
|
||||
title: string;
|
||||
body?: string;
|
||||
resource_type?: string;
|
||||
resource_id?: string;
|
||||
read_at?: string | null;
|
||||
created_at?: string;
|
||||
}
|
||||
|
||||
// Masked value the API returns for secret variables; echoing it back on
|
||||
// update preserves the stored ciphertext.
|
||||
export const MASKED_SECRET = '********';
|
||||
|
||||
export class ApiError extends Error {
|
||||
constructor(
|
||||
public status: number,
|
||||
@@ -145,6 +175,69 @@ export class Api {
|
||||
return this.req<EnvCheck>('GET', `/services/${id}/env-check`);
|
||||
}
|
||||
|
||||
serviceVariables(id: string) {
|
||||
return this.req<{ variables: Variable[] }>('GET', `/services/${id}/variables`).then(
|
||||
(r) => r.variables ?? [],
|
||||
);
|
||||
}
|
||||
|
||||
updateVariables(id: string, variables: { key: string; value: string; is_secret: boolean }[]) {
|
||||
return this.req<unknown>('PUT', `/services/${id}/variables`, { variables });
|
||||
}
|
||||
|
||||
serviceDomains(id: string) {
|
||||
return this.req<{ domains: ServiceDomain[] }>('GET', `/services/${id}/domains`).then(
|
||||
(r) => r.domains ?? [],
|
||||
);
|
||||
}
|
||||
|
||||
addDomain(id: string, domain: string) {
|
||||
return this.req<unknown>('POST', `/services/${id}/domains`, { domain });
|
||||
}
|
||||
|
||||
deleteDomain(id: string, domainId: string) {
|
||||
return this.req<unknown>('DELETE', `/services/${id}/domains/${domainId}`);
|
||||
}
|
||||
|
||||
setDefaultDomain(id: string, domainId: string) {
|
||||
return this.req<unknown>('POST', `/services/${id}/domains/${domainId}/default`);
|
||||
}
|
||||
|
||||
updateService(
|
||||
id: string,
|
||||
patch: Partial<{
|
||||
name: string;
|
||||
command: string;
|
||||
replicas: number;
|
||||
port: number;
|
||||
domain: string;
|
||||
restart_policy: string;
|
||||
healthcheck_path: string;
|
||||
cpu: string;
|
||||
memory: string;
|
||||
sleep_enabled: boolean;
|
||||
sleep_idle_minutes: number;
|
||||
maintenance_mode: boolean;
|
||||
}>,
|
||||
) {
|
||||
return this.req<unknown>('PUT', `/services/${id}`, patch);
|
||||
}
|
||||
|
||||
notifications() {
|
||||
return this.req<{ notifications: AppNotification[]; unread: number }>(
|
||||
'GET',
|
||||
'/notifications?limit=50',
|
||||
);
|
||||
}
|
||||
|
||||
markNotificationRead(id: string) {
|
||||
return this.req<unknown>('POST', `/notifications/${id}/read`);
|
||||
}
|
||||
|
||||
markAllNotificationsRead() {
|
||||
return this.req<unknown>('POST', '/notifications/read-all');
|
||||
}
|
||||
|
||||
serviceDeployments(id: string) {
|
||||
return this.req<{ deployments: Deployment[] }>(
|
||||
'GET',
|
||||
|
||||
Reference in new issue
Block a user