diff --git a/.github/config.json b/.github/config.json index 674c20eda1..98679a4224 100644 --- a/.github/config.json +++ b/.github/config.json @@ -1 +1 @@ -{"runners":[{"versioning":{"source":"milestones","type":"SemVer"},"prereleaseName":"alpha","issue":{"labels":{"Team Managers Pod":{"conditions":[{"label":"Login / Signup","type":"hasLabel","value":true},{"label":"Settings","type":"hasLabel","value":true},{"label":"Git Version Control","type":"hasLabel","value":true},{"label":"Home Page","type":"hasLabel","value":true},{"label":"Import-Export-App","type":"hasLabel","value":true},{"label":"advanced","type":"hasLabel","value":true},{"label":"Team Managers Pod","type":"hasLabel","value":true},{"label":"Invite users","type":"hasLabel","value":true},{"label":"ACL","type":"hasLabel","value":true},{"label":"Realtime Commenting","type":"hasLabel","value":true},{"label":"SSO","type":"hasLabel","value":true},{"label":"Multi User Realtime","type":"hasLabel","value":true},{"label":"RBAC","type":"hasLabel","value":true}],"requires":1},"New Developers Pod":{"conditions":[{"label":"Fork App","type":"hasLabel","value":true},{"label":"Omnibar","type":"hasLabel","value":true},{"label":"Onboarding","type":"hasLabel","value":true},{"label":"Telemetry","type":"hasLabel","value":true},{"label":"Entity Explorer","type":"hasLabel","value":true},{"label":"Generate Page","type":"hasLabel","value":true},{"label":"IDE","type":"hasLabel","value":true},{"label":"In App Comms","type":"hasLabel","value":true},{"label":"New Developers Pod","type":"hasLabel","value":true},{"label":"Sniping Mode","type":"hasLabel","value":true},{"label":"Design System","type":"hasLabel","value":true},{"label":"Example Apps","type":"hasLabel","value":true},{"label":"i18n","type":"hasLabel","value":true},{"label":"Welcome Screen","type":"hasLabel","value":true},{"label":"Templates","type":"hasLabel","value":true}],"requires":1},"BE Coders Pod":{"conditions":[{"label":"Datasources","type":"hasLabel","value":true},{"label":"Firestore","type":"hasLabel","value":true},{"label":"Google Sheets","type":"hasLabel","value":true},{"label":"Mongo","type":"hasLabel","value":true},{"label":"MySQL","type":"hasLabel","value":true},{"label":"Redshift","type":"hasLabel","value":true},{"label":"UQI","type":"hasLabel","value":true},{"label":"Query Editor","type":"hasLabel","value":true},{"label":"API pane","type":"hasLabel","value":true},{"label":"snowflake","type":"hasLabel","value":true},{"label":"S3","type":"hasLabel","value":true},{"label":"BE Coders Pod","type":"hasLabel","value":true},{"label":"Redis","type":"hasLabel","value":true},{"label":"New Datasource","type":"hasLabel","value":true},{"label":"Query Execution","type":"hasLabel","value":true},{"label":"Postgres","type":"hasLabel","value":true},{"label":"REST API plugin","type":"hasLabel","value":true},{"label":"SAAS Plugins","type":"hasLabel","value":true},{"label":"UQI components","type":"hasLabel","value":true},{"label":"UQI validations","type":"hasLabel","value":true},{"label":"Action form","type":"hasLabel","value":true},{"label":"UQI migration","type":"hasLabel","value":true},{"label":"SQL","type":"hasLabel","value":true},{"label":"Query Templates","type":"hasLabel","value":true},{"label":"Plugin Development","type":"hasLabel","value":true},{"label":"GraphQL Plugin","type":"hasLabel","value":true},{"label":"ArangoDB","type":"hasLabel","value":true},{"label":"SmartJSONSubstitution","type":"hasLabel","value":true},{"label":"smartBSONsubstitution","type":"hasLabel","value":true},{"label":"Airtable","type":"hasLabel","value":true}],"requires":1},"FE Coders Pod":{"conditions":[{"label":"JS Linting & Errors","type":"hasLabel","value":true},{"label":"JS Editor","type":"hasLabel","value":true},{"label":"Debugger","type":"hasLabel","value":true},{"label":"JS","type":"hasLabel","value":true},{"label":"JS Snippets","type":"hasLabel","value":true},{"label":"Autocomplete","type":"hasLabel","value":true},{"label":"FE Coders Pod","type":"hasLabel","value":true},{"label":"Evaluated Value","type":"hasLabel","value":true},{"label":"Slash Command","type":"hasLabel","value":true},{"label":"New JS Function","type":"hasLabel","value":true},{"label":"JS Promises","type":"hasLabel","value":true},{"label":"OnPageLoad","type":"hasLabel","value":true},{"label":"Function execution","type":"hasLabel","value":true},{"label":"JS Refactoring","type":"hasLabel","value":true},{"label":"JS Usability","type":"hasLabel","value":true},{"label":"Code Refactoring","type":"hasLabel","value":true}],"requires":1},"App Viewers Pod":{"conditions":[{"label":"Button Widget","type":"hasLabel","value":true},{"label":"Chart Widget","type":"hasLabel","value":true},{"label":"Checkbox Widget","type":"hasLabel","value":true},{"label":"Container Widget","type":"hasLabel","value":true},{"label":"Date Picker Widget","type":"hasLabel","value":true},{"label":"Select Widget","type":"hasLabel","value":true},{"label":"File Picker Widget","type":"hasLabel","value":true},{"label":"Form Widget","type":"hasLabel","value":true},{"label":"Image Widget","type":"hasLabel","value":true},{"label":"Input Widget","type":"hasLabel","value":true},{"label":"List Widget","type":"hasLabel","value":true},{"label":"MultiSelect Widget","type":"hasLabel","value":true},{"label":"Map Widget","type":"hasLabel","value":true},{"label":"Modal Widget","type":"hasLabel","value":true},{"label":"Radio Widget","type":"hasLabel","value":true},{"label":"Rich Text Editor Widget","type":"hasLabel","value":true},{"label":"Tab Widget","type":"hasLabel","value":true},{"label":"Table Widget","type":"hasLabel","value":true},{"label":"Text Widget","type":"hasLabel","value":true},{"label":"Video Widget","type":"hasLabel","value":true},{"label":"iFrame","type":"hasLabel","value":true},{"label":"Menu Button","type":"hasLabel","value":true},{"label":"Rating","type":"hasLabel","value":true},{"label":"Widget Validation","type":"hasLabel","value":true},{"label":"reallabel","type":"hasLabel","value":true},{"label":"New Widget","type":"hasLabel","value":true},{"label":"Switch widget","type":"hasLabel","value":true},{"label":"Widget Styling","type":"hasLabel","value":true},{"label":"Audio Widget","type":"hasLabel","value":true},{"label":"Icon Button Widget","type":"hasLabel","value":true},{"label":"Checkbox Group widget","type":"hasLabel","value":true},{"label":"Stat Box Widget","type":"hasLabel","value":true},{"label":"Voice Recorder Widget","type":"hasLabel","value":true},{"label":"Calendar Widget","type":"hasLabel","value":true},{"label":"Menu Button Widget","type":"hasLabel","value":true},{"label":"Divider Widget","type":"hasLabel","value":true},{"label":"Rating Widget","type":"hasLabel","value":true},{"label":"App Viewers Pod","type":"hasLabel","value":true},{"label":"App Navigation","type":"hasLabel","value":true},{"label":"View Mode","type":"hasLabel","value":true},{"label":"Embedding Apps","type":"hasLabel","value":true},{"label":"Widget Property","type":"hasLabel","value":true},{"label":"Document Viewer Widget","type":"hasLabel","value":true},{"label":"Radio Group Widget","type":"hasLabel","value":true},{"label":"Currency Input Widget","type":"hasLabel","value":true},{"label":"TreeSelect","type":"hasLabel","value":true},{"label":"MultiTree Select Widget","type":"hasLabel","value":true},{"label":"Phone Input Widget","type":"hasLabel","value":true},{"label":"JSON Form","type":"hasLabel","value":true},{"label":"All Widgets","type":"hasLabel","value":true},{"label":"App Theming","type":"hasLabel","value":true},{"label":"Button Group widget","type":"hasLabel","value":true},{"label":"Progress bar widget","type":"hasLabel","value":true},{"label":"Audio Recorder Widget","type":"hasLabel","value":true}],"requires":1},"UI Builders Pod":{"conditions":[{"label":"Property Pane","type":"hasLabel","value":true},{"label":"Pages","type":"hasLabel","value":true},{"label":"UI Builders Pod","type":"hasLabel","value":true},{"label":"Copy Paste","type":"hasLabel","value":true},{"label":"Drag & Drop","type":"hasLabel","value":true},{"label":"Undo/Redo","type":"hasLabel","value":true},{"label":"Responsive Viewport","type":"hasLabel","value":true},{"label":"Canvas Zoom","type":"hasLabel","value":true},{"label":"Widgets Pane","type":"hasLabel","value":true},{"label":"UI Performance","type":"hasLabel","value":true},{"label":"Widget Grouping","type":"hasLabel","value":true},{"label":"Reflow & Resize","type":"hasLabel","value":true},{"label":"dynamic height","type":"hasLabel","value":true}],"requires":1},"User Education Pod":{"conditions":[{"label":"Content","type":"hasLabel","value":true},{"label":"Documentation","type":"hasLabel","value":true}],"requires":1},"Platform Pod":{"conditions":[{"label":"Platform Pod","type":"hasLabel","value":true},{"label":"Team Managers Pod","type":"hasLabel","value":true},{"label":"New Developers Pod","type":"hasLabel","value":true}],"requires":1},"Actions Pod":{"conditions":[{"label":"FE Coders Pod","type":"hasLabel","value":true},{"label":"BE Coders Pod","type":"hasLabel","value":true}],"requires":1},"UI Building Pod":{"conditions":[{"label":"App Viewers Pod","type":"hasLabel","value":true},{"label":"UI Builders Pod","type":"hasLabel","value":true}],"requires":1},"DevOps Pod":{"conditions":[{"label":"Docker","type":"hasLabel","value":true},{"label":"Super Admin","type":"hasLabel","value":true},{"label":"Deployment","type":"hasLabel","value":true},{"label":"K8s","type":"hasLabel","value":true}],"requires":1},"RBAC":{"conditions":[],"requires":1}}},"root":"."}],"labels":{"Tab Widget":{"color":"e2c76c","name":"Tab Widget","description":""},"Dont merge":{"color":"ADB39C","name":"Dont merge","description":""},"Epic":{"color":"3E4B9E","name":"Epic","description":"A zenhub epic that describes a project"},"Menu Button Widget":{"color":"235708","name":"Menu Button Widget","description":"Issues related to Menu Button widget"},"advanced":{"color":"5f4115","name":"advanced","description":"Features aimed at advanced users"},"Checkbox Group widget":{"color":"D2ACD2","name":"Checkbox Group widget","description":"Issues related to Checkbox Group Widget"},"Input Widget":{"color":"ae65d8","name":"Input Widget","description":""},"Security":{"color":"99139C","name":"Security","description":""},"QA":{"color":"e2ca68","name":"QA","description":""},"Verified":{"color":"9bf416","name":"Verified","description":""},"Wont Fix":{"color":"ffffff","name":"Wont Fix","description":"This will not be worked on"},"MySQL":{"color":"B0F9F4","name":"MySQL","description":""},"Development":{"color":"9F8A02","name":"Development","description":""},"Help Wanted":{"color":"008672","name":"Help Wanted","description":"Extra attention is needed"},"Home Page":{"color":"9c0c8e","name":"Home Page","description":"Issues related to the application home page"},"Rating Widget":{"color":"235708","name":"Rating Widget","description":"Issues related to the rating widget"},"Stat Box Widget":{"color":"f1c9ce","name":"Stat Box Widget","description":"Issues related to stat box"},"Enhancement":{"color":"a2eeef","name":"Enhancement","description":"New feature or request"},"Settings":{"color":"f7ff60","name":"Settings","description":"organization, team & user settings"},"Fork App":{"color":"5369db","name":"Fork App","description":"Issues related to forking apps"},"Container Widget":{"color":"19AD0D","name":"Container Widget","description":"Container widget"},"Papercut":{"color":"B562F6","name":"Papercut","description":""},"community":{"color":"dded34","name":"community","description":"issues reported by community members"},"Needs Design":{"color":"bfd4f2","name":"Needs Design","description":"needs design or changes to design"},"UQI":{"color":"FB8E9C","name":"UQI","description":""},"AutomationGap":{"color":"ed13bb","name":"AutomationGap","description":"Issues that needs automated tests"},"i18n":{"color":"1799b0","name":"i18n","description":"Represents issues that need to be tackled to handle internationalization"},"Rich Text Editor Widget":{"color":"f72cac","name":"Rich Text Editor Widget","description":""},"Onboarding":{"color":"d5794b","name":"Onboarding","description":"Issues related to onboarding new developers"},"Pages":{"color":"d7fd80","name":"Pages","description":"Issues related to configuring pages"},"skip-changelog":{"color":"06086F","name":"skip-changelog","description":"Adding this label to a PR prevents it from being listed in the changelog"},"Low":{"color":"79e53b","name":"Low","description":"An issue that is neither critical nor breaks a user flow"},"potential-duplicate":{"color":"d3cb2e","name":"potential-duplicate","description":"This label marks issues that are potential duplicates of already open issues"},"Audio Widget":{"color":"447B9A","name":"Audio Widget","description":"Issues related to Audio Widget"},"Firestore":{"color":"F1C2DF","name":"Firestore","description":"Issues related to the firestore Integration"},"New Widget":{"color":"be4cf2","name":"New Widget","description":"A request for a new widget"},"Performance":{"color":"d30e53","name":"Performance","description":"Page Load and evaluations"},"Modal Widget":{"color":"03846f","name":"Modal Widget","description":""},"UX Improvement":{"color":"f4a089","name":"UX Improvement","description":""},"S3":{"color":"c57928","name":"S3","description":"Issues related to the S3 plugin"},"Release Blocker":{"color":"5756bf","name":"Release Blocker","description":"This issue must be resolved before the release"},"safari":{"color":"51C6AA","name":"safari","description":"Bugs seen on safari browser"},"Example Apps":{"color":"1799b0","name":"Example Apps","description":"Example apps created for new signups"},"MultiSelect Widget":{"color":"AB62D4","name":"MultiSelect Widget","description":"Issues related to MultiSelect Widget"},"JS Editor":{"color":"48b992","name":"JS Editor","description":"Issues related to JS Editor"},"Widget Styling":{"color":"37EA75","name":"Widget Styling","description":"all about widget styling"},"Calendar Widget":{"color":"8c6644","name":"Calendar Widget","description":""},"JS":{"color":"e46785","name":"JS","description":"Issues related to JS on the platform"},"Website":{"color":"151720","name":"Website","description":"Related to www.appsmith.com website"},"Low effort":{"color":"8B59F0","name":"Low effort","description":"Something that'll take a few days to build"},"App Viewers Pod":{"color":"cd8ef9","name":"App Viewers Pod","description":"This label assigns issues to the app viewers pod"},"Checkbox Widget":{"color":"074ac6","name":"Checkbox Widget","description":""},"Spam":{"color":"620faf","name":"Spam","description":""},"Voice Recorder Widget":{"color":"85bc87","name":"Voice Recorder Widget","description":""},"Select Widget":{"color":"0c669e","name":"Select Widget","description":"Select or dropdown widget"},"Bug":{"color":"d73a4a","name":"Bug","description":"Something isn't working"},"Widget Validation":{"color":"6990BC","name":"Widget Validation","description":"Issues related to widget property validation"},"Generate Page":{"color":"f14274","name":"Generate Page","description":"Issures related to page generation"},"File Picker Widget":{"color":"6ae4f2","name":"File Picker Widget","description":""},"snowflake":{"color":"47075c","name":"snowflake","description":"Issues related to the snowflake Integration"},"Automation":{"color":"CCAF60","name":"Automation","description":""},"hotfix":{"color":"BA3F1D","name":"hotfix","description":""},"Team Managers Pod":{"color":"bddb81","name":"Team Managers Pod","description":"Issues that team managers care about for the security and efficiency of their teams"},"API pane":{"color":"e417c7","name":"API pane","description":"API configuration section"},"Import-Export-App":{"color":"a7768a","name":"Import-Export-App","description":"Issues related to importing and exporting apps"},"High effort":{"color":"A7E87B","name":"High effort","description":"Something that'll take more than a month to build"},"ACL":{"color":"747224","name":"ACL","description":"User permissions and access controls"},"Telemetry":{"color":"bc70f9","name":"Telemetry","description":"Issues related to instrumenting appsmith"},"Radio Widget":{"color":"91ef15","name":"Radio Widget","description":""},"Omnibar":{"color":"10b5ce","name":"Omnibar","description":"Issues related to the omnibar for navigation"},"Button Widget":{"color":"34efae","name":"Button Widget","description":""},"Switch widget":{"color":"33A8CE","name":"Switch widget","description":"The switch widget"},"Map Widget":{"color":"7eef7a","name":"Map Widget","description":""},"UI Building Pod":{"color":"e2ffb2","name":"UI Building Pod","description":""},"Task":{"color":"085630","name":"Task","description":"A simple Todo"},"Design System":{"color":"12b715","name":"Design System","description":"Design system"},"opera":{"color":"C63F5B","name":"opera","description":"Any issues identified on the opera browser"},"Login / Signup":{"color":"949fe0","name":"Login / Signup","description":"Authentication flows"},"Image Widget":{"color":"8de8ad","name":"Image Widget","description":""},"firefox":{"color":"6d56e2","name":"firefox","description":""},"Property Pane":{"color":"b356ff","name":"Property Pane","description":"Issues related to the behaviour of the property pane"},"Deployment":{"color":"93491f","name":"Deployment","description":"Installation process of appsmith"},"Critical":{"color":"9b1b28","name":"Critical","description":"This issue needs immediate attention. Drop everything else"},"IDE":{"color":"61b2ee","name":"IDE","description":"Issues related to the IDE"},"Production":{"color":"b60205","name":"Production","description":""},"Dependencies":{"color":"0366d6","name":"Dependencies","description":"Pull requests that update a dependency file"},"Actions Pod":{"color":"61ed84","name":"Actions Pod","description":"Issues picked up by the action pod"},"Google Sheets":{"color":"51D86A","name":"Google Sheets","description":"Issues related to Google Sheets"},"Icon Button Widget":{"color":"D319CE","name":"Icon Button Widget","description":"Issues related to the icon button widget"},"Mongo":{"color":"fef2c0","name":"Mongo","description":"Issues related to Mongo DB plugin"},"Documentation":{"color":"a8dff7","name":"Documentation","description":"Improvements or additions to documentation"},"TestGap":{"color":"f28253","name":"TestGap","description":"Issues identified for test plan improvement"},"keyboard shortcut":{"color":"0688B6","name":"keyboard shortcut","description":""},"Git Version Control":{"color":"C4568E","name":"Git Version Control","description":"Issues related to version control"},"Reopen":{"color":"897548","name":"Reopen","description":""},"Redshift":{"color":"ABAEB5","name":"Redshift","description":"Issues related to the redshift integration"},"Date Picker Widget":{"color":"ef1ce1","name":"Date Picker Widget","description":""},"Entity Explorer":{"color":"a2e2f9","name":"Entity Explorer","description":"Issues related to navigation using the entity explorer"},"JS Linting & Errors":{"color":"E56AA5","name":"JS Linting & Errors","description":"Issues related to JS Linting and errors"},"iFrame":{"color":"3CD1DB","name":"iFrame","description":"Issues related to iFrame"},"Stale":{"color":"ededed","name":"Stale","description":null},"Debugger":{"color":"e79062","name":"Debugger","description":"Issues related to the debugger"},"Quick effort":{"color":"95ED65","name":"Quick effort","description":"Something that'll take a few hours to build"},"Text Widget":{"color":"d130d1","name":"Text Widget","description":""},"Video Widget":{"color":"23dd4b","name":"Video Widget","description":""},"Datasources":{"color":"f285e1","name":"Datasources","description":"Issues related to configuring datasource on appsmith"},"error":{"color":"B66773","name":"error","description":"All issues connected to error messages"},"Form Widget":{"color":"09ed77","name":"Form Widget","description":""},"Needs Triaging":{"color":"e8b851","name":"Needs Triaging","description":"Needs attention from maintainers to triage"},"Query Editor":{"color":"8887af","name":"Query Editor","description":"The section where a user can write DB queries."},"Autocomplete":{"color":"235708","name":"Autocomplete","description":"Issues related to the autocomplete"},"hacktoberfest":{"color":"0052cc","name":"hacktoberfest","description":"All issues that can be solved by the community during Hacktoberfest"},"Medium effort":{"color":"D31156","name":"Medium effort","description":"Something that'll take more than a week but less than a month to build"},"Release":{"color":"57e5e0","name":"Release","description":""},"High":{"color":"c94d14","name":"High","description":"This issue blocks a user from building or impacts a lot of users"},"Platform Pod":{"color":"500B69","name":"Platform Pod","description":"All issues related to using the appsmith platform"},"UI Performance":{"color":"1799b0","name":"UI Performance","description":"Issues related to UI performance"},"UI Builders Pod":{"color":"517fba","name":"UI Builders Pod","description":"Issues that UI Builders face using appsmith"},"Deploy Preview":{"color":"bfdadc","name":"Deploy Preview","description":"Issues found in Deploy Preview"},"Needs Tests":{"color":"8ee263","name":"Needs Tests","description":"Needs automated tests to assert a feature/bug fix"},"Refactor":{"color":"B96662","name":"Refactor","description":"needs refactoring of code"},"Divider Widget":{"color":"235708","name":"Divider Widget","description":"Issues related to the divider widget"},"Table Widget":{"color":"2eead1","name":"Table Widget","description":""},"Needs More Info":{"color":"e54c10","name":"Needs More Info","description":"Needs additional information"},"Good First Issue":{"color":"7057ff","name":"Good First Issue","description":"Good for newcomers"},"UI Improvement":{"color":"9aeef4","name":"UI Improvement","description":""},"Backend":{"color":"d4c5f9","name":"Backend","description":"This marks the issue or pull request to reference server code"},"Frontend":{"color":"87c7f2","name":"Frontend","description":"This label marks the issue or pull request to reference client code"},"In App Comms":{"color":"9168f4","name":"In App Comms","description":"Issues around communication with appsmith instances"},"Chart Widget":{"color":"616ecc","name":"Chart Widget","description":""},"regression":{"color":"ffe5bc","name":"regression","description":""},"List Widget":{"color":"8508A0","name":"List Widget","description":"Issues related to the list widget"},"Duplicate":{"color":"cfd3d7","name":"Duplicate","description":"This issue or pull request already exists"},"JS Snippets":{"color":"8d62d2","name":"JS Snippets","description":"issues related to JS Snippets"},"Copy Paste":{"name":"Copy Paste","description":"Issues related to copy paste","color":"b4f0a9"},"Drag & Drop":{"name":"Drag & Drop","description":"Issues related to the drag & drop experience","color":"92115a"},"SQL":{"name":"SQL","description":"Issues related to SQL Datasources","color":"a1633e"},"BE Coders Pod":{"color":"5d9848","name":"BE Coders Pod","description":"Issues related to users writing code to fetch and update data"},"FE Coders Pod":{"color":"a7effc","name":"FE Coders Pod","description":"Issues related to users writing javascript in appsmith"},"New Developers Pod":{"color":"6310da","name":"New Developers Pod","description":"Issues that new developers face while exploring the IDE"},"Sniping Mode":{"name":"Sniping Mode","description":"Issues related to sniping mode","color":"6310da"},"Redis":{"name":"Redis","description":"Issues related to Redis","color":"8b19cc"},"New Datasource":{"color":"9c0cf7","name":"New Datasource","description":"Requests for new datasources"},"Query Execution":{"color":"9c0cf7","name":"Query Execution","description":"Issues related to API / Query execution"},"Evaluated Value":{"name":"Evaluated Value","description":"Issues related to evaluated values","color":"39f6e7"},"Undo/Redo":{"name":"Undo/Redo","description":"Issues related to undo/redo","color":"f25880"},"App Navigation":{"name":"App Navigation","description":"Issues related to the topbar navigation and configuring it","color":"12b715"},"Responsive Viewport":{"color":"12b715","name":"Responsive Viewport","description":"Issues seen on different viewports like mobile"},"Canvas Zoom":{"name":"Canvas Zoom","description":"Issues related to zooming the canvas","color":"57da0d"},"Widgets Pane":{"name":"Widgets Pane","description":"Issues related to the discovery and organisation of widgets","color":"ad5d78"},"Invite users":{"color":"1799b0","name":"Invite users","description":"Invite users flow and any associated actions"},"View Mode":{"color":"1799b0","name":"View Mode","description":"Issues related to the view mode"},"User Education Pod":{"name":"User Education Pod","description":"Issues related to user education","color":"1799b0"},"Content":{"name":"Content","description":"For content related topics i.e blogs, templates, videos","color":"a8dff7"},"Embedding Apps":{"name":"Embedding Apps","description":"Issues related to embedding","color":"849aff"},"Slash Command":{"name":"Slash Command","description":"Issues related to the slash command","color":"a0608e"},"Widget Property":{"name":"Widget Property","description":"Issues related to adding / modifying widget properties across widgets","color":"5e92cb"},"Windows":{"name":"Windows","description":"Issues related exclusively to Windows systems","color":"b4cb8a"},"Old App Issues":{"name":"Old App Issues","description":"Issues related to apps old apps a few weeks old and app issues in stale browser session","color":"87ab18"},"Document Viewer Widget":{"name":"Document Viewer Widget","description":"Issues related to Document Viewer Widget","color":"899d4b"},"Radio Group Widget":{"name":"Radio Group Widget","description":"Issues related to radio group widget","color":"b68495"},"Super Admin":{"name":"Super Admin","description":"Issues related to the super admin page","color":"aa95cf"},"Postgres":{"name":"Postgres","description":"Postgres related issues","color":"b68495"},"REST API plugin":{"name":"REST API plugin","description":"REST API plugin related issues","color":"9f538c"},"New JS Function":{"name":"New JS Function","description":"Issues related to adding a JS Function","color":"8e8aa4"},"Cannot Reproduce Issue":{"color":"93c9cc","name":"Cannot Reproduce Issue","description":"Issues that cannot be reproduced"},"Widget Grouping":{"name":"Widget Grouping","description":"Issues related to Widget Grouping","color":"a49951"},"K8s":{"name":"K8s","description":"Kubernetes related issues","color":"5f318a"},"Docker":{"name":"Docker","description":"Issues related to docker","color":"89b808"},"Camera Widget":{"name":"Camera Widget","description":"Issues and enhancements related to camera widget","color":"c7ace5"},"SAAS Plugins":{"name":"SAAS Plugins","description":"Issues related to SAAS Plugins","color":"ef9c9d"},"UQI components":{"name":"UQI components","description":"UQI specifically for components like sorting pagination and projection","color":"d7771f"},"UQI validations":{"name":"UQI validations","description":"validations for UQI datasources and action forms","color":"d7771f"},"Action form":{"name":"Action form","description":"Action forms for queries and API operations","color":"d7771f"},"UQI migration":{"name":"UQI migration","description":"migration of various datasources to uqi","color":"d7771f"},"JS Promises":{"name":"JS Promises","description":"Issues related to promises","color":"d7771f"},"OnPageLoad":{"name":"OnPageLoad","description":"OnPageLoad settings for JS functions","color":"63744e"},"Function execution":{"name":"Function execution","description":"JS function execution","color":"a302b0"},"JS Refactoring":{"name":"JS Refactoring","description":"cascading refactors to user JS due to user changes","color":"a302b0"},"JS Usability":{"name":"JS Usability","description":"usability issues with JS editor and JS elsewhere","color":"a302b0"},"Currency Input Widget":{"name":"Currency Input Widget","description":"Issues related to currency input widget","color":"b2164f"},"TreeSelect":{"name":"TreeSelect","description":"Issues related to TreeSelect Widget","color":"a1633e"},"MultiTree Select Widget":{"name":"MultiTree Select Widget","description":"Issues related to MultiTree Select Widget","color":"a1633e"},"Welcome Screen":{"name":"Welcome Screen","description":"Issues related to the welcome screen","color":"3897be"},"Query Templates":{"name":"Query Templates","description":"Issues related to query templates","color":"8f02d6"},"Realtime Commenting":{"color":"a70b86","name":"Realtime Commenting","description":"In-app communication between teams"},"Phone Input Widget":{"name":"Phone Input Widget","description":"Issues related to the Phone Input widget","color":"a70b86"},"JSON Form":{"name":"JSON Form","description":"Issue / features related to the JSON form wiget","color":"46b209"},"All Widgets":{"name":"All Widgets","description":"Issues related to all widgets","color":"972b36"},"V1":{"name":"V1","description":"V1","color":"67ab2e"},"Plugin Development":{"name":"Plugin Development","description":"Issues related to plugin development","color":"5e9d7b"},"Reflow & Resize":{"name":"Reflow & Resize","description":"All issues related to reflow and resize experience","color":"748a13"},"App Theming":{"name":"App Theming","description":"Items that are related to the App level theming controls epic","color":"8bf430"},"SSO":{"name":"SSO","description":"Issues, requests and enhancements around Single sign-on.","color":"bf019b"},"Multi User Realtime":{"name":"Multi User Realtime","description":"Issues related to multiple users using or editing an application","color":"e7b6ce"},"Templates":{"name":"Templates","description":"Issues related to Templates","color":"c3b541"},"Ready for design":{"name":"Ready for design","description":"this issue is ready for design: it contains clear problem statements and other required information","color":"ebf442"},"Support":{"name":"Support","description":"Issues created by the A-force team to address user queries","color":"1740f3"},"Button Group widget":{"name":"Button Group widget","description":"Issue and enhancements related to the button group widget","color":"f17025"},"GraphQL Plugin":{"name":"GraphQL Plugin","description":"Issues related to GraphQL plugin","color":"afde1c"},"DevOps Pod":{"name":"DevOps Pod","description":"Issues related to devops","color":"d956c7"},"medium":{"name":"medium","description":"Issues that frustrate users due to poor UX","color":"23dfd9"},"ArangoDB":{"name":"ArangoDB","description":"Issues related to arangoDB","color":"c881a5"},"SmartJSONSubstitution":{"name":"SmartJSONSubstitution","description":"Issues related to Smart JSON substitution of mustache bindings","color":"76310e"},"smartBSONsubstitution":{"name":"smartBSONsubstitution","description":"","color":"76310e"},"Code Refactoring":{"name":"Code Refactoring","description":"Issues related to code refactoring","color":"76310e"},"Progress bar widget":{"name":"Progress bar widget","description":"To track issues related to progress bar","color":"2d7abf"},"Audio Recorder Widget":{"name":"Audio Recorder Widget","description":"Issues related to Audio Recorder Widget","color":"9accef"},"Airtable":{"name":"Airtable","description":"Issues for Airtable","color":"9accef"},"dynamic height":{"name":"dynamic height","description":"","color":"22a5df"},"RBAC":{"name":"RBAC","description":"Issues, requests and enhancements around RBAC.","color":"5cfd3d"}}} \ No newline at end of file +{"runners":[{"versioning":{"source":"milestones","type":"SemVer"},"prereleaseName":"alpha","issue":{"labels":{"Team Managers Pod":{"conditions":[{"label":"Login / Signup","type":"hasLabel","value":true},{"label":"Settings","type":"hasLabel","value":true},{"label":"Git Version Control","type":"hasLabel","value":true},{"label":"Home Page","type":"hasLabel","value":true},{"label":"Import-Export-App","type":"hasLabel","value":true},{"label":"advanced","type":"hasLabel","value":true},{"label":"Team Managers Pod","type":"hasLabel","value":true},{"label":"Invite users","type":"hasLabel","value":true},{"label":"ACL","type":"hasLabel","value":true},{"label":"Realtime Commenting","type":"hasLabel","value":true},{"label":"SSO","type":"hasLabel","value":true},{"label":"Multi User Realtime","type":"hasLabel","value":true},{"label":"RBAC","type":"hasLabel","value":true}],"requires":1},"New Developers Pod":{"conditions":[{"label":"Fork App","type":"hasLabel","value":true},{"label":"Omnibar","type":"hasLabel","value":true},{"label":"Onboarding","type":"hasLabel","value":true},{"label":"Telemetry","type":"hasLabel","value":true},{"label":"Entity Explorer","type":"hasLabel","value":true},{"label":"Generate Page","type":"hasLabel","value":true},{"label":"IDE","type":"hasLabel","value":true},{"label":"In App Comms","type":"hasLabel","value":true},{"label":"New Developers Pod","type":"hasLabel","value":true},{"label":"Sniping Mode","type":"hasLabel","value":true},{"label":"Design System","type":"hasLabel","value":true},{"label":"Example Apps","type":"hasLabel","value":true},{"label":"i18n","type":"hasLabel","value":true},{"label":"Welcome Screen","type":"hasLabel","value":true},{"label":"Templates","type":"hasLabel","value":true}],"requires":1},"BE Coders Pod":{"conditions":[{"label":"Datasources","type":"hasLabel","value":true},{"label":"Firestore","type":"hasLabel","value":true},{"label":"Google Sheets","type":"hasLabel","value":true},{"label":"Mongo","type":"hasLabel","value":true},{"label":"MySQL","type":"hasLabel","value":true},{"label":"Redshift","type":"hasLabel","value":true},{"label":"UQI","type":"hasLabel","value":true},{"label":"Query Editor","type":"hasLabel","value":true},{"label":"API pane","type":"hasLabel","value":true},{"label":"snowflake","type":"hasLabel","value":true},{"label":"S3","type":"hasLabel","value":true},{"label":"BE Coders Pod","type":"hasLabel","value":true},{"label":"Redis","type":"hasLabel","value":true},{"label":"New Datasource","type":"hasLabel","value":true},{"label":"Query Execution","type":"hasLabel","value":true},{"label":"Postgres","type":"hasLabel","value":true},{"label":"REST API plugin","type":"hasLabel","value":true},{"label":"SAAS Plugins","type":"hasLabel","value":true},{"label":"UQI components","type":"hasLabel","value":true},{"label":"UQI validations","type":"hasLabel","value":true},{"label":"Action form","type":"hasLabel","value":true},{"label":"UQI migration","type":"hasLabel","value":true},{"label":"SQL","type":"hasLabel","value":true},{"label":"Query Templates","type":"hasLabel","value":true},{"label":"Plugin Development","type":"hasLabel","value":true},{"label":"GraphQL Plugin","type":"hasLabel","value":true},{"label":"ArangoDB","type":"hasLabel","value":true},{"label":"SmartJSONSubstitution","type":"hasLabel","value":true},{"label":"smartBSONsubstitution","type":"hasLabel","value":true},{"label":"Airtable","type":"hasLabel","value":true},{"label":"CURL","type":"hasLabel","value":true}],"requires":1},"FE Coders Pod":{"conditions":[{"label":"JS Linting & Errors","type":"hasLabel","value":true},{"label":"JS Editor","type":"hasLabel","value":true},{"label":"Debugger","type":"hasLabel","value":true},{"label":"JS","type":"hasLabel","value":true},{"label":"JS Snippets","type":"hasLabel","value":true},{"label":"Autocomplete","type":"hasLabel","value":true},{"label":"FE Coders Pod","type":"hasLabel","value":true},{"label":"Evaluated Value","type":"hasLabel","value":true},{"label":"Slash Command","type":"hasLabel","value":true},{"label":"New JS Function","type":"hasLabel","value":true},{"label":"JS Promises","type":"hasLabel","value":true},{"label":"OnPageLoad","type":"hasLabel","value":true},{"label":"Function execution","type":"hasLabel","value":true},{"label":"JS Refactoring","type":"hasLabel","value":true},{"label":"JS Usability","type":"hasLabel","value":true},{"label":"Code Refactoring","type":"hasLabel","value":true}],"requires":1},"App Viewers Pod":{"conditions":[{"label":"Button Widget","type":"hasLabel","value":true},{"label":"Chart Widget","type":"hasLabel","value":true},{"label":"Checkbox Widget","type":"hasLabel","value":true},{"label":"Container Widget","type":"hasLabel","value":true},{"label":"Date Picker Widget","type":"hasLabel","value":true},{"label":"Select Widget","type":"hasLabel","value":true},{"label":"File Picker Widget","type":"hasLabel","value":true},{"label":"Form Widget","type":"hasLabel","value":true},{"label":"Image Widget","type":"hasLabel","value":true},{"label":"Input Widget","type":"hasLabel","value":true},{"label":"List Widget","type":"hasLabel","value":true},{"label":"MultiSelect Widget","type":"hasLabel","value":true},{"label":"Map Widget","type":"hasLabel","value":true},{"label":"Modal Widget","type":"hasLabel","value":true},{"label":"Radio Widget","type":"hasLabel","value":true},{"label":"Rich Text Editor Widget","type":"hasLabel","value":true},{"label":"Tab Widget","type":"hasLabel","value":true},{"label":"Table Widget","type":"hasLabel","value":true},{"label":"Text Widget","type":"hasLabel","value":true},{"label":"Video Widget","type":"hasLabel","value":true},{"label":"iFrame","type":"hasLabel","value":true},{"label":"Menu Button","type":"hasLabel","value":true},{"label":"Rating","type":"hasLabel","value":true},{"label":"Widget Validation","type":"hasLabel","value":true},{"label":"reallabel","type":"hasLabel","value":true},{"label":"New Widget","type":"hasLabel","value":true},{"label":"Switch widget","type":"hasLabel","value":true},{"label":"Widget Styling","type":"hasLabel","value":true},{"label":"Audio Widget","type":"hasLabel","value":true},{"label":"Icon Button Widget","type":"hasLabel","value":true},{"label":"Checkbox Group widget","type":"hasLabel","value":true},{"label":"Stat Box Widget","type":"hasLabel","value":true},{"label":"Voice Recorder Widget","type":"hasLabel","value":true},{"label":"Calendar Widget","type":"hasLabel","value":true},{"label":"Menu Button Widget","type":"hasLabel","value":true},{"label":"Divider Widget","type":"hasLabel","value":true},{"label":"Rating Widget","type":"hasLabel","value":true},{"label":"App Viewers Pod","type":"hasLabel","value":true},{"label":"App Navigation","type":"hasLabel","value":true},{"label":"View Mode","type":"hasLabel","value":true},{"label":"Embedding Apps","type":"hasLabel","value":true},{"label":"Widget Property","type":"hasLabel","value":true},{"label":"Document Viewer Widget","type":"hasLabel","value":true},{"label":"Radio Group Widget","type":"hasLabel","value":true},{"label":"Currency Input Widget","type":"hasLabel","value":true},{"label":"TreeSelect","type":"hasLabel","value":true},{"label":"MultiTree Select Widget","type":"hasLabel","value":true},{"label":"Phone Input Widget","type":"hasLabel","value":true},{"label":"JSON Form","type":"hasLabel","value":true},{"label":"All Widgets","type":"hasLabel","value":true},{"label":"App Theming","type":"hasLabel","value":true},{"label":"Button Group widget","type":"hasLabel","value":true},{"label":"Progress bar widget","type":"hasLabel","value":true},{"label":"Audio Recorder Widget","type":"hasLabel","value":true}],"requires":1},"UI Builders Pod":{"conditions":[{"label":"Property Pane","type":"hasLabel","value":true},{"label":"Pages","type":"hasLabel","value":true},{"label":"UI Builders Pod","type":"hasLabel","value":true},{"label":"Copy Paste","type":"hasLabel","value":true},{"label":"Drag & Drop","type":"hasLabel","value":true},{"label":"Undo/Redo","type":"hasLabel","value":true},{"label":"Responsive Viewport","type":"hasLabel","value":true},{"label":"Canvas Zoom","type":"hasLabel","value":true},{"label":"Widgets Pane","type":"hasLabel","value":true},{"label":"UI Performance","type":"hasLabel","value":true},{"label":"Widget Grouping","type":"hasLabel","value":true},{"label":"Reflow & Resize","type":"hasLabel","value":true},{"label":"dynamic height","type":"hasLabel","value":true},{"label":"Canvas / Grid","type":"hasLabel","value":true}],"requires":1},"User Education Pod":{"conditions":[{"label":"Content","type":"hasLabel","value":true},{"label":"Documentation","type":"hasLabel","value":true}],"requires":1},"Platform Pod":{"conditions":[{"label":"Platform Pod","type":"hasLabel","value":true},{"label":"Team Managers Pod","type":"hasLabel","value":true},{"label":"New Developers Pod","type":"hasLabel","value":true}],"requires":1},"Actions Pod":{"conditions":[{"label":"FE Coders Pod","type":"hasLabel","value":true},{"label":"BE Coders Pod","type":"hasLabel","value":true}],"requires":1},"UI Building Pod":{"conditions":[{"label":"App Viewers Pod","type":"hasLabel","value":true},{"label":"UI Builders Pod","type":"hasLabel","value":true}],"requires":1},"DevOps Pod":{"conditions":[{"label":"Docker","type":"hasLabel","value":true},{"label":"Super Admin","type":"hasLabel","value":true},{"label":"Deployment","type":"hasLabel","value":true},{"label":"K8s","type":"hasLabel","value":true},{"label":"Email Config","type":"hasLabel","value":true}],"requires":1},"RBAC":{"conditions":[],"requires":1}}},"root":"."}],"labels":{"Tab Widget":{"color":"e2c76c","name":"Tab Widget","description":""},"Dont merge":{"color":"ADB39C","name":"Dont merge","description":""},"Epic":{"color":"3E4B9E","name":"Epic","description":"A zenhub epic that describes a project"},"Menu Button Widget":{"color":"235708","name":"Menu Button Widget","description":"Issues related to Menu Button widget"},"advanced":{"color":"5f4115","name":"advanced","description":"Features aimed at advanced users"},"Checkbox Group widget":{"color":"D2ACD2","name":"Checkbox Group widget","description":"Issues related to Checkbox Group Widget"},"Input Widget":{"color":"ae65d8","name":"Input Widget","description":""},"Security":{"color":"99139C","name":"Security","description":""},"QA":{"color":"e2ca68","name":"QA","description":""},"Verified":{"color":"9bf416","name":"Verified","description":""},"Wont Fix":{"color":"ffffff","name":"Wont Fix","description":"This will not be worked on"},"MySQL":{"color":"B0F9F4","name":"MySQL","description":""},"Development":{"color":"9F8A02","name":"Development","description":""},"Help Wanted":{"color":"008672","name":"Help Wanted","description":"Extra attention is needed"},"Home Page":{"color":"9c0c8e","name":"Home Page","description":"Issues related to the application home page"},"Rating Widget":{"color":"235708","name":"Rating Widget","description":"Issues related to the rating widget"},"Stat Box Widget":{"color":"f1c9ce","name":"Stat Box Widget","description":"Issues related to stat box"},"Enhancement":{"color":"a2eeef","name":"Enhancement","description":"New feature or request"},"Settings":{"color":"f7ff60","name":"Settings","description":"organization, team & user settings"},"Fork App":{"color":"5369db","name":"Fork App","description":"Issues related to forking apps"},"Container Widget":{"color":"19AD0D","name":"Container Widget","description":"Container widget"},"Papercut":{"color":"B562F6","name":"Papercut","description":""},"community":{"color":"dded34","name":"community","description":"issues reported by community members"},"Needs Design":{"color":"bfd4f2","name":"Needs Design","description":"needs design or changes to design"},"UQI":{"color":"FB8E9C","name":"UQI","description":""},"AutomationGap":{"color":"ed13bb","name":"AutomationGap","description":"Issues that needs automated tests"},"i18n":{"color":"1799b0","name":"i18n","description":"Represents issues that need to be tackled to handle internationalization"},"Rich Text Editor Widget":{"color":"f72cac","name":"Rich Text Editor Widget","description":""},"Onboarding":{"color":"d5794b","name":"Onboarding","description":"Issues related to onboarding new developers"},"Pages":{"color":"d7fd80","name":"Pages","description":"Issues related to configuring pages"},"skip-changelog":{"color":"06086F","name":"skip-changelog","description":"Adding this label to a PR prevents it from being listed in the changelog"},"Low":{"color":"79e53b","name":"Low","description":"An issue that is neither critical nor breaks a user flow"},"potential-duplicate":{"color":"d3cb2e","name":"potential-duplicate","description":"This label marks issues that are potential duplicates of already open issues"},"Audio Widget":{"color":"447B9A","name":"Audio Widget","description":"Issues related to Audio Widget"},"Firestore":{"color":"F1C2DF","name":"Firestore","description":"Issues related to the firestore Integration"},"New Widget":{"color":"be4cf2","name":"New Widget","description":"A request for a new widget"},"Performance":{"color":"d30e53","name":"Performance","description":"Page Load and evaluations"},"Modal Widget":{"color":"03846f","name":"Modal Widget","description":""},"UX Improvement":{"color":"f4a089","name":"UX Improvement","description":""},"S3":{"color":"c57928","name":"S3","description":"Issues related to the S3 plugin"},"Release Blocker":{"color":"5756bf","name":"Release Blocker","description":"This issue must be resolved before the release"},"safari":{"color":"51C6AA","name":"safari","description":"Bugs seen on safari browser"},"Example Apps":{"color":"1799b0","name":"Example Apps","description":"Example apps created for new signups"},"MultiSelect Widget":{"color":"AB62D4","name":"MultiSelect Widget","description":"Issues related to MultiSelect Widget"},"JS Editor":{"color":"48b992","name":"JS Editor","description":"Issues related to JS Editor"},"Widget Styling":{"color":"37EA75","name":"Widget Styling","description":"all about widget styling"},"Calendar Widget":{"color":"8c6644","name":"Calendar Widget","description":""},"JS":{"color":"e46785","name":"JS","description":"Issues related to JS on the platform"},"Website":{"color":"151720","name":"Website","description":"Related to www.appsmith.com website"},"Low effort":{"color":"8B59F0","name":"Low effort","description":"Something that'll take a few days to build"},"App Viewers Pod":{"color":"cd8ef9","name":"App Viewers Pod","description":"This label assigns issues to the app viewers pod"},"Checkbox Widget":{"color":"074ac6","name":"Checkbox Widget","description":""},"Spam":{"color":"620faf","name":"Spam","description":""},"Voice Recorder Widget":{"color":"85bc87","name":"Voice Recorder Widget","description":""},"Select Widget":{"color":"0c669e","name":"Select Widget","description":"Select or dropdown widget"},"Bug":{"color":"d73a4a","name":"Bug","description":"Something isn't working"},"Widget Validation":{"color":"6990BC","name":"Widget Validation","description":"Issues related to widget property validation"},"Generate Page":{"color":"f14274","name":"Generate Page","description":"Issures related to page generation"},"File Picker Widget":{"color":"6ae4f2","name":"File Picker Widget","description":""},"snowflake":{"color":"47075c","name":"snowflake","description":"Issues related to the snowflake Integration"},"Automation":{"color":"CCAF60","name":"Automation","description":""},"hotfix":{"color":"BA3F1D","name":"hotfix","description":""},"Team Managers Pod":{"color":"bddb81","name":"Team Managers Pod","description":"Issues that team managers care about for the security and efficiency of their teams"},"API pane":{"color":"e417c7","name":"API pane","description":"API configuration section"},"Import-Export-App":{"color":"a7768a","name":"Import-Export-App","description":"Issues related to importing and exporting apps"},"High effort":{"color":"A7E87B","name":"High effort","description":"Something that'll take more than a month to build"},"ACL":{"color":"747224","name":"ACL","description":"User permissions and access controls"},"Telemetry":{"color":"bc70f9","name":"Telemetry","description":"Issues related to instrumenting appsmith"},"Radio Widget":{"color":"91ef15","name":"Radio Widget","description":""},"Omnibar":{"color":"10b5ce","name":"Omnibar","description":"Issues related to the omnibar for navigation"},"Button Widget":{"color":"34efae","name":"Button Widget","description":""},"Switch widget":{"color":"33A8CE","name":"Switch widget","description":"The switch widget"},"Map Widget":{"color":"7eef7a","name":"Map Widget","description":""},"UI Building Pod":{"color":"e2ffb2","name":"UI Building Pod","description":""},"Task":{"color":"085630","name":"Task","description":"A simple Todo"},"Design System":{"color":"12b715","name":"Design System","description":"Design system"},"opera":{"color":"C63F5B","name":"opera","description":"Any issues identified on the opera browser"},"Login / Signup":{"color":"949fe0","name":"Login / Signup","description":"Authentication flows"},"Image Widget":{"color":"8de8ad","name":"Image Widget","description":""},"firefox":{"color":"6d56e2","name":"firefox","description":""},"Property Pane":{"color":"b356ff","name":"Property Pane","description":"Issues related to the behaviour of the property pane"},"Deployment":{"color":"93491f","name":"Deployment","description":"Installation process of appsmith"},"Critical":{"color":"9b1b28","name":"Critical","description":"This issue needs immediate attention. Drop everything else"},"IDE":{"color":"61b2ee","name":"IDE","description":"Issues related to the IDE"},"Production":{"color":"b60205","name":"Production","description":""},"Dependencies":{"color":"0366d6","name":"Dependencies","description":"Pull requests that update a dependency file"},"Actions Pod":{"color":"61ed84","name":"Actions Pod","description":"Issues picked up by the action pod"},"Google Sheets":{"color":"51D86A","name":"Google Sheets","description":"Issues related to Google Sheets"},"Icon Button Widget":{"color":"D319CE","name":"Icon Button Widget","description":"Issues related to the icon button widget"},"Mongo":{"color":"fef2c0","name":"Mongo","description":"Issues related to Mongo DB plugin"},"Documentation":{"color":"a8dff7","name":"Documentation","description":"Improvements or additions to documentation"},"TestGap":{"color":"f28253","name":"TestGap","description":"Issues identified for test plan improvement"},"keyboard shortcut":{"color":"0688B6","name":"keyboard shortcut","description":""},"Git Version Control":{"color":"C4568E","name":"Git Version Control","description":"Issues related to version control"},"Reopen":{"color":"897548","name":"Reopen","description":""},"Redshift":{"color":"ABAEB5","name":"Redshift","description":"Issues related to the redshift integration"},"Date Picker Widget":{"color":"ef1ce1","name":"Date Picker Widget","description":""},"Entity Explorer":{"color":"a2e2f9","name":"Entity Explorer","description":"Issues related to navigation using the entity explorer"},"JS Linting & Errors":{"color":"E56AA5","name":"JS Linting & Errors","description":"Issues related to JS Linting and errors"},"iFrame":{"color":"3CD1DB","name":"iFrame","description":"Issues related to iFrame"},"Stale":{"color":"ededed","name":"Stale","description":null},"Debugger":{"color":"e79062","name":"Debugger","description":"Issues related to the debugger"},"Quick effort":{"color":"95ED65","name":"Quick effort","description":"Something that'll take a few hours to build"},"Text Widget":{"color":"d130d1","name":"Text Widget","description":""},"Video Widget":{"color":"23dd4b","name":"Video Widget","description":""},"Datasources":{"color":"f285e1","name":"Datasources","description":"Issues related to configuring datasource on appsmith"},"error":{"color":"B66773","name":"error","description":"All issues connected to error messages"},"Form Widget":{"color":"09ed77","name":"Form Widget","description":""},"Needs Triaging":{"color":"e8b851","name":"Needs Triaging","description":"Needs attention from maintainers to triage"},"Query Editor":{"color":"8887af","name":"Query Editor","description":"The section where a user can write DB queries."},"Autocomplete":{"color":"235708","name":"Autocomplete","description":"Issues related to the autocomplete"},"hacktoberfest":{"color":"0052cc","name":"hacktoberfest","description":"All issues that can be solved by the community during Hacktoberfest"},"Medium effort":{"color":"D31156","name":"Medium effort","description":"Something that'll take more than a week but less than a month to build"},"Release":{"color":"57e5e0","name":"Release","description":""},"High":{"color":"c94d14","name":"High","description":"This issue blocks a user from building or impacts a lot of users"},"Platform Pod":{"color":"500B69","name":"Platform Pod","description":"All issues related to using the appsmith platform"},"UI Performance":{"color":"1799b0","name":"UI Performance","description":"Issues related to UI performance"},"UI Builders Pod":{"color":"517fba","name":"UI Builders Pod","description":"Issues that UI Builders face using appsmith"},"Deploy Preview":{"color":"bfdadc","name":"Deploy Preview","description":"Issues found in Deploy Preview"},"Needs Tests":{"color":"8ee263","name":"Needs Tests","description":"Needs automated tests to assert a feature/bug fix"},"Refactor":{"color":"B96662","name":"Refactor","description":"needs refactoring of code"},"Divider Widget":{"color":"235708","name":"Divider Widget","description":"Issues related to the divider widget"},"Table Widget":{"color":"2eead1","name":"Table Widget","description":""},"Needs More Info":{"color":"e54c10","name":"Needs More Info","description":"Needs additional information"},"Good First Issue":{"color":"7057ff","name":"Good First Issue","description":"Good for newcomers"},"UI Improvement":{"color":"9aeef4","name":"UI Improvement","description":""},"Backend":{"color":"d4c5f9","name":"Backend","description":"This marks the issue or pull request to reference server code"},"Frontend":{"color":"87c7f2","name":"Frontend","description":"This label marks the issue or pull request to reference client code"},"In App Comms":{"color":"9168f4","name":"In App Comms","description":"Issues around communication with appsmith instances"},"Chart Widget":{"color":"616ecc","name":"Chart Widget","description":""},"regression":{"color":"ffe5bc","name":"regression","description":""},"List Widget":{"color":"8508A0","name":"List Widget","description":"Issues related to the list widget"},"Duplicate":{"color":"cfd3d7","name":"Duplicate","description":"This issue or pull request already exists"},"JS Snippets":{"color":"8d62d2","name":"JS Snippets","description":"issues related to JS Snippets"},"Copy Paste":{"name":"Copy Paste","description":"Issues related to copy paste","color":"b4f0a9"},"Drag & Drop":{"name":"Drag & Drop","description":"Issues related to the drag & drop experience","color":"92115a"},"SQL":{"name":"SQL","description":"Issues related to SQL Datasources","color":"a1633e"},"BE Coders Pod":{"color":"5d9848","name":"BE Coders Pod","description":"Issues related to users writing code to fetch and update data"},"FE Coders Pod":{"color":"a7effc","name":"FE Coders Pod","description":"Issues related to users writing javascript in appsmith"},"New Developers Pod":{"color":"6310da","name":"New Developers Pod","description":"Issues that new developers face while exploring the IDE"},"Sniping Mode":{"name":"Sniping Mode","description":"Issues related to sniping mode","color":"6310da"},"Redis":{"name":"Redis","description":"Issues related to Redis","color":"8b19cc"},"New Datasource":{"color":"9c0cf7","name":"New Datasource","description":"Requests for new datasources"},"Query Execution":{"color":"9c0cf7","name":"Query Execution","description":"Issues related to API / Query execution"},"Evaluated Value":{"name":"Evaluated Value","description":"Issues related to evaluated values","color":"39f6e7"},"Undo/Redo":{"name":"Undo/Redo","description":"Issues related to undo/redo","color":"f25880"},"App Navigation":{"name":"App Navigation","description":"Issues related to the topbar navigation and configuring it","color":"12b715"},"Responsive Viewport":{"color":"12b715","name":"Responsive Viewport","description":"Issues seen on different viewports like mobile"},"Canvas Zoom":{"name":"Canvas Zoom","description":"Issues related to zooming the canvas","color":"57da0d"},"Widgets Pane":{"name":"Widgets Pane","description":"Issues related to the discovery and organisation of widgets","color":"ad5d78"},"Invite users":{"color":"1799b0","name":"Invite users","description":"Invite users flow and any associated actions"},"View Mode":{"color":"1799b0","name":"View Mode","description":"Issues related to the view mode"},"User Education Pod":{"name":"User Education Pod","description":"Issues related to user education","color":"1799b0"},"Content":{"name":"Content","description":"For content related topics i.e blogs, templates, videos","color":"a8dff7"},"Embedding Apps":{"name":"Embedding Apps","description":"Issues related to embedding","color":"849aff"},"Slash Command":{"name":"Slash Command","description":"Issues related to the slash command","color":"a0608e"},"Widget Property":{"name":"Widget Property","description":"Issues related to adding / modifying widget properties across widgets","color":"5e92cb"},"Windows":{"name":"Windows","description":"Issues related exclusively to Windows systems","color":"b4cb8a"},"Old App Issues":{"name":"Old App Issues","description":"Issues related to apps old apps a few weeks old and app issues in stale browser session","color":"87ab18"},"Document Viewer Widget":{"name":"Document Viewer Widget","description":"Issues related to Document Viewer Widget","color":"899d4b"},"Radio Group Widget":{"name":"Radio Group Widget","description":"Issues related to radio group widget","color":"b68495"},"Super Admin":{"name":"Super Admin","description":"Issues related to the super admin page","color":"aa95cf"},"Postgres":{"name":"Postgres","description":"Postgres related issues","color":"b68495"},"REST API plugin":{"name":"REST API plugin","description":"REST API plugin related issues","color":"9f538c"},"New JS Function":{"name":"New JS Function","description":"Issues related to adding a JS Function","color":"8e8aa4"},"Cannot Reproduce Issue":{"color":"93c9cc","name":"Cannot Reproduce Issue","description":"Issues that cannot be reproduced"},"Widget Grouping":{"name":"Widget Grouping","description":"Issues related to Widget Grouping","color":"a49951"},"K8s":{"name":"K8s","description":"Kubernetes related issues","color":"5f318a"},"Docker":{"name":"Docker","description":"Issues related to docker","color":"89b808"},"Camera Widget":{"name":"Camera Widget","description":"Issues and enhancements related to camera widget","color":"c7ace5"},"SAAS Plugins":{"name":"SAAS Plugins","description":"Issues related to SAAS Plugins","color":"ef9c9d"},"UQI components":{"name":"UQI components","description":"UQI specifically for components like sorting pagination and projection","color":"d7771f"},"UQI validations":{"name":"UQI validations","description":"validations for UQI datasources and action forms","color":"d7771f"},"Action form":{"name":"Action form","description":"Action forms for queries and API operations","color":"d7771f"},"UQI migration":{"name":"UQI migration","description":"migration of various datasources to uqi","color":"d7771f"},"JS Promises":{"name":"JS Promises","description":"Issues related to promises","color":"d7771f"},"OnPageLoad":{"name":"OnPageLoad","description":"OnPageLoad settings for JS functions","color":"63744e"},"Function execution":{"name":"Function execution","description":"JS function execution","color":"a302b0"},"JS Refactoring":{"name":"JS Refactoring","description":"cascading refactors to user JS due to user changes","color":"a302b0"},"JS Usability":{"name":"JS Usability","description":"usability issues with JS editor and JS elsewhere","color":"a302b0"},"Currency Input Widget":{"name":"Currency Input Widget","description":"Issues related to currency input widget","color":"b2164f"},"TreeSelect":{"name":"TreeSelect","description":"Issues related to TreeSelect Widget","color":"a1633e"},"MultiTree Select Widget":{"name":"MultiTree Select Widget","description":"Issues related to MultiTree Select Widget","color":"a1633e"},"Welcome Screen":{"name":"Welcome Screen","description":"Issues related to the welcome screen","color":"3897be"},"Query Templates":{"name":"Query Templates","description":"Issues related to query templates","color":"8f02d6"},"Realtime Commenting":{"color":"a70b86","name":"Realtime Commenting","description":"In-app communication between teams"},"Phone Input Widget":{"name":"Phone Input Widget","description":"Issues related to the Phone Input widget","color":"a70b86"},"JSON Form":{"name":"JSON Form","description":"Issue / features related to the JSON form wiget","color":"46b209"},"All Widgets":{"name":"All Widgets","description":"Issues related to all widgets","color":"972b36"},"V1":{"name":"V1","description":"V1","color":"67ab2e"},"Plugin Development":{"name":"Plugin Development","description":"Issues related to plugin development","color":"5e9d7b"},"Reflow & Resize":{"name":"Reflow & Resize","description":"All issues related to reflow and resize experience","color":"748a13"},"App Theming":{"name":"App Theming","description":"Items that are related to the App level theming controls epic","color":"8bf430"},"SSO":{"name":"SSO","description":"Issues, requests and enhancements around Single sign-on.","color":"bf019b"},"Multi User Realtime":{"name":"Multi User Realtime","description":"Issues related to multiple users using or editing an application","color":"e7b6ce"},"Templates":{"name":"Templates","description":"Issues related to Templates","color":"c3b541"},"Ready for design":{"name":"Ready for design","description":"this issue is ready for design: it contains clear problem statements and other required information","color":"ebf442"},"Support":{"name":"Support","description":"Issues created by the A-force team to address user queries","color":"1740f3"},"Button Group widget":{"name":"Button Group widget","description":"Issue and enhancements related to the button group widget","color":"f17025"},"GraphQL Plugin":{"name":"GraphQL Plugin","description":"Issues related to GraphQL plugin","color":"afde1c"},"DevOps Pod":{"name":"DevOps Pod","description":"Issues related to devops","color":"d956c7"},"medium":{"name":"medium","description":"Issues that frustrate users due to poor UX","color":"23dfd9"},"ArangoDB":{"name":"ArangoDB","description":"Issues related to arangoDB","color":"c881a5"},"SmartJSONSubstitution":{"name":"SmartJSONSubstitution","description":"Issues related to Smart JSON substitution of mustache bindings","color":"76310e"},"smartBSONsubstitution":{"name":"smartBSONsubstitution","description":"","color":"76310e"},"Code Refactoring":{"name":"Code Refactoring","description":"Issues related to code refactoring","color":"76310e"},"Progress bar widget":{"name":"Progress bar widget","description":"To track issues related to progress bar","color":"2d7abf"},"Audio Recorder Widget":{"name":"Audio Recorder Widget","description":"Issues related to Audio Recorder Widget","color":"9accef"},"Airtable":{"name":"Airtable","description":"Issues for Airtable","color":"9accef"},"dynamic height":{"name":"dynamic height","description":"","color":"22a5df"},"RBAC":{"name":"RBAC","description":"Issues, requests and enhancements around RBAC.","color":"5cfd3d"},"Canvas / Grid":{"name":"Canvas / Grid","description":"Issues related to the canvas","color":"16b092"},"Email Config":{"name":"Email Config","description":"Issues related to configuring the email service","color":"2a21d1"},"CURL":{"name":"CURL","description":"Issues related to CURL impor","color":"4b78b6"}}} \ No newline at end of file diff --git a/app/client/cypress/fixtures/widgetSelection.json b/app/client/cypress/fixtures/widgetSelection.json index be88d3e195..a584ad7ad6 100644 --- a/app/client/cypress/fixtures/widgetSelection.json +++ b/app/client/cypress/fixtures/widgetSelection.json @@ -1,209 +1,256 @@ { - "dsl": { - "widgetName": "MainContainer", - "backgroundColor": "none", - "rightColumn": 1270, - "snapColumns": 64, - "detachFromLayout": true, - "widgetId": "0", - "topRow": 0, - "bottomRow": 820, - "containerStyle": "none", - "snapRows": 125, - "parentRowSpace": 1, - "type": "CANVAS_WIDGET", - "canExtend": true, - "version": 23, - "minHeight": 830, - "parentColumnSpace": 1, - "dynamicTriggerPathList": [], - "dynamicBindingPathList": [], - "leftColumn": 0, - "children": [ - { - "widgetName": "Chart1", - "rightColumn": 26, - "allowScroll": false, - "widgetId": "ypstklohw5", - "topRow": 4, - "bottomRow": 36, - "parentRowSpace": 10, - "isVisible": true, - "type": "CHART_WIDGET", - "version": 1, - "parentId": "0", - "isLoading": false, - "chartData": { - "3jzahcrorq": { - "seriesName": "Sales", - "data": [ - { - "x": "Mon", - "y": 10000 - }, - { - "x": "Tue", - "y": 12000 - }, - { - "x": "Wed", - "y": 32000 - }, - { - "x": "Thu", - "y": 28000 - }, - { - "x": "Fri", - "y": 14000 - }, - { - "x": "Sat", - "y": 19000 - }, - { - "x": "Sun", - "y": 36000 - } - ] - } - }, - "yAxisName": "Total Order Revenue $", - "parentColumnSpace": 19.65625, - "chartName": "Last week's revenue", - "leftColumn": 2, - "xAxisName": "Last Week", - "customFusionChartConfig": { - "type": "column2d", - "dataSource": { - "chart": { - "caption": "Last week's revenue", - "xAxisName": "Last Week", - "yAxisName": "Total Order Revenue $", - "theme": "fusion" + "dsl": { + "widgetName": "MainContainer", + "backgroundColor": "none", + "rightColumn": 1270, + "snapColumns": 64, + "detachFromLayout": true, + "widgetId": "0", + "topRow": 0, + "bottomRow": 1050, + "containerStyle": "none", + "snapRows": 125, + "parentRowSpace": 1, + "type": "CANVAS_WIDGET", + "canExtend": true, + "version": 58, + "minHeight": 830, + "parentColumnSpace": 1, + "dynamicTriggerPathList": [], + "dynamicBindingPathList": [], + "leftColumn": 0, + "children": [ + { + "labelTextSize": "0.875rem", + "boxShadow": "none", + "widgetName": "Chart1", + "rightColumn": 26, + "widgetId": "ypstklohw5", + "topRow": 4, + "bottomRow": 36, + "parentRowSpace": 10, + "isVisible": true, + "type": "CHART_WIDGET", + "version": 1, + "parentId": "0", + "isLoading": false, + "chartData": { + "3jzahcrorq": { + "seriesName": "Sales", + "data": [ + { + "x": "Mon", + "y": 10000 }, - "data": [ - { - "label": "Mon", - "value": 10000 - }, - { - "label": "Tue", - "value": 12000 - }, - { - "label": "Wed", - "value": 32000 - }, - { - "label": "Thu", - "value": 28000 - }, - { - "label": "Fri", - "value": 14000 - }, - { - "label": "Sat", - "value": 19000 - }, - { - "label": "Sun", - "value": 36000 - } - ], - "trendlines": [ - { - "line": [ - { - "startvalue": "38000", - "valueOnRight": "1", - "displayvalue": "Weekly Target" - } - ] - } - ] - } - }, - "chartType": "LINE_CHART" + { + "x": "Tue", + "y": 12000 + }, + { + "x": "Wed", + "y": 32000 + }, + { + "x": "Thu", + "y": 28000 + }, + { + "x": "Fri", + "y": 14000 + }, + { + "x": "Sat", + "y": 19000 + }, + { + "x": "Sun", + "y": 36000 + } + ] + } }, - { - "backgroundColor": "#FFFFFF", - "widgetName": "Container1", - "rightColumn": 62, - "widgetId": "6y21iarlp4", - "containerStyle": "card", - "topRow": 11, - "bottomRow": 51, - "parentRowSpace": 10, - "isVisible": true, - "type": "CONTAINER_WIDGET", - "version": 1, - "parentId": "0", - "isLoading": false, - "parentColumnSpace": 19.65625, - "leftColumn": 30, - "children": [ - { - "widgetName": "Canvas1", - "rightColumn": 629, - "detachFromLayout": true, - "widgetId": "jqasr1uss5", - "containerStyle": "none", - "topRow": 0, - "bottomRow": 400, - "parentRowSpace": 1, - "isVisible": true, - "canExtend": false, - "type": "CANVAS_WIDGET", - "version": 1, - "parentId": "6y21iarlp4", - "minHeight": 400, - "isLoading": false, - "parentColumnSpace": 1, - "leftColumn": 0, - "children": [] - } - ] + "yAxisName": "Total Order Revenue $", + "parentColumnSpace": 19.65625, + "chartName": "Last week's revenue", + "leftColumn": 2, + "borderRadius": "0px", + "xAxisName": "Last Week", + "customFusionChartConfig": { + "type": "column2d", + "dataSource": { + "chart": { + "caption": "Last week's revenue", + "xAxisName": "Last Week", + "yAxisName": "Total Order Revenue $", + "theme": "fusion" + }, + "data": [ + { + "label": "Mon", + "value": 10000 + }, + { + "label": "Tue", + "value": 12000 + }, + { + "label": "Wed", + "value": 32000 + }, + { + "label": "Thu", + "value": 28000 + }, + { + "label": "Fri", + "value": 14000 + }, + { + "label": "Sat", + "value": 19000 + }, + { + "label": "Sun", + "value": 36000 + } + ], + "trendlines": [ + { + "line": [ + { + "startvalue": "38000", + "valueOnRight": "1", + "displayvalue": "Weekly Target" + } + ] + } + ] + } }, - { - "image": "", - "widgetName": "Image1", - "rightColumn": 22, - "widgetId": "1t50avy6f1", - "topRow": 58, - "bottomRow": 70, - "parentRowSpace": 10, - "isVisible": true, - "type": "IMAGE_WIDGET", - "version": 1, - "parentId": "0", - "isLoading": false, - "maxZoomLevel": 1, - "parentColumnSpace": 19.65625, - "imageShape": "RECTANGLE", - "leftColumn": 6, - "defaultImage": "https://res.cloudinary.com/drako999/image/upload/v1589196259/default.png" - }, - { - "widgetName": "Button1", - "rightColumn": 18, - "isDefaultClickDisabled": true, - "widgetId": "41wgbhd5vp", - "buttonStyle": "PRIMARY_BUTTON", - "topRow": 44, - "bottomRow": 48, - "parentRowSpace": 10, - "isVisible": true, - "type": "BUTTON_WIDGET", - "version": 1, - "parentId": "0", - "isLoading": false, - "parentColumnSpace": 19.65625, - "leftColumn": 10, - "text": "Submit", - "isDisabled": false - } - ] - } - } \ No newline at end of file + "chartType": "LINE_CHART" + }, + { + "labelTextSize": "0.875rem", + "boxShadow": "none", + "backgroundColor": "#FFFFFF", + "widgetName": "Container1", + "rightColumn": 62, + "widgetId": "6y21iarlp4", + "containerStyle": "card", + "topRow": 11, + "bottomRow": 51, + "parentRowSpace": 10, + "isVisible": true, + "type": "CONTAINER_WIDGET", + "version": 1, + "parentId": "0", + "isLoading": false, + "parentColumnSpace": 19.65625, + "leftColumn": 30, + "borderRadius": "0px", + "children": [ + { + "labelTextSize": "0.875rem", + "boxShadow": "none", + "widgetName": "Canvas1", + "rightColumn": 629, + "detachFromLayout": true, + "widgetId": "jqasr1uss5", + "containerStyle": "none", + "topRow": 0, + "bottomRow": 400, + "parentRowSpace": 1, + "isVisible": true, + "canExtend": false, + "type": "CANVAS_WIDGET", + "version": 1, + "parentId": "6y21iarlp4", + "minHeight": 400, + "isLoading": false, + "parentColumnSpace": 1, + "leftColumn": 0, + "borderRadius": "0px", + "children": [] + } + ] + }, + { + "labelTextSize": "0.875rem", + "image": "", + "boxShadow": "none", + "widgetName": "Image1", + "rightColumn": 22, + "widgetId": "1t50avy6f1", + "topRow": 58, + "bottomRow": 70, + "parentRowSpace": 10, + "isVisible": true, + "type": "IMAGE_WIDGET", + "version": 1, + "parentId": "0", + "isLoading": false, + "maxZoomLevel": 1, + "parentColumnSpace": 19.65625, + "imageShape": "RECTANGLE", + "leftColumn": 6, + "borderRadius": "0px", + "defaultImage": "https://res.cloudinary.com/drako999/image/upload/v1589196259/default.png" + }, + { + "labelTextSize": "0.875rem", + "boxShadow": "none", + "widgetName": "Button1", + "rightColumn": 18, + "isDefaultClickDisabled": true, + "buttonColor": "#03B365", + "widgetId": "41wgbhd5vp", + "topRow": 44, + "bottomRow": 48, + "parentRowSpace": 10, + "isVisible": true, + "type": "BUTTON_WIDGET", + "version": 1, + "recaptchaType": "V3", + "parentId": "0", + "isLoading": false, + "parentColumnSpace": 19.65625, + "leftColumn": 10, + "borderRadius": "0px", + "buttonVariant": "PRIMARY", + "text": "Submit", + "isDisabled": false + }, + { + "boxShadow": "none", + "widgetName": "Camera1", + "isCanvas": false, + "displayName": "Camera", + "iconSVG": "/static/media/icon.79c0d6de.svg", + "topRow": 70, + "bottomRow": 103, + "parentRowSpace": 10, + "type": "CAMERA_WIDGET", + "hideCard": false, + "mode": "CAMERA", + "parentColumnSpace": 12.5625, + "leftColumn": 2, + "dynamicBindingPathList": [ + { + "key": "borderRadius" + } + ], + "isDisabled": false, + "key": "bybcx1x9lk", + "isMirrored": true, + "rightColumn": 27, + "widgetId": "wv1qtmzsbm", + "isVisible": true, + "version": 1, + "parentId": "0", + "renderMode": "CANVAS", + "isLoading": false, + "borderRadius": "{{appsmith.theme.borderRadius.appBorderRadius}}" + } + ] + } +} \ No newline at end of file diff --git a/app/client/cypress/integration/Smoke_TestSuite/Application/CommunityIssues_Spec.ts b/app/client/cypress/integration/Smoke_TestSuite/Application/CommunityIssues_Spec.ts index 7cf0ca2304..7adf444daf 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/Application/CommunityIssues_Spec.ts +++ b/app/client/cypress/integration/Smoke_TestSuite/Application/CommunityIssues_Spec.ts @@ -9,9 +9,8 @@ let homePage = ObjectsRegistry.HomePage, jsEditor = ObjectsRegistry.JSEditor, locator = ObjectsRegistry.CommonLocators; -describe("AForce - Community Issues page validations", function () { - - before(function () { +describe("AForce - Community Issues page validations", function() { + before(function() { agHelper.clearLocalStorageCache(); }); @@ -28,231 +27,267 @@ describe("AForce - Community Issues page validations", function () { cy.visit("/applications"); homePage.ImportApp("CommunityIssuesExport.json"); cy.wait("@importNewApplication").then((interception: any) => { - agHelper.Sleep() + agHelper.Sleep(); const { isPartialImport } = interception.response.body.data; if (isPartialImport) { // should reconnect modal - dataSources.ReconnectDataSourcePostgres("AForceDB") + dataSources.ReconnectDataSourcePostgres("AForceDB"); } else { - homePage.AssertImport() + homePage.AssertImport(); } //Validate table is not empty! - table.WaitUntilTableLoad() + table.WaitUntilTableLoad(); //Validating order of header columns! - table.AssertTableHeaderOrder("TypeTitleStatus+1CommentorsVotesAnswerUpVoteStatesupvote_ididgithub_issue_idauthorcreated_atdescriptionlabelsstatelinkupdated_at") + table.AssertTableHeaderOrder( + "TypeTitleStatus+1CommentorsVotesAnswerUpVoteStatesupvote_ididgithub_issue_idauthorcreated_atdescriptionlabelsstatelinkupdated_at", + ); //Validating hidden columns: - table.AssertHiddenColumns(['States', 'upvote_id', 'id', 'github_issue_id', 'author', 'created_at', 'description', 'labels', 'state', 'link', 'updated_at']) + table.AssertHiddenColumns([ + "States", + "upvote_id", + "id", + "github_issue_id", + "author", + "created_at", + "description", + "labels", + "state", + "link", + "updated_at", + ]); }); }); it("2. Validate table navigation with Server Side pagination enabled with Default selected row", () => { - ee.SelectEntityByName("Table1", 'WIDGETS') - agHelper.AssertExistingToggleState("serversidepagination", 'checked') + ee.SelectEntityByName("Table1", "WIDGETS"); + agHelper.AssertExistingToggleState("serversidepagination", "checked"); - agHelper.EvaluateExistingPropertyFieldValue("Default Selected Row") - .then($selectedRow => { + agHelper + .EvaluateExistingPropertyFieldValue("Default Selected Row") + .then(($selectedRow) => { selectedRow = Number($selectedRow); - table.AssertSelectedRow(selectedRow) + table.AssertSelectedRow(selectedRow); }); - agHelper.DeployApp() - table.WaitUntilTableLoad() + agHelper.DeployApp(); + table.WaitUntilTableLoad(); //Verify hidden columns are infact hidden in deployed app! - table.AssertTableHeaderOrder("TypeTitleStatus+1CommentorsVotesAnswerUpVote")//from case #1 + table.AssertTableHeaderOrder( + "TypeTitleStatus+1CommentorsVotesAnswerUpVote", + ); //from case #1 - table.AssertSelectedRow(selectedRow)//Assert default selected row + table.AssertSelectedRow(selectedRow); //Assert default selected row table.AssertPageNumber(1); - table.NavigateToNextPage()//page 2 - agHelper.Sleep(3000)//wait for table navigation to take effect! - table.WaitUntilTableLoad() - table.AssertSelectedRow(selectedRow) + table.NavigateToNextPage(); //page 2 + agHelper.Sleep(3000); //wait for table navigation to take effect! + table.WaitUntilTableLoad(); + table.AssertSelectedRow(selectedRow); + table.NavigateToNextPage(); //page 3 + agHelper.Sleep(3000); //wait for table navigation to take effect! + table.WaitForTableEmpty(); //page 3 + table.NavigateToPreviousPage(); //page 2 + agHelper.Sleep(3000); //wait for table navigation to take effect! + table.WaitUntilTableLoad(); + table.AssertSelectedRow(selectedRow); - table.NavigateToNextPage()//page 3 - agHelper.Sleep(3000)//wait for table navigation to take effect! - table.WaitForTableEmpty()//page 3 - table.NavigateToPreviousPage()//page 2 - agHelper.Sleep(3000)//wait for table navigation to take effect! - table.WaitUntilTableLoad() - table.AssertSelectedRow(selectedRow) - - table.NavigateToPreviousPage()//page 1 - agHelper.Sleep(3000)//wait for table navigation to take effect! - table.WaitUntilTableLoad() - table.AssertSelectedRow(selectedRow) + table.NavigateToPreviousPage(); //page 1 + agHelper.Sleep(3000); //wait for table navigation to take effect! + table.WaitUntilTableLoad(); + table.AssertSelectedRow(selectedRow); table.AssertPageNumber(1); - - }) + }); it("3. Validate table navigation with Server Side pagination disabled with Default selected row selection", () => { - - agHelper.NavigateBacktoEditor() - table.WaitUntilTableLoad() - ee.SelectEntityByName("Table1", 'WIDGETS') - agHelper.ToggleOnOrOff('serversidepagination', 'Off') - agHelper.DeployApp() - table.WaitUntilTableLoad() - table.AssertPageNumber(1, 'Off'); - table.AssertSelectedRow(selectedRow) - agHelper.NavigateBacktoEditor() - table.WaitUntilTableLoad() - ee.SelectEntityByName("Table1", 'WIDGETS') - agHelper.ToggleOnOrOff('serversidepagination', 'On') - + agHelper.NavigateBacktoEditor(); + table.WaitUntilTableLoad(); + ee.SelectEntityByName("Table1", "WIDGETS"); + agHelper.ToggleOnOrOff("serversidepagination", "Off"); + agHelper.DeployApp(); + table.WaitUntilTableLoad(); + table.AssertPageNumber(1, "Off"); + table.AssertSelectedRow(selectedRow); + agHelper.NavigateBacktoEditor(); + table.WaitUntilTableLoad(); + ee.SelectEntityByName("Table1", "WIDGETS"); + agHelper.ToggleOnOrOff("serversidepagination", "On"); }); it("4. Change Default selected row in table and verify", () => { - - jsEditor.EnterJSContext("Default Selected Row", "1") - agHelper.DeployApp() - table.WaitUntilTableLoad() + jsEditor.EnterJSContext("Default Selected Row", "1"); + agHelper.DeployApp(); + table.WaitUntilTableLoad(); table.AssertPageNumber(1); - table.AssertSelectedRow(1) - table.NavigateToNextPage()//page 2 + table.AssertSelectedRow(1); + table.NavigateToNextPage(); //page 2 table.AssertPageNumber(2); - table.AssertSelectedRow(1) - agHelper.NavigateBacktoEditor() - table.WaitUntilTableLoad() - + table.AssertSelectedRow(1); + agHelper.NavigateBacktoEditor(); + table.WaitUntilTableLoad(); }); it.skip("5. Verify Default search text in table as per 'Default Search Text' property set + Bug 12228", () => { + ee.SelectEntityByName("Table1", "WIDGETS"); + jsEditor.EnterJSContext("Default Search Text", "Bug", false); + agHelper.DeployApp(); + table.AssertSearchText("Bug"); + table.WaitUntilTableLoad(); + table.WaitUntilTableLoad(); + agHelper.NavigateBacktoEditor(); - ee.SelectEntityByName("Table1", 'WIDGETS') - jsEditor.EnterJSContext("Default Search Text", "Bug", false) - agHelper.DeployApp() - table.AssertSearchText('Bug') - table.WaitUntilTableLoad() - table.WaitUntilTableLoad() - agHelper.NavigateBacktoEditor() + ee.SelectEntityByName("Table1", "WIDGETS"); + jsEditor.EnterJSContext("Default Search Text", "Question", false); + agHelper.DeployApp(); + table.AssertSearchText("Question"); + table.WaitUntilTableLoad(); + agHelper.NavigateBacktoEditor(); + table.WaitUntilTableLoad(); - ee.SelectEntityByName("Table1", 'WIDGETS') - jsEditor.EnterJSContext("Default Search Text", "Question", false) - agHelper.DeployApp() - table.AssertSearchText('Question') - table.WaitUntilTableLoad() - agHelper.NavigateBacktoEditor() - table.WaitUntilTableLoad() - - ee.SelectEntityByName("Table1", 'WIDGETS') - jsEditor.EnterJSContext("Default Search Text", "Epic", false)//Bug 12228 - Searching based on hidden column value should not be allowed - agHelper.DeployApp() - table.AssertSearchText('Epic') - table.WaitForTableEmpty() - agHelper.NavigateBacktoEditor() - table.WaitUntilTableLoad() - - ee.SelectEntityByName("Table1", 'WIDGETS') - jsEditor.RemoveText('defaultsearchtext') - table.WaitUntilTableLoad() + ee.SelectEntityByName("Table1", "WIDGETS"); + jsEditor.EnterJSContext("Default Search Text", "Epic", false); //Bug 12228 - Searching based on hidden column value should not be allowed + agHelper.DeployApp(); + table.AssertSearchText("Epic"); + table.WaitForTableEmpty(); + agHelper.NavigateBacktoEditor(); + table.WaitUntilTableLoad(); + ee.SelectEntityByName("Table1", "WIDGETS"); + jsEditor.RemoveText("defaultsearchtext"); + table.WaitUntilTableLoad(); }); it.skip("6. Validate Search table with Client Side Search enabled & disabled", () => { - ee.SelectEntityByName("Table1", 'WIDGETS') - agHelper.AssertExistingToggleState("enableclientsidesearch", 'checked') + ee.SelectEntityByName("Table1", "WIDGETS"); + agHelper.AssertExistingToggleState("enableclientsidesearch", "checked"); - agHelper.DeployApp() - table.WaitUntilTableLoad() + agHelper.DeployApp(); + table.WaitUntilTableLoad(); - table.SearchTable('Bug') - table.WaitUntilTableLoad() - cy.xpath(table._searchBoxCross).click() + table.SearchTable("Bug"); + table.WaitUntilTableLoad(); + cy.xpath(table._searchBoxCross).click(); - table.SearchTable('Question') - table.WaitUntilTableLoad() - cy.xpath(table._searchBoxCross).click() + table.SearchTable("Question"); + table.WaitUntilTableLoad(); + cy.xpath(table._searchBoxCross).click(); - agHelper.NavigateBacktoEditor() - table.WaitUntilTableLoad() + agHelper.NavigateBacktoEditor(); + table.WaitUntilTableLoad(); - ee.SelectEntityByName("Table1", 'WIDGETS') - agHelper.ToggleOnOrOff("enableclientsidesearch", 'Off') + ee.SelectEntityByName("Table1", "WIDGETS"); + agHelper.ToggleOnOrOff("enableclientsidesearch", "Off"); - agHelper.DeployApp() - table.WaitUntilTableLoad() + agHelper.DeployApp(); + table.WaitUntilTableLoad(); - table.SearchTable('Bug') - table.WaitForTableEmpty() - cy.xpath(table._searchBoxCross).click() + table.SearchTable("Bug"); + table.WaitForTableEmpty(); + cy.xpath(table._searchBoxCross).click(); - table.SearchTable('Question') - table.WaitForTableEmpty() - cy.xpath(table._searchBoxCross).click() + table.SearchTable("Question"); + table.WaitForTableEmpty(); + cy.xpath(table._searchBoxCross).click(); - agHelper.NavigateBacktoEditor() - table.WaitUntilTableLoad() - ee.SelectEntityByName("Table1", 'WIDGETS') - agHelper.ToggleOnOrOff("enableclientsidesearch", 'On') - }) + agHelper.NavigateBacktoEditor(); + table.WaitUntilTableLoad(); + ee.SelectEntityByName("Table1", "WIDGETS"); + agHelper.ToggleOnOrOff("enableclientsidesearch", "On"); + }); it("7. Validate Filter table", () => { - agHelper.DeployApp() - table.WaitUntilTableLoad() + var filterTitle = new Array(); + agHelper.DeployApp(); + table.WaitUntilTableLoad(); //One filter - table.OpenNFilterTable("Type", "is exactly", "Bug") - table.ReadTableRowColumnData(0, 1).then(($cellData) => { - expect($cellData).to.eq("[Bug]: Postgres queries unable to execute with more than 9 placeholders"); - }); - table.ReadTableRowColumnData(2, 1).then(($cellData) => { - expect($cellData).to.eq("[Bug]: Input updates with default values are not captured"); - }); - table.RemoveFilterNVerify("Question", true, false) + table.OpenNFilterTable("Type", "is exactly", "Bug"); + for (let i = 0; i < 3; i++) { + table.ReadTableRowColumnData(i, 0, 200).then(($cellData) => { + expect($cellData).to.eq("Bug"); + }); + } + table.RemoveFilterNVerify("Question", true, false); //Two filters - OR - table.OpenNFilterTable("Type", "starts with", "Trouble") - table.ReadTableRowColumnData(0, 0).then(($cellData) => { - expect($cellData).to.eq("Troubleshooting"); + table.OpenNFilterTable("Type", "starts with", "Trouble"); + for (let i = 0; i < 5; i++) { + table.ReadTableRowColumnData(i, 0, 200).then(($cellData) => { + expect($cellData).to.eq("Troubleshooting"); + }); + } + + table.OpenNFilterTable("Title", "contains", "query", "OR", 1); + table.ReadTableRowColumnData(1, 0, 200).then(($cellData) => { + expect($cellData).to.be.oneOf(["Troubleshooting", "Question"]); }); + + for (let i = 0; i < 8; i++) { + table.ReadTableRowColumnData(i, 1, 100).then(($cellData) => { + if ($cellData.toLowerCase().includes("query")) + filterTitle.push($cellData); + }); + } + cy.wrap(filterTitle).as("filterTitleText"); // alias it for later + cy.get("@filterTitleText") + .its("length") + .should("eq", 2); + + table.RemoveFilterNVerify("Question", true, false); + + //Two filters - AND + table.OpenNFilterTable("Votes", "greater than", "2"); table.ReadTableRowColumnData(0, 1).then(($cellData) => { - expect($cellData).to.eq("Renew expired SSL certificate on a self-hosted instance"); + expect($cellData).to.eq("Combine queries from different datasources"); }); - table.OpenNFilterTable("Title", "contains", "query", 'OR', 1) - table.ReadTableRowColumnData(1, 0).then(($cellData) => { - expect($cellData).to.be.oneOf(['Troubleshooting','Question']) + table.OpenNFilterTable("Title", "contains", "button", "AND", 1); + table.ReadTableRowColumnData(0, 1).then(($cellData) => { + expect($cellData).to.eq( + "Change the video in the video player with a button click", + ); }); - table.ReadTableRowColumnData(6, 1).then(($cellData) => { - expect($cellData).to.eq("Run storeValue commands before a Query.run()"); - }); - table.RemoveFilterNVerify("Question", true, false) - - //Two filters - AND - table.OpenNFilterTable("Votes", "greater than", "3") - table.ReadTableRowColumnData(1, 1).then(($cellData) => { - expect($cellData).to.eq("Combine queries from different datasources"); - }); - - table.OpenNFilterTable("Title", "contains", "button", 'AND', 1) - table.ReadTableRowColumnData(0, 1).then(($cellData) => { - expect($cellData).to.eq("Change the video in the video player with a button click"); - }); - table.RemoveFilterNVerify("Question", true, false) - }) + table.RemoveFilterNVerify("Question", true, false); + }); it("8. Validate Adding a New issue from Add Modal", () => { // agHelper.DeployApp() // table.WaitUntilTableLoad() - cy.get(table._addIcon).closest('div').click() - agHelper.AssertElementPresence(locator._modal) - agHelper.SelectFromDropDown('Suggestion', 't--modal-widget') + cy.get(table._addIcon) + .closest("div") + .click(); + agHelper.AssertElementPresence(locator._modal); + agHelper.SelectFromDropDown("Suggestion", "t--modal-widget"); - cy.get(locator._inputWidgetv1InDeployed).eq(3).type("Adding Title Suggestion via script") - cy.get(locator._textAreainputWidgetv1InDeployed).eq(1).type("Adding Description Suggestion via script") - cy.get(locator._inputWidgetv1InDeployed).eq(4).type("https://github.com/appsmithorg/appsmith/issues/12532") - agHelper.SelectFromMultiSelect(['Epic', 'Task'], 1) - cy.xpath(table._visibleTextSpan('Labels')).click() - cy.get(locator._inputWidgetv1InDeployed).eq(5).type("https://release.app.appsmith.com/applications/62486d45ab307a026918639e/pages/62486d45ab307a02691863a7") - agHelper.SelectFromMultiSelect(['Documented', 'Needs App'], 1, true, 'multiselectwidget') + cy.get(locator._inputWidgetv1InDeployed) + .eq(3) + .type("Adding Title Suggestion via script"); + cy.get(locator._textAreainputWidgetv1InDeployed) + .eq(1) + .type("Adding Description Suggestion via script"); + cy.get(locator._inputWidgetv1InDeployed) + .eq(4) + .type("https://github.com/appsmithorg/appsmith/issues/12532"); + agHelper.SelectFromMultiSelect(["Epic", "Task"], 1); + cy.xpath(table._visibleTextSpan("Labels")).click(); + cy.get(locator._inputWidgetv1InDeployed) + .eq(5) + .type( + "https://release.app.appsmith.com/applications/62486d45ab307a026918639e/pages/62486d45ab307a02691863a7", + ); + agHelper.SelectFromMultiSelect( + ["Documented", "Needs App"], + 1, + true, + "multiselectwidget", + ); - agHelper.ClickButton('Confirm') - agHelper.Sleep(3000) - table.SearchTable('Suggestion', 2) - table.WaitUntilTableLoad() + agHelper.ClickButton("Confirm"); + agHelper.Sleep(3000); + table.SearchTable("Suggestion", 2); + table.WaitUntilTableLoad(); table.ReadTableRowColumnData(0, 0, 1000).then((cellData) => { expect(cellData).to.be.equal("Suggestion"); @@ -261,22 +296,32 @@ describe("AForce - Community Issues page validations", function () { table.ReadTableRowColumnData(0, 1, 1000).then((cellData) => { expect(cellData).to.be.equal("Adding Title Suggestion via script"); }); - - }) + }); it("9. Validate Updating issue from Details tab", () => { - - agHelper.AssertElementAbsence(locator._widgetInDeployed('tabswidget')) - table.SelectTableRow(0) - agHelper.AssertElementPresence(locator._widgetInDeployed('tabswidget')) - agHelper.GetNClick(locator._inputWidgetv1InDeployed).type("-updating title") - agHelper.GetNClick(locator._textAreainputWidgetv1InDeployed).type("-updating desc") - agHelper.GetNClick(locator._inputWidgetv1InDeployed, 1).type("-updating issue link") - agHelper.SelectFromDropDown('Troubleshooting', 't--widget-tabswidget') - agHelper.SelectFromMultiSelect(['Epic', 'Task'], 0, false) - agHelper.SelectFromMultiSelect(['High', 'Dependencies'], 0, true) - agHelper.SelectFromDropDown('[Bug] TypeError: o is undefined', 't--widget-tabswidget', 1) - agHelper.GetNClick(locator._inputWidgetv1InDeployed, 2).type("-updating answer link") + agHelper.AssertElementAbsence(locator._widgetInDeployed("tabswidget")); + table.SelectTableRow(0); + agHelper.AssertElementPresence(locator._widgetInDeployed("tabswidget")); + agHelper + .GetNClick(locator._inputWidgetv1InDeployed) + .type("-updating title"); + agHelper + .GetNClick(locator._textAreainputWidgetv1InDeployed) + .type("-updating desc"); + agHelper + .GetNClick(locator._inputWidgetv1InDeployed, 1) + .type("-updating issue link"); + agHelper.SelectFromDropDown("Troubleshooting", "t--widget-tabswidget"); + agHelper.SelectFromMultiSelect(["Epic", "Task"], 0, false); + agHelper.SelectFromMultiSelect(["High", "Dependencies"], 0, true); + agHelper.SelectFromDropDown( + "[Bug] TypeError: o is undefined", + "t--widget-tabswidget", + 1, + ); + agHelper + .GetNClick(locator._inputWidgetv1InDeployed, 2) + .type("-updating answer link"); //cy.get("body").tab().type("{enter}") @@ -288,34 +333,41 @@ describe("AForce - Community Issues page validations", function () { // key: 'Enter', // }) - //agHelper.Sleep(2000) //cy.get("body").type("{enter}") - agHelper.RemoveMultiSelectItems(['Documented', 'Needs App']) + agHelper.RemoveMultiSelectItems(["Documented", "Needs App"]); //agHelper.SelectFromMultiSelect(['Documented', 'Needs App', 'App Built'], 0, false, 'multiselectwidget') - agHelper.SelectFromMultiSelect(['Needs Product'], 0, true, 'multiselectwidget') - agHelper.ClickButton('Save') + agHelper.SelectFromMultiSelect( + ["Needs Product"], + 0, + true, + "multiselectwidget", + ); + agHelper.ClickButton("Save"); table.ReadTableRowColumnData(0, 0, 1000).then((cellData) => { expect(cellData).to.be.equal("Troubleshooting"); }); table.ReadTableRowColumnData(0, 1, 1000).then((cellData) => { - expect(cellData).to.be.equal("Adding Title Suggestion via script-updating title"); + expect(cellData).to.be.equal( + "Adding Title Suggestion via script-updating title", + ); }); - - }) + }); it("10. Validate Deleting the newly created issue", () => { - agHelper.AssertElementAbsence(locator._widgetInDeployed('tabswidget')) - table.SelectTableRow(0) - agHelper.AssertElementPresence(locator._widgetInDeployed('tabswidget')) - agHelper.Sleep() - cy.get(table._trashIcon).closest('div').click() - agHelper.AssertElementAbsence(locator._widgetInDeployed('tabswidget')) - table.WaitForTableEmpty() + agHelper.AssertElementAbsence(locator._widgetInDeployed("tabswidget")); + table.SelectTableRow(0); + agHelper.AssertElementPresence(locator._widgetInDeployed("tabswidget")); + agHelper.Sleep(); + cy.get(table._trashIcon) + .closest("div") + .click(); + agHelper.AssertElementAbsence(locator._widgetInDeployed("tabswidget")); + table.WaitForTableEmpty(); //2nd search is not working, hence commenting below // cy.xpath(table._searchBoxCross).click() diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ApiPaneTests/API_MultiPart_Spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ApiPaneTests/API_MultiPart_Spec.ts index 8d772ae7bf..43c0ff1bcf 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ApiPaneTests/API_MultiPart_Spec.ts +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/ApiPaneTests/API_MultiPart_Spec.ts @@ -113,7 +113,7 @@ describe("Validate API request body panel", () => { paste: true, completeReplace: true, toRun: false, - shouldNavigate: true, + shouldCreateNewJSObj: true, }, ); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/JSObjectToInput_Spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/JSObjectToInput_Spec.ts index 9557ceac17..a9b4f93e1b 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/JSObjectToInput_Spec.ts +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/JSObjectToInput_Spec.ts @@ -19,7 +19,7 @@ describe("Validate JSObjects binding to Input widget", () => { paste: false, completeReplace: false, toRun: true, - shouldNavigate: true, + shouldCreateNewJSObj: true, }); ee.expandCollapseEntity("WIDGETS"); //to expand widgets ee.expandCollapseEntity("Form1"); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/JSObjectToListWidget_Spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/JSObjectToListWidget_Spec.ts index 1326edcf8d..c850603c43 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/JSObjectToListWidget_Spec.ts +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/JSObjectToListWidget_Spec.ts @@ -32,7 +32,7 @@ describe("Validate JSObj binding to Table widget", () => { paste: false, completeReplace: false, toRun: true, - shouldNavigate: true, + shouldCreateNewJSObj: true, }); cy.get("@jsObjName").then((jsObj) => { jsName = jsObj; diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/Promises_Spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/Promises_Spec.ts index ad96902d14..e483a018d9 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/Promises_Spec.ts +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/Binding/Promises_Spec.ts @@ -319,7 +319,7 @@ showAlert("Wonderful! all apis executed", "success")).catch(() => showAlert("Ple return Promise.any([this.func2(), this.func3(), this.func1()]).then((value) => showAlert("Resolved promise is:" + value)) } }`, - { paste: true, completeReplace: true, toRun: true, shouldNavigate: true }, + { paste: true, completeReplace: true, toRun: true, shouldCreateNewJSObj: true }, ); ee.SelectEntityByName("Button1", "WIDGETS"); cy.get("@jsObjName").then((jsObjName) => { diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/JsFunctionExecution/JSFunctionExecution_spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/JsFunctionExecution/JSFunctionExecution_spec.ts index d4ae0043f1..9deeb4e232 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/JsFunctionExecution/JSFunctionExecution_spec.ts +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/JsFunctionExecution/JSFunctionExecution_spec.ts @@ -15,7 +15,7 @@ describe("JS Function Execution", function() { paste: true, completeReplace: true, toRun: false, - shouldNavigate: true, + shouldCreateNewJSObj: true, }, ); @@ -33,7 +33,7 @@ describe("JS Function Execution", function() { paste: true, completeReplace: true, toRun: false, - shouldNavigate: true, + shouldCreateNewJSObj: true, }, ); @@ -41,8 +41,8 @@ describe("JS Function Execution", function() { }); it("3. Prioritizes parse errors that render JS Object invalid over function execution parse errors in debugger callouts", function() { - const JSObjectWithFunctionExecutionParseErrors = `export default { - myFun1 :()=>{ + const JSObjectWithFunctionExecutionParseErrors = `export default { + myFun1 :()=>{ return f } }`; @@ -58,7 +58,7 @@ describe("JS Function Execution", function() { paste: true, completeReplace: true, toRun: true, - shouldNavigate: true, + shouldCreateNewJSObj: true, }); // Assert presence of function execution parse error callout @@ -69,7 +69,7 @@ describe("JS Function Execution", function() { paste: true, completeReplace: true, toRun: false, - shouldNavigate: false, + shouldCreateNewJSObj: false, }); // Assert presence of parse error callout (entire JS Object is invalid) diff --git a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/WidgetGrouping/WidgetGrouping_spec.js b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/WidgetGrouping/WidgetGrouping_spec.js index 56d83bd71f..f536f43a4a 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/WidgetGrouping/WidgetGrouping_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/ClientSideTests/WidgetGrouping/WidgetGrouping_spec.js @@ -33,5 +33,17 @@ describe("Widget Grouping", function() { .should("have.length", 2); cy.get(`@group`).find(`.t--draggable-buttonwidget`); cy.get(`@group`).find(`.t--draggable-imagewidget`); + + // verify the position so that the camera widget is still below the newly grouped container + cy.get(`.t--widget-containerwidget`) + .eq(1) + .then((element) => { + const elementTop = parseFloat(element.css("top")); + const elementHeight = parseFloat(element.css("height")); + const containerBottom = (elementTop + elementHeight).toString() + "px"; + cy.get(`.t--widget-camerawidget`) + .invoke("attr", "style") + .should("contain", `top: ${containerBottom}`); + }); }); }); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/ExplorerTests/JSEditorContextMenu_Spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/ExplorerTests/JSEditorContextMenu_Spec.ts index 8c0a802f5c..f01a6a17ff 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/ExplorerTests/JSEditorContextMenu_Spec.ts +++ b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/ExplorerTests/JSEditorContextMenu_Spec.ts @@ -43,7 +43,7 @@ describe("Validate basic operations on Entity explorer JSEditor structure", () = it("5. Validate Move JSObject", function() { const newPageId = "Page2"; - agHelper.AddNewPage(); + ee.AddNewPage(); ee.AssertEntityPresenceInExplorer(newPageId); ee.SelectEntityByName(pageId); ee.expandCollapseEntity("QUERIES/JS"); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/OnLoadTests/JSOnLoad_Spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/OnLoadTests/JSOnLoad_Spec.ts index cf9e123d8f..32245662cf 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/OnLoadTests/JSOnLoad_Spec.ts +++ b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/OnLoadTests/JSOnLoad_Spec.ts @@ -39,7 +39,7 @@ describe("JSObjects OnLoad Actions tests", function() { paste: true, completeReplace: true, toRun: false, - shouldNavigate: true, + shouldCreateNewJSObj: true, }, ); jsEditor.EnableDisableAsyncFuncSettings("getId", false, true); //Only before calling confirmation is enabled by User here @@ -189,7 +189,7 @@ describe("JSObjects OnLoad Actions tests", function() { paste: true, completeReplace: true, toRun: false, - shouldNavigate: true, + shouldCreateNewJSObj: true, }, ); @@ -251,7 +251,7 @@ describe("JSObjects OnLoad Actions tests", function() { paste: true, completeReplace: true, toRun: false, - shouldNavigate: true, + shouldCreateNewJSObj: true, }, ); @@ -440,7 +440,7 @@ describe("JSObjects OnLoad Actions tests", function() { paste: true, completeReplace: true, toRun: false, - shouldNavigate: true, + shouldCreateNewJSObj: true, }, ); @@ -481,7 +481,7 @@ describe("JSObjects OnLoad Actions tests", function() { // `{{` + // jsObjName + // `.callCountry(); - // showAlert('Your country is: ' + getCountry.data[0].country, 'info')}}`, + // Select1.selectedOptionValue? showAlert('Your country is: ' + getCountry.data[0].country, 'info'): null`, // true, // true, // ); diff --git a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/Params/PassingParams_Spec.ts b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/Params/PassingParams_Spec.ts index 9effc1745e..ce83bdca2c 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/Params/PassingParams_Spec.ts +++ b/app/client/cypress/integration/Smoke_TestSuite/ServerSideTests/Params/PassingParams_Spec.ts @@ -38,7 +38,7 @@ describe("[Bug] - 10784 - Passing params from JS to SQL query should not break", paste: true, completeReplace: false, toRun: false, - shouldNavigate: true, + shouldCreateNewJSObj: true, }, ); }); diff --git a/app/client/cypress/locators/commonlocators.json b/app/client/cypress/locators/commonlocators.json index 2f14d90c94..ff24170dff 100644 --- a/app/client/cypress/locators/commonlocators.json +++ b/app/client/cypress/locators/commonlocators.json @@ -74,6 +74,7 @@ "evaluatedType": ".t--CodeEditor-evaluatedValue > div:first-of-type pre", "evaluatedCurrentValue": "div:last-of-type .t--CodeEditor-evaluatedValue > div:last-of-type pre", "entityExplorersearch": "#entity-explorer-search", + "searchEntityInExplorer": "#search-entity", "entitySearchResult": ".t--entity-name:contains('", "saveStatusContainer": ".t--save-status-container", "saveStatusIsSaving": "t--save-status-is-saving", @@ -156,9 +157,9 @@ "debugErrorMsg": ".t--debugger-message", "tableButtonVariant": ".t--property-control-buttonvariant .bp3-popover-target", "debuggerLabel": "span.debugger-label", - "debuggerContextMenu":".t--debugger-contextual-error-menu", + "debuggerContextMenu": ".t--debugger-contextual-error-menu", "cyclicDependencyError": "//div[@class='Toastify']//span[contains(text(),'Cyclic dependency found while evaluating')]", - "openDocumentationfromErrorTab":"//span[@name='book-line']", + "openDocumentationfromErrorTab": "//span[@name='book-line']", "appNameDeployMenu": ".t--app-name-menu-deploy-parent", "appNameDeployMenuPublish": ".t--app-name-menu-deploy", "appNameDeployMenuCurrentVersion": ".t--app-name-menu-deploy-current-version", @@ -178,4 +179,4 @@ "saveThemeBtn": ".t--save-theme-btn", "selectThemeBackBtn": ".t--theme-select-back-btn", "themeAppBorderRadiusBtn": ".t--theme-appBorderRadius" -} +} \ No newline at end of file diff --git a/app/client/cypress/support/Pages/AggregateHelper.ts b/app/client/cypress/support/Pages/AggregateHelper.ts index e42286bf51..99c3d1c46b 100644 --- a/app/client/cypress/support/Pages/AggregateHelper.ts +++ b/app/client/cypress/support/Pages/AggregateHelper.ts @@ -134,17 +134,6 @@ export class AggregateHelper { localStorage.setItem("inDeployedMode", "true"); } - public AddNewPage() { - cy.get(this.locator._newPage) - .first() - .click(); - cy.wait("@createPage").should( - "have.nested.property", - "response.body.responseMeta.status", - 201, - ); - } - public ValidateToastMessage(text: string, length = 1) { cy.get(this.locator._toastMsg) .should("have.length", length) @@ -409,6 +398,17 @@ export class AggregateHelper { .wait(500); } + public GetNClickByContains( + selector: string, + containsText: string, + index = 0, + ) { + cy.get(selector) + .contains(containsText) + .eq(index) + .click().wait(200); + } + public ToggleOnOrOff(propertyName: string, toggle: "On" | "Off") { if (toggle == "On") { cy.get(this.locator._propertyToggle(propertyName)) @@ -605,7 +605,11 @@ export class AggregateHelper { locator.should("not.exist"); } - public GetText(selector: string, textOrValue : 'text'| 'val' = 'text', index = 0) { + public GetText( + selector: string, + textOrValue: "text" | "val" = "text", + index = 0, + ) { let locator = selector.startsWith("//") ? cy.xpath(selector) : cy.get(selector); diff --git a/app/client/cypress/support/Pages/DataSources.ts b/app/client/cypress/support/Pages/DataSources.ts index d2afa614e6..979baa3b97 100644 --- a/app/client/cypress/support/Pages/DataSources.ts +++ b/app/client/cypress/support/Pages/DataSources.ts @@ -34,26 +34,28 @@ export class DataSources { _reconnectModal = "div.reconnect-datasource-modal"; _activeDSListReconnectModal = (dbName: string) => "//div[contains(@class, 't--ds-list')]//span[text()='" + dbName + "']"; - _apiQueryBtn = ".t--run-query"; + _runQueryBtn = ".t--run-query"; + _newDatabases = "#new-datasources"; + _selectDatasourceDropdown = "[data-cy=t--datasource-dropdown]"; + _datasourceDropdownOption = "[data-cy=t--datasource-dropdown-option]"; + _selectTableDropdown = "[data-cy=t--table-dropdown]"; + _tableDropdownOption = ".bp3-popover-content .t--dropdown-option"; + _generatePageBtn = "[data-cy=t--generate-page-form-submit]"; - public NavigateToDSAdd() { + public CreatePlugIn(pluginName: string) { + cy.get(this._createNewPlgin(pluginName)).trigger("click"); + } + + public NavigateToDSCreateNew() { cy.get(this._addNewDataSource) .last() .scrollIntoView() .should("be.visible") .click({ force: true }); - } - - public CreatePlugIn(pluginName: string) { - cy.get(this._createNewPlgin(pluginName)).click(); - } - - public NavigateToDSCreateNew() { - this.NavigateToDSAdd(); - cy.get(this._dsCreateNewTab) - .should("be.visible") - .click({ force: true }); - cy.get(this.locator._loading).should("not.exist"); + // cy.get(this._dsCreateNewTab) + // .should("be.visible") + // .click({ force: true }); + cy.get(this._newDatabases).should("be.visible"); } public FillPostgresDSForm(shouldAddTrailingSpaces = false) { @@ -73,6 +75,18 @@ export class DataSources { cy.get(this._password).type(datasourceFormData["postgres-password"]); } + public FillMongoDSForm(shouldAddTrailingSpaces = false) { + const hostAddress = shouldAddTrailingSpaces + ? datasourceFormData["mongo-host"] + " " + : datasourceFormData["mongo-host"]; + cy.get(this._host).type(hostAddress); + cy.get(this._port).type(datasourceFormData["mongo-port"].toString()); + cy.get(this._sectionAuthentication).click(); + cy.get(this._databaseName) + .clear() + .type(datasourceFormData["mongo-databaseName"]); + } + public TestSaveDatasource(expectedRes = true) { this.TestDatasource(expectedRes); this.SaveDatasource(); @@ -94,7 +108,7 @@ export class DataSources { } public NavigateToActiveDSQueryPane(datasourceName: string) { - this.NavigateToDSAdd(); + this.NavigateToDSCreateNew(); this.agHelper.GetNClick(this.locator._activeTab); cy.get(this._datasourceCard) .contains(datasourceName) @@ -145,7 +159,7 @@ export class DataSources { } RunQuery() { - cy.get(this._apiQueryBtn).click({ force: true }); + cy.get(this._runQueryBtn).click({ force: true }); this.agHelper.ValidateNetworkExecutionSuccess("@postExecute"); } } diff --git a/app/client/cypress/support/Pages/EntityExplorer.ts b/app/client/cypress/support/Pages/EntityExplorer.ts index 513caccc11..dcc540c1cd 100644 --- a/app/client/cypress/support/Pages/EntityExplorer.ts +++ b/app/client/cypress/support/Pages/EntityExplorer.ts @@ -1,69 +1,88 @@ -import { ObjectsRegistry } from "../Objects/Registry" +import { ObjectsRegistry } from "../Objects/Registry"; export class EntityExplorer { + public agHelper = ObjectsRegistry.AggregateHelper; + public locator = ObjectsRegistry.CommonLocators; - public agHelper = ObjectsRegistry.AggregateHelper - public locator = ObjectsRegistry.CommonLocators; + public SelectEntityByName( + entityNameinLeftSidebar: string, + section: "WIDGETS" | "QUERIES/JS" | "DATASOURCES" | "" = "", + ) { + if (section) this.expandCollapseEntity(section); //to expand respective section + cy.xpath(this.locator._entityNameInExplorer(entityNameinLeftSidebar)) + .last() + .click({ multiple: true }); + this.agHelper.Sleep(); + } - public SelectEntityByName(entityNameinLeftSidebar: string, section: 'WIDGETS' | 'QUERIES/JS' | 'DATASOURCES' | '' = '') { - if (section) - this.expandCollapseEntity(section)//to expand respective section - cy.xpath(this.locator._entityNameInExplorer(entityNameinLeftSidebar)) - .last() - .click({ multiple: true }) - this.agHelper.Sleep() + public AddNewPage() { + cy.get(this.locator._newPage) + .first() + .click(); + this.agHelper.ValidateNetworkStatus("@createPage", 201); + } + + public NavigateToSwitcher(navigationTab: "explorer" | "widgets") { + cy.get(this.locator._openNavigationTab(navigationTab)).click(); + } + + public AssertEntityPresenceInExplorer(entityNameinLeftSidebar: string) { + cy.xpath( + this.locator._entityNameInExplorer(entityNameinLeftSidebar), + ).should("have.length", 1); + } + + public AssertEntityAbsenceInExplorer(entityNameinLeftSidebar: string) { + cy.xpath( + this.locator._entityNameInExplorer(entityNameinLeftSidebar), + ).should("not.exist"); + } + + public expandCollapseEntity(entityName: string, expand = true) { + cy.xpath(this.locator._expandCollapseArrow(entityName)) + .invoke("attr", "name") + .then((arrow) => { + if (expand && arrow == "arrow-right") + cy.xpath(this.locator._expandCollapseArrow(entityName)) + .trigger("click", { multiple: true }) + .wait(1000); + else if (!expand && arrow == "arrow-down") + cy.xpath(this.locator._expandCollapseArrow(entityName)) + .trigger("click", { multiple: true }) + .wait(1000); + else this.agHelper.Sleep(500); + }); + } + + public ActionContextMenuByEntityName( + entityNameinLeftSidebar: string, + action = "Delete", + subAction = "", + ) { + this.agHelper.Sleep(); + cy.xpath(this.locator._contextMenu(entityNameinLeftSidebar)) + .last() + .click({ force: true }); + cy.xpath(this.locator._contextMenuItem(action)).click({ force: true }); + this.agHelper.Sleep(500); + if (subAction) { + cy.xpath(this.locator._contextMenuItem(subAction)).click({ force: true }); + this.agHelper.Sleep(500); } + } - public NavigateToSwitcher(navigationTab: 'explorer' | 'widgets') { - cy.get(this.locator._openNavigationTab(navigationTab)).click() - } - - public AssertEntityPresenceInExplorer(entityNameinLeftSidebar: string) { - cy.xpath(this.locator._entityNameInExplorer(entityNameinLeftSidebar)) - .should("have.length", 1); - } - - public AssertEntityAbsenceInExplorer(entityNameinLeftSidebar: string) { - cy.xpath(this.locator._entityNameInExplorer(entityNameinLeftSidebar)).should('not.exist'); - } - - public expandCollapseEntity(entityName: string, expand = true) { - cy.xpath(this.locator._expandCollapseArrow(entityName)).invoke('attr', 'name').then((arrow) => { - if (expand && arrow == 'arrow-right') - cy.xpath(this.locator._expandCollapseArrow(entityName)).trigger('click', { multiple: true }).wait(1000); - else if (!expand && arrow == 'arrow-down') - cy.xpath(this.locator._expandCollapseArrow(entityName)).trigger('click', { multiple: true }).wait(1000); - else - this.agHelper.Sleep(500) - }) - } - - public ActionContextMenuByEntityName(entityNameinLeftSidebar: string, action = "Delete", subAction = "") { - this.agHelper.Sleep(); - cy.xpath(this.locator._contextMenu(entityNameinLeftSidebar)) - .last() - .click({ force: true }); - cy.xpath(this.locator._contextMenuItem(action)) - .click({ force: true }) - this.agHelper.Sleep(500) - if (subAction) { - cy.xpath(this.locator._contextMenuItem(subAction)) - .click({ force: true }) - this.agHelper.Sleep(500) - } - } - - public DragDropWidgetNVerify(widgetType: string, x: number, y: number) { - this.NavigateToSwitcher('widgets') - this.agHelper.Sleep() - cy.get(this.locator._widgetPageIcon(widgetType)).first() - .trigger("dragstart", { force: true }) - .trigger("mousemove", x, y, { force: true }); - cy.get(this.locator._dropHere) - .trigger("mousemove", x, y, { eventConstructor: "MouseEvent" }) - .trigger("mousemove", x, y, { eventConstructor: "MouseEvent" }) - .trigger("mouseup", x, y, { eventConstructor: "MouseEvent" }); - this.agHelper.AssertAutoSave()//settling time for widget on canvas! - cy.get(this.locator._widgetInCanvas(widgetType)).should('exist') - } + public DragDropWidgetNVerify(widgetType: string, x: number, y: number) { + this.NavigateToSwitcher("widgets"); + this.agHelper.Sleep(); + cy.get(this.locator._widgetPageIcon(widgetType)) + .first() + .trigger("dragstart", { force: true }) + .trigger("mousemove", x, y, { force: true }); + cy.get(this.locator._dropHere) + .trigger("mousemove", x, y, { eventConstructor: "MouseEvent" }) + .trigger("mousemove", x, y, { eventConstructor: "MouseEvent" }) + .trigger("mouseup", x, y, { eventConstructor: "MouseEvent" }); + this.agHelper.AssertAutoSave(); //settling time for widget on canvas! + cy.get(this.locator._widgetInCanvas(widgetType)).should("exist"); + } } diff --git a/app/client/cypress/support/Pages/HomePage.ts b/app/client/cypress/support/Pages/HomePage.ts index 5e219f2a50..6bca4a7bf9 100644 --- a/app/client/cypress/support/Pages/HomePage.ts +++ b/app/client/cypress/support/Pages/HomePage.ts @@ -29,7 +29,7 @@ export class HomePage { private _editAppName = "bp3-editable-text-editing" private _appMenu = ".t--editor-appname-menu-portal .bp3-menu-item" private _buildFromScratchActionCard = ".t--BuildFromScratch" - private _buildFromDataTableActionCard = ".t--GenerateCRUDPage" + _buildFromDataTableActionCard = ".t--GenerateCRUDPage" private _selectRole = "//span[text()='Select a role']/ancestor::div" private _searchInput = "input[type='text']" _appHoverIcon = (action: string) => ".t--application-" + action + "-link" diff --git a/app/client/cypress/support/Pages/JSEditor.ts b/app/client/cypress/support/Pages/JSEditor.ts index 9c984b5439..3bb584cd27 100644 --- a/app/client/cypress/support/Pages/JSEditor.ts +++ b/app/client/cypress/support/Pages/JSEditor.ts @@ -4,13 +4,13 @@ export interface ICreateJSObjectOptions { paste: boolean; completeReplace: boolean; toRun: boolean; - shouldNavigate: boolean; + shouldCreateNewJSObj: boolean; } const DEFAULT_CREATE_JS_OBJECT_OPTIONS = { paste: true, completeReplace: false, toRun: true, - shouldNavigate: true, + shouldCreateNewJSObj: true, }; export class JSEditor { @@ -82,7 +82,7 @@ export class JSEditor { //#endregion //#region Page functions - public NavigateToJSEditor() { + public NavigateToNewJSEditor() { cy.get(this.locator._createNew) .last() .click({ force: true }); @@ -107,9 +107,9 @@ export class JSEditor { JSCode: string, options: ICreateJSObjectOptions = DEFAULT_CREATE_JS_OBJECT_OPTIONS, ) { - const { completeReplace, paste, shouldNavigate, toRun } = options; + const { completeReplace, paste, shouldCreateNewJSObj, toRun } = options; - shouldNavigate && this.NavigateToJSEditor(); + shouldCreateNewJSObj && this.NavigateToNewJSEditor(); if (!completeReplace) { cy.get(this.locator._codeMirrorTextArea) .first() @@ -377,7 +377,7 @@ export class JSEditor { this.agHelper.GetNClick(this._codeTab); } /** - * + * There are two types of parse errors in the JS Editor 1. Parse errors that render the JS Object invalid and all functions unrunnable 2. Parse errors within functions that throw errors when executing those functions diff --git a/app/client/cypress/support/commands.js b/app/client/cypress/support/commands.js index 1c6e433b5a..188e0f4c62 100644 --- a/app/client/cypress/support/commands.js +++ b/app/client/cypress/support/commands.js @@ -313,7 +313,7 @@ Cypress.Commands.add("SearchApp", (appname) => { }); Cypress.Commands.add("SearchEntity", (apiname1, apiname2) => { - cy.get(commonlocators.entityExplorersearch) + cy.get(commonlocators.searchEntityInExplorer) .clear({ force: true }) .type(apiname1, { force: true }); // eslint-disable-next-line cypress/no-unnecessary-waiting @@ -329,7 +329,7 @@ Cypress.Commands.add("SearchEntity", (apiname1, apiname2) => { Cypress.Commands.add("GlobalSearchEntity", (apiname1, dontAssertVisibility) => { // entity explorer search will be hidden - cy.get(commonlocators.entityExplorersearch) + cy.get(commonlocators.searchEntityInExplorer) .clear({ force: true }) .type(apiname1, { force: true }); // eslint-disable-next-line cypress/no-unnecessary-waiting @@ -413,7 +413,7 @@ Cypress.Commands.add("CheckAndUnfoldWidgets", () => { }); Cypress.Commands.add("SearchEntityandOpen", (apiname1) => { - cy.get(commonlocators.entityExplorersearch) + cy.get(commonlocators.searchEntityInExplorer) .clear({ force: true }) .type(apiname1, { force: true }); cy.CheckAndUnfoldWidgets(); @@ -432,7 +432,7 @@ Cypress.Commands.add("SearchEntityandOpen", (apiname1) => { }); Cypress.Commands.add("SearchEntityAndUnfold", (apiname1) => { - cy.get(commonlocators.entityExplorersearch) + cy.get(commonlocators.searchEntityInExplorer) .clear({ force: true }) .type(apiname1, { force: true }); // eslint-disable-next-line cypress/no-unnecessary-waiting @@ -451,7 +451,7 @@ Cypress.Commands.add("SearchEntityAndUnfold", (apiname1) => { Cypress.Commands.add("OpenBindings", (apiname1) => { cy.wait(500); - cy.get(commonlocators.entityExplorersearch) + cy.get(commonlocators.searchEntityInExplorer) .clear({ force: true }) .type(apiname1, { force: true }); cy.CheckAndUnfoldWidgets(); diff --git a/app/client/src/components/editorComponents/Sidebar.tsx b/app/client/src/components/editorComponents/Sidebar.tsx index 7c302c29de..56b78ec0f3 100644 --- a/app/client/src/components/editorComponents/Sidebar.tsx +++ b/app/client/src/components/editorComponents/Sidebar.tsx @@ -7,22 +7,17 @@ import React, { useMemo, } from "react"; import classNames from "classnames"; -import history from "utils/history"; import * as Sentry from "@sentry/react"; -import { PanelStack } from "@blueprintjs/core"; import { useDispatch, useSelector } from "react-redux"; import PerformanceTracker, { PerformanceTransactionName, } from "utils/PerformanceTracker"; -import { AppState } from "reducers"; import { getFirstTimeUserOnboardingComplete, getIsFirstTimeUserOnboardingEnabled, } from "selectors/onboardingSelectors"; import Explorer from "pages/Editor/Explorer"; -import Switcher from "components/ads/Switcher"; -import { trimQueryString } from "utils/helpers"; import AppComments from "comments/AppComments/AppComments"; import { setExplorerActiveAction } from "actions/explorerActions"; import { @@ -33,14 +28,10 @@ import { tailwindLayers } from "constants/Layers"; import TooltipComponent from "components/ads/Tooltip"; import { previewModeSelector } from "selectors/editorSelectors"; import useHorizontalResize from "utils/hooks/useHorizontalResize"; -import { forceOpenWidgetPanel } from "actions/widgetSidebarActions"; -import { toggleInOnboardingWidgetSelection } from "actions/onboardingActions"; import OnboardingStatusbar from "pages/Editor/FirstTimeUserOnboarding/Statusbar"; import Pages from "pages/Editor/Explorer/Pages"; -import { Colors } from "constants/Colors"; import { EntityProperties } from "pages/Editor/Explorer/Entity/EntityProperties"; import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; -import { builderURL } from "RouteBuilder"; type Props = { width: number; @@ -58,38 +49,12 @@ export const EntityExplorerSidebar = memo((props: Props) => { const enableFirstTimeUserOnboarding = useSelector( getIsFirstTimeUserOnboardingEnabled, ); - const isFirstTimeUserOnboardingEnabled = useSelector( - getIsFirstTimeUserOnboardingEnabled, - ); const resizer = useHorizontalResize( sidebarRef, props.onWidthChange, props.onDragEnd, ); - const switches = [ - { - id: "explorer", - text: "Explorer", - action: () => dispatch(forceOpenWidgetPanel(false)), - }, - { - id: "widgets", - text: "Widgets", - action: () => { - !(trimQueryString(builderURL()) === window.location.pathname) && - history.push(builderURL()); - setTimeout(() => dispatch(forceOpenWidgetPanel(true)), 0); - if (isFirstTimeUserOnboardingEnabled) { - dispatch(toggleInOnboardingWidgetSelection(true)); - } - }, - }, - ]; - const [activeSwitch, setActiveSwitch] = useState(switches[0]); const [tooltipIsOpen, setTooltipIsOpen] = useState(false); - const isForceOpenWidgetPanel = useSelector( - (state: AppState) => state.ui.onBoarding.forceOpenWidgetPanel, - ); const isFirstTimeUserOnboardingComplete = useSelector( getFirstTimeUserOnboardingComplete, ); @@ -98,14 +63,6 @@ export const EntityExplorerSidebar = memo((props: Props) => { PerformanceTracker.stopTracking(); }); - useEffect(() => { - if (isForceOpenWidgetPanel) { - setActiveSwitch(switches[1]); - } else { - setActiveSwitch(switches[0]); - } - }, [isForceOpenWidgetPanel]); - // registering event listeners useEffect(() => { document.addEventListener("mousemove", onMouseMove); @@ -191,7 +148,7 @@ export const EntityExplorerSidebar = memo((props: Props) => {
{ > {/* SIDEBAR */}
@@ -209,19 +166,8 @@ export const EntityExplorerSidebar = memo((props: Props) => { {/* Popover that contains the bindings info */} - {/* SWITCHER */} -
- -
- + {/* Contains entity explorer & widgets library along with a switcher*/} +
{/* RESIZER */} diff --git a/app/client/src/constants/Explorer.ts b/app/client/src/constants/Explorer.ts index 94f482e1a5..3fa4f47fa3 100644 --- a/app/client/src/constants/Explorer.ts +++ b/app/client/src/constants/Explorer.ts @@ -1,2 +1,3 @@ export const ENTITY_EXPLORER_SEARCH_ID = "entity-explorer-search"; export const WIDGETS_SEARCH_ID = "#widgets-search"; +export const SEARCH_ENTITY = "search-entity"; diff --git a/app/client/src/pages/Editor/Explorer/Entity/index.tsx b/app/client/src/pages/Editor/Explorer/Entity/index.tsx index d1a460c1b9..431504df46 100644 --- a/app/client/src/pages/Editor/Explorer/Entity/index.tsx +++ b/app/client/src/pages/Editor/Explorer/Entity/index.tsx @@ -220,11 +220,11 @@ export const Entity = forwardRef( /* eslint-disable react-hooks/exhaustive-deps */ useEffect(() => { - if (props.isDefaultExpanded) { + if (props.isDefaultExpanded || props.searchKeyword) { open(true); props.onToggle && props.onToggle(true); } - }, [props.isDefaultExpanded]); + }, [props.isDefaultExpanded, props.searchKeyword]); useEffect(() => { if (!props.searchKeyword && !props.isDefaultExpanded) { open(false); diff --git a/app/client/src/pages/Editor/Explorer/EntityExplorer.tsx b/app/client/src/pages/Editor/Explorer/EntityExplorer.tsx index f0fe15aa49..c1d8059bb9 100644 --- a/app/client/src/pages/Editor/Explorer/EntityExplorer.tsx +++ b/app/client/src/pages/Editor/Explorer/EntityExplorer.tsx @@ -8,9 +8,7 @@ import React, { import styled from "styled-components"; import Divider from "components/editorComponents/Divider"; import Search from "./ExplorerSearch"; -import { NonIdealState, Classes, IPanelProps } from "@blueprintjs/core"; -import WidgetSidebar from "../WidgetSidebar"; -import history from "utils/history"; +import { NonIdealState, Classes } from "@blueprintjs/core"; import JSDependencies from "./JSDependencies"; import PerformanceTracker, { PerformanceTransactionName, @@ -29,6 +27,8 @@ import Datasources from "./Datasources"; import Files from "./Files"; import ExplorerWidgetGroup from "./Widgets/WidgetGroup"; import { builderURL } from "RouteBuilder"; +import history from "utils/history"; +import { SEARCH_ENTITY } from "constants/Explorer"; const Wrapper = styled.div` height: 100%; @@ -71,7 +71,7 @@ const StyledDivider = styled(Divider)` border-bottom-color: #f0f0f0; `; -function EntityExplorer(props: IPanelProps) { +function EntityExplorer({ isActive }: { isActive: boolean }) { const dispatch = useDispatch(); const [searchKeyword, setSearchKeyword] = useState(""); const searchInputRef: MutableRefObject = useRef( @@ -86,15 +86,13 @@ function EntityExplorer(props: IPanelProps) { getIsFirstTimeUserOnboardingEnabled, ); const noResults = false; - const { openPanel } = props; const showWidgetsSidebar = useCallback(() => { history.push(builderURL()); - openPanel({ component: WidgetSidebar }); dispatch(forceOpenWidgetPanel(true)); if (isFirstTimeUserOnboardingEnabled) { dispatch(toggleInOnboardingWidgetSelection(true)); } - }, [openPanel, isFirstTimeUserOnboardingEnabled]); + }, [isFirstTimeUserOnboardingEnabled]); /** * filter entitites @@ -112,10 +110,14 @@ function EntityExplorer(props: IPanelProps) { }; return ( - + {/* SEARCH */} void; + id?: string; }, ref: Ref, ) => { @@ -62,7 +63,7 @@ export const ExplorerSearch = forwardRef( autoComplete="off" autoFocus className="flex-grow py-2 text-gray-800 bg-transparent placeholder-trueGray-500" - id={ENTITY_EXPLORER_SEARCH_ID} + id={props.id || ENTITY_EXPLORER_SEARCH_ID} onBlur={() => setFocussed(false)} onChange={onChange} onFocus={() => setFocussed(true)} @@ -78,8 +79,7 @@ export const ExplorerSearch = forwardRef(
diff --git a/app/client/src/pages/Editor/Explorer/index.tsx b/app/client/src/pages/Editor/Explorer/index.tsx index 5760cccc59..306551757a 100644 --- a/app/client/src/pages/Editor/Explorer/index.tsx +++ b/app/client/src/pages/Editor/Explorer/index.tsx @@ -1,23 +1,73 @@ -import { IPanelProps } from "@blueprintjs/core"; -import React from "react"; -import { useEffect } from "react"; -import { useSelector } from "react-redux"; +import { toggleInOnboardingWidgetSelection } from "actions/onboardingActions"; +import { forceOpenWidgetPanel } from "actions/widgetSidebarActions"; +import { Switcher } from "components/ads"; +import { Colors } from "constants/Colors"; +import { tailwindLayers } from "constants/Layers"; +import React, { useEffect, useMemo, useState } from "react"; +import { useDispatch, useSelector } from "react-redux"; import { AppState } from "reducers"; +import { builderURL } from "RouteBuilder"; +import { getIsFirstTimeUserOnboardingEnabled } from "selectors/onboardingSelectors"; +import { trimQueryString } from "utils/helpers"; +import history from "utils/history"; import WidgetSidebar from "../WidgetSidebar"; import EntityExplorer from "./EntityExplorer"; -const isForceOpenWidgetPanelSelector = (state: AppState) => +const selectForceOpenWidgetPanel = (state: AppState) => state.ui.onBoarding.forceOpenWidgetPanel; -function ExplorerContent(props: IPanelProps) { - const isForceOpenWidgetPanel = useSelector(isForceOpenWidgetPanelSelector); - useEffect(() => { - if (isForceOpenWidgetPanel) { - props.openPanel({ component: WidgetSidebar }); - } - }, [isForceOpenWidgetPanel]); +function ExplorerContent() { + const dispatch = useDispatch(); + const isFirstTimeUserOnboardingEnabled = useSelector( + getIsFirstTimeUserOnboardingEnabled, + ); + const switches = useMemo( + () => [ + { + id: "explorer", + text: "Explorer", + action: () => dispatch(forceOpenWidgetPanel(false)), + }, + { + id: "widgets", + text: "Widgets", + action: () => { + !(trimQueryString(builderURL()) === window.location.pathname) && + history.push(builderURL()); + dispatch(forceOpenWidgetPanel(true)); + if (isFirstTimeUserOnboardingEnabled) { + dispatch(toggleInOnboardingWidgetSelection(true)); + } + }, + }, + ], + [ + dispatch, + forceOpenWidgetPanel, + isFirstTimeUserOnboardingEnabled, + toggleInOnboardingWidgetSelection, + ], + ); + const [activeSwitch, setActiveSwitch] = useState(switches[0]); + const openWidgetPanel = useSelector(selectForceOpenWidgetPanel); - return ; + useEffect(() => { + setActiveSwitch(switches[openWidgetPanel ? 1 : 0]); + }, [openWidgetPanel]); + + return ( +
+
+ +
+ + +
+ ); } export default ExplorerContent; diff --git a/app/client/src/pages/Editor/FirstTimeUserOnboarding/Statusbar.tsx b/app/client/src/pages/Editor/FirstTimeUserOnboarding/Statusbar.tsx index 0147752356..2548f3a578 100644 --- a/app/client/src/pages/Editor/FirstTimeUserOnboarding/Statusbar.tsx +++ b/app/client/src/pages/Editor/FirstTimeUserOnboarding/Statusbar.tsx @@ -33,7 +33,6 @@ import { ONBOARDING_STATUS_STEPS_THIRD_ALT, } from "@appsmith/constants/messages"; import { getTypographyByKey } from "constants/DefaultTheme"; - import { Colors } from "constants/Colors"; import { onboardingCheckListUrl } from "RouteBuilder"; diff --git a/app/client/src/pages/Editor/WidgetSidebar.tsx b/app/client/src/pages/Editor/WidgetSidebar.tsx index 323e45d764..03386b2bfa 100644 --- a/app/client/src/pages/Editor/WidgetSidebar.tsx +++ b/app/client/src/pages/Editor/WidgetSidebar.tsx @@ -1,22 +1,16 @@ -import React, { useRef, useEffect, useState } from "react"; +import React, { useRef, useState } from "react"; import { useSelector } from "react-redux"; import WidgetCard from "./WidgetCard"; import { getWidgetCards } from "selectors/editorSelectors"; -import { IPanelProps } from "@blueprintjs/core"; import ExplorerSearch from "./Explorer/ExplorerSearch"; import { debounce } from "lodash"; import produce from "immer"; -import { useLocation } from "react-router"; - import { createMessage, WIDGET_SIDEBAR_CAPTION, } from "@appsmith/constants/messages"; -import { matchBuilderPath } from "constants/routes"; -import { AppState } from "reducers"; -function WidgetSidebar(props: IPanelProps) { - const location = useLocation(); +function WidgetSidebar({ isActive }: { isActive: boolean }) { const cards = useSelector(getWidgetCards); const [filteredCards, setFilteredCards] = useState(cards); const searchInputRef = useRef(null); @@ -33,17 +27,6 @@ function WidgetSidebar(props: IPanelProps) { } setFilteredCards(filteredCards); }; - const isForceOpenWidgetPanel = useSelector( - (state: AppState) => state.ui.onBoarding.forceOpenWidgetPanel, - ); - - const onCanvas = matchBuilderPath(window.location.pathname); - - useEffect(() => { - if (!onCanvas || isForceOpenWidgetPanel === false) { - props.closePanel(); - } - }, [onCanvas, location, isForceOpenWidgetPanel]); /** * filter widgets @@ -64,7 +47,9 @@ function WidgetSidebar(props: IPanelProps) { }; return ( -
+
diff --git a/app/client/src/sagas/WidgetOperationSagas.tsx b/app/client/src/sagas/WidgetOperationSagas.tsx index 87d26d4ff5..d5900a1b19 100644 --- a/app/client/src/sagas/WidgetOperationSagas.tsx +++ b/app/client/src/sagas/WidgetOperationSagas.tsx @@ -128,7 +128,12 @@ import { collisionCheckPostReflow, getBottomRowAfterReflow, } from "utils/reflowHookUtils"; -import { PrevReflowState, ReflowDirection, SpaceMap } from "reflow/reflowTypes"; +import { + GridProps, + PrevReflowState, + ReflowDirection, + SpaceMap, +} from "reflow/reflowTypes"; import { WidgetSpace } from "constants/CanvasEditorConstants"; import { reflow } from "reflow"; import { getBottomMostRow } from "reflow/reflowUtils"; @@ -845,7 +850,6 @@ export function calculateNewWidgetPosition( * @param copiedTotalWidth total width of the copied widgets * @param copiedTopMostRow top row of the top most copied widget * @param copiedLeftMostColumn left column of the left most copied widget - * @param shouldGroup boolean to indicate if the user is grouping instead of pasting * @returns */ const getNewPositions = function*( @@ -854,11 +858,7 @@ const getNewPositions = function*( copiedTotalWidth: number, copiedTopMostRow: number, copiedLeftMostColumn: number, - shouldGroup: boolean, ) { - // if it is grouping instead of pasting then skip the pasting logic - if (shouldGroup) return {}; - const selectedWidgetIDs: string[] = yield select(getSelectedWidgets); const canvasWidgets: CanvasWidgetsReduxState = yield select(getWidgets); const { @@ -1187,16 +1187,18 @@ function* pasteWidgetSaga( let widgets: CanvasWidgetsReduxState = canvasWidgets; const selectedWidget: FlattenedWidgetProps = yield getSelectedWidgetWhenPasting(); + let reflowedMovementMap, + bottomMostRow: number | undefined, + gridProps: GridProps | undefined, + newPastingPositionMap: SpaceMap | undefined, + canvasId; + let pastingIntoWidgetId: string = yield getParentWidgetIdForPasting( canvasWidgets, selectedWidget, ); - let isThereACollision: boolean = yield isSelectedWidgetsColliding( - widgets, - copiedWidgetGroups, - pastingIntoWidgetId, - ); + let isThereACollision = false; // if this is true, selected widgets will be grouped in container if (shouldGroup) { @@ -1204,7 +1206,6 @@ function* pasteWidgetSaga( pastingIntoWidgetId = yield getParentWidgetIdForGrouping( widgets, copiedWidgetGroups, - pastingIntoWidgetId, ); widgets = yield filterOutSelectedWidgets( copiedWidgetGroups[0].parentId, @@ -1216,10 +1217,20 @@ function* pasteWidgetSaga( pastingIntoWidgetId, ); - copiedWidgetGroups = yield groupWidgetsIntoContainer( + //while grouping, the container around the selected widgets will increase by 2 rows, + //hence if there are any widgets in that path then we reflow those widgets + // If there are already widgets inside the selection box even before grouping + //then we will have to move it down to the bottom most row + ({ + bottomMostRow, + copiedWidgetGroups, + gridProps, + reflowedMovementMap, + } = yield groupWidgetsIntoContainer( copiedWidgetGroups, pastingIntoWidgetId, - ); + isThereACollision, + )); } else if (isCopiedModalWidget(copiedWidgetGroups, widgets)) { pastingIntoWidgetId = MAIN_CONTAINER_WIDGET_ID; } @@ -1242,25 +1253,27 @@ function* pasteWidgetSaga( widgets, ); - // new pasting positions, the variables are undefined if the positions cannot be calculated, - // then it pastes the regular way at the bottom of the canvas - const { - bottomMostRow, - canvasId, - gridProps, - newPastingPositionMap, - reflowedMovementMap, - }: NewPastePositionVariables = yield call( - getNewPositions, - copiedWidgetGroups, - action.payload.mouseLocation, - copiedTotalWidth, - topMostWidget.topRow, - leftMostWidget.leftColumn, - shouldGroup, - ); + // skip new position calculation if grouping + if (!shouldGroup) { + // new pasting positions, the variables are undefined if the positions cannot be calculated, + // then it pastes the regular way at the bottom of the canvas + ({ + bottomMostRow, + canvasId, + gridProps, + newPastingPositionMap, + reflowedMovementMap, + } = yield call( + getNewPositions, + copiedWidgetGroups, + action.payload.mouseLocation, + copiedTotalWidth, + topMostWidget.topRow, + leftMostWidget.leftColumn, + )); - if (canvasId) pastingIntoWidgetId = canvasId; + if (canvasId) pastingIntoWidgetId = canvasId; + } yield all( copiedWidgetGroups.map((copiedWidgets) => diff --git a/app/client/src/sagas/WidgetOperationUtils.ts b/app/client/src/sagas/WidgetOperationUtils.ts index 03771742b4..94d0546d90 100644 --- a/app/client/src/sagas/WidgetOperationUtils.ts +++ b/app/client/src/sagas/WidgetOperationUtils.ts @@ -33,15 +33,24 @@ import { import { getNextEntityName } from "utils/AppsmithUtils"; import WidgetFactory from "utils/WidgetFactory"; import { getParentWithEnhancementFn } from "./WidgetEnhancementHelpers"; -import { OccupiedSpace } from "constants/CanvasEditorConstants"; +import { OccupiedSpace, WidgetSpace } from "constants/CanvasEditorConstants"; import { areIntersecting } from "utils/WidgetPropsUtils"; -import { GridProps, ReflowedSpaceMap, SpaceMap } from "reflow/reflowTypes"; +import { + GridProps, + PrevReflowState, + ReflowDirection, + ReflowedSpaceMap, + SpaceMap, +} from "reflow/reflowTypes"; import { getBaseWidgetClassName, getSlidingCanvasName, getStickyCanvasName, POSITIONED_WIDGET, } from "constants/componentClassNameConstants"; +import { getWidgetSpacesSelectorForContainer } from "selectors/editorSelectors"; +import { reflow } from "reflow"; +import { getBottomRowAfterReflow } from "utils/reflowHookUtils"; export interface CopiedWidgetGroup { widgetId: string; @@ -992,6 +1001,7 @@ export function isDropTarget(type: WidgetType, includeCanvasWidget = false) { export const groupWidgetsIntoContainer = function*( copiedWidgetGroups: CopiedWidgetGroup[], pastingIntoWidgetId: string, + isThereACollision: boolean, ) { const containerWidgetId = generateReactKey(); const evalTree: DataTree = yield select(getDataTree); @@ -1006,6 +1016,7 @@ export const groupWidgetsIntoContainer = function*( "CANVAS_WIDGET", evalTree, ); + let reflowedMovementMap, bottomMostRow, gridProps; const { bottomMostWidget, leftMostWidget, @@ -1018,8 +1029,12 @@ export const groupWidgetsIntoContainer = function*( (w) => w.widgetId === copiedWidgetGroup.widgetId, ), ); + + //calculating parentColumnSpace because the values stored inside widget DSL are not entirely reliable const parentColumnSpace = - copiedWidgetGroups[0].list[0].parentColumnSpace || 1; + getParentColumnSpace(canvasWidgets, pastingIntoWidgetId) || + copiedWidgetGroups[0].list[0].parentColumnSpace || + 1; const boundary = { top: _.minBy(copiedWidgets, (copiedWidget) => copiedWidget?.topRow), @@ -1124,13 +1139,73 @@ export const groupWidgetsIntoContainer = function*( const flatList = _.flattenDeep(list); - return [ - { - list: [newContainerWidget, newCanvasWidget, ...flatList], - widgetId: newContainerWidget.widgetId, - parentId: pastingIntoWidgetId, - }, - ]; + // if there are no collision already then reflow the below widgets by 2 rows. + if (!isThereACollision) { + const widgetSpacesSelector = getWidgetSpacesSelectorForContainer( + pastingIntoWidgetId, + ); + const widgetSpaces: WidgetSpace[] = yield select(widgetSpacesSelector) || + []; + + const copiedWidgetIds = copiedWidgets + .map((widget) => widget?.widgetId) + .filter((id) => !!id); + + // filter out copiedWidgets from occupied spaces + const widgetOccupiedSpaces = widgetSpaces.filter( + (widgetSpace) => copiedWidgetIds.indexOf(widgetSpace.id) === -1, + ); + + // create the object of the new container in the form of OccupiedSpace + const containerSpace = { + id: "1", + left: newContainerWidget.leftColumn, + top: newContainerWidget.topRow, + right: newContainerWidget.rightColumn, + bottom: newContainerWidget.bottomRow, + }; + + gridProps = { + parentColumnSpace, + parentRowSpace: GridDefaults.DEFAULT_GRID_ROW_HEIGHT, + maxGridColumns: GridDefaults.DEFAULT_GRID_COLUMNS, + }; + + //get movement map of reflowed widgets + const { movementMap } = reflow( + [containerSpace], + [containerSpace], + widgetOccupiedSpaces, + ReflowDirection.BOTTOM, + gridProps, + true, + false, + { prevSpacesMap: {} } as PrevReflowState, + ); + + reflowedMovementMap = movementMap; + + //get the new calculated bottom row + bottomMostRow = getBottomRowAfterReflow( + reflowedMovementMap, + containerSpace.bottom, + widgetOccupiedSpaces, + gridProps, + ); + } + + return { + reflowedMovementMap, + bottomMostRow, + gridProps, + copiedWidgetGroups: [ + { + list: [newContainerWidget, newCanvasWidget, ...flatList], + widgetId: newContainerWidget.widgetId, + parentId: pastingIntoWidgetId, + }, + ], + }; }; /** @@ -1225,27 +1300,20 @@ export const isSelectedWidgetsColliding = function*( widget.parentId === pastingIntoWidgetId && widget.type !== "MODAL_WIDGET", ); - let isColliding = false; - for (let i = 0; i < widgetsArray.length; i++) { const widget = widgetsArray[i]; - if ( - widget.bottomRow + 2 < topMostWidget.topRow || - widget.topRow > bottomMostWidget.bottomRow - ) { - isColliding = false; - } else if ( - widget.rightColumn < leftMostWidget.leftColumn || - widget.leftColumn > rightMostWidget.rightColumn - ) { - isColliding = false; - } else { + !( + widget.leftColumn >= rightMostWidget.rightColumn || + widget.rightColumn <= leftMostWidget.leftColumn || + widget.topRow >= bottomMostWidget.bottomRow || + widget.bottomRow <= topMostWidget.topRow + ) + ) return true; - } } - return isColliding; + return false; }; /** @@ -1351,8 +1419,8 @@ export const getParentBottomRowAfterAddingWidget = ( export function* getParentWidgetIdForGrouping( widgets: CanvasWidgetsReduxState, copiedWidgetGroups: CopiedWidgetGroup[], - pastingIntoWidgetId: string, ) { + const pastingIntoWidgetId = copiedWidgetGroups[0]?.parentId; const widgetIds = copiedWidgetGroups.map( (widgetGroup) => widgetGroup.widgetId, ); @@ -1445,6 +1513,33 @@ export function purgeOrphanedDynamicPaths(widget: WidgetProps) { return widget; } +/** + * + * @param canvasWidgets + * @param pastingIntoWidgetId + * @returns + */ +export function getParentColumnSpace( + canvasWidgets: CanvasWidgetsReduxState, + pastingIntoWidgetId: string, +) { + const containerId = getContainerIdForCanvas(pastingIntoWidgetId); + + const containerWidget = canvasWidgets[containerId]; + const canvasDOM = document.querySelector( + `#${getSlidingCanvasName(pastingIntoWidgetId)}`, + ); + + if (!canvasDOM || !containerWidget) return; + + const rect = canvasDOM.getBoundingClientRect(); + + // get Grid values such as snapRowSpace and snapColumnSpace + const { snapGrid } = getSnappedGrid(containerWidget, rect.width); + + return snapGrid?.snapColumnSpace; +} + /* * Function to extend the lodash's get function to check * paths which have dots in it's key diff --git a/app/client/src/widgets/JSONFormWidget/schemaParser.test.ts b/app/client/src/widgets/JSONFormWidget/schemaParser.test.ts index f26fe038e2..25d2816b53 100644 --- a/app/client/src/widgets/JSONFormWidget/schemaParser.test.ts +++ b/app/client/src/widgets/JSONFormWidget/schemaParser.test.ts @@ -62,7 +62,8 @@ describe("#parse", () => { ); }); - it("returns unmodified schema when existing field's value in data source changes to null/undefined", () => { + it("returns unmodified schema when existing field's value in data source changes to null and back", () => { + // Get the initial schema const initialSchema = SchemaParser.parse(widgetName, { currSourceData: testData.initialDataset.dataSource, schema: {}, @@ -71,45 +72,390 @@ describe("#parse", () => { expect(initialSchema).toEqual(testData.initialDataset.schemaOutput); - // With null field - const nulledDataSource = klona(testData.initialDataset.dataSource); - set(nulledDataSource, "dob", null); + // Set all keys to null + const nulledSourceData = klona(testData.initialDataset.dataSource); + set(nulledSourceData, "name", null); + set(nulledSourceData, "age", null); + set(nulledSourceData, "dob", null); + set(nulledSourceData, "boolean", null); + set(nulledSourceData, "hobbies", null); + set(nulledSourceData, "%%", null); + set(nulledSourceData, "हिन्दि", null); + set(nulledSourceData, "education", null); + set(nulledSourceData, "address", null); - const expectedNulledSchema = klona(initialSchema); - set(expectedNulledSchema, "__root_schema__.children.dob.sourceData", null); - set(expectedNulledSchema, "__root_schema__.sourceData.dob", null); + // Set the sourceData entry in each SchemaItem to null (only property that changes) + const expectedSchema = klona(initialSchema); + set(expectedSchema, "__root_schema__.children.name.sourceData", null); + set(expectedSchema, "__root_schema__.sourceData.name", null); + set(expectedSchema, "__root_schema__.children.age.sourceData", null); + set(expectedSchema, "__root_schema__.sourceData.age", null); + set(expectedSchema, "__root_schema__.children.dob.sourceData", null); + set(expectedSchema, "__root_schema__.sourceData.dob", null); + set(expectedSchema, "__root_schema__.children.boolean.sourceData", null); + set(expectedSchema, "__root_schema__.sourceData.boolean", null); + set(expectedSchema, "__root_schema__.children.hobbies.sourceData", null); + set(expectedSchema, "__root_schema__.sourceData.hobbies", null); + set(expectedSchema, "__root_schema__.children.education.sourceData", null); + set(expectedSchema, "__root_schema__.sourceData.education", null); + set(expectedSchema, "__root_schema__.children.__.sourceData", null); + set(expectedSchema, "__root_schema__.sourceData['%%']", null); + set( + expectedSchema, + "__root_schema__.children.xn__j2bd4cyac6f.sourceData", + null, + ); + set(expectedSchema, "__root_schema__.sourceData.हिन्दि", null); + set(expectedSchema, "__root_schema__.children.address.sourceData", null); + set(expectedSchema, "__root_schema__.sourceData.address", null); - const schemaWithNulledField = SchemaParser.parse(widgetName, { - currSourceData: nulledDataSource, + // Parse with the nulled sourceData + const schemaWithNullKeys = SchemaParser.parse(widgetName, { + currSourceData: nulledSourceData, schema: initialSchema, fieldThemeStylesheets: testData.fieldThemeStylesheets, }); - expect(schemaWithNulledField).toEqual(expectedNulledSchema); + expect(schemaWithNullKeys).toEqual(expectedSchema); - // With undefined field - const undefinedDataSource = klona(nulledDataSource); - set(undefinedDataSource, "boolean", undefined); - - const expectedUndefinedSchema = klona(expectedNulledSchema); - set( - expectedUndefinedSchema, - "__root_schema__.children.boolean.sourceData", - undefined, - ); - set( - expectedUndefinedSchema, - "__root_schema__.sourceData.boolean", - undefined, - ); - - const schemaWithUndefinedField = SchemaParser.parse(widgetName, { - currSourceData: undefinedDataSource, - schema: schemaWithNulledField, + /** + * Parse with initial sourceData to check if previous schema with null sourceData + * can still retain the schema structure + */ + const schemaWithRevertedData = SchemaParser.parse(widgetName, { + currSourceData: testData.initialDataset.dataSource, + schema: schemaWithNullKeys, fieldThemeStylesheets: testData.fieldThemeStylesheets, }); - expect(schemaWithUndefinedField).toEqual(expectedUndefinedSchema); + expect(schemaWithRevertedData).toEqual( + testData.initialDataset.schemaOutput, + ); + }); + + it("returns unmodified schema when existing fields value in data source changes to undefined and back", () => { + // Get the initial schema + const initialSchema = SchemaParser.parse(widgetName, { + currSourceData: testData.initialDataset.dataSource, + schema: {}, + fieldThemeStylesheets: testData.fieldThemeStylesheets, + }); + + expect(initialSchema).toEqual(testData.initialDataset.schemaOutput); + + // Set all keys to undefined + const undefinedDataSource = klona(testData.initialDataset.dataSource); + set(undefinedDataSource, "name", undefined); + set(undefinedDataSource, "age", undefined); + set(undefinedDataSource, "dob", undefined); + set(undefinedDataSource, "boolean", undefined); + set(undefinedDataSource, "hobbies", undefined); + set(undefinedDataSource, "%%", undefined); + set(undefinedDataSource, "हिन्दि", undefined); + set(undefinedDataSource, "education", undefined); + set(undefinedDataSource, "address", undefined); + + // Set the sourceData entry in each SchemaItem to undefined (only property that changes) + const expectedSchema = klona(initialSchema); + set(expectedSchema, "__root_schema__.children.name.sourceData", undefined); + set(expectedSchema, "__root_schema__.sourceData.name", undefined); + set(expectedSchema, "__root_schema__.children.age.sourceData", undefined); + set(expectedSchema, "__root_schema__.sourceData.age", undefined); + set(expectedSchema, "__root_schema__.children.dob.sourceData", undefined); + set(expectedSchema, "__root_schema__.sourceData.dob", undefined); + set( + expectedSchema, + "__root_schema__.children.boolean.sourceData", + undefined, + ); + set(expectedSchema, "__root_schema__.sourceData.boolean", undefined); + set( + expectedSchema, + "__root_schema__.children.hobbies.sourceData", + undefined, + ); + set(expectedSchema, "__root_schema__.sourceData.hobbies", undefined); + set( + expectedSchema, + "__root_schema__.children.education.sourceData", + undefined, + ); + set(expectedSchema, "__root_schema__.sourceData.education", undefined); + set(expectedSchema, "__root_schema__.children.__.sourceData", undefined); + set(expectedSchema, "__root_schema__.sourceData['%%']", undefined); + set( + expectedSchema, + "__root_schema__.children.xn__j2bd4cyac6f.sourceData", + undefined, + ); + set(expectedSchema, "__root_schema__.sourceData.हिन्दि", undefined); + set( + expectedSchema, + "__root_schema__.children.address.sourceData", + undefined, + ); + set(expectedSchema, "__root_schema__.sourceData.address", undefined); + + // Parse with the undefined sourceData keys + const schemaWithUndefinedKeys = SchemaParser.parse(widgetName, { + currSourceData: undefinedDataSource, + schema: initialSchema, + fieldThemeStylesheets: testData.fieldThemeStylesheets, + }); + + expect(schemaWithUndefinedKeys).toEqual(expectedSchema); + + /** + * Parse with initial sourceData to check if previous schema with null sourceData + * can still retain the schema structure + */ + const schemaWithRevertedData = SchemaParser.parse(widgetName, { + currSourceData: testData.initialDataset.dataSource, + schema: schemaWithUndefinedKeys, + fieldThemeStylesheets: testData.fieldThemeStylesheets, + }); + + expect(schemaWithRevertedData).toEqual( + testData.initialDataset.schemaOutput, + ); + }); + + it("returns unmodified schema when existing inner field's value in data source changes to null and back", () => { + // Get the initial schema + const initialSchema = SchemaParser.parse(widgetName, { + currSourceData: testData.initialDataset.dataSource, + schema: {}, + fieldThemeStylesheets: testData.fieldThemeStylesheets, + }); + + expect(initialSchema).toEqual(testData.initialDataset.schemaOutput); + + // Set all keys to null + const nulledSourceData = klona(testData.initialDataset.dataSource); + set(nulledSourceData, "address.Line1", null); + set(nulledSourceData, "address.city", null); + set(nulledSourceData, "education[0].college", null); + set(nulledSourceData, "education[0].number", null); + set(nulledSourceData, "education[0].graduationDate", null); + set(nulledSourceData, "education[0].boolean", null); + + // Set the sourceData entry in each SchemaItem to null (only property that changes) + const expectedSchema = klona(initialSchema); + set( + expectedSchema, + "__root_schema__.children.address.children.Line1.sourceData", + null, + ); + set(expectedSchema, "__root_schema__.sourceData.address.Line1", null); + set( + expectedSchema, + "__root_schema__.children.address.children.city.sourceData", + null, + ); + set(expectedSchema, "__root_schema__.sourceData.address.city", null); + set( + expectedSchema, + "__root_schema__.children.education.children.__array_item__.children.college.sourceData", + null, + ); + set(expectedSchema, "__root_schema__.children.address.sourceData", { + Line1: null, + city: null, + }); + + set( + expectedSchema, + "__root_schema__.sourceData.education[0].college", + null, + ); + set( + expectedSchema, + "__root_schema__.children.education.children.__array_item__.children.number.sourceData", + null, + ); + set(expectedSchema, "__root_schema__.sourceData.education[0].number", null); + set( + expectedSchema, + "__root_schema__.children.education.children.__array_item__.children.graduationDate.sourceData", + null, + ); + set( + expectedSchema, + "__root_schema__.sourceData.education[0].graduationDate", + null, + ); + set( + expectedSchema, + "__root_schema__.children.education.children.__array_item__.children.boolean.sourceData", + null, + ); + set( + expectedSchema, + "__root_schema__.sourceData.education[0].boolean", + null, + ); + set(expectedSchema, "__root_schema__.children.education.sourceData", [ + { + college: null, + number: null, + graduationDate: null, + boolean: null, + }, + ]); + set( + expectedSchema, + "__root_schema__.children.education.children.__array_item__.sourceData", + { + college: null, + number: null, + graduationDate: null, + boolean: null, + }, + ); + + // Parse with the nulled sourceData + const schemaWithNullKeys = SchemaParser.parse(widgetName, { + currSourceData: nulledSourceData, + schema: initialSchema, + fieldThemeStylesheets: testData.fieldThemeStylesheets, + }); + + expect(schemaWithNullKeys).toEqual(expectedSchema); + + /** + * Parse with initial sourceData to check if previous schema with null sourceData + * can still retain the schema structure + */ + const schemaWithRevertedData = SchemaParser.parse(widgetName, { + currSourceData: testData.initialDataset.dataSource, + schema: schemaWithNullKeys, + fieldThemeStylesheets: testData.fieldThemeStylesheets, + }); + + expect(schemaWithRevertedData).toEqual( + testData.initialDataset.schemaOutput, + ); + }); + + it("returns unmodified schema when existing inner field's value in data source changes to undefined and back", () => { + // Get the initial schema + const initialSchema = SchemaParser.parse(widgetName, { + currSourceData: testData.initialDataset.dataSource, + schema: {}, + fieldThemeStylesheets: testData.fieldThemeStylesheets, + }); + + expect(initialSchema).toEqual(testData.initialDataset.schemaOutput); + + // Set all keys to undefined + const undefinedSourceData = klona(testData.initialDataset.dataSource); + set(undefinedSourceData, "address.Line1", undefined); + set(undefinedSourceData, "address.city", undefined); + set(undefinedSourceData, "education[0].college", undefined); + set(undefinedSourceData, "education[0].number", undefined); + set(undefinedSourceData, "education[0].graduationDate", undefined); + set(undefinedSourceData, "education[0].boolean", undefined); + + // Set the sourceData entry in each SchemaItem to undefined (only property that changes) + const expectedSchema = klona(initialSchema); + set( + expectedSchema, + "__root_schema__.children.address.children.Line1.sourceData", + undefined, + ); + set(expectedSchema, "__root_schema__.sourceData.address.Line1", undefined); + set( + expectedSchema, + "__root_schema__.children.address.children.city.sourceData", + undefined, + ); + set(expectedSchema, "__root_schema__.sourceData.address.city", undefined); + set( + expectedSchema, + "__root_schema__.children.education.children.__array_item__.children.college.sourceData", + undefined, + ); + set(expectedSchema, "__root_schema__.children.address.sourceData", { + Line1: undefined, + city: undefined, + }); + + set( + expectedSchema, + "__root_schema__.sourceData.education[0].college", + undefined, + ); + set( + expectedSchema, + "__root_schema__.children.education.children.__array_item__.children.number.sourceData", + undefined, + ); + set( + expectedSchema, + "__root_schema__.sourceData.education[0].number", + undefined, + ); + set( + expectedSchema, + "__root_schema__.children.education.children.__array_item__.children.graduationDate.sourceData", + undefined, + ); + set( + expectedSchema, + "__root_schema__.sourceData.education[0].graduationDate", + undefined, + ); + set( + expectedSchema, + "__root_schema__.children.education.children.__array_item__.children.boolean.sourceData", + undefined, + ); + set( + expectedSchema, + "__root_schema__.sourceData.education[0].boolean", + undefined, + ); + set(expectedSchema, "__root_schema__.children.education.sourceData", [ + { + college: undefined, + number: undefined, + graduationDate: undefined, + boolean: undefined, + }, + ]); + set( + expectedSchema, + "__root_schema__.children.education.children.__array_item__.sourceData", + { + college: undefined, + number: undefined, + graduationDate: undefined, + boolean: undefined, + }, + ); + + // Parse with the undefined sourceData + const schemaWithUndefinedKeys = SchemaParser.parse(widgetName, { + currSourceData: undefinedSourceData, + schema: initialSchema, + fieldThemeStylesheets: testData.fieldThemeStylesheets, + }); + + expect(schemaWithUndefinedKeys).toEqual(expectedSchema); + + /** + * Parse with initial sourceData to check if previous schema with undefined sourceData + * can still retain the schema structure + */ + const schemaWithRevertedData = SchemaParser.parse(widgetName, { + currSourceData: testData.initialDataset.dataSource, + schema: schemaWithUndefinedKeys, + fieldThemeStylesheets: testData.fieldThemeStylesheets, + }); + + expect(schemaWithRevertedData).toEqual( + testData.initialDataset.schemaOutput, + ); }); }); diff --git a/app/client/src/widgets/JSONFormWidget/schemaParser.ts b/app/client/src/widgets/JSONFormWidget/schemaParser.ts index 33e785c230..55164564af 100644 --- a/app/client/src/widgets/JSONFormWidget/schemaParser.ts +++ b/app/client/src/widgets/JSONFormWidget/schemaParser.ts @@ -27,11 +27,10 @@ import { } from "./constants"; import { getFieldStylesheet } from "./helper"; -type Obj = Record; -type JSON = Obj | Obj[]; +type Obj = Record; type ParserOptions = { - currSourceData?: JSON | string; + currSourceData?: unknown; fieldThemeStylesheets?: FieldThemeStylesheet; fieldType?: FieldType; isCustomField?: boolean; @@ -60,11 +59,15 @@ type GetKeysFromSchemaOptions = { }; type ParseOptions = { - currSourceData?: JSON; + currSourceData?: unknown; schema?: Schema; fieldThemeStylesheets?: FieldThemeStylesheet; }; +function isObject(val: unknown): val is Obj { + return typeof val === "object" && !Array.isArray(val) && val !== null; +} + /** * * This method takes in array of object and squishes every object in the @@ -604,7 +607,7 @@ class SchemaParser { // This method deals with the conversion of array data to a schema static convertArrayToSchema = ({ - currSourceData = [], + currSourceData, fieldThemeStylesheets, prevSchema = {}, sourceDataPath, @@ -612,7 +615,12 @@ class SchemaParser { ...rest }: Omit): Schema => { const schema = klona(prevSchema); - const currData = normalizeArrayValue(currSourceData as any[]); + + if (!Array.isArray(currSourceData)) { + return schema; + } + + const currData = normalizeArrayValue(currSourceData); const prevDataType = schema[ARRAY_ITEM_KEY]?.dataType; const currDataType = dataTypeFor(currData); @@ -644,7 +652,7 @@ class SchemaParser { // This method deals with the conversion of object data to a schema static convertObjectToSchema = ({ - currSourceData = {}, + currSourceData, prevSchema = {}, sourceDataPath, widgetName, @@ -654,8 +662,10 @@ class SchemaParser { const origIdentifierToIdentifierMap = mapOriginalIdentifierToSanitizedIdentifier( schema, ); - const currObj = currSourceData as Obj; + if (!isObject(currSourceData)) { + return schema; + } const customFieldAccessors = getKeysFromSchema(prevSchema, ["accessor"], { onlyCustomFieldKeys: true, }); @@ -683,7 +693,7 @@ class SchemaParser { modifiedKeys.forEach((modifiedKey) => { const identifier = origIdentifierToIdentifierMap[modifiedKey]; const prevSchemaItem = klona(schema[identifier]); - const currData = currObj[modifiedKey]; + const currData = currSourceData[modifiedKey]; const prevData = prevSchemaItem.sourceData; const currDataType = dataTypeFor(currData); const prevDataType = schema[identifier].dataType; @@ -743,7 +753,7 @@ class SchemaParser { newKeys.forEach((newKey) => { const schemaItem = SchemaParser.getSchemaItemFor(newKey, { ...rest, - currSourceData: currObj[newKey], + currSourceData: currSourceData[newKey], sourceDataPath: getSourcePath(newKey, sourceDataPath), identifier: sanitizeSchemaItemKey(newKey, schema), widgetName, diff --git a/app/client/src/widgets/PhoneInputWidget/widget/index.tsx b/app/client/src/widgets/PhoneInputWidget/widget/index.tsx index 6c387e6d0d..2b4c22a398 100644 --- a/app/client/src/widgets/PhoneInputWidget/widget/index.tsx +++ b/app/client/src/widgets/PhoneInputWidget/widget/index.tsx @@ -106,7 +106,7 @@ class PhoneInputWidget extends BaseInputWidget< propertyName: "defaultText", label: "Default Text", controlType: "INPUT_TEXT", - placeholderText: "John Doe", + placeholderText: "(000) 000-0000", isBindProperty: true, isTriggerProperty: false, validation: { @@ -115,7 +115,7 @@ class PhoneInputWidget extends BaseInputWidget< fn: defaultValueValidation, expected: { type: "string", - example: `000 0000`, + example: `(000) 000-0000`, autocompleteDataType: AutocompleteDataType.STRING, }, }, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java index 1ab2f9272f..4604265f54 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java @@ -89,13 +89,7 @@ public class ApplicationControllerCE extends BaseController> publish(@PathVariable String defaultApplicationId, @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) { return applicationPageService.publish(defaultApplicationId, branchName, true) - .flatMap(application -> - // This event should parallel a similar event sent from the client, so we want it to be sent by the - // controller and not the service method. - applicationPageService.sendApplicationPublishedEvent(application) - // This will only be called when the publishing was successful, so we can always return `true` here. - .thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), true, null)) - ); + .thenReturn(new ResponseDTO<>(HttpStatus.OK.value(), true, null)); } @PutMapping("/{defaultApplicationId}/page/{defaultPageId}/makeDefault") diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCE.java index 9582cd8b94..14aac589af 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCE.java @@ -51,8 +51,6 @@ public interface ApplicationPageServiceCE { void generateAndSetPagePolicies(Application application, PageDTO page); - Mono sendApplicationPublishedEvent(Application application); - Mono reorderPage(String applicationId, String pageId, Integer order, String branchName); Mono deleteApplicationByResource(Application application); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java index bc08f31502..b00cfa833c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java @@ -892,7 +892,7 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE { application -> themeService.publishTheme(application.getId()) ); - Flux publishApplicationAndPages = applicationMono + Mono> publishApplicationAndPages = applicationMono //Return all the pages in the Application .flatMap(application -> { List pages = application.getPages(); @@ -952,10 +952,11 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE { page.setPublishedPage(page.getUnpublishedPage()); return page; })) + .flatMap(newPageService::save) .collectList() - .flatMapMany(newPageService::saveAll); + .cache(); // caching as we'll need this to send analytics attributes after publishing the app - Flux publishedActionsFlux = newActionService + Mono> publishedActionsListMono = newActionService .findAllByApplicationIdAndViewMode(applicationId, false, MANAGE_ACTIONS, null) .flatMap(newAction -> { // If the action was deleted in edit mode, now this document can be safely archived @@ -967,10 +968,11 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE { newAction.setPublishedAction(newAction.getUnpublishedAction()); return Mono.just(newAction); }) + .flatMap(newActionService::save) .collectList() - .flatMapMany(newActionService::saveAll); + .cache(); // caching as we'll need this to send analytics attributes after publishing the app - Flux publishedCollectionsFlux = actionCollectionService + Mono> publishedActionCollectionsListMono = actionCollectionService .findAllByApplicationIdAndViewMode(applicationId, false, MANAGE_ACTIONS, null) .flatMap(collection -> { // If the collection was deleted in edit mode, now this can be safely deleted from the repository @@ -982,16 +984,42 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE { collection.setPublishedCollection(collection.getUnpublishedCollection()); return Mono.just(collection); }) - .collectList() - .flatMapMany(actionCollectionService::saveAll); + .flatMap(actionCollectionService::save) + .collectList(); return Mono.when( - publishApplicationAndPages.collectList(), - publishedActionsFlux.collectList(), - publishedCollectionsFlux, + publishApplicationAndPages, + publishedActionsListMono, + publishedActionCollectionsListMono, publishThemeMono ) - .then(applicationMono); + .then(sendApplicationPublishedEvent(publishApplicationAndPages, publishedActionsListMono, publishedActionCollectionsListMono, applicationId)); + } + + private Mono sendApplicationPublishedEvent(Mono> publishApplicationAndPages, + Mono> publishedActionsFlux, + Mono> publishedActionsCollectionFlux, + String applicationId) { + return Mono.zip( + publishApplicationAndPages, + publishedActionsFlux, + publishedActionsCollectionFlux, + // not using existing applicationMono because we need the latest Application after published + applicationService.findById(applicationId, MANAGE_APPLICATIONS) + ) + .flatMap(objects -> { + Application application = objects.getT4(); + Map extraProperties = new HashMap<>(); + extraProperties.put("pageCount", objects.getT1().size()); + extraProperties.put("queryCount", objects.getT2().size()); + extraProperties.put("actionCollectionCount", objects.getT3().size()); + extraProperties.put("appId", defaultIfNull(application.getId(), "")); + extraProperties.put("appName", defaultIfNull(application.getName(), "")); + extraProperties.put("orgId", defaultIfNull(application.getOrganizationId(), "")); + extraProperties.put("publishedAt", defaultIfNull(application.getLastDeployedAt(), "")); + + return analyticsService.sendObjectEvent(AnalyticsEvents.PUBLISH_APPLICATION, application, extraProperties); + }); } @Override @@ -1001,34 +1029,6 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE { .map(responseUtils::updateApplicationWithDefaultResources); } - @Override - public Mono sendApplicationPublishedEvent(Application application) { - if (!analyticsService.isActive()) { - return Mono.empty(); - } - - return sessionUserService.getCurrentUser() - .flatMap(user -> { - int publishedPageCount = 0; - if(application.getPublishedPages() != null) { - publishedPageCount = application.getPublishedPages().size(); - } - - analyticsService.sendEvent( - AnalyticsEvents.PUBLISH_APPLICATION.getEventName(), - user.getUsername(), - Map.of( - "appId", defaultIfNull(application.getId(), ""), - "appName", defaultIfNull(application.getName(), ""), - "orgId", defaultIfNull(application.getOrganizationId(), ""), - "pageCount", publishedPageCount + "", - "publishedAt", defaultIfNull(application.getLastDeployedAt(), "") - ) - ); - return Mono.empty(); - }); - } - /** This function walks through all the pages and reorders them and updates the order as per the user preference. * A page can be moved up or down from the current position and accordingly the order of the remaining page changes. * @param defaultAppId The id of the Application