clickup

package
v0.0.16 Latest Latest
Warning

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

Go to latest
Published: Feb 22, 2022 License: MIT Imports: 18 Imported by: 0

README

asap-tools sync with clickup

quick start

Install asap-tools via brew

brew install gebv/tap/asap-tools
# asap-tools-cli -v
# AsapTools cli version 0.0.3 (darwin_amd64) git commit 40401abab24202e19852464d953e16e99e77125e
# Build Date: 2022-01-23T05:27:34Z
# Start Date: 2022-01-23T05:32:02Z
# https://github.com/gebv/asap-tools

or download binary files from the latest release

curl -L https://github.com/gebv/asap-tools/releases/latest/download/asap-tools_Linux_x86_64.zip > ./file.zip && \
  unzip ./file.zip
chmod +x ./asap-tools-cli
sudo mv ./asap-tools-cli /usr/local/bin/asap-tools-cli
asap-tools-cli -v
# AsapTools cli version 0.0.6 (linux_amd64) git commit 598374dedea93708f9b5fc49178b0bd7bea32d6f
# Build Date: 2022-01-23T07:58:37Z
# Start Date: 2022-01-23T08:18:30Z

# https://github.com/gebv/asap-tools

Configuring the spec file (command for example yaml file asap-tools-cli clickup -debug-example-spec).

mirror_task_rules:
- name: <NameRule>
  # conds for adding new tasks from the team with the original tasks
  cond_add:
    # list folders of interest
    if_in_folders: []
    # list lists of interest
    if_in_lists:
    - https://app.clickup.com/<TeamID>/v/li/<ListID>
    # only the specified task statuses or all tasks
    eq_any_task_status_names: []
    # if assigned task to member
    if_assigned_to_member_email: ""
  # conds for track changes from the team with the original tasks
  cond_track_changes:
    if_in_folders: []
    if_in_lists:
    - https://app.clickup.com/<TeamID>/v/li/<ListID>
    eq_any_task_status_names: []
    if_assigned_to_member_email: ""
  # spec for adding new mirror tasks
  spec_add:
    # mirror tasks are added to the list
    add_to_list: https://app.clickup.com/<TeamID>/v/li/<ListID>
    set_status_name: ""
    assign_to_member_email: ""
# status association
global_mirror_task_statuses:
  # status "done" in mirror task says
  done:
    # not sync estimate and due date
    sync_estimate: false
    # orig task status will be set to "ready"
    orig_task_status: ready
  open:
    sync_estimate: true
    orig_task_status: in progress
  wip:
    sync_estimate: true
    orig_task_status: in progress

Set the necessary envs (current on 2021-01-23, show actual envs and commands via command asap-tools-cli -help)

KEY                                            TYPE             DEFAULT    REQUIRED    DESCRIPTION
ASAPTOOLS_LOG_DEV                              True or False    false
ASAPTOOLS_LOG_LEVEL                            String           WARN                   Logging level (availabel DEBUG, INFO, WARN, ERROR)
ASAPTOOLS_FIRESTORE_PRIVATE_KEY_INLINE_JSON    String                                  Inline json file with Google Cloud service account private key.
ASAPTOOLS_FIRESTORE_PROJECT_ID                 String                                  Google Cloud project ID
ASAPTOOLS_CLICKUP_API_TOKEN                    String                                  Token from ClickUp API (follow link https://app.clickup.com/settings/apps)
ASAPTOOLS_CLICKUP_FILE_SPEC_SYNC               String

Run a command to retrieve changed tasks and processing them.

asap-tools-cli clickup -recent-activity-sync

After each spec file change, run the command (to upgrade and processing to existing tasks)

asap-tools-cli clickup -db-sync

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	TaskModel   = (*Task)(nil)
	ListModel   = (*List)(nil)
	FolderModel = (*Folder)(nil)
	TeamModel   = (*Team)(nil)
	MemberModel = (*Member)(nil)
)
View Source
var ErrInvalidContent = errors.New("invalid content")
View Source
var ErrSignatureMismatch = errors.New("webhook signature mismatch")
View Source
var (
	LoadStatusOfChangedTeamTasksModel = (*LoadStatusOfChangedTeamTasks)(nil)
)
View Source
var (
	MirrorTaskModel = (*MirrorTask)(nil)
)
View Source
var NewWithID = storage.NewWithID

Functions

func MirrorTaskSyncer

func MirrorTaskSyncer(api *api.API, store *Storage) *mirrorTaskSyncer

func ModelTaskSetupLazyload added in v0.0.7

