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