Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
88c4108
New AutoTask plugin and data streams
TimWheeler-SQUP Apr 25, 2026
b2687e6
Update folder
TimWheeler-SQUP Apr 27, 2026
878e49e
Fix paging
TimWheeler-SQUP Apr 28, 2026
dc0265b
update icon
TimWheeler-SQUP Apr 29, 2026
46bc12b
remove js file and updated status field
TimWheeler-SQUP Apr 30, 2026
eb642ce
new data stream and removes .js ref
TimWheeler-SQUP Apr 30, 2026
15f856f
New AutoTask plugin and data streams
TimWheeler-SQUP Apr 25, 2026
9722709
Update folder
TimWheeler-SQUP Apr 27, 2026
a9f1a7b
Fix paging
TimWheeler-SQUP Apr 28, 2026
7f86a27
update icon
TimWheeler-SQUP Apr 29, 2026
0fa1dd4
remove js file and updated status field
TimWheeler-SQUP Apr 30, 2026
cae7a44
new data stream and removes .js ref
TimWheeler-SQUP Apr 30, 2026
01c069d
Merge branch 'work/tw/AutoTask' of https://github.com/squaredup/plugi…
TimWheeler-SQUP May 1, 2026
aa930bc
update tags and timeframes
TimWheeler-SQUP May 2, 2026
c20b366
Add OOB dashboard
TimWheeler-SQUP May 3, 2026
e4b0b44
Fix survey results and update contractStatus data streams
TimWheeler-SQUP May 4, 2026
ca0bc31
Improve column mappings and status values. Fix OOB dashboard
TimWheeler-SQUP May 5, 2026
9c26e59
updated plugin type and fixed contractStatus
TimWheeler-SQUP May 6, 2026
4b7ece8
updated terminology and added object and parameter step to Tickets
TimWheeler-SQUP May 9, 2026
0325310
fix OOB dashboards and reduce API calls for high number of objects
TimWheeler-SQUP May 9, 2026
ce3ec2a
Fix oob dashboard
TimWheeler-SQUP May 9, 2026
b73c422
Apply review feedback and remove non-plugin files from PR
TimWheeler-SQUP May 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/.github/* @squaredup/community-moderators

# Request review from original author
plugins/AutoTask/* @TimWheeler-SQUP
plugins/DattoRMM/* @TimWheeler-SQUP
plugins/DigiCert/* @shaswot77
plugins/FantasyPremierLeague/* @TimWheeler-SQUP
Expand Down
11 changes: 11 additions & 0 deletions plugins/AutoTask/v1/configValidation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"steps": [
{
"displayName": "Autotask connection",
"dataStream": { "name": "companies", "timeframe": "none" },
"success": "Successfully connected to Autotask",
"error": "Cannot connect to Autotask — check your Zone URL, Integration Code, Username and Secret",
"required": true
}
]
}
37 changes: 37 additions & 0 deletions plugins/AutoTask/v1/custom_types.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[
{
"name": "Autotask Company",
"sourceType": "autotask-company",
"icon": "building-2",
"singular": "Company",
"plural": "Companies"
},
{
"name": "AutotaskContact",
"sourceType": "autotask-contact",
"icon": "user",
"singular": "Contact",
"plural": "Contacts"
},
{
"name": "AutotaskProject",
"sourceType": "autotask-project",
"icon": "folder-kanban",
"singular": "Project",
"plural": "Projects"
},
{
"name": "AutotaskResource",
"sourceType": "autotask-resource",
"icon": "hard-hat",
"singular": "Resource",
"plural": "Resources"
},
{
"name": "AutotaskContract",
"sourceType": "autotask-contract",
"icon": "file-text",
"singular": "Contract",
"plural": "Contracts"
}
]
36 changes: 36 additions & 0 deletions plugins/AutoTask/v1/dataStreams/companies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "companies",
"displayName": "Companies",
"description": "All active companies in AutoTask",
"tags": ["Companies"],
"baseDataSourceName": "httpRequestUnscoped",
"timeframes": false,
"config": {
"httpMethod": "get",
"expandInnerObjects": true,
"endpointPath": "atservicesrest/v1.0/Companies/query?search={\"MaxRecords\":500,\"filter\":[{\"op\":\"exist\",\"field\":\"id\"}]}",
"pathToData": "items",
"paging": {
"mode": "nextUrl",
"pageSize": { "realm": "none" },
"in": {
"realm": "payload",
"path": "pageDetails.nextPageUrl"
}
}
},
"metadata": [
{ "name": "companyName", "displayName": "Company Name" },
{ "name": "isActive", "displayName": "Is Active" },
{ "name": "phone", "displayName": "Phone" },
{ "name": "address1", "displayName": "Address" },
{ "name": "city", "displayName": "City" },
{ "name": "state", "displayName": "State" },
{ "name": "postalCode", "displayName": "Postal Code" },
{ "name": "country", "displayName": "Country" },
{ "name": "createDate", "displayName": "Created Date", "shape": ["date", { "timeZone": "Etc/UTC" }] },
{ "name": "ownerResourceID", "sourceType": "autotask-resource", "shape": "string", "visible": false },
{ "name": "ownerResourceName", "displayName": "Owner", "sourceId": "ownerResourceID", "objectPropertyPath": "name" },
{ "pattern": ".*" }
]
}
31 changes: 31 additions & 0 deletions plugins/AutoTask/v1/dataStreams/contacts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "contacts",
"displayName": "Contacts",
"baseDataSourceName": "httpRequestUnscoped",
"visibility": { "type": "hidden" },
"timeframes": false,
"config": {
"httpMethod": "get",
"expandInnerObjects": true,
"endpointPath": "atservicesrest/v1.0/Contacts/query?search={\"MaxRecords\":500,\"filter\":[{\"op\":\"exist\",\"field\":\"id\"}]}",
"pathToData": "items",
"paging": {
"mode": "nextUrl",
"pageSize": { "realm": "none" },
"in": {
"realm": "payload",
"path": "pageDetails.nextPageUrl"
}
}
},
"metadata": [
{ "name": "id", "displayName": "ID", "shape": "string" },
{
"name": "fullName",
"displayName": "Full Name",
"computed": true,
"valueExpression": "{{ $['firstName'] + ' ' + $['lastName'] }}"
},
{ "pattern": ".*" }
]
}
55 changes: 55 additions & 0 deletions plugins/AutoTask/v1/dataStreams/contractStatus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"name": "contractStatus",
"displayName": "Contract Status",
"description": "Status and key dates for contracts belonging to the selected company",
"tags": ["Contracts"],
"baseDataSourceName": "httpRequestScopedSingle",
"timeframes": false,
"matches": {
"sourceType": "autotask-company"
},
"config": {
"httpMethod": "get",
"expandInnerObjects": true,
"endpointPath": "atservicesrest/v1.0/Contracts/query?search={\"MaxRecords\":500,\"filter\":[{\"op\":\"eq\",\"field\":\"companyID\",\"value\":{{objects[0].companyId}}}]}",
"pathToData": "items",
"paging": {
"mode": "nextUrl",
"pageSize": { "realm": "none" },
"in": {
"realm": "payload",
"path": "pageDetails.nextPageUrl"
}
}
},
"metadata": [
{ "name": "sourceId", "displayName": "Object ID", "shape": "string", "visible": false },
{ "name": "id", "displayName": "ID", "sourceType": "autotask-contract", "shape": "string", "visible": false },
{ "name": "contractName", "displayName": "Contract Name" },
{ "name": "companyID", "displayName": "Company ID", "sourceType": "autotask-company", "shape": "string", "visible": false },
{ "name": "companyName", "displayName": "Company", "sourceId": "companyID", "objectPropertyPath": "name" },
{
"name": "contractTypeName",
"displayName": "Contract Type",
"computed": true,
"valueExpression": "{{ $['contractType'] == 1 ? 'Time and Materials' : $['contractType'] == 3 ? 'Fixed Price' : $['contractType'] == 4 ? 'Block Hours' : $['contractType'] == 6 ? 'Retainer' : $['contractType'] == 7 ? 'Recurring Service' : $['contractType'] == 8 ? 'Incident' : 'Unknown' }}"
},
{
"name": "statusName",
"displayName": "Status",
"computed": true,
"valueExpression": "{{ $['status'] == 1 ? 'Active' : $['status'] == 2 ? 'Upcoming' : $['status'] == 3 ? 'Cancelled' : $['status'] == 4 ? 'Completed' : $['status'] == 6 ? 'Inactive' : 'Unknown' }}",
"shape": ["state", {
"map": {
"success": ["Active", "Completed"],
"error": ["Cancelled"],
"warning": ["Upcoming"],
"unknown": ["Inactive", "Unknown"]
}
}]
},
{ "name": "startDate", "displayName": "Start Date", "shape": ["date", { "timeZone": "Etc/UTC" }] },
{ "name": "endDate", "displayName": "End Date", "shape": ["date", { "timeZone": "Etc/UTC" }] },
{ "pattern": ".*" }
]
}
21 changes: 21 additions & 0 deletions plugins/AutoTask/v1/dataStreams/contracts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "contracts",
"displayName": "Contracts",
"baseDataSourceName": "httpRequestUnscoped",
"visibility": { "type": "hidden" },
"timeframes": false,
"config": {
"httpMethod": "get",
"expandInnerObjects": true,
"endpointPath": "atservicesrest/v1.0/Contracts/query?search={\"MaxRecords\":500,\"filter\":[{\"op\":\"exist\",\"field\":\"id\"}]}",
"pathToData": "items",
"paging": {
"mode": "nextUrl",
"pageSize": { "realm": "none" },
"in": {
"realm": "payload",
"path": "pageDetails.nextPageUrl"
}
}
}
}
50 changes: 50 additions & 0 deletions plugins/AutoTask/v1/dataStreams/financialHealth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"name": "financialHealth",
"displayName": "Financial Health",
"description": "Estimated revenue, cost, and hours across all contracts",
"tags": ["Finance"],
"baseDataSourceName": "httpRequestUnscoped",
"timeframes": false,
"config": {
"httpMethod": "get",
"expandInnerObjects": true,
"endpointPath": "atservicesrest/v1.0/Contracts/query?search={\"MaxRecords\":500,\"filter\":[{\"op\":\"exist\",\"field\":\"id\"}]}",
"pathToData": "items",
"paging": {
"mode": "nextUrl",
"pageSize": { "realm": "none" },
"in": {
"realm": "payload",
"path": "pageDetails.nextPageUrl"
}
}
},
"metadata": [
{ "name": "id", "displayName": "ID", "visible": false, "shape":"string" },
{ "name": "contractName", "displayName": "Contract Name" },
{
"name": "contractTypeName",
"displayName": "Contract Type",
"computed": true,
"valueExpression": "{{ $['contractType'] == 1 ? 'Time and Materials' : $['contractType'] == 3 ? 'Fixed Price' : $['contractType'] == 4 ? 'Block Hours' : $['contractType'] == 6 ? 'Retainer' : $['contractType'] == 7 ? 'Recurring Service' : $['contractType'] == 8 ? 'Incident' : 'Unknown' }}"
},
{ "name": "estimatedRevenue", "displayName": "Estimated Revenue", "shape": ["number", { "decimalPlaces": 2 }] },
{ "name": "estimatedCost", "displayName": "Estimated Cost", "shape": ["number", { "decimalPlaces": 2 }] },
{ "name": "estimatedHours", "displayName": "Estimated Hours", "shape": ["number", { "decimalPlaces": 2 }] },
{
"name": "statusName",
"displayName": "Status",
"computed": true,
"valueExpression": "{{ $['status'] == 1 ? 'Active' : $['status'] == 2 ? 'Upcoming' : $['status'] == 3 ? 'Cancelled' : $['status'] == 4 ? 'Completed' : $['status'] == 6 ? 'Inactive' : 'Unknown' }}",
"shape": ["state", {
"map": {
"success": ["Active", "Completed"],
"error": ["Cancelled"],
"warning": ["Upcoming"],
"unknown": ["Inactive", "Unknown"]
}
}]
},
{ "pattern": ".*" }
]
}
46 changes: 46 additions & 0 deletions plugins/AutoTask/v1/dataStreams/projectStatus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "projectStatus",
"displayName": "Project Status",
"description": "Status, progress, and schedule for all projects",
"tags": ["Projects"],
"baseDataSourceName": "httpRequestUnscoped",
"timeframes": false,
"config": {
"httpMethod": "get",
"expandInnerObjects": true,
"endpointPath": "atservicesrest/v1.0/Projects/query?search={\"MaxRecords\":500,\"filter\":[{\"op\":\"exist\",\"field\":\"id\"}]}",
"pathToData": "items",
"paging": {
"mode": "nextUrl",
"pageSize": { "realm": "none" },
"in": {
"realm": "payload",
"path": "pageDetails.nextPageUrl"
}
}
},
"metadata": [
{ "name": "id", "displayName": "ID", "shape": "string" },
{ "name": "projectName", "displayName": "Project Name" },
{ "name": "status", "displayName": "Status (Raw)", "shape": ["number", { "decimalPlaces": 0 }], "visible": false },
{
"name": "statusName",
"displayName": "Status",
"computed": true,
"valueExpression": "{{ $['status'] == 1 ? 'Active' : $['status'] == 2 ? 'Inactive' : $['status'] == 3 ? 'Completed' : $['status'] == 5 ? 'On Hold' : 'Unknown' }}",
"shape": ["state", {
"map": {
"success": ["Active", "Completed"],
"warning": ["On Hold"],
"unknown": ["Inactive", "Unknown"]
}
}]
},
{ "name": "completedPercentage", "displayName": "Completed %", "shape": ["number", { "decimalPlaces": 0 }] },
{ "name": "actualHours", "displayName": "Actual Hours", "shape": ["number", { "decimalPlaces": 2 }] },
{ "name": "estimatedTime", "displayName": "Estimated Hours", "shape": ["number", { "decimalPlaces": 2 }] },
{ "name": "startDateTime", "displayName": "Start Date", "shape": ["date", { "timeZone": "Etc/UTC" }] },
{ "name": "endDateTime", "displayName": "End Date", "shape": ["date", { "timeZone": "Etc/UTC" }] },
{ "pattern": ".*" }
]
}
21 changes: 21 additions & 0 deletions plugins/AutoTask/v1/dataStreams/projects.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "projects",
"displayName": "Projects",
"baseDataSourceName": "httpRequestUnscoped",
"visibility": { "type": "hidden" },
"timeframes": false,
"config": {
"httpMethod": "get",
"expandInnerObjects": true,
"endpointPath": "atservicesrest/v1.0/Projects/query?search={\"MaxRecords\":500,\"filter\":[{\"op\":\"exist\",\"field\":\"id\"}]}",
"pathToData": "items",
"paging": {
"mode": "nextUrl",
"pageSize": { "realm": "none" },
"in": {
"realm": "payload",
"path": "pageDetails.nextPageUrl"
}
}
}
}
33 changes: 33 additions & 0 deletions plugins/AutoTask/v1/dataStreams/resourceUtilisation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "resourceUtilisation",
"displayName": "Resource Utilization",
"description": "Time entries logged by resources within the selected timeframe",
"tags": ["Resources"],
"baseDataSourceName": "httpRequestUnscoped",
"timeframes": true,
"config": {
"httpMethod": "get",
"expandInnerObjects": true,
"endpointPath": "atservicesrest/v1.0/TimeEntries/query?search={\"MaxRecords\":500,\"filter\":[{\"op\":\"gte\",\"field\":\"dateWorked\",\"value\":\"{{timeframe.start}}\"},{\"op\":\"lte\",\"field\":\"dateWorked\",\"value\":\"{{timeframe.end}}\"}]}",
"pathToData": "items",
"paging": {
"mode": "nextUrl",
"pageSize": { "realm": "none" },
"in": {
"realm": "payload",
"path": "pageDetails.nextPageUrl"
}
}
},
"metadata": [
{ "name": "id", "displayName": "ID", "visible": false,"shape":"string" },
{ "name": "resourceID", "sourceType": "autotask-resource", "shape": "string", "visible": false },
{ "name": "resourceName", "displayName": "Resource", "sourceId": "resourceID", "objectPropertyPath": "name" },
{ "name": "dateWorked", "displayName": "Date Worked", "shape": ["date", { "timeZone": "Etc/UTC" }] },
{ "name": "hoursWorked", "displayName": "Hours Worked", "shape": ["number", { "decimalPlaces": 2 }] },
{ "name": "hoursToBill", "displayName": "Hours to Bill", "shape": ["number", { "decimalPlaces": 2 }] },
{ "name": "billingCodeID", "displayName": "Billing Code ID" },
{ "name": "ticketID", "displayName": "Ticket ID" },
{ "pattern": ".*" }
]
}
31 changes: 31 additions & 0 deletions plugins/AutoTask/v1/dataStreams/resources.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "resources",
"displayName": "Resources",
"baseDataSourceName": "httpRequestUnscoped",
"visibility": { "type": "hidden" },
"timeframes": false,
"config": {
"httpMethod": "get",
"expandInnerObjects": true,
"endpointPath": "atservicesrest/v1.0/Resources/query?search={\"MaxRecords\":500,\"filter\":[{\"op\":\"exist\",\"field\":\"id\"}]}",
"pathToData": "items",
"paging": {
"mode": "nextUrl",
"pageSize": { "realm": "none" },
"in": {
"realm": "payload",
"path": "pageDetails.nextPageUrl"
}
}
},
"metadata": [
{ "name": "id", "displayName": "ID", "shape": "string" },
{
"name": "fullName",
"displayName": "Full Name",
"computed": true,
"valueExpression": "{{ $['firstName'] + ' ' + $['lastName'] }}"
},
{ "pattern": ".*" }
]
}
2 changes: 2 additions & 0 deletions plugins/AutoTask/v1/dataStreams/scripts/tickets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const selectedIds = new Set(context.objects.map(o => String(o.companyId)));
result = (data.items ?? []).filter(ticket => selectedIds.has(String(ticket.companyID)));
Loading
Loading