func ModelTaskSetupLazyload(ctx context.Context, store *Storage, model *Task)

Types

type ChangeManager

type ChangeManager struct {
	// contains filtered or unexported fields
}

func NewChangeManager

func NewChangeManager(api *api.API, s *Storage) *ChangeManager

func (*ChangeManager) ApplyChangesInTeam

func (s *ChangeManager) ApplyChangesInTeam(ctx context.Context, opts *SyncPreferences, teamID string)

ApplyChangesInTeam fetchs the latest changed tasks and handle. Save the date of the last changed task.

Processing details: - call to ClickUp API "give me changes tasks" - fetch and upsert related (list, folder, members) data if not exists - processing for each tasks

  • lookup for rules to add mirror tasks and add if need
  • lookup for rules to track changes for mirror tasks or for tasks that have a mirror task and process if need

func (*ChangeManager) AuthorizeTask

func (s *ChangeManager) AuthorizeTask(ctx context.Context, task *Task) (_ *Task, changed bool)

func (*ChangeManager) ForceSyncForAllTasks added in v0.0.2

func (s *ChangeManager) ForceSyncForAllTasks(ctx context.Context, opts *SyncPreferences, teamID string)

ForceSyncForAllTasks force update each task from the database and apply processing to it. Not found tasks from ClickUp API to marked as deleted.

func (*ChangeManager) Sync

func (s *ChangeManager) Sync(ctx context.Context, opts *SyncPreferences, oldTask, task *Task, changed bool)

type DocRef

type DocRef = storage.DocumentRef

type Folder

type Folder struct {
	StdStoreModel
	Name     string
	Archived bool
}

func (*Folder) CollectionName

func (t *Folder) CollectionName() string

func (*Folder) NewModel

func (*Folder) NewModel() StoreModel

type List

type List struct {
	StdStoreModel
	Name      string
	Archived  bool
	FolderRef *DocRef
	Folder    *Folder `firestore:"-"`
}

func (*List) CollectionName

func (t *List) CollectionName() string

func (*List) GetFolder

func (t *List) GetFolder(ctx context.Context) *Folder

func (*List) NewModel

func (*List) NewModel() StoreModel

type LoadStatusOfChangedTeamTasks

type LoadStatusOfChangedTeamTasks struct {
	StoreModelCustomID
	TeamID  string `firestore:"-"`
	TeamRef *DocRef
	// stores the value from the API
	LastTaskUpdatedAt int64
}

func (LoadStatusOfChangedTeamTasks) CollectionName

func (LoadStatusOfChangedTeamTasks) CollectionName() string

func (*LoadStatusOfChangedTeamTasks) ModelID

func (t *LoadStatusOfChangedTeamTasks) ModelID() string

func (*LoadStatusOfChangedTeamTasks) NewModel

func (*LoadStatusOfChangedTeamTasks) SetModelID

func (m *LoadStatusOfChangedTeamTasks) SetModelID(in string)

type Member

type Member struct {
	StdStoreModel
	Username string
	Email    string
	Initials string
}

func (*Member) CollectionName

func (t *Member) CollectionName() string

func (*Member) NewModel

func (*Member) NewModel() StoreModel

type MirrorTask

type MirrorTask struct {
	StoreModelCustomID
	TaskID, MirrorTaskID string `firestore:"-"`
	TaskRef              *DocRef
	Task                 *Task `firestore:"-"`
	MirrorTaskRef        *DocRef
	MirrorTask           *Task `firestore:"-"`

	Destroyed       bool
	DestroyedReason string
	DestroyedAt     *Timestamp
	// contains filtered or unexported fields
}

func (*MirrorTask) CollectionName

func (t *MirrorTask) CollectionName() string

func (*MirrorTask) GetMirrorTask

func (t *MirrorTask) GetMirrorTask(ctx context.Context) *Task

func (*MirrorTask) GetOrigTask added in v0.0.15

func (t *MirrorTask) GetOrigTask(ctx context.Context) *Task

func (*MirrorTask) ModelID

func (t *MirrorTask) ModelID() string

func (*MirrorTask) NewModel

func (*MirrorTask) NewModel() StoreModel

func (*MirrorTask) ParseID

func (t *MirrorTask) ParseID(in string) (taskID, mirrorTaskID string, err error)

func (*MirrorTask) SetModelID

func (t *MirrorTask) SetModelID(in string)

type MirrorTaskSpecification

