mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
chore: switch to generated types (#1394)
* Make column renderer use the same type as its key
That way the renderer only takes `string` for example when rendering the
name field instead of `string | number` when the interface has some
fields that are strings and some fields are numbers.
This will be necessary when switching to generated types since some of
the fields are numbers (like the owner count on a template).
* Switch fully to generated types
In some places the organization ID is part of the URL but not part of
the request so I separated out the ID into a separate argument in the
relevant API functions.
Otherwise this was a straightforward replacement where I mostly only
needed to change some of the interface names (User instead of
UserResponse for example) and add a few missing but required properties.
I kind of winged the template form; I am not sure what the difference
between a template and template version is or why the latter comes
before the former so the form just returns all the data required to
create both.
* Delete handwritten types
Except for UserAgent which seems to be purely frontend and
ReconnectingPTYRequest which is not in codersdk so I am just leaving it
for now.
* Remove implemented omitempty as a future idea
This was implemented in 2d3dc436a8
.
* Add missing optionalities to generated request interfaces
This commit is contained in:
@ -24,14 +24,14 @@ type Organization struct {
|
|||||||
// CreateTemplateVersionRequest enables callers to create a new Template Version.
|
// CreateTemplateVersionRequest enables callers to create a new Template Version.
|
||||||
type CreateTemplateVersionRequest struct {
|
type CreateTemplateVersionRequest struct {
|
||||||
// TemplateID optionally associates a version with a template.
|
// TemplateID optionally associates a version with a template.
|
||||||
TemplateID uuid.UUID `json:"template_id"`
|
TemplateID uuid.UUID `json:"template_id,omitempty"`
|
||||||
|
|
||||||
StorageMethod database.ProvisionerStorageMethod `json:"storage_method" validate:"oneof=file,required"`
|
StorageMethod database.ProvisionerStorageMethod `json:"storage_method" validate:"oneof=file,required"`
|
||||||
StorageSource string `json:"storage_source" validate:"required"`
|
StorageSource string `json:"storage_source" validate:"required"`
|
||||||
Provisioner database.ProvisionerType `json:"provisioner" validate:"oneof=terraform echo,required"`
|
Provisioner database.ProvisionerType `json:"provisioner" validate:"oneof=terraform echo,required"`
|
||||||
// ParameterValues allows for additional parameters to be provided
|
// ParameterValues allows for additional parameters to be provided
|
||||||
// during the dry-run provision stage.
|
// during the dry-run provision stage.
|
||||||
ParameterValues []CreateParameterRequest `json:"parameter_values"`
|
ParameterValues []CreateParameterRequest `json:"parameter_values,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateTemplateRequest provides options when creating a template.
|
// CreateTemplateRequest provides options when creating a template.
|
||||||
@ -45,7 +45,7 @@ type CreateTemplateRequest struct {
|
|||||||
// template works. There is no reason the data-model cannot support
|
// template works. There is no reason the data-model cannot support
|
||||||
// empty templates, but it doesn't make sense for users.
|
// empty templates, but it doesn't make sense for users.
|
||||||
VersionID uuid.UUID `json:"template_version_id" validate:"required"`
|
VersionID uuid.UUID `json:"template_version_id" validate:"required"`
|
||||||
ParameterValues []CreateParameterRequest `json:"parameter_values"`
|
ParameterValues []CreateParameterRequest `json:"parameter_values,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateWorkspaceRequest provides options for creating a new workspace.
|
// CreateWorkspaceRequest provides options for creating a new workspace.
|
||||||
@ -54,7 +54,7 @@ type CreateWorkspaceRequest struct {
|
|||||||
Name string `json:"name" validate:"username,required"`
|
Name string `json:"name" validate:"username,required"`
|
||||||
// ParameterValues allows for additional parameters to be provided
|
// ParameterValues allows for additional parameters to be provided
|
||||||
// during the initial provision.
|
// during the initial provision.
|
||||||
ParameterValues []CreateParameterRequest `json:"parameter_values"`
|
ParameterValues []CreateParameterRequest `json:"parameter_values,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Organization(ctx context.Context, id uuid.UUID) (Organization, error) {
|
func (c *Client) Organization(ctx context.Context, id uuid.UUID) (Organization, error) {
|
||||||
|
@ -21,9 +21,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type UsersRequest struct {
|
type UsersRequest struct {
|
||||||
Search string `json:"search"`
|
Search string `json:"search,omitempty"`
|
||||||
// Filter users by status
|
// Filter users by status
|
||||||
Status string `json:"status"`
|
Status string `json:"status,omitempty"`
|
||||||
Pagination
|
Pagination
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,9 +31,9 @@ type Workspace struct {
|
|||||||
|
|
||||||
// CreateWorkspaceBuildRequest provides options to update the latest workspace build.
|
// CreateWorkspaceBuildRequest provides options to update the latest workspace build.
|
||||||
type CreateWorkspaceBuildRequest struct {
|
type CreateWorkspaceBuildRequest struct {
|
||||||
TemplateVersionID uuid.UUID `json:"template_version_id"`
|
TemplateVersionID uuid.UUID `json:"template_version_id,omitempty"`
|
||||||
Transition database.WorkspaceTransition `json:"transition" validate:"oneof=create start stop delete,required"`
|
Transition database.WorkspaceTransition `json:"transition" validate:"oneof=create start stop delete,required"`
|
||||||
DryRun bool `json:"dry_run"`
|
DryRun bool `json:"dry_run,omitempty"`
|
||||||
ProvisionerState []byte `json:"state,omitempty"`
|
ProvisionerState []byte `json:"state,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ This main.go generates typescript types from the codersdk types in Go.
|
|||||||
# Features
|
# Features
|
||||||
|
|
||||||
- Supports Go types
|
- Supports Go types
|
||||||
- [x] Basics (string/int/etc)
|
- [x] Basics (string/int/etc)
|
||||||
- [x] Maps
|
- [x] Maps
|
||||||
- [x] Slices
|
- [x] Slices
|
||||||
- [x] Enums
|
- [x] Enums
|
||||||
@ -36,5 +36,4 @@ type InternalType struct {
|
|||||||
|
|
||||||
# Future Ideas
|
# Future Ideas
|
||||||
|
|
||||||
- Should `omitempty` in the `json` tag indicate optional?
|
|
||||||
- Use a yaml config for overriding certain types
|
- Use a yaml config for overriding certain types
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
import { getApiKey, login, logout } from "./api"
|
import { getApiKey, login, logout } from "./api"
|
||||||
import { APIKeyResponse, LoginResponse } from "./types"
|
import * as TypesGen from "./typesGenerated"
|
||||||
|
|
||||||
// Mock the axios module so that no real network requests are made, but rather
|
// Mock the axios module so that no real network requests are made, but rather
|
||||||
// we swap in a resolved or rejected value
|
// we swap in a resolved or rejected value
|
||||||
@ -12,7 +12,7 @@ describe("api.ts", () => {
|
|||||||
describe("login", () => {
|
describe("login", () => {
|
||||||
it("should return LoginResponse", async () => {
|
it("should return LoginResponse", async () => {
|
||||||
// given
|
// given
|
||||||
const loginResponse: LoginResponse = {
|
const loginResponse: TypesGen.LoginWithPasswordResponse = {
|
||||||
session_token: "abc_123_test",
|
session_token: "abc_123_test",
|
||||||
}
|
}
|
||||||
const axiosMockPost = jest.fn().mockImplementationOnce(() => {
|
const axiosMockPost = jest.fn().mockImplementationOnce(() => {
|
||||||
@ -87,7 +87,7 @@ describe("api.ts", () => {
|
|||||||
describe("getApiKey", () => {
|
describe("getApiKey", () => {
|
||||||
it("should return APIKeyResponse", async () => {
|
it("should return APIKeyResponse", async () => {
|
||||||
// given
|
// given
|
||||||
const apiKeyResponse: APIKeyResponse = {
|
const apiKeyResponse: TypesGen.GenerateAPIKeyResponse = {
|
||||||
key: "abc_123_test",
|
key: "abc_123_test",
|
||||||
}
|
}
|
||||||
const axiosMockPost = jest.fn().mockImplementationOnce(() => {
|
const axiosMockPost = jest.fn().mockImplementationOnce(() => {
|
||||||
|
@ -1,26 +1,32 @@
|
|||||||
import axios, { AxiosRequestHeaders } from "axios"
|
import axios, { AxiosRequestHeaders } from "axios"
|
||||||
import { mutate } from "swr"
|
import { mutate } from "swr"
|
||||||
import * as Types from "./types"
|
|
||||||
import * as TypesGen from "./typesGenerated"
|
import * as TypesGen from "./typesGenerated"
|
||||||
|
|
||||||
const CONTENT_TYPE_JSON: AxiosRequestHeaders = {
|
const CONTENT_TYPE_JSON: AxiosRequestHeaders = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const provisioners: Types.Provisioner[] = [
|
export const provisioners: TypesGen.ProvisionerDaemon[] = [
|
||||||
{
|
{
|
||||||
id: "terraform",
|
id: "terraform",
|
||||||
name: "Terraform",
|
name: "Terraform",
|
||||||
|
created_at: "",
|
||||||
|
provisioners: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "cdr-basic",
|
id: "cdr-basic",
|
||||||
name: "Basic",
|
name: "Basic",
|
||||||
|
created_at: "",
|
||||||
|
provisioners: [],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export namespace Workspace {
|
export namespace Workspace {
|
||||||
export const create = async (request: Types.CreateWorkspaceRequest): Promise<Types.Workspace> => {
|
export const create = async (
|
||||||
const response = await fetch(`/api/v2/organizations/${request.organization_id}/workspaces`, {
|
organizationId: string,
|
||||||
|
request: TypesGen.CreateWorkspaceRequest,
|
||||||
|
): Promise<TypesGen.Workspace> => {
|
||||||
|
const response = await fetch(`/api/v2/organizations/${organizationId}/workspaces`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -43,13 +49,13 @@ export namespace Workspace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const login = async (email: string, password: string): Promise<Types.LoginResponse> => {
|
export const login = async (email: string, password: string): Promise<TypesGen.LoginWithPasswordResponse> => {
|
||||||
const payload = JSON.stringify({
|
const payload = JSON.stringify({
|
||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
})
|
})
|
||||||
|
|
||||||
const response = await axios.post<Types.LoginResponse>("/api/v2/users/login", payload, {
|
const response = await axios.post<TypesGen.LoginWithPasswordResponse>("/api/v2/users/login", payload, {
|
||||||
headers: { ...CONTENT_TYPE_JSON },
|
headers: { ...CONTENT_TYPE_JSON },
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -60,8 +66,8 @@ export const logout = async (): Promise<void> => {
|
|||||||
await axios.post("/api/v2/users/logout")
|
await axios.post("/api/v2/users/logout")
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUser = async (): Promise<Types.UserResponse> => {
|
export const getUser = async (): Promise<TypesGen.User> => {
|
||||||
const response = await axios.get<Types.UserResponse>("/api/v2/users/me")
|
const response = await axios.get<TypesGen.User>("/api/v2/users/me")
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,8 +76,8 @@ export const getAuthMethods = async (): Promise<TypesGen.AuthMethods> => {
|
|||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getApiKey = async (): Promise<Types.APIKeyResponse> => {
|
export const getApiKey = async (): Promise<TypesGen.GenerateAPIKeyResponse> => {
|
||||||
const response = await axios.post<Types.APIKeyResponse>("/api/v2/users/me/keys")
|
const response = await axios.post<TypesGen.GenerateAPIKeyResponse>("/api/v2/users/me/keys")
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,23 +86,23 @@ export const getUsers = async (): Promise<TypesGen.User[]> => {
|
|||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getOrganization = async (organizationId: string): Promise<Types.Organization> => {
|
export const getOrganization = async (organizationId: string): Promise<TypesGen.Organization> => {
|
||||||
const response = await axios.get<Types.Organization>(`/api/v2/organizations/${organizationId}`)
|
const response = await axios.get<TypesGen.Organization>(`/api/v2/organizations/${organizationId}`)
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getOrganizations = async (): Promise<Types.Organization[]> => {
|
export const getOrganizations = async (): Promise<TypesGen.Organization[]> => {
|
||||||
const response = await axios.get<Types.Organization[]>("/api/v2/users/me/organizations")
|
const response = await axios.get<TypesGen.Organization[]>("/api/v2/users/me/organizations")
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getTemplate = async (templateId: string): Promise<Types.Template> => {
|
export const getTemplate = async (templateId: string): Promise<TypesGen.Template> => {
|
||||||
const response = await axios.get<Types.Template>(`/api/v2/templates/${templateId}`)
|
const response = await axios.get<TypesGen.Template>(`/api/v2/templates/${templateId}`)
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getWorkspace = async (workspaceId: string): Promise<Types.Workspace> => {
|
export const getWorkspace = async (workspaceId: string): Promise<TypesGen.Workspace> => {
|
||||||
const response = await axios.get<Types.Workspace>(`/api/v2/workspaces/${workspaceId}`)
|
const response = await axios.get<TypesGen.Workspace>(`/api/v2/workspaces/${workspaceId}`)
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,31 +110,33 @@ export const getWorkspaceByOwnerAndName = async (
|
|||||||
organizationID: string,
|
organizationID: string,
|
||||||
username = "me",
|
username = "me",
|
||||||
workspaceName: string,
|
workspaceName: string,
|
||||||
): Promise<Types.Workspace> => {
|
): Promise<TypesGen.Workspace> => {
|
||||||
const response = await axios.get<Types.Workspace>(
|
const response = await axios.get<TypesGen.Workspace>(
|
||||||
`/api/v2/organizations/${organizationID}/workspaces/${username}/${workspaceName}`,
|
`/api/v2/organizations/${organizationID}/workspaces/${username}/${workspaceName}`,
|
||||||
)
|
)
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getWorkspaceResources = async (workspaceBuildID: string): Promise<Types.WorkspaceResource[]> => {
|
export const getWorkspaceResources = async (workspaceBuildID: string): Promise<TypesGen.WorkspaceResource[]> => {
|
||||||
const response = await axios.get<Types.WorkspaceResource[]>(`/api/v2/workspacebuilds/${workspaceBuildID}/resources`)
|
const response = await axios.get<TypesGen.WorkspaceResource[]>(
|
||||||
|
`/api/v2/workspacebuilds/${workspaceBuildID}/resources`,
|
||||||
|
)
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createUser = async (user: Types.CreateUserRequest): Promise<TypesGen.User> => {
|
export const createUser = async (user: TypesGen.CreateUserRequest): Promise<TypesGen.User> => {
|
||||||
const response = await axios.post<TypesGen.User>("/api/v2/users", user)
|
const response = await axios.post<TypesGen.User>("/api/v2/users", user)
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getBuildInfo = async (): Promise<Types.BuildInfoResponse> => {
|
export const getBuildInfo = async (): Promise<TypesGen.BuildInfoResponse> => {
|
||||||
const response = await axios.get("/api/v2/buildinfo")
|
const response = await axios.get("/api/v2/buildinfo")
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export const putWorkspaceAutostart = async (
|
export const putWorkspaceAutostart = async (
|
||||||
workspaceID: string,
|
workspaceID: string,
|
||||||
autostart: Types.WorkspaceAutostartRequest,
|
autostart: TypesGen.UpdateWorkspaceAutostartRequest,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const payload = JSON.stringify(autostart)
|
const payload = JSON.stringify(autostart)
|
||||||
await axios.put(`/api/v2/workspaces/${workspaceID}/autostart`, payload, {
|
await axios.put(`/api/v2/workspaces/${workspaceID}/autostart`, payload, {
|
||||||
@ -138,7 +146,7 @@ export const putWorkspaceAutostart = async (
|
|||||||
|
|
||||||
export const putWorkspaceAutostop = async (
|
export const putWorkspaceAutostop = async (
|
||||||
workspaceID: string,
|
workspaceID: string,
|
||||||
autostop: Types.WorkspaceAutostopRequest,
|
autostop: TypesGen.UpdateWorkspaceAutostopRequest,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const payload = JSON.stringify(autostop)
|
const payload = JSON.stringify(autostop)
|
||||||
await axios.put(`/api/v2/workspaces/${workspaceID}/autostop`, payload, {
|
await axios.put(`/api/v2/workspaces/${workspaceID}/autostop`, payload, {
|
||||||
@ -146,7 +154,10 @@ export const putWorkspaceAutostop = async (
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const updateProfile = async (userId: string, data: Types.UpdateProfileRequest): Promise<Types.UserResponse> => {
|
export const updateProfile = async (
|
||||||
|
userId: string,
|
||||||
|
data: TypesGen.UpdateUserProfileRequest,
|
||||||
|
): Promise<TypesGen.User> => {
|
||||||
const response = await axios.put(`/api/v2/users/${userId}/profile`, data)
|
const response = await axios.put(`/api/v2/users/${userId}/profile`, data)
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
@ -1,101 +1,3 @@
|
|||||||
/**
|
|
||||||
* `BuildInfoResponse` must be kept in sync with the go struct in buildinfo.go.
|
|
||||||
*/
|
|
||||||
export interface BuildInfoResponse {
|
|
||||||
external_url: string
|
|
||||||
version: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LoginResponse {
|
|
||||||
session_token: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateUserRequest {
|
|
||||||
username: string
|
|
||||||
email: string
|
|
||||||
password: string
|
|
||||||
organization_id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserResponse {
|
|
||||||
readonly id: string
|
|
||||||
readonly username: string
|
|
||||||
readonly email: string
|
|
||||||
readonly created_at: string
|
|
||||||
readonly status: "active" | "suspended"
|
|
||||||
readonly organization_ids: string[]
|
|
||||||
readonly roles: { name: string; display_name: string }[]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* `Organization` must be kept in sync with the go struct in organizations.go
|
|
||||||
*/
|
|
||||||
export interface Organization {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
created_at: string
|
|
||||||
updated_at: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Provisioner {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// This must be kept in sync with the `Template` struct in the back-end
|
|
||||||
export interface Template {
|
|
||||||
id: string
|
|
||||||
created_at: string
|
|
||||||
updated_at: string
|
|
||||||
organization_id: string
|
|
||||||
name: string
|
|
||||||
provisioner: string
|
|
||||||
active_version_id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateTemplateRequest {
|
|
||||||
name: string
|
|
||||||
organizationId: string
|
|
||||||
provisioner: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateWorkspaceRequest {
|
|
||||||
name: string
|
|
||||||
template_id: string
|
|
||||||
organization_id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WorkspaceBuild {
|
|
||||||
id: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Workspace {
|
|
||||||
id: string
|
|
||||||
created_at: string
|
|
||||||
updated_at: string
|
|
||||||
owner_id: string
|
|
||||||
template_id: string
|
|
||||||
name: string
|
|
||||||
autostart_schedule: string
|
|
||||||
autostop_schedule: string
|
|
||||||
latest_build: WorkspaceBuild
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WorkspaceResource {
|
|
||||||
id: string
|
|
||||||
agents?: WorkspaceAgent[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WorkspaceAgent {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
operating_system: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface APIKeyResponse {
|
|
||||||
key: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserAgent {
|
export interface UserAgent {
|
||||||
readonly browser: string
|
readonly browser: string
|
||||||
readonly device: string
|
readonly device: string
|
||||||
@ -103,19 +5,6 @@ export interface UserAgent {
|
|||||||
readonly os: string
|
readonly os: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WorkspaceAutostartRequest {
|
|
||||||
schedule: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WorkspaceAutostopRequest {
|
|
||||||
schedule: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpdateProfileRequest {
|
|
||||||
readonly username: string
|
|
||||||
readonly email: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ReconnectingPTYRequest {
|
export interface ReconnectingPTYRequest {
|
||||||
readonly data?: string
|
readonly data?: string
|
||||||
readonly height?: number
|
readonly height?: number
|
||||||
|
@ -63,18 +63,18 @@ export interface CreateParameterRequest {
|
|||||||
export interface CreateTemplateRequest {
|
export interface CreateTemplateRequest {
|
||||||
readonly name: string
|
readonly name: string
|
||||||
readonly template_version_id: string
|
readonly template_version_id: string
|
||||||
readonly parameter_values: CreateParameterRequest[]
|
readonly parameter_values?: CreateParameterRequest[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// From codersdk/organizations.go:25:6
|
// From codersdk/organizations.go:25:6
|
||||||
export interface CreateTemplateVersionRequest {
|
export interface CreateTemplateVersionRequest {
|
||||||
readonly template_id: string
|
readonly template_id?: string
|
||||||
// This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ProvisionerStorageMethod")
|
// This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ProvisionerStorageMethod")
|
||||||
readonly storage_method: string
|
readonly storage_method: string
|
||||||
readonly storage_source: string
|
readonly storage_source: string
|
||||||
// This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ProvisionerType")
|
// This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ProvisionerType")
|
||||||
readonly provisioner: string
|
readonly provisioner: string
|
||||||
readonly parameter_values: CreateParameterRequest[]
|
readonly parameter_values?: CreateParameterRequest[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// From codersdk/users.go:54:6
|
// From codersdk/users.go:54:6
|
||||||
@ -87,10 +87,10 @@ export interface CreateUserRequest {
|
|||||||
|
|
||||||
// From codersdk/workspaces.go:33:6
|
// From codersdk/workspaces.go:33:6
|
||||||
export interface CreateWorkspaceBuildRequest {
|
export interface CreateWorkspaceBuildRequest {
|
||||||
readonly template_version_id: string
|
readonly template_version_id?: string
|
||||||
// This is likely an enum in an external package ("github.com/coder/coder/coderd/database.WorkspaceTransition")
|
// This is likely an enum in an external package ("github.com/coder/coder/coderd/database.WorkspaceTransition")
|
||||||
readonly transition: string
|
readonly transition: string
|
||||||
readonly dry_run: boolean
|
readonly dry_run?: boolean
|
||||||
readonly state?: string
|
readonly state?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ export interface CreateWorkspaceBuildRequest {
|
|||||||
export interface CreateWorkspaceRequest {
|
export interface CreateWorkspaceRequest {
|
||||||
readonly template_id: string
|
readonly template_id: string
|
||||||
readonly name: string
|
readonly name: string
|
||||||
readonly parameter_values: CreateParameterRequest[]
|
readonly parameter_values?: CreateParameterRequest[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// From codersdk/users.go:91:6
|
// From codersdk/users.go:91:6
|
||||||
@ -323,8 +323,8 @@ export interface UserRoles {
|
|||||||
|
|
||||||
// From codersdk/users.go:23:6
|
// From codersdk/users.go:23:6
|
||||||
export interface UsersRequest extends Pagination {
|
export interface UsersRequest extends Pagination {
|
||||||
readonly search: string
|
readonly search?: string
|
||||||
readonly status: string
|
readonly status?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// From codersdk/workspaces.go:18:6
|
// From codersdk/workspaces.go:18:6
|
||||||
|
@ -3,7 +3,7 @@ import TextField from "@material-ui/core/TextField"
|
|||||||
import { FormikContextType, FormikErrors, useFormik } from "formik"
|
import { FormikContextType, FormikErrors, useFormik } from "formik"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import * as Yup from "yup"
|
import * as Yup from "yup"
|
||||||
import { CreateUserRequest } from "../../api/types"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
import { getFormHelpers, onChangeTrimmed } from "../../util/formUtils"
|
import { getFormHelpers, onChangeTrimmed } from "../../util/formUtils"
|
||||||
import { FormFooter } from "../FormFooter/FormFooter"
|
import { FormFooter } from "../FormFooter/FormFooter"
|
||||||
import { FullPageForm } from "../FullPageForm/FullPageForm"
|
import { FullPageForm } from "../FullPageForm/FullPageForm"
|
||||||
@ -21,9 +21,9 @@ export const Language = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateUserFormProps {
|
export interface CreateUserFormProps {
|
||||||
onSubmit: (user: CreateUserRequest) => void
|
onSubmit: (user: TypesGen.CreateUserRequest) => void
|
||||||
onCancel: () => void
|
onCancel: () => void
|
||||||
formErrors?: FormikErrors<CreateUserRequest>
|
formErrors?: FormikErrors<TypesGen.CreateUserRequest>
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
error?: string
|
error?: string
|
||||||
myOrgId: string
|
myOrgId: string
|
||||||
@ -43,7 +43,7 @@ export const CreateUserForm: React.FC<CreateUserFormProps> = ({
|
|||||||
error,
|
error,
|
||||||
myOrgId,
|
myOrgId,
|
||||||
}) => {
|
}) => {
|
||||||
const form: FormikContextType<CreateUserRequest> = useFormik<CreateUserRequest>({
|
const form: FormikContextType<TypesGen.CreateUserRequest> = useFormik<TypesGen.CreateUserRequest>({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
email: "",
|
email: "",
|
||||||
password: "",
|
password: "",
|
||||||
@ -53,7 +53,7 @@ export const CreateUserForm: React.FC<CreateUserFormProps> = ({
|
|||||||
validationSchema,
|
validationSchema,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
})
|
})
|
||||||
const getFieldHelpers = getFormHelpers<CreateUserRequest>(form, formErrors)
|
const getFieldHelpers = getFormHelpers<TypesGen.CreateUserRequest>(form, formErrors)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FullPageForm title="Create user" onCancel={onCancel}>
|
<FullPageForm title="Create user" onCancel={onCancel}>
|
||||||
|
@ -3,11 +3,11 @@ import { makeStyles } from "@material-ui/core/styles"
|
|||||||
import Typography from "@material-ui/core/Typography"
|
import Typography from "@material-ui/core/Typography"
|
||||||
import { useActor } from "@xstate/react"
|
import { useActor } from "@xstate/react"
|
||||||
import React, { useContext } from "react"
|
import React, { useContext } from "react"
|
||||||
import { BuildInfoResponse } from "../../api/types"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
import { XServiceContext } from "../../xServices/StateContext"
|
import { XServiceContext } from "../../xServices/StateContext"
|
||||||
|
|
||||||
export const Language = {
|
export const Language = {
|
||||||
buildInfoText: (buildInfo: BuildInfoResponse): string => {
|
buildInfoText: (buildInfo: TypesGen.BuildInfoResponse): string => {
|
||||||
return `Coder ${buildInfo.version}`
|
return `Coder ${buildInfo.version}`
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,14 @@ import ListItem from "@material-ui/core/ListItem"
|
|||||||
import { fade, makeStyles } from "@material-ui/core/styles"
|
import { fade, makeStyles } from "@material-ui/core/styles"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { NavLink } from "react-router-dom"
|
import { NavLink } from "react-router-dom"
|
||||||
import { UserResponse } from "../../api/types"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
import { navHeight } from "../../theme/constants"
|
import { navHeight } from "../../theme/constants"
|
||||||
import { AdminDropdown } from "../AdminDropdown/AdminDropdown"
|
import { AdminDropdown } from "../AdminDropdown/AdminDropdown"
|
||||||
import { Logo } from "../Icons/Logo"
|
import { Logo } from "../Icons/Logo"
|
||||||
import { UserDropdown } from "../UserDropdown/UsersDropdown"
|
import { UserDropdown } from "../UserDropdown/UsersDropdown"
|
||||||
|
|
||||||
export interface NavbarViewProps {
|
export interface NavbarViewProps {
|
||||||
user?: UserResponse
|
user?: TypesGen.User
|
||||||
onSignOut: () => void
|
onSignOut: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,20 +8,22 @@ import React from "react"
|
|||||||
import { TableHeaders } from "../TableHeaders/TableHeaders"
|
import { TableHeaders } from "../TableHeaders/TableHeaders"
|
||||||
import { TableTitle } from "../TableTitle/TableTitle"
|
import { TableTitle } from "../TableTitle/TableTitle"
|
||||||
|
|
||||||
export interface Column<T> {
|
export type Column<T> = {
|
||||||
/**
|
[K in keyof T]: {
|
||||||
* The field of type T that this column is associated with
|
/**
|
||||||
*/
|
* The field of type T that this column is associated with
|
||||||
key: keyof T
|
*/
|
||||||
/**
|
key: K
|
||||||
* Friendly name of the field, shown in headers
|
/**
|
||||||
*/
|
* Friendly name of the field, shown in headers
|
||||||
name: string
|
*/
|
||||||
/**
|
name: string
|
||||||
* Custom render for the field inside the table
|
/**
|
||||||
*/
|
* Custom render for the field inside the table
|
||||||
renderer?: (field: T[keyof T], data: T) => React.ReactElement
|
*/
|
||||||
}
|
renderer?: (field: T[K], data: T) => React.ReactElement
|
||||||
|
}
|
||||||
|
}[keyof T]
|
||||||
|
|
||||||
export interface TableProps<T> {
|
export interface TableProps<T> {
|
||||||
/**
|
/**
|
||||||
|
@ -7,7 +7,7 @@ import { fade, makeStyles } from "@material-ui/core/styles"
|
|||||||
import AccountIcon from "@material-ui/icons/AccountCircleOutlined"
|
import AccountIcon from "@material-ui/icons/AccountCircleOutlined"
|
||||||
import React, { useState } from "react"
|
import React, { useState } from "react"
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "react-router-dom"
|
||||||
import { UserResponse } from "../../api/types"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
import { BorderedMenu } from "../BorderedMenu/BorderedMenu"
|
import { BorderedMenu } from "../BorderedMenu/BorderedMenu"
|
||||||
import { CloseDropdown, OpenDropdown } from "../DropdownArrows/DropdownArrows"
|
import { CloseDropdown, OpenDropdown } from "../DropdownArrows/DropdownArrows"
|
||||||
import { DocsIcon } from "../Icons/DocsIcon"
|
import { DocsIcon } from "../Icons/DocsIcon"
|
||||||
@ -21,7 +21,7 @@ export const Language = {
|
|||||||
signOutLabel: "Sign Out",
|
signOutLabel: "Sign Out",
|
||||||
}
|
}
|
||||||
export interface UserDropdownProps {
|
export interface UserDropdownProps {
|
||||||
user: UserResponse
|
user: TypesGen.User
|
||||||
onSignOut: () => void
|
onSignOut: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { makeStyles } from "@material-ui/core/styles"
|
import { makeStyles } from "@material-ui/core/styles"
|
||||||
import Typography from "@material-ui/core/Typography"
|
import Typography from "@material-ui/core/Typography"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { UserResponse } from "../../api/types"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
import { UserAvatar } from "../UserAvatar/UserAvatar"
|
import { UserAvatar } from "../UserAvatar/UserAvatar"
|
||||||
|
|
||||||
interface UserProfileCardProps {
|
interface UserProfileCardProps {
|
||||||
user: UserResponse
|
user: TypesGen.User
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UserProfileCard: React.FC<UserProfileCardProps> = ({ user }) => {
|
export const UserProfileCard: React.FC<UserProfileCardProps> = ({ user }) => {
|
||||||
|
@ -5,7 +5,6 @@ import TableCell from "@material-ui/core/TableCell"
|
|||||||
import TableHead from "@material-ui/core/TableHead"
|
import TableHead from "@material-ui/core/TableHead"
|
||||||
import TableRow from "@material-ui/core/TableRow"
|
import TableRow from "@material-ui/core/TableRow"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { UserResponse } from "../../api/types"
|
|
||||||
import * as TypesGen from "../../api/typesGenerated"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
import { EmptyState } from "../EmptyState/EmptyState"
|
import { EmptyState } from "../EmptyState/EmptyState"
|
||||||
import { RoleSelect } from "../RoleSelect/RoleSelect"
|
import { RoleSelect } from "../RoleSelect/RoleSelect"
|
||||||
@ -25,10 +24,10 @@ export const Language = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface UsersTableProps {
|
export interface UsersTableProps {
|
||||||
users: UserResponse[]
|
users: TypesGen.User[]
|
||||||
onSuspendUser: (user: UserResponse) => void
|
onSuspendUser: (user: TypesGen.User) => void
|
||||||
onResetUserPassword: (user: UserResponse) => void
|
onResetUserPassword: (user: TypesGen.User) => void
|
||||||
onUpdateUserRoles: (user: UserResponse, roles: TypesGen.Role["name"][]) => void
|
onUpdateUserRoles: (user: TypesGen.User, roles: TypesGen.Role["name"][]) => void
|
||||||
roles: TypesGen.Role[]
|
roles: TypesGen.Role[]
|
||||||
isUpdatingUserRoles?: boolean
|
isUpdatingUserRoles?: boolean
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,15 @@ import Typography from "@material-ui/core/Typography"
|
|||||||
import CloudCircleIcon from "@material-ui/icons/CloudCircle"
|
import CloudCircleIcon from "@material-ui/icons/CloudCircle"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "react-router-dom"
|
||||||
import * as Types from "../../api/types"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
import { WorkspaceSchedule } from "../WorkspaceSchedule/WorkspaceSchedule"
|
import { WorkspaceSchedule } from "../WorkspaceSchedule/WorkspaceSchedule"
|
||||||
import { WorkspaceSection } from "../WorkspaceSection/WorkspaceSection"
|
import { WorkspaceSection } from "../WorkspaceSection/WorkspaceSection"
|
||||||
import * as Constants from "./constants"
|
import * as Constants from "./constants"
|
||||||
|
|
||||||
export interface WorkspaceProps {
|
export interface WorkspaceProps {
|
||||||
organization: Types.Organization
|
organization: TypesGen.Organization
|
||||||
workspace: Types.Workspace
|
workspace: TypesGen.Workspace
|
||||||
template: Types.Template
|
template: TypesGen.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,7 +3,7 @@ import { makeStyles } from "@material-ui/core/styles"
|
|||||||
import { FormikContextType, useFormik } from "formik"
|
import { FormikContextType, useFormik } from "formik"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import * as Yup from "yup"
|
import * as Yup from "yup"
|
||||||
import { CreateTemplateRequest, Organization, Provisioner, Template } from "../api/types"
|
import * as TypesGen from "../api/typesGenerated"
|
||||||
import { FormCloseButton } from "../components/FormCloseButton/FormCloseButton"
|
import { FormCloseButton } from "../components/FormCloseButton/FormCloseButton"
|
||||||
import { FormDropdownField, FormDropdownItem } from "../components/FormDropdownField/FormDropdownField"
|
import { FormDropdownField, FormDropdownItem } from "../components/FormDropdownField/FormDropdownField"
|
||||||
import { FormSection } from "../components/FormSection/FormSection"
|
import { FormSection } from "../components/FormSection/FormSection"
|
||||||
@ -12,13 +12,21 @@ import { FormTitle } from "../components/FormTitle/FormTitle"
|
|||||||
import { LoadingButton } from "../components/LoadingButton/LoadingButton"
|
import { LoadingButton } from "../components/LoadingButton/LoadingButton"
|
||||||
import { maxWidth } from "../theme/constants"
|
import { maxWidth } from "../theme/constants"
|
||||||
|
|
||||||
|
// It appears that to create a template you need to create a template version
|
||||||
|
// and then a template so this contains the information to do both.
|
||||||
|
export type CreateTemplateRequest = TypesGen.CreateTemplateVersionRequest & Pick<TypesGen.CreateTemplateRequest, "name">
|
||||||
|
|
||||||
export interface CreateTemplateFormProps {
|
export interface CreateTemplateFormProps {
|
||||||
provisioners: Provisioner[]
|
provisioners: TypesGen.ProvisionerDaemon[]
|
||||||
organizations: Organization[]
|
organizations: TypesGen.Organization[]
|
||||||
onSubmit: (request: CreateTemplateRequest) => Promise<Template>
|
onSubmit: (organizationId: string, request: CreateTemplateRequest) => Promise<TypesGen.Template>
|
||||||
onCancel: () => void
|
onCancel: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CreateTemplateFields extends Pick<CreateTemplateRequest, "name" | "provisioner"> {
|
||||||
|
organizationId: string
|
||||||
|
}
|
||||||
|
|
||||||
const validationSchema = Yup.object({
|
const validationSchema = Yup.object({
|
||||||
provisioner: Yup.string().required("Provisioner is required."),
|
provisioner: Yup.string().required("Provisioner is required."),
|
||||||
organizationId: Yup.string().required("Organization is required."),
|
organizationId: Yup.string().required("Organization is required."),
|
||||||
@ -33,7 +41,7 @@ export const CreateTemplateForm: React.FC<CreateTemplateFormProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const styles = useStyles()
|
const styles = useStyles()
|
||||||
|
|
||||||
const form: FormikContextType<CreateTemplateRequest> = useFormik<CreateTemplateRequest>({
|
const form: FormikContextType<CreateTemplateFields> = useFormik<CreateTemplateFields>({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
provisioner: provisioners[0].id,
|
provisioner: provisioners[0].id,
|
||||||
organizationId: organizations[0].name,
|
organizationId: organizations[0].name,
|
||||||
@ -42,7 +50,12 @@ export const CreateTemplateForm: React.FC<CreateTemplateFormProps> = ({
|
|||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
validationSchema: validationSchema,
|
validationSchema: validationSchema,
|
||||||
onSubmit: (req) => {
|
onSubmit: (req) => {
|
||||||
return onSubmit(req)
|
return onSubmit(req.organizationId, {
|
||||||
|
name: req.name,
|
||||||
|
storage_method: "file",
|
||||||
|
storage_source: "hash",
|
||||||
|
provisioner: req.provisioner,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ describe("CreateWorkspaceForm", () => {
|
|||||||
template={MockTemplate}
|
template={MockTemplate}
|
||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
organization_id={MockOrganization.id}
|
organizationId={MockOrganization.id}
|
||||||
/>,
|
/>,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { makeStyles } from "@material-ui/core/styles"
|
|||||||
import { FormikContextType, useFormik } from "formik"
|
import { FormikContextType, useFormik } from "formik"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import * as Yup from "yup"
|
import * as Yup from "yup"
|
||||||
import { CreateWorkspaceRequest, Template, Workspace } from "../api/types"
|
import * as TypesGen from "../api/typesGenerated"
|
||||||
import { FormCloseButton } from "../components/FormCloseButton/FormCloseButton"
|
import { FormCloseButton } from "../components/FormCloseButton/FormCloseButton"
|
||||||
import { FormSection } from "../components/FormSection/FormSection"
|
import { FormSection } from "../components/FormSection/FormSection"
|
||||||
import { FormTextField } from "../components/FormTextField/FormTextField"
|
import { FormTextField } from "../components/FormTextField/FormTextField"
|
||||||
@ -12,10 +12,10 @@ import { LoadingButton } from "../components/LoadingButton/LoadingButton"
|
|||||||
import { maxWidth } from "../theme/constants"
|
import { maxWidth } from "../theme/constants"
|
||||||
|
|
||||||
export interface CreateWorkspaceForm {
|
export interface CreateWorkspaceForm {
|
||||||
template: Template
|
template: TypesGen.Template
|
||||||
onSubmit: (request: CreateWorkspaceRequest) => Promise<Workspace>
|
onSubmit: (organizationId: string, request: TypesGen.CreateWorkspaceRequest) => Promise<TypesGen.Workspace>
|
||||||
onCancel: () => void
|
onCancel: () => void
|
||||||
organization_id: string
|
organizationId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const validationSchema = Yup.object({
|
const validationSchema = Yup.object({
|
||||||
@ -26,7 +26,7 @@ export const CreateWorkspaceForm: React.FC<CreateWorkspaceForm> = ({
|
|||||||
template,
|
template,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onCancel,
|
onCancel,
|
||||||
organization_id,
|
organizationId,
|
||||||
}) => {
|
}) => {
|
||||||
const styles = useStyles()
|
const styles = useStyles()
|
||||||
|
|
||||||
@ -37,10 +37,9 @@ export const CreateWorkspaceForm: React.FC<CreateWorkspaceForm> = ({
|
|||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
validationSchema: validationSchema,
|
validationSchema: validationSchema,
|
||||||
onSubmit: ({ name }) => {
|
onSubmit: ({ name }) => {
|
||||||
return onSubmit({
|
return onSubmit(organizationId, {
|
||||||
template_id: template.id,
|
template_id: template.id,
|
||||||
name: name,
|
name: name,
|
||||||
organization_id,
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -4,7 +4,7 @@ import React, { useCallback, useContext } from "react"
|
|||||||
import { useNavigate, useParams } from "react-router-dom"
|
import { useNavigate, useParams } from "react-router-dom"
|
||||||
import useSWR from "swr"
|
import useSWR from "swr"
|
||||||
import * as API from "../../../../api/api"
|
import * as API from "../../../../api/api"
|
||||||
import * as Types from "../../../../api/types"
|
import * as TypesGen from "../../../../api/typesGenerated"
|
||||||
import { ErrorSummary } from "../../../../components/ErrorSummary/ErrorSummary"
|
import { ErrorSummary } from "../../../../components/ErrorSummary/ErrorSummary"
|
||||||
import { FullScreenLoader } from "../../../../components/Loader/FullScreenLoader"
|
import { FullScreenLoader } from "../../../../components/Loader/FullScreenLoader"
|
||||||
import { CreateWorkspaceForm } from "../../../../forms/CreateWorkspaceForm"
|
import { CreateWorkspaceForm } from "../../../../forms/CreateWorkspaceForm"
|
||||||
@ -20,11 +20,11 @@ export const CreateWorkspacePage: React.FC = () => {
|
|||||||
const xServices = useContext(XServiceContext)
|
const xServices = useContext(XServiceContext)
|
||||||
const myOrgId = useSelector(xServices.authXService, selectOrgId)
|
const myOrgId = useSelector(xServices.authXService, selectOrgId)
|
||||||
|
|
||||||
const { data: organizationInfo, error: organizationError } = useSWR<Types.Organization, Error>(
|
const { data: organizationInfo, error: organizationError } = useSWR<TypesGen.Organization, Error>(
|
||||||
() => `/api/v2/users/me/organizations/${organizationName}`,
|
() => `/api/v2/users/me/organizations/${organizationName}`,
|
||||||
)
|
)
|
||||||
|
|
||||||
const { data: template, error: templateError } = useSWR<Types.Template, Error>(() => {
|
const { data: template, error: templateError } = useSWR<TypesGen.Template, Error>(() => {
|
||||||
return `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/templates/${templateName}`
|
return `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/templates/${templateName}`
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -32,8 +32,8 @@ export const CreateWorkspacePage: React.FC = () => {
|
|||||||
navigate(`/templates/${organizationName}/${templateName}`)
|
navigate(`/templates/${organizationName}/${templateName}`)
|
||||||
}, [navigate, organizationName, templateName])
|
}, [navigate, organizationName, templateName])
|
||||||
|
|
||||||
const onSubmit = async (req: Types.CreateWorkspaceRequest) => {
|
const onSubmit = async (organizationId: string, req: TypesGen.CreateWorkspaceRequest) => {
|
||||||
const workspace = await API.Workspace.create(req)
|
const workspace = await API.Workspace.create(organizationId, req)
|
||||||
navigate(`/workspaces/${workspace.id}`)
|
navigate(`/workspaces/${workspace.id}`)
|
||||||
return workspace
|
return workspace
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ export const CreateWorkspacePage: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
<CreateWorkspaceForm onCancel={onCancel} onSubmit={onSubmit} template={template} organization_id={myOrgId} />
|
<CreateWorkspaceForm onCancel={onCancel} onSubmit={onSubmit} template={template} organizationId={myOrgId} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { Link, useNavigate, useParams } from "react-router-dom"
|
import { Link, useNavigate, useParams } from "react-router-dom"
|
||||||
import useSWR from "swr"
|
import useSWR from "swr"
|
||||||
import { Organization, Template, Workspace, WorkspaceBuild } from "../../../../api/types"
|
import * as TypesGen from "../../../../api/typesGenerated"
|
||||||
import { EmptyState } from "../../../../components/EmptyState/EmptyState"
|
import { EmptyState } from "../../../../components/EmptyState/EmptyState"
|
||||||
import { ErrorSummary } from "../../../../components/ErrorSummary/ErrorSummary"
|
import { ErrorSummary } from "../../../../components/ErrorSummary/ErrorSummary"
|
||||||
import { Header } from "../../../../components/Header/Header"
|
import { Header } from "../../../../components/Header/Header"
|
||||||
@ -16,18 +16,18 @@ export const TemplatePage: React.FC = () => {
|
|||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { template: templateName, organization: organizationName } = useParams()
|
const { template: templateName, organization: organizationName } = useParams()
|
||||||
|
|
||||||
const { data: organizationInfo, error: organizationError } = useSWR<Organization, Error>(
|
const { data: organizationInfo, error: organizationError } = useSWR<TypesGen.Organization, Error>(
|
||||||
() => `/api/v2/users/me/organizations/${organizationName}`,
|
() => `/api/v2/users/me/organizations/${organizationName}`,
|
||||||
)
|
)
|
||||||
|
|
||||||
const { data: templateInfo, error: templateError } = useSWR<Template, Error>(
|
const { data: templateInfo, error: templateError } = useSWR<TypesGen.Template, Error>(
|
||||||
() => `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/templates/${templateName}`,
|
() => `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/templates/${templateName}`,
|
||||||
)
|
)
|
||||||
|
|
||||||
// This just grabs all workspaces... and then later filters them to match the
|
// This just grabs all workspaces... and then later filters them to match the
|
||||||
// current template.
|
// current template.
|
||||||
|
|
||||||
const { data: workspaces, error: workspacesError } = useSWR<Workspace[], Error>(
|
const { data: workspaces, error: workspacesError } = useSWR<TypesGen.Workspace[], Error>(
|
||||||
() => `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/workspaces`,
|
() => `/api/v2/organizations/${unsafeSWRArgument(organizationInfo).id}/workspaces`,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -62,11 +62,11 @@ export const TemplatePage: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
const columns: Column<Workspace>[] = [
|
const columns: Column<TypesGen.Workspace>[] = [
|
||||||
{
|
{
|
||||||
key: "name",
|
key: "name",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
renderer: (nameField: string | WorkspaceBuild, workspace: Workspace) => {
|
renderer: (nameField: string | TypesGen.WorkspaceBuild, workspace: TypesGen.Workspace) => {
|
||||||
return <Link to={`/workspaces/${workspace.id}`}>{nameField}</Link>
|
return <Link to={`/workspaces/${workspace.id}`}>{nameField}</Link>
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,7 @@ import { makeStyles } from "@material-ui/core/styles"
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "react-router-dom"
|
||||||
import useSWR from "swr"
|
import useSWR from "swr"
|
||||||
import { Organization, Template } from "../../api/types"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
import { CodeExample } from "../../components/CodeExample/CodeExample"
|
import { CodeExample } from "../../components/CodeExample/CodeExample"
|
||||||
import { EmptyState } from "../../components/EmptyState/EmptyState"
|
import { EmptyState } from "../../components/EmptyState/EmptyState"
|
||||||
import { ErrorSummary } from "../../components/ErrorSummary/ErrorSummary"
|
import { ErrorSummary } from "../../components/ErrorSummary/ErrorSummary"
|
||||||
@ -14,8 +14,8 @@ import { Column, Table } from "../../components/Table/Table"
|
|||||||
|
|
||||||
export const TemplatesPage: React.FC = () => {
|
export const TemplatesPage: React.FC = () => {
|
||||||
const styles = useStyles()
|
const styles = useStyles()
|
||||||
const { data: orgs, error: orgsError } = useSWR<Organization[], Error>("/api/v2/users/me/organizations")
|
const { data: orgs, error: orgsError } = useSWR<TypesGen.Organization[], Error>("/api/v2/users/me/organizations")
|
||||||
const { data: templates, error } = useSWR<Template[] | null, Error>(
|
const { data: templates, error } = useSWR<TypesGen.Template[] | null, Error>(
|
||||||
orgs ? `/api/v2/organizations/${orgs[0].id}/templates` : null,
|
orgs ? `/api/v2/organizations/${orgs[0].id}/templates` : null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,18 +33,18 @@ export const TemplatesPage: React.FC = () => {
|
|||||||
|
|
||||||
// Create a dictionary of organization ID -> organization Name
|
// Create a dictionary of organization ID -> organization Name
|
||||||
// Needed to properly construct links to dive into a template
|
// Needed to properly construct links to dive into a template
|
||||||
const orgDictionary = orgs.reduce((acc: Record<string, string>, curr: Organization) => {
|
const orgDictionary = orgs.reduce((acc: Record<string, string>, curr: TypesGen.Organization) => {
|
||||||
return {
|
return {
|
||||||
...acc,
|
...acc,
|
||||||
[curr.id]: curr.name,
|
[curr.id]: curr.name,
|
||||||
}
|
}
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
const columns: Column<Template>[] = [
|
const columns: Column<TypesGen.Template>[] = [
|
||||||
{
|
{
|
||||||
key: "name",
|
key: "name",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
renderer: (nameField: string, data: Template) => {
|
renderer: (nameField: string, data: TypesGen.Template) => {
|
||||||
return <Link to={`/templates/${orgDictionary[data.organization_id]}/${nameField}`}>{nameField}</Link>
|
return <Link to={`/templates/${orgDictionary[data.organization_id]}/${nameField}`}>{nameField}</Link>
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useActor, useSelector } from "@xstate/react"
|
import { useActor, useSelector } from "@xstate/react"
|
||||||
import React, { useContext } from "react"
|
import React, { useContext } from "react"
|
||||||
import { useNavigate } from "react-router"
|
import { useNavigate } from "react-router"
|
||||||
import { CreateUserRequest } from "../../../api/types"
|
import * as TypesGen from "../../../api/typesGenerated"
|
||||||
import { CreateUserForm } from "../../../components/CreateUserForm/CreateUserForm"
|
import { CreateUserForm } from "../../../components/CreateUserForm/CreateUserForm"
|
||||||
import { Margins } from "../../../components/Margins/Margins"
|
import { Margins } from "../../../components/Margins/Margins"
|
||||||
import { selectOrgId } from "../../../xServices/auth/authSelectors"
|
import { selectOrgId } from "../../../xServices/auth/authSelectors"
|
||||||
@ -25,7 +25,7 @@ export const CreateUserPage: React.FC = () => {
|
|||||||
<Margins>
|
<Margins>
|
||||||
<CreateUserForm
|
<CreateUserForm
|
||||||
formErrors={createUserFormErrors}
|
formErrors={createUserFormErrors}
|
||||||
onSubmit={(user: CreateUserRequest) => usersSend({ type: "CREATE", user })}
|
onSubmit={(user: TypesGen.CreateUserRequest) => usersSend({ type: "CREATE", user })}
|
||||||
onCancel={() => navigate("/users")}
|
onCancel={() => navigate("/users")}
|
||||||
isLoading={usersState.hasTag("loading")}
|
isLoading={usersState.hasTag("loading")}
|
||||||
error={genericError}
|
error={genericError}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { UserResponse } from "../../api/types"
|
|
||||||
import * as TypesGen from "../../api/typesGenerated"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
import { ErrorSummary } from "../../components/ErrorSummary/ErrorSummary"
|
import { ErrorSummary } from "../../components/ErrorSummary/ErrorSummary"
|
||||||
import { Header } from "../../components/Header/Header"
|
import { Header } from "../../components/Header/Header"
|
||||||
@ -13,11 +12,11 @@ export const Language = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface UsersPageViewProps {
|
export interface UsersPageViewProps {
|
||||||
users: UserResponse[]
|
users: TypesGen.User[]
|
||||||
openUserCreationDialog: () => void
|
openUserCreationDialog: () => void
|
||||||
onSuspendUser: (user: UserResponse) => void
|
onSuspendUser: (user: TypesGen.User) => void
|
||||||
onResetUserPassword: (user: UserResponse) => void
|
onResetUserPassword: (user: TypesGen.User) => void
|
||||||
onUpdateUserRoles: (user: UserResponse, roles: TypesGen.Role["name"][]) => void
|
onUpdateUserRoles: (user: TypesGen.User, roles: TypesGen.Role["name"][]) => void
|
||||||
roles: TypesGen.Role[]
|
roles: TypesGen.Role[]
|
||||||
error?: unknown
|
error?: unknown
|
||||||
isUpdatingUserRoles?: boolean
|
isUpdatingUserRoles?: boolean
|
||||||
|
@ -1,44 +1,37 @@
|
|||||||
import {
|
import * as Types from "../api/types"
|
||||||
BuildInfoResponse,
|
import * as TypesGen from "../api/typesGenerated"
|
||||||
Organization,
|
|
||||||
Provisioner,
|
|
||||||
Template,
|
|
||||||
UserAgent,
|
|
||||||
UserResponse,
|
|
||||||
Workspace,
|
|
||||||
WorkspaceAgent,
|
|
||||||
WorkspaceAutostartRequest,
|
|
||||||
WorkspaceResource,
|
|
||||||
} from "../api/types"
|
|
||||||
import { AuthMethods, Role } from "../api/typesGenerated"
|
|
||||||
|
|
||||||
export const MockSessionToken = { session_token: "my-session-token" }
|
export const MockSessionToken: TypesGen.LoginWithPasswordResponse = {
|
||||||
|
session_token: "my-session-token",
|
||||||
|
}
|
||||||
|
|
||||||
export const MockAPIKey = { key: "my-api-key" }
|
export const MockAPIKey: TypesGen.GenerateAPIKeyResponse = {
|
||||||
|
key: "my-api-key",
|
||||||
|
}
|
||||||
|
|
||||||
export const MockBuildInfo: BuildInfoResponse = {
|
export const MockBuildInfo: TypesGen.BuildInfoResponse = {
|
||||||
external_url: "file:///mock-url",
|
external_url: "file:///mock-url",
|
||||||
version: "v99.999.9999+c9cdf14",
|
version: "v99.999.9999+c9cdf14",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockAdminRole: Role = {
|
export const MockAdminRole: TypesGen.Role = {
|
||||||
name: "admin",
|
name: "admin",
|
||||||
display_name: "Admin",
|
display_name: "Admin",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockMemberRole: Role = {
|
export const MockMemberRole: TypesGen.Role = {
|
||||||
name: "member",
|
name: "member",
|
||||||
display_name: "Member",
|
display_name: "Member",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockAuditorRole: Role = {
|
export const MockAuditorRole: TypesGen.Role = {
|
||||||
name: "auditor",
|
name: "auditor",
|
||||||
display_name: "Auditor",
|
display_name: "Auditor",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockSiteRoles = [MockAdminRole, MockAuditorRole, MockMemberRole]
|
export const MockSiteRoles = [MockAdminRole, MockAuditorRole, MockMemberRole]
|
||||||
|
|
||||||
export const MockUser: UserResponse = {
|
export const MockUser: TypesGen.User = {
|
||||||
id: "test-user",
|
id: "test-user",
|
||||||
username: "TestUser",
|
username: "TestUser",
|
||||||
email: "test@coder.com",
|
email: "test@coder.com",
|
||||||
@ -48,7 +41,7 @@ export const MockUser: UserResponse = {
|
|||||||
roles: [MockAdminRole, MockMemberRole],
|
roles: [MockAdminRole, MockMemberRole],
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockUser2: UserResponse = {
|
export const MockUser2: TypesGen.User = {
|
||||||
id: "test-user-2",
|
id: "test-user-2",
|
||||||
username: "TestUser2",
|
username: "TestUser2",
|
||||||
email: "test2@coder.com",
|
email: "test2@coder.com",
|
||||||
@ -58,19 +51,27 @@ export const MockUser2: UserResponse = {
|
|||||||
roles: [MockMemberRole],
|
roles: [MockMemberRole],
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockOrganization: Organization = {
|
export const MockOrganization: TypesGen.Organization = {
|
||||||
id: "test-org",
|
id: "test-org",
|
||||||
name: "Test Organization",
|
name: "Test Organization",
|
||||||
created_at: "",
|
created_at: "",
|
||||||
updated_at: "",
|
updated_at: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockProvisioner: Provisioner = {
|
export const MockProvisioner: TypesGen.ProvisionerDaemon = {
|
||||||
|
created_at: "",
|
||||||
id: "test-provisioner",
|
id: "test-provisioner",
|
||||||
name: "Test Provisioner",
|
name: "Test Provisioner",
|
||||||
|
provisioners: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockTemplate: Template = {
|
export const MockProvisionerJob: TypesGen.ProvisionerJob = {
|
||||||
|
created_at: "",
|
||||||
|
id: "test-provisioner-job",
|
||||||
|
status: "succeeded",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MockTemplate: TypesGen.Template = {
|
||||||
id: "test-template",
|
id: "test-template",
|
||||||
created_at: "",
|
created_at: "",
|
||||||
updated_at: "",
|
updated_at: "",
|
||||||
@ -78,60 +79,86 @@ export const MockTemplate: Template = {
|
|||||||
name: "Test Template",
|
name: "Test Template",
|
||||||
provisioner: MockProvisioner.id,
|
provisioner: MockProvisioner.id,
|
||||||
active_version_id: "",
|
active_version_id: "",
|
||||||
|
workspace_owner_count: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockWorkspaceAutostartDisabled: WorkspaceAutostartRequest = {
|
export const MockWorkspaceAutostartDisabled: TypesGen.UpdateWorkspaceAutostartRequest = {
|
||||||
schedule: "",
|
schedule: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockWorkspaceAutostartEnabled: WorkspaceAutostartRequest = {
|
export const MockWorkspaceAutostartEnabled: TypesGen.UpdateWorkspaceAutostartRequest = {
|
||||||
// Runs at 9:30am Monday through Friday using Canada/Eastern
|
// Runs at 9:30am Monday through Friday using Canada/Eastern
|
||||||
// (America/Toronto) time
|
// (America/Toronto) time
|
||||||
schedule: "CRON_TZ=Canada/Eastern 30 9 * * 1-5",
|
schedule: "CRON_TZ=Canada/Eastern 30 9 * * 1-5",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockWorkspaceAutostopDisabled: WorkspaceAutostartRequest = {
|
export const MockWorkspaceAutostopDisabled: TypesGen.UpdateWorkspaceAutostartRequest = {
|
||||||
schedule: "",
|
schedule: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockWorkspaceAutostopEnabled: WorkspaceAutostartRequest = {
|
export const MockWorkspaceAutostopEnabled: TypesGen.UpdateWorkspaceAutostartRequest = {
|
||||||
// Runs at 9:30pm Monday through Friday using America/Toronto
|
// Runs at 9:30pm Monday through Friday using America/Toronto
|
||||||
schedule: "CRON_TZ=America/Toronto 30 21 * * 1-5",
|
schedule: "CRON_TZ=America/Toronto 30 21 * * 1-5",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockWorkspace: Workspace = {
|
export const MockWorkspaceBuild: TypesGen.WorkspaceBuild = {
|
||||||
|
after_id: "",
|
||||||
|
before_id: "",
|
||||||
|
created_at: "",
|
||||||
|
id: "test-workspace-build",
|
||||||
|
initiator_id: "",
|
||||||
|
job: MockProvisionerJob,
|
||||||
|
name: "a-workspace-build",
|
||||||
|
template_version_id: "",
|
||||||
|
transition: "start",
|
||||||
|
updated_at: "",
|
||||||
|
workspace_id: "test-workspace",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MockWorkspace: TypesGen.Workspace = {
|
||||||
id: "test-workspace",
|
id: "test-workspace",
|
||||||
name: "Test-Workspace",
|
name: "Test-Workspace",
|
||||||
created_at: "",
|
created_at: "",
|
||||||
updated_at: "",
|
updated_at: "",
|
||||||
template_id: MockTemplate.id,
|
template_id: MockTemplate.id,
|
||||||
|
template_name: MockTemplate.name,
|
||||||
|
outdated: false,
|
||||||
owner_id: MockUser.id,
|
owner_id: MockUser.id,
|
||||||
autostart_schedule: MockWorkspaceAutostartEnabled.schedule,
|
autostart_schedule: MockWorkspaceAutostartEnabled.schedule,
|
||||||
autostop_schedule: MockWorkspaceAutostopEnabled.schedule,
|
autostop_schedule: MockWorkspaceAutostopEnabled.schedule,
|
||||||
latest_build: {
|
latest_build: MockWorkspaceBuild,
|
||||||
id: "test-workspace-build",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockWorkspaceAgent: WorkspaceAgent = {
|
export const MockWorkspaceAgent: TypesGen.WorkspaceAgent = {
|
||||||
|
architecture: "amd64",
|
||||||
|
created_at: "",
|
||||||
|
environment_variables: {},
|
||||||
id: "test-workspace-agent",
|
id: "test-workspace-agent",
|
||||||
name: "a-workspace-agent",
|
name: "a-workspace-agent",
|
||||||
operating_system: "linux",
|
operating_system: "linux",
|
||||||
|
resource_id: "",
|
||||||
|
status: "connected",
|
||||||
|
updated_at: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockWorkspaceResource: WorkspaceResource = {
|
export const MockWorkspaceResource: TypesGen.WorkspaceResource = {
|
||||||
id: "test-workspace-resource",
|
|
||||||
agents: [MockWorkspaceAgent],
|
agents: [MockWorkspaceAgent],
|
||||||
|
created_at: "",
|
||||||
|
id: "test-workspace-resource",
|
||||||
|
job_id: "",
|
||||||
|
name: "a-workspace-resource",
|
||||||
|
type: "google_compute_disk",
|
||||||
|
workspace_transition: "start",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockUserAgent: UserAgent = {
|
export const MockUserAgent: Types.UserAgent = {
|
||||||
browser: "Chrome 99.0.4844",
|
browser: "Chrome 99.0.4844",
|
||||||
device: "Other",
|
device: "Other",
|
||||||
ip_address: "11.22.33.44",
|
ip_address: "11.22.33.44",
|
||||||
os: "Windows 10",
|
os: "Windows 10",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MockAuthMethods: AuthMethods = {
|
export const MockAuthMethods: TypesGen.AuthMethods = {
|
||||||
password: true,
|
password: true,
|
||||||
github: false,
|
github: false,
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { assign, createMachine } from "xstate"
|
import { assign, createMachine } from "xstate"
|
||||||
import * as API from "../../api/api"
|
import * as API from "../../api/api"
|
||||||
import * as Types from "../../api/types"
|
|
||||||
import * as TypesGen from "../../api/typesGenerated"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
import { displaySuccess } from "../../components/GlobalSnackbar/utils"
|
import { displaySuccess } from "../../components/GlobalSnackbar/utils"
|
||||||
|
|
||||||
@ -13,14 +12,14 @@ export interface AuthContext {
|
|||||||
getMethodsError?: Error | unknown
|
getMethodsError?: Error | unknown
|
||||||
authError?: Error | unknown
|
authError?: Error | unknown
|
||||||
updateProfileError?: Error | unknown
|
updateProfileError?: Error | unknown
|
||||||
me?: Types.UserResponse
|
me?: TypesGen.User
|
||||||
methods?: TypesGen.AuthMethods
|
methods?: TypesGen.AuthMethods
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AuthEvent =
|
export type AuthEvent =
|
||||||
| { type: "SIGN_OUT" }
|
| { type: "SIGN_OUT" }
|
||||||
| { type: "SIGN_IN"; email: string; password: string }
|
| { type: "SIGN_IN"; email: string; password: string }
|
||||||
| { type: "UPDATE_PROFILE"; data: Types.UpdateProfileRequest }
|
| { type: "UPDATE_PROFILE"; data: TypesGen.UpdateUserProfileRequest }
|
||||||
|
|
||||||
export const authMachine =
|
export const authMachine =
|
||||||
/** @xstate-layout N4IgpgJg5mDOIC5QEMCuAXAFgZXc9YAdLAJZQB2kA8hgMTYCSA4gHID6DLioADgPal0JPuW4gAHogDsABgCshOQA4AzABY5ARgBMUgJxrtcgDQgAnok0zNSwkpkrNKvQDY3aqS6kBfb6bRYuPhEpBQk5FAM5LQQIkThAG58ANYhZORRYvyCwqJIEohyMlKE2mrFKo7aLq5SJuaILtq2mjZqrboy2s4+fiABOHgExOnhkdFgAE6TfJOEPAA2+ABmswC2IxSZ+dkkQiJikgiyCsrqWroGRqYWCHoq2oQyDpouXa1qGmq+-hiDwYQYOghBEAKqwKYxOKERIpIhAgCyYCyAj2uUOiF0mieTik3UqMhqSleN0QhgUOhUbzUKhk9jKch+-T+QWGQJBUHBkKmMzmixW60BYHQSJROQO+SOUmxVKUniUcjkUgVLjlpOOCqecj0LyKmmVeiUTIGrPhwo5SKwfAgsChlBh5CSqSFIuFmGt8B2qP2eVARxUeNKCo02k0cllTRc6qUalsCtU731DikvV+gSGZuBY0t7pttB5s3mS3Qq0mG0Rbo9YrREr9iHUMkIUnKHSklQVKnqtz0BkImjUbmeShcVmejL6Jozm0oECi8xmyxIC3iEGXtFBAAUACIAQQAKgBRNgbgBKVAAYgwADIH6s+jEIOV6Qgj1oxnTBkfq7qNlxyT4aC4saaPcVLGiyU6hDOc48AuS5EKgPAQPgYwbnBa6xPasLOpOAJQZAMHoQhSEoREaF8Iuy4ILCADGKEiAA2jIAC6d7opKiBPi+rRtB+-5fg0CDqM+YafG8+jWLI2jgemeHpAR5DzhR8GEIhyEcuRlFgPm0yFvyJaCrhwz4bOimwcpy6qSRGlEdRjp8HRPpMaxXrir6BSPvo3Fvu0zT8Zo6oDmoTb-p8cjaFcsjqDJ-zGfJpn0Mw7BUKCe5sbWHm6CU2jWKGnhaFSeLqv2jZKMOehOE49i0v+MWmtOYw0OgdrxPZzpQU16XuUcAC0-aPGGSgVQOTS4ko2jfjGhC0gB1WeDIBguHVkGjBETU6byRYCmW06da5NbdZiKalLl+p-k4XgTYJNhxuVNKGCB77fEy5DWnAYhGWkFDUBgXUPoqLiKOoxIqGVejNKoxXPCUMgjZ8zj6sORoThBclhBE2y8N67F1o+xIvhoejavqEX-gFgl6IGFWOC2bzWNqy0AuyYxcpMf0cQghjqn+JT6GJeJynIqrI2msWZhalY2uzuN9dojwpn+epDvqHjRkUL7KBDEljiLzKyXF32mUpWkwquRCvQeuls-t94c606s8c0A5C00UjqqDja5cUXQRXiDiMwb0FmURpuWQW1tY25D7242jsxn+bi6IFhh2K4qjKP+fsqAHX1B8bKkkGb0seR0gNx87idu4JtIwzoxTdELzbheOov1SZhEWcR6moURxdHCOgPhsBoNDRDKju84hCfHS4ZAXPqg59OCn58ufeFODQPD2DY-FUqGsASmdShgvKP67nClrwgQu2EPIPb2V4+CVNf7w5TOphs22en2LDVrb9Ns4w8j1coU8iafDKJVWQagDDqmOsOKBVhXDgweNJb+ppL59TcH2ZQw1E5jSurcYK8CHCODfE0B4vRfBAA */
|
/** @xstate-layout N4IgpgJg5mDOIC5QEMCuAXAFgZXc9YAdLAJZQB2kA8hgMTYCSA4gHID6DLioADgPal0JPuW4gAHogDsABgCshOQA4AzABY5ARgBMUgJxrtcgDQgAnok0zNSwkpkrNKvQDY3aqS6kBfb6bRYuPhEpBQk5FAM5LQQIkThAG58ANYhZORRYvyCwqJIEohyMlKE2mrFKo7aLq5SJuaILtq2mjZqrboy2s4+fiABOHgExOnhkdFgAE6TfJOEPAA2+ABmswC2IxSZ+dkkQiJikgiyCsrqWroGRqYWCHoq2oQyDpouXa1qGmq+-hiDwYQYOghBEAKqwKYxOKERIpIhAgCyYCyAj2uUOiF0mieTik3UqMhqSleN0QhgUOhUbzUKhk9jKch+-T+QWGQJBUHBkKmMzmixW60BYHQSJROQO+SOUmxVKUniUcjkUgVLjlpOOCqecj0LyKmmVeiUTIGrPhwo5SKwfAgsChlBh5CSqSFIuFmGt8B2qP2eVARxUeNKCo02k0cllTRc6qUalsCtU731DikvV+gSGZuBY0t7pttB5s3mS3Qq0mG0Rbo9YrREr9iHUMkIUnKHSklQVKnqtz0BkImjUbmeShcVmejL6Jozm0oECi8xmyxIC3iEGXtFBAAUACIAQQAKgBRNgbgBKVAAYgwADIH6s+jEIOV6Qgj1oxnTBkfq7qNlxyT4aC4saaPcVLGiyU6hDOc48AuS5EKgPAQPgYwbnBa6xPasLOpOAJQZAMHoQhSEoREaF8Iuy4ILCADGKEiAA2jIAC6d7opKiBPi+rRtB+-5fg0CDqM+YafG8+jWLI2jgemeHpAR5DzhR8GEIhyEcuRlFgPm0yFvyJaCrhwz4bOimwcpy6qSRGlEdRjp8HRPpMaxXrir6BSPvo3Fvu0zT8Zo6oDmoTb-p8cjaFcsjqDJ-zGfJpn0Mw7BUKCe5sbWHm6CU2jWKGnhaFSeLqv2jZKMOehOE49i0v+MWmtOYw0OgdrxPZzpQU16XuUcAC0-aPGGSgVQOTS4ko2jfjGhC0gB1WeDIBguHVkGjBETU6byRYCmW06da5NbdZiKalLl+p-k4XgTYJNhxuVNKGCB77fEy5DWnAYhGWkFDUBgXUPoqLiKOoxIqGVejNKoxXPCUMgjZ8zj6sORoThBclhBE2y8N67F1o+xIvhoejavqEX-gFgl6IGFWOC2bzWNqy0AuyYxcpMf0cQghjqn+JT6GJeJynIqrI2msWZhalY2uzuN9dojwpn+epDvqHjRkUL7KBDEljiLzKyXF32mUpWkwquRCvQeuls-t94c606s8c0A5C00UjqqDja5cUXQRXiDiMwb0FmURpuWQW1tY25D7242jsxn+bi6IFhh2K4qjKP+fsqAHX1B8bKkkGb0seR0gNx87idu4JtIwzoxTdELzbheOov1SZhEWcR6moURxdHCOgPhsBoNDRDKju84hCfHS4ZAXPqg59OCn58ufeFODQPD2DY-FUqGsASmdShgvKP67nClrwgQu2EPIPb2V4+CVNf7w5TOphs22en2LDVrb9Ns4w8j1coU8iafDKJVWQagDDqmOsOKBVhXDgweNJb+ppL59TcH2ZQw1E5jSurcYK8CHCODfE0B4vRfBAA */
|
||||||
@ -40,16 +39,16 @@ export const authMachine =
|
|||||||
events: {} as AuthEvent,
|
events: {} as AuthEvent,
|
||||||
services: {} as {
|
services: {} as {
|
||||||
getMe: {
|
getMe: {
|
||||||
data: Types.UserResponse
|
data: TypesGen.User
|
||||||
}
|
}
|
||||||
getMethods: {
|
getMethods: {
|
||||||
data: TypesGen.AuthMethods
|
data: TypesGen.AuthMethods
|
||||||
}
|
}
|
||||||
signIn: {
|
signIn: {
|
||||||
data: Types.LoginResponse
|
data: TypesGen.LoginWithPasswordResponse
|
||||||
}
|
}
|
||||||
updateProfile: {
|
updateProfile: {
|
||||||
data: Types.UserResponse
|
data: TypesGen.User
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { assign, createMachine } from "xstate"
|
import { assign, createMachine } from "xstate"
|
||||||
import * as API from "../../api/api"
|
import * as API from "../../api/api"
|
||||||
import * as Types from "../../api/types"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
|
|
||||||
export interface BuildInfoContext {
|
export interface BuildInfoContext {
|
||||||
getBuildInfoError?: Error | unknown
|
getBuildInfoError?: Error | unknown
|
||||||
buildInfo?: Types.BuildInfoResponse
|
buildInfo?: TypesGen.BuildInfoResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
export const buildInfoMachine = createMachine(
|
export const buildInfoMachine = createMachine(
|
||||||
@ -14,7 +14,7 @@ export const buildInfoMachine = createMachine(
|
|||||||
context: {} as BuildInfoContext,
|
context: {} as BuildInfoContext,
|
||||||
services: {} as {
|
services: {} as {
|
||||||
getBuildInfo: {
|
getBuildInfo: {
|
||||||
data: Types.BuildInfoResponse
|
data: TypesGen.BuildInfoResponse
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { assign, createMachine } from "xstate"
|
import { assign, createMachine } from "xstate"
|
||||||
import * as API from "../../api/api"
|
import * as API from "../../api/api"
|
||||||
import * as Types from "../../api/types"
|
import * as Types from "../../api/types"
|
||||||
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
|
|
||||||
export interface TerminalContext {
|
export interface TerminalContext {
|
||||||
organizationsError?: Error | unknown
|
organizationsError?: Error | unknown
|
||||||
organizations?: Types.Organization[]
|
organizations?: TypesGen.Organization[]
|
||||||
workspaceError?: Error | unknown
|
workspaceError?: Error | unknown
|
||||||
workspace?: Types.Workspace
|
workspace?: TypesGen.Workspace
|
||||||
workspaceAgent?: Types.WorkspaceAgent
|
workspaceAgent?: TypesGen.WorkspaceAgent
|
||||||
workspaceAgentError?: Error | unknown
|
workspaceAgentError?: Error | unknown
|
||||||
websocket?: WebSocket
|
websocket?: WebSocket
|
||||||
websocketError?: Error | unknown
|
websocketError?: Error | unknown
|
||||||
@ -34,13 +35,13 @@ export const terminalMachine =
|
|||||||
events: {} as TerminalEvent,
|
events: {} as TerminalEvent,
|
||||||
services: {} as {
|
services: {} as {
|
||||||
getOrganizations: {
|
getOrganizations: {
|
||||||
data: Types.Organization[]
|
data: TypesGen.Organization[]
|
||||||
}
|
}
|
||||||
getWorkspace: {
|
getWorkspace: {
|
||||||
data: Types.Workspace
|
data: TypesGen.Workspace
|
||||||
}
|
}
|
||||||
getWorkspaceAgent: {
|
getWorkspaceAgent: {
|
||||||
data: Types.WorkspaceAgent
|
data: TypesGen.WorkspaceAgent
|
||||||
}
|
}
|
||||||
connect: {
|
connect: {
|
||||||
data: WebSocket
|
data: WebSocket
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { assign, createMachine } from "xstate"
|
import { assign, createMachine } from "xstate"
|
||||||
import * as API from "../../api/api"
|
import * as API from "../../api/api"
|
||||||
import { ApiError, FieldErrors, isApiError, mapApiErrorToFieldErrors } from "../../api/errors"
|
import { ApiError, FieldErrors, isApiError, mapApiErrorToFieldErrors } from "../../api/errors"
|
||||||
import * as Types from "../../api/types"
|
|
||||||
import * as TypesGen from "../../api/typesGenerated"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
import { displayError, displaySuccess } from "../../components/GlobalSnackbar/utils"
|
import { displayError, displaySuccess } from "../../components/GlobalSnackbar/utils"
|
||||||
import { generateRandomString } from "../../util/random"
|
import { generateRandomString } from "../../util/random"
|
||||||
@ -36,7 +35,7 @@ export interface UsersContext {
|
|||||||
|
|
||||||
export type UsersEvent =
|
export type UsersEvent =
|
||||||
| { type: "GET_USERS" }
|
| { type: "GET_USERS" }
|
||||||
| { type: "CREATE"; user: Types.CreateUserRequest }
|
| { type: "CREATE"; user: TypesGen.CreateUserRequest }
|
||||||
// Suspend events
|
// Suspend events
|
||||||
| { type: "SUSPEND_USER"; userId: TypesGen.User["id"] }
|
| { type: "SUSPEND_USER"; userId: TypesGen.User["id"] }
|
||||||
| { type: "CONFIRM_USER_SUSPENSION" }
|
| { type: "CONFIRM_USER_SUSPENSION" }
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { assign, createMachine } from "xstate"
|
import { assign, createMachine } from "xstate"
|
||||||
import * as API from "../../api/api"
|
import * as API from "../../api/api"
|
||||||
import * as Types from "../../api/types"
|
import * as TypesGen from "../../api/typesGenerated"
|
||||||
|
|
||||||
interface WorkspaceContext {
|
interface WorkspaceContext {
|
||||||
workspace?: Types.Workspace
|
workspace?: TypesGen.Workspace
|
||||||
template?: Types.Template
|
template?: TypesGen.Template
|
||||||
organization?: Types.Organization
|
organization?: TypesGen.Organization
|
||||||
getWorkspaceError?: Error | unknown
|
getWorkspaceError?: Error | unknown
|
||||||
getTemplateError?: Error | unknown
|
getTemplateError?: Error | unknown
|
||||||
getOrganizationError?: Error | unknown
|
getOrganizationError?: Error | unknown
|
||||||
@ -21,13 +21,13 @@ export const workspaceMachine = createMachine(
|
|||||||
events: {} as WorkspaceEvent,
|
events: {} as WorkspaceEvent,
|
||||||
services: {} as {
|
services: {} as {
|
||||||
getWorkspace: {
|
getWorkspace: {
|
||||||
data: Types.Workspace
|
data: TypesGen.Workspace
|
||||||
}
|
}
|
||||||
getTemplate: {
|
getTemplate: {
|
||||||
data: Types.Template
|
data: TypesGen.Template
|
||||||
}
|
}
|
||||||
getOrganization: {
|
getOrganization: {
|
||||||
data: Types.Organization
|
data: TypesGen.Organization
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user