@@ -14,17 +14,18 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
architecture: [x64, arm64]
|
architecture: [x64, arm64]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Docker Compose
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y docker-compose
|
||||||
|
docker-compose --version
|
||||||
|
|
||||||
- name: Set up opensearch directory
|
- name: Set up opensearch directory
|
||||||
run: mkdir shuffle-database
|
run: chmod -R 777 shuffle-database
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Elevate rights for it
|
|
||||||
run: chmod -R 777 shuffle-database
|
|
||||||
|
|
||||||
- name: Build the stack
|
- name: Build the stack
|
||||||
run: docker compose up -d
|
run: docker compose up -d
|
||||||
@@ -59,7 +60,6 @@ jobs:
|
|||||||
echo "The word 'Shuffle' was not found in the response."
|
echo "The word 'Shuffle' was not found in the response."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Register a user and check the status code
|
- name: Register a user and check the status code
|
||||||
run: |
|
run: |
|
||||||
MAX_RETRIES=30
|
MAX_RETRIES=30
|
||||||
@@ -100,31 +100,36 @@ jobs:
|
|||||||
echo "User registration failed after $MAX_RETRIES attempts."
|
echo "User registration failed after $MAX_RETRIES attempts."
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
|
- name: Run Selenium testing for frontend
|
||||||
|
run: |
|
||||||
|
cd $GITHUB_WORKSPACE/frontend
|
||||||
|
# write some log to see the current directory
|
||||||
|
chmod +x frontend-testing.sh
|
||||||
|
./frontend-testing.sh
|
||||||
|
|
||||||
- name: Get the API key and run a health check
|
- name: Get the API key and run a health check
|
||||||
|
id: health_check
|
||||||
run: |
|
run: |
|
||||||
RESPONSE=$(curl -s -k -u admin:StrongShufflePassword321! 'https://localhost:9200/users/_search')
|
RESPONSE=$(curl -s -k -u admin:StrongShufflePassword321! 'https://localhost:9200/users/_search')
|
||||||
|
echo "Raw Response: $RESPONSE"
|
||||||
|
|
||||||
API_KEY=$(echo "$RESPONSE" | jq -r '.hits.hits[0]._source.apikey')
|
API_KEY=$(echo "$RESPONSE" | jq -r '.hits.hits[0]._source.apikey')
|
||||||
if [ -n "$API_KEY" ]; then
|
if [ -n "$API_KEY" ] && [ "$API_KEY" != "null" ]; then
|
||||||
echo "Admin API key: $API_KEY"
|
echo "Admin API key: $API_KEY"
|
||||||
|
echo "API_KEY=$API_KEY" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
echo "Failed to retrieve the API key for the admin user."
|
echo "Failed to retrieve the API key for the admin user."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "Waiting 1 minute before sending the health API request..."
|
||||||
|
sleep 60
|
||||||
|
|
||||||
|
echo "Checking health API..."
|
||||||
HEALTH_RESPONSE=$(curl -s 'http://localhost:3001/api/v1/health?force=true' \
|
HEALTH_RESPONSE=$(curl -s 'http://localhost:3001/api/v1/health?force=true' \
|
||||||
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \
|
-H "Authorization: Bearer $API_KEY")
|
||||||
-H 'Accept-Language: en-US,en;q=0.9' \
|
|
||||||
-H 'Connection: keep-alive' \
|
echo "Health API Response: $HEALTH_RESPONSE"
|
||||||
-H 'Sec-Fetch-Dest: document' \
|
|
||||||
-H 'Sec-Fetch-Mode: navigate' \
|
|
||||||
-H 'Sec-Fetch-Site: none' \
|
|
||||||
-H "Authorization: Bearer $API_KEY" \
|
|
||||||
-H 'Sec-Fetch-User: ?1' \
|
|
||||||
-H 'Upgrade-Insecure-Requests: 1' \
|
|
||||||
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' \
|
|
||||||
-H 'sec-ch-ua: "Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"' \
|
|
||||||
-H 'sec-ch-ua-mobile: ?0' \
|
|
||||||
-H 'sec-ch-ua-platform: "macOS"')
|
|
||||||
|
|
||||||
WORKFLOWS_CREATE=$(echo "$HEALTH_RESPONSE" | jq -r '.workflows.create')
|
WORKFLOWS_CREATE=$(echo "$HEALTH_RESPONSE" | jq -r '.workflows.create')
|
||||||
WORKFLOWS_RUN=$(echo "$HEALTH_RESPONSE" | jq -r '.workflows.run')
|
WORKFLOWS_RUN=$(echo "$HEALTH_RESPONSE" | jq -r '.workflows.run')
|
||||||
@@ -132,9 +137,35 @@ jobs:
|
|||||||
WORKFLOWS_RUN_STATUS=$(echo "$HEALTH_RESPONSE" | jq -r '.workflows.run_status')
|
WORKFLOWS_RUN_STATUS=$(echo "$HEALTH_RESPONSE" | jq -r '.workflows.run_status')
|
||||||
WORKFLOWS_DELETE=$(echo "$HEALTH_RESPONSE" | jq -r '.workflows.delete')
|
WORKFLOWS_DELETE=$(echo "$HEALTH_RESPONSE" | jq -r '.workflows.delete')
|
||||||
|
|
||||||
|
echo "WORKFLOWS_CREATE: $WORKFLOWS_CREATE"
|
||||||
|
echo "WORKFLOWS_RUN: $WORKFLOWS_RUN"
|
||||||
|
echo "WORKFLOWS_RUN_FINISHED: $WORKFLOWS_RUN_FINISHED"
|
||||||
|
echo "WORKFLOWS_RUN_STATUS: $WORKFLOWS_RUN_STATUS"
|
||||||
|
echo "WORKFLOWS_DELETE: $WORKFLOWS_DELETE"
|
||||||
|
|
||||||
if [ "$WORKFLOWS_CREATE" = "true" ] && [ "$WORKFLOWS_RUN" = "true" ] && [ "$WORKFLOWS_RUN_FINISHED" = "true" ] && [ "$WORKFLOWS_RUN_STATUS" = "FINISHED" ] && [ "$WORKFLOWS_DELETE" = "true" ]; then
|
if [ "$WORKFLOWS_CREATE" = "true" ] && [ "$WORKFLOWS_RUN" = "true" ] && [ "$WORKFLOWS_RUN_FINISHED" = "true" ] && [ "$WORKFLOWS_RUN_STATUS" = "FINISHED" ] && [ "$WORKFLOWS_DELETE" = "true" ]; then
|
||||||
echo "Health endpoint check was successful."
|
echo "Health endpoint check was successful."
|
||||||
|
exit 0
|
||||||
else
|
else
|
||||||
echo "Health endpoint check failed. Response did not meet expected criteria."
|
echo "Health check failed."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
notify:
|
||||||
|
needs: build
|
||||||
|
if: failure()
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Send Twilio Alert
|
||||||
|
run: |
|
||||||
|
WORKFLOW_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||||
|
MESSAGE="🚨 Shuffle Workflow Failed!
|
||||||
|
Repository: ${{ github.repository }}
|
||||||
|
Branch: ${{ github.ref_name }}
|
||||||
|
Workflow URL: $WORKFLOW_URL"
|
||||||
|
|
||||||
|
curl -s -X POST https://api.twilio.com/2010-04-01/Accounts/${{ secrets.TWILIO_ACCOUNT_SID }}/Messages.json \
|
||||||
|
--data-urlencode "To=${{ secrets.TWILIO_TO_NUMBER }}" \
|
||||||
|
--data-urlencode "From=${{ secrets.TWILIO_FROM_NUMBER }}" \
|
||||||
|
--data-urlencode "Body=$MESSAGE" \
|
||||||
|
-u "${{ secrets.TWILIO_ACCOUNT_SID }}:${{ secrets.TWILIO_AUTH_TOKEN }}" > /dev/null
|
||||||
|
|||||||
@@ -984,11 +984,4 @@ func activateWorkflowAppDocker(resp http.ResponseWriter, request *http.Request)
|
|||||||
|
|
||||||
log.Printf("[INFO] User %s (%s) is activating %s. Public: %t, Shared: %t", user.Username, user.Id, app.Name, app.Public, app.Sharing)
|
log.Printf("[INFO] User %s (%s) is activating %s. Public: %t, Shared: %t", user.Username, user.Id, app.Name, app.Public, app.Sharing)
|
||||||
buildSwaggerApp(resp, []byte(openApiApp.Body), user, true)
|
buildSwaggerApp(resp, []byte(openApiApp.Body), user, true)
|
||||||
|
|
||||||
//app.Active = true
|
|
||||||
//app.Generated = true
|
|
||||||
//app, err := shuffle.SetApp(ctx, app)
|
|
||||||
|
|
||||||
//resp.WriteHeader(200)
|
|
||||||
//resp.Write([]byte(`{"success": true}`))
|
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-9
@@ -1,7 +1,9 @@
|
|||||||
module shuffle
|
module shuffle
|
||||||
|
|
||||||
go 1.22.2
|
|
||||||
toolchain go1.24.1
|
go 1.23.0
|
||||||
|
|
||||||
|
toolchain go1.23.7
|
||||||
|
|
||||||
//replace github.com/shuffle/shuffle-shared => ../../../shuffle-shared
|
//replace github.com/shuffle/shuffle-shared => ../../../shuffle-shared
|
||||||
|
|
||||||
@@ -19,8 +21,8 @@ require (
|
|||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/h2non/filetype v1.1.3
|
github.com/h2non/filetype v1.1.3
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shuffle/shuffle-shared v0.8.12
|
github.com/shuffle/shuffle-shared v0.8.18
|
||||||
golang.org/x/crypto v0.35.0
|
golang.org/x/crypto v0.36.0
|
||||||
google.golang.org/api v0.176.1
|
google.golang.org/api v0.176.1
|
||||||
google.golang.org/grpc v1.68.1
|
google.golang.org/grpc v1.68.1
|
||||||
gopkg.in/src-d/go-git.v4 v4.13.1
|
gopkg.in/src-d/go-git.v4 v4.13.1
|
||||||
@@ -121,12 +123,12 @@ require (
|
|||||||
go.opentelemetry.io/proto/otlp v0.11.0 // indirect
|
go.opentelemetry.io/proto/otlp v0.11.0 // indirect
|
||||||
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
golang.org/x/net v0.36.0 // indirect
|
golang.org/x/net v0.37.0 // indirect
|
||||||
golang.org/x/oauth2 v0.23.0 // indirect
|
golang.org/x/oauth2 v0.23.0 // indirect
|
||||||
golang.org/x/sync v0.11.0 // indirect
|
golang.org/x/sync v0.12.0 // indirect
|
||||||
golang.org/x/sys v0.30.0 // indirect
|
golang.org/x/sys v0.31.0 // indirect
|
||||||
golang.org/x/term v0.29.0 // indirect
|
golang.org/x/term v0.30.0 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.23.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||||
google.golang.org/appengine v1.6.8 // indirect
|
google.golang.org/appengine v1.6.8 // indirect
|
||||||
|
|||||||
+5
-14
@@ -347,8 +347,6 @@ github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdR
|
|||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||||
github.com/shuffle/shuffle-shared v0.8.12 h1:fg6jGAuevOGLgR7kpoZDJh//tzFjrEqj/bpxRFzxUTw=
|
|
||||||
github.com/shuffle/shuffle-shared v0.8.12/go.mod h1:bBXhEsPKjxln0mFnSeri7gIJ3tL/636Sh5NyTyNrvIQ=
|
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
@@ -423,8 +421,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
|
||||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@@ -480,8 +476,7 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
|
|
||||||
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -497,8 +492,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
|
||||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -527,14 +521,12 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
|
||||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -545,8 +537,7 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
|
||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
|
||||||
|
SERVER_URL="http://localhost:3000"
|
||||||
|
|
||||||
|
declare -a Routes=($(grep -oP '(?<=path=")[^"]*' src/App.jsx | grep -E '^[a-zA-Z0-9/_:-]+$' | grep -vE '^/$'))
|
||||||
|
|
||||||
|
for i in "${!Routes[@]}"; do
|
||||||
|
Routes[$i]="${Routes[$i]#/}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# # Add all tab routes and unique routes here
|
||||||
|
Routes+=(
|
||||||
|
'workflows?tab=org_workflows'
|
||||||
|
'workflows?tab=my_workflows'
|
||||||
|
'workflows?tab=all_workflows'
|
||||||
|
'apps/gmail'
|
||||||
|
'apis/gmail'
|
||||||
|
'apps?tab=my_apps'
|
||||||
|
'apps?tab=all_apps'
|
||||||
|
'search?tab=org_apps'
|
||||||
|
'search?tab=my_apps'
|
||||||
|
'search?tab=workflows'
|
||||||
|
'search?tab=docs'
|
||||||
|
'search?tab=creators'
|
||||||
|
'search?tab=discord'
|
||||||
|
"admin?tab=organization"
|
||||||
|
"admin?tab=users"
|
||||||
|
"admin?tab=app_auth"
|
||||||
|
"admin?tab=datastore"
|
||||||
|
"admin?tab=files"
|
||||||
|
"admin?tab=triggers"
|
||||||
|
"admin?tab=locations"
|
||||||
|
"admin?tab=tenants"
|
||||||
|
"admin?admin_tab=org_config"
|
||||||
|
"admin?admin_tab=sso"
|
||||||
|
"admin?admin_tab=notifications"
|
||||||
|
"admin?admin_tab=billingstats"
|
||||||
|
"admin?admin_tab=branding(beta)"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Stop frontend container so it test unpushed changes
|
||||||
|
docker stop shuffle-frontend
|
||||||
|
|
||||||
|
# # Install all frontend dependencies
|
||||||
|
yarn add selenium-webdriver --dev && yarn install
|
||||||
|
echo "Starting frontend..."
|
||||||
|
|
||||||
|
BROWSER=none yarn start &
|
||||||
|
SERVER_PID=$!
|
||||||
|
echo "Frontend started with PID: $SERVER_PID"
|
||||||
|
|
||||||
|
echo "Waiting for 1 minute to ensure the server is fully up..."
|
||||||
|
sleep 60
|
||||||
|
|
||||||
|
echo "Server is up! Starting Selenium tests..."
|
||||||
|
|
||||||
|
echo "Starting frontend tests..."
|
||||||
|
node selenium-test.js "$SERVER_URL" "${Routes[@]}"
|
||||||
|
|
||||||
|
TEST_EXIT_CODE=$?
|
||||||
|
|
||||||
|
if [[ $TEST_EXIT_CODE -ne 0 ]]; then
|
||||||
|
echo "Selenium tests failed. Exiting..."
|
||||||
|
kill $SERVER_PID
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill $SERVER_PID
|
||||||
|
echo "Testing complete. See above logs for errors if any."
|
||||||
|
|
||||||
|
# Starting shuffle-frontend container
|
||||||
|
echo "Starting shuffle-frontend container..."
|
||||||
|
docker start shuffle-frontend
|
||||||
|
echo "shuffle-frontend started successfully."
|
||||||
|
exit 0
|
||||||
@@ -128,6 +128,7 @@
|
|||||||
"babel-preset-es2015": "^6.24.1",
|
"babel-preset-es2015": "^6.24.1",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
"promise-window": "^1.2.1",
|
"promise-window": "^1.2.1",
|
||||||
|
"selenium-webdriver": "^4.29.0",
|
||||||
"webpack-cli": "^5.1.4"
|
"webpack-cli": "^5.1.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,253 @@
|
|||||||
|
const { Builder, By, until } = require('selenium-webdriver');
|
||||||
|
const chrome = require('selenium-webdriver/chrome');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
console.log('Starting Selenium script for testing pages...');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const userDataDir = path.join(__dirname, 'chrome-user-data', `${Date.now()}-${Math.random().toString(36).substring(2, 8)}`);
|
||||||
|
fs.mkdirSync(userDataDir, { recursive: true });
|
||||||
|
|
||||||
|
let options = new chrome.Options();
|
||||||
|
options.addArguments('--no-sandbox');
|
||||||
|
options.addArguments('--headless');
|
||||||
|
|
||||||
|
let driver = await new Builder()
|
||||||
|
.forBrowser('chrome')
|
||||||
|
.setChromeOptions(options)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
const SuccessfullyLoadedPath = [];
|
||||||
|
const FailedToLoadPath = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
await driver.manage().window().setRect({ width: 1600, height: 1200 });
|
||||||
|
await driver.manage().window().maximize()
|
||||||
|
await driver.manage().setTimeouts({ implicit: 15000 });
|
||||||
|
|
||||||
|
const frontendURL = process.argv[2];
|
||||||
|
const routes = process.argv.slice(3);
|
||||||
|
|
||||||
|
console.log('Frontend URL:', frontendURL);
|
||||||
|
const isCloud = frontendURL === 'http://localhost:3002' || frontendURL === 'https://sandbox.shuffler.io' || frontendURL === 'https://shuffler.io';
|
||||||
|
|
||||||
|
if (isCloud) {
|
||||||
|
// Login Credentials
|
||||||
|
const LOGIN_URL = `${frontendURL}/login`;
|
||||||
|
// put your login credentials here
|
||||||
|
const USERNAME = '';
|
||||||
|
const PASSWORD = '';
|
||||||
|
|
||||||
|
console.log('Logging in...');
|
||||||
|
await driver.get(LOGIN_URL);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await driver.wait(until.elementLocated(By.css('#emailfield')), 10000);
|
||||||
|
await driver.findElement(By.css('#emailfield')).sendKeys(USERNAME);
|
||||||
|
|
||||||
|
await driver.wait(until.elementLocated(By.css('#outlined-password-input')), 10000);
|
||||||
|
await driver.findElement(By.css('#outlined-password-input')).sendKeys(PASSWORD);
|
||||||
|
|
||||||
|
await driver.wait(until.elementLocated(By.css('#loginButton')), 10000);
|
||||||
|
await driver.findElement(By.css('#loginButton')).click();
|
||||||
|
|
||||||
|
// Ensure login success by checking URL change
|
||||||
|
await driver.wait(async () => {
|
||||||
|
const url = await driver.getCurrentUrl();
|
||||||
|
return url.includes('welcome');
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
console.log('Successfully logged in!');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Login failed:', error.message);
|
||||||
|
FailedToLoadPath.push(LOGIN_URL);
|
||||||
|
await driver.quit();
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
// Steps for onprem testing
|
||||||
|
// 1. Login
|
||||||
|
// 2. Create new workflow
|
||||||
|
|
||||||
|
// Write your own login credentials here if you are testing onprem locally
|
||||||
|
const USERNAME = 'demo@demo.io';
|
||||||
|
const PASSWORD = 'supercoolpassword';
|
||||||
|
const WORKFLOW_URL = `${frontendURL}/workflows`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Login
|
||||||
|
console.log('Logging in...');
|
||||||
|
await driver.get(`${frontendURL}/login`);
|
||||||
|
|
||||||
|
await driver.wait(until.elementLocated(By.css('#emailfield')), 10000);
|
||||||
|
await driver.findElement(By.css('#emailfield')).sendKeys(USERNAME);
|
||||||
|
|
||||||
|
await driver.wait(until.elementLocated(By.css('#outlined-password-input')), 10000);
|
||||||
|
await driver.findElement(By.css('#outlined-password-input')).sendKeys(PASSWORD);
|
||||||
|
|
||||||
|
const loginButton = await driver.findElement(By.css('#loginButton'));
|
||||||
|
await driver.executeScript("arguments[0].scrollIntoView(true);", loginButton);
|
||||||
|
await loginButton.click();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Ensure signup success by checking URL change
|
||||||
|
await driver.wait(async () => {
|
||||||
|
const url = await driver.getCurrentUrl();
|
||||||
|
return url.includes('welcome') || url.includes('workflows');
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
|
||||||
|
const isParentPresent = await driver.wait(async () => {
|
||||||
|
return await driver.executeScript(
|
||||||
|
"return document.querySelector('.parent-component') !== null;"
|
||||||
|
);
|
||||||
|
}, 5000).catch(() => false);
|
||||||
|
|
||||||
|
if (!isParentPresent) {
|
||||||
|
const logs = await driver.manage().logs().get('browser');
|
||||||
|
const severeErrors = logs.filter(log => log.level.name === 'SEVERE');
|
||||||
|
if (severeErrors.length > 0) {
|
||||||
|
const crashCausingErrors = severeErrors.filter(err => {
|
||||||
|
return !err.message.includes('Warning:') &&
|
||||||
|
!err.message.includes('MUI:')
|
||||||
|
});
|
||||||
|
|
||||||
|
console.error(`Page (${frontendURL}/login) did not load correctly:`, crashCausingErrors);
|
||||||
|
FailedToLoadPath.push(`${frontendURL}/login`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Successfully logged in!');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to login:', error.message);
|
||||||
|
FailedToLoadPath.push(WORKFLOW_URL);
|
||||||
|
await driver.quit();
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create new workflow
|
||||||
|
console.log('Creating new workflow...');
|
||||||
|
await driver.get(WORKFLOW_URL);
|
||||||
|
|
||||||
|
await driver.sleep(1000);
|
||||||
|
|
||||||
|
await driver.wait(until.elementLocated(By.css('#create_workflow_button')), 10000);
|
||||||
|
const create_workflow_button = await driver.findElement(By.css('#create_workflow_button'));
|
||||||
|
|
||||||
|
await driver.sleep(1000);
|
||||||
|
await create_workflow_button.click();
|
||||||
|
|
||||||
|
await driver.sleep(1500);
|
||||||
|
|
||||||
|
await driver.wait(until.elementLocated(By.css('#Enter-Workflow-Name')), 10000);
|
||||||
|
const enter_workflow_name_field = await driver.findElement(By.css('#Enter-Workflow-Name'));
|
||||||
|
|
||||||
|
await driver.sleep(1000);
|
||||||
|
await enter_workflow_name_field.sendKeys("Test Workflow");
|
||||||
|
|
||||||
|
// Wait before saving
|
||||||
|
await driver.sleep(1500);
|
||||||
|
|
||||||
|
await driver.wait(until.elementLocated(By.css('#save_workflow_button')), 10000);
|
||||||
|
const save_workflow_button = await driver.findElement(By.css('#save_workflow_button'));
|
||||||
|
|
||||||
|
await driver.sleep(1000); // Delay before clicking
|
||||||
|
await save_workflow_button.click();
|
||||||
|
|
||||||
|
// Wait for the parent component to appear
|
||||||
|
await driver.sleep(2000);
|
||||||
|
|
||||||
|
const isParentPresent = await driver.wait(async () => {
|
||||||
|
return await driver.executeScript(
|
||||||
|
"return document.querySelector('.parent-component') !== null;"
|
||||||
|
);
|
||||||
|
}, 5000).catch(() => false);
|
||||||
|
|
||||||
|
if (!isParentPresent) {
|
||||||
|
const logs = await driver.manage().logs().get('browser');
|
||||||
|
const severeErrors = logs.filter(log => log.level.name === 'SEVERE');
|
||||||
|
if (severeErrors.length > 0) {
|
||||||
|
const crashCausingErrors = severeErrors.filter(err => {
|
||||||
|
return !err.message.includes('Warning:') &&
|
||||||
|
!err.message.includes('MUI:');
|
||||||
|
});
|
||||||
|
|
||||||
|
console.error(`Page (${WORKFLOW_URL}) did not load correctly:`, crashCausingErrors);
|
||||||
|
FailedToLoadPath.push(`${WORKFLOW_URL}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to create new workflow:', error.message);
|
||||||
|
FailedToLoadPath.push(WORKFLOW_URL);
|
||||||
|
await driver.quit();
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get routes from command line arguments
|
||||||
|
if (routes.length === 0) {
|
||||||
|
console.error('No routes found to test.');
|
||||||
|
await driver.quit();
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
console.log(`Found ${routes.length} routes to test.`);
|
||||||
|
|
||||||
|
for (const route of routes) {
|
||||||
|
const url = `${frontendURL}/${route}`;
|
||||||
|
console.log(`Testing route: ${url}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await driver.get(url);
|
||||||
|
await driver.sleep(3000);
|
||||||
|
|
||||||
|
// Wait for document readiness
|
||||||
|
await driver.wait(async () => {
|
||||||
|
return await driver.executeScript('return document.readyState') === 'complete';
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
const isParentPresent = await driver.wait(async () => {
|
||||||
|
return await driver.executeScript(
|
||||||
|
"return document.querySelector('.parent-component') !== null;"
|
||||||
|
);
|
||||||
|
}, 5000).catch(() => false);
|
||||||
|
|
||||||
|
if (!isParentPresent) {
|
||||||
|
const logs = await driver.manage().logs().get('browser');
|
||||||
|
const severeErrors = logs.filter(log => log.level.name === 'SEVERE');
|
||||||
|
if (severeErrors.length > 0) {
|
||||||
|
const crashCausingErrors = severeErrors.filter(err => {
|
||||||
|
return !err.message.includes('Warning:') &&
|
||||||
|
!err.message.includes('MUI:')
|
||||||
|
});
|
||||||
|
|
||||||
|
console.error(`Page (${url}) did not load correctly:`, crashCausingErrors);
|
||||||
|
FailedToLoadPath.push(url);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Successfully loaded: ${url}`);
|
||||||
|
SuccessfullyLoadedPath.push(url);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to load ${url}:`, error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
console.log("Total pages tested: ", SuccessfullyLoadedPath.length + FailedToLoadPath.length);
|
||||||
|
console.log("Successfully loaded pages: ", SuccessfullyLoadedPath.length);
|
||||||
|
if (FailedToLoadPath.length > 0) {
|
||||||
|
console.log("Failed to load pages: ", FailedToLoadPath.length);
|
||||||
|
console.log("Failed to load pages paths: ", FailedToLoadPath);
|
||||||
|
process.exit(1);
|
||||||
|
}else {
|
||||||
|
console.log("No pages failed to load. Congrats!");
|
||||||
|
}
|
||||||
|
await driver.quit();
|
||||||
|
fs.rmSync(userDataDir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
})();
|
||||||
+28
-1
@@ -189,6 +189,7 @@ const App = (message, props) => {
|
|||||||
color: "rgba(255, 255, 255, 0.65)",
|
color: "rgba(255, 255, 255, 0.65)",
|
||||||
minHeight: "100vh",
|
minHeight: "100vh",
|
||||||
}}
|
}}
|
||||||
|
className='parent-component'
|
||||||
>
|
>
|
||||||
<ScrollToTop
|
<ScrollToTop
|
||||||
getUserNotifications={getUserNotifications}
|
getUserNotifications={getUserNotifications}
|
||||||
@@ -371,6 +372,7 @@ const App = (message, props) => {
|
|||||||
element={
|
element={
|
||||||
<Admin
|
<Admin
|
||||||
isLoggedIn={isLoggedIn}
|
isLoggedIn={isLoggedIn}
|
||||||
|
userdata={userdata}
|
||||||
setIsLoggedIn={setIsLoggedIn}
|
setIsLoggedIn={setIsLoggedIn}
|
||||||
register={true}
|
register={true}
|
||||||
isLoaded={isLoaded}
|
isLoaded={isLoaded}
|
||||||
@@ -634,6 +636,32 @@ const App = (message, props) => {
|
|||||||
<Route exact path="/forms/:key/run" element={<RunWorkflow serverside={false} userdata={userdata} globalUrl={globalUrl} isLoaded={isLoaded} isLoggedIn={isLoggedIn} surfaceColor={theme.palette.surfaceColor} inputColor={theme.palette.inputColor}{...props} />} />
|
<Route exact path="/forms/:key/run" element={<RunWorkflow serverside={false} userdata={userdata} globalUrl={globalUrl} isLoaded={isLoaded} isLoggedIn={isLoggedIn} surfaceColor={theme.palette.surfaceColor} inputColor={theme.palette.inputColor}{...props} />} />
|
||||||
<Route exact path="/forms/:key" element={<RunWorkflow serverside={false} userdata={userdata} globalUrl={globalUrl} isLoaded={isLoaded} isLoggedIn={isLoggedIn} surfaceColor={theme.palette.surfaceColor} inputColor={theme.palette.inputColor}{...props} />} />
|
<Route exact path="/forms/:key" element={<RunWorkflow serverside={false} userdata={userdata} globalUrl={globalUrl} isLoaded={isLoaded} isLoggedIn={isLoggedIn} surfaceColor={theme.palette.surfaceColor} inputColor={theme.palette.inputColor}{...props} />} />
|
||||||
|
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/legal/:key"
|
||||||
|
element={
|
||||||
|
<Docs
|
||||||
|
isMobile={isMobile}
|
||||||
|
isLoaded={isLoaded}
|
||||||
|
globalUrl={globalUrl}
|
||||||
|
isLoggedIn={isLoggedIn}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/legal"
|
||||||
|
element={
|
||||||
|
<Docs
|
||||||
|
isMobile={isMobile}
|
||||||
|
isLoaded={isLoaded}
|
||||||
|
globalUrl={globalUrl}
|
||||||
|
isLoggedIn={isLoggedIn}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/docs/:key"
|
path="/docs/:key"
|
||||||
@@ -651,7 +679,6 @@ const App = (message, props) => {
|
|||||||
exact
|
exact
|
||||||
path="/docs"
|
path="/docs"
|
||||||
element={
|
element={
|
||||||
//navigate(`/docs/about`)
|
|
||||||
<Docs
|
<Docs
|
||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
isLoaded={isLoaded}
|
isLoaded={isLoaded}
|
||||||
|
|||||||
@@ -860,6 +860,7 @@ const Billing = memo((props) => {
|
|||||||
"Add Card Details"
|
"Add Card Details"
|
||||||
}
|
}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{userdata.has_card_available === true ?
|
{userdata.has_card_available === true ?
|
||||||
<Button
|
<Button
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -888,7 +889,8 @@ const Billing = memo((props) => {
|
|||||||
: null}
|
: null}
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
{showSupport ?
|
{showSupport ?
|
||||||
<Button variant="outlined" color="primary" style={{ marginTop: 20, marginBottom: 10, }} onClick={() => {
|
<Button variant="outlined" color="primary" style={{ marginTop: 20, marginBottom: 10, }} onClick={() => {
|
||||||
if (window.drift !== undefined) {
|
if (window.drift !== undefined) {
|
||||||
@@ -1204,12 +1206,13 @@ const Billing = memo((props) => {
|
|||||||
ReactGA.event({
|
ReactGA.event({
|
||||||
category: "Billing",
|
category: "Billing",
|
||||||
action: "Buy_consultation_hours",
|
action: "Buy_consultation_hours",
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = userdata.licensed === true
|
const url = userdata.licensed === true
|
||||||
? "https://book.stripe.com/6oEeY23fw2T84M06oq"
|
? "https://buy.stripe.com/aEU3fk17o0L092g5kt"
|
||||||
: "https://book.stripe.com/00g6rw3fw9hwguI289";
|
: "https://buy.stripe.com/aEU3fk17o0L092g5kt"
|
||||||
window.open(url, "_blank");
|
window.open(url, "_blank")
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Book Professional Service Hours
|
Book Professional Service Hours
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ const EditWorkflow = (props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
style={{}}
|
style={{}}
|
||||||
|
id="save_workflow_button"
|
||||||
disabled={name.length === 0 || submitLoading === true}
|
disabled={name.length === 0 || submitLoading === true}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSubmitLoading(true)
|
setSubmitLoading(true)
|
||||||
@@ -406,6 +407,7 @@ const EditWorkflow = (props) => {
|
|||||||
label="Name"
|
label="Name"
|
||||||
autoFocus
|
autoFocus
|
||||||
fullWidth
|
fullWidth
|
||||||
|
id="Enter-Workflow-Name"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div style={{ display: "flex", marginTop: 10, }}>
|
<div style={{ display: "flex", marginTop: 10, }}>
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ const ExpandMoreAndLessIcon = "/icons/expandMoreIcon.svg";
|
|||||||
const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const {setLeftSideBarOpenByClick, leftSideBarOpenByClick, setSearchBarModalOpen, searchBarModalOpen} = useContext(Context);
|
const {setLeftSideBarOpenByClick, leftSideBarOpenByClick, setSearchBarModalOpen, searchBarModalOpen, isDocSearchModalOpen} = useContext(Context);
|
||||||
|
|
||||||
const [expandLeftNav, setExpandLeftNav] = useState(false);
|
const [expandLeftNav, setExpandLeftNav] = useState(false);
|
||||||
const [activeOrgName, setActiveOrgName] = useState(
|
const [activeOrgName, setActiveOrgName] = useState(
|
||||||
@@ -526,7 +526,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
<Divider style={{ marginBottom: 10, }} />
|
<Divider style={{ marginBottom: 10, }} />
|
||||||
|
|
||||||
<Typography color="textSecondary" align="center" style={{ marginTop: 5, marginBottom: 5, fontSize: 18 }}>
|
<Typography color="textSecondary" align="center" style={{ marginTop: 5, marginBottom: 5, fontSize: 18 }}>
|
||||||
Version: 2.0.0
|
Version: 2.0.1
|
||||||
</Typography>
|
</Typography>
|
||||||
</Menu>
|
</Menu>
|
||||||
</span>
|
</span>
|
||||||
@@ -773,6 +773,9 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
|
|
||||||
}, [window?.location?.pathname]);
|
}, [window?.location?.pathname]);
|
||||||
|
|
||||||
|
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -785,12 +788,13 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
transition: "width 0.3s ease",
|
transition: "width 0.3s ease",
|
||||||
boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.2)" ,
|
boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.2)" ,
|
||||||
resize: 'both',
|
resize: 'both',
|
||||||
|
zoom: isSafari ? undefined : 0.8,
|
||||||
zoom: 0.8,
|
transform: isSafari ? "scale(0.8)" : undefined,
|
||||||
|
transformOrigin: isSafari ? "top left" : undefined,
|
||||||
height: "calc((100vh - 32px)*1.2)",
|
height: "calc((100vh - 32px)*1.2)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{searchBarModalOpen ? <ModalView serverside={serverside} userdata={userdata} searchBarModalOpen={searchBarModalOpen} setSearchBarModalOpen={setSearchBarModalOpen} globalUrl={globalUrl} /> : null}
|
{searchBarModalOpen && !isDocSearchModalOpen ? <ModalView serverside={serverside} userdata={userdata} searchBarModalOpen={searchBarModalOpen} setSearchBarModalOpen={setSearchBarModalOpen} globalUrl={globalUrl} isDocSearchModalOpen={isDocSearchModalOpen} /> : null}
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -1911,11 +1915,11 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default LeftSideBar;
|
export default LeftSideBar;
|
||||||
const ModalView = memo(({searchBarModalOpen, setSearchBarModalOpen, globalUrl, serverside, userdata}) => {
|
const ModalView = memo(({searchBarModalOpen, setSearchBarModalOpen, globalUrl, serverside, userdata, isDocSearchModalOpen}) => {
|
||||||
return (
|
return (
|
||||||
(
|
(
|
||||||
<Dialog
|
<Dialog
|
||||||
open={searchBarModalOpen}
|
open={searchBarModalOpen && !isDocSearchModalOpen}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setSearchBarModalOpen(false);
|
setSearchBarModalOpen(false);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -909,21 +909,23 @@ const LicencePopup = (props) => {
|
|||||||
const priceItem =
|
const priceItem =
|
||||||
window.location.origin === "https://shuffler.io/" || "https://sandbox.shuffler.io/"
|
window.location.origin === "https://shuffler.io/" || "https://sandbox.shuffler.io/"
|
||||||
? shuffleVariant === 0
|
? shuffleVariant === 0
|
||||||
? "app_executions"
|
? "price_1PWI3uDzMUgUjxHSffUBwWCy"
|
||||||
: "cores"
|
: "price_1PWI8EDzMUgUjxHSfEhUB7oL"
|
||||||
|
|
||||||
: shuffleVariant === 0
|
: shuffleVariant === 0
|
||||||
? "price_1PZPSSEJjT17t98NLJoTMYja"
|
? "price_1PZPSSEJjT17t98NLJoTMYja"
|
||||||
: "price_1PZPQuEJjT17t98N3yORUtd9";
|
: "price_1PZPQuEJjT17t98N3yORUtd9";
|
||||||
|
|
||||||
const successUrl = `${window.location.origin}/admin?admin_tab=billingstats&payment=success`
|
const successUrl = `${window.location.origin}/admin?admin_tab=billingstats&payment=success`
|
||||||
const failUrl = `${window.location.origin}/admin?admin_tab=billingstats&payment=failure`
|
const failUrl = `${window.location.origin}/admin?admin_tab=billingstats&payment=failure`
|
||||||
|
const quantity = shuffleVariant === 0 ? selectedValue / 100 : selectedValue
|
||||||
|
|
||||||
console.log("Priceitem: ", priceItem, shuffleVariant)
|
console.log("Priceitem: ", priceItem, quantity, shuffleVariant)
|
||||||
var checkoutObject = {
|
var checkoutObject = {
|
||||||
lineItems: [
|
lineItems: [
|
||||||
{
|
{
|
||||||
price: priceItem,
|
price: priceItem,
|
||||||
quantity: shuffleVariant === 0 ? selectedValue / 100 : selectedValue,
|
quantity: quantity,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
mode: "subscription",
|
mode: "subscription",
|
||||||
@@ -1141,6 +1143,7 @@ const LicencePopup = (props) => {
|
|||||||
>
|
>
|
||||||
View all plans
|
View all plans
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
style={{ borderRadius: 4, textTransform: "capitalize", color: "#1a1a1a", backgroundColor: "#ff8544", width: "100%", fontSize: 16}}
|
style={{ borderRadius: 4, textTransform: "capitalize", color: "#1a1a1a", backgroundColor: "#ff8544", width: "100%", fontSize: 16}}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
AppBar,
|
AppBar,
|
||||||
@@ -35,6 +35,7 @@ import { toast } from "react-toastify";
|
|||||||
import AddIcon from '@mui/icons-material/Add';
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
import Mousetrap from "mousetrap";
|
import Mousetrap from "mousetrap";
|
||||||
import LicencePopup from "../components/LicencePopup.jsx";
|
import LicencePopup from "../components/LicencePopup.jsx";
|
||||||
|
import { Context } from "../context/ContextApi.jsx";
|
||||||
|
|
||||||
const curpath = (typeof window !== "undefined" && window.location && typeof window.location.pathname === "string")
|
const curpath = (typeof window !== "undefined" && window.location && typeof window.location.pathname === "string")
|
||||||
? window.location.pathname
|
? window.location.pathname
|
||||||
@@ -47,7 +48,7 @@ const menuData = {
|
|||||||
title: "Shuffle",
|
title: "Shuffle",
|
||||||
description:
|
description:
|
||||||
"The most versatile automation engine with focus on security.",
|
"The most versatile automation engine with focus on security.",
|
||||||
icon: "images/icons/shuffleLogo.svg",
|
icon: "/images/icons/shuffleLogo.svg",
|
||||||
path: "/docs/about",
|
path: "/docs/about",
|
||||||
gaData: {
|
gaData: {
|
||||||
category: "navbar",
|
category: "navbar",
|
||||||
@@ -750,7 +751,7 @@ const Navbar = (props) => {
|
|||||||
const topbar_var = "topbar_closed10"
|
const topbar_var = "topbar_closed10"
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [searchBarModalOpen, setSearchBarModalOpen] = useState(false);
|
const {searchBarModalOpen, setSearchBarModalOpen, isDocSearchModalOpen} = useContext(Context)
|
||||||
const [pricingModalOpen, setPricingModalOpen] = useState(false);
|
const [pricingModalOpen, setPricingModalOpen] = useState(false);
|
||||||
const isTabletOrMobile = useMediaQuery(theme.breakpoints.down("lg"));
|
const isTabletOrMobile = useMediaQuery(theme.breakpoints.down("lg"));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down("md"));
|
const isMobile = useMediaQuery(theme.breakpoints.down("md"));
|
||||||
@@ -845,7 +846,7 @@ const Navbar = (props) => {
|
|||||||
|
|
||||||
const modalView = (
|
const modalView = (
|
||||||
<Dialog
|
<Dialog
|
||||||
open={searchBarModalOpen}
|
open={searchBarModalOpen && !isDocSearchModalOpen}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setSearchBarModalOpen(false);
|
setSearchBarModalOpen(false);
|
||||||
}}
|
}}
|
||||||
@@ -1287,10 +1288,21 @@ const Navbar = (props) => {
|
|||||||
<Button
|
<Button
|
||||||
onMouseEnter={() => handleMenuOpen(item)}
|
onMouseEnter={() => handleMenuOpen(item)}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e) => {
|
||||||
// Only close if not moving to dropdown
|
|
||||||
|
const dropdown = document.querySelector('.dropdown-content'); // Adjust the selector as needed
|
||||||
const rect = e.currentTarget.getBoundingClientRect();
|
const rect = e.currentTarget.getBoundingClientRect();
|
||||||
|
const dropdownRect = dropdown ? dropdown.getBoundingClientRect() : null;
|
||||||
|
|
||||||
|
// Check if the cursor is moving down
|
||||||
const isMovingDown = e.clientY > rect.bottom;
|
const isMovingDown = e.clientY > rect.bottom;
|
||||||
if (!isMovingDown) {
|
|
||||||
|
// Check if the cursor is within the dropdown area or a buffer zone
|
||||||
|
const isOverDropdown = dropdownRect && (
|
||||||
|
(e.clientY >= dropdownRect.top - 20 && e.clientY <= dropdownRect.bottom + 20) && // Buffer zone
|
||||||
|
(e.clientX >= dropdownRect.left && e.clientX <= dropdownRect.right)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isMovingDown && !isOverDropdown) {
|
||||||
handleMenuClose();
|
handleMenuClose();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -1352,6 +1364,11 @@ const Navbar = (props) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if(isCloud) {
|
if(isCloud) {
|
||||||
navigate("/pricing");
|
navigate("/pricing");
|
||||||
|
ReactGA.event({
|
||||||
|
category: "navbar",
|
||||||
|
action: "pricing_click",
|
||||||
|
label: "go_to_pricing",
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
window.open("https://shuffler.io/pricing", '_blank');
|
window.open("https://shuffler.io/pricing", '_blank');
|
||||||
return;
|
return;
|
||||||
@@ -1365,6 +1382,11 @@ const Navbar = (props) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if(isCloud) {
|
if(isCloud) {
|
||||||
navigate("/partners");
|
navigate("/partners");
|
||||||
|
ReactGA.event({
|
||||||
|
category: "navbar",
|
||||||
|
action: "partners_click",
|
||||||
|
label: "go_to_partners",
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
window.open("https://shuffler.io/partners", '_blank');
|
window.open("https://shuffler.io/partners", '_blank');
|
||||||
return;
|
return;
|
||||||
@@ -1722,7 +1744,11 @@ const Navbar = (props) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{topbar}
|
{topbar}
|
||||||
<Container maxWidth="xl">
|
<Container maxWidth="xl" sx={{ zoom: {
|
||||||
|
md: "0.7",
|
||||||
|
lg: "0.8",
|
||||||
|
xl: "1",
|
||||||
|
} }}>
|
||||||
<Toolbar disableGutters sx={{ justifyContent: "space-between" }}>
|
<Toolbar disableGutters sx={{ justifyContent: "space-between" }}>
|
||||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||||
<Link
|
<Link
|
||||||
|
|||||||
@@ -307,17 +307,16 @@ const OrgHeaderexpandedNew = (props) => {
|
|||||||
const setSelectedRegion = (region) => {
|
const setSelectedRegion = (region) => {
|
||||||
|
|
||||||
// send a POST request to /api/v1/orgs/{org_id}/region with the region as the body
|
// send a POST request to /api/v1/orgs/{org_id}/region with the region as the body
|
||||||
if (region === "US") {
|
const regionMap = {
|
||||||
region = "us-west2"
|
"US": "us-west2",
|
||||||
} else if (region === "EU") {
|
"EU": "europe-west2",
|
||||||
region = "europe-west2"
|
"CA": "northamerica-northeast1",
|
||||||
} else if (region === "CA") {
|
"UK": "europe-west2",
|
||||||
region = "northamerica-northeast1"
|
"EU-2": "europe-west3",
|
||||||
} else if (region === "UK") {
|
"AUS": "australia-southeast1"
|
||||||
region = "europe-west2"
|
};
|
||||||
} else if (region === "EU-2") {
|
|
||||||
region = "europe-west3"
|
region = regionMap[region] || region;
|
||||||
}
|
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
dst_region: region
|
dst_region: region
|
||||||
@@ -336,7 +335,11 @@ const OrgHeaderexpandedNew = (props) => {
|
|||||||
timeOut: 1000
|
timeOut: 1000
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
toast("Failed to change region!")
|
response.json().then((reason) => {
|
||||||
|
toast.error("Failed to change region: " + reason.reason)
|
||||||
|
}).catch((err) => {
|
||||||
|
toast.error("Failed to change region")
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
toast("Region changed successfully! Reloading in 5 seconds..")
|
toast("Region changed successfully! Reloading in 5 seconds..")
|
||||||
@@ -347,7 +350,7 @@ const OrgHeaderexpandedNew = (props) => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
// return responseJson
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1091,6 +1094,7 @@ const RegionChangeModal = memo(({ selectedOrganization, setSelectedRegion, userd
|
|||||||
"EU-2": "eu",
|
"EU-2": "eu",
|
||||||
"CA": "ca",
|
"CA": "ca",
|
||||||
"UK": "gb",
|
"UK": "gb",
|
||||||
|
"AUS": "au",
|
||||||
};
|
};
|
||||||
|
|
||||||
//let regiontag = "UK";
|
//let regiontag = "UK";
|
||||||
@@ -1112,6 +1116,9 @@ const RegionChangeModal = memo(({ selectedOrganization, setSelectedRegion, userd
|
|||||||
} else if (regiontag === "ca") {
|
} else if (regiontag === "ca") {
|
||||||
regiontag = "CA";
|
regiontag = "CA";
|
||||||
regionCode = "ca";
|
regionCode = "ca";
|
||||||
|
} else if (regiontag === "austrailia") {
|
||||||
|
regiontag = "AUS";
|
||||||
|
regionCode = "au"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1124,11 +1131,12 @@ const RegionChangeModal = memo(({ selectedOrganization, setSelectedRegion, userd
|
|||||||
value={regiontag}
|
value={regiontag}
|
||||||
style={{ minWidth: 120, height: 35, borderRadius: 4 }}
|
style={{ minWidth: 120, height: 35, borderRadius: 4 }}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
if (userdata?.support) {
|
// if (userdata?.support) {
|
||||||
setSelectedRegion(e.target.value)
|
// setSelectedRegion(e.target.value)
|
||||||
} else {
|
// } else {
|
||||||
handleSendChangeRegionMail(e.target.value)
|
// handleSendChangeRegionMail(e.target.value)
|
||||||
}
|
// }
|
||||||
|
setSelectedRegion(e.target.value)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{Object.keys(regionMapping).map((region, index) => {
|
{Object.keys(regionMapping).map((region, index) => {
|
||||||
@@ -1138,6 +1146,10 @@ const RegionChangeModal = memo(({ selectedOrganization, setSelectedRegion, userd
|
|||||||
selectedOrganization.region = "europe-west2";
|
selectedOrganization.region = "europe-west2";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (region === "AUS") {
|
||||||
|
region = "AUS (test)"
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the current region matches the selected region
|
// Check if the current region matches the selected region
|
||||||
if (region === selectedOrganization.region) {
|
if (region === selectedOrganization.region) {
|
||||||
// If the region matches, set the MenuItem as selected
|
// If the region matches, set the MenuItem as selected
|
||||||
|
|||||||
@@ -2551,7 +2551,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
{workflow.execution_variables !== undefined && workflow.execution_variables !== null && workflow.execution_variables.length > 0 ? (
|
{workflow.execution_variables !== undefined && workflow.execution_variables !== null && workflow.execution_variables.length > 0 ? (
|
||||||
<div style={{ marginTop: "20px" }}>
|
<div style={{ marginTop: "20px" }}>
|
||||||
<Typography>Execution variable (optional)</Typography>
|
<Typography color="textSecondary">Runtime variable (optional)</Typography>
|
||||||
<Select
|
<Select
|
||||||
MenuProps={{
|
MenuProps={{
|
||||||
disableScrollLock: true,
|
disableScrollLock: true,
|
||||||
|
|||||||
@@ -51,12 +51,13 @@ const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e52
|
|||||||
const SearchData = props => {
|
const SearchData = props => {
|
||||||
const { serverside, globalUrl, userdata } = props
|
const { serverside, globalUrl, userdata } = props
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
const { searchBarModalOpen, setSearchBarModalOpen } = useContext(Context);
|
const { searchBarModalOpen, setSearchBarModalOpen, isDocSearchModalOpen } = useContext(Context);
|
||||||
const borderRadius = 3
|
const borderRadius = 3
|
||||||
const node = useRef()
|
const node = useRef()
|
||||||
const [searchOpen, setSearchOpen] = useState(false)
|
const [searchOpen, setSearchOpen] = useState(false)
|
||||||
const [oldPath, setOldPath] = useState("")
|
const [oldPath, setOldPath] = useState("")
|
||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
|
const isDocSearchModal = isDocSearchModalOpen;
|
||||||
|
|
||||||
const handleLinkClick = () => {
|
const handleLinkClick = () => {
|
||||||
if (searchBarModalOpen) {
|
if (searchBarModalOpen) {
|
||||||
@@ -90,6 +91,8 @@ const SearchData = props => {
|
|||||||
const [inputValue, setInputValue] = useState(currentRefinement);
|
const [inputValue, setInputValue] = useState(currentRefinement);
|
||||||
|
|
||||||
const textFieldRef = useRef(null);
|
const textFieldRef = useRef(null);
|
||||||
|
const debounceTimeoutRef = useRef(null);
|
||||||
|
|
||||||
const keyPressHandler = (e) => {
|
const keyPressHandler = (e) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -110,10 +113,25 @@ const SearchData = props => {
|
|||||||
}, [searchOpen]);
|
}, [searchOpen]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentRefinement !== inputValue) {
|
// Clear any existing timeout to prevent multiple executions
|
||||||
refine(inputValue);
|
if (debounceTimeoutRef.current) {
|
||||||
|
clearTimeout(debounceTimeoutRef.current);
|
||||||
}
|
}
|
||||||
}, [currentRefinement]);
|
|
||||||
|
// Set a new timeout that will execute the search after a 200ms delay
|
||||||
|
debounceTimeoutRef.current = setTimeout(() => {
|
||||||
|
refine(inputValue);
|
||||||
|
setSearchOpen(inputValue.trim() !== '');
|
||||||
|
}, 200);
|
||||||
|
|
||||||
|
// Cleanup function that runs when component unmounts or when dependencies change
|
||||||
|
// This ensures we don't have any hanging timeouts
|
||||||
|
return () => {
|
||||||
|
if (debounceTimeoutRef.current) {
|
||||||
|
clearTimeout(debounceTimeoutRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [inputValue, refine]); // Effect runs when inputValue or refine function changes
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
@@ -122,7 +140,7 @@ const SearchData = props => {
|
|||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
style={{ zIndex: 1100, marginTop: -20, marginBottom: 200, position: "fixed", backgroundColor: theme.palette.inputColor, borderRadius: borderRadius, width: 685, }}
|
style={{ zIndex: 1100, marginTop: -20, marginBottom: 200, position: "fixed", backgroundColor: theme.palette.inputColor, borderRadius: borderRadius, width: 690, }}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
style: {
|
style: {
|
||||||
color: "white",
|
color: "white",
|
||||||
@@ -149,7 +167,7 @@ const SearchData = props => {
|
|||||||
autoComplete='off'
|
autoComplete='off'
|
||||||
type="search"
|
type="search"
|
||||||
color="primary"
|
color="primary"
|
||||||
placeholder="Find Public Apps, Workflows, Documentation..."
|
placeholder={isDocSearchModal ? "Type to search documentation..." : "Find Public Apps, Workflows, Documentation..."}
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
id="shuffle_search_field"
|
id="shuffle_search_field"
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
@@ -163,12 +181,6 @@ const SearchData = props => {
|
|||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
const newValue = event.target.value;
|
const newValue = event.target.value;
|
||||||
setInputValue(newValue);
|
setInputValue(newValue);
|
||||||
refine(newValue);
|
|
||||||
if (newValue.trim() !== '') {
|
|
||||||
setSearchOpen(true);
|
|
||||||
} else {
|
|
||||||
setSearchOpen(false);
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
onKeyDown={keyPressHandler}
|
onKeyDown={keyPressHandler}
|
||||||
inputRef={textFieldRef}
|
inputRef={textFieldRef}
|
||||||
@@ -605,7 +617,11 @@ const SearchData = props => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hits.length > 4) {
|
if (hits.length > 4) {
|
||||||
hits = hits.slice(0, 4)
|
if(!isDocSearchModal) {
|
||||||
|
hits = hits.slice(0, 4)
|
||||||
|
} else {
|
||||||
|
hits = hits.slice(0, 15)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const type = "documentation"
|
const type = "documentation"
|
||||||
@@ -614,15 +630,19 @@ const SearchData = props => {
|
|||||||
//console.log(type, hits.length, hits)
|
//console.log(type, hits.length, hits)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card elevation={0} style={{ marginRight: 10, marginTop: 50, color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: "100%", left: 470, boxShadows: "none", }}>
|
<Card elevation={0} style={{ marginRight: 10, marginTop: isDocSearchModal ? 0 : 50, color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: "100%", left: 470, boxShadows: "none", }}>
|
||||||
{/* <IconButton style={{ zIndex: 5000, position: "absolute", right: 14, color: "grey" }} onClick={() => {
|
{/* <IconButton style={{ zIndex: 5000, position: "absolute", right: 14, color: "grey" }} onClick={() => {
|
||||||
setSearchOpen(false)
|
setSearchOpen(false)
|
||||||
}}>
|
}}>
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton> */}
|
</IconButton> */}
|
||||||
<Typography variant="h6" style={{ margin: "10px 10px 0px 20px", color: "#FF8444", borderBottom: "1px solid", width: 152 }}>
|
{
|
||||||
Documentation
|
!isDocSearchModal && (
|
||||||
</Typography>
|
<Typography variant="h6" style={{ margin: "10px 10px 0px 20px", color: "#FF8444", borderBottom: "1px solid", width: 152 }}>
|
||||||
|
Documentation
|
||||||
|
</Typography>
|
||||||
|
)
|
||||||
|
}
|
||||||
{/*
|
{/*
|
||||||
<IconButton edge="end" aria-label="delete" style={{position: "absolute", top: 5, right: 15,}} onClick={() => {
|
<IconButton edge="end" aria-label="delete" style={{position: "absolute", top: 5, right: 15,}} onClick={() => {
|
||||||
setSearchOpen(false)
|
setSearchOpen(false)
|
||||||
@@ -630,7 +650,7 @@ const SearchData = props => {
|
|||||||
<DeleteIcon />
|
<DeleteIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
*/}
|
*/}
|
||||||
<List style={{ backgroundColor: theme.palette.inputColor, }}>
|
<List style={{ backgroundColor: theme.palette.inputColor, marginTop: isDocSearchModal ? 35 : 0, }}>
|
||||||
{hits.length === 0 ?
|
{hits.length === 0 ?
|
||||||
<ListItem style={outerlistitemStyle}>
|
<ListItem style={outerlistitemStyle}>
|
||||||
<ListItemAvatar onClick={() => console.log(hits)}>
|
<ListItemAvatar onClick={() => console.log(hits)}>
|
||||||
@@ -654,8 +674,8 @@ const SearchData = props => {
|
|||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
marginLeft: 5,
|
marginLeft: 5,
|
||||||
marginRight: 5,
|
marginRight: 5,
|
||||||
maxHeight: 75,
|
maxHeight: isDocSearchModal ? 100 : 75,
|
||||||
minHeight: 75,
|
minHeight: isDocSearchModal ? 100 : 75,
|
||||||
maxWidth: 420,
|
maxWidth: 420,
|
||||||
minWidth: "100%",
|
minWidth: "100%",
|
||||||
}
|
}
|
||||||
@@ -666,9 +686,13 @@ const SearchData = props => {
|
|||||||
(hit.name.charAt(0).toUpperCase() + hit.name.slice(1)).replaceAll("_", " ")
|
(hit.name.charAt(0).toUpperCase() + hit.name.slice(1)).replaceAll("_", " ")
|
||||||
|
|
||||||
if (name.length > 30) {
|
if (name.length > 30) {
|
||||||
name = name.slice(0, 30) + "..."
|
if(isDocSearchModal) {
|
||||||
|
name = name.slice(0, 70) + "..."
|
||||||
|
} else {
|
||||||
|
name = name.slice(0, 30) + "..."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const secondaryText = hit.data !== undefined ? hit.data.slice(0, 40) + "..." : ""
|
const secondaryText = hit.data !== undefined ? hit.data.slice(0, 80) + "..." : ""
|
||||||
const avatar = hit.image_url === undefined ?
|
const avatar = hit.image_url === undefined ?
|
||||||
baseImage
|
baseImage
|
||||||
:
|
:
|
||||||
@@ -719,7 +743,7 @@ const SearchData = props => {
|
|||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={name}
|
primary={name}
|
||||||
secondary={secondaryText}
|
secondary={<div style={{ padding: '8px 0' }}>{secondaryText}</div>}
|
||||||
/>
|
/>
|
||||||
{/*
|
{/*
|
||||||
<ListItemSecondaryAction>
|
<ListItemSecondaryAction>
|
||||||
@@ -897,28 +921,38 @@ const SearchData = props => {
|
|||||||
|
|
||||||
const modalView = (
|
const modalView = (
|
||||||
<div>
|
<div>
|
||||||
<Grid container style={{ display: "contents", }}>
|
{
|
||||||
<Grid item xs="auto" style={{}}>
|
!isDocSearchModal ? (
|
||||||
<Index indexName="appsearch">
|
<Grid container style={{ display: "contents", }}>
|
||||||
<CustomAppHits />
|
<Grid item xs="auto" style={{}}>
|
||||||
</Index>
|
<Index indexName="appsearch">
|
||||||
|
<CustomAppHits />
|
||||||
|
</Index>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs="auto" style={{}}>
|
||||||
|
<Index indexName="workflows">
|
||||||
|
<CustomWorkflowHits />
|
||||||
|
</Index>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs="auto" style={{}}>
|
||||||
|
<Index indexName="documentation">
|
||||||
|
<CustomDocHits />
|
||||||
|
</Index>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs="auto" style={{}}>
|
||||||
|
<Index indexName="discord_chat">
|
||||||
|
<CustomDiscordHits />
|
||||||
|
</Index>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs="auto" style={{}}>
|
) : (
|
||||||
<Index indexName="workflows">
|
<Grid item xs="auto" style={{width: "100%"}}>
|
||||||
<CustomWorkflowHits />
|
<Index indexName="documentation">
|
||||||
</Index>
|
<CustomDocHits />
|
||||||
</Grid>
|
</Index>
|
||||||
<Grid item xs="auto" style={{}}>
|
</Grid>
|
||||||
<Index indexName="documentation">
|
)
|
||||||
<CustomDocHits />
|
}
|
||||||
</Index>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs="auto" style={{}}>
|
|
||||||
<Index indexName="discord_chat">
|
|
||||||
<CustomDiscordHits />
|
|
||||||
</Index>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -932,7 +966,7 @@ const SearchData = props => {
|
|||||||
<CustomSearchBox />
|
<CustomSearchBox />
|
||||||
{modalView}
|
{modalView}
|
||||||
</InstantSearch>
|
</InstantSearch>
|
||||||
{gettingStartData}
|
{!isDocSearchModal && gettingStartData}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2476,7 +2476,8 @@ const CodeEditor = (props) => {
|
|||||||
var fixedcodedata = localcodedata
|
var fixedcodedata = localcodedata
|
||||||
const valid = validateJson(localcodedata, true)
|
const valid = validateJson(localcodedata, true)
|
||||||
if (valid.valid) {
|
if (valid.valid) {
|
||||||
fixedcodedata = JSON.stringify(valid.result, null, 2)
|
//fixedcodedata = JSON.stringify(valid.result, null, 2)
|
||||||
|
fixedcodedata = JSON.stringify(valid.result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log(codedata)
|
// console.log(codedata)
|
||||||
|
|||||||
@@ -398,8 +398,9 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
nodecolor = green
|
nodecolor = green
|
||||||
branchcolor = green
|
branchcolor = green
|
||||||
} else {
|
} else {
|
||||||
nodecolor = grey
|
// Green by default
|
||||||
branchcolor = grey
|
nodecolor = green
|
||||||
|
branchcolor = green
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nodecolor = green
|
nodecolor = green
|
||||||
@@ -561,8 +562,6 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
nodecolor = green
|
nodecolor = green
|
||||||
branchcolor = green
|
branchcolor = green
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var flex = index !== 0 && index !== relevantactions.length - 1 ? 1 : 3
|
var flex = index !== 0 && index !== relevantactions.length - 1 ? 1 : 3
|
||||||
if (nodecolor === green) {
|
if (nodecolor === green) {
|
||||||
@@ -609,6 +608,8 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
const ballsize = 8
|
const ballsize = 8
|
||||||
const topMargin = 20
|
const topMargin = 20
|
||||||
|
|
||||||
|
console.log("CHIP: ", index, chipColor, chipBackground)
|
||||||
|
|
||||||
const chipStyle = {
|
const chipStyle = {
|
||||||
height: 40,
|
height: 40,
|
||||||
minWidth: 125,
|
minWidth: 125,
|
||||||
@@ -676,7 +677,6 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
{founderror.length > 0 ? founderror : `App: ${appname} - Action: ${action.label}`}
|
{founderror.length > 0 ? founderror : `App: ${appname} - Action: ${action.label}`}
|
||||||
</Typography>
|
</Typography>
|
||||||
} placement="top">
|
} placement="top">
|
||||||
|
|
||||||
<Chip label={`${appname}`} style={chipStyle} icon={
|
<Chip label={`${appname}`} style={chipStyle} icon={
|
||||||
<Avatar
|
<Avatar
|
||||||
variant="round"
|
variant="round"
|
||||||
|
|||||||
@@ -7,11 +7,7 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
TextField,
|
TextField,
|
||||||
Grid,
|
Grid,
|
||||||
Skeleton,
|
Checkbox
|
||||||
Dialog,
|
|
||||||
DialogTitle,
|
|
||||||
DialogContent,
|
|
||||||
Box,
|
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { makeStyles } from "@mui/styles";
|
import { makeStyles } from "@mui/styles";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
@@ -30,6 +26,8 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
|||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [show2faSetup, setShow2faSetup] = React.useState(false);
|
const [show2faSetup, setShow2faSetup] = React.useState(false);
|
||||||
const [autoPrivision, setAutoProvision] = React.useState(selectedOrganization?.sso_config?.auto_provision)
|
const [autoPrivision, setAutoProvision] = React.useState(selectedOrganization?.sso_config?.auto_provision)
|
||||||
|
const [showOpenIdCred, setShowOpenIdCred] = React.useState(false);
|
||||||
|
const [showSamlCred, setShowSamlCred] = React.useState(false);
|
||||||
const [ssoEntrypoint, setSsoEntrypoint] = React.useState(
|
const [ssoEntrypoint, setSsoEntrypoint] = React.useState(
|
||||||
selectedOrganization.sso_config === undefined
|
selectedOrganization.sso_config === undefined
|
||||||
? ""
|
? ""
|
||||||
@@ -393,7 +391,27 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
|||||||
</span>
|
</span>
|
||||||
<Typography style={{ textAlign: "left", fontSize: 16, marginTop: 8, color: "rgba(158, 158, 158, 1)", fontWeight: 400 }}>
|
<Typography style={{ textAlign: "left", fontSize: 16, marginTop: 8, color: "rgba(158, 158, 158, 1)", fontWeight: 400 }}>
|
||||||
IdP URL for Shuffle OpenID: <Link to={`${globalUrl}/api/v1/login_openid`} target="_blank" style={{ color: "rgba(241, 241, 241, 1)", textDecoration: "none", fontSize: 16,}}>{`${globalUrl}/api/v1/login_openid`}</Link>
|
IdP URL for Shuffle OpenID: <Link to={`${globalUrl}/api/v1/login_openid`} target="_blank" style={{ color: "rgba(241, 241, 241, 1)", textDecoration: "none", fontSize: 16,}}>{`${globalUrl}/api/v1/login_openid`}</Link>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<div style={{ display: 'flex', marginTop: 10, }}>
|
||||||
|
<Typography
|
||||||
|
style={{
|
||||||
|
textAlign: "left",
|
||||||
|
fontSize: 16,
|
||||||
|
marginTop: 8,
|
||||||
|
color: "rgba(158, 158, 158, 1)",
|
||||||
|
fontWeight: 400,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Show OpenID Credentials
|
||||||
|
</Typography>
|
||||||
|
<Checkbox
|
||||||
|
checked={showOpenIdCred}
|
||||||
|
onChange={(e) => setShowOpenIdCred(e.target.checked)}
|
||||||
|
name="showOpenIdCred"
|
||||||
|
color="primary"
|
||||||
|
style={{ color: "rgba(255, 255, 255, 1)", }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<Grid container style={{ marginTop: 8, }} spacing={2}>
|
<Grid container style={{ marginTop: 8, }} spacing={2}>
|
||||||
<Grid item xs={6} style={{}}>
|
<Grid item xs={6} style={{}}>
|
||||||
<span>
|
<span>
|
||||||
@@ -407,30 +425,29 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
|||||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||||
}}
|
}}
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
type="name"
|
|
||||||
multiline={true}
|
multiline={true}
|
||||||
rows={2}
|
rows={2}
|
||||||
id="outlined-with-placeholder"
|
id="outlined-with-placeholder"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
placeholder="The OpenID client ID from the identity provider"
|
placeholder="The OpenID client ID from the identity provider"
|
||||||
value={openidClientId}
|
value={showOpenIdCred ? openidClientId : openidClientId?.length > 0 ? "•".repeat(50) : ""}
|
||||||
onChange={(e) => {
|
onChange={(e) => setOpenidClientId(e.target.value)}
|
||||||
setOpenidClientId(e.target.value);
|
onFocus={(e) => setShowOpenIdCred(true)}
|
||||||
}}
|
onBlur={(e) => setShowOpenIdCred(false)}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
classes: {
|
classes: {
|
||||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||||
},
|
},
|
||||||
style: {
|
style: {
|
||||||
color: "white",
|
color: "white",
|
||||||
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
|
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6} style={{}}>
|
<Grid item xs={6} style={{}}>
|
||||||
@@ -445,17 +462,19 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
|||||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||||
}}
|
}}
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
type="name"
|
type={showOpenIdCred ? "text" : "password"}
|
||||||
multiline={true}
|
multiline={true}
|
||||||
rows={2}
|
rows={2}
|
||||||
id="outlined-with-placeholder"
|
id="outlined-with-placeholder"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
placeholder="The OpenID client secret - DONT use this if dealing with implicit auth / PKCE"
|
placeholder="The OpenID client secret - DONT use this if dealing with implicit auth / PKCE"
|
||||||
value={openidClientSecret}
|
value={showOpenIdCred ? openidClientSecret : openidClientSecret?.length > 0 ? "•".repeat(50) : ""}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setOpenidClientSecret(e.target.value);
|
setOpenidClientSecret(e.target.value);
|
||||||
}}
|
}}
|
||||||
|
onFocus={(e) => setShowOpenIdCred(true)}
|
||||||
|
onBlur={(e) => setShowOpenIdCred(false)}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
classes: {
|
classes: {
|
||||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||||
@@ -485,17 +504,19 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
|||||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||||
}}
|
}}
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
type="name"
|
type={showOpenIdCred ? "text" : "password"}
|
||||||
id="outlined-with-placeholder"
|
id="outlined-with-placeholder"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
multiline={true}
|
multiline={true}
|
||||||
rows={2}
|
rows={2}
|
||||||
placeholder="The OpenID authorization URL (usually ends with /authorize)"
|
placeholder="The OpenID authorization URL (usually ends with /authorize)"
|
||||||
value={openidAuthorization}
|
value={showOpenIdCred ? openidAuthorization : openidAuthorization?.length > 0 ? "•".repeat(50) : ""}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setOpenidAuthorization(e.target.value)
|
setOpenidAuthorization(e.target.value)
|
||||||
}}
|
}}
|
||||||
|
onFocus={(e) => setShowOpenIdCred(true)}
|
||||||
|
onBlur={(e) => setShowOpenIdCred(false)}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
classes: {
|
classes: {
|
||||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||||
@@ -523,17 +544,19 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
|||||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||||
}}
|
}}
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
type="name"
|
type={showOpenIdCred ? "text" : "password"}
|
||||||
id="outlined-with-placeholder"
|
id="outlined-with-placeholder"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
multiline={true}
|
multiline={true}
|
||||||
rows={2}
|
rows={2}
|
||||||
placeholder="The OpenID token URL (usually ends with /token)"
|
placeholder="The OpenID token URL (usually ends with /token)"
|
||||||
value={openidToken}
|
value={showOpenIdCred ? openidToken : openidToken?.length > 0 ? "•".repeat(50) : ""}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setOpenidToken(e.target.value)
|
setOpenidToken(e.target.value)
|
||||||
}}
|
}}
|
||||||
|
onFocus={(e) => setShowOpenIdCred(true)}
|
||||||
|
onBlur={(e) => setShowOpenIdCred(false)}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
classes: {
|
classes: {
|
||||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||||
@@ -557,7 +580,27 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
|||||||
<Typography variant="h4" style={{ textAlign: "left", color: "rgba(241, 241, 241, 1)", fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontSize: 24, fontWeight: 600, }}>SAML SSO (v1.1)</Typography>
|
<Typography variant="h4" style={{ textAlign: "left", color: "rgba(241, 241, 241, 1)", fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontSize: 24, fontWeight: 600, }}>SAML SSO (v1.1)</Typography>
|
||||||
<Typography variant="body2" style={{ textAlign: "left", marginTop: 8, color: "rgba(241, 241, 241, 1)", fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontSize: 16, fontWeight: 400, color: "rgba(158, 158, 158, 1)" }} color="textSecondary">
|
<Typography variant="body2" style={{ textAlign: "left", marginTop: 8, color: "rgba(241, 241, 241, 1)", fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontSize: 16, fontWeight: 400, color: "rgba(158, 158, 158, 1)" }} color="textSecondary">
|
||||||
IdP URL for Shuffle SAML/SSO: <Link to={`${globalUrl}/api/v1/login_sso`} target="_blank" style={{ color: "rgba(241, 241, 241, 1)", textDecoration: "none" }}>{`${globalUrl}/api/v1/login_sso`}</Link>
|
IdP URL for Shuffle SAML/SSO: <Link to={`${globalUrl}/api/v1/login_sso`} target="_blank" style={{ color: "rgba(241, 241, 241, 1)", textDecoration: "none" }}>{`${globalUrl}/api/v1/login_sso`}</Link>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<div style={{ display: 'flex', marginTop: 10, }}>
|
||||||
|
<Typography
|
||||||
|
style={{
|
||||||
|
textAlign: "left",
|
||||||
|
fontSize: 16,
|
||||||
|
marginTop: 8,
|
||||||
|
color: "rgba(158, 158, 158, 1)",
|
||||||
|
fontWeight: 400,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Show SAML Credentials
|
||||||
|
</Typography>
|
||||||
|
<Checkbox
|
||||||
|
checked={showSamlCred}
|
||||||
|
onChange={(e) => setShowSamlCred(e.target.checked)}
|
||||||
|
name="showSamlCred"
|
||||||
|
color="primary"
|
||||||
|
style={{ color: "rgba(255, 255, 255, 1)", }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<Grid container style={{ marginTop: 10, }} spacing={2}>
|
<Grid container style={{ marginTop: 10, }} spacing={2}>
|
||||||
<Grid item xs={6} style={{}}>
|
<Grid item xs={6} style={{}}>
|
||||||
<span>
|
<span>
|
||||||
@@ -571,17 +614,19 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
|||||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||||
}}
|
}}
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
type="name"
|
type={showSamlCred ? "text" : "password"}
|
||||||
multiline={true}
|
multiline={true}
|
||||||
rows={2}
|
rows={2}
|
||||||
id="outlined-with-placeholder"
|
id="outlined-with-placeholder"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
placeholder="The entrypoint URL from your provider"
|
placeholder="The entrypoint URL from your provider"
|
||||||
value={ssoEntrypoint}
|
value={showSamlCred ? ssoEntrypoint : ssoEntrypoint?.length > 0 ? "•".repeat(50) : ""}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSsoEntrypoint(e.target.value);
|
setSsoEntrypoint(e.target.value);
|
||||||
}}
|
}}
|
||||||
|
onFocus={(e) => setShowSamlCred(true)}
|
||||||
|
onBlur={(e) => setShowSamlCred(false)}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
classes: {
|
classes: {
|
||||||
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
notchedOutline: isEditOrgTab ? null : classes.notchedOutline,
|
||||||
@@ -609,14 +654,16 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
|||||||
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor,
|
||||||
}}
|
}}
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
type="name"
|
type={showSamlCred ? "text" : "password"}
|
||||||
id="outlined-with-placeholder"
|
id="outlined-with-placeholder"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
multiline={true}
|
multiline={true}
|
||||||
rows={2}
|
rows={2}
|
||||||
placeholder="The X509 certificate to use"
|
placeholder="The X509 certificate to use"
|
||||||
value={ssoCertificate}
|
value={showSamlCred ? ssoCertificate : ssoCertificate?.length > 0 ? "•".repeat(50) : ""}
|
||||||
|
onFocus={(e) => setShowSamlCred(true)}
|
||||||
|
onBlur={(e) => setShowSamlCred(false)}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSsoCertificate(e.target.value);
|
setSsoCertificate(e.target.value);
|
||||||
}}
|
}}
|
||||||
@@ -646,4 +693,4 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SSOTab
|
export default SSOTab
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const AppContext = (props) => {
|
|||||||
|
|
||||||
// Left side bar global states
|
// Left side bar global states
|
||||||
const [searchBarModalOpen, setSearchBarModalOpen] = useState(false);
|
const [searchBarModalOpen, setSearchBarModalOpen] = useState(false);
|
||||||
|
const [isDocSearchModalOpen, setIsDocSearchModalOpen] = useState(false);
|
||||||
const [leftSideBarOpenByClick, setLeftSideBarOpenByClick] = useState(currentLocation?.includes('/workflows/') ? false : true)
|
const [leftSideBarOpenByClick, setLeftSideBarOpenByClick] = useState(currentLocation?.includes('/workflows/') ? false : true)
|
||||||
const [windowWidth, setWindowWidth] = useState(serverside === true ? 100 : window.innerWidth);
|
const [windowWidth, setWindowWidth] = useState(serverside === true ? 100 : window.innerWidth);
|
||||||
|
|
||||||
@@ -37,6 +38,8 @@ export const AppContext = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Context.Provider value={{
|
<Context.Provider value={{
|
||||||
|
isDocSearchModalOpen,
|
||||||
|
setIsDocSearchModalOpen,
|
||||||
searchBarModalOpen,
|
searchBarModalOpen,
|
||||||
setSearchBarModalOpen,
|
setSearchBarModalOpen,
|
||||||
leftSideBarOpenByClick,
|
leftSideBarOpenByClick,
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ const theme = createTheme(adaptV4Theme({
|
|||||||
singulBlackWhite: "/images/singul_black_white.png",
|
singulBlackWhite: "/images/singul_black_white.png",
|
||||||
},
|
},
|
||||||
typography: {
|
typography: {
|
||||||
fontFamily: `"Roboto", "Helvetica", "Arial", "inter", sans-serif`,
|
fontFamily: `"inter", "Roboto", "Helvetica", "Arial", sans-serif`,
|
||||||
useNextVariants: true,
|
useNextVariants: true,
|
||||||
fontWeightLight: 300,
|
fontWeightLight: 300,
|
||||||
fontWeightRegular: 400,
|
fontWeightRegular: 400,
|
||||||
|
|||||||
@@ -386,6 +386,8 @@ const useStyles = makeStyles({
|
|||||||
|
|
||||||
const splitter = "|~|";
|
const splitter = "|~|";
|
||||||
const svgSize = 24;
|
const svgSize = 24;
|
||||||
|
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||||
|
|
||||||
//const referenceUrl = "https://shuffler.io/functions/webhooks/"
|
//const referenceUrl = "https://shuffler.io/functions/webhooks/"
|
||||||
//const referenceUrl = window.location.origin+"/api/v1/hooks/"
|
//const referenceUrl = window.location.origin+"/api/v1/hooks/"
|
||||||
|
|
||||||
@@ -1320,33 +1322,45 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const allTriggersInOne = useTriggers.pipelines.concat(useTriggers.schedules).concat(useTriggers.webhooks)
|
const allTriggersInOne = useTriggers.pipelines.concat(useTriggers.schedules).concat(useTriggers.webhooks)
|
||||||
for (let triggerkey in allTriggersInOne) {
|
for (let triggerkey in allTriggersInOne) {
|
||||||
const curtrigger = allTriggersInOne[triggerkey]
|
const curtrigger = allTriggersInOne[triggerkey]
|
||||||
if (curtrigger.id === selectedTrigger.id) {
|
if (curtrigger.id !== selectedTrigger.id) {
|
||||||
if (curtrigger.status === undefined || curtrigger.status === null) {
|
continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curtrigger.running === undefined || curtrigger.running === null) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var changed = false
|
|
||||||
if (curtrigger.status !== selectedTrigger.status) {
|
|
||||||
changed = true
|
|
||||||
selectedTrigger.status = curtrigger.status
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curtrigger.running !== selectedTrigger.running) {
|
|
||||||
changed = true
|
|
||||||
selectedTrigger.running = curtrigger.running
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed) {
|
|
||||||
//console.log("TRIGGER FIX: ", selectedTrigger)
|
|
||||||
setSelectedTrigger(selectedTrigger)
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (curtrigger.status === undefined || curtrigger.status === null) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var changed = false
|
||||||
|
if (selectedTrigger?.parameters === undefined || selectedTrigger?.parameters === null) {
|
||||||
|
changed = true
|
||||||
|
|
||||||
|
if (selectedTrigger?.trigger_type === "SCHEDULE" && curtrigger?.frequency !== undefined && curtrigger?.frequency !== null) {
|
||||||
|
selectedTrigger.parameters = [{
|
||||||
|
name: "cron",
|
||||||
|
value: curtrigger.frequency,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "execution_argument",
|
||||||
|
value: curtrigger.argument,
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curtrigger.status !== selectedTrigger.status) {
|
||||||
|
changed = true
|
||||||
|
selectedTrigger.status = curtrigger.status
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curtrigger.running !== selectedTrigger.running) {
|
||||||
|
changed = true
|
||||||
|
selectedTrigger.running = curtrigger.running
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
setSelectedTrigger(selectedTrigger)
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2799,11 +2813,11 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
// FIXME: Check if any node contains $exec in a param
|
// FIXME: Check if any node contains $exec in a param
|
||||||
// If they do, show a popup asking if they want to execute it without an execution argument, or to use a previous one
|
// If they do, show a popup asking if they want to execute it without an execution argument, or to use a previous one
|
||||||
if (skip_popup !== true && executionArgument === undefined || executionArgument === null || executionArgument.length === 0)
|
if (skip_popup !== true && executionArgument === undefined || executionArgument === null || executionArgument?.length === 0)
|
||||||
|
|
||||||
if (workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) {
|
if (workflow?.actions !== undefined && workflow?.actions !== null && workflow?.actions?.length > 0) {
|
||||||
var foundmissing = false
|
var foundmissing = false
|
||||||
for (let actionkey in workflow.actions) {
|
for (let actionkey in workflow?.actions) {
|
||||||
if (workflow.actions[actionkey].parameters === undefined || workflow.actions[actionkey].parameters === null || workflow.actions[actionkey].parameters.length === 0) {
|
if (workflow.actions[actionkey].parameters === undefined || workflow.actions[actionkey].parameters === null || workflow.actions[actionkey].parameters.length === 0) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -12236,7 +12250,9 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
overflowAnchor: "none",
|
overflowAnchor: "none",
|
||||||
minWidth: minSize,
|
minWidth: minSize,
|
||||||
width: isMobile ? "100%" : minSize,
|
width: isMobile ? "100%" : minSize,
|
||||||
zoom: 0.9,
|
zoom: isSafari ? undefined : 0.9,
|
||||||
|
transform: isSafari ? "scale(0.9)" : undefined,
|
||||||
|
transformOrigin: isSafari ? "top right" : undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const setTriggerFolderWrapperMulti = (event) => {
|
const setTriggerFolderWrapperMulti = (event) => {
|
||||||
@@ -18011,10 +18027,10 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const topBarStyle = {
|
const topBarStyle = {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
|
|
||||||
top: isMobile ? 30 : 25,
|
top: isMobile ? 30 : isSafari ? 15 : 25,
|
||||||
transform: isMobile ? "translateX(20px)" : `translateX(${leftBarSize}px)`,
|
transform: isMobile ? "translateX(20px)" : `translateX(${leftBarSize}px)`,
|
||||||
transition: "all 0.3s ease",
|
transition: "all 0.3s ease",
|
||||||
zoom: 0.9,
|
zoom: isSafari ? undefined : 0.9,
|
||||||
}
|
}
|
||||||
|
|
||||||
const TopCytoscapeBar = (props) => {
|
const TopCytoscapeBar = (props) => {
|
||||||
@@ -21834,13 +21850,23 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||||
const chosenNodeId = new URLSearchParams(cursearch).get("node");
|
const chosenNodeId = new URLSearchParams(cursearch).get("node");
|
||||||
const highlightNode = chosenNodeId !== null && chosenNodeId !== undefined && chosenNodeId !== "" && chosenNodeId === data.action.id
|
const highlightNode = chosenNodeId !== null && chosenNodeId !== undefined && chosenNodeId !== "" && chosenNodeId === data.action.id
|
||||||
|
var relevant_errors = []
|
||||||
|
if (data?.action?.parameters !== undefined && data?.action?.parameters !== null && data?.action?.parameters.length > 0) {
|
||||||
|
for (var i = 0; i < data.action.parameters.length; i++) {
|
||||||
|
// Specific error patterns in params
|
||||||
|
const param = data.action.parameters[i]
|
||||||
|
if (param?.name?.endsWith("_error") && (param?.name?.startsWith("shuffle_") || param?.name?.startsWith("liquid_"))) {
|
||||||
|
relevant_errors.push(param)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
style={{
|
style={{
|
||||||
marginBottom: 20,
|
marginBottom: 20,
|
||||||
border: highlightNode ? "2px solid red"
|
border: highlightNode ? `2px solid ${red}`
|
||||||
:
|
:
|
||||||
data.action.sub_action === true
|
data.action.sub_action === true
|
||||||
? "1px solid rgba(255,255,255,0.3)"
|
? "1px solid rgba(255,255,255,0.3)"
|
||||||
@@ -21913,11 +21939,17 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
>
|
>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
color="primary"
|
color="primary"
|
||||||
title="Expand result window"
|
title={
|
||||||
|
<Typography variant="body1">
|
||||||
|
Expand result window. Errors: {relevant_errors.length}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
placement="top"
|
placement="top"
|
||||||
style={{ zIndex: 50000 }}
|
style={{ zIndex: 50000 }}
|
||||||
>
|
>
|
||||||
<ArrowLeftIcon style={{ color: "white" }} />
|
<ArrowLeftIcon style={{
|
||||||
|
color: relevant_errors.length > 0 ? yellow : "rgba(255,255,255,0.7)",
|
||||||
|
}} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
{actionimg}
|
{actionimg}
|
||||||
@@ -22087,6 +22119,11 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const checked = validateJson(data.value.trim())
|
const checked = validateJson(data.value.trim())
|
||||||
|
|
||||||
if (data.name === "shuffle_action_logs" && data.value !== undefined && data.value !== null && data.value.length > 0 && data.value.includes("add env SHUFFLE_LOGS_DISABLED")) {
|
if (data.name === "shuffle_action_logs" && data.value !== undefined && data.value !== null && data.value.length > 0 && data.value.includes("add env SHUFFLE_LOGS_DISABLED")) {
|
||||||
|
|
||||||
|
if (isCloud) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ maxWidth: 600, marginTop: 75, overflowX: "hidden", }}>
|
<div style={{ maxWidth: 600, marginTop: 75, overflowX: "hidden", }}>
|
||||||
<Typography
|
<Typography
|
||||||
|
|||||||
+179
-23
@@ -23,7 +23,12 @@ import {
|
|||||||
List,
|
List,
|
||||||
Collapse,
|
Collapse,
|
||||||
ListItemButton,
|
ListItemButton,
|
||||||
ListItemText
|
ListItemText,
|
||||||
|
Dialog,
|
||||||
|
DialogTitle,
|
||||||
|
Box,
|
||||||
|
DialogContent,
|
||||||
|
InputAdornment
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import {
|
import {
|
||||||
Link as LinkIcon,
|
Link as LinkIcon,
|
||||||
@@ -32,9 +37,12 @@ import {
|
|||||||
ExpandMore as ExpandMoreIcon,
|
ExpandMore as ExpandMoreIcon,
|
||||||
FileCopy as FileCopyIcon,
|
FileCopy as FileCopyIcon,
|
||||||
ChevronLeft,
|
ChevronLeft,
|
||||||
ChevronRight
|
ChevronRight,
|
||||||
|
Search as SearchIcon,
|
||||||
|
Close as CloseIcon
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import { fontGrid } from "@mui/material/styles/cssUtils.js";
|
import { fontGrid } from "@mui/material/styles/cssUtils.js";
|
||||||
|
import SearchBox from "../components/SearchData.jsx";
|
||||||
|
|
||||||
const Body = {
|
const Body = {
|
||||||
//maxWidth: 1000,
|
//maxWidth: 1000,
|
||||||
@@ -158,12 +166,13 @@ export const OuterLink = (props) => {
|
|||||||
|
|
||||||
export const Img = (props) => {
|
export const Img = (props) => {
|
||||||
// Find parent container and check width
|
// Find parent container and check width
|
||||||
const isArticlePage = window.location.pathname.includes("/articles/");
|
const isArticlePage = window.location.pathname.includes("/articles/")
|
||||||
|
const isFormPage = window.location.pathname.includes("/forms/")
|
||||||
var height = "auto"
|
var height = "auto"
|
||||||
var width = isArticlePage ? 1000 : 750
|
var width = isArticlePage ? 1000 : isFormPage ? 400: 750
|
||||||
|
|
||||||
const docsImageStyle = {
|
const docsImageStyle = {
|
||||||
border: "1px solid rgba(255,255,255,0.3)",
|
border: isFormPage ? null : "1px solid rgba(255,255,255,0.3)",
|
||||||
borderRadius: theme.palette?.borderRadius,
|
borderRadius: theme.palette?.borderRadius,
|
||||||
width: width,
|
width: width,
|
||||||
maxWidth: width,
|
maxWidth: width,
|
||||||
@@ -191,11 +200,13 @@ export const Img = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<img
|
<div style={{width: "100%", textAlign: "center", }}>
|
||||||
style={isArticlePage ? articleImageStyle : docsImageStyle}
|
<img
|
||||||
alt={props.alt}
|
style={isArticlePage ? articleImageStyle : docsImageStyle}
|
||||||
src={props.src}
|
alt={props.alt}
|
||||||
/>
|
src={props.src}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +289,7 @@ export const CodeHandler = (props) => {
|
|||||||
const Docs = (defaultprops) => {
|
const Docs = (defaultprops) => {
|
||||||
const { globalUrl, selectedDoc, serverside, serverMobile, isLoggedIn, isLoaded, userdata } = defaultprops;
|
const { globalUrl, selectedDoc, serverside, serverMobile, isLoggedIn, isLoaded, userdata } = defaultprops;
|
||||||
|
|
||||||
console.log("\n\nSELECTED DOC\n", selectedDoc, "\n\n")
|
const { searchBarModalOpen, setSearchBarModalOpen, isDocSearchModalOpen, setIsDocSearchModalOpen, leftSideBarOpenByClick } = useContext(Context);
|
||||||
|
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@@ -316,20 +327,36 @@ const Docs = (defaultprops) => {
|
|||||||
const [activeSubItem, setActiveSubItem] = useState(false);
|
const [activeSubItem, setActiveSubItem] = useState(false);
|
||||||
const headingElementsRef = useRef({})
|
const headingElementsRef = useRef({})
|
||||||
var isArticlePage = window.location.pathname.includes("/articles/") || window.location.pathname === "/articles" ? true : false;
|
var isArticlePage = window.location.pathname.includes("/articles/") || window.location.pathname === "/articles" ? true : false;
|
||||||
|
const searchFieldRef = useRef(null);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchDocList();
|
fetchDocList();
|
||||||
setSidebarOpen(false);
|
setSidebarOpen(false);
|
||||||
|
|
||||||
|
if (props.match.params === undefined || props.match.params === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const propkey = props.match.params.key
|
||||||
|
if (propkey === undefined || propkey === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (location.pathname.includes("/docs/")) {
|
||||||
|
if (propkey === "cookie_policy" || propkey === "compliance" || propkey === "privacy_policy" || propkey === "terms_of_service") {
|
||||||
|
navigate(`/legal/${propkey}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
}, [location]);
|
}, [location]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//if (params["key"] === undefined) {
|
return () => {
|
||||||
// navigate("/docs/about")
|
setIsDocSearchModalOpen(false);
|
||||||
// return
|
setSearchBarModalOpen(false);
|
||||||
//}
|
};
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
const handleClick = (event) => {
|
const handleClick = (event) => {
|
||||||
setAnchorEl(event.currentTarget);
|
setAnchorEl(event.currentTarget);
|
||||||
}
|
}
|
||||||
@@ -459,6 +486,71 @@ const Docs = (defaultprops) => {
|
|||||||
return headings;
|
return headings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const modalView = (
|
||||||
|
<Dialog
|
||||||
|
open={searchBarModalOpen && isDocSearchModalOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setSearchBarModalOpen(false);
|
||||||
|
if (searchFieldRef.current) {
|
||||||
|
searchFieldRef.current.blur();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
PaperProps={{
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
minWidth: 750,
|
||||||
|
minHeight: "180px",
|
||||||
|
maxHeight: "85vh",
|
||||||
|
borderRadius: 16,
|
||||||
|
border: "1px solid var(--Container-Stroke, #494949)",
|
||||||
|
background: "var(--Container, #000000)",
|
||||||
|
boxShadow: "0px 16px 24px 8px rgba(0, 0, 0, 0.25)",
|
||||||
|
position: "fixed",
|
||||||
|
top: "70px",
|
||||||
|
left: "50%",
|
||||||
|
transform: "translateX(-50%)",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
zIndex: 50005,
|
||||||
|
'& .MuiBackdrop-root': {
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", px: 2, pr: 3, pt: 2 }}>
|
||||||
|
<DialogTitle
|
||||||
|
sx={{
|
||||||
|
color: "var(--Paragraph-text, #C8C8C8)",
|
||||||
|
p: 0,
|
||||||
|
m: 0,
|
||||||
|
ml: 1.5,
|
||||||
|
fontFamily: theme.typography.fontFamily,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Search for Documentation
|
||||||
|
</DialogTitle>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => setSearchBarModalOpen(false)}
|
||||||
|
sx={{
|
||||||
|
color: 'white',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.1)'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
<DialogContent>
|
||||||
|
<Box sx={{ pt: 3 }}>
|
||||||
|
<SearchBox globalUrl={globalUrl} serverside={serverside} userdata={userdata} />
|
||||||
|
</Box>
|
||||||
|
</DialogContent>
|
||||||
|
<Divider sx={{ backgroundColor: 'rgba(255, 255, 255, 0.1)' }}/>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// extract TOC from actual markdown
|
// extract TOC from actual markdown
|
||||||
const tocvalue = (markdown) => {
|
const tocvalue = (markdown) => {
|
||||||
@@ -761,7 +853,13 @@ const Docs = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fetchDocList = (resetCache = false) => {
|
const fetchDocList = (resetCache = false) => {
|
||||||
const url = isArticlePage ? `${globalUrl}/api/v1/articles?resetCache=${resetCache}` : `${globalUrl}/api/v1/docs`;
|
var url = `${globalUrl}/api/v1/docs`
|
||||||
|
if (location.pathname.includes("/legal")) {
|
||||||
|
url = `${globalUrl}/api/v1/docs?folder=legal&resetCache=${resetCache}`
|
||||||
|
} else if (location.pathname.includes("/articles")) {
|
||||||
|
url = `${globalUrl}/api/v1/docs?folder=articles&resetCache=${resetCache}`
|
||||||
|
}
|
||||||
|
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -782,8 +880,18 @@ const Docs = (defaultprops) => {
|
|||||||
.catch((error) => { });
|
.catch((error) => { });
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchDocs = (docId) => {
|
const fetchDoc = (docId) => {
|
||||||
const url = isArticlePage ? `${globalUrl}/api/v1/articles/${docId}` : `${globalUrl}/api/v1/docs/${docId}`;
|
if (docId === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = `${globalUrl}/api/v1/docs/${docId}`
|
||||||
|
if (location.pathname.includes("/legal")) {
|
||||||
|
url = `${globalUrl}/api/v1/docs/${docId}?folder=legal`
|
||||||
|
} else if (location.pathname.includes("/articles")) {
|
||||||
|
url = `${globalUrl}/api/v1/docs/${docId}?folder=articles`
|
||||||
|
}
|
||||||
|
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -902,7 +1010,7 @@ const Docs = (defaultprops) => {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log("DOCID: ", props.match.params.key)
|
console.log("DOCID: ", props.match.params.key)
|
||||||
fetchDocs(props.match.params.key)
|
fetchDoc(props.match.params.key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -911,7 +1019,7 @@ const Docs = (defaultprops) => {
|
|||||||
// Handles search-based changes that origin from outside this file
|
// Handles search-based changes that origin from outside this file
|
||||||
if (serverside !== true && window.location.href !== baseUrl) {
|
if (serverside !== true && window.location.href !== baseUrl) {
|
||||||
setBaseUrl(window.location.href);
|
setBaseUrl(window.location.href);
|
||||||
fetchDocs(props.match.params.key);
|
fetchDoc(props.match.params.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
const markdownStyle = {
|
const markdownStyle = {
|
||||||
@@ -1093,9 +1201,50 @@ const Docs = (defaultprops) => {
|
|||||||
<div style={Body}>
|
<div style={Body}>
|
||||||
<div style={!isArticlePage ? SideBar : (sidebarOpen ? SideBar : collapsedSideBar)}>
|
<div style={!isArticlePage ? SideBar : (sidebarOpen ? SideBar : collapsedSideBar)}>
|
||||||
<Paper style={SidebarPaperStyle}>
|
<Paper style={SidebarPaperStyle}>
|
||||||
|
{modalView}
|
||||||
|
{
|
||||||
|
!isArticlePage && (
|
||||||
|
<TextField
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="Search Docs..."
|
||||||
|
size="small"
|
||||||
|
onClick={() => {
|
||||||
|
setIsDocSearchModalOpen(true)
|
||||||
|
setSearchBarModalOpen(true)
|
||||||
|
}}
|
||||||
|
inputRef={searchFieldRef}
|
||||||
|
InputProps={{
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<SearchIcon style={{ color: "white" }} />
|
||||||
|
</InputAdornment>
|
||||||
|
),
|
||||||
|
style: {
|
||||||
|
backgroundColor: "#212121",
|
||||||
|
borderRadius: 4,
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
marginTop: 10,
|
||||||
|
marginLeft: 10,
|
||||||
|
borderRadius: 4,
|
||||||
|
width: !isLoggedIn ? "14%" : !leftSideBarOpenByClick ? "12%" : "11%",
|
||||||
|
maxWidth: "285px",
|
||||||
|
position: "fixed",
|
||||||
|
zIndex: 1100,
|
||||||
|
}}
|
||||||
|
inputProps={{
|
||||||
|
readOnly: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
<List style={{
|
<List style={{
|
||||||
listStyle: "none",
|
listStyle: "none",
|
||||||
paddingLeft: "0",
|
paddingLeft: "0",
|
||||||
|
paddingTop: !isArticlePage ? "60px" : undefined,
|
||||||
|
paddingBottom: !isArticlePage ? "30px" : undefined,
|
||||||
display: isArticlePage ? sidebarOpen ? "block" : "none" : undefined,
|
display: isArticlePage ? sidebarOpen ? "block" : "none" : undefined,
|
||||||
opacity: isArticlePage ? sidebarOpen ? 1 : 0 : undefined,
|
opacity: isArticlePage ? sidebarOpen ? 1 : 0 : undefined,
|
||||||
transition: isArticlePage ? "opacity 0.3s ease" : undefined,
|
transition: isArticlePage ? "opacity 0.3s ease" : undefined,
|
||||||
@@ -1106,7 +1255,14 @@ const Docs = (defaultprops) => {
|
|||||||
if (item === undefined) {
|
if (item === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const path = "/docs/" + item;
|
|
||||||
|
var path = "/docs/" + item;
|
||||||
|
if (location.pathname.includes("/legal")) {
|
||||||
|
path = "/legal/" + item
|
||||||
|
} else if (location.pathname.includes("/articles")) {
|
||||||
|
path = "/articles/" + item
|
||||||
|
}
|
||||||
|
|
||||||
const newname =
|
const newname =
|
||||||
item.charAt(0).toUpperCase() +
|
item.charAt(0).toUpperCase() +
|
||||||
item.substring(1).split("_").join(" ").split("-").join(" ");
|
item.substring(1).split("_").join(" ").split("-").join(" ");
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import { useNavigate, Link, useParams } from "react-router-dom";
|
|||||||
import { isMobile } from "react-device-detect";
|
import { isMobile } from "react-device-detect";
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { useInterval } from "react-powerhooks";
|
import { useInterval } from "react-powerhooks";
|
||||||
|
import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
|
||||||
|
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
|
||||||
import {
|
import {
|
||||||
ConnectingAirportsOutlined,
|
ConnectingAirportsOutlined,
|
||||||
ConstructionOutlined,
|
ConstructionOutlined,
|
||||||
@@ -81,21 +81,6 @@ const useStyles = makeStyles({
|
|||||||
notchedOutline: {
|
notchedOutline: {
|
||||||
borderColor: "#f85a3e !important"
|
borderColor: "#f85a3e !important"
|
||||||
},
|
},
|
||||||
marketplaceButton: {
|
|
||||||
width: "100%",
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
padding: "12px",
|
|
||||||
marginBottom: "12px",
|
|
||||||
backgroundColor: "#1A1A1A",
|
|
||||||
border: "1px solid #494949",
|
|
||||||
borderRadius: "8px",
|
|
||||||
color: "white",
|
|
||||||
opacity: 0.7,
|
|
||||||
'&:hover': {
|
|
||||||
opacity: 1,
|
|
||||||
cursor: "not-allowed",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
marketplaceIcon: {
|
marketplaceIcon: {
|
||||||
width: 28,
|
width: 28,
|
||||||
height: 28,
|
height: 28,
|
||||||
@@ -174,6 +159,14 @@ const FreePlanCard = ({ classes }) => {
|
|||||||
|
|
||||||
const MarketplaceCard = ({ classes }) => {
|
const MarketplaceCard = ({ classes }) => {
|
||||||
const marketplaceOptions = [
|
const marketplaceOptions = [
|
||||||
|
{
|
||||||
|
name: "Open Source Install",
|
||||||
|
logo: "https://static.cdnlogo.com/logos/g/69/github-icon.svg",
|
||||||
|
tooltipText: "Click to install!",
|
||||||
|
valid: true,
|
||||||
|
|
||||||
|
link: "https://github.com/shuffle/shuffle/blob/main/.github/install-guide.md"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Amazon Web Services",
|
name: "Amazon Web Services",
|
||||||
logo: "https://cdn.cdnlogo.com/logos/a/19/aws.svg",
|
logo: "https://cdn.cdnlogo.com/logos/a/19/aws.svg",
|
||||||
@@ -213,31 +206,50 @@ const MarketplaceCard = ({ classes }) => {
|
|||||||
Self Host
|
Self Host
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
{marketplaceOptions.map((option, index) => (
|
{marketplaceOptions.map((option, index) => {
|
||||||
<Tooltip
|
return (
|
||||||
key={index}
|
<Tooltip
|
||||||
title={option.tooltipText}
|
key={index}
|
||||||
placement="top"
|
title={option.tooltipText}
|
||||||
arrow
|
placement="top"
|
||||||
>
|
arrow
|
||||||
<button
|
|
||||||
className={classes.marketplaceButton}
|
|
||||||
disabled
|
|
||||||
>
|
>
|
||||||
<img
|
<button
|
||||||
src={option.logo}
|
onClick={() => {
|
||||||
alt={option.name}
|
if (option.valid === true) {
|
||||||
className={classes.marketplaceIcon}
|
window.open(option.link, "_blank")
|
||||||
style={{
|
}
|
||||||
filter: option.valid === true ? null : "grayscale(1)",
|
|
||||||
}}
|
}}
|
||||||
/>
|
style={{
|
||||||
<Typography className={classes.marketplaceText}>
|
width: "100%",
|
||||||
{option.name}
|
justifyContent: "flex-start",
|
||||||
</Typography>
|
padding: "12px",
|
||||||
</button>
|
marginBottom: "12px",
|
||||||
</Tooltip>
|
backgroundColor: "#1A1A1A",
|
||||||
))}
|
border: "1px solid #494949",
|
||||||
|
borderRadius: "8px",
|
||||||
|
color: "white",
|
||||||
|
opacity: 0.7,
|
||||||
|
cursor: option.valid === true ? "pointer" : "not-allowed",
|
||||||
|
}}
|
||||||
|
disabled={option.valid === false}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={option.logo}
|
||||||
|
alt={option.name}
|
||||||
|
className={classes.marketplaceIcon}
|
||||||
|
style={{
|
||||||
|
filter: option.valid === true ? null : "grayscale(1)",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography className={classes.marketplaceText}>
|
||||||
|
{option.name}
|
||||||
|
</Typography>
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
|
||||||
<div style={{
|
<div style={{
|
||||||
marginTop: "0.5rem",
|
marginTop: "0.5rem",
|
||||||
@@ -256,7 +268,7 @@ const MarketplaceCard = ({ classes }) => {
|
|||||||
</a>
|
</a>
|
||||||
*/}
|
*/}
|
||||||
<a
|
<a
|
||||||
href="/docs/configuration#installing-shuffle"
|
href="/docs/configuration#installation"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
style={{ color: "rgba(255, 132, 68, 1)", textDecoration: "underline" }}
|
style={{ color: "rgba(255, 132, 68, 1)", textDecoration: "underline" }}
|
||||||
>
|
>
|
||||||
@@ -282,7 +294,7 @@ const LoginPage = props => {
|
|||||||
const [register, setRegister] = useState(inregister);
|
const [register, setRegister] = useState(inregister);
|
||||||
const [checkboxClicked, setCheckboxClicked] = useState(false);
|
const [checkboxClicked, setCheckboxClicked] = useState(false);
|
||||||
const [loginWithSSO, setLoginWithSSO] = useState(false)
|
const [loginWithSSO, setLoginWithSSO] = useState(false)
|
||||||
|
const [showPassword, setShowPassword] = useState(false)
|
||||||
const [ssoUrl, setSSOUrl] = useState("");
|
const [ssoUrl, setSSOUrl] = useState("");
|
||||||
|
|
||||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "migration.shuffler.io";
|
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "migration.shuffler.io";
|
||||||
@@ -315,7 +327,15 @@ const LoginPage = props => {
|
|||||||
} else {
|
} else {
|
||||||
document.title = "Register to Shuffle SaaS"
|
document.title = "Register to Shuffle SaaS"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
if (loginWithSSO && window?.location?.pathname === "/register") {
|
||||||
|
setLoginWithSSO(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
},[window?.location?.pathname])
|
||||||
|
|
||||||
// Just a way to force location loading properly
|
// Just a way to force location loading properly
|
||||||
// Register & login should be split :3
|
// Register & login should be split :3
|
||||||
@@ -354,7 +374,8 @@ const LoginPage = props => {
|
|||||||
color: "white",
|
color: "white",
|
||||||
padding: "40px",
|
padding: "40px",
|
||||||
flex: 1,
|
flex: 1,
|
||||||
maxWidth: isMobile ? "100%" : "550px",
|
maxWidth: isMobile ? "100%" : 410,
|
||||||
|
minWidth: 410,
|
||||||
background: "#212121",
|
background: "#212121",
|
||||||
borderRadius: "12px",
|
borderRadius: "12px",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -461,7 +482,6 @@ const LoginPage = props => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const onSubmit = (e) => {
|
const onSubmit = (e) => {
|
||||||
//toast("Testing from login page")
|
//toast("Testing from login page")
|
||||||
|
|
||||||
@@ -650,26 +670,16 @@ const LoginPage = props => {
|
|||||||
setLoginWithSSO(true)
|
setLoginWithSSO(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
//const onClickRegister = () => {
|
|
||||||
// if (props.location.pathname === "/login") {
|
|
||||||
// window.location.pathname = "/register"
|
|
||||||
// } else {
|
|
||||||
// window.location.pathname = "/login"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// setLoginCheck(!register)
|
|
||||||
//}
|
|
||||||
|
|
||||||
//var loginChange = register ? (<div><p onClick={setLoginCheck(false)}>Want to register? Click here.</p></div>) : (<div><p onClick={setLoginCheck(true)}>Go back to login? Click here.</p></div>);
|
|
||||||
var formtitle = register ? <div>Welcome Back!</div> : <div>Create your account</div>
|
var formtitle = register ? <div>Welcome Back!</div> : <div>Create your account</div>
|
||||||
var formButton = !isCloud ? "" : register ? <div style={{ display: "flex" }}> <div style={{ fontSize: "14px", paddingRight: "7px", textDecoration: "none", }}>Don’t have an account yet?</div> <Link style={hrefStyle} to={`/register${parsedsearch}`}><div>Register here</div></Link></div> : <>
|
var formButton = !isCloud ? "" : register ? <div style={{ display: "flex" }}> <div style={{ fontSize: "14px", paddingRight: "7px", textDecoration: "none", }}>Don’t have an account yet?</div> <Link style={hrefStyle} to={`/register${parsedsearch}`}><div>Register here</div></Link></div> : <>
|
||||||
|
|
||||||
<div style={{ display: "flex", marginTop: 40, marginBottom: -10 }}> <div style={{ fontSize: "14px", paddingRight: "7px", textDecoration: "none", }}>Already have an account?</div> <Link style={hrefStyle} to={`/login${parsedsearch}`}><div>Login here</div></Link></div>
|
<div style={{ display: "flex", marginTop: 40, marginBottom: -10 }}> <div style={{ fontSize: "14px", paddingRight: "7px", textDecoration: "none", }}>Already have an account?</div> <Link style={hrefStyle} to={`/login${parsedsearch}`}><div>Login here</div></Link></div>
|
||||||
</>
|
</>
|
||||||
//<Link to={`/login${parsedsearch}`} style={hrefStyle}><div>Click here to Login</div></Link>
|
//<Link to={`/login${parsedsearch}`} style={hrefStyle}><div>Click here to Login</div></Link>
|
||||||
|
|
||||||
// <DialogTitle>{formtitle}</DialogTitle>
|
// <DialogTitle>{formtitle}</DialogTitle>
|
||||||
|
|
||||||
const buttonBackground = "linear-gradient(89.83deg, #FF8444 0.13%, #F2643B 99.84%)"
|
const buttonBackground = "linear-gradient(89.83deg, #FF8444 0.13%, #F2643B 99.84%)"
|
||||||
|
|
||||||
const buttonStyle = { borderRadius: 25, height: 50, fontSize: 18, backgroundImage: handleValidateForm(username, password) || loginLoading || (checkboxClicked && register) ? buttonBackground : "grey", color: "white" }
|
const buttonStyle = { borderRadius: 25, height: 50, fontSize: 18, backgroundImage: handleValidateForm(username, password) || loginLoading || (checkboxClicked && register) ? buttonBackground : "grey", color: "white" }
|
||||||
//<Button variant="contained" type="submit" fullWidth style={buttonStyle} disabled={!handleValidateForm() || loginLoading}>
|
//<Button variant="contained" type="submit" fullWidth style={buttonStyle} disabled={!handleValidateForm() || loginLoading}>
|
||||||
@@ -775,15 +785,29 @@ const LoginPage = props => {
|
|||||||
color: "white",
|
color: "white",
|
||||||
fontSize: "1em",
|
fontSize: "1em",
|
||||||
},
|
},
|
||||||
|
endAdornment: (
|
||||||
|
<Tooltip title={showPassword ? "Hide password" : "Show password"} arrow>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
cursor: "pointer",
|
||||||
|
marginRight: 10,
|
||||||
|
color: "white"
|
||||||
|
}}
|
||||||
|
onClick={() => setShowPassword(!showPassword)}
|
||||||
|
>
|
||||||
|
{showPassword ? <VisibilityOutlinedIcon /> : <VisibilityOffOutlinedIcon />}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
}}
|
}}
|
||||||
required
|
required
|
||||||
id="outlined-password-input"
|
id="outlined-password-input"
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
type="password"
|
|
||||||
autoComplete="current-password"
|
autoComplete="current-password"
|
||||||
placeholder="at least 10 characters"
|
placeholder="at least 10 characters"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
type={showPassword ? "text" : "password"}
|
||||||
onChange={onChangePass}
|
onChange={onChangePass}
|
||||||
helperText={
|
helperText={
|
||||||
handleValidateForm(username, password)
|
handleValidateForm(username, password)
|
||||||
@@ -907,7 +931,10 @@ const LoginPage = props => {
|
|||||||
{loginInfo}
|
{loginInfo}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ssoUrl !== undefined && ssoUrl !== null && ssoUrl.length > 0 ? (
|
{(
|
||||||
|
ssoUrl !== undefined && ssoUrl !== null && ssoUrl.length) > 0
|
||||||
|
//|| (isCloud && !loginWithSSO && window?.location?.pathname !== "/register")
|
||||||
|
? (
|
||||||
<div>
|
<div>
|
||||||
<Typography style={{ textAlign: "center" }}>Or</Typography>
|
<Typography style={{ textAlign: "center" }}>Or</Typography>
|
||||||
<div style={{ textAlign: "center", margin: 10 }}>
|
<div style={{ textAlign: "center", margin: 10 }}>
|
||||||
@@ -917,11 +944,17 @@ const LoginPage = props => {
|
|||||||
color="secondary"
|
color="secondary"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
type="button"
|
type="button"
|
||||||
style={{ flex: "1", marginTop: 5 }}
|
style={{ flex: "1", marginTop: 5, textTransform: 'none', fontSize: 16 }}
|
||||||
onClick={() => {
|
onClick={(e) => {
|
||||||
//console.log("CLICK SSO");
|
//console.log("CLICK SSO");
|
||||||
window.location.href = ssoUrl
|
e.preventDefault();
|
||||||
//navigate(ssoUrl)
|
//navigate(ssoUrl)
|
||||||
|
if (isCloud) {
|
||||||
|
setLoginWithSSO(true)
|
||||||
|
setPassword("")
|
||||||
|
}else {
|
||||||
|
window.location.href = ssoUrl
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Use SSO
|
Use SSO
|
||||||
@@ -929,6 +962,19 @@ const LoginPage = props => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
{isCloud && loginWithSSO && (
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color="secondary"
|
||||||
|
onClick={() => {
|
||||||
|
setLoginWithSSO(false)
|
||||||
|
setLoginInfo("")
|
||||||
|
}}
|
||||||
|
style={{ width: '100%', marginTop: 5, flex: "1", textTransform: 'none', fontSize: 16 }}
|
||||||
|
>
|
||||||
|
Back to login
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</form>
|
</form>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
@@ -952,7 +998,7 @@ const LoginPage = props => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{zoom: 0.8, paddingTop: 75, paddingBottom: 90 }}>
|
<div style={{zoom: 0.8, minHeight: "75vh", paddingTop: 75, paddingBottom: 90 }}>
|
||||||
{loadedCheck}
|
{loadedCheck}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1197,6 +1197,7 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
<form onSubmit={(e) => {onSubmit(e)}} style={{margin: "25px 0px 15px 0px",}}>
|
<form onSubmit={(e) => {onSubmit(e)}} style={{margin: "25px 0px 15px 0px",}}>
|
||||||
{workflowQuestion !== "" || (workflow.form_control.input_markdown !== undefined && workflow.form_control.input_markdown !== null && workflow.form_control.input_markdown.length > 0) ? null :
|
{workflowQuestion !== "" || (workflow.form_control.input_markdown !== undefined && workflow.form_control.input_markdown !== null && workflow.form_control.input_markdown.length > 0) ? null :
|
||||||
<div>
|
<div>
|
||||||
|
{/*
|
||||||
<img
|
<img
|
||||||
alt={workflow.name}
|
alt={workflow.name}
|
||||||
src={image}
|
src={image}
|
||||||
@@ -1211,6 +1212,7 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
left: 200,
|
left: 200,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
*/}
|
||||||
|
|
||||||
<Typography variant="h6" style={{marginBottom: 10, marginTop: 50, textAlign: "center", }}>
|
<Typography variant="h6" style={{marginBottom: 10, marginTop: 50, textAlign: "center", }}>
|
||||||
{organization}
|
{organization}
|
||||||
|
|||||||
@@ -724,6 +724,8 @@ const Workflows2 = (props) => {
|
|||||||
|
|
||||||
const [apps, setApps] = React.useState([]);
|
const [apps, setApps] = React.useState([]);
|
||||||
|
|
||||||
|
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||||
|
|
||||||
document.title = "Shuffle - Workflows";
|
document.title = "Shuffle - Workflows";
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -2327,7 +2329,7 @@ const Workflows2 = (props) => {
|
|||||||
key={"explore forms"}
|
key={"explore forms"}
|
||||||
>
|
>
|
||||||
<EditNoteIcon style={{ marginLeft: 0, marginRight: 8 }} />
|
<EditNoteIcon style={{ marginLeft: 0, marginRight: 8 }} />
|
||||||
{"Create Form"}
|
{"Edit Form"}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
@@ -4289,7 +4291,7 @@ const Workflows2 = (props) => {
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
maxWidth: "70%",
|
maxWidth: isSafari ? "100%" : "70%",
|
||||||
margin: "auto",
|
margin: "auto",
|
||||||
}}>
|
}}>
|
||||||
<Typography variant="h4" style={{ marginBottom: 20, paddingLeft: 15, textTransform: 'none', fontFamily: theme?.typography?.fontFamily }}>
|
<Typography variant="h4" style={{ marginBottom: 20, paddingLeft: 15, textTransform: 'none', fontFamily: theme?.typography?.fontFamily }}>
|
||||||
@@ -4616,6 +4618,7 @@ const Workflows2 = (props) => {
|
|||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={handleCreateWorkflow}
|
onClick={handleCreateWorkflow}
|
||||||
|
id="create_workflow_button"
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
flex: 0.8,
|
flex: 0.8,
|
||||||
@@ -5060,8 +5063,9 @@ const Workflows2 = (props) => {
|
|||||||
</iframe>
|
</iframe>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
|
//isLoaded && isLoggedIn && workflowDone ? (
|
||||||
const loadedCheck =
|
const loadedCheck =
|
||||||
isLoaded && isLoggedIn && workflowDone ? (
|
workflowDone ? (
|
||||||
<div>
|
<div>
|
||||||
{/*
|
{/*
|
||||||
<ShepherdTour steps={newSteps} tourOptions={tourOptions}>
|
<ShepherdTour steps={newSteps} tourOptions={tourOptions}>
|
||||||
@@ -5128,8 +5132,14 @@ const Workflows2 = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const safariStyle = {
|
||||||
|
transform: 'scale(0.7)',
|
||||||
|
transformOrigin: 'top',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
}
|
||||||
// Maybe use gridview or something, idk
|
// Maybe use gridview or something, idk
|
||||||
return <div style={{zoom: 0.7, }}>{loadedCheck}</div>;
|
return <div style={isSafari ? safariStyle : {zoom: 0.7, minHeight: "80vh",}}>{loadedCheck}</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
module orborus
|
module orborus
|
||||||
|
|
||||||
go 1.22.0
|
go 1.23.0
|
||||||
toolchain go1.24.1
|
|
||||||
|
toolchain go1.23.6
|
||||||
|
|
||||||
//replace github.com/shuffle/shuffle-shared => ../../../../shuffle-shared
|
//replace github.com/shuffle/shuffle-shared => ../../../../shuffle-shared
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ require (
|
|||||||
github.com/docker/docker v27.5.0+incompatible
|
github.com/docker/docker v27.5.0+incompatible
|
||||||
github.com/docker/go-connections v0.5.0
|
github.com/docker/go-connections v0.5.0
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shuffle/shuffle-shared v0.8.7
|
github.com/shuffle/shuffle-shared v0.8.18
|
||||||
k8s.io/api v0.30.2
|
k8s.io/api v0.30.2
|
||||||
k8s.io/apimachinery v0.30.2
|
k8s.io/apimachinery v0.30.2
|
||||||
)
|
)
|
||||||
@@ -96,14 +97,14 @@ require (
|
|||||||
go.opentelemetry.io/otel/trace v1.33.0 // indirect
|
go.opentelemetry.io/otel/trace v1.33.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
|
||||||
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
||||||
golang.org/x/crypto v0.35.0 // indirect
|
golang.org/x/crypto v0.36.0 // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
golang.org/x/net v0.36.0 // indirect
|
golang.org/x/net v0.37.0 // indirect
|
||||||
golang.org/x/oauth2 v0.23.0 // indirect
|
golang.org/x/oauth2 v0.23.0 // indirect
|
||||||
golang.org/x/sync v0.11.0 // indirect
|
golang.org/x/sync v0.12.0 // indirect
|
||||||
golang.org/x/sys v0.30.0 // indirect
|
golang.org/x/sys v0.31.0 // indirect
|
||||||
golang.org/x/term v0.29.0 // indirect
|
golang.org/x/term v0.30.0 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.23.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||||
|
|||||||
@@ -301,8 +301,6 @@ github.com/sendgrid/sendgrid-go v3.14.0+incompatible h1:KDSasSTktAqMJCYClHVE94Fc
|
|||||||
github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8=
|
github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8=
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||||
github.com/shuffle/shuffle-shared v0.8.7 h1:+UdRx7b/KUy/E92ODNr87UvCI2Dxfnv0samQWuggJu4=
|
|
||||||
github.com/shuffle/shuffle-shared v0.8.7/go.mod h1:bBXhEsPKjxln0mFnSeri7gIJ3tL/636Sh5NyTyNrvIQ=
|
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
@@ -366,8 +364,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
|
||||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@@ -423,8 +419,6 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
|
|
||||||
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -440,8 +434,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
|
||||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -468,14 +460,10 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
|
||||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -486,8 +474,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
|
||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
|
|||||||
@@ -456,6 +456,7 @@ func deployServiceWorkers(image string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
isMemcachedRunning, err := checkMemcached(ctx, dockercli)
|
isMemcachedRunning, err := checkMemcached(ctx, dockercli)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[ERROR] Failed checking memcached: %s", err)
|
log.Printf("[ERROR] Failed checking memcached: %s", err)
|
||||||
@@ -466,8 +467,10 @@ func deployServiceWorkers(image string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ip := "shuffle-cache"
|
ip := "shuffle-cache"
|
||||||
|
if len(os.Getenv("SHUFFLE_MEMCACHED")) == 0 {
|
||||||
os.Setenv("SHUFFLE_MEMCACHED", fmt.Sprintf("%s:11211", ip))
|
os.Setenv("SHUFFLE_MEMCACHED", fmt.Sprintf("%s:11211", ip))
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
defaultNetworkAttach := false
|
defaultNetworkAttach := false
|
||||||
if containerId != "" {
|
if containerId != "" {
|
||||||
@@ -608,7 +611,7 @@ func deployServiceWorkers(image string) {
|
|||||||
fmt.Sprintf("SHUFFLE_LOGS_DISABLED=%s", os.Getenv("SHUFFLE_LOGS_DISABLED")),
|
fmt.Sprintf("SHUFFLE_LOGS_DISABLED=%s", os.Getenv("SHUFFLE_LOGS_DISABLED")),
|
||||||
fmt.Sprintf("DEBUG_MEMORY=%s", os.Getenv("DEBUG_MEMORY")),
|
fmt.Sprintf("DEBUG_MEMORY=%s", os.Getenv("DEBUG_MEMORY")),
|
||||||
fmt.Sprintf("SHUFFLE_APP_SDK_TIMEOUT=%s", os.Getenv("SHUFFLE_APP_SDK_TIMEOUT")),
|
fmt.Sprintf("SHUFFLE_APP_SDK_TIMEOUT=%s", os.Getenv("SHUFFLE_APP_SDK_TIMEOUT")),
|
||||||
fmt.Sprintf("SHUFFLE_MAX_SWARM_NODES=%d", os.Getenv("SHUFFLE_MAX_SWARM_NODES")),
|
fmt.Sprintf("SHUFFLE_MAX_SWARM_NODES=%s", os.Getenv("SHUFFLE_MAX_SWARM_NODES")),
|
||||||
fmt.Sprintf("SHUFFLE_BASE_IMAGE_NAME=%s", os.Getenv("SHUFFLE_BASE_IMAGE_NAME")),
|
fmt.Sprintf("SHUFFLE_BASE_IMAGE_NAME=%s", os.Getenv("SHUFFLE_BASE_IMAGE_NAME")),
|
||||||
fmt.Sprintf("SHUFFLE_APP_REQUEST_TIMEOUT=%s", os.Getenv("SHUFFLE_APP_REQUEST_TIMEOUT")),
|
fmt.Sprintf("SHUFFLE_APP_REQUEST_TIMEOUT=%s", os.Getenv("SHUFFLE_APP_REQUEST_TIMEOUT")),
|
||||||
},
|
},
|
||||||
@@ -766,42 +769,40 @@ func handleBackendImageDownload(ctx context.Context, images string) error {
|
|||||||
|
|
||||||
// Remove the image
|
// Remove the image
|
||||||
handled := []string{}
|
handled := []string{}
|
||||||
log.Printf("[DEBUG] Should remove existing image (s): %s. Waiting 30 seconds to ensure backend has the latest images built and ready to distribute.", images)
|
log.Printf("[DEBUG] Removing existing image (s): %s. Waiting 30 seconds before starting to ensure backend has the latest images built and ready to distribute.", images)
|
||||||
removeOptions := image.RemoveOptions{}
|
//time.Sleep(time.Duration(30) * time.Second)
|
||||||
|
|
||||||
time.Sleep(time.Duration(30) * time.Second)
|
|
||||||
|
|
||||||
newImages := []string{}
|
newImages := []string{}
|
||||||
for _, image := range strings.Split(images, ",") {
|
for _, curimage := range strings.Split(images, ",") {
|
||||||
image = strings.TrimSpace(image)
|
curimage = strings.TrimSpace(curimage)
|
||||||
if shuffle.ArrayContains(handled, image) {
|
if shuffle.ArrayContains(handled, curimage) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
handled = append(handled, image)
|
handled = append(handled, curimage)
|
||||||
if !strings.Contains(image, "/") {
|
if !strings.Contains(curimage, "/") {
|
||||||
image = fmt.Sprintf("frikky/shuffle:%s", image)
|
curimage = fmt.Sprintf("frikky/shuffle:%s", curimage)
|
||||||
}
|
}
|
||||||
|
|
||||||
newImages = append(newImages, image)
|
newImages = append(newImages, curimage)
|
||||||
|
|
||||||
|
// Force remove the current image to avoid cached layers
|
||||||
|
_, err := dockercli.ImageRemove(ctx, curimage, image.RemoveOptions{
|
||||||
|
Force: true,
|
||||||
|
PruneChildren: true,
|
||||||
|
})
|
||||||
|
|
||||||
// There is no real point in actual removal. This may however be a good idea, as Worker will force download the new one anyway
|
|
||||||
resp, err := dockercli.ImageRemove(ctx, image, removeOptions)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[ERROR] Failed removing image: %s. Resp: %#v", err, resp)
|
log.Printf("[ERROR] Failed removing image for re-download: %s", err)
|
||||||
|
|
||||||
// Goroutining images that don't already exist, as they are most likely not the correct one
|
|
||||||
go shuffle.DownloadDockerImageBackend(&http.Client{Timeout: imagedownloadTimeout}, image)
|
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[DEBUG] Removed image: %s", image)
|
log.Printf("[DEBUG] Removed image: %s", curimage)
|
||||||
|
}
|
||||||
|
|
||||||
err = shuffle.DownloadDockerImageBackend(&http.Client{Timeout: imagedownloadTimeout}, image)
|
err = shuffle.DownloadDockerImageBackend(&http.Client{Timeout: imagedownloadTimeout}, curimage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[ERROR] Failed downloading image: %s", err)
|
log.Printf("[ERROR] Failed downloading image: %s", err)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[DEBUG] Downloaded image: %s", image)
|
log.Printf("[DEBUG] Downloaded image: %s", curimage)
|
||||||
//break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -820,20 +821,18 @@ func handleBackendImageDownload(ctx context.Context, images string) error {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[ERROR] Failed finding containers: %s", err)
|
log.Printf("[ERROR] Failed finding services: %s", err)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[DEBUG] Found %d services", len(services))
|
found := false
|
||||||
|
|
||||||
for _, service := range services {
|
for _, service := range services {
|
||||||
|
//log.Printf("Service image: %s", service.Spec.TaskTemplate.ContainerSpec.Image)
|
||||||
log.Printf("Imagename: %s", service.Spec.TaskTemplate.ContainerSpec.Image)
|
|
||||||
|
|
||||||
for _, image := range newImages {
|
for _, image := range newImages {
|
||||||
if !strings.Contains(service.Spec.TaskTemplate.ContainerSpec.Image, image) {
|
if !strings.Contains(service.Spec.TaskTemplate.ContainerSpec.Image, image) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Found service for image %#v: %#v", service.Spec.Annotations.Name)
|
log.Printf("[DEBUG] Found service for image: %#v", service.Spec.Annotations.Name)
|
||||||
|
|
||||||
// Update the service to run with the new image
|
// Update the service to run with the new image
|
||||||
//docker service update --image username/imagename:latest servicename --force
|
//docker service update --image username/imagename:latest servicename --force
|
||||||
@@ -853,9 +852,20 @@ func handleBackendImageDownload(ctx context.Context, images string) error {
|
|||||||
|
|
||||||
if !strings.Contains(fmt.Sprintf("%s", resp), "error") {
|
if !strings.Contains(fmt.Sprintf("%s", resp), "error") {
|
||||||
break
|
break
|
||||||
|
} else {
|
||||||
|
found = true
|
||||||
|
log.Printf("[ERROR] Failed updating service %s with the new image %s: %s. Resp: %#v", service.Spec.Annotations.Name, image, err, resp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if found {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
log.Printf("[DEBUG] Failed to find service to update for service %s", newImages)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1479,29 +1489,34 @@ func initializeImages() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check whether they are the same first
|
// check whether they are the same first
|
||||||
images := []string{
|
|
||||||
fmt.Sprintf("frikky/shuffle:app_sdk"),
|
|
||||||
fmt.Sprintf("shuffle/shuffle:app_sdk"),
|
|
||||||
fmt.Sprintf("%s/%s/shuffle-app_sdk:%s", baseimageregistry, baseimagename, appSdkVersion),
|
|
||||||
newWorker,
|
|
||||||
}
|
|
||||||
|
|
||||||
pullOptions := image.PullOptions{}
|
if os.Getenv("SHUFFLE_AUTO_IMAGE_DOWNLOAD") != "true" {
|
||||||
for _, image := range images {
|
images := []string{
|
||||||
if isKubernetes == "true" {
|
fmt.Sprintf("frikky/shuffle:app_sdk"),
|
||||||
log.Printf("[DEBUG] Skipping image pull of '%s' because Kubernetes does it in realtime instead", image)
|
fmt.Sprintf("shuffle/shuffle:app_sdk"),
|
||||||
} else {
|
fmt.Sprintf("%s/%s/shuffle-app_sdk:%s", baseimageregistry, baseimagename, appSdkVersion),
|
||||||
log.Printf("[DEBUG] Pulling image %s", image)
|
newWorker,
|
||||||
reader, err := dockercli.ImagePull(ctx, image, pullOptions)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("[ERROR] Failed getting image %s: %s", image, err)
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
io.Copy(os.Stdout, reader)
|
|
||||||
log.Printf("[DEBUG] Successfully downloaded and built %s", image)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pullOptions := image.PullOptions{}
|
||||||
|
for _, image := range images {
|
||||||
|
if isKubernetes == "true" {
|
||||||
|
log.Printf("[DEBUG] Skipping image pull of '%s' because Kubernetes does it in realtime instead", image)
|
||||||
|
} else {
|
||||||
|
log.Printf("[DEBUG] Pulling image %s", image)
|
||||||
|
reader, err := dockercli.ImagePull(ctx, image, pullOptions)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[ERROR] Failed getting image %s: %s", image, err)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
io.Copy(os.Stdout, reader)
|
||||||
|
log.Printf("[DEBUG] Successfully downloaded and built %s", image)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("[DEBUG] Skipping image download as SHUFFLE_AUTO_IMAGE_DOWNLOAD is set to true")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2245,7 +2260,7 @@ func main() {
|
|||||||
|
|
||||||
toBeRemoved.Data = append(toBeRemoved.Data, incRequest)
|
toBeRemoved.Data = append(toBeRemoved.Data, incRequest)
|
||||||
} else if incRequest.Type == "DOCKER_IMAGE_DOWNLOAD" {
|
} else if incRequest.Type == "DOCKER_IMAGE_DOWNLOAD" {
|
||||||
log.Printf("[INFO] Should delete -> download new images: %#v", incRequest.ExecutionArgument)
|
log.Printf("[INFO] Re-downloading new image(s): %#v", incRequest.ExecutionArgument)
|
||||||
|
|
||||||
if len(incRequest.ExecutionArgument) > 0 {
|
if len(incRequest.ExecutionArgument) > 0 {
|
||||||
// FIXME: Wait X seconds before running this as the image build may not be done yet. This is shitty, but may be ok to do in Orborus. Easy fix for the future: Just let it run through jobs 5-10 times before actually picking it up
|
// FIXME: Wait X seconds before running this as the image build may not be done yet. This is shitty, but may be ok to do in Orborus. Easy fix for the future: Just let it run through jobs 5-10 times before actually picking it up
|
||||||
@@ -3462,7 +3477,7 @@ func sendPipelineHealthStatus() (shuffle.LakeConfig, error) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
tenzirDisabled = true
|
tenzirDisabled = true
|
||||||
log.Printf("[ERROR] Disabling pipelines: %s. You will need to restart the Orborus to fix this.", err)
|
log.Printf("[WARNING] Disabling pipelines: %s. You will need to restart the Orborus to fix this.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pipelinePayload, err
|
return pipelinePayload, err
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
module worker
|
module worker
|
||||||
|
|
||||||
go 1.22.7
|
go 1.23.0
|
||||||
toolchain go1.24.1
|
|
||||||
|
toolchain go1.23.7
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/docker/docker v27.5.0+incompatible
|
github.com/docker/docker v27.5.0+incompatible
|
||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shuffle/shuffle-shared v0.8.7
|
github.com/shuffle/shuffle-shared v0.8.18
|
||||||
k8s.io/api v0.30.2
|
k8s.io/api v0.30.2
|
||||||
k8s.io/apimachinery v0.30.2
|
k8s.io/apimachinery v0.30.2
|
||||||
k8s.io/client-go v0.30.2
|
k8s.io/client-go v0.30.2
|
||||||
@@ -97,14 +98,14 @@ require (
|
|||||||
go.opentelemetry.io/otel/trace v1.33.0 // indirect
|
go.opentelemetry.io/otel/trace v1.33.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.4.0 // indirect
|
||||||
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
go4.org v0.0.0-20201209231011-d4a079459e60 // indirect
|
||||||
golang.org/x/crypto v0.35.0 // indirect
|
golang.org/x/crypto v0.36.0 // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
golang.org/x/net v0.36.0 // indirect
|
golang.org/x/net v0.37.0 // indirect
|
||||||
golang.org/x/oauth2 v0.23.0 // indirect
|
golang.org/x/oauth2 v0.23.0 // indirect
|
||||||
golang.org/x/sync v0.11.0 // indirect
|
golang.org/x/sync v0.12.0 // indirect
|
||||||
golang.org/x/sys v0.30.0 // indirect
|
golang.org/x/sys v0.31.0 // indirect
|
||||||
golang.org/x/term v0.29.0 // indirect
|
golang.org/x/term v0.30.0 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.23.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||||
google.golang.org/api v0.162.0 // indirect
|
google.golang.org/api v0.162.0 // indirect
|
||||||
|
|||||||
@@ -294,8 +294,6 @@ github.com/sendgrid/sendgrid-go v3.14.0+incompatible h1:KDSasSTktAqMJCYClHVE94Fc
|
|||||||
github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8=
|
github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8=
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||||
github.com/shuffle/shuffle-shared v0.8.7 h1:+UdRx7b/KUy/E92ODNr87UvCI2Dxfnv0samQWuggJu4=
|
|
||||||
github.com/shuffle/shuffle-shared v0.8.7/go.mod h1:bBXhEsPKjxln0mFnSeri7gIJ3tL/636Sh5NyTyNrvIQ=
|
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
@@ -359,8 +357,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
|
||||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@@ -415,8 +411,6 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
|
|
||||||
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -432,8 +426,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
|
||||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -459,14 +451,10 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
|
||||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -477,8 +465,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
|
||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
|
|||||||
@@ -57,11 +57,10 @@ var cleanupEnv = strings.ToLower(os.Getenv("CLEANUP"))
|
|||||||
var swarmNetworkName = os.Getenv("SHUFFLE_SWARM_NETWORK_NAME")
|
var swarmNetworkName = os.Getenv("SHUFFLE_SWARM_NETWORK_NAME")
|
||||||
var dockerApiVersion = strings.ToLower(os.Getenv("DOCKER_API_VERSION"))
|
var dockerApiVersion = strings.ToLower(os.Getenv("DOCKER_API_VERSION"))
|
||||||
|
|
||||||
var baseimagename = "frikky/shuffle"
|
|
||||||
var kubernetesNamespace = os.Getenv("KUBERNETES_NAMESPACE")
|
var kubernetesNamespace = os.Getenv("KUBERNETES_NAMESPACE")
|
||||||
var executionCount int64
|
var executionCount int64
|
||||||
|
|
||||||
// var baseimagename = os.Getenv("SHUFFLE_BASE_IMAGE_NAME")
|
var baseimagename = os.Getenv("SHUFFLE_BASE_IMAGE_NAME")
|
||||||
|
|
||||||
// var baseimagename = "registry.hub.docker.com/frikky/shuffle"
|
// var baseimagename = "registry.hub.docker.com/frikky/shuffle"
|
||||||
var registryName = "registry.hub.docker.com"
|
var registryName = "registry.hub.docker.com"
|
||||||
@@ -106,9 +105,7 @@ var window = shuffle.NewTimeWindow(10 * time.Second)
|
|||||||
// Images to be autodeployed in the latest version of Shuffle.
|
// Images to be autodeployed in the latest version of Shuffle.
|
||||||
var autoDeploy = map[string]string{
|
var autoDeploy = map[string]string{
|
||||||
"http:1.4.0": "frikky/shuffle:http_1.4.0",
|
"http:1.4.0": "frikky/shuffle:http_1.4.0",
|
||||||
"http:1.3.0": "frikky/shuffle:http_1.3.0",
|
|
||||||
"shuffle-tools:1.2.0": "frikky/shuffle:shuffle-tools_1.2.0",
|
"shuffle-tools:1.2.0": "frikky/shuffle:shuffle-tools_1.2.0",
|
||||||
"shuffle-subflow:1.0.0": "frikky/shuffle:shuffle-subflow_1.0.0",
|
|
||||||
"shuffle-subflow:1.1.0": "frikky/shuffle:shuffle-subflow_1.1.0",
|
"shuffle-subflow:1.1.0": "frikky/shuffle:shuffle-subflow_1.1.0",
|
||||||
// "shuffle-tools-fork:1.0.0": "frikky/shuffle:shuffle-tools-fork_1.0.0",
|
// "shuffle-tools-fork:1.0.0": "frikky/shuffle:shuffle-tools-fork_1.0.0",
|
||||||
}
|
}
|
||||||
@@ -3726,7 +3723,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if baseimagename == "" {
|
if baseimagename == "" {
|
||||||
log.Printf("[DEBUG] Setting baseimagename")
|
log.Printf("[DEBUG] Setting baseimagename to frikky/shuffle")
|
||||||
baseimagename = "frikky/shuffle" // Dockerhub
|
baseimagename = "frikky/shuffle" // Dockerhub
|
||||||
//baseimagename = "shuffle" // Github (ghcr.io)
|
//baseimagename = "shuffle" // Github (ghcr.io)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user