type MirrorTaskSpecification struct {
	Name string `yaml:"name"`

	CondAdd          *SyncRule_CondOfAdd        `yaml:"cond_add"`
	CondTrackChanges *SyncRule_CondTrackChanges `yaml:"cond_track_changes"`
	SpecAdd          *SyncRule_SpecOfAdd        `yaml:"spec_add"`
}

func (*MirrorTaskSpecification) UsedTeamIDs

func (r *MirrorTaskSpecification) UsedTeamIDs() []string

type MirrorTaskStatus added in v0.0.15

type MirrorTaskStatus struct {
	SyncEstimateAndDueDateToOrigTask bool   `yaml:"sync_estimate"`
	SetStatusToOriginalTask          string `yaml:"orig_task_status"`
}

type MirrorTaskStatuses added in v0.0.15

type MirrorTaskStatuses map[string]MirrorTaskStatus

func (MirrorTaskStatuses) AllowedSyncEstimate added in v0.0.15

func (s MirrorTaskStatuses) AllowedSyncEstimate(mirrorTaskStatus string) bool

func (MirrorTaskStatuses) SetStatusToOrigTaskIfExists added in v0.0.15

func (s MirrorTaskStatuses) SetStatusToOrigTaskIfExists(mirrorTaskStatus string) string

returns "" if nothing needs to be done

type StdStoreModel

type StdStoreModel = storage.StdModel

type Storage

type Storage struct {
	*storage.Storage
	// contains filtered or unexported fields
}

- method Get<ModelName> - returns model by ID - method GetStateOf<ModelName> - returns status of loading of changes for the model - method Upsert<ModelName> - create or overwrite model by ID

func NewStorage

func NewStorage(s *storage.Storage) *Storage

func (*Storage) AllMatchesForMirrorTasks

func (s *Storage) AllMatchesForMirrorTasks(ctx context.Context, taskID string) (_ []*MirrorTask, _ bool)

AllMatchesForMirrorTasks returns union list mirror tasks by task ID and by mirror task ID.

func (*Storage) AllTeamTasks

func (s *Storage) AllTeamTasks(ctx context.Context, teamID string) []*Task

func (*Storage) DeleteFolder

func (s *Storage) DeleteFolder(ctx context.Context, model *Folder) error

alias to DeleteModel

func (*Storage) DeleteList

func (s *Storage) DeleteList(ctx context.Context, model *List) error

alias to DeleteModel

func (*Storage) DeleteMember

func (s *Storage) DeleteMember(ctx context.Context, model *Member) error

alias to DeleteModel

func (*Storage) DeleteTask

func (s *Storage) DeleteTask(ctx context.Context, model *Task) error

alias to DeleteModel

func (*Storage) DeleteTeam

func (s *Storage) DeleteTeam(ctx context.Context, model *Team) error

alias to DeleteModel

func (*Storage) FetchListMembers

func (s *Storage) FetchListMembers(ctx context.Context, list []*DocRef) []*Member

func (*Storage) FetchListTasks

func (s *Storage) FetchListTasks(ctx context.Context, list []*DocRef) []*Task

func (*Storage) GetFolder

func (s *Storage) GetFolder(ctx context.Context, modelID string) *Folder

a new model instance and call GetModel

func (*Storage) GetList

func (s *Storage) GetList(ctx context.Context, modelID string) *List

a new model instance and call GetModel

func (*Storage) GetMember

func (s *Storage) GetMember(ctx context.Context, modelID string) *Member

a new model instance and call GetModel

func (*Storage) GetMirrorTask

func (s *Storage) GetMirrorTask(ctx context.Context, modelID string) *MirrorTask

alias to GetModel for custom model

func (*Storage) GetStateOfLoadChangesForTeamTasks

func (s *Storage) GetStateOfLoadChangesForTeamTasks(ctx context.Context, teamID string) *LoadStatusOfChangedTeamTasks

a new model instance and call GetModel

func (*Storage) GetTask

func (s *Storage) GetTask(ctx context.Context, modelID string) *Task

a new model instance and call GetModel

func (*Storage) GetTeam

func (s *Storage) GetTeam(ctx context.Context, modelID string) *Team

a new model instance and call GetModel

func (*Storage) LoadSubTasks

func (s *Storage) LoadSubTasks(ctx context.Context, task *Task)

func (*Storage) MemberByEmail

func (s *Storage) MemberByEmail(ctx context.Context, email string) *Member

func (*Storage) ModelMirrorTaskFor

func (s *Storage) ModelMirrorTaskFor(taskID, mirrorTaskID string) *MirrorTask

ModelMirrorTaskFor returns prepared MirrorTask model with the corrects populate of the primary information. Because the user logic for preparing the storage model ID

