projects

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2025 License: MIT Imports: 9 Imported by: 0

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type LegacyDate

type LegacyDate time.Time

LegacyDate is a type alias for time.Time, used to represent legacy date values in the API.

func (LegacyDate) MarshalJSON

func (d LegacyDate) MarshalJSON() ([]byte, error)

MarshalJSON encodes the LegacyDate as a string in the format "20060102".

func (*LegacyDate) UnmarshalJSON

func (d *LegacyDate) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a JSON string into a LegacyDate type.

type LegacyNumber

type LegacyNumber int64

LegacyNumber is a type alias for int64, used to represent numeric values in the API.

func (LegacyNumber) MarshalJSON

func (n LegacyNumber) MarshalJSON() ([]byte, error)

MarshalJSON encodes the LegacyNumber as a string.

func (*LegacyNumber) UnmarshalJSON

func (n *LegacyNumber) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes a JSON string into a LegacyNumber type.

type Project added in v0.0.3

type Project struct {
	// ID is the unique identifier of the project.
	ID int64 `json:"id"`

	// Description is an optional description of the project.
	Description *string `json:"description"`

	// Name is the name of the project.
	Name string `json:"name"`

	// StartAt is the start date of the project.
	StartAt *time.Time `json:"startAt"`

	// EndAt is the end date of the project.
	EndAt *time.Time `json:"endAt"`

	// Company is the company associated with the project.
	Company twapi.Relationship `json:"company"`

	// Owner is the user who owns the project.
	Owner *twapi.Relationship `json:"projectOwner"`

	// Tags is a list of tags associated with the project.
	Tags []twapi.Relationship `json:"tags"`

	// CreatedAt is the date and time when the project was created.
	CreatedAt *time.Time `json:"createdAt"`

	// CreatedBy is the ID of the user who created the project.
	CreatedBy *int64 `json:"createdBy"`

	// UpdatedAt is the date and time when the project was last updated.
	UpdatedAt *time.Time `json:"updatedAt"`

	// UpdatedBy is the ID of the user who last updated the project.
	UpdatedBy *int64 `json:"updatedBy"`

	// CompletedAt is the date and time when the project was completed.
	CompletedAt *time.Time `json:"completedAt"`

	// CompletedBy is the ID of the user who completed the project.
	CompletedBy *int64 `json:"completedBy"`

	// Status is the status of the project. It can be "active", "inactive"
	// (archived) or "deleted".
	Status string `json:"status"`

	// Type is the type of the project. It can be "normal", "tasklists-template",
	// "projects-template", "personal", "holder-project", "tentative" or
	// "global-messages".
	Type string `json:"type"`
}

Project represents a project in Teamwork.

type ProjectCreateRequest

type ProjectCreateRequest struct {
	// Name is the name of the project.
	Name string `json:"name"`

	// Description is an optional description of the project.
	Description *string `json:"description,omitempty"`

	// StartAt is an optional start date for the project. By default it doesn't
	// have a start date.
	StartAt *LegacyDate `json:"start-date,omitempty"`

	// EndAt is an optional end date for the project. By default it doesn't have
	// an end date.
	EndAt *LegacyDate `json:"end-date,omitempty"`

	// CompanyID is an optional ID of the company/client associated with the
	// project. By default it is the ID of the company of the logged user
	// creating the project.
	CompanyID int64 `json:"companyId"`

	// OwnerID is an optional ID of the user who owns the project. By default it
	// is the ID of the logged user creating the project.
	OwnerID *int64 `json:"projectOwnerId,omitempty"`

	// TagIDs is an optional list of tag IDs associated with the project.
	TagIDs []int64 `json:"tagIds,omitempty"`
}

ProjectCreateRequest represents the request body for creating a new project.

https://apidocs.teamwork.com/docs/teamwork/v1/projects/post-projects-json

func NewProjectCreateRequest added in v0.0.6

func NewProjectCreateRequest(name string) ProjectCreateRequest

NewProjectCreateRequest creates a new ProjectCreateRequest with the provided name. The name is required to create a new project.

func (ProjectCreateRequest) HTTPRequest

func (p ProjectCreateRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the ProjectCreateRequest.

type ProjectCreateResponse

type ProjectCreateResponse struct {
	// ID is the unique identifier of the created project.
	ID LegacyNumber `json:"id"`
}

ProjectCreateResponse represents the response body for creating a new project.

https://apidocs.teamwork.com/docs/teamwork/v1/projects/post-projects-json

func ProjectCreate

func ProjectCreate(
	ctx context.Context,
	engine *twapi.Engine,
	req ProjectCreateRequest,
) (*ProjectCreateResponse, error)

ProjectCreate creates a new project using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"
	"time"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startProjectServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	project, err := projects.ProjectCreate(ctx, engine, projects.ProjectCreateRequest{
		Name:        "New Project",
		Description: twapi.Ptr("This is a new project created via the API."),
		StartAt:     twapi.Ptr(projects.LegacyDate(time.Now().AddDate(0, 0, 1))),  // Start tomorrow
		EndAt:       twapi.Ptr(projects.LegacyDate(time.Now().AddDate(0, 0, 30))), // End in 30 days
		CompanyID:   12345,                                                        // Replace with your company ID
		OwnerID:     twapi.Ptr(int64(67890)),                                      // Replace with the owner user ID
		TagIDs:      []int64{11111, 22222},                                        // Replace with your tag IDs
	})
	if err != nil {
		fmt.Printf("failed to create project: %s", err)
	} else {
		fmt.Printf("created project with identifier %d\n", project.ID)
	}

}

func startProjectServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK","id":"12345"}`)
	})
	mux.HandleFunc("PUT /projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("DELETE /projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("GET /projects/api/v3/projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"project":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/projects", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"projects":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

created project with identifier 12345

func (*ProjectCreateResponse) HandleHTTPResponse

func (p *ProjectCreateResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the ProjectCreateResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type ProjectDeleteRequest added in v0.0.3

type ProjectDeleteRequest struct {
	// Path contains the path parameters for the request.
	Path ProjectDeleteRequestPath
}

ProjectDeleteRequest represents the request body for deleting a project.

https://apidocs.teamwork.com/docs/teamwork/v1/projects/delete-projects-id-json

func NewProjectDeleteRequest added in v0.0.6

func NewProjectDeleteRequest(projectID int64) ProjectDeleteRequest

NewProjectDeleteRequest creates a new ProjectDeleteRequest with the provided project ID.

func (ProjectDeleteRequest) HTTPRequest added in v0.0.3

func (p ProjectDeleteRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the ProjectDeleteRequest.

type ProjectDeleteRequestPath added in v0.0.6

type ProjectDeleteRequestPath struct {
	// ID is the unique identifier of the project to be deleted.
	ID int64
}

ProjectDeleteRequestPath contains the path parameters for deleting a project.

type ProjectDeleteResponse added in v0.0.3

type ProjectDeleteResponse struct{}

ProjectDeleteResponse represents the response body for deleting a project.

https://apidocs.teamwork.com/docs/teamwork/v1/projects/delete-projects-id-json

func ProjectDelete added in v0.0.3

func ProjectDelete(
	ctx context.Context,
	engine *twapi.Engine,
	req ProjectDeleteRequest,
) (*ProjectDeleteResponse, error)

ProjectDelete creates a new project using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startProjectServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	_, err = projects.ProjectDelete(ctx, engine, projects.NewProjectDeleteRequest(12345))
	if err != nil {
		fmt.Printf("failed to delete project: %s", err)
	} else {
		fmt.Println("project deleted!")
	}

}

func startProjectServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK","id":"12345"}`)
	})
	mux.HandleFunc("PUT /projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("DELETE /projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("GET /projects/api/v3/projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"project":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/projects", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"projects":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

project deleted!

func (*ProjectDeleteResponse) HandleHTTPResponse added in v0.0.3

func (p *ProjectDeleteResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the ProjectDeleteResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type ProjectGetRequest added in v0.0.6

type ProjectGetRequest struct {
	// Path contains the path parameters for the request.
	Path ProjectGetRequestPath
}

ProjectGetRequest represents the request body for loading a single project.

https://apidocs.teamwork.com/docs/teamwork/v3/projects/get-projects-api-v3-projects-project-id-json

func NewProjectGetRequest added in v0.0.6

func NewProjectGetRequest(projectID int64) ProjectGetRequest

NewProjectGetRequest creates a new ProjectGetRequest with the provided project ID. The ID is required to load a project.

func (ProjectGetRequest) HTTPRequest added in v0.0.6

func (p ProjectGetRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the ProjectGetRequest.

type ProjectGetRequestPath added in v0.0.6

type ProjectGetRequestPath struct {
	// ID is the unique identifier of the project to be retrieved.
	ID int64 `json:"id"`
}

ProjectGetRequestPath contains the path parameters for loading a single project.

type ProjectGetResponse added in v0.0.6

type ProjectGetResponse struct {
	Project Project `json:"project"`
}

ProjectGetResponse contains all the information related to a project.

https://apidocs.teamwork.com/docs/teamwork/v3/projects/get-projects-api-v3-projects-project-id-json

func ProjectGet added in v0.0.6

func ProjectGet(
	ctx context.Context,
	engine *twapi.Engine,
	req ProjectGetRequest,
) (*ProjectGetResponse, error)

ProjectGet retrieves a single project using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startProjectServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	projectResponse, err := projects.ProjectGet(ctx, engine, projects.NewProjectGetRequest(12345))
	if err != nil {
		fmt.Printf("failed to retrieve project: %s", err)
	} else {
		fmt.Printf("retrieved project with identifier %d\n", projectResponse.Project.ID)
	}

}

func startProjectServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK","id":"12345"}`)
	})
	mux.HandleFunc("PUT /projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("DELETE /projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("GET /projects/api/v3/projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"project":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/projects", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"projects":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

retrieved project with identifier 12345

func (*ProjectGetResponse) HandleHTTPResponse added in v0.0.6

func (p *ProjectGetResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the ProjectGetResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type ProjectListRequest added in v0.0.6

type ProjectListRequest struct {
	// Filters contains the filters for loading multiple projects.
	Filters ProjectListRequestFilters
}

ProjectListRequest represents the request body for loading multiple projects.

https://apidocs.teamwork.com/docs/teamwork/v3/projects/get-projects-api-v3-projects-json

func NewProjectListRequest added in v0.0.6

func NewProjectListRequest() ProjectListRequest

NewProjectListRequest creates a new ProjectListRequest with default values.

func (ProjectListRequest) HTTPRequest added in v0.0.6

func (p ProjectListRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the ProjectListRequest.

type ProjectListRequestFilters added in v0.0.6

type ProjectListRequestFilters struct {
	// SearchTerm is an optional search term to filter projects by name or
	// description.
	SearchTerm string

	// TagIDs is an optional list of tag IDs to filter projects by tags.
	TagIDs []int64

	// MatchAllTags is an optional flag to indicate if all tags must match. If
	// set to true, only projects matching all specified tags will be returned.
	MatchAllTags *bool

	// Page is the page number to retrieve. Defaults to 1.
	Page int64

	// PageSize is the number of projects to retrieve per page. Defaults to 50.
	PageSize int64
}

ProjectListRequestFilters contains the filters for loading multiple projects.

type ProjectListResponse added in v0.0.6

type ProjectListResponse struct {
	Meta struct {
		Page struct {
			HasMore bool `json:"hasMore"`
		} `json:"page"`
	} `json:"meta"`
	Projects []Project `json:"projects"`
	// contains filtered or unexported fields
}

ProjectListResponse contains information by multiple projects matching the request filters.

https://apidocs.teamwork.com/docs/teamwork/v3/projects/get-projects-api-v3-projects-json

func ProjectList added in v0.0.6

func ProjectList(
	ctx context.Context,
	engine *twapi.Engine,
	req ProjectListRequest,
) (*ProjectListResponse, error)

ProjectList retrieves multiple projects using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startProjectServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	projectsResponse, err := projects.ProjectList(ctx, engine, projects.ProjectListRequest{
		Filters: projects.ProjectListRequestFilters{
			SearchTerm: "Example",
		},
	})
	if err != nil {
		fmt.Printf("failed to list projects: %s", err)
	} else {
		for _, project := range projectsResponse.Projects {
			fmt.Printf("retrieved project with identifier %d\n", project.ID)
		}
	}

}

func startProjectServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK","id":"12345"}`)
	})
	mux.HandleFunc("PUT /projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("DELETE /projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("GET /projects/api/v3/projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"project":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/projects", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"projects":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

retrieved project with identifier 12345
retrieved project with identifier 12346

func (*ProjectListResponse) HandleHTTPResponse added in v0.0.6

func (p *ProjectListResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the ProjectListResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

func (*ProjectListResponse) Iterate added in v0.0.7

Iterate returns the request set to the next page, if available. If there are no more pages, a nil request is returned.

func (*ProjectListResponse) SetRequest added in v0.0.7

func (p *ProjectListResponse) SetRequest(req ProjectListRequest)

SetRequest sets the request used to load this response. This is used for pagination purposes, so the Iterate method can return the next page.

type ProjectUpdateRequest added in v0.0.3

type ProjectUpdateRequest struct {
	// Path contains the path parameters for the request.
	Path ProjectUpdateRequestPath

	// Name is the name of the project.
	Name *string `json:"name,omitempty"`

	// Description is the project description.
	Description *string `json:"description,omitempty"`

	// StartAt is the start date for the project.
	StartAt *LegacyDate `json:"start-date,omitempty"`

	// EndAt is the end date for the project.
	EndAt *LegacyDate `json:"end-date,omitempty"`

	// CompanyID is the company/client associated with the project.
	CompanyID *int64 `json:"companyId,omitempty"`

	// OwnerID is the ID of the user who owns the project.
	OwnerID *int64 `json:"projectOwnerId,omitempty"`

	// TagIDs is the list of tag IDs associated with the project.
	TagIDs []int64 `json:"tagIds,omitempty"`
}

ProjectUpdateRequest represents the request body for updating a project. Besides the identifier, all other fields are optional. When a field is not provided, it will not be modified.

https://apidocs.teamwork.com/docs/teamwork/v1/projects/put-projects-id-json

func NewProjectUpdateRequest added in v0.0.6

func NewProjectUpdateRequest(projectID int64) ProjectUpdateRequest

NewProjectUpdateRequest creates a new ProjectUpdateRequest with the provided project ID. The ID is required to update a project.

func (ProjectUpdateRequest) HTTPRequest added in v0.0.3

func (p ProjectUpdateRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the ProjectUpdateRequest.

type ProjectUpdateRequestPath added in v0.0.6

type ProjectUpdateRequestPath struct {
	// ID is the unique identifier of the project to be updated.
	ID int64
}

ProjectUpdateRequestPath contains the path parameters for updating a project.

type ProjectUpdateResponse added in v0.0.3

type ProjectUpdateResponse struct{}

ProjectUpdateResponse represents the response body for updating a project.

https://apidocs.teamwork.com/docs/teamwork/v1/projects/put-projects-id-json

func ProjectUpdate added in v0.0.3

func ProjectUpdate(
	ctx context.Context,
	engine *twapi.Engine,
	req ProjectUpdateRequest,
) (*ProjectUpdateResponse, error)

ProjectUpdate creates a new project using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startProjectServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	_, err = projects.ProjectUpdate(ctx, engine, projects.ProjectUpdateRequest{
		Path: projects.ProjectUpdateRequestPath{
			ID: 12345,
		},
		Description: twapi.Ptr("This is an updated description."),
	})
	if err != nil {
		fmt.Printf("failed to update project: %s", err)
	} else {
		fmt.Println("project updated!")
	}

}

func startProjectServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK","id":"12345"}`)
	})
	mux.HandleFunc("PUT /projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("DELETE /projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("GET /projects/api/v3/projects/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"project":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/projects", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"projects":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

project updated!

func (*ProjectUpdateResponse) HandleHTTPResponse added in v0.0.3

func (p *ProjectUpdateResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the ProjectUpdateResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type Task added in v0.2.0

type Task struct {
	// ID is the unique identifier of the task.
	ID int64 `json:"id"`

	// Name is the name of the task.
	Name string `json:"name"`

	// Description is the description of the task.
	Description *string `json:"description"`

	// DescriptionContentType is the content type of the description. It can be
	// "TEXT" or "HTML".
	DescriptionContentType *string `json:"descriptionContentType"`

	// Priority is the priority of the task. It can be "none", "low", "medium" or
	// "high".
	Priority *string `json:"priority"`

	// Progress is the progress of the task, in percentage (0-100).
	Progress int64 `json:"progress"`

	// StartAt is the date and time when the task is scheduled to start.
	StartAt *time.Time `json:"startDate"`

	// DueAt is the date and time when the task is scheduled to be completed.
	DueAt *time.Time `json:"dueDate"`

	// EstimatedMinutes is the estimated time to complete the task, in minutes.
	EstimatedMinutes int64 `json:"estimateMinutes"`

	// Tasklist is the relationship to the tasklist containing this task.
	Tasklist twapi.Relationship `json:"tasklist"`

	// Assignees is the list of users, teams or clients/companies assigned to this
	// task.
	Assignees []twapi.Relationship `json:"assignees"`

	// Tags is the list of tags associated with this task.
	Tags []twapi.Relationship `json:"tags"`

	// CreatedBy is the ID of the user who created the task.
	CreatedBy *int64 `json:"createdBy"`

	// CreatedAt is the date and time when the task was created.
	CreatedAt *time.Time `json:"createdAt"`

	// UpdatedBy is the ID of the user who last updated the task.
	UpdatedBy *int64 `json:"updatedBy"`

	// UpdatedAt is the date and time when the task was last updated.
	UpdatedAt time.Time `json:"updatedAt"`

	// DeletedBy is the ID of the user who deleted the task, if it was deleted.
	DeletedBy *int64 `json:"deletedBy"`

	// DeletedAt is the date and time when the task was deleted, if it was
	// deleted.
	DeletedAt *time.Time `json:"deletedAt"`

	// CompletedBy is the ID of the user who completed the task, if it was
	// completed.
	CompletedBy *int64 `json:"completedBy,omitempty"`

	// CompletedAt is the date and time when the task was completed, if it was
	// completed.
	CompletedAt *time.Time `json:"completedAt,omitempty"`

	// Status is the status of the task. It can be "new", "reopened", "completed"
	// or "deleted".
	Status string `json:"status"`
}

Task represents a task in Teamwork.

type TaskCreateRequest added in v0.2.0

type TaskCreateRequest struct {
	// Path contains the path parameters for the request.
	Path TaskCreateRequestPath `json:"-"`

	// Name is the name of the task
	Name string `json:"name"`

	// Description is an optional description of the task.
	Description *string `json:"description,omitempty"`

	// Priority is the priority of the task. It can be "none", "low", "medium" or
	// "high".
	Priority *string `json:"priority,omitempty"`

	// Progress is the progress of the task, in percentage (0-100).
	Progress *int64 `json:"progress,omitempty"`

	// StartAt is the date and time when the task is scheduled to start.
	StartAt *twapi.Date `json:"startAt,omitempty"`

	// DueAt is the date and time when the task is scheduled to be completed.
	DueAt *twapi.Date `json:"dueAt,omitempty"`

	// EstimatedMinutes is the estimated time to complete the task, in minutes.
	EstimatedMinutes *int64 `json:"estimatedMinutes,omitempty"`

	// Assignees is the list of users, teams or clients/companies assigned to this
	// task.
	Assignees *UserGroups `json:"assignees,omitempty"`

	// TagIDs is the list of tag IDs associated with this task.
	TagIDs []int64 `json:"tagIds,omitempty"`
}

TaskCreateRequest represents the request body for creating a new task.

https://apidocs.teamwork.com/docs/teamwork/v3/tasks/post-projects-api-v3-tasklists-tasklist-id-tasks-json

func NewTaskCreateRequest added in v0.2.0

func NewTaskCreateRequest(tasklistID int64, name string) TaskCreateRequest

NewTaskCreateRequest creates a new TaskCreateRequest with the provided name in a specific tasklist.

func (TaskCreateRequest) HTTPRequest added in v0.2.0

func (t TaskCreateRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the TaskCreateRequest.

type TaskCreateRequestPath added in v0.2.0

type TaskCreateRequestPath struct {
	// TasklistID is the unique identifier of the tasklist that will contain the
	// task.
	TasklistID int64
}

TaskUpdateRequestPath contains the path parameters for creating a task.

type TaskCreateResponse added in v0.2.0

type TaskCreateResponse struct {
	// Task is the created task.
	Task Task `json:"task"`
}

TaskCreateResponse represents the response body for creating a new task.

https://apidocs.teamwork.com/docs/teamwork/v3/tasks/post-projects-api-v3-tasklists-tasklist-id-tasks-json

func TaskCreate added in v0.2.0

func TaskCreate(
	ctx context.Context,
	engine *twapi.Engine,
	req TaskCreateRequest,
) (*TaskCreateResponse, error)

TaskCreate creates a new task using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startTaskServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	task, err := projects.TaskCreate(ctx, engine, projects.TaskCreateRequest{
		Path: projects.TaskCreateRequestPath{
			TasklistID: 777,
		},
		Name:        "New Task",
		Description: twapi.Ptr("This is a new task created via the API."),
	})
	if err != nil {
		fmt.Printf("failed to create task: %s", err)
	} else {
		fmt.Printf("created task with identifier %d\n", task.Task.ID)
	}

}

func startTaskServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects/api/v3/tasklists/{id}/tasks", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "777" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("PUT /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("DELETE /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"affected":{"taskIds":[12345]}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasks", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasks":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

created task with identifier 12345

func (*TaskCreateResponse) HandleHTTPResponse added in v0.2.0

func (t *TaskCreateResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the TaskCreateResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type TaskDeleteRequest added in v0.2.0

type TaskDeleteRequest struct {
	// Path contains the path parameters for the request.
	Path TaskDeleteRequestPath
}

TaskDeleteRequest represents the request body for deleting a task.

https://apidocs.teamwork.com/docs/teamwork/v3/tasks/delete-projects-api-v3-tasks-task-id-json

func NewTaskDeleteRequest added in v0.2.0

func NewTaskDeleteRequest(taskID int64) TaskDeleteRequest

NewTaskDeleteRequest creates a new TaskDeleteRequest with the provided task ID.

func (TaskDeleteRequest) HTTPRequest added in v0.2.0

func (t TaskDeleteRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the TaskDeleteRequest.

type TaskDeleteRequestPath added in v0.2.0

type TaskDeleteRequestPath struct {
	// ID is the unique identifier of the task to be deleted.
	ID int64
}

TaskDeleteRequestPath contains the path parameters for deleting a task.

type TaskDeleteResponse added in v0.2.0

type TaskDeleteResponse struct{}

TaskDeleteResponse represents the response body for deleting a task.

https://apidocs.teamwork.com/docs/teamwork/v3/tasks/delete-projects-api-v3-tasks-task-id-json

func TaskDelete added in v0.2.0

func TaskDelete(
	ctx context.Context,
	engine *twapi.Engine,
	req TaskDeleteRequest,
) (*TaskDeleteResponse, error)

TaskDelete creates a new task using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startTaskServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	_, err = projects.TaskDelete(ctx, engine, projects.NewTaskDeleteRequest(12345))
	if err != nil {
		fmt.Printf("failed to delete task: %s", err)
	} else {
		fmt.Println("task deleted!")
	}

}

func startTaskServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects/api/v3/tasklists/{id}/tasks", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "777" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("PUT /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("DELETE /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"affected":{"taskIds":[12345]}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasks", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasks":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

task deleted!

func (*TaskDeleteResponse) HandleHTTPResponse added in v0.2.0

func (t *TaskDeleteResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the TaskDeleteResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type TaskGetRequest added in v0.2.0

type TaskGetRequest struct {
	// Path contains the path parameters for the request.
	Path TaskGetRequestPath
}

TaskGetRequest represents the request body for loading a single task.

https://apidocs.teamwork.com/docs/teamwork/v3/tasks/get-projects-api-v3-tasks-task-id-json

func NewTaskGetRequest added in v0.2.0

func NewTaskGetRequest(taskID int64) TaskGetRequest

NewTaskGetRequest creates a new TaskGetRequest with the provided task ID. The ID is required to load a task.

func (TaskGetRequest) HTTPRequest added in v0.2.0

func (t TaskGetRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the TaskGetRequest.

type TaskGetRequestPath added in v0.2.0

type TaskGetRequestPath struct {
	// ID is the unique identifier of the task to be retrieved.
	ID int64 `json:"id"`
}

TaskGetRequestPath contains the path parameters for loading a single task.

type TaskGetResponse added in v0.2.0

type TaskGetResponse struct {
	Task Task `json:"task"`
}

TaskGetResponse contains all the information related to a task.

https://apidocs.teamwork.com/docs/teamwork/v3/tasks/get-projects-api-v3-tasks-task-id-json

func TaskGet added in v0.2.0

func TaskGet(
	ctx context.Context,
	engine *twapi.Engine,
	req TaskGetRequest,
) (*TaskGetResponse, error)

TaskGet retrieves a single task using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startTaskServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	taskResponse, err := projects.TaskGet(ctx, engine, projects.NewTaskGetRequest(12345))
	if err != nil {
		fmt.Printf("failed to retrieve task: %s", err)
	} else {
		fmt.Printf("retrieved task with identifier %d\n", taskResponse.Task.ID)
	}

}

func startTaskServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects/api/v3/tasklists/{id}/tasks", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "777" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("PUT /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("DELETE /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"affected":{"taskIds":[12345]}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasks", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasks":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

retrieved task with identifier 12345

func (*TaskGetResponse) HandleHTTPResponse added in v0.2.0

func (t *TaskGetResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the TaskGetResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type TaskListRequest added in v0.2.0

type TaskListRequest struct {
	// Path contains the path parameters for the request.
	Path TaskListRequestPath

	// Filters contains the filters for loading multiple tasks.
	Filters TaskListRequestFilters
}

TaskListRequest represents the request body for loading multiple tasks.

https://apidocs.teamwork.com/docs/teamwork/v3/tasks/get-projects-api-v3-tasks-json https://apidocs.teamwork.com/docs/teamwork/v3/tasks/get-projects-api-v3-projects-project-id-tasks-json https://apidocs.teamwork.com/docs/teamwork/v3/tasks/get-projects-api-v3-tasklists-tasklist-id-tasks-json

func NewTaskListRequest added in v0.2.0

func NewTaskListRequest() TaskListRequest

NewTaskListRequest creates a new TaskListRequest with default values.

func (TaskListRequest) HTTPRequest added in v0.2.0

func (t TaskListRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the TaskListRequest.

type TaskListRequestFilters added in v0.2.0

type TaskListRequestFilters struct {
	// SearchTerm is an optional search term to filter tasks by name, description
	// or tasklist's name.
	SearchTerm string

	// TagIDs is an optional list of tag IDs to filter tasks by tags.
	TagIDs []int64

	// MatchAllTags is an optional flag to indicate if all tags must match. If set
	// to true, only tasks matching all specified tags will be returned.
	MatchAllTags *bool

	// Page is the page number to retrieve. Defaults to 1.
	Page int64

	// PageSize is the number of tasks to retrieve per page. Defaults to 50.
	PageSize int64
}

TaskListRequestFilters contains the filters for loading multiple tasks.

type TaskListRequestPath added in v0.2.0

type TaskListRequestPath struct {
	// ProjectID is the unique identifier of the project whose tasks are to be
	// retrieved.
	ProjectID int64
	// TasklistID is the unique identifier of the tasklist whose tasks are to be
	// retrieved. If provided, the ProjectID is ignored.
	TasklistID int64
}

TaskListRequestPath contains the path parameters for loading multiple tasks.

type TaskListResponse added in v0.2.0

type TaskListResponse struct {
	Meta struct {
		Page struct {
			HasMore bool `json:"hasMore"`
		} `json:"page"`
	} `json:"meta"`
	Tasks []Task `json:"tasks"`
	// contains filtered or unexported fields
}

TaskListResponse contains information by multiple tasks matching the request filters.

https://apidocs.teamwork.com/docs/teamwork/v3/tasks/get-projects-api-v3-tasks-json https://apidocs.teamwork.com/docs/teamwork/v3/tasks/get-projects-api-v3-projects-project-id-tasks-json https://apidocs.teamwork.com/docs/teamwork/v3/tasks/get-projects-api-v3-tasklists-tasklist-id-tasks-json

func TaskList added in v0.2.0

func TaskList(
	ctx context.Context,
	engine *twapi.Engine,
	req TaskListRequest,
) (*TaskListResponse, error)

TaskList retrieves multiple tasks using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startTaskServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	tasksResponse, err := projects.TaskList(ctx, engine, projects.TaskListRequest{
		Filters: projects.TaskListRequestFilters{
			SearchTerm: "Example",
		},
	})
	if err != nil {
		fmt.Printf("failed to list tasks: %s", err)
	} else {
		for _, task := range tasksResponse.Tasks {
			fmt.Printf("retrieved task with identifier %d\n", task.ID)
		}
	}

}

func startTaskServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects/api/v3/tasklists/{id}/tasks", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "777" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("PUT /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("DELETE /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"affected":{"taskIds":[12345]}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasks", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasks":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

retrieved task with identifier 12345
retrieved task with identifier 12346

func (*TaskListResponse) HandleHTTPResponse added in v0.2.0

func (t *TaskListResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the TaskListResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

func (*TaskListResponse) Iterate added in v0.2.0

func (t *TaskListResponse) Iterate() *TaskListRequest

Iterate returns the request set to the next page, if available. If there are no more pages, a nil request is returned.

func (*TaskListResponse) SetRequest added in v0.2.0

func (t *TaskListResponse) SetRequest(req TaskListRequest)

SetRequest sets the request used to load this response. This is used for pagination purposes, so the Iterate method can return the next page.

type TaskUpdateRequest added in v0.2.0

type TaskUpdateRequest struct {
	// Path contains the path parameters for the request.
	Path TaskUpdateRequestPath `json:"-"`

	// Name is the name of the task
	Name *string `json:"name,omitempty"`

	// Description is an optional description of the task.
	Description *string `json:"description,omitempty"`

	// Priority is the priority of the task. It can be "none", "low", "medium" or
	// "high".
	Priority *string `json:"priority,omitempty"`

	// Progress is the progress of the task, in percentage (0-100).
	Progress *int64 `json:"progress,omitempty"`

	// StartAt is the date and time when the task is scheduled to start.
	StartAt *twapi.Date `json:"startAt,omitempty"`

	// DueAt is the date and time when the task is scheduled to be completed.
	DueAt *twapi.Date `json:"dueAt,omitempty"`

	// EstimatedMinutes is the estimated time to complete the task, in minutes.
	EstimatedMinutes *int64 `json:"estimatedMinutes,omitempty"`

	// TasklistID is the identifier of the tasklist that will contain the task. If
	// provided, the task will be moved to this tasklist.
	TasklistID *int64 `json:"tasklistId,omitempty"`

	// Assignees is the list of users, teams or clients/companies assigned to this
	// task.
	Assignees *UserGroups `json:"assignees,omitempty"`

	// TagIDs is the list of tag IDs associated with this task.
	TagIDs []int64 `json:"tagIds,omitempty"`
}

TaskUpdateRequest represents the request body for updating a task. Besides the identifier, all other fields are optional. When a field is not provided, it will not be modified.

https://apidocs.teamwork.com/docs/teamwork/v3/tasks/patch-projects-api-v3-tasks-task-id-json

func NewTaskUpdateRequest added in v0.2.0

func NewTaskUpdateRequest(taskID int64) TaskUpdateRequest

NewTaskUpdateRequest creates a new TaskUpdateRequest with the provided task ID. The ID is required to update a task.

func (TaskUpdateRequest) HTTPRequest added in v0.2.0

func (t TaskUpdateRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the TaskUpdateRequest.

type TaskUpdateRequestPath added in v0.2.0

type TaskUpdateRequestPath struct {
	// ID is the unique identifier of the task to be updated.
	ID int64
}

TaskUpdateRequestPath contains the path parameters for updating a task.

type TaskUpdateResponse added in v0.2.0

type TaskUpdateResponse struct {
	// Task is the updated task.
	Task Task `json:"task"`
}

TaskUpdateResponse represents the response body for updating a task.

https://apidocs.teamwork.com/docs/teamwork/v3/tasks/patch-projects-api-v3-tasks-task-id-json

func TaskUpdate added in v0.2.0

func TaskUpdate(
	ctx context.Context,
	engine *twapi.Engine,
	req TaskUpdateRequest,
) (*TaskUpdateResponse, error)

TaskUpdate creates a new task using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startTaskServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	_, err = projects.TaskUpdate(ctx, engine, projects.TaskUpdateRequest{
		Path: projects.TaskUpdateRequestPath{
			ID: 12345,
		},
		Description: twapi.Ptr("This is an updated description."),
	})
	if err != nil {
		fmt.Printf("failed to update task: %s", err)
	} else {
		fmt.Println("task updated!")
	}

}

func startTaskServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects/api/v3/tasklists/{id}/tasks", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "777" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("PUT /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("DELETE /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"affected":{"taskIds":[12345]}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"task":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasks", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasks":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

task updated!

func (*TaskUpdateResponse) HandleHTTPResponse added in v0.2.0

func (t *TaskUpdateResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the TaskUpdateResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type Tasklist added in v0.1.0

type Tasklist struct {
	// ID is the unique identifier of the tasklist.
	ID int64 `json:"id"`

	// Name is the name of the tasklist.
	Name string `json:"name"`

	// Description is the description of the tasklist.
	Description string `json:"description"`

	// Project is the project associated with the tasklist.
	Project twapi.Relationship `json:"project"`

	// Milestone is the milestone associated with the tasklist.
	Milestone *twapi.Relationship `json:"milestone"`

	// CreatedAt is the date and time when the tasklist was created.
	CreatedAt *time.Time `json:"createdAt"`

	// UpdatedAt is the date and time when the tasklist was last updated.
	UpdatedAt *time.Time `json:"updatedAt"`

	// Status is the status of the tasklist. It can be "new", "reopened",
	// "completed" or "deleted".
	Status string `json:"status"`
}

Tasklist represents a tasklist in Teamwork.

type TasklistCreateRequest added in v0.1.0

type TasklistCreateRequest struct {
	// Path contains the path parameters for the request.
	Path TasklistCreateRequestPath `json:"-"`

	// Name is the name of the tasklist
	Name string `json:"name"`

	// Description is an optional description of the tasklist.
	Description *string `json:"description,omitempty"`

	// MilestoneID is an optional ID of the milestone associated with the
	// tasklist.
	MilestoneID *int64 `json:"milestone-Id,omitempty"`
}

TasklistCreateRequest represents the request body for creating a new tasklist.

https://apidocs.teamwork.com/docs/teamwork/v1/task-lists/post-projects-id-tasklists-json

func NewTasklistCreateRequest added in v0.1.0

func NewTasklistCreateRequest(projectID int64, name string) TasklistCreateRequest

NewTasklistCreateRequest creates a new TasklistCreateRequest with the provided name in a specific project.

func (TasklistCreateRequest) HTTPRequest added in v0.1.0

func (t TasklistCreateRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the TasklistCreateRequest.

type TasklistCreateRequestPath added in v0.1.0

type TasklistCreateRequestPath struct {
	// ProjectID is the unique identifier of the project that will contain the
	// tasklist.
	ProjectID int64
}

TasklistUpdateRequestPath contains the path parameters for creating a tasklist.

type TasklistCreateResponse added in v0.1.0

type TasklistCreateResponse struct {
	// ID is the unique identifier of the created tasklist.
	ID LegacyNumber `json:"tasklistId"`
}

TasklistCreateResponse represents the response body for creating a new tasklist.

https://apidocs.teamwork.com/docs/teamwork/v1/task-lists/post-projects-id-tasklists-json

func TasklistCreate added in v0.1.0

func TasklistCreate(
	ctx context.Context,
	engine *twapi.Engine,
	req TasklistCreateRequest,
) (*TasklistCreateResponse, error)

TasklistCreate creates a new tasklist using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startTasklistServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	tasklist, err := projects.TasklistCreate(ctx, engine, projects.TasklistCreateRequest{
		Path: projects.TasklistCreateRequestPath{
			ProjectID: 777,
		},
		Name:        "New Tasklist",
		Description: twapi.Ptr("This is a new tasklist created via the API."),
	})
	if err != nil {
		fmt.Printf("failed to create tasklist: %s", err)
	} else {
		fmt.Printf("created tasklist with identifier %d\n", tasklist.ID)
	}

}

func startTasklistServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects/{id}/tasklists", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "777" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK","tasklistId":"12345"}`)
	})
	mux.HandleFunc("PUT /tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("DELETE /tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasklist":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasklists", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasklists":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

created tasklist with identifier 12345

func (*TasklistCreateResponse) HandleHTTPResponse added in v0.1.0

func (t *TasklistCreateResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the TasklistCreateResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type TasklistDeleteRequest added in v0.1.0

type TasklistDeleteRequest struct {
	// Path contains the path parameters for the request.
	Path TasklistDeleteRequestPath
}

TasklistDeleteRequest represents the request body for deleting a tasklist.

https://apidocs.teamwork.com/docs/teamwork/v1/task-lists/delete-tasklists-id-json

func NewTasklistDeleteRequest added in v0.1.0

func NewTasklistDeleteRequest(tasklistID int64) TasklistDeleteRequest

NewTasklistDeleteRequest creates a new TasklistDeleteRequest with the provided tasklist ID.

func (TasklistDeleteRequest) HTTPRequest added in v0.1.0

func (t TasklistDeleteRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the TasklistDeleteRequest.

type TasklistDeleteRequestPath added in v0.1.0

type TasklistDeleteRequestPath struct {
	// ID is the unique identifier of the tasklist to be deleted.
	ID int64
}

TasklistDeleteRequestPath contains the path parameters for deleting a tasklist.

type TasklistDeleteResponse added in v0.1.0

type TasklistDeleteResponse struct{}

TasklistDeleteResponse represents the response body for deleting a tasklist.

https://apidocs.teamwork.com/docs/teamwork/v1/task-lists/delete-tasklists-id-json

func TasklistDelete added in v0.1.0

func TasklistDelete(
	ctx context.Context,
	engine *twapi.Engine,
	req TasklistDeleteRequest,
) (*TasklistDeleteResponse, error)

TasklistDelete creates a new tasklist using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startTasklistServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	_, err = projects.TasklistDelete(ctx, engine, projects.NewTasklistDeleteRequest(12345))
	if err != nil {
		fmt.Printf("failed to delete tasklist: %s", err)
	} else {
		fmt.Println("tasklist deleted!")
	}

}

func startTasklistServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects/{id}/tasklists", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "777" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK","tasklistId":"12345"}`)
	})
	mux.HandleFunc("PUT /tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("DELETE /tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasklist":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasklists", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasklists":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

tasklist deleted!

func (*TasklistDeleteResponse) HandleHTTPResponse added in v0.1.0

func (t *TasklistDeleteResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the TasklistDeleteResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type TasklistGetRequest added in v0.1.0

type TasklistGetRequest struct {
	// Path contains the path parameters for the request.
	Path TasklistGetRequestPath
}

TasklistGetRequest represents the request body for loading a single tasklist.

https://apidocs.teamwork.com/docs/teamwork/v3/task-lists/get-projects-api-v3-tasklists-tasklist-id

func NewTasklistGetRequest added in v0.1.0

func NewTasklistGetRequest(tasklistID int64) TasklistGetRequest

NewTasklistGetRequest creates a new TasklistGetRequest with the provided tasklist ID. The ID is required to load a tasklist.

func (TasklistGetRequest) HTTPRequest added in v0.1.0

func (t TasklistGetRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the TasklistGetRequest.

type TasklistGetRequestPath added in v0.1.0

type TasklistGetRequestPath struct {
	// ID is the unique identifier of the tasklist to be retrieved.
	ID int64 `json:"id"`
}

TasklistGetRequestPath contains the path parameters for loading a single tasklist.

type TasklistGetResponse added in v0.1.0

type TasklistGetResponse struct {
	Tasklist Tasklist `json:"tasklist"`
}

TasklistGetResponse contains all the information related to a tasklist.

https://apidocs.teamwork.com/docs/teamwork/v3/task-lists/get-projects-api-v3-tasklists-tasklist-id

func TasklistGet added in v0.1.0

func TasklistGet(
	ctx context.Context,
	engine *twapi.Engine,
	req TasklistGetRequest,
) (*TasklistGetResponse, error)

TasklistGet retrieves a single tasklist using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startTasklistServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	tasklistResponse, err := projects.TasklistGet(ctx, engine, projects.NewTasklistGetRequest(12345))
	if err != nil {
		fmt.Printf("failed to retrieve tasklist: %s", err)
	} else {
		fmt.Printf("retrieved tasklist with identifier %d\n", tasklistResponse.Tasklist.ID)
	}

}

func startTasklistServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects/{id}/tasklists", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "777" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK","tasklistId":"12345"}`)
	})
	mux.HandleFunc("PUT /tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("DELETE /tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasklist":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasklists", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasklists":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

retrieved tasklist with identifier 12345

func (*TasklistGetResponse) HandleHTTPResponse added in v0.1.0

func (t *TasklistGetResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the TasklistGetResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type TasklistListRequest added in v0.1.0

type TasklistListRequest struct {
	// Path contains the path parameters for the request.
	Path TasklistListRequestPath

	// Filters contains the filters for loading multiple tasklists.
	Filters TasklistListRequestFilters
}

TasklistListRequest represents the request body for loading multiple tasklists.

https://apidocs.teamwork.com/docs/teamwork/v3/task-lists/get-projects-api-v3-tasklists https://apidocs.teamwork.com/docs/teamwork/v3/task-lists/get-projects-api-v3-projects-project-id-tasklists

func NewTasklistListRequest added in v0.1.0

func NewTasklistListRequest() TasklistListRequest

NewTasklistListRequest creates a new TasklistListRequest with default values.

func (TasklistListRequest) HTTPRequest added in v0.1.0

func (t TasklistListRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the TasklistListRequest.

type TasklistListRequestFilters added in v0.1.0

type TasklistListRequestFilters struct {
	// SearchTerm is an optional search term to filter tasklists by name.
	SearchTerm string

	// Page is the page number to retrieve. Defaults to 1.
	Page int64

	// PageSize is the number of tasklists to retrieve per page. Defaults to 50.
	PageSize int64
}

TasklistListRequestFilters contains the filters for loading multiple tasklists.

type TasklistListRequestPath added in v0.1.0

type TasklistListRequestPath struct {
	// ProjectID is the unique identifier of the project whose tasklists are to be
	// retrieved.
	ProjectID int64
}

TasklistListRequestPath contains the path parameters for loading multiple tasklists.

type TasklistListResponse added in v0.1.0

type TasklistListResponse struct {
	Meta struct {
		Page struct {
			HasMore bool `json:"hasMore"`
		} `json:"page"`
	} `json:"meta"`
	Tasklists []Tasklist `json:"tasklists"`
	// contains filtered or unexported fields
}

TasklistListResponse contains information by multiple tasklists matching the request filters.

https://apidocs.teamwork.com/docs/teamwork/v3/task-lists/get-projects-api-v3-tasklists https://apidocs.teamwork.com/docs/teamwork/v3/task-lists/get-projects-api-v3-projects-project-id-tasklists

func TasklistList added in v0.1.0

func TasklistList(
	ctx context.Context,
	engine *twapi.Engine,
	req TasklistListRequest,
) (*TasklistListResponse, error)

TasklistList retrieves multiple tasklists using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startTasklistServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	tasklistsResponse, err := projects.TasklistList(ctx, engine, projects.TasklistListRequest{
		Filters: projects.TasklistListRequestFilters{
			SearchTerm: "Example",
		},
	})
	if err != nil {
		fmt.Printf("failed to list tasklists: %s", err)
	} else {
		for _, tasklist := range tasklistsResponse.Tasklists {
			fmt.Printf("retrieved tasklist with identifier %d\n", tasklist.ID)
		}
	}

}

func startTasklistServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects/{id}/tasklists", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "777" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK","tasklistId":"12345"}`)
	})
	mux.HandleFunc("PUT /tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("DELETE /tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasklist":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasklists", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasklists":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

retrieved tasklist with identifier 12345
retrieved tasklist with identifier 12346

func (*TasklistListResponse) HandleHTTPResponse added in v0.1.0

func (t *TasklistListResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the TasklistListResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

func (*TasklistListResponse) Iterate added in v0.1.0

Iterate returns the request set to the next page, if available. If there are no more pages, a nil request is returned.

func (*TasklistListResponse) SetRequest added in v0.1.0

func (t *TasklistListResponse) SetRequest(req TasklistListRequest)

SetRequest sets the request used to load this response. This is used for pagination purposes, so the Iterate method can return the next page.

type TasklistUpdateRequest added in v0.1.0

type TasklistUpdateRequest struct {
	// Path contains the path parameters for the request.
	Path TasklistUpdateRequestPath `json:"-"`

	// Name is the name of the tasklist.
	Name *string `json:"name,omitempty"`

	// Description is the tasklist description.
	Description *string `json:"description,omitempty"`

	// MilestoneID is the ID of the milestone associated with the tasklist.
	MilestoneID *int64 `json:"milestone-Id,omitempty"`
}

TasklistUpdateRequest represents the request body for updating a tasklist. Besides the identifier, all other fields are optional. When a field is not provided, it will not be modified.

https://apidocs.teamwork.com/docs/teamwork/v1/task-lists/put-tasklists-id-json

func NewTasklistUpdateRequest added in v0.1.0

func NewTasklistUpdateRequest(tasklistID int64) TasklistUpdateRequest

NewTasklistUpdateRequest creates a new TasklistUpdateRequest with the provided tasklist ID. The ID is required to update a tasklist.

func (TasklistUpdateRequest) HTTPRequest added in v0.1.0

func (t TasklistUpdateRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error)

HTTPRequest creates an HTTP request for the TasklistUpdateRequest.

type TasklistUpdateRequestPath added in v0.1.0

type TasklistUpdateRequestPath struct {
	// ID is the unique identifier of the tasklist to be updated.
	ID int64
}

TasklistUpdateRequestPath contains the path parameters for updating a tasklist.

type TasklistUpdateResponse added in v0.1.0

type TasklistUpdateResponse struct{}

TasklistUpdateResponse represents the response body for updating a tasklist.

https://apidocs.teamwork.com/docs/teamwork/v1/task-lists/put-tasklists-id-json

func TasklistUpdate added in v0.1.0

func TasklistUpdate(
	ctx context.Context,
	engine *twapi.Engine,
	req TasklistUpdateRequest,
) (*TasklistUpdateResponse, error)

TasklistUpdate creates a new tasklist using the provided request and returns the response.

Example
package main

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"strings"

	twapi "github.com/teamwork/twapi-go-sdk"
	"github.com/teamwork/twapi-go-sdk/projects"
	"github.com/teamwork/twapi-go-sdk/session"
)

func main() {
	address, stop, err := startTasklistServer() // mock server for demonstration purposes
	if err != nil {
		fmt.Printf("failed to start server: %s", err)
		return
	}
	defer stop()

	ctx := context.Background()
	engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))

	_, err = projects.TasklistUpdate(ctx, engine, projects.TasklistUpdateRequest{
		Path: projects.TasklistUpdateRequestPath{
			ID: 12345,
		},
		Description: twapi.Ptr("This is an updated description."),
	})
	if err != nil {
		fmt.Printf("failed to update tasklist: %s", err)
	} else {
		fmt.Println("tasklist updated!")
	}

}

func startTasklistServer() (string, func(), error) {
	ln, err := net.Listen("tcp", "localhost:0")
	if err != nil {
		return "", nil, fmt.Errorf("failed to start server: %w", err)
	}

	mux := http.NewServeMux()
	mux.HandleFunc("POST /projects/{id}/tasklists", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "777" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK","tasklistId":"12345"}`)
	})
	mux.HandleFunc("PUT /tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Content-Type") != "application/json" {
			http.Error(w, "Unsupported Media Type", http.StatusUnsupportedMediaType)
			return
		}
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("DELETE /tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"STATUS":"OK"}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasklists/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.PathValue("id") != "12345" {
			http.Error(w, "Not Found", http.StatusNotFound)
			return
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasklist":{"id":12345}}`)
	})
	mux.HandleFunc("GET /projects/api/v3/tasklists", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		_, _ = fmt.Fprintln(w, `{"tasklists":[{"id":12345},{"id":12346}]}`)
	})

	server := &http.Server{
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			if r.Header.Get("Authorization") != "Bearer your_token" {
				http.Error(w, "Unauthorized", http.StatusUnauthorized)
				return
			}
			r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
			mux.ServeHTTP(w, r)
		}),
	}

	stop := make(chan struct{})
	go func() {
		_ = server.Serve(ln)
	}()
	go func() {
		<-stop
		_ = server.Shutdown(context.Background())
	}()

	return ln.Addr().String(), func() {
		close(stop)
	}, nil
}
Output:

tasklist updated!

func (*TasklistUpdateResponse) HandleHTTPResponse added in v0.1.0

func (t *TasklistUpdateResponse) HandleHTTPResponse(resp *http.Response) error

HandleHTTPResponse handles the HTTP response for the TasklistUpdateResponse. If some unexpected HTTP status code is returned by the API, a twapi.HTTPError is returned.

type UserGroups added in v0.2.0

type UserGroups struct {
	UserIDs    []int64 `json:"userIds"`
	CompanyIDs []int64 `json:"companyIds"`
	TeamIDs    []int64 `json:"teamIds"`
}

UserGroups represents a collection of users, companies, and teams.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL