Add CLI tools for task CRUD and file attachments
This commit is contained in:
parent
9453f88df4
commit
89e1cbcbb7
79
scripts/attach-file.sh
Executable file
79
scripts/attach-file.sh
Executable file
@ -0,0 +1,79 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Attach a file to a gantt board task
|
||||||
|
# Usage: ./attach-file.sh <task-id> <file-path>
|
||||||
|
|
||||||
|
SUPABASE_URL="https://qnatchrjlpehiijwtreh.supabase.co"
|
||||||
|
SERVICE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InFuYXRjaHJqbHBlaGlpand0cmVoIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc3MTY0MDQzNiwiZXhwIjoyMDg3MjE2NDM2fQ.rHoc3NfL59S4lejU4-ArSzox1krQkQG-TnfXb6sslm0"
|
||||||
|
|
||||||
|
HEADERS=(-H "apikey: $SERVICE_KEY" -H "Authorization: Bearer $SERVICE_KEY" -H "Content-Type: application/json")
|
||||||
|
|
||||||
|
TASK_ID="$1"
|
||||||
|
FILE_PATH="$2"
|
||||||
|
|
||||||
|
if [[ -z "$TASK_ID" || -z "$FILE_PATH" ]]; then
|
||||||
|
echo "Usage: $0 <task-id> <file-path>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$FILE_PATH" ]]; then
|
||||||
|
echo "Error: File not found: $FILE_PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
FILENAME=$(basename "$FILE_PATH")
|
||||||
|
# Determine MIME type based on extension
|
||||||
|
EXTENSION="${FILENAME##*.}"
|
||||||
|
case "$EXTENSION" in
|
||||||
|
md|markdown) MIME_TYPE="text/markdown" ;;
|
||||||
|
txt) MIME_TYPE="text/plain" ;;
|
||||||
|
json) MIME_TYPE="application/json" ;;
|
||||||
|
pdf) MIME_TYPE="application/pdf" ;;
|
||||||
|
png) MIME_TYPE="image/png" ;;
|
||||||
|
jpg|jpeg) MIME_TYPE="image/jpeg" ;;
|
||||||
|
gif) MIME_TYPE="image/gif" ;;
|
||||||
|
*) MIME_TYPE="application/octet-stream" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Convert file to base64 data URL
|
||||||
|
BASE64_CONTENT=$(base64 -i "$FILE_PATH" | tr -d '\n')
|
||||||
|
DATA_URL="data:$MIME_TYPE;base64,$BASE64_CONTENT"
|
||||||
|
|
||||||
|
# Generate attachment ID and timestamp
|
||||||
|
ATTACHMENT_ID=$(uuidgen | tr '[:upper:]' '[:lower:]')
|
||||||
|
NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
FILE_SIZE=$(stat -f%z "$FILE_PATH")
|
||||||
|
|
||||||
|
# Get current task attachments
|
||||||
|
echo "Fetching current task..."
|
||||||
|
CURRENT_ATTACHMENTS=$(curl -s "$SUPABASE_URL/rest/v1/tasks?id=eq.$TASK_ID&select=attachments" "${HEADERS[@]}" | jq 'if type == "array" then .[0].attachments // [] else .attachments // [] end')
|
||||||
|
|
||||||
|
# Create new attachment object (field names must match UI expectations)
|
||||||
|
NEW_ATTACHMENT=$(jq -n \
|
||||||
|
--arg id "$ATTACHMENT_ID" \
|
||||||
|
--arg name "$FILENAME" \
|
||||||
|
--arg type "$MIME_TYPE" \
|
||||||
|
--argjson size "$FILE_SIZE" \
|
||||||
|
--arg dataUrl "$DATA_URL" \
|
||||||
|
--arg uploadedAt "$NOW" \
|
||||||
|
'{
|
||||||
|
id: $id,
|
||||||
|
name: $name,
|
||||||
|
type: $type,
|
||||||
|
size: $size,
|
||||||
|
dataUrl: $dataUrl,
|
||||||
|
uploadedAt: $uploadedAt
|
||||||
|
}')
|
||||||
|
|
||||||
|
# Merge with existing attachments
|
||||||
|
UPDATED_ATTACHMENTS=$(echo "$CURRENT_ATTACHMENTS" | jq --argjson new "$NEW_ATTACHMENT" '. + [$new]')
|
||||||
|
|
||||||
|
# Update task
|
||||||
|
echo "Attaching file to task..."
|
||||||
|
curl -s -X PATCH "$SUPABASE_URL/rest/v1/tasks?id=eq.$TASK_ID" \
|
||||||
|
"${HEADERS[@]}" \
|
||||||
|
-d "{\"attachments\": $UPDATED_ATTACHMENTS, \"updated_at\": \"$NOW\"}" | jq '.'
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ Attached: $FILENAME"
|
||||||
|
echo " Size: $FILE_SIZE bytes"
|
||||||
|
echo " Type: $MIME_TYPE"
|
||||||
100
scripts/gantt-task-crud.sh
Executable file
100
scripts/gantt-task-crud.sh
Executable file
@ -0,0 +1,100 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Gantt Board Task CRUD Operations
|
||||||
|
# Usage: ./task-crud.sh [create|read|update|delete|list] [args...]
|
||||||
|
|
||||||
|
SUPABASE_URL="https://qnatchrjlpehiijwtreh.supabase.co"
|
||||||
|
SERVICE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InFuYXRjaHJqbHBlaGlpand0cmVoIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc3MTY0MDQzNiwiZXhwIjoyMDg3MjE2NDM2fQ.rHoc3NfL59S4lejU4-ArSzox1krQkQG-TnfXb6sslm0"
|
||||||
|
|
||||||
|
HEADERS=(-H "apikey: $SERVICE_KEY" -H "Authorization: Bearer $SERVICE_KEY" -H "Content-Type: application/json")
|
||||||
|
|
||||||
|
function list_tasks() {
|
||||||
|
local status_filter="${1:-}"
|
||||||
|
local url="$SUPABASE_URL/rest/v1/tasks?select=*&order=created_at.desc"
|
||||||
|
if [[ -n "$status_filter" ]]; then
|
||||||
|
url="$SUPABASE_URL/rest/v1/tasks?select=*&status=eq.$status_filter&order=created_at.desc"
|
||||||
|
fi
|
||||||
|
curl -s "$url" "${HEADERS[@]}" | jq '.'
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_task() {
|
||||||
|
local task_id="$1"
|
||||||
|
curl -s "$SUPABASE_URL/rest/v1/tasks?id=eq.$task_id&select=*" "${HEADERS[@]}" | jq '.[0]'
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_task() {
|
||||||
|
local title="$1"
|
||||||
|
local status="${2:-open}"
|
||||||
|
local priority="${3:-medium}"
|
||||||
|
local project_id="${4:-1}"
|
||||||
|
local assignee_id="${5:-9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa}"
|
||||||
|
|
||||||
|
local uuid=$(uuidgen | tr '[:upper:]' '[:lower:]')
|
||||||
|
local now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
|
||||||
|
curl -s -X POST "$SUPABASE_URL/rest/v1/tasks" \
|
||||||
|
"${HEADERS[@]}" \
|
||||||
|
-d "{
|
||||||
|
\"id\": \"$uuid\",
|
||||||
|
\"title\": \"$title\",
|
||||||
|
\"status\": \"$status\",
|
||||||
|
\"priority\": \"$priority\",
|
||||||
|
\"project_id\": \"$project_id\",
|
||||||
|
\"assignee_id\": \"$assignee_id\",
|
||||||
|
\"created_at\": \"$now\",
|
||||||
|
\"updated_at\": \"$now\",
|
||||||
|
\"comments\": [],
|
||||||
|
\"tags\": [],
|
||||||
|
\"attachments\": []
|
||||||
|
}" | jq '.'
|
||||||
|
|
||||||
|
echo "Created task: $uuid"
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_task() {
|
||||||
|
local task_id="$1"
|
||||||
|
local field="$2"
|
||||||
|
local value="$3"
|
||||||
|
local now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
|
||||||
|
curl -s -X PATCH "$SUPABASE_URL/rest/v1/tasks?id=eq.$task_id" \
|
||||||
|
"${HEADERS[@]}" \
|
||||||
|
-d "{\"$field\": \"$value\", \"updated_at\": \"$now\"}" | jq '.'
|
||||||
|
|
||||||
|
echo "Updated task $task_id: $field = $value"
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete_task() {
|
||||||
|
local task_id="$1"
|
||||||
|
curl -s -X DELETE "$SUPABASE_URL/rest/v1/tasks?id=eq.$task_id" "${HEADERS[@]}"
|
||||||
|
echo "Deleted task: $task_id"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main
|
||||||
|
case "$1" in
|
||||||
|
list)
|
||||||
|
list_tasks "$2"
|
||||||
|
;;
|
||||||
|
get)
|
||||||
|
get_task "$2"
|
||||||
|
;;
|
||||||
|
create)
|
||||||
|
create_task "$2" "$3" "$4" "$5" "$6"
|
||||||
|
;;
|
||||||
|
update)
|
||||||
|
update_task "$2" "$3" "$4"
|
||||||
|
;;
|
||||||
|
delete)
|
||||||
|
delete_task "$2"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 [list|get|create|update|delete] [args...]"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 list # List all tasks"
|
||||||
|
echo " $0 list open # List open tasks"
|
||||||
|
echo " $0 get <task-id> # Get specific task"
|
||||||
|
echo " $0 create \"Task title\" open medium # Create task"
|
||||||
|
echo " $0 update <task-id> status done # Update task status"
|
||||||
|
echo " $0 delete <task-id> # Delete task"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
77
scripts/view-attachment.sh
Executable file
77
scripts/view-attachment.sh
Executable file
@ -0,0 +1,77 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# View attachment from a gantt board task
|
||||||
|
# Usage: ./view-attachment.sh <task-id> [attachment-index]
|
||||||
|
|
||||||
|
SUPABASE_URL="https://qnatchrjlpehiijwtreh.supabase.co"
|
||||||
|
SERVICE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InFuYXRjaHJqbHBlaGlpand0cmVoIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc3MTY0MDQzNiwiZXhwIjoyMDg3MjE2NDM2fQ.rHoc3NfL59S4lejU4-ArSzox1krQkQG-TnfXb6sslm0"
|
||||||
|
|
||||||
|
HEADERS=(-H "apikey: $SERVICE_KEY" -H "Authorization: Bearer $SERVICE_KEY" -H "Content-Type: application/json")
|
||||||
|
|
||||||
|
TASK_ID="$1"
|
||||||
|
ATTACHMENT_INDEX="${2:-0}"
|
||||||
|
|
||||||
|
if [[ -z "$TASK_ID" ]]; then
|
||||||
|
echo "Usage: $0 <task-id> [attachment-index]"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 33ebc71e-7d40-456c-8f98-bb3578d2bb2b # View first attachment"
|
||||||
|
echo " $0 33ebc71e-7d40-456c-8f98-bb3578d2bb2b 0 # View first attachment (explicit)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fetch task with attachments
|
||||||
|
echo "Fetching task attachments..."
|
||||||
|
TASK_DATA=$(curl -s "$SUPABASE_URL/rest/v1/tasks?id=eq.$TASK_ID&select=title,attachments" "${HEADERS[@]}")
|
||||||
|
|
||||||
|
# Extract attachments array
|
||||||
|
ATTACHMENTS=$(echo "$TASK_DATA" | jq -r 'if type == "array" then (.[0].attachments // []) else (.attachments // []) end')
|
||||||
|
ATTACHMENT_COUNT=$(echo "$ATTACHMENTS" | jq 'length')
|
||||||
|
|
||||||
|
if [[ "$ATTACHMENT_COUNT" -eq 0 ]]; then
|
||||||
|
echo "❌ No attachments found on this task."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Found $ATTACHMENT_COUNT attachment(s):"
|
||||||
|
echo "$ATTACHMENTS" | jq -r '.[] | " - \(.name) (\(.size) bytes, \(.type))"'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get the requested attachment
|
||||||
|
ATTACHMENT=$(echo "$ATTACHMENTS" | jq -r ".[$ATTACHMENT_INDEX]")
|
||||||
|
if [[ "$ATTACHMENT" == "null" ]]; then
|
||||||
|
echo "❌ Attachment index $ATTACHMENT_INDEX not found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
FILENAME=$(echo "$ATTACHMENT" | jq -r '.name')
|
||||||
|
MIME_TYPE=$(echo "$ATTACHMENT" | jq -r '.type')
|
||||||
|
DATA_URL=$(echo "$ATTACHMENT" | jq -r '.url')
|
||||||
|
|
||||||
|
# Extract base64 content from data URL (remove data:mime/type;base64, prefix)
|
||||||
|
BASE64_CONTENT=$(echo "$DATA_URL" | sed 's/^data:[^;]*;base64,//')
|
||||||
|
|
||||||
|
# Decode to temp file
|
||||||
|
TEMP_FILE="/tmp/gantt-attachment-$(date +%s)-$FILENAME"
|
||||||
|
echo "$BASE64_CONTENT" | base64 -d > "$TEMP_FILE"
|
||||||
|
|
||||||
|
echo "📎 Attachment: $FILENAME"
|
||||||
|
echo "📋 Type: $MIME_TYPE"
|
||||||
|
echo "📊 Size: $(stat -f%z "$TEMP_FILE") bytes"
|
||||||
|
echo ""
|
||||||
|
echo "--- CONTENT ---"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Display based on type
|
||||||
|
if [[ "$MIME_TYPE" == text/* ]] || [[ "$FILENAME" == *.md ]] || [[ "$FILENAME" == *.txt ]]; then
|
||||||
|
cat "$TEMP_FILE"
|
||||||
|
else
|
||||||
|
echo "(Binary file - saved to: $TEMP_FILE)"
|
||||||
|
echo "Open with: open '$TEMP_FILE'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "---------------"
|
||||||
|
|
||||||
|
# Clean up temp file
|
||||||
|
rm -f "$TEMP_FILE"
|
||||||
Loading…
Reference in New Issue
Block a user