func (*Storage) UnlinkMirroredTask

func (s *Storage) UnlinkMirroredTask(ctx context.Context, taskID, mirrorTaskID string) error

alias to DeleteModel for custom model

func (*Storage) UpsertFolder

func (s *Storage) UpsertFolder(ctx context.Context, model *Folder) error

alias to UpsertModel

func (*Storage) UpsertList

func (s *Storage) UpsertList(ctx context.Context, model *List) error

alias to UpsertModel

func (*Storage) UpsertLoadStatusOfChangedTeamTasks

func (s *Storage) UpsertLoadStatusOfChangedTeamTasks(ctx context.Context, model *LoadStatusOfChangedTeamTasks) error

alias to UpsertModel

func (*Storage) UpsertMember

func (s *Storage) UpsertMember(ctx context.Context, model *Member) error

alias to UpsertModel

func (*Storage) UpsertMirrorTask

func (s *Storage) UpsertMirrorTask(ctx context.Context, model *MirrorTask) error

alias to UpsertModel

func (*Storage) UpsertTask

func (s *Storage) UpsertTask(ctx context.Context, model *Task) error

alias to UpsertModel

func (*Storage) UpsertTeam

func (s *Storage) UpsertTeam(ctx context.Context, model *Team) error

alias to UpsertModel

type StoreModel

type StoreModel = storage.Model

type StoreModelCustomID

type StoreModelCustomID = storage.ModelCustomID

type SyncPreferences

type SyncPreferences struct {
	MirrorTaskRules []MirrorTaskSpecification `yaml:"mirror_task_rules"`
	// ASSERTS: all mirror tasks have the same status life cycle
	GlobalMirrorTaskStatuses MirrorTaskStatuses `yaml:"global_mirror_task_statuses"`
}

func ParseSyncPreferences

func ParseSyncPreferences(in io.Reader) (*SyncPreferences, error)

func (*SyncPreferences) AllUsedTeamIDs

func (s *SyncPreferences) AllUsedTeamIDs() []string

type SyncRule_CondOfAdd

type SyncRule_CondOfAdd struct {
	// Example: https://app.clickup.com/2431928/v/f/96471870/42552884
	IfInFolders []string `yaml:"if_in_folders"`
	// Example: https://app.clickup.com/2431928/v/li/174318787
	IfInLists []string `yaml:"if_in_lists"`

	EqAnyTaskStatusNames    []string `yaml:"eq_any_task_status_names"`
	IfAssignedToMemberEmail string   `yaml:"if_assigned_to_member_email"`
}

func (*SyncRule_CondOfAdd) GetIfInFolderIDs

func (s *SyncRule_CondOfAdd) GetIfInFolderIDs() []string

func (*SyncRule_CondOfAdd) GetIfInListsIDs

func (s *SyncRule_CondOfAdd) GetIfInListsIDs() []string

func (*SyncRule_CondOfAdd) PassedCheckByFolderID

func (s *SyncRule_CondOfAdd) PassedCheckByFolderID(in string) bool

func (*SyncRule_CondOfAdd) PassedCheckByListID

func (s *SyncRule_CondOfAdd) PassedCheckByListID(in string) bool

func (*SyncRule_CondOfAdd) PassedCheckByStatus

func (s *SyncRule_CondOfAdd) PassedCheckByStatus(in string) bool

type SyncRule_CondTrackChanges

type SyncRule_CondTrackChanges struct {
	// Example: https://app.clickup.com/2431928/v/f/96471870/42552884
	IfInFolders []string `yaml:"if_in_folders"`
	// Example: https://app.clickup.com/2431928/v/li/174318787
	IfInLists []string `yaml:"if_in_lists"`

	EqAnyTaskStatusNames    []string `yaml:"eq_any_task_status_names"`
	IfAssignedToMemberEmail string   `yaml:"if_assigned_to_member_email"`
}

func (*SyncRule_CondTrackChanges) GetIfInFolderIDs

func (s *SyncRule_CondTrackChanges) GetIfInFolderIDs() []string

func (*SyncRule_CondTrackChanges) GetIfInListsIDs

func (s *SyncRule_CondTrackChanges) GetIfInListsIDs() []string

func (*SyncRule_CondTrackChanges) PassedCheckByFolderID

func (s *SyncRule_CondTrackChanges) PassedCheckByFolderID(in string) bool

func (*SyncRule_CondTrackChanges) PassedCheckByListID

func (s *SyncRule_CondTrackChanges) PassedCheckByListID(in string) bool

func (*SyncRule_CondTrackChanges) PassedCheckByStatus

func (s *SyncRule_CondTrackChanges) PassedCheckByStatus(in string) bool

type SyncRule_SpecOfAdd

type SyncRule_SpecOfAdd struct {
	// synced tasks to list
	AddToList           string `yaml:"add_to_list"`
	SetStatusName       string `yaml:"set_status_name"`
	AssignToMemberEmail string `yaml:"assign_to_member_email"`
}

func (*SyncRule_SpecOfAdd) GetAddToListID

func (s *SyncRule_SpecOfAdd) GetAddToListID() string

type Task

type Task struct {
	StdStoreModel
	Name          string
	CustomID      *string
	Description   string
	TextContent   string
	StatusType    string
	StatusName    string
	DateCreatedAt *Timestamp
	DateUpdatedAt *Timestamp

	DateClosedAt     *Timestamp
	DueDateAt        *Timestamp
	StartDateAt      *Timestamp
	TimeEstimateMs   *int64
	Archived         bool
	Deleted          bool
	CreatorMemberRef *DocRef
	AssigneesRef     []*DocRef
	URL              string
	ParentTaskRef    *DocRef
	PriorityID       *int
	Tags             []string
	LinkedTasksRef   []*DocRef

	TeamRef   *DocRef
	ListRef   *DocRef
	FolderRef *DocRef

	CreatorMember *Member `firestore:"-"`
	ParentTask    *Task   `firestore:"-"`
	Team          *Team   `firestore:"-"`
	List          *List   `firestore:"-"`
	Folder        *Folder `firestore:"-"`

	// NOTE: concurrent  not safe
	Assignees []*Member `firestore:"-"`

	SubTasks []*Task `firestore:"-"`

	LinkedTasks []*Task `firestore:"-"`
	// contains filtered or unexported fields
}

func ModelTaskFromAPI added in v0.0.2

func ModelTaskFromAPI(ctx context.Context, store *Storage, taskAPI *api.Task) *Task

func (*Task) AssignedByEmail

func (t *Task) AssignedByEmail(in string) bool

func (*Task) CollectionName

func (t *Task) CollectionName() string

func (*Task) EqualUpdatedAt

func (t *Task) EqualUpdatedAt(in *Timestamp) bool

func (*Task) GetAssignees

func (t *Task) GetAssignees() []*Member

func (*Task) GetFolder

func (t *Task) GetFolder(ctx context.Context) *Folder

func (*Task) GetLinkedTasks

func (t *Task) GetLinkedTasks() []*Task

func (*Task) GetList

func (t *Task) GetList(ctx context.Context) *List

func (*Task) GetMember

func (t *Task) GetMember(ctx context.Context) *Member

func (*Task) GetParentTask

func (t *Task) GetParentTask(ctx context.Context) *Task

func (*Task) GetSubTasks

func (t *Task) GetSubTasks() []*Task

func (*Task) GetTeam

func (t *Task) GetTeam(ctx context.Context) *Team

func (*Task) IsDeletedOrHidden

func (t *Task) IsDeletedOrHidden() bool

func (*Task) MarkdownTaskID added in v0.0.15

func (t *Task) MarkdownTaskID() string

func (*Task) MirrorTaskDescription

func (t *Task) MirrorTaskDescription() string

func (*Task) MirrorTaskName

func (t *Task) MirrorTaskName(ctx context.Context) string

func (*Task) NewModel

func (*Task) NewModel() StoreModel

func (*Task) TeamID

func (t *Task) TeamID() string

func (*Task) TotalEstimate

func (t *Task) TotalEstimate() int64

type Team

type Team struct {
	StdStoreModel
	Name string
}

func (*Team) CollectionName

func (t *Team) CollectionName() string

func (*Team) NewModel

func (*Team) NewModel() StoreModel

type Timestamp

type Timestamp = storage.Timestamp

func TimestampFromTimestampWithMilliseconds

func TimestampFromTimestampWithMilliseconds(in *int64) *Timestamp

Returns Timestamp from timestamp with millesecond.

Clickup uses timestamp with milleseconds. https://clickup20.docs.apiary.io/#introduction/faq > How are dates formatted in ClickUp? ClickUp will always display dates in Unix time in milliseconds. You can use a website like Epoch Converter to convert dates between Unix and human readable date formats.

func TimestampNow added in v0.0.7

func TimestampNow() *Timestamp

type WebhookManager

type WebhookManager struct {
	// contains filtered or unexported fields
}

func (*WebhookManager) Handle

func (s *WebhookManager) Handle(w http.ResponseWriter, req *http.Request) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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